Imagine being tasked with developing a highly sophisticated humanoid robot, a project involving a diverse team of engineers. Your specific mandate is the intricate design and programming of the robot’s arms and hands, ensuring they can execute precise movements, grasp objects, and interact delicately with the environment, such as shaking a human hand. Crucially, you operate without direct sensor input; that responsibility falls to another specialized team. Furthermore, your work must be seamlessly integrated with the locomotion team, as arm movements are vital for maintaining the robot’s overall balance and stability. The challenge lies in harmonizing these disparate components, each developed by different teams, into a cohesive, functional entity. A crucial initial meeting would involve mapping out all these complex components on a giant whiteboard, delineating their interdependencies and defining how they will communicate. For instance, cameras and motion sensors in the robot’s head must transmit raw data to a central processing core, which then computes optimal movements for the arms and legs. Simultaneously, this positional data must loop back to the processing core to continuously adjust the robot’s stability. The fundamental question then arises: how will this intricate web of communication be established? Is it necessary to devise a unique, bespoke communication protocol for every single component interaction, a task that historically consumed countless engineering hours?

The Genesis of Standardization: From Chaos to ROS 1
Until the late 2000s, roboticists grappled with precisely these communication challenges, often resorting to the time-consuming and inefficient practice of creating new messaging schemes from the ground up for each new robot project. This constant "reinvention of the wheel" for underlying frameworks and communication protocols frequently consumed more development time than the actual construction and functional programming of the robots themselves. This fragmentation severely hindered progress, collaboration, and the scalability of robotic systems.

A pivotal shift occurred in 2006 when two visionary Ph.D. students at Stanford University’s Salisbury Robotics Lab, Eric Berger and Keenan Wyrobek, embarked on a mission to solve this pervasive problem. Their groundbreaking initiative led to the creation of the Robot Operating System (ROS), designed to introduce a much-needed standardization to communication among various robot components. Their innovative work quickly garnered attention, notably from Scott Hassan, the founder of the influential Willow Garage incubator. Recognizing the immense potential of ROS, Hassan extended an invitation to Berger and Wyrobek to continue their development efforts within Willow Garage’s supportive environment. Over the subsequent three years, the dedicated team at Willow Garage developed the PR2 robot, an advanced successor to the earlier PR1 prototype initiated at Stanford. During this period, ROS was meticulously fleshed out and refined, evolving into the robust underlying software framework that powered the PR2, demonstrating its practical efficacy and laying the foundation for its widespread adoption.
ROS 2: A Modern Evolution for Next-Generation Robotics

ROS, at its core, is an open-source robotics middleware framework, complemented by a rich collection of libraries. It is important to clarify that ROS is not a traditional "operating system" in the vein of Windows, macOS, or Linux. It does not directly control hardware at the lowest level, nor does it possess a kernel for managing processes and memory allocation. Instead, ROS is built on top of an existing operating system, predominantly Linux, leveraging its capabilities while providing a sophisticated layer for multiprocessing communication and offering specialized computational libraries. A prime example is the Transform Library 2 (TF2), essential for handling complex coordinate frame transformations in robotic navigation and manipulation.
The initial iteration of ROS, now referred to as ROS 1, faced certain technical limitations, particularly in its underlying messaging layers, which became more apparent as robotics advanced. To address these evolving requirements and build a more robust, future-proof platform, the ROS team initiated the development of ROS 2 in 2014. This significant undertaking aimed to overcome the limitations of its predecessor, particularly concerning real-time performance, security, and support for multi-robot systems. The transition culminated with ROS 1 reaching its official end-of-life status on May 31, 2025, signifying a complete shift of focus and support to ROS 2. This strategic move ensured that the robotics community would benefit from a modern, actively maintained framework capable of meeting the demands of contemporary and future robotic applications.

ROS 2 operates on a system of distributions, which are versioned sets of ROS packages, akin to how Linux distributions bundle various software packages. These distributions are whimsically named, typically featuring a turtle and progressing alphabetically. While the latest release, Kilted Kaiju, emerged in May 2025, the Jazzy Jalisco distribution remains a popular choice due to its long-term support (LTS) extending until 2029. Each ROS distribution is meticulously "pinned" to specific versions of underlying operating systems to guarantee compatibility and proper functioning of all its libraries. For instance, Jazzy Jalisco officially supports Ubuntu 24.04 and Windows 10 (requiring Visual Studio 2019).
Understanding the ROS 2 Ecosystem: Nodes and Packages

