ros_control icon indicating copy to clipboard operation
ros_control copied to clipboard

New ideas on chaining controllers

Open mikepurvis opened this issue 8 years ago • 4 comments

There have been a number of interesting discussions here at various points about ros_control's non-support of chaining controllers— each controller is expected to expose a ROS API, and plug in to a hardware_interface joint API.

As far as an option to use chained/composed controllers, @jbohren did a small prototype here many moons ago, but it basically boils down the controller having its own controller manager, and its own separate "subcontroller" services. While certainly workable, this seems inelegant. Using the example of velocity_controllers::JointPositionController, the ideal setup from my perspective would be:

  • The existing velocity_controllers::JointPositionController remains as it is today— controls a velocity interface, takes position commands from a command topic.
  • A new velocity_controllers::JointPositionCompositeController (or whatever) is created, which controls a velocity interface, but upon init registers a new position interface on the RobotHW instance to which another position controller may be connected (which in turn exposes a ROS API).

I think the main barrier at present to this is the additional bookkeeping required to ensure that a) controllers chained off a controller being unloaded get themselves unloaded (or the switch_controllers service simply refuses to disable X without disabling Y), and b) controller update methods are called in the correct order to avoid injecting a control period worth of delay between executions. This requires tracking any hardware interfaces which are being provided by controllers. It may not ever be necessary to "sort" the list, though— it should always be possible to update the controllers in the order that they are loaded, so some of the burden may be moved onto the user defining the configuration.

Anyhow, I'm interested to play with a toy implementation of this, but curious to hear thoughts or objections from others who have been thinking about the problem for longer, particularly given recent developments like MultiControllerInterface and combined_robot_hw.

mikepurvis avatar Nov 14 '17 16:11 mikepurvis

This is something the @adolfo-rt and many others had in mind for the next version of ros_control, perhaps enabled by ROS2. I think while with ROS2's communication this could be a given, inter-controller interfaces are still a more efficient way of doing it + it can work with ROS1.

Off the top of my head:

  • Controllers could change in-out interfaces
  • Controller interface mode could be changed online via the controller_manager
  • controller_manager would still provide reasonable checks & safe operation
  • For deployed robots we should support a static setup where a special spawner reads a yaml file and sets up a configuration accordingly.
  • ROS interfaces should still be implemented in code but the switching mechanism & inter-controller interfaces should be injected via inheritance so we minimize the new interface creeping into existing code.

bmagyar avatar Nov 20 '17 17:11 bmagyar

Forgot to add that it may be useful to have a look at robot_controllers although I haven't personally checked out if/how they allow stacking controllers, they claim they do.

bmagyar avatar Nov 23 '17 14:11 bmagyar

Hi guys,

we did some steps in this direction, but solutions are pretty dirty. We are mostly inheriting controllers and tweaking RobotHW to enable different controller structures.

I have one issue which I think is related to this discussion (if not please correct me). Issue we often have is to create "normal" control structure build of sensor --> controller --> actor (robot). E.g. we have FTS independent from the robot and using robot as actor. In this case input data in controller are wrenches and output are velocities or positions of the robot. Current solution is to extend RobotHW with FTS Hardware interface to enable this, nevertheless this is not elegant (and not correct?). Using combined_robot_hw and wrapping FTS to RobotHW is also not really a solution. Current idea is to create SensorRobotHW similar to combined_robot_hw but accepting any HardwareInterface for Sensor. We will than see what is missing... If you have any toughs we will be grateful.

destogl avatar Dec 05 '17 07:12 destogl

Another interesting angle might be exposing multiple handles of different types for a single joint. So, for example, register the usual VelocityJointInterface for your wheel, but also a EffortJointInterface. Let the EffortJointInterface be what commands the hardware, and load two controllers:

  • DiffDriveController to expose a ROS interface and command velocities.
  • A VelocityEffortController to observe the wheel state and commanded velocity, and command efforts to the hardware.

This is limited in that it only allows chaining of basic PID behaviours, and as written it requires the control structure to be explicitly set (or at least supported) by the hardware. So it's not a perfectly general solution, but it's possible the need for specific hardware support could be relaxed by adding some additional cleverness in the framework. For example, if you attempt to grab a named joint from the "wrong" interface type, it will create the intermediate interface, but not consider that a startable controller configuration unless it includes the secondary controller needed to bridge the gap.

mikepurvis avatar Feb 10 '18 02:02 mikepurvis