Open-source project
ros-controls/ros2_control_demos avatar
ros-controls/ros2_control_demos

ros2_control_demos: seventeen small robots, one ros2_control concept each

This repository aims at providing examples to illustrate ros2_control and ros2_controllers

869 stars321 forksPythonApache-2.0

At a glance

What is it?
ros2_control_demos is a set of example packages that isolate single ideas from the ros2_control framework, from switching controllers to multi-robot hardware lifecycle management. It is a teaching repository, and the README says its folder layout is not one you should copy into a real robot.
Who is it for?
ros2_control_demos fits an engineer who needs to understand one ros2_control mechanism at a time, in a form they can read end to end and run on the matching distribution branch. It does not fit a robot project, because the README explicitly warns against using this folder layout for real hardware, and it does not fit anyone without a ROS 2 distribution already installed.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One idea per example, spread over seventeen packages

The repository exists to illustrate the ros2_control framework and the ros2_controllers packages. The README describes it as simple implementations that demonstrate different concepts, and the content list confirms the approach: each entry isolates one capability rather than building a complete robot application.

The early examples are the conceptual core. Example 1 is RRBot, a simple position controlled robot with one hardware interface, and it also demonstrates switching between different controllers. Example 2 is DiffBot, a differential mobile robot whose body is described as a box moving according to differential drive kinematics. Later examples push into the harder parts of a real system: hardware components with multiple interfaces, an integrated sensor, an externally connected sensor, separate communication to each actuator, transmissions, GPIO interfaces, a steering controller library, and a full tutorial for a 6 DOF robot aimed at intermediate ROS 2 users.

The last few examples are the ones that matter if you are running a fleet. Example 12 shows a simple chainable controller integrated to form a controller chain for RRBot's joints. Example 13 handles multiple robots in a single controller manager instance. Example 15 integrates multiple robots under different controller manager instances. Example 16 builds chained controllers from diff_drive_controller and two pid_controllers. Example 17 publishes diagnostics from a hardware component using the Executor passed from the Controller Manager.

Two imaginary robots, RRBot and DiffBot, carry all of this. The README calls them well known imaginary robots and trivial simulations, which is a fair description of the teaching vehicle.

Every example repeats the same four folder layout

Each example_XY directory is a complete package named ros2_control_demos_example_XY, and inside it the subfolders are consistent. The bringup folder holds launch files and runtime configurations. The description folder holds URDF and XACRO description files, rviz configurations and meshes. The hardware folder holds implementations of example hardware components, which the README calls interfaces. The controllers folder is optional and holds example controller implementations.

The README then lists the files worth opening in each example, which is the most useful part of the document for a newcomer:

bash
bringup/launch/<example_name>.launch.py
bringup/config/<example_name>_controllers.yaml
description/<example_name>.ros2_control.xacro
description/<example_name>.urdf.xacro
hardware/<example_name>.hpp
hardware/<example_name>.cpp

The controller parameters live in a YAML file per example, and the XACRO file carries the ros2_control URDF tag with the hardware setup and its parameters. The main description XACRO generates the URDF on the fly and publishes it on the /robot_description topic. The launch file ties the two together.

The primary language of the repository is Python, which is what the launch files are written in, while the hardware and controller implementations are C++ in the examples given. The C++ is the point of the examples, since the interface classes are what a real robot has to implement.

Where the controller manager does the interesting work

Several of the examples exist to show how the controller manager behaves, and grouping them makes the progression clear.

Example 1 starts with switching between different controllers on one robot. Example 12 extends that to controller chaining, where a simple chainable controller is integrated to form a chain controlling RRBot's joints. Example 16 does the same with a different vocabulary: chained controllers built from diff_drive_controller and two pid_controllers to drive a differential robot. The difference between the two is instructive, because one shows the chain over revolute joints and the other over a mobile base.

Then the scope widens. Example 13 handles multiple robots in a single controller manager instance, and Example 15 integrates multiple robots under different controller manager instances. Together they mark the boundary between one manager owning several robots and several managers each owning their own, which is the kind of question a fleet operator asks on day one.

Example 17 adds observability from the other direction. It publishes diagnostics from a hardware component using the Executor passed from the Controller Manager, so the diagnostic data path runs through the same executor the controller manager hands out. If you are wiring up a device with its own health reporting, that example shows where the plumbing goes.

Sensors and actuators appear in four different arrangements

Hardware interfaces are where real robots diverge from toys, and the examples cover several distinct arrangements rather than one canonical one.

Example 3 is RRBot with multiple interfaces. Example 4 is an industrial robot with an integrated sensor, where the sensor lives inside the robot description. Example 5 is an industrial robot with an externally connected sensor, a different wiring and timing assumption. Example 6 is a modular robot with separate communication to each actuator, which the README describes as showing how to implement robot hardware with separate communication per actuator. Example 10 is RRBot with GPIO interfaces, and Example 14 covers modular robots whose actuators do not provide states and which carry additional sensors.

Example 8 exposes a transmission interface on RRBot, and the repository has a separate directory for a shared description package and one for test utilities, ros2_control_demo_description/ and ros2_control_demo_test_utils/.

The practical reading of this set is that there is no single right way to attach a sensor in ros2_control, and the demos exist so you can see the trade-offs side by side rather than inherit one from a single tutorial.

Example 9 is where simulation and hardware are separated

One example is dedicated to the question every robotics team eventually asks: how do I run the same thing in simulation and on the robot. Example 9 demonstrates how to switch between simulation and hardware, and it uses Gazebo for the simulation side.

