diff --git a/nav2_smac_planner/src/smac_planner_2d.cpp b/nav2_smac_planner/src/smac_planner_2d.cpp index 1dfdebfbfc6..99734849a0a 100644 --- a/nav2_smac_planner/src/smac_planner_2d.cpp +++ b/nav2_smac_planner/src/smac_planner_2d.cpp @@ -258,7 +258,7 @@ nav_msgs::msg::Path SmacPlanner2D::createPlan( pose.pose.orientation.z = 0.0; pose.pose.orientation.w = 1.0; - // Corner case of start and goal beeing on the same cell + // Corner case of start and goal being on the same cell if (std::floor(mx_start) == std::floor(mx_goal) && std::floor(my_start) == std::floor(my_goal)) { pose.pose = start.pose; // if we have a different start and goal orientation, set the unique path pose to the goal @@ -268,6 +268,12 @@ nav_msgs::msg::Path SmacPlanner2D::createPlan( pose.pose.orientation = goal.pose.orientation; } plan.poses.push_back(pose); + + // Publish raw path for debug + if (_raw_plan_publisher->get_subscription_count() > 0) { + _raw_plan_publisher->publish(plan); + } + return plan; } diff --git a/nav2_smac_planner/src/smac_planner_hybrid.cpp b/nav2_smac_planner/src/smac_planner_hybrid.cpp index 02b85fef7a5..fcce89cdfea 100644 --- a/nav2_smac_planner/src/smac_planner_hybrid.cpp +++ b/nav2_smac_planner/src/smac_planner_hybrid.cpp @@ -359,8 +359,13 @@ nav_msgs::msg::Path SmacPlannerHybrid::createPlan( _a_star->setCollisionChecker(&_collision_checker); // Set starting point, in A* bin search coordinates - float mx, my; - if (!costmap->worldToMapContinuous(start.pose.position.x, start.pose.position.y, mx, my)) { + float mx_start, my_start, mx_goal, my_goal; + if (!costmap->worldToMapContinuous( + start.pose.position.x, + start.pose.position.y, + mx_start, + my_start)) + { throw nav2_core::StartOutsideMapBounds( "Start Coordinates of(" + std::to_string(start.pose.position.x) + ", " + std::to_string(start.pose.position.y) + ") was outside bounds"); @@ -374,10 +379,15 @@ nav_msgs::msg::Path SmacPlannerHybrid::createPlan( if (orientation_bin >= static_cast(_angle_quantizations)) { orientation_bin -= static_cast(_angle_quantizations); } - _a_star->setStart(mx, my, static_cast(orientation_bin)); + _a_star->setStart(mx_start, my_start, static_cast(orientation_bin)); // Set goal point, in A* bin search coordinates - if (!costmap->worldToMapContinuous(goal.pose.position.x, goal.pose.position.y, mx, my)) { + if (!costmap->worldToMapContinuous( + goal.pose.position.x, + goal.pose.position.y, + mx_goal, + my_goal)) + { throw nav2_core::GoalOutsideMapBounds( "Goal Coordinates of(" + std::to_string(goal.pose.position.x) + ", " + std::to_string(goal.pose.position.y) + ") was outside bounds"); @@ -390,7 +400,7 @@ nav_msgs::msg::Path SmacPlannerHybrid::createPlan( if (orientation_bin >= static_cast(_angle_quantizations)) { orientation_bin -= static_cast(_angle_quantizations); } - _a_star->setGoal(mx, my, static_cast(orientation_bin)); + _a_star->setGoal(mx_goal, my_goal, static_cast(orientation_bin)); // Setup message nav_msgs::msg::Path plan; @@ -404,6 +414,22 @@ nav_msgs::msg::Path SmacPlannerHybrid::createPlan( pose.pose.orientation.z = 0.0; pose.pose.orientation.w = 1.0; + // Corner case of start and goal being on the same cell + if (std::floor(mx_start) == std::floor(mx_goal) && + std::floor(my_start) == std::floor(my_goal)) + { + pose.pose = start.pose; + pose.pose.orientation = goal.pose.orientation; + plan.poses.push_back(pose); + + // Publish raw path for debug + if (_raw_plan_publisher->get_subscription_count() > 0) { + _raw_plan_publisher->publish(plan); + } + + return plan; + } + // Compute plan NodeHybrid::CoordinateVector path; int num_iterations = 0; diff --git a/nav2_smac_planner/src/smac_planner_lattice.cpp b/nav2_smac_planner/src/smac_planner_lattice.cpp index ebeead9c5c4..82bdcc9810e 100644 --- a/nav2_smac_planner/src/smac_planner_lattice.cpp +++ b/nav2_smac_planner/src/smac_planner_lattice.cpp @@ -286,24 +286,34 @@ nav_msgs::msg::Path SmacPlannerLattice::createPlan( _a_star->setCollisionChecker(&_collision_checker); // Set starting point, in A* bin search coordinates - float mx, my; - if (!_costmap->worldToMapContinuous(start.pose.position.x, start.pose.position.y, mx, my)) { + float mx_start, my_start, mx_goal, my_goal; + if (!_costmap->worldToMapContinuous( + start.pose.position.x, + start.pose.position.y, + mx_start, + my_start)) + { throw nav2_core::StartOutsideMapBounds( "Start Coordinates of(" + std::to_string(start.pose.position.x) + ", " + std::to_string(start.pose.position.y) + ") was outside bounds"); } _a_star->setStart( - mx, my, + mx_start, my_start, NodeLattice::motion_table.getClosestAngularBin(tf2::getYaw(start.pose.orientation))); // Set goal point, in A* bin search coordinates - if (!_costmap->worldToMapContinuous(goal.pose.position.x, goal.pose.position.y, mx, my)) { + if (!_costmap->worldToMapContinuous( + goal.pose.position.x, + goal.pose.position.y, + mx_goal, + my_goal)) + { throw nav2_core::GoalOutsideMapBounds( "Goal Coordinates of(" + std::to_string(goal.pose.position.x) + ", " + std::to_string(goal.pose.position.y) + ") was outside bounds"); } _a_star->setGoal( - mx, my, + mx_goal, my_goal, NodeLattice::motion_table.getClosestAngularBin(tf2::getYaw(goal.pose.orientation))); // Setup message @@ -318,6 +328,22 @@ nav_msgs::msg::Path SmacPlannerLattice::createPlan( pose.pose.orientation.z = 0.0; pose.pose.orientation.w = 1.0; + // Corner case of start and goal being on the same cell + if (std::floor(mx_start) == std::floor(mx_goal) && + std::floor(my_start) == std::floor(my_goal)) + { + pose.pose = start.pose; + pose.pose.orientation = goal.pose.orientation; + plan.poses.push_back(pose); + + // Publish raw path for debug + if (_raw_plan_publisher->get_subscription_count() > 0) { + _raw_plan_publisher->publish(plan); + } + + return plan; + } + // Compute plan NodeLattice::CoordinateVector path; int num_iterations = 0; diff --git a/nav2_smac_planner/test/test_smac_2d.cpp b/nav2_smac_planner/test/test_smac_2d.cpp index e2dff5a56f4..89ad666b789 100644 --- a/nav2_smac_planner/test/test_smac_2d.cpp +++ b/nav2_smac_planner/test/test_smac_2d.cpp @@ -77,6 +77,13 @@ TEST(SmacTest, test_smac_2d) { } catch (...) { } + // corner case where the start and goal are on the same cell + goal.pose.position.x = 0.01; + goal.pose.position.y = 0.01; + + nav_msgs::msg::Path plan = planner_2d->createPlan(start, goal, dummy_cancel_checker); + EXPECT_EQ(plan.poses.size(), 1); // single point path + planner_2d->deactivate(); planner_2d->cleanup(); diff --git a/nav2_smac_planner/test/test_smac_hybrid.cpp b/nav2_smac_planner/test/test_smac_hybrid.cpp index 9952912596b..a70ae86fc7d 100644 --- a/nav2_smac_planner/test/test_smac_hybrid.cpp +++ b/nav2_smac_planner/test/test_smac_hybrid.cpp @@ -76,6 +76,13 @@ TEST(SmacTest, test_smac_se2) } catch (...) { } + // corner case where the start and goal are on the same cell + goal.pose.position.x = 0.01; + goal.pose.position.y = 0.01; + + nav_msgs::msg::Path plan = planner->createPlan(start, goal, dummy_cancel_checker); + EXPECT_EQ(plan.poses.size(), 1); // single point path + planner->deactivate(); planner->cleanup(); diff --git a/nav2_smac_planner/test/test_smac_lattice.cpp b/nav2_smac_planner/test/test_smac_lattice.cpp index dcc925e9e72..c187abd8591 100644 --- a/nav2_smac_planner/test/test_smac_lattice.cpp +++ b/nav2_smac_planner/test/test_smac_lattice.cpp @@ -84,6 +84,13 @@ TEST(SmacTest, test_smac_lattice) } catch (...) { } + // corner case where the start and goal are on the same cell + goal.pose.position.x = 0.01; + goal.pose.position.y = 0.01; + + nav_msgs::msg::Path plan = planner->createPlan(start, goal, dummy_cancel_checker); + EXPECT_EQ(plan.poses.size(), 1); // single point path + planner->deactivate(); planner->cleanup();