How to change your robot’s motion controller#
In order to change robot controllers, as for example to start whole body kinematic controller or gravity compensation controller, and stop position controllers, there are two available methods.
Use the ROS 2 service API with the controller manager services
Use the /change_controllers action
Controller manager services#
The controller_manager node is the main component managing lifecycle of controllers. In order to change controller through command line, a direct call to the controller manager service can be done. As an alternative, the ros2_control framework provides some commands support interacting with the controller manager.
There are four main services.
/controller_manager/list_controllers lists all the loaded controllers, and shows which of them are active and which of them are inactive.
The service can be called in the following way
ros2 service call /controller_manager/list_controllers controller_manager_msgs/srv/ListControllers
Or the following ros2_control
command can be used
ros2 control list_controllers
Caution
Please note that ROS 2 control does not permit two active controllers to utilize a shared resource
/controller_manager/load_controller loads a controller. The parameter file for the specific controller must be previously spawned within the controller manager node, otherwise the loading will fail.
The service can be called in the following way
ros2 service call /controller_manager/load_controller controller_manager_msgs/srv/LoadController
"name:'controller_name'"
Or the following ros2_control
command can be used
ros2 control load_controller controller_name
It returns true if the controller has been loaded correctly, and false otherwise.
After being loaded, the controller will result to be unconfigured.
The controller state can be optionally set during the loading (configured/inactive/active) using the following
ros2_control
command.
ros2 control load_controller controller_name --set-state active
Otherwise, it can be configured in a successive moment through the /controller_manager/configure_controller service, with the following call
ros2 service call /controller_manager/configure_controller controller_manager_msgs/srv/ConfigureController
"name: controller_name"
Or through the following ros2_control
command
ros2 control set_controller_state controller_name active
/controller_manager/switch_controller starts and/or stops a set of controllers. A controller should be active in order to be stopped. A controller must be loaded before start it.
The service can be called in the following way
ros2 service call /controller_manager/switch_controller controller_manager_msgs/srv/SwitchController
"{ activate_controllers: ["whole_body_kinematic_controller"],
deactivate_controllers:["head_controller", "arm_controller", "torso_controller"]}"
Or the following ros2_control
command can be used
ros2 switch_controllers --activate whole_body_kinematic_controller
--deactivate_controllers head_controller, arm_controller, torso_controller
It is recommended to start and stop the desired controllers in one service call.
In the case of the gravity compensation controller this is crucial, because once the controller is stopped, the current applied on the arm is zero so it falls down.
The service returns true if the switch has been successfully executed, false otherwise.
/controller_manager/unload_controller unloads a controller. The controller must be stopped before being unloaded.
The service can be called in the following way
ros2 service call /controller_manager/unload_controller controller_manager_msgs/srv/UnloadController
"name: controller_name"
Or through the following ros2_control
command
ros2 unload_controller controller_name
It returns true if the controller has been unloaded correctly, and false otherwise.
Once a controller has been unloaded, it will be necessary to load it again in order to restart it.
Change controllers action#
The /change_controllers action uses the ros2 service API of the controller manager, but allows the change of controllers in a simple and intuitive way with a single call. The user doesn’t need to know which controllers are active and which resources are being used at any time. The action automatically stops the active controllers that share resources with those who want to be loaded. The goal message has different components:
start_controllers
: a list containing the names of the controllers to be startedstop_controllers
: a list containing the names of the controllers to be stoppedswitch_controllers
: If true it stops and starts the controllers in a single switch service call. Otherwise, first it calls stop and then it calls start. By default this should be always True, specially when gravity compensation controller needs to be stopped.load
: If true it loads the controllers instart_controllers
.unload
: If true it unloads the requestedstop_controllers
. This doesn’t affect the controllers that are automatically stopped because they share resources with the controllers that are going to be started.configure
: If true it configures the controllers instart_controllers
. The parameter file of the requested controller must be previously uploaded in the controller manager node.
This action is also optimized to avoid issues with PAL controllers, as for example the whole body kinematic controller that needs to be unloaded and loaded every time.
In the following an example of how the goal message should be sent
ros2 action send_goal /change_controllers change_controllers_interfaces/action/Switch
"{start_controllers: [whole_body_kinematic_controller] ,
stop_controllers: [head_controller, arm_controller, torso_controller],
switch_controllers: true,
load: true,
unload: true,
configure: true}"
In the robot the server is automatically launched on the startup. To run it on simulation execute
ros2 run change_controllers change_controllers