The Publish-Subscribe Pattern
If you learn one communication pattern for robotics, make it publish-subscribe (pub/sub). It's used in virtually every robot middleware, including DDS, MQTT, and many other frameworks. Let's understand it from the ground up.
The Core Idea
Pub/sub has three concepts:
- Topic — a named channel (like "/camera/rgb" or "/cmd_vel")
- Publisher — a node that sends messages to a topic
- Subscriber — a node that receives messages from a topic
A publisher writes messages to a topic. Any number of subscribers can listen to that topic. The publisher doesn't know who's listening — it just publishes.
Why Pub/Sub Is Powerful
1. Decoupling
The camera node doesn't import, reference, or depend on the detector. It just publishes to a topic name. You can:
- Add a new subscriber (a logger, a recorder, a second detector) without touching the camera code
- Replace the camera with a simulated camera that publishes fake images — the detector can't tell the difference
- Run the detector on a different machine
2. Many-to-Many
A single topic can have:
- Multiple publishers — two cameras publishing to "/camera/rgb"
- Multiple subscribers — a detector AND a logger both listening to "/camera/rgb"
- Any combination — no special configuration needed
3. Asynchronous
Publishers and subscribers run at their own speed. The camera publishes at 30Hz, but the detector might only process at 10Hz. That's fine — the detector just gets the latest message when it's ready (or queues them up).
The Anatomy of a Topic
Every topic has:
| Property | Example | Purpose |
|---|---|---|
| Name | /camera/rgb | Unique identifier, usually hierarchical |
| Type | Image | The message format (fields and their types) |
| QoS | Reliable / Best-Effort | Delivery guarantees |
Topic Naming
Topics use a hierarchical naming convention with / separators:
/camera/rgb → RGB camera image
/camera/depth → Depth image
/lidar/scan → LiDAR point cloud
/perception/objects → Detected objects
/planning/path → Planned path
/cmd_vel → Velocity commands to motors
/diagnostics/cpu → CPU usage stats
Good naming makes the system self-documenting. Anyone can look at the topic list and understand what data flows where.
Name topics by what they carry, not who produces them. Use /camera/rgb instead of /camera_node/output. This way, you can swap the camera hardware without renaming topics.
Quality of Service (QoS)
Not all data is equally important. A camera frame can be dropped — the next one arrives in 33ms. But a "stop immediately" emergency command must never be lost.
QoS policies let you configure this per-topic:
| QoS Policy | Behavior | Use Case |
|---|---|---|
| Best-Effort | Drop messages if subscriber is slow | High-frequency sensor data (cameras, LiDAR) |
| Reliable | Retry until message is delivered | Commands, configuration, infrequent updates |
| Keep Last N | Only buffer the N most recent messages | Sensor data where only the latest matters |
| Transient Local | New subscribers get the last published value | Configuration, map data, static transforms |
Most sensor data uses Best-Effort + Keep Last 1. This means: always have the latest data, don't waste time on old frames. Control commands typically use Reliable delivery to ensure nothing is missed.
A Common Mistake: Topic Explosion
Beginners sometimes create too many topics:
/camera/rgb/raw
/camera/rgb/compressed
/camera/rgb/undistorted
/camera/rgb/resized_640x480
/camera/rgb/resized_320x240
This creates confusion. Better approaches:
- Use one topic per semantic data stream (
/camera/rgbfor the main output) - Use parameters to configure whether the output is compressed or not
- Create secondary topics only when genuinely different consumers need different formats
What's Next?
Pub/sub isn't the only communication pattern. In the next lesson, we'll compare it with point-to-point communication and learn when each pattern is the better choice.