Required Info:
- Operating System: Ubuntu 22.04
- ROS2 Version: Humble
- DDS implementation: Cyclone DDS
- Controller: MPPI
Problem
A robot follows a path normally (everything is fine :=) ). Then, for any reason, FollowPath is aborted (Failed to make progress). At that moment the robot is on a path pose that is farther than max_robot_pose_search_dist from the start of the path
Now the same path is sent to FollowPath again, and we get the error. Here is why:
1. setPath is called → global_plan is reset to the full plan → the front goes back to pose 0. The already-traveled part comes back.
2. The robot is far along the path (e.g. pose 480 of 483).
3. The closest-point search only looks max_robot_pose_search_dist (5 m ≈ the first ~100 poses) ahead of the front. The robot's real closest pose (pose 480) is far outside this window.
4. The search returns the closest pose inside the window (e.g. pose 99, which is 14.75 m away from the robot). That pose is outside the local costmap -> the transformed plan is empty -> throw "Resulting plan has 0 poses in it." -> abort again.
5. The BT sends the same path again → reset again → empty again → loop._
So : the robot is exactly on the path and the poses it should follow are right in front of it. Only the search cannot find them, because after the front is reset the bounded window cannot reach the robot's real position.
I added a log that compares the bounded (capped) search with an unbounded (full-path) search:
Resulting plan has 0 poses. robot=(2.19, 9.23) in 'map'; global_plan=483 poses,
pruned=384 poses; nearest pose found=(-4.67, -3.83), dist robot->found=14.75 m;
costmap 'odom' origin=(1.00, -1.00) size=10.0x10.0 m [x:1.00..10.97 y:-1.00..8.98].
- bounded = result of the capped search (only looks max_robot_pose_search_dist ahead of the front).
- unbounded = result of searching the whole path (no cap).
- d(unbounded)=0.03 m, idx(unbounded)=480 → the robot is on the path, at pose 480; a full search finds it instantly.
- d(bounded)=14.75 m, idx(bounded)=99 → the capped search is stuck at pose 99, 14.75 m away, because pose 480 is far beyond the window (window_end=100).
- That far pose is outside the local costmap → transformed plan is empty → throw.
Workaround and why it is not enough
Computing a new global plan from the robot's current position fixes it. But:
- The current path is already valid and the robot is right on it
- Re-planning is expensive in large environments and is a waste of time.
So: the path could simply be resumed, but instead the system is forced into a costly replan.
Relevant code
1) setPath: when a new OR the same plan is set, the pruned plan is reset -> front goes back to pose 0
void PathHandler::setPath(const nav_msgs::msg::Path & plan) {
global_plan_ = plan;
global_plan_up_to_inversion_ = global_plan_; // front = pose 0 (pruning is lost)
}
2) The closest-point search only looks max_robot_pose_search_dist ahead of the front
auto closest_pose_upper_bound = nav2_util::geometry_utils::first_after_integrated_distance(
global_plan_.poses.begin(), global_plan_.poses.end(), max_robot_pose_search_dist_);
auto closest_point = nav2_util::geometry_utils::min_by(
global_plan_.poses.begin(), closest_pose_upper_bound,
[&](const auto & ps){ return euclidean_distance(global_pose, ps); });
3) If the window does not cover the robot's real position, the transformed plan is empty -> throw
if (transformed_plan.poses.empty()) {
throw nav2_core::InvalidPath("Resulting plan has 0 poses in it.");
}
- Happy to open a PR if there is interest.
Required Info:
Problem
A robot follows a path normally (everything is fine :=) ). Then, for any reason, FollowPath is aborted (Failed to make progress). At that moment the robot is on a path pose that is farther than max_robot_pose_search_dist from the start of the path
Now the same path is sent to FollowPath again, and we get the error. Here is why:
1. setPath is called → global_plan is reset to the full plan → the front goes back to pose 0. The already-traveled part comes back.
2. The robot is far along the path (e.g. pose 480 of 483).
3. The closest-point search only looks max_robot_pose_search_dist (5 m ≈ the first ~100 poses) ahead of the front. The robot's real closest pose (pose 480) is far outside this window.
4. The search returns the closest pose inside the window (e.g. pose 99, which is 14.75 m away from the robot). That pose is outside the local costmap -> the transformed plan is empty -> throw "Resulting plan has 0 poses in it." -> abort again.
5. The BT sends the same path again → reset again → empty again → loop._
So : the robot is exactly on the path and the poses it should follow are right in front of it. Only the search cannot find them, because after the front is reset the bounded window cannot reach the robot's real position.
I added a log that compares the bounded (capped) search with an unbounded (full-path) search:
Workaround and why it is not enough
Computing a new global plan from the robot's current position fixes it. But:
So: the path could simply be resumed, but instead the system is forced into a costly replan.
Relevant code
1) setPath: when a new OR the same plan is set, the pruned plan is reset -> front goes back to pose 0
2) The closest-point search only looks max_robot_pose_search_dist ahead of the front
3) If the window does not cover the robot's real position, the transformed plan is empty -> throw