Framework
ros-controls/ros2_control avatar
ros-controls/ros2_control

ros2_control: a hardware abstraction and controller framework for ROS 2

Generic and simple controls framework for ROS 2

1,042 stars502 forksC++Apache-2.0

At a glance

What is it?
ros2_control is the Apache-2.0 licensed core of the ROS 2 control stack, a set of C++ packages that split robot hardware access from control loops and ship one branch per ROS distribution, from Humble to Rolling. It suits a robotics team writing hardware interfaces and controllers for ROS 2, and it is the wrong layer to reach for if you are not using ROS 2 at all.
Who is it for?
ros2_control fits a robotics team already committed to ROS 2 who need the hardware interface and controller manager split that the ecosystem assumes, because changing a robot's joints should not mean rewriting its controllers. It is a poor fit for a project that only needs to read an encoder or drive a single motor, since the framework brings a controller manager, a resource manager model and a joint limits layer with it.
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 4 days ago.
What is it written in?
Mainly C++, 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

A framework split into layers that mirror a robot's structure

ros2_control is described as a generic and simple controls framework for ROS 2, and the repository root shows how that framework is decomposed. The hardware_interface/ directory holds the layer that talks to the physical robot, controller_interface/ defines what a controller can see, controller_manager/ runs and loads the controllers, and joint_limits/ enforces the ranges the mechanical hardware allows. transmission_interface/ is the abstraction between a command and the hardware it drives, hardware_interface_testing/ provides fakes so you can develop without a robot, and controller_manager_msgs/ carries the service and message types. On top of that sit ros2_control/ as the metapackage, ros2controlcli/ as the command line tool, rqt_controller_manager/ for the graphical controller view, and ros2_control_test_assets/ with hardware to test against. The primary language is C++.

Every ROS 2 distribution gets its own branch and its own docs

The build status table at the top of the README is the most useful thing in the document, because it shows that this project is maintained across five distributions at once. Rolling and Lyrical both use the master branch, with Lyrical pointing at the same tree, and Kilted, Jazzy and Humble each have their own branch. Each row gives a binary build and a semi-binary build in GitHub Actions, a build.ros2.org job for a development source build, a package build, a documentation link and an API reference link, and the documentation paths differ per branch, for example control.ros.org/jazzy/index.html and control.ros.org/humble/index.html. The Jazzy row builds on Ubuntu Noble and Humble on Ubuntu Jammy. The topics list names the same set, ros2-humble, ros2-jazzy and ros2-rolling, which is how you can tell at a glance which distributions the project tracks.

The .repos files decide what a build actually pulls in

The root listing is dominated by .repos files, and they are the mechanism that makes the per-distribution branching work. There are two families, ros2_control.<distro>.repos and ros2_control-not-released.<distro>.repos, for humble, jazzy, kilted, lyrical and rolling, plus a separate set named ros_controls.<distro>.repos for the sibling projects. The distinction the filenames encode is what the project itself calls released and not released, which in ROS 2 practice means the packages that ship in a binary distribution and the ones that are built from source. A developer on a given distro uses the appropriate file to pull the exact set of packages that work together on that release. Getting this wrong is the classic source of a control stack that compiles but mixes versions, so it is worth understanding before your first build.

Docker images are published for both source and release builds

The README has a short section on Docker images, noting that a few published images come with the latest releases and that more detail is in the .docker folder in the repository. There are two tags to pull, ghcr.io/ros-controls/ros2_control_release and ghcr.io/ros-controls/ros2_control_source, so the naming convention distinguishes a build from released binaries against one built from source. The images are on GitHub Container Registry rather than Docker Hub, which is the usual convention for ROS 2 projects and follows the same pull path the other robotics projects use. If you are running the control stack inside a container, which many simulation and CI setups do, these images remove the need to reproduce the workspace build locally.

Pulling the stack: images first, then the workspace file for your distro

Two things have to be in place before any of this compiles. The first is a Redis-style equivalent of the framework, which here means a container with the control stack in it, and the images are the fastest route to one.

bash
ghcr.io/ros-controls/ros2_control_release
ghcr.io/ros-controls/ros2_control_source

Those are the two published tags, one built with the latest releases and one from source, and the .docker folder in the repository holds the details of how they are put together. The second thing is the workspace manifest, and the choice here is which .repos file you feed your tool. The naming is deliberate, with ros2_control.<distro>.repos for the set that ships in a binary release and ros2_control-not-released.<distro>.repos for the set that is built from source, and one of each for humble, jazzy, kilted, lyrical and rolling. Pick the pair that matches the distribution you are targeting, since the whole point of the branching is that a stack assembled from the wrong manifests compiles but misbehaves in ways that are painful to trace.

Contributing is framed around picking up an existing pull request

The contributing section is short and gives an unusual instruction for an open source project, that each contributor is welcome regardless of their background and experience, and that you should pick a pull request and review it, or create your own. For new contributors the README points at a contributing guide in the documentation and says the maintainers are happy to help with a first contribution. The repository also carries a .pre-commit-config.yaml and a .clang-format file, which tells you the C++ style is enforced by tooling rather than by review comments, and a codecov.yml with a coverage badge, so test coverage is tracked as part of the build. A SECURITY.md is not listed at the root, unlike in several other projects covered here.

The framework is one layer of a larger stack

The README is careful about scope. It states that this package is a part of the ros2_control framework and points to control.ros.org for more, which means the hardware interfaces, the controller manager and the transmission interface sit inside a larger stack that also includes the resource manager and the real-time tooling. The acknowledgements section makes the same point from the other direction, noting that the project has received major contributions from companies and institutions listed on the documentation site. For a reader deciding whether to adopt it, the practical question is whether your robot's hardware already has a ros2_control hardware interface, because if it does, the controller side becomes a straightforward exercise, and if it does not, writing one is the real work.

Editorial conclusion

ros2_control fits a robotics team already committed to ROS 2 who need the hardware interface and controller manager split that the ecosystem assumes, because changing a robot's joints should not mean rewriting its controllers. It is a poor fit for a project that only needs to read an encoder or drive a single motor, since the framework brings a controller manager, a resource manager model and a joint limits layer with it. Verify first which ROS 2 distribution you are on and pick the matching branch, since the repository keeps separate trees for Humble, Jazzy, Kilted, Lyrical and Rolling, and note that the ROS 2 rolling and non-rolling package sets are described by separate .repos files that list what each build includes.

Frequently asked questions

What is ros2_control?

It is a generic and simple controls framework for ROS 2, made up of C++ packages including hardware_interface, controller_interface, controller_manager, joint_limits, transmission_interface and the ros2controlcli tool. The homepage is control.ros.org.

Which ROS 2 distributions does ros2_control support?

The build status table lists five. Rolling and Lyrical share the master branch, while Kilted, Jazzy and Humble each have their own branch, and each row links to its own documentation and API reference, with Jazzy building on Ubuntu Noble and Humble on Ubuntu Jammy.

Where are the Docker images for ros2_control?

On GitHub Container Registry, under two tags, ghcr.io/ros-controls/ros2_control_release for builds with the latest releases and ghcr.io/ros-controls/ros2_control_source for source builds. The .docker folder in the repository holds more information.

What are the .repos files in the ros2_control repository used for?

They list the packages to pull for a given ROS 2 distribution, with a separate set for the packages that ship in a binary release and another for those built from source, and separate files for humble, jazzy, kilted, lyrical and rolling.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. Project website
  4. README
  5. ros-controls/ros2_control 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.svg)](https://hysenlabs.com/projects/ros-controls-ros2-control)

Was this useful?