-
Notifications
You must be signed in to change notification settings - Fork 490
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
Add hybrid planning feature #488
Conversation
Codecov Report
@@ Coverage Diff @@
## main #488 +/- ##
==========================================
+ Coverage 54.17% 54.48% +0.32%
==========================================
Files 192 192
Lines 20182 20448 +266
==========================================
+ Hits 10931 11139 +208
- Misses 9251 9309 +58
Continue to review full report at Codecov.
|
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.
Went through mostly the local planner stuff, but skimmed the manager and global as well.
This looks great! Very clean, and I think the plugin architecture will allow a lot of flexibility
Implementation of MoveIt 2's new hybrid planning architecture. You find more information in the project's issues[#300](https://github.com/ros-planning/moveit2/issues/300), [#433](https://github.com/ros-planning/moveit2/issues/433) and on the [MoveIt 2 roadmap](https://moveit.ros.org/documentation/contributing/roadmap/). | ||
|
||
## Getting started | ||
1. Build moveit2 from source and make sure you use [this fork](https://github.com/sjahr/moveit_msgs) of moveit_msgs for the hybrid planning specific action definitions |
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.
Don't forget to change this when the msgs PR is merged
timer_ = this->create_wall_timer(1ms, [this]() { | ||
if (initialized_) | ||
{ | ||
timer_->cancel(); |
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 know we talked about initializing this way with a timer. My understanding is right now this is the easiest way to access ROS node capabilities during initialization if this class inherits from rclcpp::Node
, and that this will not be necessary with future lifecycle node work.
Maybe we should leave a TODO in all these initialization timers for after the lifecycle thing is sorted out?
{ | ||
auto& clock = *hybrid_planning_manager_->get_clock(); | ||
RCLCPP_INFO_THROTTLE(LOGGER, clock, 1000, event.c_str()); | ||
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.
Is this really desired behavior here? Looks like debugging, maybe it should give a warning that the SinglePlanExecute
plugin doesn't handle string feedback?
|
||
bool ForwardTrajectory::reset() | ||
{ | ||
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.
Just want to make sure it does not need to do anything on reset()
, and not that this got overlooked
* @param new_trajectory New reference trajectory segment to add | ||
* @return True if segment was successfully added | ||
*/ | ||
virtual bool addTrajectorySegment(const robot_trajectory::RobotTrajectory& new_trajectory) = 0; |
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 this function should include feedback (moveit_msgs::action::LocalPlanner::Feedback
), perhaps as the return instead of a bool
if (pass_through_) | ||
{ | ||
// Use reference_trajectory as local trajectory | ||
local_trajectory.swap(*reference_trajectory_); |
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 I set the pass_through
parameter true
in the config file, I get a segfault, I believe at this line
@@ -0,0 +1 @@ | |||
planner_logic_plugin_name: "moveit_hybrid_planning/ReplanInvalidatedTrajectory" |
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 it possible to combine all these config files into 1 file? Do we even want to?
load_controllers = [] | ||
for controller in [ | ||
"joint_state_controller", | ||
"panda_joint_group_position_controller", |
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 would move to using the panda_arm_controller
here as the default, because that is what the rest of the MoveIt tutorials and demos use
@@ -0,0 +1,28 @@ | |||
controller_manager: | |||
ros__parameters: | |||
update_rate: 500 # Hz |
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.
Changing this (to 100) has strange effects on the demo, which I cannot explain. Sometimes the robot moves a bit and then stops
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 an int type and not a floating point?
pass_through: false | ||
|
||
# ForwardTrajectory param | ||
stop_before_collision: 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.
I think this should be true
so the demonstration runs like the provided gif.
If this is false, the demo robot passes through the objects when I try it
global_planner/include | ||
hybrid_planning_manager/hybrid_planning_manager_component/include | ||
hybrid_planning_manager/planner_logic_plugins/include | ||
local_planner/local_planner_component/include | ||
local_planner/trajectory_operator_plugins/include | ||
local_planner/local_constraint_solver_plugins/include |
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.
global_planner/include | |
hybrid_planning_manager/hybrid_planning_manager_component/include | |
hybrid_planning_manager/planner_logic_plugins/include | |
local_planner/local_planner_component/include | |
local_planner/trajectory_operator_plugins/include | |
local_planner/local_constraint_solver_plugins/include | |
global_planner/include/ | |
hybrid_planning_manager/hybrid_planning_manager_component/include/ | |
hybrid_planning_manager/planner_logic_plugins/include/ | |
local_planner/local_planner_component/include/ | |
local_planner/trajectory_operator_plugins/include/ | |
local_planner/local_constraint_solver_plugins/include/ |
Without the trailing slash, these are installed at install/moveit_hybrid_planning/include/include/moveit/.....
(notice the extra include) and other packages cannot find them without adding an include in the path
2cd7a46
to
41eed5b
Compare
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'll do another pass after you address this round of reviews. Looks good! I'm excited to see it develop further.
...al_planner/global_planner_component/include/moveit/global_planner/global_planner_component.h
Outdated
Show resolved
Hide resolved
...al_planner/global_planner_component/include/moveit/global_planner/global_planner_interface.h
Outdated
Show resolved
Hide resolved
...ner/local_planner_component/include/moveit/local_planner/local_constraint_solver_interface.h
Outdated
Show resolved
Hide resolved
...planner/local_planner_component/include/moveit/local_planner/trajectory_operator_interface.h
Outdated
Show resolved
Hide resolved
...al_planner/global_planner_component/include/moveit/global_planner/global_planner_interface.h
Outdated
Show resolved
Hide resolved
...planning/hybrid_planning_manager/planner_logic_plugins/src/replan_invalidated_trajectory.cpp
Show resolved
Hide resolved
...planning/hybrid_planning_manager/planner_logic_plugins/src/replan_invalidated_trajectory.cpp
Show resolved
Hide resolved
...ros/hybrid_planning/global_planner/global_planner_component/src/global_planner_interface.cpp
Outdated
Show resolved
Hide resolved
* Add hybrid_planning architecture skeleton code * Add simple state machines to hybrid planning manager and local planner * Initial global planner prototype implementation * Forward joint_trajectory with local planner * Forward hybrid planning motion request to global planner * Abstract planner logic from hybrid planning manager by using a plugin * Implement single plan execution logic * Add test launch files, RViz and demo config * Add test for motion_planning_request
* Make local planner component generic * Add next_waypoint_sampler trajectory operator * Update hybrid planning test to include collision object * Clean up code and fix minor bugs. * Update local planner component parameter * Add local collision constraint solver * Update planning scene topic name and test node * Fix bugs and runtime errors in local planner component and it's plugins * Add collision object that invalidates global trajectory * Add simple "stop in front of collision object" demo * Add hybrid planning manager reaction to local planner feedback * Fix ament_lint_cmake * Ensure that local planner start command and collision event are send once * Add simple replanning logic plugin * Use current state as start state for global planner * Use RobotTrajectory instead of constraint vector describe local problem * Add PlanningSceneMonitorPtr to local solver plugin * Add local planner frequency parameter * Use PID controller to create control outputs for robot controller * Add hybrid_planning_manager config file * Add more complex test node * Update README * Reset index in next_waypoint_sampler * Use correct isPathValid() interface * Rename path_invalidation flag * Read planning scene instead of cloning it in local planner * Add TODO creator * Rename local constraint solver plugin * Use read-locked access to the planning scene for collision checking * Rename constraint_solver into local_constraint_solver * Add missing pointer initialization
* Export missing plugins * Use std::chrono_literals * Construct smart pointers with std::make_* instead of 'new' * Fixup const-ref in function signatures, reduce copies * Improve planning scene locking, robot state processing, controller logic
* Add forward_trajectory local solver plugin (#359) * Use ros2_control based joint simulation and remove unnecessary comment * Update copyrights * Restructure hybrid planning package * Fix formatting and add missing time stamp in local solver plugin * Remove unnecessary logging and param loading * Enable different interfaces between local planner and controller * Use JointGroupPositionController as demo hardware controller
* Add reset method for trajectory operator and local constraint sampler * Refactor next_waypoint_sampler into simple_sampler * Include collision checking to forward_trajectory and remove unneeded plugin * Fix formatting and plugin description * Update README and add missing planner logic plugin description
341db91
to
f9511e9
Compare
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 a first round of comments. Also, two things that should be addressed:
- Use include guards (i.e.
#pragma once
) for all headers - Consider using consistent prefixes/postfixes for plugin names. For instance
SimpleSampler
,SinglePlanExecution
does not really tell you what kind of plugin is or does. I'd suggest using postfixes like*PlannerLogic
,*TrajectoryOp
,GlobalPlanner
, etc...
...al_planner/global_planner_component/include/moveit/global_planner/global_planner_component.h
Show resolved
Hide resolved
...al_planner/global_planner_component/include/moveit/global_planner/global_planner_component.h
Show resolved
Hide resolved
std::unique_ptr<pluginlib::ClassLoader<moveit_hybrid_planning::GlobalPlannerInterface>> global_planner_plugin_loader_; | ||
|
||
// Global planner instance | ||
std::shared_ptr<moveit_hybrid_planning::GlobalPlannerInterface> global_planner_instance_; |
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.
Use std::unique_ptr
?
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.
A unique_ptr leads to an issue when creating the plugin here. I'm not quite sure how to fix this.
global_planner_instance_ = global_planner_plugin_loader_->createUniqueInstance(global_planner_name_);
The error:
error: no match for ‘operator=’ (operand types are ‘std::unique_ptr<moveit_hybrid_planning::GlobalPlannerInterface>’ and ‘pluginlib::UniquePtr<moveit_hybrid_planning::GlobalPlannerInterface>’ {aka ‘std::unique_ptr<moveit_hybrid_planning::GlobalPlannerInterface, std::function<void(moveit_hybrid_planning::GlobalPlannerInterface*)> >’})
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.
pluginlib has its own unique_ptr type which basically provides unique access to the single instance managed by the plugin loader. So you either need to use pluginlib::UniquePtr
or create an unmanaged plugin instance. Thinking about this more, I'm not sure if any of these versions is better than simply using shared_ptr, though. @tylerjw any thoughts?
last_global_solution_ = planning_solution; // TODO(sjahr) Add Service to expose this | ||
|
||
// Reset the global planner | ||
if (!global_planner_instance_->reset()) |
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 case even relevant? I think that resetting a planner should never fail. If possible, reset()
should even be noexcept
imo and we can remove this exception.
...obal_planner/global_planner_plugins/include/moveit/global_planner/moveit_planning_pipeline.h
Show resolved
Hide resolved
..._planning_manager_component/include/moveit/hybrid_planning_manager/hybrid_planning_manager.h
Show resolved
Hide resolved
std::unique_ptr<pluginlib::ClassLoader<moveit_hybrid_planning::PlannerLogicInterface>> planner_logic_plugin_loader_; | ||
|
||
// Planner logic instance to implement reactive behavior | ||
std::shared_ptr<moveit_hybrid_planning::PlannerLogicInterface> planner_logic_instance_; |
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.
unique_ptr?
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.
Same issue with plugin loading, discussed above
..._planning_manager_component/include/moveit/hybrid_planning_manager/planner_logic_interface.h
Show resolved
Hide resolved
* @param event Basic hybrid planning event | ||
* @return Reaction result that summarizes the outcome of the reaction | ||
*/ | ||
virtual ReactionResult react(const BasicHybridPlanningEvent& event) = 0; |
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.
not sure if react()
is a good function name here. Maybe use something like processEvent()
or similar
...planning/hybrid_planning_manager/planner_logic_plugins/src/replan_invalidated_trajectory.cpp
Show resolved
Hide resolved
@@ -8,7 +8,7 @@ on: | |||
pull_request: | |||
push: | |||
branches: | |||
- main |
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.
You don't need to change the branch here to trigger a CI run, you can do that just by pushing to your branch with an open PR.
By doing this you will cause CI to run twice for each time you push. Once for your push, and another because there was a push into a branch with a open PR.
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'll add a TODO to remove this. As I cannot directly push on the feature branch, I need to open PRs against it and from my understanding, without this change, these PRs wouldn't get checked by CI
|
||
HybridPlanningDemo demo(node); | ||
std::thread run_demo([&demo]() { | ||
rclcpp::sleep_for(5s); |
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 seems fairly fragile, have you tested this on slow machines?
The lack of unit tests to test the functionality inside the core classes of this is sad. Please consider adding unit tests to this to verify the logic in the core classes of this. |
I'm working on addressing the code reviews but I can't push to this branch. I'll probably just open a new PR like Tyler did already with #763 Overall, this still works with a few tweaks but bit rot is starting to set in. Would like to get it merged sooner rather than later. |
@AndyZe Thanks for taking this up! I've also addressed a couple of things today and reopened a PR to add those things to the feature branch to make them visible in this PR. Feel free to add your changes to PR #811 or incorporate them in your own PR |
Closing in favor of #811. I'll still track whether the comments get addressed here |
* Add detail on custom IK plugin param declaration. MoveIt Servo dispenses with the `automatically_declare_parameters_from_overrides` machinery discussed here: https://github.com/orgs/ros-planning/discussions/1486 However, unlike a kinematics plugin loaded by a `move_group` node, this seems to mean that the kinematics plugin code is responsible for declaring any custom parameters on `/servo_node` that it needs to load from a MoveIt Config's `kinematics.yaml` Maybe this is not the case for configs generated with `MoveItConfigsBuilder`, but it was my experience with the launch strategy used by https://github.com/UniversalRobots/Universal_Robots_ROS2_Driver/tree/main/ur_moveit_config * Typo on line number * Fix code tag formatting * getROSParam code tag * Whitespace cleanup Co-authored-by: AndyZe <andyz@utexas.edu>
Description
This PR adds the new hybrid planning architecture to MoveIt2. The related issues that document the development process are #300 and #433.
To run the demo's you simply need to build moveit2 from source and make sure you use sjahr/moveit_msgs's hybrid_planning branch until the message definitions get merged into ros_planning/moveit_msgs.
The current setup includes a demo to verify the architecture's correct behavior. To run it use the following command:
The expected behavior looks like this:
You can change the configuration of the hybrid planning architecture by switching the different plugins used by the architecture's main components in the associated config file.
Checklist