45 int start = include_edges ? 0 : 1;
46 unsigned int x_max = include_edges ? info.
width : info.
width - 1;
47 unsigned int y_max = include_edges ? info.
height : info.
height - 1;
48 nav_2d_msgs::Pose2DStamped pose;
49 pose.header.frame_id = info.
frame_id;
51 for (
unsigned int i = start; i < x_max; i++)
53 for (
unsigned int j = start; j < y_max; j++)
56 unsigned char cost = costmap(i, j);
59 free_cells.push_back(pose);
63 occupied_cells.push_back(pose);
72 double ox = costmap.getOriginX(), oy = costmap.getOriginY();
73 double res = costmap.getResolution();
74 double w = costmap.getWidth() * res, h = costmap.getHeight() * res;
75 double offset = 3.0 * res;
76 nav_2d_msgs::Pose2DStamped pose;
77 pose.header.frame_id = costmap.getFrameId();
78 pose.pose.x = ox - offset;
79 pose.pose.y = oy - offset;
80 poses.push_back(pose);
81 pose.pose.y = oy + h + offset;
82 poses.push_back(pose);
83 pose.pose.x = ox + w + offset;
84 poses.push_back(pose);
85 pose.pose.y = oy - offset;
86 poses.push_back(pose);
93 if (cells.size() == 0 || num_cells == 0)
98 if (cells.size() <= num_cells)
101 while (subset.size() < num_cells)
103 subset.push_back(cells[i++]);
104 if (i >= cells.size())
112 double inc = cells.size() /
static_cast<double>(num_cells);
114 while (subset.size() < num_cells)
116 subset.push_back(cells[static_cast<int>(i)]);
138 bool verbose,
bool quit_early)
140 int passing_plans = 0, total_plans = 0;
141 for (nav_2d_msgs::Pose2DStamped start_pose : free_cells)
143 for (nav_2d_msgs::Pose2DStamped goal_pose : free_cells)
147 if (
planExists(planner, start_pose, goal_pose))
153 ROS_INFO(
"Failed to find a path between %.2f %.2f and %.2f %.2f",
154 start_pose.pose.x, start_pose.pose.y, goal_pose.pose.x, goal_pose.pose.y);
162 ROS_INFO(
"%d/%d valid plans found.", passing_plans, total_plans);
164 return passing_plans == total_plans;
169 const std::string& test_name,
170 bool check_exception_type,
bool verbose,
bool quit_early,
bool invalid_starts)
172 int passing_plans = 0, total_plans = 0;
174 for (nav_2d_msgs::Pose2DStamped start_pose : start_cells)
176 for (nav_2d_msgs::Pose2DStamped goal_pose : goal_cells)
182 planner.
makePlan(start_pose, goal_pose);
186 ROS_INFO(
"Found an unexpected valid %s path between %.2f %.2f and %.2f %.2f", test_name.c_str(),
187 start_pose.pose.x, start_pose.pose.y, goal_pose.pose.x, goal_pose.pose.y);
194 if (check_exception_type)
195 valid = invalid_starts;
199 if (check_exception_type)
200 valid = !invalid_starts;
204 valid = !check_exception_type;
212 ROS_INFO(
"An unexpected exception was thrown attempting a %s path between %.2f %.2f and %.2f %.2f",
213 test_name.c_str(), start_pose.pose.x, start_pose.pose.y, goal_pose.pose.x, goal_pose.pose.y);
220 ROS_INFO(
"%d/%d %s plans correctly aborted.", passing_plans, total_plans, test_name.c_str());
221 return passing_plans == total_plans;
226 const std::string& test_name,
227 bool check_exception_type,
bool verbose,
bool quit_early,
bool invalid_starts)
229 int passing_plans = 0, total_plans = 0;
231 for (nav_2d_msgs::Pose2DStamped start_pose : start_cells)
233 for (nav_2d_msgs::Pose2DStamped goal_pose : goal_cells)
239 planner.
makePlan(start_pose, goal_pose);
243 ROS_INFO(
"Found an unexpected valid %s path between %.2f %.2f and %.2f %.2f", test_name.c_str(),
244 start_pose.pose.x, start_pose.pose.y, goal_pose.pose.x, goal_pose.pose.y);
251 if (check_exception_type)
252 valid = invalid_starts;
256 if (check_exception_type)
257 valid = !invalid_starts;
261 valid = !check_exception_type;
269 ROS_INFO(
"An unexpected exception was thrown attempting a %s path between %.2f %.2f and %.2f %.2f",
270 test_name.c_str(), start_pose.pose.x, start_pose.pose.y, goal_pose.pose.x, goal_pose.pose.y);
277 ROS_INFO(
"%d/%d %s plans correctly aborted.", passing_plans, total_plans, test_name.c_str());
278 return passing_plans == total_plans;
283 bool check_exception_type,
bool verbose,
bool quit_early)
285 PoseList free_cells, occupied_cells;
286 groupCells(costmap, free_cells, occupied_cells);
289 if (!ret && quit_early)
293 if (max_failure_cases >= 0)
296 occupied_cells =
subsetPoseList(occupied_cells, max_failure_cases);
300 check_exception_type, verbose, quit_early,
false) && ret;
301 if (!ret && quit_early)
307 check_exception_type, verbose, quit_early,
true) && ret;
308 if (!ret && quit_early)
314 false, verbose, quit_early) && ret;
315 if (!ret && quit_early)
322 check_exception_type, verbose, quit_early,
false) && ret;
323 if (!ret && quit_early)
329 check_exception_type, verbose, quit_early,
true) && ret;
330 if (!ret && quit_early)
336 false, verbose, quit_early) && ret;
337 if (!ret && quit_early)
346 bool check_exception_type,
bool verbose,
bool quit_early)
348 PoseList free_cells, occupied_cells;
349 groupCells(costmap, free_cells, occupied_cells);
350 int passing_plans = 0, total_plans = 0;
352 unsigned int n = free_cells.size();
353 for (
unsigned int i = 0; i < n; i++)
355 for (
unsigned int j = 0; j < n; j++)
357 if (i == j)
continue;
362 planner.
makePlan(free_cells[i], free_cells[j]);
366 ROS_INFO(
"Found an unexpected valid path between %.2f %.2f and %.2f %.2f",
367 free_cells[i].pose.x, free_cells[i].pose.y, free_cells[j].pose.x, free_cells[j].pose.y);
378 valid = !check_exception_type;
386 ROS_INFO(
"An unexpected exception was thrown attempting to plan between %.2f %.2f and %.2f %.2f",
387 free_cells[i].pose.x, free_cells[i].pose.y, free_cells[j].pose.x, free_cells[j].pose.y);
394 ROS_INFO(
"%d/%d correctly aborted for having no path.", passing_plans, total_plans);
395 return passing_plans == total_plans;
PoseList createPosesOutsideCostmap(const nav_core2::Costmap &costmap)
Create a list of poses that are outside the costmap's bounds.
std::vector< nav_2d_msgs::Pose2DStamped > PoseList
static const unsigned char INSCRIBED_INFLATED_OBSTACLE
bool checkValidPathCoverage(nav_core2::GlobalPlanner &planner, const PoseList &free_cells, bool verbose=false, bool quit_early=true)
Check if a path exists between every pair of free_cells.
void gridToWorld(const NavGridInfo &info, int mx, int my, double &wx, double &wy)
static const unsigned char NO_INFORMATION
PoseList subsetPoseList(const PoseList &cells, unsigned int num_cells)
Create a new list of poses from cells that is num_cells long.
bool checkOccupiedPathCoverage(nav_core2::GlobalPlanner &planner, const PoseList &start_cells, const PoseList &goal_cells, const std::string &test_name, bool check_exception_type=true, bool verbose=false, bool quit_early=true, bool invalid_starts=true)
Check if the appropriate exception is thrown when attempting to plan to or from an occupied cell...
bool hasCompleteCoverage(nav_core2::GlobalPlanner &planner, const nav_core2::Costmap &costmap, int max_failure_cases=10, bool check_exception_type=true, bool verbose=false, bool quit_early=true)
Run a bunch of tests, assuming there is a valid path from any free cell to any other free cell...
bool checkOutOfBoundsPathCoverage(nav_core2::GlobalPlanner &planner, const PoseList &start_cells, const PoseList &goal_cells, const std::string &test_name, bool check_exception_type=true, bool verbose=false, bool quit_early=true, bool invalid_starts=true)
Check if the appropriate exception is thrown when attempting to plan to or from a pose off the costma...
bool planExists(nav_core2::GlobalPlanner &planner, nav_2d_msgs::Pose2DStamped start, nav_2d_msgs::Pose2DStamped goal)
Simple check to see if a plan exists. Returns a boolean instead of returning path or throwing an exce...
TFSIMD_FORCE_INLINE const tfScalar & w() const
virtual nav_2d_msgs::Path2D makePlan(const nav_2d_msgs::Pose2DStamped &start, const nav_2d_msgs::Pose2DStamped &goal)=0
void groupCells(const nav_core2::Costmap &costmap, PoseList &free_cells, PoseList &occupied_cells, bool include_edges=true)
Populate two lists of poses from a costmap. one with all the free cells, the other with all the occup...
bool hasNoPaths(nav_core2::GlobalPlanner &planner, const nav_core2::Costmap &costmap, bool check_exception_type=true, bool verbose=false, bool quit_early=true)
Run a bunch of tests, assuming there are no valid paths from any free cell to any other free cell...