# Switching between controllers with ros_control / controller_manager

Is there an easy way to switch between different controllers for a single resource? I would like to control a joint of my Gazebo model either by effort_controllers/JointPositionController or effort_controllers/JointEffortController. I want to switch between these controllers during runtime by pressing a joystick button.

Right now, I make 4 service calls:

1. Stop the current controller (by calling controller_manager/switch_controller)
2. Unload the current controller (by calling controller_manager/unload_controller)
3. Load the new controller (by calling controller_manager/load_controller)
4. Start the new controller (by calling controller_manager/switch_controller again)

Is there an easier way to do that, like loading both controllers at the same time and only start/stop the corresponding controllers by a single switch_controller call? As the SwitchController Service has parameters for both start_controllers and stop_controllers, this seems to be supported somehow. But if I try to spawn both controllers in a launch file, I get a "resource conflict" error.

edit retag close merge delete

Sort by » oldest newest most voted

I finally found a way to simplify my approach. If you pass --stopped as an argument to the spawner, you can load a controller without starting it. So I ended up spawning the position controller as usual and the effort controller with the --stopped argument. Now I can switch from one controller to the other by just calling the switch_controller service.

I needed to add the following two lines to my launch file:


<node name="controller_spawner" pkg="controller_manager" type="spawner" respawn="false" ns="/mybot" args="flipper_position_controller"/>

<node name="controller_spawner_stopped" pkg="controller_manager" type="spawner" respawn="false" ns="/mybot" args="--stopped flipper_effort_controller"/>


The code to switch from position controller to effort controller looks like that:


from controller_manager_msgs.srv import SwitchController
...
rospy.wait_for_service('/mybot/controller_manager/switch_controller')
try:
switch_controller = rospy.ServiceProxy(
'/mybot/controller_manager/switch_controller', SwitchController)
ret = switch_controller(['flipper_effort_controller'],
['flipper_position_controller'], 2)
except rospy.ServiceException, e:
print "Service call failed: %s"%e


more

It is still through service call. And I tried cm.unload() function, but return 0(failed) always.

( 2018-09-29 21:02:27 -0500 )edit