ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I'm not sure whether they're recommended, but I've seen two approaches:

  1. use an external node which monitors your robot (make your hardware_interface publish some sort of robot state which includes whether it's errored or not) and then have the external node call the switch_controllers service of the controller_manager. An example of this approach would be Universal_Robots_ROS_Driver (overview in readme, controller_stopper node).
  2. as part of your hardware_interface, check the state of your robot, and whenever you encounter an error, use ControllerManager::getControllerByName(..) to retrieve all controllers you'd like/need to stop, and when any of them isRunning(), call stopRequest(..).

Both approaches result in the same thing: a set of controllers, preconfigured by you (or your user), will be stopped upon the occurence/detection of an error (either in the remote system, or your own hardware_interface).

an interface in controller_manager to stop the controllers without having to call the switch_controllers service which seems messy

It is, but on the other hand, you do use the interfaces as they were intended to be used.

At least the first approach removes the responsiblity of managing controller runtime state from the hardware_interface, and places it in a separate node. That seems cleaner than embedding the logic in it (at the very least the separate node allows to relatively easily change the policy).

I'm not sure whether they're recommended, but I've seen two approaches:

  1. use an external node which monitors your robot (make your hardware_interface publish some sort of robot state which includes whether it's errored or not) and then have the external node call the switch_controllers service of the controller_manager. An example of this approach would be Universal_Robots_ROS_Driver (overview in readme, controller_stopper node).
  2. as part of your hardware_interface, check the state of your robot, and whenever you encounter an error, use ControllerManager::getControllerByName(..) to retrieve all controllers you'd like/need to stop, and when any of them isRunning(), call stopRequest(..).. I've seen this approach used in a proprietary component, so I can't link you to it.

Both approaches result in the same thing: a set of controllers, preconfigured by you (or your user), will be stopped upon the occurence/detection of an error (either in the remote system, or your own hardware_interface).

an interface in controller_manager to stop the controllers without having to call the switch_controllers service which seems messy

It is, but on the other hand, you do use the interfaces as they were intended to be used.

At least the first approach removes the responsiblity of managing controller runtime state from the hardware_interface, and places it in a separate node. That seems cleaner than embedding the logic in it (at the very least the separate node allows to relatively easily change the policy).

I'm not sure whether they're recommended, but I've seen two approaches:

  1. use an external node which monitors your robot (make your hardware_interface publish some sort of robot state which includes whether it's errored or not) and then have the external node call the switch_controllers service of the controller_manager. An example of this approach would be Universal_Robots_ROS_Driver (overview in readme, controller_stopper node).
  2. as part of your hardware_interface, check the state of your robot, and whenever you encounter an error, use ControllerManager::getControllerByName(..) to retrieve all controllers you'd like/need to stop, and when any of them isRunning(), call stopRequest(..). I've seen this approach used in a proprietary component, so I can't link you to it.

Both approaches result in the same thing: a set of controllers, preconfigured by you (or your user), will be stopped upon the occurence/detection of an error (either in the remote system, or your own hardware_interface).

an interface in controller_manager to stop the controllers without having to call the switch_controllers service which seems messy

It is, but on the other hand, you do use the interfaces as they were intended to be used.

At least the first approach removes the responsiblity of managing controller runtime state from the hardware_interface, and places it in a separate node. That seems cleaner than embedding the logic in it (at the very least the separate node allows to relatively easily change the policy).


Edit:

As you say, the controllers are not the responsibility of the hardware interface, they were owned by whatever client is using the controllers,

If you understood it that way, that's not what I meant to say.

I agree the controllers are not the responsibility of the hardware_interface, but I don't agree they are owned by the "client". They are managed by the controller_manager, which in the end is owned by the node which wraps the entire hardware_interface.

thus the client should decide when to stop controllers when things go wrong, which is closer in concept to option 1.

It would be a different client, but yes: keeping that separate from the hardware_interface itself seems like an OK idea to me.

I think a good compromise would be a dynamic resource based approach where the joint resources could be made unavailable at any time by the hardware interface (e.g. position interfaces made unavailable, but joint states still available when the arm goes into disabled mode), and controllers can react accordingly by cancelling actions and refusing to start new ones until their resources are returned.

I would have to reason about it a bit more, but I'm not sure I like the idea of removing command handles upon error. Semantically, it would seem like it "gives the wrong message": it's not the command facilities of your robot suddenly don't exist any more, it's the state of those resources has changed (ie: command handles can't actually command the joint they represent).

Seeing as this is a state-based limitation, using a state-machine to keep track of this and then stop (and reset) controllers based on the state of the hardware_interface doesn't seem like a bad thing.

A related discussion on the ros_controllers issue tracker: ros-controls/ros_controllers#429.