better_astar.cpp文件内容:
//register this planner as a BaseGlobalPlanner plugin
PLUGINLIB_EXPORT_CLASS(BAstar_planner::BAstarPlannerROS, nav_core::BaseGlobalPlanner)
int value;
int mapSize;
bool *OGM;
static const float INFINIT_COST = INT_MAX; //!< cost of non connected nodes
float infinity = std::numeric_limits<float>::infinity();
float tBreak; // coefficient for breaking ties
ofstream MyExcelFile("BA_result.xlsx", ios::trunc);
int clock_gettime(clockid_t clk_id, struct timespect *tp);
timespec diff(timespec start, timespec end)
{
timespec temp;
if ((end.tv_nsec - start.tv_nsec) < 0)
{
temp.tv_sec = end.tv_sec - start.tv_sec - 1;
temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
}
else
{
temp.tv_sec = end.tv_sec - start.tv_sec;
temp.tv_nsec = end.tv_nsec - start.tv_nsec;
}
return temp;
}
inline vector<int> findFreeNeighborCell(int CellID);
//Default Constructor
namespace BAstar_planner
{
BAstarPlannerROS::BAstarPlannerROS()
{
}
BAstarPlannerROS::BAstarPlannerROS(ros::NodeHandle &nh)
{
ROSNodeHandle = nh;
}
BAstarPlannerROS::BAstarPlannerROS(std::string name, costmap_2d::Costmap2DROS *costmap_ros)
{
initialize(name, costmap_ros);
}
void BAstarPlannerROS::initialize(std::string name, costmap_2d::Costmap2DROS *costmap_ros)
{
initialized_ = false;
if (!initialized_)
{
costmap_ros_ = costmap_ros;
costmap_ = costmap_ros_->getCostmap();
ros::NodeHandle private_nh("~/" + name);
_plan_pub = private_nh.advertise<nav_msgs::Path>("global_plan", 1);
_frame_id = costmap_ros->getGlobalFrameID();
originX = costmap_->getOriginX();
originY = costmap_->getOriginY();
width = costmap_->getSizeInCellsX();
height = costmap_->getSizeInCellsY();
resolution = costmap_->getResolution();
mapSize = width * height;
tBreak = 1 + 1 / (mapSize);
value = 0;
OGM = new bool[mapSize];
for (unsigned int iy = 0; iy < costmap_->getSizeInCellsY(); iy++)
{
for (unsigned int ix = 0; ix < costmap_->getSizeInCellsX(); ix++)
{
unsigned int cost = static_cast<int>(costmap_->getCost(ix, iy));
//cout<<cost;
if (cost == 0)
OGM[iy * width + ix] = true;
else
OGM[iy * width + ix] = false;
}
}
MyExcelFile << "StartID\tStartX\tStartY\tGoalID\tGoalX\tGoalY\tPlannertime(ms)\tpathLength\tnumberOfCells\t" << endl;
ROS_INFO("BAstar planner initialized successfully");
initialized_ = true;
}
else
ROS_WARN("This planner has already been initialized... doing nothing");
delete[] OGM;
OGM = nullptr;
}
bool BAstarPlannerROS::makePlan(const geometry_msgs::PoseStamped &start, const geometry_msgs::PoseStamped &goal,
std::vector<geometry_msgs::PoseStamped> &plan)
{
if (!initialized_)
{
ROS_ERROR("The planner has not been initialized, please call initialize() to use the planner");
return false;
}
ROS_DEBUG("Got a start: %.2f, %.2f, and a goal: %.2f, %.2f", start.pose.position.x, start.pose.position.y,
goal.pose.position.x, goal.pose.position.y);
plan.clear();
if (goal.header.frame_id != costmap_ros_->getGlobalFrameID())
{
ROS_ERROR("This planner as configured will only accept goals in the %s frame, but a goal was sent in the %s frame.",
costmap_ros_->getGlobalFrameID().c_str(), goal.header.frame_id.c_str());
return false;
}
tf::Stamped<tf::Pose> goal_tf;
tf::Stamped<tf::Pose> start_tf;
poseStampedMsgToTF(goal, goal_tf);
poseStampedMsgToTF(start, start_tf);
// convert the start and goal positions
float startX = start.pose.position.x;
float startY = start.pose.position.y;
float goalX = goal.pose.position.x;
float goalY = goal.pose.position.y;
getCorrdinate(startX, startY);
getCorrdinate(goalX, goalY);
int startCell;
int goalCell;
if (isCellInsideMap(startX, startY) && isCellInsideMap(goalX, goalY))
{
startCell = convertToCellIndex(startX, startY);
goalCell = convertToCellIndex(goalX, goalY);
MyExcelFile << startCell << "\t" << start.pose.position.x << "\t" << start.pose.position.y << "\t" << goalCell << "\t" << goal.pose.position.x << "\t" << goal.pose.position.y;
}
else
{
ROS_WARN("the start or goal is out of the map");
return false;
}
/////////////////////////////////////////////////////////
// call global planner
if (isStartAndGoalCellsValid(startCell, goalCell))
{
vector<int> bestPath;
bestPath.clear();
bestPath = BAstarPlanner(startCell, goalCell);
//if the global planner find a path
if (bestPath.size() > 0)
{
// convert the path
for (int i = 0; i < bestPath.size(); i++)
{
float x = 0.0;
float y = 0.0;
int index = bestPath[i];
convertToCoordinate(index, x, y);
geometry_msgs::PoseStamped pose = goal;
pose.pose.position.x = x;
pose.pose.position.y = y;
pose.pose.position.z = 0.0;
pose.pose.orientation.x = 0.0;
pose.pose.orientation.y = 0.0;
pose.pose.orientation.z = 0.0;
pose.pose.orientation.w = 1.0;
plan.push_back(pose);
}
float path_length = 0.0;
std::vector<geometry_msgs::PoseStamped>::iterator it = plan.begin();
geometry_msgs::PoseStamped last_pose;
last_pose = *it;
it++;
for (; it != plan.end(); ++it)
{
path_length += hypot((*it).pose.position.x - last_pose.pose.position.x,
(*it).pose.position.y - last_pose.pose.position.y);
last_pose = *it;
}
cout << "The global path length: " << path_length << " meters" << endl;
MyExcelFile << "\t" << path_length << "\t" << plan.size() << endl;
//publish the plan
nav_msgs::Path path;
path.poses.resize(plan.size());
if (plan.empty())
{
//still set a valid frame so visualization won't hit transform issues
path.header.frame_id = _frame_id;
path.header.stamp = ros::Time::now();
}
else
{
path.header.frame_id = plan[0].header.frame_id;
path.header.stamp = plan[0].header.stamp;
}
// Extract the plan in world co-ordinates, we assume the path is all in the same frame
for (unsigned int i = 0; i < plan.size(); i++)
{
path.poses[i] = plan[i];
}
_plan_pub.publish(path);
return true;
}
else
{
ROS_WARN("The planner failed to find a path, choose other goal position");
return false;
}
}
else
{
ROS_WARN("Not valid start or goal");
return false;
}
}
void BAstarPlannerROS::getCorrdinate(float &x, float &y)
{
x = x - originX;
y = y - originY;
}
int BAstarPlannerROS::convertToCellIndex(float x, float y)
{
int cellIndex;
float newX = x / resolution;
float newY = y / resolution;
cellIndex = getCellIndex(newY, newX);
return cellIndex;
}
void BAstarPlannerROS::convertToCoordinate(int index, float &x, float &y)
{
x = getCellColID(index) * resolution;
y = getCellRowID(index) * resolution;
x = x + originX;
y = y + originY;
}
bool BAstarPlannerROS::isCellInsideMap(float x, float y)
{
bool valid = true;
if (x > (width * resolution) || y > (height * resolution))
valid = false;
return valid;
}
void BAstarPlannerROS::mapToWorld(double mx, double my, double &wx, double &wy)
{
costmap_2d::Costmap2D *costmap = costmap_ros_->getCostmap();
wx = costmap->getOriginX() + mx * resolution;
wy = costmap->getOriginY() + my * resolution;
}
vector<int> BAstarPlannerROS::BAstarPlanner(int startCell, int goalCell)
{
vector<int> bestPath;
//float g_score [mapSize][2];
float g_score[mapSize];
for (uint i = 0; i < mapSize; i++)
g_score[i] = infinity;
timespec time1, time2;
/* take current time here */
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
bestPath = findPath(startCell, goalCell, g_score);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
cout << "time to generate best global path by the new planner A* = " << (diff(time1, time2).tv_sec) * 1e3 + (diff(time1, time2).tv_nsec) * 1e-6 << " microseconds" << endl;
MyExcelFile << "\t" << (diff(time1, time2).tv_sec) * 1e3 + (diff(time1, time2).tv_nsec) * 1e-6;
return bestPath;
}
//
//Function Name: findPath
//Inputs: the map layout, the start and the goal Cells and a boolean to indicate if we will use break ties or not
//Output: the best path
//Description: it is used to generate the robot free path
/**/
vector<int> BAstarPlannerROS::findPath(int startCell, int goalCell, float g_score[])
{
value++;
vector<int> bestPath;
vector<int> emptyPath;
cells CP;
multiset<cells> OPL;
int currentCell;
//calculate g_score and f_score of the start position
g_score[startCell] = 0;
CP.currentCell = startCell;
CP.fCost = g_score[startCell] + calculateHCost(startCell, goalCell);
//add the start cell to the open list
OPL.insert(CP);
currentCell = startCell;
//while the open list is not empty continuie the search or g_score(goalCell) is equal to infinity
while (!OPL.empty() && g_score[goalCell] == infinity)
{
//choose the cell that has the lowest cost fCost in the open set which is the begin of the multiset
currentCell = OPL.begin()->currentCell;
//remove the currentCell from the openList
OPL.erase(OPL.begin());
//search the neighbors of the current Cell
vector<int> neighborCells;
neighborCells = findFreeNeighborCell(currentCell);
for (uint i = 0; i < neighborCells.size(); i++) //for each neighbor v of current cell
{
// if the g_score of the neighbor is equal to INF: unvisited cell
if (g_score[neighborCells[i]] == infinity)
{
g_score[neighborCells[i]] = g_score[currentCell] + getMoveCost(currentCell, neighborCells[i]);
addNeighborCellToOpenList(OPL, neighborCells[i], goalCell, g_score);
} //end if
} //end for
} //end while
if (g_score[goalCell] != infinity) // if g_score(goalcell)==INF : construct path
{
bestPath = constructPath(startCell, goalCell, g_score);
return bestPath;
}
else
{
cout << "Failure to find a path !" << endl;
return emptyPath;
}
}
//
//Function Name: constructPath
//Inputs: the start and the goal Cells
//Output: the best path
//Description: it is used to construct the robot path
/**/
vector<int> BAstarPlannerROS::constructPath(int startCell, int goalCell, float g_score[])
{
vector<int> bestPath;
vector<int> path;
path.insert(path.begin() + bestPath.size(), goalCell);
int currentCell = goalCell;
while (currentCell != startCell)
{
vector<int> neighborCells;
neighborCells = findFreeNeighborCell(currentCell);
vector<float> gScoresNeighbors;
for (uint i = 0; i < neighborCells.size(); i++)
gScoresNeighbors.push_back(g_score[neighborCells[i]]);
int posMinGScore = distance(gScoresNeighbors.begin(), min_element(gScoresNeighbors.begin(), gScoresNeighbors.end()));
currentCell = neighborCells[posMinGScore];
//insert the neighbor in the path
path.insert(path.begin() + path.size(), currentCell);
}
for (uint i = 0; i < path.size(); i++)
bestPath.insert(bestPath.begin() + bestPath.size(), path[path.size() - (i + 1)]);
return bestPath;
}
//
//Function Name: calculateHCost
//Inputs:the cellID and the goalCell
//Output: the distance between the current cell and the goal cell
//Description: it is used to calculate the hCost
/**/
float BAstarPlannerROS::calculateHCost(int cellID, int goalCell)
{
double h; //heuristic(n)
double distance; //distance
double w; //weight(n)
int x1=getCellRowID(goalCell);
int y1=getCellColID(goalCell);
int x2=getCellRowID(cellID);
int y2=getCellColID(cellID);
w = 3.0;
//distance = abs(x1-x2)+abs(y1-y2); //Manhatten Distance
//distance = sqrt(pow(x1,x2)+pow(y1,y2)); //Euclidean Distance
distance = min(abs(x1-x2),abs(y1-y2)) *sqrt(2) + max(abs(x1-x2),abs(y1-y2)) - min(abs(x1-x2),abs(y1-y2)); //Diagonal Distance
h = w * distance;
return h; //return h to return 0 meaning that improved A* algorithm to Dijkstra
}
//
//Function Name: addNeighborCellToOpenList
//Inputs: the open list, the neighbors Cell, the g_score matrix, the goal cell
//Output:
//Description: it is used to add a neighbor Cell to the open list
/**/
void BAstarPlannerROS::addNeighborCellToOpenList(multiset<cells> &OPL, int neighborCell, int goalCell, float g_score[])
{
cells CP;
CP.currentCell = neighborCell; //insert the neighbor cell
CP.fCost = g_score[neighborCell] + calculateHCost(neighborCell, goalCell);
OPL.insert(CP);
//multiset<cells>::iterator it = OPL.lower_bound(CP);
//multiset<cells>::iterator it = OPL.upper_bound(CP);
//OPL.insert( it, CP );
}
/*******************************************************************************
vector<int> BAstarPlannerROS::findFreeNeighborCell(int CellID)
{
int rowID = getCellRowID(CellID);
int colID = getCellColID(CellID);
int neighborIndex;
vector<int> freeNeighborCells;
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
{
//check whether the index is valid
if ((rowID + i >= 0) && (rowID + i < height) && (colID + j >= 0) && (colID + j < width) && (!(i == 0 && j == 0)))
{
neighborIndex = getCellIndex(rowID + i, colID + j);
if (isFree(neighborIndex))
freeNeighborCells.push_back(neighborIndex);
}
}
return freeNeighborCells;
}
//
//Function Name: isStartAndGoalCellsValid
//Inputs: the start and Goal cells
//Output: true if the start and the goal cells are valid
//Description: check if the start and goal cells are valid
/**/
bool BAstarPlannerROS::isStartAndGoalCellsValid(int startCell, int goalCell)
{
bool isvalid = true;
bool isFreeStartCell = isFree(startCell);
bool isFreeGoalCell = isFree(goalCell);
if (startCell == goalCell)
{
//cout << "The Start and the Goal cells are the same..." << endl;
isvalid = false;
}
else
{
if (!isFreeStartCell && !isFreeGoalCell)
{
//cout << "The start and the goal cells are obstacle positions..." << endl;
isvalid = false;
}
else
{
if (!isFreeStartCell)
{
//cout << "The start is an obstacle..." << endl;
isvalid = false;
}
else
{
if (!isFreeGoalCell)
{
//cout << "The goal cell is an obstacle..." << endl;
isvalid = false;
}
else
{
if (findFreeNeighborCell(goalCell).size() == 0)
{
//cout << "The goal cell is encountred by obstacles... "<< endl;
isvalid = false;
}
else
{
if (findFreeNeighborCell(startCell).size() == 0)
{
//cout << "The start cell is encountred by obstacles... "<< endl;
isvalid = false;
}
}
}
}
}
}
return isvalid;
}
float BAstarPlannerROS::getMoveCost(int i1, int j1, int i2, int j2)
{
float moveCost = INFINIT_COST; //start cost with maximum value. Change it to real cost of cells are connected
//if cell2(i2,j2) exists in the diagonal of cell1(i1,j1)
if ((j2 == j1 + 1 && i2 == i1 + 1) || (i2 == i1 - 1 && j2 == j1 + 1) || (i2 == i1 - 1 && j2 == j1 - 1) || (j2 == j1 - 1 && i2 == i1 + 1))
{
//moveCost = DIAGONAL_MOVE_COST;
moveCost = 1.4;
}
//if cell 2(i2,j2) exists in the horizontal or vertical line with cell1(i1,j1)
else
{
if ((j2 == j1 && i2 == i1 - 1) || (i2 == i1 && j2 == j1 - 1) || (i2 == i1 + 1 && j2 == j1) || (i1 == i2 && j2 == j1 + 1))
{
//moveCost = MOVE_COST;
moveCost = 1;
}
}
return moveCost;
}
float BAstarPlannerROS::getMoveCost(int CellID1, int CellID2)
{
int i1 = 0, i2 = 0, j1 = 0, j2 = 0;
i1 = getCellRowID(CellID1);
j1 = getCellColID(CellID1);
i2 = getCellRowID(CellID2);
j2 = getCellColID(CellID2);
return getMoveCost(i1, j1, i2, j2);
}
//verify if the cell(i,j) is free
bool BAstarPlannerROS::isFree(int i, int j)
{
int CellID = getCellIndex(i, j);
return OGM[CellID];
}
//verify if the cell(i,j) is free
bool BAstarPlannerROS::isFree(int CellID)
{
return OGM[CellID];
}
};
bool operator<(cells const &c1, cells const &c2) { return c1.fCost < c2.fCost; }
better_astar.h文件内容:
/** include the libraries you need in your planner here */
//#define forEach BOOST_FOREACH
/** for global path planner interface */
//#include <pcl_conversions/pcl_conversions.h>
using namespace std;
using std::string;
/**
};
namespace BAstar_planner {
class BAstarPlannerROS : public nav_core::BaseGlobalPlanner {
public:
BAstarPlannerROS (ros::NodeHandle &);
BAstarPlannerROS ();
BAstarPlannerROS(std::string name, costmap_2d::Costmap2DROS* costmap_ros);
ros::NodeHandle ROSNodeHandle;
ros::Publisher _plan_pub;
std::string _frame_id;
/** overriden classes from interface nav_core::BaseGlobalPlanner */
void initialize(std::string name, costmap_2d::Costmap2DROS costmap_ros);
bool makePlan(const geometry_msgs::PoseStamped& start,
const geometry_msgs::PoseStamped& goal,
std::vector<geometry_msgs::PoseStamped>& plan
);
void getCorrdinate (float& x, float& y);
int convertToCellIndex (float x, float y);
void convertToCoordinate(int index, float& x, float& y);
bool isCellInsideMap(float x, float y);
void mapToWorld(double mx, double my, double& wx, double& wy);
vector<int> BAstarPlanner(int startCell, int goalCell);
vector<int> findPath(int startCell, int goalCell, float g_score[]);
vector<int> constructPath(int startCell, int goalCell, float g_score[]);
float calculateHCost(int cellID, int goalCell);
// {
// int x1=getCellRowID(goalCell);
// int y1=getCellColID(goalCell);
// int x2=getCellRowID(cellID);
// int y2=getCellColID(cellID);
// return abs(x1-x2)+abs(y1-y2);
// //return min(abs(x1-x2),abs(y1-y2))*sqrt(2) + max(abs(x1-x2),abs(y1-y2))-min(abs(x1-x2),abs(y1-y2));
// }
void addNeighborCellToOpenList(multiset<cells> & OPL, int neighborCell, int goalCell, float g_score[]);
vector <int> findFreeNeighborCell (int CellID);
bool isStartAndGoalCellsValid(int startCell,int goalCell);
float getMoveCost(int CellID1, int CellID2);
float getMoveCost(int i1, int j1, int i2, int j2);
bool isFree(int CellID); //returns true if the cell is Free
bool isFree(int i, int j);
int getCellIndex(int i,int j) //get the index of the cell to be used in Path
{
return (i*width)+j;
}
int getCellRowID(int index)//get the row ID from cell index
{
return index/width;
}
int getCellColID(int index)//get colunm ID from cell index
{
return index%width;
}
float originX;
float originY;
float resolution;
costmap_2d::Costmap2DROS* costmap_ros_;
double step_size_, min_dist_from_robot_;
costmap_2d::Costmap2D* costmap_;
//base_local_planner::WorldModel* world_model_;
bool initialized_;
int width;
int height;
};
};
通过这两个文件构建的全局路径规划器会导致move_base节点崩溃
是不是代码中可能全局规划器里有一些非法内存操作?C++的程序能编译通过,不代表运行的时候不会崩溃,请各位大佬看看代码的问题
根据你提供的代码,以下是一些可能导致崩溃的问题和改进建议:
头文件引用:你在代码中使用了一些头文件,但是缺少了 # 符号,例如 include <stdio.h> 应该是 #include <stdio.h>。确保所有的头文件引用正确。
命名空间:在 better_astar.h 文件中,你使用了 namespace BAstar_planner,但在 better_astar.cpp 文件中没有使用该命名空间。请确保在 better_astar.cpp 中使用 namespace BAstar_planner。
类构造函数:在 better_astar.cpp 文件中,你定义了三个构造函数,但是没有实现它们的函数体。请确保在构造函数中进行必要的初始化操作,否则会导致未定义的行为。
initialize 函数:在 better_astar.cpp 文件中,你定义了 initialize 函数,但是函数签名与接口规范不符。接口规范要求传入 costmap_2d::Costmap2DROS* 类型的参数,但是你定义为 costmap_2d::Costmap2DROS 类型。请修改函数签名以匹配接口规范。
内存管理:在 initialize 函数中,你使用 new 运算符为 OGM 分配了内存,但是在函数结尾处没有使用 delete 运算符释放内存。请确保在适当的地方释放动态分配的内存,避免内存泄漏。
addNeighborCellToOpenList 函数:在该函数中,你尝试通过插入 CP 结构体元素到 multiset 容器中,但是注释掉的代码表明你可能想要在特定位置插入元素。请注意 multiset 是按照元素的值进行排序,因此不需要手动指定插入位置。
请仔细检查以上问题并进行相应的修改。如果问题仍然存在,请提供更多关于错误的详细信息或错误日志,以便更好地帮助你解决问题。
现在节点不崩溃了,只会一直报错无效起点和终点