-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Centralize path handler logic in controller server #5446
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@SteveMacenski before I go too far, can you take a quick look to make sure I am on the right track? I have only pushed the changes in nav2_controller, graceful_controller and RPP |
@mini-1235, your PR has failed to build. Please check CI outputs and resolve issues. |
I have spent some time reading into MPPI's path handler, I can see there are some improvements like #3659, #3443. Also, there is a related PR for RPP in #4763, maybe we need to check if these changes are applicable to all controllers? If yes, I guess it will be easier to move them in Controller Server I also noticed that the DWB/MPPI need the path from planner to find its goal, should we pass this plan via the setplan api or a new argument in computevelocitycommands? |
Hi, sorry to jump in here but just sharing my two cents: |
I think path_handler implementation from MPPI is more comprehensive as it also considers path up to inversion point. This would also be helpful when user uses Hybrid A* with reeds-shepp as the global planner. |
Thanks for sharing, I will try to implement this and compare with my current method |
@mini-1235, your PR has failed to build. Please check CI outputs and resolve issues. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry it took so long!
// Current path container | ||
nav_msgs::msg::Path current_path_; | ||
nav_msgs::msg::Path local_path_; | ||
bool interpolate_curvature_after_goal_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really a controller-server specific parameter? This feels specific to a given control algorithm plugin. Does the path handler need to know about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think path handler needs to, this is used as the reject_unit_path
in rpp's path handler
bool reject_unit_path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I should rename it as reject unit path in my new path handler?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is still valid, any suggestions? @SteveMacenski
goal_checker_loader_("nav2_core", "nav2_core::GoalChecker"), | ||
default_goal_checker_ids_{"goal_checker"}, | ||
default_goal_checker_types_{"nav2_controller::SimpleGoalChecker"}, | ||
default_goal_checker_types_{"nav2_controller::PathCompleteGoalChecker"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think by 'default' I mean that this should just be built into the simple goal checker so that this just given to everyone 'for free'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I should remove this new plugin and add the path_length_tolerance
to simple goal checker, do I understand this correctly?
|
||
odom_sub_ = std::make_unique<nav2_util::OdomSmoother>(node, odom_duration, odom_topic); | ||
vel_publisher_ = std::make_unique<nav2_util::TwistPublisher>(node, "cmd_vel"); | ||
global_path_pub_ = node->create_publisher<nav_msgs::msg::Path>("received_global_plan"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this? We in other contexts publish out the path after its been pruned and converted into the odom frame for the local_path publisher so that we have a sense of what the controller is working with. Why directly publish out the global plan?
auto transformed_plan = path_handler_->transformGlobalPlan( | ||
pose, max_robot_pose_search_dist_, interpolate_curvature_after_goal_); | ||
// RCLCPP_INFO(get_logger(), "compute remaining distance %lf ",nav2_util::geometry_utils::calculate_path_length(transformed_plan)); | ||
global_path_pub_->publish(transformed_plan); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if this is pruned, in the odom frame, and such, this is a local plan
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, make this into a unique pointer make_unique<nav_msgs::msg::Path>(local_path_)
I agree with this general sentiment. I think it would be nice to review all the path handlers and make sure the key features of all are being respected in the server's implementation. There's a number of CI failures that should also be looked at, but I'm sure you know :-) |
Yes, I will continue this PR once #5496 and other future PRs targeting path handler are done |
145b2d9
to
ea45821
Compare
@mini-1235, your PR has failed to build. Please check CI outputs and resolve issues. |
@SteveMacenski I think you can start reviewing this when you have time, in the following days I plan to:
Things to debate:
I think this becomes problematic when enforce_path_inversion is set to true. In that case, the local goal ends up being the cusping point, and the robot may stop there once it satisfies the XY and yaw tolerances. Because of this, I believe we still need the global goal for the goal checker. But as @SteveMacenski suggested, we could add this directly into the simple goal checker, so by default the simple goal checker is checking both the global goal and local path length. Do you agree with this approach? @mamariomiamo
Previously, the transform tolerance in the controller server was obtained from
Before merging this, I also need to:
|
@mini-1235, your PR has failed to build. Please check CI outputs and resolve issues. |
OK will do! This is admittedly alot so this next round is going to be more high level.
Ah ok. That makes sense for the goal checker, though probably not the other elements right? When enforcing inversions is off, its the same either way since we just prune to the prune distance / costmap bounds. When is it enabled, then we prune to that which we want from the control algorithm's perspective, but not the goal checker.
Why not have it still acquire it from costmap2D, just stored and used at the controller server level? I suppose I prefer less parameters to more, but I'm OK either way.
Do both - first after the integrated distance, as long as that distance is within the costmap bounds. |
*/ | ||
~ParameterHandler(); | ||
|
||
std::mutex & getMutex() {return mutex_;} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this being properly locked when needed in the main function(s) so that dynamic parameters aren't being updated during execution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I forgot to add this, will add it in the next update
Yes, when it is on, the distance to the local goal can become very small. That's why I think this local goal is not suitable to use in the goal checker
For the controller plugins as well?
Not sure if I understand this, can you elaborate? |
Isn't that in effect what is done today?
Basically combine the two: navigation2/nav2_controller/src/path_handler.cpp Lines 134 to 146 in 3404f3a
|
A good suggestion I received today: It would be great to make the path handler itself a plugin so that other users can replace this implementation if they see fit. A nice side effect is it makes us have to think a bit more about the API interfaces for it to make sure its generally good for a broad range of purposes and include all the information for the APIs other implementations may want that we have access to. Another would be possibly changing the pruning distance to be proportional to time instead, to prune the distance set out by that time by the maximum velocity. That way it wasn't something that needed to be tuned for changing velocity limits. Finally, maybe it would be good to provide feedback about the current idx of the path we're on to use in the BT Navigator for computing ETA, path length remaining, and so forth. That way we handle the issue of path looping using the wrong index globally |
I will think about it and reply tomorrow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you have some settings for 4 spaces rather than 2 which have affected a number of file's indentations
* @brief Creates list of BT ports | ||
* @return BT::PortsList Containing basic ports along with node-specific ports | ||
*/ | ||
static BT::PortsList providedPorts() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per usual: new BT nodes, parameters, etc should have configuration guide updates and migration guide entries. For new BT nodes and plugins, add them to the Navigation Plugins table
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add when this PR is close to merge
* @param velocity Current robot velocity | ||
* @param goal_checker Pointer to the current goal checker the task is utilizing | ||
* @param transformed_global_plan The global plan after being processed by the path handler | ||
* @param goal The last pose of the global plan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd call this 'global_goal' and offer a PoseStamped so the frame information is retained.
* path segments the robot has already traversed and transforming the remaining, | ||
* relevant portion of the path into the costmap's global or base frame. | ||
*/ | ||
class PathHandler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe ControllerPathHandler
since if this is outside of hte context of the controller server, it would be good to make sure its clear the intent of how this is to be used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think PathHandler
is better here, as we only have GoalChecker
, ProgressChecker
instead of ControllerGoalChecker
and ControllerProgressChecker
, it would be strange to see something like
controller_server:
ros__parameters:
goal_checker_plugins: ["general_goal_checker"] # "precise_goal_checker"
controller_path_handler_plugins: ["path_handler"]
(?)
} | ||
|
||
/** @brief Returns the delay in transform (tf) data that is tolerable in seconds */ | ||
double getTransformTolerance() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd leave this as is in case others are using this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed #4907 when refactoring the dynamic parameters in controller server. I think my current approach is problematic since the server and the plugin share the same parameter (similar to controller frequency we removed in #4907). I guess your suggestion earlier is better in this case for both server and plugin?
Why not have it still acquire it from costmap2D, just stored and used at the controller server level?
string controller_id | ||
string goal_checker_id | ||
string progress_checker_id | ||
string path_handler_id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to expose this in the Simple Commander API as well
Also in the example uses of the FollowPath BT node + in the Nav2 default BT XMLs (where ever existing ones have the other Progress Checker / Goal Checker Selectors)
Probably happened when I copy + paste some old files, maybe I should open another PR to format them all first? |
This pull request is in conflict. Could you fix it @mini-1235? |
Signed-off-by: mini-1235 <[email protected]>
Signed-off-by: mini-1235 <[email protected]>
Signed-off-by: mini-1235 <[email protected]>
@mini-1235, your PR has failed to build. Please check CI outputs and resolve issues. |
Signed-off-by: mini-1235 <[email protected]>
Signed-off-by: mini-1235 <[email protected]>
Signed-off-by: mini-1235 <[email protected]>
Signed-off-by: mini-1235 <[email protected]>
@mini-1235, your PR has failed to build. Please check CI outputs and resolve issues. |
Signed-off-by: mini-1235 <[email protected]>
Signed-off-by: mini-1235 <[email protected]>
Signed-off-by: mini-1235 <[email protected]>
Signed-off-by: mini-1235 <[email protected]>
I have been testing this PR for a few days, updating my result here:
Note that this only happens in NavThroughPoses mode
|
Signed-off-by: mini-1235 <[email protected]>
std::bind( | ||
&ParameterHandler::validateParameterUpdatesCallback, | ||
this, std::placeholders::_1)); | ||
post_set_params_handler_ = node->add_post_set_parameters_callback( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create the post- callback first so that it is ready anytime the on-set callback could be triggered (could cause a really rare race condition issue)
nav2_bt_navigator/behavior_trees/navigate_w_replanning_distance.xml
Outdated
Show resolved
Hide resolved
Why so on DWB? If the goal checker / path given is restricted to the local time horizon, it shouldn't know anything about far away loops and so forth once a path segment leaves the local costmap bounds / search distance (like MPPI, RPP, etc).
Yeah that is true. Setting |
Signed-off-by: mini-1235 <[email protected]>
Signed-off-by: mini-1235 <[email protected]>
Let me clarify, consider the following situation: Oct.16.2025.Video.mp4where the first goal overlaps with the third goal. When the robot reaches the final goal, the path handler still generates a local plan (blue path), and the goal checker doesn’t report that the goal has been reached. However, due to the goal critic, the robot can’t move further |
Oh. Can we add that similar constraint from the goal checker for the path length into DWB? That should be a 3 liner easy enough to resolve, no? When you have a chance, comment on any open review items. I think some are done / irrelevant now, but might be good to see what's still open and if they're still important to think about. Super happy and excited by this! This is a great refactor and going to fix a pretty long-standing issue with NavigateThroughPoses that I'm really excited for ❤️ |
I think we have 3 critics that are related to goal:
I added an if condition in those critics:
However, the robot ends up staying still instead of navigating toward the goal. From my understanding, the
I left a comment here #5446 (comment). For other comments, I believe I have replied to your questions as well, could you please check and see if I have addressed your concerns? I will do a self-review tomorrow to make sure I didn't miss anything, and also format the files :) |
This PR continues the work in #4789
Fixes #4757
Fixes #4304