The mechanism is visible in the folder design already described. The description folder holds the URDF and XACRO files, and the ros2_control URDF tag carries the hardware setup and its parameters, which is where a fake hardware component and a real driver get swapped. The controllers YAML and the launch file sit above that, so the controller side of the experiment can stay fixed while the hardware component changes.

That is the reusable lesson of the whole repository: the layering of bringup, description, hardware and controllers is what makes the switch possible, and the same layering is what a real robot package needs, even though the demo layout itself is not the layout you should ship.

One branch per ROS 2 distribution, plus the .repos files that fetch them

The README instructs users to choose the branch matching their ROS 2 distribution, and the build status table starts with Rolling on the master branch, with binary and semi-binary build workflows wired to GitHub Actions. The repository is not archived, and the last push was on 2026-10-17.

The distribution pinning is also present as files rather than only as branches. At the top level there are .repos files per distribution, covering humble, jazzy, kilted, lyrical and rolling, plus matching not-released variants for the same set:

bash
ros2_control_demos.humble.repos
ros2_control_demos.jazzy.repos
ros2_control_demos.kilted.repos
ros2_control_demos.lyrical.repos
ros2_control_demos.rolling.repos

That is a workspace recipe rather than a single package, and it matches how ROS 2 repositories are usually consumed, in a workspace that a tool fetches.

The repository also carries a Dockerfile/ directory, a .clang-format file, a .pre-commit-config.yaml for hook management and a doc/ directory. The presence of stale.yml suggests a periodic job marks issues and pull requests that have gone quiet, which is a reasonable thing to have in a repository with seventeen examples and many contributors.

Licensing is Apache-2.0, with the LICENSE file at the root and a badge in the README pointing at the standard Apache 2.0 text. Read that file for the terms themselves; this is not legal advice.

The README tells you not to use this structure in your robot

The most useful paragraph in the whole document is a warning. The README states that the structure of packages, folders and files given in this repository is not recommended for your robot, and that you should usually define all of those folders as separate packages with the naming convention <robot_name_or_type>/[bringup|description|hardware|controllers].

That is a demo layout, deliberately flattened so that a reader can open one directory and see everything about one concept. It is the opposite of what a production robot wants, where the hardware interface for one device has its own lifecycle and its own release cadence, separate from the bringup package that starts it.

The README then points at two concrete places to get the guidance right. One is the ros_control_boilerplate repository from Dave Coleman, which provides a more standard structure for the same four folders. The other is the documentation on robot package structure from Stogl Robotics, published under the ros_team_workspace guidelines. Neither is described as a competitor to the demos. They are the recommended alternative shape for the same concepts.

There is also a second pointer for learning rather than for structure. If you want a step by step manual on doing things with ros2_control, the README sends you to the ros-control/roscon2022_workshop repository. The demos show the concept, the workshop walks through it by hand, and the boilerplate shows how to package it properly.

Where ros2_control_demos is the wrong tool

It is the wrong tool for building a robot. These are teaching packages with trivial simulated hardware, and the README says so plainly. If you start from example_1 and grow it into a production robot, you are fighting the demo layout the whole way, and the README has already told you not to do that.

It is also the wrong tool for a specific question with a specific answer. Seventeen examples means seventeen branches of the framework to hold in your head, and the right way to use the repository is to find the one example that isolates the behaviour you are stuck on, read its hardware component and its launch file, and then go back to your own package. Using it as a library of components is a category error, since these are demonstrations rather than reusable packages.

The third limit is distribution lag. A repository that must publish a branch and a .repos file per ROS 2 distribution is necessarily tied to the release cycle of those distributions. If you are on a distribution the project has not yet added a branch for, you are reading source code rather than running examples, and the behaviour of a framework under development can differ from the version you have installed.

The fourth is that the examples are C++ against the framework interfaces, which is the point, but it means a Python-only team will be reading code in a language they may not write. The launch files are Python, and the controllers and hardware are not.

Editorial conclusion

ros2_control_demos fits an engineer who needs to understand one ros2_control mechanism at a time, in a form they can read end to end and run on the matching distribution branch. It does not fit a robot project, because the README explicitly warns against using this folder layout for real hardware, and it does not fit anyone without a ROS 2 distribution already installed. Before copying anything, follow the structure guidance in the README to the ros_control_boilerplate repository instead.

Frequently asked questions

What is ros2_control_demos used for?

It provides simple example implementations that illustrate concepts in the ros2_control framework and the ros2_controllers packages, spread across seventeen example packages built around the RRBot and DiffBot example robots.

How do I install ros2_control_demos?

The README directs you to the installation steps in the project documentation on control.ros.org, and tells you to pick the branch matching your ROS 2 distribution. The repository also ships .repos files per distribution, covering humble, jazzy, kilted, lyrical and rolling.

Should I copy the folder layout from ros2_control_demos into my robot?

No. The README explicitly says the structure of packages, folders and files in this repository is not recommended for your robot, and that the folders should normally be separate packages named <robot_name_or_type>/[bringup|description|hardware|controllers]. It points to the ros_control_boilerplate repository and the ros_team_workspace guidelines for the standard shape.

Which example shows how to switch between simulation and hardware?

Example 9, the Gazebo simulation example, demonstrates how to switch between simulation and hardware.

How do multiple robots work with the controller manager in these demos?

Example 13 shows how to handle multiple robots in a single controller manager instance, and Example 15 shows how to integrate multiple robots under different controller manager instances. Example 17 then shows a hardware component publishing diagnostics using the Executor passed from the Controller Manager.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. Project website
  4. README
  5. ros-controls/ros2_control_demos on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ros-controls-ros2-control-demos.svg)](https://hysenlabs.com/projects/ros-controls-ros2-control-demos)

Was this useful?