-
Notifications
You must be signed in to change notification settings - Fork 532
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
Allowing users to load and change dynamically new optimization objective for OMPL's planners #1436
base: main
Are you sure you want to change the base?
Allowing users to load and change dynamically new optimization objective for OMPL's planners #1436
Conversation
Update the document accordingly the pull request #1436 (moveit/moveit2#1436)
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.
Great feature, I'm unsure about the concrete implementation.
@@ -350,8 +354,26 @@ void ompl_interface::ModelBasedPlanningContext::useConfig() | |||
} | |||
else | |||
{ | |||
objective = | |||
std::make_shared<ompl::base::PathLengthOptimizationObjective>(ompl_simple_setup_->getSpaceInformation()); | |||
pluginlib::ClassLoader<ompl_optimization_loader::OptimizationObjectiveLoader> poly_loader("moveit_core", "ompl_optimization_loader::OptimizationObjectiveLoader"); |
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 they address this issue in ROS2 or shouldn't you keep the ClassLoader
instance alive?
Technically the OptimizationObjectiveLoader
is correctly destroyed before the plugin, but I guess the usual assumption is that all the methods in the instantiated objective returned by getOptimizationObjective
live in the same shared object as the loader and technically pluginlib is allowed to dlclose
the object once the plugin is destroyed.
@@ -34,7 +34,7 @@ install(TARGETS moveit_ompl_interface moveit_ompl_planner_plugin | |||
INCLUDES DESTINATION include | |||
) | |||
ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET) | |||
ament_export_dependencies(moveit_core ompl) | |||
ament_export_dependencies(moveit_core ompl moveit_ros_planning) |
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.
moveit/planning_interface/
lives in moveit_core
, so there is no need for this new dependency.
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 my bad, the include in top of the file was false. See new commit
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 still don't see the need to depend on moveit_ros_planning
unless that dependency was missing here before your patch?
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.
For some reasons, the header inside moveit/ompl_interface
are not found unless we add moveit_ros_planning
to the export_dependendencies.
...nners/ompl/ompl_interface/include/moveit/ompl_interface/ompl_optimization_objective_loader.h
Show resolved
Hide resolved
try | ||
{ | ||
RCLCPP_DEBUG(LOGGER, "Using optimization objective : %s", optimizer.c_str()); | ||
std::shared_ptr<ompl_optimization_loader::OptimizationObjectiveLoader> obj = poly_loader.createSharedInstance(optimizer); |
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 believe this way the name for the objective you need to define in your config is
optimization_objective: your_package/YourObjectiveLoader
right? It would be nicer to leave the Loader
part out of the config name to keep them in line with the other objective names.
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 depend on how the user creates his plugin_description.xml because the name tag allows the user to define the name he wants to use to load and therefor he can give a name consistent with the other objective, without any Loader.
If he doesn't give any name, yes he has to give the fully qualified type to the optimization_objective
parameter. But because we have no choice to use a loader because of the parameter given to the constructor of the class OtpimizationObjective, I could not think to another solution.
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.
the name tag allows the user to define the name he wants to use to load
Indeed. I guess I assumed everyone always uses the same name for C++ class name and plugin name.
I guess it is ok to deviate from that norm here.
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #1436 +/- ##
==========================================
- Coverage 50.47% 50.46% -0.01%
==========================================
Files 387 387
Lines 31819 31840 +21
==========================================
+ Hits 16059 16066 +7
- Misses 15760 15774 +14
☔ View full report in Codecov by Sentry. |
It would really help to have an example for such a plugin in a tutorial because otherwise we have another undocumented feature with additional aspects to consider. I guess my main open question is #1436 (comment) Aside from that I'm wondering whether we could get around having to load the plugin for each planning request instead of once. |
We updated the ompl_interface tutorial in one of the commit here
I think we could add the
The objective was re-created at each request https://github.com/ros-planning/moveit2/blob/a2a8b48d990bc840820d7c608b8b502c00094c84/moveit_planners/ompl/ompl_interface/src/model_based_planning_context.cpp#L325-L354 Or Is it because loading the plugin takes time compared to instantiating a class normally? In that case we might have to store a shared instance somewhere in the context to be "re-used" later. |
I like the idea behind this PR a lot! I share @v4hn's concern, though, that creating an optimization objective for every planning request seems redundant. It sounds like @ejalaa12 is saying that this is, in fact, what is currently done for all the predefined optimization objectives (so this PR would behave no differently). Is that right? |
@mamoll yes exactly, the lines I've cited in my previous response shows that all the predefined objective are created at the moment of the request. |
I agree that the OptimizationObjectives are currently `new` created when they are needed. This is fine, we don't aim for an allocation-free pipeline here.
But `ClassLoader` invokes pluginlib which starts to read xml files from plugin definitions of downstream packages it can find in the workspace (possibly recursively crawling folder structures) to figure out which plugins are available and map the passed plugin to a library it can dlopen and map into memory for dynamic function calls. I guess I made my point. :-)
In practice that overhead is somewhat reduced because pluginlib is known to do some debatable caching (it avoids `dlclose`ing libraries and moves them [to a "graveyard"](https://github.com/ros/class_loader/blob/rolling/src/class_loader_core.cpp#L236-L244) instead for technical reasons), but that is definitely not part of the public API, so we should not rely on it.
|
One solution for this problem is the following:
That way, we minimize the amount of call to pluginlib. We can provide a PR for that if this is ok for you. |
I did not look through all the details the proposed solution requires, but it does sound like a good idea.
|
In fact, OptimizationObjectives has indeed need to be created each time a planning is requested because it needs the updated version of the SpaceInformation and the only way to give it to it is by instantiated again.
This method ensure that the call to PluginLib occurs only once at the creation of the planning context. One of the drawbacks is that it will not search for newly, during runtime, added plugin but this should not be a frequent case. |
This pull request is in conflict. Could you fix it @AntoineDevop? |
1 similar comment
This pull request is in conflict. Could you fix it @AntoineDevop? |
…he number of call to PluginLib
8426df7
to
52fa9b7
Compare
Update the document accordingly the pull request #1436 (moveit/moveit2#1436)
@mamoll @v4hn We also went ahead and rebased our PR on Thanks for reviewing it. |
@mamoll Any update on this PR ? I've just rebased the changes on |
@sjahr @henningkayser can you have a look at this? This seems relevant to our recent discussion. |
This pull request is in conflict. Could you fix it @AntoineDevop? |
This pull request is in conflict. Could you fix it @AntoineDevop? |
I created an issue about this. I'll try to get someone to review this and provide more feedback. I'm sorry it looks like this has gone without reviews since you last updated it. |
@tylerjw Hi, I can update this branch with what's necessary. I was waiting for a review and forgot about it ^^. |
These modification allow user to create new optimizer for OMPL and load it into MoveIt trough the parameter optimization_objective.
After creating his own custom optimizer, with a simple call to the macro defined in the new header, the user can load it in MoveIt.
Checklist