Robotics Middleware Advanced¶
When you'd use this
Build robot software with ROS 2 — nodes, topics, services and Python.
Connect robot components with middleware like ROS for messaging, control, and sensor integration.
What you'll learn¶
- What robotics middleware solves
- ROS 2 nodes, topics, and the pub/sub model
- Write publisher and subscriber nodes in Python (
rclpy) - Services vs topics
- How sensors, control, and actuators connect
This topic requires a ROS 2 installation
The examples use ROS 2's Python client library rclpy, which needs a ROS 2 distribution installed (Humble, Jazzy, etc.) and isn't part of standard Python — so they aren't run-verified here. They follow the documented rclpy API. The concepts (nodes, pub/sub) mirror the tested event-bus from Event-driven Architecture.
The problem middleware solves¶
The problem middleware solves — a key concept in Robotics Middleware.
A robot is many components that must cooperate: cameras, LIDAR, motors, a planner, a controller. Wiring them together directly — each part knowing about every other — is unmanageable. Robotics middleware provides the plumbing: a standard way for components to find each other and exchange messages, so you build the robot from independent, reusable pieces.
ROS (Robot Operating System) — really a middleware and toolset, not an OS — is the dominant framework. ROS 2 is the modern version (production-ready, real-time-friendly, no central master). Its core abstraction is a graph of nodes that communicate over topics.
┌─────────────────── ROS 2 graph ───────────────────┐
│ │
[camera node] ──/image──▶ [detector node] ──/objects──▶ [planner node]
│ │
[lidar node] ──/scan───▶ [ ... ] /cmd_vel──▶ [motor node]
└─────────────────────────────────────────────────────┘
nodes publish/subscribe to named topics
Nodes, topics, and pub/sub¶
Robot components as nodes exchanging messages over named topics.
- Node — an independent process doing one job (read the camera, plan a path, drive the motors).
- Topic — a named channel (
/scan,/cmd_vel) carrying a stream of typed messages. - Publisher / Subscriber — a node publishes to a topic; any node subscribes to receive. Publishers and subscribers don't know about each other — exactly the decoupling of an event bus, distributed across processes.
This is publish/subscribe, the same pattern as Event-driven Architecture — a node announces data on a topic and moves on; interested nodes react.
A publisher node¶
Send sensor/command data onto a topic.
rclpy is ROS 2's Python client library. A node that publishes a counter every second:
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class TalkerNode(Node):
def __init__(self):
super().__init__("talker")
self.pub = self.create_publisher(String, "chatter", 10)
self.count = 0
self.create_timer(1.0, self.tick) # call tick() every 1s
def tick(self):
msg = String()
msg.data = f"hello {self.count}"
self.pub.publish(msg)
self.get_logger().info(f"publishing: {msg.data}")
self.count += 1
def main():
rclpy.init()
rclpy.spin(TalkerNode()) # process callbacks until shutdown
rclpy.shutdown()
A subscriber node¶
React to messages arriving on a topic.
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class ListenerNode(Node):
def __init__(self):
super().__init__("listener")
self.create_subscription(String, "chatter", self.on_message, 10)
def on_message(self, msg):
self.get_logger().info(f"received: {msg.data}")
def main():
rclpy.init()
rclpy.spin(ListenerNode())
rclpy.shutdown()
Run both (in separate terminals) and the listener prints each message the talker sends — received: hello 0, received: hello 1, … — even though neither node references the other. They meet only through the chatter topic. The 10 argument is the queue depth (how many messages to buffer).
Topics vs services vs actions¶
Streaming vs request/response vs long-running goals in ROS.
ROS 2 offers three communication styles for different needs:
| Mechanism | Style | Use for |
|---|---|---|
| Topic | One-way stream (pub/sub) | Continuous data: sensor readings, velocity commands |
| Service | Request/response (like a function call) | One-off queries: "what's the battery level?" |
| Action | Long-running goal with feedback | Tasks that take time: "navigate to X", with progress + cancel |
Rule of thumb: topics for streams, services for quick request/reply, actions for goals that take time and need feedback or cancellation.
How it fits a real robot¶
How these pieces compose into perception-control-actuation.
A typical robot software stack layers these pieces:
Sensors → perception → planning → control → actuators
(/scan, (detect (path (/cmd_vel) (motors,
/image) objects) planning) servos)
Each stage is one or more nodes exchanging messages on topics. ROS 2 also brings a rich toolset: rviz (3D visualization), ros2 bag (record/replay all messages — invaluable for debugging and testing offline), simulation via Gazebo, and coordinate-frame tracking (tf2). The Hardware Simulation idea applies here: develop and test against a simulated robot, then deploy to the real one.
Record everything with ros2 bag
Because all communication flows through topics, you can record the entire message stream and replay it later. That turns a hard-to-reproduce field bug into a repeatable test — one of ROS's biggest practical wins.
Practice exercises¶
- Modify the talker to publish a
sensor_msgs/Temperaturemessage instead of a string. - Write a node that subscribes to
chatterand republishes an uppercased version to a new topic — a simple processing node. - Sketch (in words or code) a ROS 2 service that returns a robot's battery percentage on request.
- Explain why pub/sub decoupling lets you swap the camera node for a simulated one without touching the detector node.
- Describe how you'd use
ros2 bagto debug a navigation failure that only happens outdoors.
💬 Discussion
Have a question about this topic? Found an error? Share your thoughts below.