August 24, 2026
hands-on-with-ros-2-nodes-topics-and-services-1

The intricate world of robotics development has long grappled with the challenge of seamless communication between diverse hardware and software components. Before the advent of standardized frameworks, roboticists frequently found themselves rebuilding fundamental messaging schemes from scratch for each new project, a laborious process that often consumed more development time than the actual construction of the robot itself. This perennial struggle, often described as "reinventing the wheel," highlighted an urgent need for a unified approach to inter-component communication in complex robotic systems.

The Genesis of a Revolution: The Robot Operating System

Hands On with ROS 2: Nodes, Topics, and Services

The turning point arrived in 2006, when Eric Berger and Keenan Wyrobek, then Ph.D. students at Stanford University’s Salisbury Robotics Lab, embarked on a mission to address this pervasive inefficiency. Their innovative solution was the Robot Operating System (ROS), conceived as a standardized platform to streamline communication among various robotic constituents. Their groundbreaking work quickly captured the attention of Scott Hassan, the visionary founder of Willow Garage, a prominent robotics incubator. Hassan extended an invitation to Berger and Wyrobek to further their development within Willow Garage’s supportive environment.

Over the subsequent three years, this collaborative effort led to the creation of the PR2 robot, an advanced research platform that served as a successor to Stanford’s earlier PR1 project. Crucially, ROS was concurrently refined and expanded, solidifying its role as the foundational software framework underpinning the PR2’s sophisticated capabilities. The PR2 robot, famously showcased at events like Maker Faire Bay Area in 2011, demonstrated remarkable dexterity in navigating human environments and interacting with objects, a testament to the robust and flexible architecture provided by ROS. This period marked a significant leap forward, transforming ROS from a theoretical concept into a practical, open-source middleware that would profoundly influence the trajectory of robotics development.

Understanding ROS: Middleware, Not an OS

Hands On with ROS 2: Nodes, Topics, and Services

It is imperative to clarify that ROS, despite its name, is not a traditional "operating system" in the vein of Windows, macOS, or Linux. It does not possess a kernel for direct hardware control or memory management. Instead, ROS functions as an open-source robotics middleware framework and a comprehensive collection of libraries. Typically built atop a full-fledged operating system (most commonly Linux), ROS excels at managing multiprocessing communication and offers an extensive suite of computational libraries. A prime example is the Transform Library 2 (TF2), which is indispensable for handling complex coordinate frame transformations in robotic perception and control.

The design philosophy of ROS inherently favors scalability. While it may introduce unnecessary overhead for simple, single-purpose robotic applications like basic vacuum cleaners or maze-solving bots, its true value becomes evident in scenarios involving multiple, complex components requiring synchronous and asynchronous operation. In such large-scale projects, ROS can dramatically reduce development time and mitigate the frustrations associated with bespoke communication protocols. Its modular architecture allows different teams of engineers to work on distinct components (e.g., arms, locomotion, sensors) independently, with ROS providing the standardized glue that brings these disparate elements together.

Widespread Adoption Across Industries

Hands On with ROS 2: Nodes, Topics, and Services

The impact of ROS extends far beyond academic research labs. It has been widely adopted by industry leaders for deployment in real-world commercial robots, underscoring its robustness and reliability. Notable examples include segments of Amazon’s advanced warehouse robotics fleet, which leverage ROS for coordinating complex material handling tasks. Avidbots, a pioneer in commercial-grade cleaning robots, also integrates ROS into its systems for autonomous navigation and operation. Similarly, Omron’s TM series manipulator arms, designed for industrial automation, benefit from ROS’s flexible communication capabilities. This broad industrial acceptance validates ROS as a practical and effective solution for complex robotic applications, from logistics and manufacturing to service and exploration.

The Evolution to ROS 2: Addressing New Challenges

The initial iteration of ROS, while revolutionary, faced certain technical limitations in its underlying messaging layers, particularly concerning real-time performance, security, and multi-robot deployments. Recognizing these emerging needs, the ROS team initiated the development of ROS 2 in 2014. This second generation was designed from the ground up to overcome the shortcomings of its predecessor, offering enhanced capabilities for embedded systems, improved security features, and native support for Windows. The transition marked a significant architectural shift, moving away from ROS 1’s centralized "roscore" to a more distributed architecture based on the Data Distribution Service (DDS) standard, enabling greater resilience and scalability.

Hands On with ROS 2: Nodes, Topics, and Services

ROS 1 officially reached its end-of-life (EOL) status on May 31, 2025, meaning it no longer receives updates or support. ROS 2 has comprehensively superseded it, establishing itself as the de facto standard for new robotics development. The ROS team maintains a regular release cycle, typically delivering a new distribution annually. Each distribution is a versioned collection of ROS packages, characterized by whimsical, alliterative names, often featuring a turtle, and progressing alphabetically. For instance, the latest release, Kilted Kaiju, debuted in May 2025. However, for long-term stability and support, Jazzy Jalisco remains a popular choice, boasting long-term support (LTS) until 2029. Each ROS distribution is meticulously pinned to specific versions of operating systems to ensure the proper functioning of its underlying libraries. Jazzy Jalisco, for example, officially supports Ubuntu 24.04 and Windows 10 (requiring Visual Studio 2019 for the latter).