The design philosophy behind ROS, particularly ROS 2, centers on scalability and modularity. It is not ideally suited for simple, single-purpose robotic applications like basic vacuum cleaners or maze-solving robots, where the overhead of a full operating system and multiprocessing environment would be unnecessary. Its true value shines in complex scenarios involving multiple, interdependent components. In such environments, ROS can dramatically reduce development time and mitigate frustration by providing a standardized, robust framework for inter-component communication and coordination.
The impact of ROS 2 extends far beyond academia, where it is a cornerstone for research. It has been widely adopted across various industries for real-world, commercial robotic deployments. Notable examples include advanced logistics robots in Amazon warehouses, high-performance commercial-grade cleaning robots from Avidbots, and precision manipulator arms manufactured by Omron. This widespread industrial adoption underscores ROS 2’s reliability, flexibility, and practical utility in diverse applications.

For those eager to delve into this powerful framework, whether to build a sophisticated helper bot for household chores, enhance their robotic programming skills for professional advancement, or simply explore the capabilities of modern robotics, understanding the core principles is key. The fundamental building blocks of ROS 2 applications are nodes. These are independent processes, essentially self-contained programs, each responsible for handling a specific task. This could range from reading sensor data and executing complex algorithms to controlling motors. Each node operates autonomously within its own runtime environment, communicating with other nodes through a set of predefined mechanisms.
A workspace in ROS 2 is the overarching directory where you organize, build, and manage your ROS packages. The example introduction-to-ros repository creates such a workspace. Within this workspace, the src/ directory houses your source code, organized into packages. A package is the fundamental unit of code organization in ROS 2, typically containing one or more nodes that form part of your robot application. When these nodes are built using the colcon build tool, the compiled libraries, executable files, and other artifacts are placed in the install/ directory. Intermediate build files and logs are stored in the build/ and log/ directories, respectively.

When creating a package, you specify its build type. For Python-based nodes, ament_python is used, signaling to ROS 2 that Python will be the language of choice for that package’s nodes. ROS 2 natively supports Python and C++, offering developers flexibility. C++ is typically favored for low-level drivers and performance-critical processes requiring rapid execution due to its efficiency. Python, conversely, provides faster development cycles and is excellent for prototyping, as well as integrating with high-level libraries for computer vision (e.g., OpenCV) and machine learning frameworks (e.g., PyTorch, TensorFlow). A significant advantage of ROS is its language agnosticism: nodes written in one language can seamlessly communicate with nodes written in another, fostering truly heterogeneous development environments. ROS relies heavily on object-oriented programming, with individual nodes typically implemented as subclasses of the Node class, inheriting its core properties and functionalities. Publishers and subscribers, as we will see, are instances of objects within these nodes, allowing a single custom node to manage multiple communication channels.
The Publish/Subscribe Paradigm: ROS 2 Topics in Action

The first and most common communication mechanism in ROS 2 is the topic, which operates on a publish/subscribe messaging model. In this model, a publisher node sends data to a named topic. The underlying ROS system then efficiently handles the delivery of that message to any subscriber nodes that have registered an interest in that specific topic. This asynchronous, one-to-many communication pattern is ideal for continuous data streams, such as sensor readings (e.g., lidar scans, camera feeds, IMU data), motor status updates, or telemetry information.
To illustrate this, consider a practical demonstration using a Docker image. After installing Docker Desktop and cloning the introduction-to-ros GitHub repository, the docker build -t env-ros2 . command creates a robust environment. This Docker image, based on the XFCE Ubuntu webtop, provides a full Ubuntu desktop accessible via https://localhost:3000, preconfigured with ROS 2 development tools. Within this environment, a ROS package named my_first_pkg is created using ros2 pkg create --build-type ament_python my_first_pkg.

Two Python scripts, my_publisher.py and my_subscriber.py, are then developed within my_first_pkg/my_first_pkg/. The my_publisher.py script defines a MinimalPublisher class that inherits from the ROS Node class. It instantiates a publisher object using self.create_publisher() and a timer that periodically calls _timer_callback(). This callback constructs a "Hello world: " string appended with an incrementing counter and publishes it to a topic named my_topic twice per second. The main() function initializes rclpy (the ROS Client Library for Python), creates and spins the MinimalPublisher node, and handles graceful shutdown.
Concurrently, my_subscriber.py defines a MinimalSubscriber node. This node instantiates a subscription object configured to listen to my_topic. Whenever a message arrives on my_topic, the _listener_callback() method is invoked, receiving the message as a msg parameter and simply printing it to the console. This setup clearly demonstrates the publish/subscribe model, where the publisher broadcasts information without needing to know who is listening, and subscribers receive relevant data passively.

