Every article on LWN.net is written by humans, for humans. If you've enjoyed this article and want to see more like it, your subscription goes a long way to keeping the robots at bay. We are offering a free one-month trial subscription (no credit card required) to get you started.
October 3, 2025
This article was contributed by Chris Lalancette
Despite its name, the Robot Operating System (ROS) is not an operating system; it is a software development kit (SDK) that provides building blocks for robotic applications. One of the main goals of ROS is to present a common API that abstracts away the details of particular hardware drivers or algorithms to make development easier; developers can focus on what a robot should do rather than the low-level details of specific controllers. The latest release of ROS, Kilted Kaiju, features improvements to the middleware layer that is used to deliver data between components.
Overview
Robots are complex electromechanical systems composed of sensors, actuators, one or more computers, and the software that ties it all together. A simple way to think about a robot is that it uses sensors to gather data about the world around it, interprets that sensor data, and then performs some activity toward a goal using its actuators. Robots use algorithms to carry out tasks that humans want them to do. For example, a robot might process camera data to extract semantic meaning, or use laser scanners to determine the robot's position in a room; it might also use an algorithm to calculate how its arm should move to pick up an object.
There are many ways to do these things, and this is where ROS comes in. It provides the tools and plumbing that helps developers create applications to run on all manner of robots. It provides abstractions so that an application does not need, for example, to deal with how a robot knows its position in space. Instead, an application can simply use the map data and position provided to it.
Before the 2010s, the challenges of developing the robot hardware and software often fell to the same people. In those days, just getting a robot to move was a challenge and it was celebrated when it happened. Unfortunately, that meant that the state of the art of robotics was slow to develop since each university, lab, or company was starting from scratch every time. It was difficult to improve the software that robots need to understand the world before funding ran out or students graduated.
That scenario started to change in the late 2000s to early 2010s with the introduction of cheaper sensors, cheaper computation, and industry-standard hardware like the Arduino. One of the drivers toward standardization and software reuse for robotics was the introduction of ROS in 2010.
A brief history of ROS
The initial version of ROS (now called ROS 1) was released as a set of BSD-licensed libraries in 2010. Before that, it had been developed internally at Willow Garage, a robotics research lab and technology incubator, initially to support the PR2 robot. Early on, it was recognized that the software needed to run this complex robot could also be used in other robots, so the software was purposefully kept as generic as possible.
In 2012, Willow Garage was winding down, and the non-profit Open Source Robotics Foundation (OSRF) was created to shepherd the open-source project. The OSRF owns the copyright to the ROS code, the trademarks, and other IP related to ROS and its sister projects.
The OSRF started to think about the future of ROS and learn from the mistakes made while creating the first version. That led to the initial implementation of ROS 2, the current major release version of ROS. It keeps many of the concepts from ROS 1 while improving the overall implementation and making it production-ready. As of 2025, more than 80% of user downloads from the ROS community are for ROS 2, and support for the final release of ROS 1 ended in May 2025.
Robots are widely used for everything from vacuum cleaners to satellites, in industrial manipulators and humanoid hardware, and many things in between. ROS 2 has been used in all of these contexts, and for different kinds of projects, from hobbyist all the way up to the largest players in the industry. There is a showcase of robots on the ROS web site that illustrates the wide variety of applications that ROS is used in.
Governance
The ROS community is a bit more structured than many open-source projects. Since 2024, the OSRF has managed the ROS community under the Open Source Robotics Alliance (OSRA), which is an initiative created to improve the governance of OSRF's open-source projects, provide funding, and ensure long-term stability for them. According to its explainer, the OSRA is modeled after organizations such as the Linux Foundation and Eclipse Foundation.
OSRA provides a home for several initiatives in addition to ROS 2. This includes the Gazebo robotic simulator, a robotics fleet manager called Open-RMF, and ros2_control, which is a framework for realtime control of robots. OSRA also manages the infrastructure for the build and continuous-integration systems for all of these efforts. Each of the projects has its own project management committee (PMC), which is responsible for the management of the project, including development, support, releases, and responding to security incidents according to the security policy.
The OSRA also collects dues from members and can distribute that money to the individual projects. For instance, if the ROS PMC needs to hire a technical writer for a specific feature, it can submit a request to the OSRA for funds.
Distributions and Releases
The core of ROS 2 includes about 400 packages; these are listed in the ros2.repos file in each release's branch. The code for the core is hosted on GitHub and is mostly Apache-2.0 licensed, with some of the older code using the three-clause BSD license.
The official mascot of ROS is the turtle; as such, ROS 2 releases are made annually on World Turtle Day on May 23. Releases in odd-numbered years have 18 months of support, while releases in even-numbered years have five years of support. The project uses a naming scheme similar to Ubuntu's; each release has a code name that is an adjective followed by a noun. For instance, the 2024 release of ROS 2 is named Jazzy Jalisco and will be supported through 2029, while the 2025 release is named Kilted Kaiju and will be supported until December 2026. This support period aligns with the Ubuntu LTS release schedule; Ubuntu is the recommended platform to use to develop applications with ROS 2, though others are also supported. Releases are almost always referred to by their adjective name, such as Kilted.
A ROS 2 release consists of the release-critical core packages plus thousands of extra packages provided by the larger community; together this is called a ROS distribution. The core contains the SDK for both C++ and Python, basic communication mechanisms, common structures for collecting and exchanging data (called messages), command-line debugging tools, tools for recording and playing back data, visualization tools, tracing tools, and examples.
Packages from the community include SDKs for other languages (like C, Rust, and Java), messages that aren't common enough for the core, hardware drivers, additional debugging tools, experimental tools/drivers/capabilities, and anything else that the community thinks would be helpful to other robotics developers. Each ROS distribution has a YAML file which lists all packages available; for instance, the Kilted YAML file is available on GitHub. Developers are encouraged to add their own packages to that list, which members of the ROS PMC will review for relevance to ROS and merge.
A platform in ROS terms is a combination of an operating system and hardware architecture; for example, Ubuntu Noble on x86-64 is a supported platform, as is Ubuntu Noble on arm64, or Windows 10 on x86-64. Each ROS 2 release defines its supported platforms in a document called REP-2000, which is updated periodically for new releases. A release may be delivered on a platform via Debian packages, RPMs, binary tarballs, or from source. It is often possible to build from source if a platform is not officially supported. The ROS developer documentation site has installation guides and tutorials for each release.
Communication mechanisms
In ROS 2, the unit of computation is referred to as a node, and each node is responsible for "a single, modular purpose". This purpose might be getting data from a sensor, driving an actuator, determining the robot's position, displaying data, or anything else needed to make the robot operate. As mentioned earlier, robots are frequently made up of one or more computers responsible for different parts of the functionality, and nodes may be deployed on any of them.
To facilitate communication between nodes, ROS 2 offers three different network-communication primitives: a publish/subscribe (pub/sub) bus called "topics", a remote procedure call (RPC) mechanism referred to as "services", and a cancelable RPC mechanism called "actions" for longer-running tasks. The connections between nodes, topics, services, and actions are collectively referred to as the "network graph".
By far the most commonly used primitives in ROS are topics, each of which have zero or more publishers that generate data and zero or more subscriptions that receive and process data. Both publishers and subscriptions may be added dynamically to the network "graph", which allows users to easily attach debugging points and additional functionality as a robot grows more complex. Publishers and subscriptions to a particular topic find each other on the graph by using a common name like /right_camera, and a typical robot has hundreds, if not thousands, of individual topics.
The data transferred over the topic is a strongly typed "message", which is specified using an INI-like syntax that is described in the documentation. The core provides a number of common robotic message types, such as an Image, a LaserScan for scans from a laser range finder, and more.
The service mechanism in ROS 2 is more lightly used but it fills an important niche. Services use a call-and-response model; a server provides data to a client when it asks for information. The clients make RPC calls to the server, which calculates and returns a result.
For instance, a typical feature of a robot is a "software emergency stop", where a user or another piece of the robot can send a signal to cut off power to the actuators. This is typically implemented with a service server that has access to the physical emergency-stop hardware; one or more clients can send the signal to emergency stop when the user requests it or when a dangerous situation is detected.
Services find each other in the network graph by using a name like /emergency_stop. It is technically possible, but inadvisable, to have more than one service server with the same name; ROS does not provide a way to define which server will respond and how many responses will be received if more than one server is available.
Like topics, data for each service is transferred using a strongly typed "service message". The ROS 2 core has a few defined services, such as Trigger (where the client sends no data and only receives a boolean response), SetBool (where the client sends a boolean and receives a boolean response), etc. Services have some significant downsides; once a service call has been made, there is no way to cancel it, and there is no way to find out what progress the remote resource has made in performing the task. Because of this, services are typically only used for short-running activities.
For longer-running tasks, actions should be used instead. Actions are similar to services in that they request a remote resource to perform some operation. Unlike services, actions have a cancellation mechanism and a feedback mechanism so they are appropriate for long-running operations, such as asking a robot to move to a location. Actions are built on top of topics and services, thus utilize the same underlying network mechanisms. As with topics and services, data for actions is transferred using a strongly-typed "action message". The ROS project offers tutorials on how actions work, as well as how to create a custom action
Messages for topics, services, and actions can be thought of as the ROS API; by conforming to them, users can add, remove, or replace parts of the ROS stack one at a time, using any language that has a ROS 2 SDK. For instance, a robot may start out using a low-cost laser scanner when its design is being prototyped. As the robot becomes more complex, that laser scanner may not have enough resolution and be replaced with one that has higher fidelity. When this happens, only the driver for the laser scanner needs to be replaced; the rest of the network will still get laser-scanner data, just at a higher resolution. Because of this property, developers are highly encouraged to use existing messages if at all possible. If none of the messages fit the current use case, developers can create their own messages using the same INI-like syntax.
For instance, a custom message to control an RGB LED could look like:
std_msgs/Header header uint8 red uint8 green uint8 blueThe header field embeds a message type from another package into this one, and the red, green, and blue fields allow control of the LED. More documentation about the syntax, including the available primitive types, is available on the documentation site.
All of the above communication mechanisms can be run locally on the same system or across the network to another system. This allows for straightforward remote debugging and development, as developers can attach to a robot from their laptop, watch what is happening, and make changes.
A new (middleware) hope
Because of its design, ROS 2 heavily depends on efficiently delivering data over the network. One of its big innovations was the addition of an abstraction layer for communication, called the ROS Middleware (RMW), which is pluggable both at compile time and at runtime. The documentation has a diagram of the layering of ROS 2, including the RMW.
When development began in 2014, the team thoroughly evaluated the available pub/sub technology. The result of that research was to choose the Data Distribution Service (DDS) standard by the Object Management Group as the default protocol. As of Kilted, it ships with three fully supported DDS RMW implementations: Fast-DDS (Apache-2.0 licensed), Cyclone DDS (Eclipse 2.0 licensed), and RTI Connext (proprietary licensed). While these DDS implementations have worked, ten years of experience in the field have revealed some shortcomings with the protocol.
Armed with the knowledge of these shortcomings, in 2023 the team reviewed the current landscape of pub/sub protocols to find one that would solve the problems with DDS. The findings of that research were published as a white paper on the ROS Discourse forum, and the team chose Zenoh as additional middleware. Zenoh was created by former DDS developers who were frustrated by the problems in DDS, including the ones affecting ROS 2. The protocol promises to address those problems.
DDS nodes announce themselves and discover other participants, such as nodes, topics, services and actions, on the network when they are started. By design, DDS networks are fully connected, meaning that all participants know about the existence of all other participants. This leads to the first problem, which is that the overhead of discovery in large or complex robots can overwhelm the network, causing problems for the robot and other devices that share the network. The first major improvement of Zenoh over DDS is that Zenoh keeps its network discovery overhead low by having each participant only look for the resources it needs.
Second, DDS has two mechanisms to discover other participants in the network: static peers and UDP multicast. When using static peers, each participant is given a list of hosts to connect to at startup, which is efficient but isn't dynamic. UDP multicast can be used for dynamic discovery, but many networks limit or entirely disable UDP multicast for performance or security reasons. When UDP multicast fails to work, it can be hard to debug the reason that participants in the network can't find each other.
As described in the Zenoh documentation, Zenoh can also use static peers or UDP multicast for discovery, but it adds a third mechanism called "routers". In ROS, Zenoh routers are a separate process configured to only facilitate discovery, and ROS nodes, topics, services, and actions are configured to contact the router on localhost during startup. After receiving a list of peers from the router, these ROS entities establish peer-to-peer connections to deliver data. Zenoh routers can also be configured to connect to other Zenoh routers for discovery and data delivery.
The third problem is that, in some scenarios, DDS can struggle to deliver large pieces of data. DDS uses UDP to send messages so that it can implement features like quality-of-service attributes, but this also means it suffers from performance problems. In particular, the UDP stack on Linux has a small default maximum socket receive size, a relatively small default IP fragmentation maximum size, and it keeps IP fragments around for a large amount of time (up to 30 seconds). With these defaults, large data like images may not fit in the receive buffers, and receivers of fragmented data may not have room to be reassembled. If the network is reliable and the consumer of the data keeps up with processing the socket, this can work for large messages. If either one of those isn't true, then the buffers can fill up, and depending on the quality of service, DDS can spend a lot of time attempting to redeliver fragments of large messages.
In contrast, Zenoh uses TCP for data delivery by default. While TCP isn't a panacea and has its own delivery problems (such as head-of-line blocking and bufferbloat), years of experience have shown that TCP tends to work better on wireless networks and across the internet.
Based on the promised improvements, the ROS 2 team, in collaboration with Zenoh's developers, created a new RMW implementation based on Zenoh called rmw_zenoh. By default, rmw_zenoh sets up one Zenoh router per host and uses it in discovery-only mode.
For the Jazzy release, rmw_zenoh was delivered as a technology preview; for the Kilted release, rmw_zenoh is shipped with the core and supports all security options, supports Windows, and passes all core tests. The team has high hopes that rmw_zenoh will improve the situation for roboticists who depend on ROS. Unfortunately, this will only be known for sure once it is deployed on many different robots running on many types of network infrastructure. Because of this, the default RMW for Kilted is still based on DDS, but rmw_zenoh is fully supported and documented as an option.
The future
It is a large project and it is pulled in many different directions based on what the community is using it for. As with many open-source projects, it can be difficult to tell exactly what will be in the next release; that is often dictated by what the community contributes during the development cycle. However, there are well-known issues and features that would be nice to address in the next release (Lyrical Luth).
The Python SDK is known as rclpy and is used both by developers looking to quickly prototype, and by the core command-line tools. Currently rclpy has some performance issues with sending/receiving large messages and in reacting to new data being available. Improving its performance will expand the number of situations that rclpy can be used in, as well as make the core command-line tools faster.
The logging subsystem takes printf()-style log messages and outputs them to various sinks. This is pretty standard functionality, but it has a bit of a twist in ROS 2 because that data is often written out to some combination of the console, the disk, and a ROS topic. As of today, this subsystem is too slow, and logging can't be used in performance-critical code sections. It is also not as configurable as the community needs. For example, it is not possible to have debug messages go to the disk while only warning messages get printed to the screen. Making this subsystem more performant and configurable would open up new uses for it.
Another feature that has been long sought after is additional flexibility and performance for the message-generation pipeline. As discussed earlier, messages in ROS 2 are defined with an INI-like syntax. The message generation pipeline is used to parse that INI-like syntax, then generate language-specific bindings to allow users to interact with those messages as structures. That pipeline can be slow, particularly when generating messages for many languages and with large message definitions. It is also limited, in that all language generators need to be available at the time the messages are generated; it is not possible to add an SDK for a new language without building the entire ROS 2 core from source. Lifting that limitation would be a major boon to developers looking to add SDKs for other languages.
Better documentation for the project is always needed. The basic tutorials for ROS 2 are fairly extensive, but there aren't many good tutorials for advanced use cases. There also aren't many tutorials for migration from ROS 1 to ROS 2. And it would be great to have tutorials describing particular use cases, such as using it with a manipulator arm, on a drone, or other common uses.
For anyone looking to get involved or learn more, the main ROS communication channels are a Discourse instance for general discussion, a Discord server for realtime communication, and there is a section on Robotics StackExchange for Q&A.
.png)
