Skip to main content

ROS-II Fundamentals: Middleware Architecture

Overview

Robot Operating System 2 (ROS 2) is a flexible framework for writing robot software that provides the services you would expect from an operating system, including hardware abstraction, device drivers, libraries, visualizers, message-passing, package management, and more. Unlike traditional operating systems, ROS 2 is not a single monolithic piece of software but a collection of tools, libraries, and conventions that facilitate the creation of complex and robust robot behavior across a heterogeneous cluster of processors.

Architecture and Design Philosophy

Client Library Architecture

ROS 2 uses a client library architecture that abstracts the underlying middleware implementation. This design allows for different middleware implementations while maintaining a consistent API for users:

┌─────────────────┐    ┌─────────────────┐
│ Application │ │ Application │
├─────────────────┤ ├─────────────────┤
│ rclcpp/rclpy │ │ rclcpp/rclpy │
├─────────────────┤ ├─────────────────┤
│ rmw layer │ │ rmw layer │
├─────────────────┼────┼─────────────────┤
│ DDS Impl. │ │ DDS Impl. │
└─────────────────┘ └─────────────────┘

The architecture consists of:

  • Client Libraries (rclcpp, rclpy): C++ and Python client libraries that provide the ROS 2 API
  • ROS Middleware (rmw): Abstraction layer that interfaces with the underlying middleware
  • DDS Implementation: Data Distribution Service that handles the actual message passing

DDS-Based Communication

ROS 2 uses Data Distribution Service (DDS) as its underlying communication middleware, providing:

  • Real-time Performance: Deterministic message delivery with bounded latency
  • Scalability: Support for large numbers of nodes and topics
  • Reliability: Quality of Service (QoS) policies for message delivery guarantees
  • Distributed Architecture: Nodes can run on different machines without special configuration

Core Concepts

Nodes

A node is an executable that uses ROS 2 to communicate with other nodes. In ROS 2, nodes are more isolated than in ROS 1:

#include "rclcpp/rclcpp.hpp"

class MinimalPublisher : public rclcpp::Node
{
public:
MinimalPublisher()
: Node("minimal_publisher"), count_(0)
{
publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
timer_ = this->create_wall_timer(
500ms, std::bind(&MinimalPublisher::timer_callback, this));
}

private:
void timer_callback()
{
auto message = std_msgs::msg::String();
message.data = "Hello, world! " + std::to_string(count_++);
RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
publisher_->publish(message);
}
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
size_t count_;
};

Topics and Messages

Topics are named buses over which nodes exchange messages. ROS 2 uses a more robust topic discovery mechanism:

// Publisher with QoS configuration
auto publisher = this->create_publisher<std_msgs::msg::String>(
"topic_name",
rclcpp::QoS(rclcpp::KeepLast(10)).reliability(RMW_QOS_POLICY_RELIABILITY_RELIABLE)
);

// Subscriber with matching QoS
auto subscription = this->create_subscription<std_msgs::msg::String>(
"topic_name",
rclcpp::QoS(rclcpp::KeepLast(10)).reliability(RMW_QOS_POLICY_RELIABILITY_RELIABLE),
[this](const std_msgs::msg::String::SharedPtr msg) {
RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg->data.c_str());
});

Services and Actions

ROS 2 introduces Actions as a new communication pattern for long-running tasks:

// Action server
class FibonacciActionServer : public rclcpp::Node
{
public:
FibonacciActionServer()
: Node("fibonacci_action_server")
{
using namespace std::placeholders;

this->action_server_ = rclcpp_action::create_server<Fibonacci>(
this->get_node_base_interface(),
this->get_node_clock_interface(),
this->get_node_logging_interface(),
this->get_node_waitables_interface(),
"fibonacci",
std::bind(&FibonacciActionServer::handle_goal, this, _1, _2),
std::bind(&FibonacciActionServer::handle_cancel, this, _1),
std::bind(&FibonacciActionServer::handle_accepted, this, _1));
}

private:
rclcpp_action::Server<Fibonacci>::SharedPtr action_server_;
};

Quality of Service (QoS) Policies

QoS policies allow fine-tuning of communication behavior:

Reliability Policy

  • Reliable: All messages are delivered (at the cost of latency)
  • Best Effort: Messages may be dropped (lower latency)

Durability Policy

  • Transient Local: Publishers send recent messages to new subscribers
  • Volatile: No message persistence for late-joining subscribers

History Policy

  • Keep Last: Maintain a fixed number of most recent messages
  • Keep All: Maintain all messages (use with caution)

Depth Policy

Controls the number of messages in the queue when using Keep Last history policy.

Lifecycle Management

ROS 2 introduces lifecycle nodes for better system management:

class LifecyclePublisher : public rclcpp_lifecycle::LifecycleNode
{
public:
LifecyclePublisher() : rclcpp_lifecycle::LifecycleNode("lifecycle_publisher") {}

private:
rclcpp_lifecycle::LifecyclePublisher<std_msgs::msg::String>::SharedPtr pub_;

rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
on_configure(const rclcpp_lifecycle::State &)
{
pub_ = this->create_publisher<std_msgs::msg::String>("lifecycle_chatter", 10);
RCLCPP_INFO(get_logger(), "Publisher created");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
}

rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
on_activate(const rclcpp_lifecycle::State &)
{
pub_->on_activate();
RCLCPP_INFO(get_logger(), "Publisher activated");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
}
};

Parameter System

ROS 2 has an improved parameter system with dynamic reconfiguration:

// Declare parameters with default values
this->declare_parameter("param_name", "default_value");

// Get parameter value
std::string param_value;
this->get_parameter("param_name", param_value);

// Set parameters from command line or launch files
auto parameters_client = std::make_shared<rclcpp::AsyncParametersClient>(this);
parameters_client->set_parameters({rclcpp::Parameter("param_name", "new_value")});

Launch System

ROS 2 uses Python-based launch files for complex system management:

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
return LaunchDescription([
Node(
package='demo_nodes_cpp',
executable='talker',
name='talker',
parameters=[
{'param_name': 'param_value'}
],
remappings=[
('original_topic', 'remapped_topic')
]
),
Node(
package='demo_nodes_cpp',
executable='listener',
name='listener'
)
])

Security Features

ROS 2 includes built-in security capabilities:

Authentication

  • Identity verification of nodes
  • Certificate-based authentication

Authorization

  • Access control lists for topics and services
  • Role-based permissions

Encryption

  • Message payload encryption
  • Secure communication channels

Migration from ROS 1

Key differences from ROS 1:

  • Middleware: DDS-based instead of custom ROS 1 transport
  • API Changes: New client libraries with improved design
  • Quality of Service: Configurable communication behavior
  • Lifecycle Management: Built-in node lifecycle management
  • Security: Native security features
  • Real-time Support: Better real-time capabilities
  • Cross-platform: Improved Windows and macOS support

Best Practices

Node Design

  • Keep nodes focused on single responsibilities
  • Use composition for complex systems
  • Implement proper error handling
  • Follow naming conventions

Communication

  • Choose appropriate QoS policies
  • Use services for request-response patterns
  • Use actions for long-running tasks
  • Avoid large message sizes

Performance

  • Use intra-process communication when possible
  • Optimize message serialization
  • Consider message frequency and size
  • Monitor network utilization

ROS 2 provides the robust middleware foundation needed for complex physical AI systems, enabling reliable communication between diverse hardware and software components in robotic applications.