Expand the controller tutorial to include ros_control and fake_controllers
The current tutorial on using controllers with moveit does not mention how to integrate with ros_control or the fake controllers. We need to consolidate the READMEs from:
https://github.com/ros-planning/moveit/tree/kinetic-devel/moveit_plugins/moveit_ros_control_interface https://github.com/ros-planning/moveit/tree/kinetic-devel/moveit_plugins/moveit_fake_controller_manager
And update the README.mds to instead point at the moveit_tutorials
@davetcoleman The pull request of @simonGoldstein already significantly improved the documentation on the controller manager plugins.
I, however, think there are still some things there are not documented.
- The
moveit_ros_control_interfacedoes not appear to use thecontroller_listparameter (also see my discussion with @rhaschke here and here). - The
moveit_ros_control_interfacedoes not yet work withGripperCommandservices. - For the
moveit_ros_control_interfaceto work it needs to find a controller manager on the/root namespace. If the controller manager is not on this namespace themoveit_ros_control_interfaceparameter can be used to point it to the controller manager. - Only the
moveit_simple_controller_managerandmoveit_fake_controller_manageruse thecontroller_listparameter.
Below you will find a more detailed explanation of how I think these three controller manager plugins work. Would you please correct me if I misunderstood something?
moveit_ros_control_interface
When a controller manager is found in the root namespace, MoveIt can automatically find the trajectory controllers it should use (see this code). When no controller manager is found, it throws the following error:
[/panda/move_group] [ WARN] [WallTime: 1635408493.753962593, 23.776000000]: Failed to read controllers from /controller_manager/list_controllers
[/panda/move_group] [ERROR] [WallTime: 1635408493.753997938, 23.776000000]: Unable to identify any set of controllers that can actuate the specified joints: [ panda_joint1 panda_joint2 panda_joint3 panda_joint4 panda_joint5 panda_joint6 panda_joint7 ]
[/panda/move_group] [ERROR] [WallTime: 1635408493.754017065, 23.776000000]: Known controllers and their joints:
[/panda/move_group] [ERROR] [WallTime: 1635408493.754036758, 23.776000000]: Apparently trajectory initialization failed
This can be solved by using the moveit_ros_control_interface parameter. This parameter points MoveIt to the controller manager, after which it can automatically find Trajectory controllers. It does not automatically find or work with any GripperCommand services.
Further, the controller_list parameter seems to be ignored by the moveit_ros_control_interface in both cases.
moveit_simple_controller_manager and moveit_fake_controller_manager
The moveit_simple_controller_manager and moveit_fake_controller_manager on the other hand do not automatically find the robot controller configuration. For these controller managers you need to set the controller_list parameter. The logic for this is implemented here and here.
This is correct. Note that the ros_control MoveIt controller manager is not intended to support the GripperCommand action.
@rickstaa
You can control the namespace of moveit_ros_control_interface through the ros_control_namespace parameter.
I like to mention this parameter in the ros_control_moveit_controller_manager.launch.xml file:
<param name="ros_control_namespace" value="your_robot" />
@leander-dsouza Your right, that is another way to make MoveIt aware of the controller manager. Could also be added to the documentation.
@rhaschke @rickstaa
Why doesn't the moveit_ros_control_interface support the GripperCommand action?
@leander-dsouza I think the quick answer is that nobody has yet added the [gripper_controller_handle](https://github.com/ros-planning/moveit/blob/kinetic-devel/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/gripper_controller_handle.to the moveit_ros_control_interface. I am simply a user of these controller managers and not a contributor, so there might be other reasons related to the differences between these two controller managers, of which I'm not aware.
This is correct. Note that the ros_control MoveIt controller manager is not intended to support the GripperCommand action.
@rhaschke would this be something you would like a PR for, or is GripperCommand controller meant to be a testing utility that should not be used on a real robot/in production?
@01binary, the GripperCommand controller is only supported by MoveIt's SimpleControllerManager, not the ROSControlControllerManager. It is definitely intended for production use. You are welcome to extend the documentation.
@rhaschke could you help me unravel the confusion around gripper action controller?
New MoveIt project created by MSA is setup as follows:
-
demo.launch(Launch in RViz visualization only): uses Fake Controller Manager -
demo_gazebo.launch(Launch Gazebo simulation and RViz visualization): uses ROS Control Controller Manager -
gazebo.launch(Launch Gazebo simulation only): uses ROS Control Controller Manager -
move_group.launch(No visualization, no simulation): uses Simple Controller Manager by default
If I am a new MoveIt user setting up MoveIt for my own robot, my entry point into the documentation is Integration with a New Robot section.
I read about MSA, then URDF/SRDF, and then I land on Low-Level Controllers page.
This has me setup a joint trajectory controller for the arm, and a gripper controller for the gripper.
Next it tells me to launch with Simple MoveIt Controller Manager. This example cannot actually be followed because it ends with "Now, you should be ready to have MoveIt talk to your robot." and there are no instructions on how to use a custom launch file it has you create. Let's assume you somehow figure it out and get it running.
Then the tutorial tells you:
For most use cases, the included MoveItSimpleControllerManager is sufficient if your robot controllers already provide ROS actions for FollowJointTrajectory. If you use ros_control, the included MoveItRosControlInterface is also ideal.
If my robot works with Joint Trajectory Controller from ROS Controls I stop there. If I have a custom ROS Controller then this is telling me to switch to ROS Control Controller Manager.
So I switch to ROS Control Controller Manager, and my gripper stops working. It has a Controller Handle, but no Controller Handle Allocator. At this point I am confused - why can't I use the gripper? As a new user, I did everything correctly. So then I have to write and export a Controller Handle Allocator for it as part of my own project, or go back to using MoveIt Simple Controller Manager.
Does this flow make sense to you? Maybe you can spot where the disconnect happens?
If you need to use GripperCommand you must use the SimpleControllerManager.
Any ROS controller supporting the FollowTrajectory action API, works with the SimpleControllerManager as well.
If you have a ROS controller, which does not support that action, you are lost anyway, because both SimpleControllerManager and ROSControlControllerManager require that action.
So, my suggestion is: Use SimpleControllerManager and augment your ros_control controller with a FollowTrajectory action if needed.
If you were to describe why Gripper Action Controller exists, would you say it's for "simple usage scenarios"? As in, it lets you setup a new robot in the fastest and easiest way possible (and you would be using Simple Controller Manager).
People who use ROS Control Controller Manager are likely to have their own setup for grippers (or already use Joint Trajectory Controller), so it's just not the sort of audience who would care to use Gripper Action Controller?
Your last few responses had more to do with the "how", I am actually more interested in the "why".
The GripperCommand action is fundamentally different from the FollowJointTrajectory action: While the latter allows precise following of a joint trajectory, the GripperCommand action just commands the gripper to close or open, but doesn't specify a precise trajectory to do so (but rather a maximal force).
So there are conceptual reasons, why we have two different action types.
I see what you mean
// goal to be sent
control_msgs::GripperCommandGoal goal;
goal.command.position = 0.0;
// send last point
int tpoint = trajectory.joint_trajectory.points.size() - 1;
ROS_DEBUG_NAMED("GripperController", "Sending command from trajectory point %d", tpoint);