Before execution, the package metadata in my_first_pkg/package.xml is updated to declare rclpy as a dependency, ensuring the ROS build system recognizes it. The my_first_pkg/setup.py file is then modified to define my_publisher:main and my_subscriber:main as executable entry points. The package is built using colcon build --packages-select my_first_pkg. Once built, separate terminal windows are used to source the workspace environment (source install/setup.bash) and run ros2 run my_first_pkg my_publisher and ros2 run my_first_pkg my_subscriber. The simultaneous output in both terminals confirms successful communication. Furthermore, the rqt_graph tool provides a visual representation of these nodes and their topic-based communication, proving invaluable for debugging and understanding complex system architectures.
Client-Server Interaction: Leveraging ROS 2 Services

While the publish/subscribe model excels at continuous data broadcasting, it is not suited for situations requiring a direct request-response interaction between nodes. For such scenarios, ROS 2 provides services, which implement a client/server communication model. In this paradigm, one node functions as a server, passively waiting to receive and process incoming requests. Another node acts as a client, initiating a request to a specific server and then pausing its operation, awaiting a corresponding response. This synchronous pattern is particularly effective for operations that demand a single, specific action or a one-time data retrieval. Examples include instructing a motion node to move the robot a precise distance, querying the status of a particular sensor, or setting a configuration parameter on another component.
To demonstrate services, two new Python scripts, my_server.py and my_client.py, are added to my_first_pkg/my_first_pkg/. The my_server.py script defines a MinimalServer node. This node instantiates a service named add_ints, using the AddTwoInts interface (imported from example_interfaces.srv). This interface dictates the structure of both the request and response messages. The _server_callback() method is attached to this service, which is invoked whenever a request arrives. The request, contained in the req parameter, is expected to have two integer fields, a and b. The server adds these integers, stores the sum in the sum field of the response object, logs the operation, and returns the response. The ROS 2 framework then manages the delivery of this response back to the client.

The my_client.py script creates a MinimalClient node. It instantiates a client object, also specifying the AddTwoInts interface and the service name add_ints. Similar to the publisher, a timer is set up, calling a callback method every two seconds. This callback constructs a request with two random integers (between 0 and 10) for fields a and b. It then sends this request to the server and assigns the result to a future object. A future is a powerful construct that acts as a placeholder for a result that will become available asynchronously. A callback is attached to this future, which executes once the client receives the response from the server, allowing the sum to be extracted and printed.
As with the topic-based nodes, my_first_pkg/setup.py is updated to include my_client:main and my_server:main as entry points, and the package is rebuilt using colcon build --packages-select my_first_pkg. Running ros2 run my_first_pkg my_server and ros2 run my_first_pkg my_client in separate terminals demonstrates the client sending requests and the server processing them, with sums appearing in both consoles. While rqt_graph can visualize the presence of these nodes, it typically does not draw direct lines for services, as their interaction is a discrete request-response rather than a continuous data stream.

Broadening Horizons: Commercial Impact and Future Implications
At first glance, the extensive effort dedicated to enabling software components to communicate might seem disproportionate. However, these foundational concepts—nodes, topics, and services—form the bedrock of ROS, a crucial middleware messaging layer. Its true value lies not in being a mere collection of robot drivers or sensor libraries, but in solving the critical challenge of scaling software projects for large, complex robotics systems. While the overhead might be excessive for simpler projects, for ambitious endeavors, ROS saves hundreds, if not thousands, of hours of development time and alleviates significant frustration.

This brief introduction merely scratches the surface of ROS’s capabilities. Beyond its fundamental messaging system, ROS ships with a comprehensive suite of libraries, including TF2 for coordinate transformations, sophisticated diagnostic tools for system monitoring, and advanced visualizers like RQt, which are indispensable for building, testing, and deploying robust robot software. Topics and services are just the initial steps into a vast ecosystem designed to handle extremely complex designs.
The transformative power of ROS has been instrumental in democratizing robotics development. By providing a standardized framework, it has fostered unprecedented collaboration within the global robotics community, accelerating both research and commercial innovation. Its open-source nature ensures continuous development, driven by a vibrant community of engineers and researchers worldwide. As robotics continues to evolve, encompassing more sophisticated autonomous systems, multi-robot coordination, and tighter integration with artificial intelligence, ROS 2 is poised to remain a critical enabler. Its modular architecture, robust communication protocols, and extensive toolchain empower developers to create the next generation of intelligent, capable robots that will increasingly shape our world, from advanced manufacturing to assistive technologies and beyond. The future of robotics is intrinsically linked to platforms like ROS 2, which provide the essential infrastructure for complexity, collaboration, and innovation.