Setting Up the Development Environment: A Docker Approach

For real-world robotic applications that interface directly with motors and sensors, installing Ubuntu on a dedicated machine like a small laptop or a single-board computer (e.g., Raspberry Pi) is often preferred. However, for introductory tutorials and development, a pre-configured Docker image offers an excellent, platform-independent solution. Docker encapsulates the entire development environment, pinning various package versions and ensuring consistent functionality across different host operating systems, including macOS, Windows, and most Linux distributions.

Hands On with ROS 2: Nodes, Topics, and Services

To begin, users need to install Docker Desktop from docker.com, accepting the default settings. Following this, the ROS Docker image and an example repository must be obtained. This involves navigating to the introduction-to-ros GitHub repository, downloading the ZIP archive, and unzipping it to a chosen location on the host computer.

The next step involves building the Docker image from the command line. After navigating to the introduction-to-ros/ directory, the command docker build -t env-ros2 . is executed. This process, which can take some time due to the image containing a full Ubuntu 24.04 instance with a graphical interface, creates a containerized environment.

Once the image is built, it can be run using specific commands tailored to the host operating system. For macOS or Linux, the command is:
docker run --rm -it -e PUID=$(id -u) -e PGID=$(id -g) -p 22002:22 -p 3000:3000 -v “$PWD/workspace:/config/workspace” env-ros2
For Windows (PowerShell), the command differs slightly:
docker run --rm -it -e PUID=$(wsl id -u) -e PGID=$(wsl id -g) -p 22002:22 -p 3000:3000 -v “$PWDworkspace:/config/workspace” env-ros2

Hands On with ROS 2: Nodes, Topics, and Services

Successful execution will display an Xvnc KasmVNC welcome message in the terminal. Ignoring minor warnings, users can then access a full Ubuntu desktop environment by navigating to https://localhost:3000 in their web browser. This env-ros2 Docker image is based on the XFCE Ubuntu webtop image maintained by the LinuxServer.io group, providing a robust and accessible environment for ROS 2 development.

Core Communication Paradigms: Nodes, Topics, and Services

In ROS 2, applications are meticulously structured into a series of nodes. These are independent, executable processes, each dedicated to a specific task within the robotic system, such as reading sensor data, executing complex algorithms, or driving motors. Each node operates within its own runtime environment, communicating with other nodes through well-defined mechanisms.

Hands On with ROS 2: Nodes, Topics, and Services

Topics: The Publish-Subscribe Model

The primary communication method in ROS 2 is the topic, which operates on a publish/subscribe messaging model. In this asynchronous paradigm, a node acting as a publisher transmits data to a named topic. The underlying ROS system efficiently handles the delivery of this message to all nodes that have subscribed to that particular topic. This model is ideal for continuous data streams, such as real-time sensor readings (e.g., LiDAR scans, camera feeds), motor encoder values, or robot status updates. The beauty of topics lies in their decoupling of publishers from subscribers; they don’t need to know about each other’s existence directly, only the topic name.

ROS 2 nodes can be developed in various programming languages. Out of the box, Python and C++ are officially supported, offering flexibility based on performance requirements and development speed. C++ is typically chosen for low-level drivers and performance-critical processes, while Python, with its faster development cycles and extensive libraries (e.g., OpenCV for vision processing, PyTorch/TensorFlow for machine learning), is favored for prototyping and complex algorithmic tasks. Critically, ROS enables seamless communication between nodes written in different languages, fostering interoperability within heterogeneous robotic systems.

Hands On with ROS 2: Nodes, Topics, and Services

Nodes are fundamentally built upon object-oriented programming principles, instantiated as subclasses of the ROS-provided Node class. This inheritance grants access to core ROS functionalities. Within these nodes, publishers and subscribers are created as object instances. A single custom node can thus host any number of publishers and subscribers, enabling multifaceted communication.

For illustrative purposes, consider a scenario where a simple subscriber node listens on a topic named my_topic and prints incoming messages to the console. Concurrently, a publisher node transmits a "Hello world" string, appended with a counter value, to the same topic twice per second. This demonstrates the basic yet powerful real-time data flow facilitated by topics.

Building a ROS Package and Running the Topic Example

Hands On with ROS 2: Nodes, Topics, and Services

A workspace in ROS 2 is a directory dedicated to storing and building ROS packages. A package, the fundamental unit of code organization, contains one or more nodes (parts of the robot application). When nodes within a package are built, required libraries, artifacts, and executables are placed in the install/ directory of the workspace, while intermediate files and logs reside in build/ and log/ respectively.

To create a new package for Python nodes, one navigates to the src/ directory within the workspace and executes ros2 pkg create --build-type ament_python my_first_pkg. This command generates the necessary directory structure and template files.

