-
Notifications
You must be signed in to change notification settings - Fork 155
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
WIP: Alternatives and fallback planners #451
base: ros2
Are you sure you want to change the base?
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## ros2 #451 +/- ##
==========================================
- Coverage 41.80% 41.25% -0.54%
==========================================
Files 78 80 +2
Lines 7846 7952 +106
==========================================
+ Hits 3279 3280 +1
- Misses 4567 4672 +105
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report in Codecov by Sentry. |
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.
Do you plan to have these planners in ROS1 as well? If so, I suggest implementing them there first.
(Our standard development branch is master / ROS1 in this repo and we forward-port changes to ROS2 via merge commits.)
I don't yet like the code redundancy of the two plan()
functions for the AlternativesPlanner. I think this calls for a template.
Which problems did you face when defining a stopping criterion for AlternativesPlanner?
I guess it's difficult to stop other planning threads? How did you solve that with ParallelPlanning?
StoppingCriterionFunction stopping_criterion_function_ = | ||
[](const robot_trajectory::RobotTrajectoryPtr& result, | ||
const moveit_msgs::msg::Constraints& /*path_constraints*/) { |
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 suggest implementing this default as a reusable standalone function.
remaining_time -= std::chrono::duration<double>(now - start_time).count(); | ||
start_time = now; | ||
} | ||
return 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.
This return false;
needs to be outside the for loop.
if (stopping_criterion_function_(result, path_constraints)) { | ||
return true; | ||
} |
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.
In this repo, we usually omit parentheses for one-line statements like here.
if (stopping_criterion_function_(result, path_constraints)) { | |
return true; | |
} | |
if (stopping_criterion_function_(result, path_constraints)) | |
return true; |
const moveit::core::JointModelGroup* jmg, double timeout, | ||
robot_trajectory::RobotTrajectoryPtr& result, | ||
const moveit_msgs::msg::Constraints& path_constraints) { | ||
moveit::planning_pipeline_interfaces::PlanResponsesContainer plan_responses_container{ this->size() }; |
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 do you want to use a PlanResponsesContainer
instead of a simple vector of solutions?
|
||
std::vector<::planning_interface::MotionPlanResponse> solutions; | ||
solutions.reserve(1); | ||
solutions.push_back(solution_selection_function_(plan_responses_container.getSolutions())); |
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.
MTC has a solution-selection inbuilt already: solutions have costs and the best solution (least costs) is selected.
There is no need to reinvent the wheel.
solutions.reserve(1); | ||
solutions.push_back(solution_selection_function_(plan_responses_container.getSolutions())); | ||
|
||
if (solutions.empty()) { |
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.
Solutions cannot be empty in your implementation. I don't see the need for a solutions
vector...
I don't agree. Why would it be beneficial to have parallel planning implemented in PipelinePlanner too, when we already have |
@rhaschke Sorry for my late response.
I don't have the capacity at the moment to implement this in ROS 1, since I am working most of the time with ROS 2.
For parallel planning within MoveIt 2 I used the member function Additionally, I am running into a segfault when I am using the AlternativesPlanner planner. So I am assuming the solvers are not thread safe at the moment. I haven't taken the time to dig more into this |
While both interfaces enable parallel planning, they are doing it on different hierachy levels. The Alternative Solver enables using multiple MTC solvers in parallel and the pipeline planner (as a single MTC solver) uses MoveIt's planning interface to use one or multiple planning pipelines. Having a parallel planning interface in MoveIt is useful for using the feature independent of MTC e.g. with moveit_cpp or hybrid planning. |
I exactly want to avoid a redundant implementation at two different levels of hierarchy, which are then prone to diverge in implementation and features. Modularity stems from simple building blocks, which can be nicely combined with each other. I'm not sure how parallel planning pipelines are configured in MoveItCpp: Do you dynamically pick several pipeline configs or do you need to define those statically in advance? In the former case, I don't see any limitation in using the AlternativesPlanner. |
The pipelines are created and initialized in advance & when you run plan() you decide which subset you'd like to use.
I don't see how this can be avoided for example because |
Maybe this would be a good discussion to have in the Maintainer meeting 🤔 |
@rhaschke I'd still like to see #450 merged. I think enabling the pipeline-level parallel planning feature is useful for MTC users.
Pushing the solver interface down to MoveIt would resolve the issues with redundant implementations while keeping the feature available in both, MoveIt and MTC. Do you have time this week for a video call to discuss how we can move forward? |
There are no temporary solutions in MoveIt (those are called feature branches). In contrast to Robert I would encourage #450 over #451.
The MTC solver interface is very limited in that you cannot pass arbitrary goal constraints, not even multiple poses for different links. It suffices for what we modeled in MTC so far, but I believe it is definitely too limited to describe general MoveIt interface. |
I agree. The MTC solver interface is very much tailored toward MTC's needs. I will think about #450 again, now having Michael's opinion on it. |
😅
Ok, that makes sense. I am imagining this interface to provide the same functionality as the solver interface does: The capability to use a solver (Joint or Cartesian Interpolation) or a planner (more specifically: A planning pipeline) for a given MotionPlanRequest but more generalized as the MTC solver interface. Within MTC this new MoveIt interface replaces the solver interface. @henningkayser Is this understanding of your idea correct and can you elaborate a bit more on the idea and maybe how it should look like? |
Yes, my idea was more along the lines of reducing the number of planning interfaces that we have across MoveIt and MTC while also filling the gap in combining the different solvers that MoveIt has (as in, MoveIt doesn't provide a common interface for Cartesian interpolation, planners, joint interpolation). MTC's interface already provides this in a limited way, so I would very much be in favor of a single solver interface that is part of MoveIt, but is also used by MTC. (I don't think that's feasible without a significant amount of extra work, though). About parallel planning: I think Cartesian interpolation is not thread-safe by default because of the IK solver (I think kdl and bio_ik are both not thread-safe, pick_ik should be). Until there is a way to enforce thread-safety, we shouldn't enable parallel planning for this type of solver. To me, MTC's stages and containers are sufficient for now. I would advocate for merging #450 since the MoveIt-internal version is a feature that already exists and that is under active development. I agree that there is a certain conceptual overlap between MTC's container types and this feature, however MTC's approach does not suffice configuring and optimizing specific planner setups. And that's the whole point of this feature, allowing to experiment with and optimizing groups of planners and configurations that can be used as a default in MoveIt and in MTC, without having to implement new boilerplate code around that. It is not problem-specific, it is a tool for switching to say OMPL+STOMP+PILZ for all planning requests in an application instead of only solving with RRTConnect. That's where I see the advantage of enabling MoveIt's version for MTC. |
Depends on moveit/moveit2#2043 (Merged but not released 04/05/23)
Implement planners proposed by @rhaschke here
FallbackPlanner is a renamed version of the already existing MultiPlanner ported to ROS2 with the extensions, that it is now possible to pass a stopping criterion to the planner.
AlternativesPlanner is an implementation of the parallel planning interface in Moveit but on an MTC solver level so it is possible to run multiple solvers in parallel and select a solution. I did not find an easy way to add a stopping criteria here, so each parallel solver uses it's complete timeout for the moment.
This PR does not invalidate #450 because that is a refactoring of solely the PipelinePlanner to support MoveIt2's parallel planning feature.