You're reading the documentation for a development version. For the latest released version, please have a look at Iron.


This GitHub Repository provides templates for the development of ros2_control-enabled robots and simple simulations to demonstrate and prove ros2_control concepts.

If you want to have a rather step by step manual how to do things with ros2_control checkout ros-control/roscon2022_workshop repository.

What you can find in this repository

This repository demonstrates the following ros2_control concepts:

  • Creating a HardwareInterface for a System, Sensor, and Actuator.

  • Creating a robot description in the form of URDF files.

  • Loading the configuration and starting a robot using launch files.

  • Control of a differential mobile base DiffBot.

  • Control of two joints of RRBot.

  • Control of a 6-degrees-of-freedom robot.

  • Implementing a controller switching strategy for a robot.

  • Using joint limits and transmission concepts in ros2_control.


The repository has two other goals:

  1. Implements the example configuration described in the ros-controls/roadmap repository file components_architecture_and_urdf_examples.

  2. The repository is a validation environment for ros2_control concepts, which can only be tested during run-time (e.g., execution of controllers by the controller manager, communication between robot hardware and controllers).

Examples Overview

Example 1: RRBot

RRBot - or ‘’Revolute-Revolute Manipulator Robot’’ - a simple position controlled robot with one hardware interface. This example also demonstrates the switching between different controllers.

Example 2: DiffBot

DiffBot, or ‘’Differential Mobile Robot’’, is a simple mobile base with differential drive. The robot is basically a box moving according to differential drive kinematics.

Example 3: “RRBot with multiple interfaces”

RRBot with multiple interfaces.

Example 4: “Industrial robot with integrated sensor”

RRBot with an integrated sensor.

Example 5: “Industrial robot with externally connected sensor”

RRBot with an externally connected sensor.

Example 6: “Modular robot with separate communication to each actuator”

The example shows how to implement robot hardware with separate communication to each actuator.

Example 7: “6-DOF robot”

A full tutorial for a 6 DOF robot for intermediate ROS 2 users.

Example 8: “Using transmissions”

RRBot with an exposed transmission interface.

Example 9: “Gazebo Classic”

Demonstrates how to switch between simulation and hardware.

Example 10: “GPIO interfaces”

Industrial robot with GPIO interfaces

Example 11: “CarlikeBot”

CarlikeBot with a bicycle steering controller

Example 12: “Controller chaining”

The example shows a simple chainable controller and its integration to form a controller chain to control the joints of RRBot.

Example 13: “Multi-robot example (tba.)”

Example 14: “Modular robots with actuators not providing states and with additional sensors”


You can install the demos locally or use the provided docker file.

Local installation

If you have ROS 2 installed already, choose the right version of this documentation and branch of the ros2_control_demos repository matching you ROS 2 distribution, see this table.

Otherwise, install ROS 2 rolling on your computer.


ros2_control and ros2_controllers packages are released and can be installed using a package manager. We provide officially released and maintained debian packages, which can easily be installed via aptitude. However, there might be cases in which not-yet released demos or features are only available through a source build in your own workspace.

Build from debian packages

Download the ros2_control_demos repository and install its dependencies with

mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
git clone -b master
cd ~/ros2_ws/
rosdep update --rosdistro=$ROS_DISTRO
sudo apt-get update
sudo rosdep install --from-paths ./ -i -y --rosdistro ${ROS_DISTRO}

Now you can build the repository (source your ROS 2 installation first)

cd ~/ros2_ws/
. /opt/ros/${ROS_DISTRO}/
colcon build --merge-install

Build from source

  • Download all repositories

    mkdir -p ~/ros2_ws/src
    cd ~/ros2_ws/src
    git clone
    cd ~/ros2_ws/
    vcs import src < src/ros2_control_demos/ros2_control_demos.$ROS_DISTRO.repos
    rosdep update --rosdistro=$ROS_DISTRO
    sudo apt-get update
  • Install dependencies:

    rosdep install --from-paths src --ignore-src -r -y
  • Build everything, e.g. with:

    . /opt/ros/${ROS_DISTRO}/
    colcon build --symlink-install
  • Do not forget to source setup.bash from the install folder!

Using Docker

First, build the dockerfile with

mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
git clone
cd ros2_control_demos
docker build . -t ros2_control_demos -f Dockerfile/Dockerfile

To view the robot

Docker now allows us to run the demo without the GUI if configured properly. Now we can view the robot by the following procedure:

After having ROS 2 installed on your local system (not inside the docker), we can use rviz2 to visualize the robot state and joint_state_publisher_gui package to give manual joint values to the robot. To install the package you can run:

sudo apt-get install -y ros-${ROS_DISTRO}-joint-state-publisher-gui ros-${ROS_DISTRO}-rviz2

Then we are ready to bring up all the components to view the robot. Let’s start with the docker container by running the following command:

docker run -it --rm --name ros2_control_demos --net host ros2_control_demos ros2 launch ros2_control_demo_example_1 gui:=false


Depending on your machine settings, it might be possible that you have to omit --net host.

Now, we need to start rviz2 to view the robot as well as joint_state_publisher_gui, each in their own terminals after sourcing our ROS 2 installation.

Terminal 1:

source /opt/ros/${ROS_DISTRO}/setup.bash
ros2 run joint_state_publisher_gui joint_state_publisher_gui

Terminal 2:

source /opt/ros/${ROS_DISTRO}/setup.bash
cd ~/ros2_ws
rviz2 -d src/ros2_control_demos/example_1/description/rviz/rrbot.rviz

Now, you can see the robot moving by changing the values of the joints by moving the sliders around in the joint_state_publisher_gui.

To run the ros2_control demos

The following command runs the demo without the GUI:

docker run -it --rm --name ros2_control_demos --net host ros2_control_demos


Depending on your machine settings, it might be possible that you have to omit --net host.

Then on your local machine, you can run rviz2 with the config file specified:

cd ~/ros2_ws
source /opt/ros/${ROS_DISTRO}/
rviz2 -d src/ros2_control_demos/example_1/description/rviz/rrbot.rviz

You can also run other commands or launch files from the docker, e.g.

docker run -it --rm --name ros2_control_demos --net host ros2_control_demos ros2 launch ros2_control_demo_example_2

Quick Hints

These are some quick hints, especially for those coming from a ROS1 control background:

  • There are now three categories of hardware components: Sensor, Actuator, and System. Sensor is for individual sensors; Actuator is for individual actuators; System is for any combination of multiple sensors/actuators. You could think of a Sensor as read-only. All components are used as plugins and therefore exported using PLUGINLIB_EXPORT_CLASS macro.

  • ros(1)_control only allowed three hardware interface types: position, velocity, and effort. ros2_control allows you to create any interface type by defining a custom string. For example, you might define a position_in_degrees or a temperature interface. The most common (position, velocity, acceleration, effort) are already defined as constants in hardware_interface/types/hardware_interface_type_values.hpp.

  • Joint names in <ros2_control> tags in the URDF must be compatible with the controller’s configuration.

  • In ros2_control, all parameters for the driver are specified in the URDF. The ros2_control framework uses the <ros2_control> tag in the URDF.

  • Joint names in <ros2_control> tags in the URDF must be compatible with the controller’s configuration.