The core logic for the publisher and subscriber nodes is implemented in Python files, my_publisher.py and my_subscriber.py, located within the my_first_pkg/my_first_pkg/ directory. The MinimalPublisher class, derived from the Node class, creates a publisher object and a timer that periodically invokes a callback function to send messages. Similarly, the MinimalSubscriber class instantiates a subscription object with a callback that processes received messages. The rclpy (ROS Client Library for Python) library is essential for initializing ROS functionality within these Python nodes.

Hands On with ROS 2: Nodes, Topics, and Services

Before building, two configuration files require modification: package.xml and setup.py. The package.xml file, the package manifest, lists metadata and dependencies. The rclpy dependency must be explicitly added to ensure proper build and runtime linking. The setup.py file, generated during package creation, defines the entry_points for executables. Here, the console_scripts key is updated to declare my_publisher and my_subscriber as executable entry points, linking them to their respective main functions.

With the code and configuration in place, the package is built using the colcon build --packages-select my_first_pkg command from the workspace directory. Colcon is the standard build tool for ROS 2, managing the compilation and installation processes.

To observe the topic communication, three terminal windows are typically opened within the Docker container. In the first terminal, the workspace environment is sourced (source install/setup.bash), and the publisher node is launched (ros2 run my_first_pkg my_publisher). The second terminal follows the same setup to launch the subscriber (ros2 run my_first_pkg my_subscriber). Messages "Hello world: [count]" will appear in both terminals, demonstrating successful publish-subscribe communication. The third terminal can then run rqt_graph, a graphical interface that visualizes the active nodes and their topic connections, providing an invaluable debugging tool for complex robotic systems.

Hands On with ROS 2: Nodes, Topics, and Services

Services: The Client-Server Request-Response Model

While topics excel at broadcasting continuous data, a different communication paradigm is needed when one node requires a direct, one-time request and expects a specific response from another. This is where services come into play, implementing a client/server model. In this synchronous communication pattern, a server node waits for incoming requests, while a client node sends a request to a particular server and blocks, awaiting a response.

Services are ideal for actions that require a definitive outcome, such as setting a robot’s parameter, triggering a specific motion (e.g., "move forward by X meters"), or requesting a one-time data update (e.g., "what is the current battery level?"). The synchronous nature ensures that the client knows precisely when its request has been processed and a response has been received.

Hands On with ROS 2: Nodes, Topics, and Services

Implementing and Running Service Examples

Similar to topics, client and server nodes are created within the my_first_pkg/my_first_pkg/ directory as my_server.py and my_client.py. The MinimalServer class, a subclass of Node, instantiates a service named add_ints. It specifies an interface, such as AddTwoInts (imported from example_interfaces.srv), which defines the structure of the request (e.g., two integers a and b) and the response (e.g., a sum sum). A callback method, _server_callback(), is attached to the service to process incoming requests, perform the specified operation (e.g., adding a and b), and return the response.

The MinimalClient class creates a client object, also specifying the AddTwoInts interface and the service name add_ints. A timer periodically triggers a callback that constructs a request with random integers, sends it to the server, and stores the expected response in a future object. A future acts as a placeholder for a result that will become available asynchronously. A callback attached to this future is executed once the response is received, allowing the client to access and print the sum.

Hands On with ROS 2: Nodes, Topics, and Services

As with topic nodes, my_client and my_server must be added to the console_scripts in my_first_pkg/setup.py and the package rebuilt using colcon build.

To run the service example, two terminal windows are opened. In the first, the server node is launched (ros2 run my_first_pkg my_server). In the second, the client node is run (ros2 run my_first_pkg my_client). The server terminal will display the received request (the two random integers), and the client terminal will show the calculated sum returned by the server, confirming the successful client-server interaction. Unlike topics, rqt_graph will only show the active client and server nodes, without explicitly visualizing the service connections.

The Mighty Middleware: Accelerating Robotics Innovation

Hands On with ROS 2: Nodes, Topics, and Services

The concepts of nodes, topics, and services, though seemingly fundamental, form the bedrock of ROS. At its heart, ROS is a powerful middleware messaging layer, rather than a collection of drivers or sensor libraries. It addresses the critical challenge of scaling software projects in large, complex robotics by providing a standardized, robust, and flexible communication infrastructure. While its overhead may be excessive for trivial projects, its utility in multi-component, multi-disciplinary robotic endeavors is immense.

This brief introduction merely scratches the surface of ROS’s capabilities. Beyond its sophisticated messaging system, ROS offers a rich ecosystem of libraries and tools, including TF2 for coordinate transformations, diagnostic tools for system monitoring, and advanced visualizers for debugging and understanding complex robot behaviors. The framework is designed to facilitate the entire robot software development lifecycle, from initial prototyping to deployment and maintenance.

The ongoing development of ROS, driven by a vibrant global open-source community, continues to push the boundaries of what is possible in robotics. Its widespread adoption across academia and industry has significantly lowered the entry barrier for new developers and researchers, fostering innovation and collaboration. As robots become increasingly sophisticated and pervasive in our daily lives, ROS will undoubtedly continue to play a pivotal role in shaping the future of automation, autonomous systems, and human-robot interaction across diverse fields such as logistics, healthcare, exploration, and smart manufacturing.