-
Notifications
You must be signed in to change notification settings - Fork 1.6k
MPPI cost-based visualization #5643
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
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
nav2_mppi_controller/include/nav2_mppi_controller/critics/path_align_critic.hpp
Outdated
Show resolved
Hide resolved
| const float j_flt = static_cast<float>(j); | ||
| float blue_component = 1.0f - j_flt / shape_1; | ||
| float green_component = j_flt / shape_1; | ||
| // Use percentile-based normalization to handle outliers |
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.
It's important because the CostCritic creates high-cost outliers which increases the range of the color gradient to a point where it's just green or red
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.
We could also skip trajectories marked as collision from the normalization process. Only have the scale normalization apply to non-collision trajectories. Have in-collision trajectories be straight up red-only (which makes sense to a casual viewer as well)
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.
We could also skip trajectories marked as collision from the normalization process
I thought about that but how would you determine that? Just based off the cost? or would you add a in_collision field to Trajectories
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.
Did you end up addressing this point? I see trajectory visualizations below that have collision ones as magenta
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
|
I only had a quick look as I am traveling. I think keeping the optimal trajectory visualized and distinguished is important, as it's the most useful part. |
|
Thanks for the review, will polish it tomorrow |
|
I'll be on a plane to singapore, so it might be a minute before I can give it another looksee given ROSCon. |
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
| if (publish_optimal_path_) { | ||
| optimal_path_pub_ = node->create_publisher<nav_msgs::msg::Path>("~/optimal_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.
We already have the optimal path published under a namespace in ~/candidate_trajectories, do you see the need to publish it on a separate topic as well?
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, please leave 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.
Gladly but just fmi, why the duplicate visualization? If we were to keep one though, I'd keep this one and remove the one namespaced under ~/candidate_trajectories because that topic is very heavy and if I just want the optimal_trajectory I'd rather not get the extra baggage with it
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
|
@SteveMacenski I addressed many of your comments but additionally made many more changes. Can you give it a general look? There are probably a bunch of nitpicks left. For now I dropped visualizing in-collision trajectories with another color because I think that would require adding an additional vector in CriticsData that tracks which trajectories are in-collision. Would you be open to that? Another option would be to somewhat infer from the cost if there was a collision |
Oh, I didn't see it. It probably looks clearer when reducing the number of steps. |
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
Signed-off-by: Tony Najjar <[email protected]>
SteveMacenski
left a comment
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 is just alot of changes which is making this hard for me to review. I don't want to flood you with stuff so I'm going to keep many of these items higher level
| for (Eigen::Index i = 0; i < costs.size(); ++i) { | ||
| min_cost = std::min(min_cost, costs(i)); | ||
| max_cost = std::max(max_cost, costs(i)); | ||
| } |
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.
float min_val = arr.minCoeff();
float max_val = arr.maxCoeff();
would do the same in a vectorized format
| blue_component = 0.5f; | ||
| } else { | ||
| // Normal gradient for trajectories | ||
| float normalized_cost = (costs(i) - min_cost) / cost_range; |
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.
https://github.com/ros-navigation/navigation2/blob/main/nav2_mppi_controller/src/optimizer.cpp#L511 this can also be used to normalized in vectorized way that is more efficient than doing this in a loop. Use this before we get looping so we can just get float normalized_cost = normalized_costs(i);
You can even do the / cost_range too
| const float j_flt = static_cast<float>(j); | ||
| float blue_component = 1.0f - j_flt / shape_1; | ||
| float green_component = j_flt / shape_1; | ||
| // Use percentile-based normalization to handle outliers |
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.
Did you end up addressing this point? I see trajectory visualizations below that have collision ones as magenta
| if (publish_optimal_path_) { | ||
| optimal_path_pub_ = node->create_publisher<nav_msgs::msg::Path>("~/optimal_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.
Yes, please leave this :-)
| publish_optimal_trajectory: true | ||
| regenerate_noises: true | ||
| TrajectoryVisualizer: | ||
| Visualization: |
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.
What happened to visualize? Also why change the namespace from TrajectoryVisualizer for these? I don't want to make more changes than strictly required, it makes the migration path for users harder if there's no tangible benefit. The namespace here seems like an unnecessary change
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.
What happened to visualize?
I replaced it with more granular configurations because some topics e.g. candidate_trajectories are much heavier than others and for my use case I'd like to have the optimal_path always published and rosbag-recorded, even in production, but not the candidate trajectories.
Alternatively we could have the catch-all visualize parameter and for those who would like to have a subset of visualizations activated in production, visualize would be true but only the visualizations with an active subscription would be created and published. But that's a little more... risky
What strategy would you follow?
Also why change the namespace from TrajectoryVisualizer
Since it now includes params not directly related to the candidate trajectories, e.g. publish_transformed_path, I thought I'd rename it to something more general but if it creates unnecessary migration effort for everyone, I can revert to TrajectoryVisualizer
| */ | ||
| const std::vector<std::pair<std::string, Eigen::ArrayXf>> & getCriticCosts() const | ||
| { | ||
| if (critics_data_.individual_critics_cost) { |
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.
When would this not be the case?
| const models::Trajectories & trajectories, | ||
| const Eigen::ArrayXf & total_costs, | ||
| const std::vector<std::pair<std::string, Eigen::ArrayXf>> & individual_critics_cost = {}, | ||
| const builtin_interfaces::msg::Time & cmd_stamp = builtin_interfaces::msg::Time()); |
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.
There should be no default value for time, that should be real at all times (har-de-har-har)
| threshold_to_consider_, | ||
| "threshold_to_consider", 0.5f); | ||
| getParam(use_path_orientations_, "use_path_orientations", false); | ||
| getParam(visualize_furthest_point_, "visualize_furthest_point", false); |
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.
If we have a catch all "debug_visualizations" can this just be part of that instead of introducing new parameters for each critic?
Or, can each critic simply have a "visualize" setting so its global for any visualizations that a given critic might have rather than enabling each individually (should there be later > 1)?
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.
Here I can propose to simplify things by publishing the pose at data.furthest_reached_path_point in the trajectory_visualizer. The upside is simplification in code and parameters, the downside is that it's less accurate because it doesn't reflect exactly the pose used in each critic because it's slightly changed, e.g. in PathAngle there is offset_from_furthest_. But I can personally live with that
| * @param ns Namespace for the markers | ||
| * @param cmd_stamp Timestamp for the markers | ||
| */ | ||
| void createTrajectoryMarkers( |
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.
Can't these be free utils functions like the others before? I don't think these require class members and make them more easily unit testable
| } | ||
| } | ||
|
|
||
| void TrajectoryVisualizer::add( |
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 we have some major unused functions now if we're adding this / other createXYZ methods




Basic Info
Description of contribution in a few bullet points
Total Cost


CostCritic

PathFollowCritic

furthest_reached_path_pointto the Path critics (this revealed a bug which I will fix in another PR)Description of documentation updates required from your changes
Description of how this change was tested
Future work that may be required in bullet points
For Maintainers:
backport-*.