Most ROS 2 bugs are not algorithm bugs. They are messages sent on the wrong channel. Topics, services and actions look interchangeable when you are learning, then one of them blocks your control loop at the worst moment. Each exists because it solves a different timing and feedback problem.
This guide explains what each pattern is for, the QoS settings that silently drop messages, and how to debug a system where nodes are running but nothing arrives.
Three patterns, three jobs
| Pattern | Shape | Use it for | Do not use it for |
|---|---|---|---|
| Topic | Publisher sends, any number of subscribers receive, no reply | Sensor streams, odometry, status, commands at a steady rate | Anything that needs a guaranteed answer |
| Service | Client calls, server replies once | Quick queries, mode changes, calibration triggers | Long tasks, anything that must be cancellable |
| Action | Client sends a goal, receives feedback, gets a final result | Navigation, docking, arm moves, anything taking seconds or minutes | High-rate data or simple state reads |
The test is simple: if the receiver must reply before the sender can continue, it is not a topic. If the task can take longer than a fraction of a second, it should not be a service.
Topics: the default for streaming data
A topic is a named bus. Publishers write, subscribers read, and neither knows how many of the other exist. This decoupling is why ROS 2 systems scale: a LiDAR driver publishes /scan without caring whether one node or five consume it.
Commands are also topics when they are continuous. A velocity command published at 20 Hz is a topic, not a service, because the consumer wants the latest value and does not want to reply to every message.
ros2 topic list
ros2 topic info /scan --verbose
ros2 topic echo /scan --once
ros2 topic hz /odom
ros2 topic bw /camera/image_rawros2 topic hz and ros2 topic bw answer the two questions that matter first: is data arriving, and is it arriving at the rate and size you expect. A camera topic at 0.4 Hz is a driver problem, not a perception problem.
Services: one question, one answer
A service is a remote function call with a typed request and typed response. It is the right choice for short, bounded operations: read a parameter set, trigger a calibration, clear an error, switch a mode.
The trap is using a service for work that takes time. The client blocks waiting for the response, the server may be busy, and there is no feedback and no cancellation. A service that takes eight seconds to return will make your operator interface feel broken even when it is working correctly.
ros2 service list -t
ros2 service type /robot/clear_faults
ros2 service call /robot/clear_faults std_srvs/srv/TriggerServices are also stateful in a way that is easy to forget: if the server node restarts, pending calls fail. Code that treats a service call as reliable needs a timeout and a retry, not a bare call.
Actions: long tasks with feedback
An action is built on topics and services but exposes the pattern every mobile robot needs: send a goal, receive progress, cancel if conditions change, and get a final result. Navigation, docking, arm trajectories and palletising all belong here.
| Action part | What it carries | Example |
|---|---|---|
| Goal | What to achieve | Pose to reach, pallet pattern to build |
| Feedback | Progress while running | Distance remaining, current waypoint |
| Result | Final outcome | Success, failure code, final pose |
| Cancel | Stop request | Operator presses stop or a person enters the zone |
ros2 action list -t
ros2 action info /navigate_to_pose
ros2 action send_goal /navigate_to_pose nav2_msgs/action/NavigateToPose "{pose: {header: {frame_id: map}, pose: {position: {x: 2.0, y: 1.0}}}}" --feedbackThe --feedback flag is the difference between watching a robot work and guessing whether it is still working. Any operator interface you build should subscribe to feedback rather than polling a status topic.
QoS: the setting that silently drops messages
ROS 2 adds Quality of Service profiles, and mismatched profiles are the most common reason a publisher and subscriber exist but never connect. The default for topics is reliable, which is fine for most data but wrong for high-rate sensor streams on a congested network.
| Setting | Options | Practical rule |
|---|---|---|
| Reliability | Reliable / best effort | Reliable for commands and state, best effort for cameras and LiDAR |
| Durability | Volatile / transient local | Transient local for maps and static configuration |
| History | Keep last N / keep all | Keep last with a small depth unless replaying data |
| Depth | Queue size | 1 for commands, 5–10 for sensor data |
If ros2 topic info --verbose shows publishers and subscribers but ros2 topic echo shows nothing, check QoS before rewriting code. A best-effort subscriber will never receive from a reliable publisher in some middleware configurations, and a transient-local map will never reach a volatile subscriber.
How the three fit in one robot
- LiDAR and cameras publish on topics at 10–30 Hz with best-effort QoS.
- Odometry and joint states publish on topics, reliable, small messages.
- Velocity commands publish on a topic at a fixed rate; the base stops if they stop arriving.
- Navigation is an action: goal, feedback, cancel, result.
- Mode changes and fault clearing are services, called from an operator interface with a timeout.
When a robot behaves strangely, check the channel type first. A missed service call looks like a frozen button; a dropped topic looks like a sensor failure; an action that never completes looks like a planner problem. Naming the pattern usually narrows the fault within minutes.
Mistakes that cost debugging days
| Mistake | Symptom | Fix |
|---|---|---|
| Service for a long task | UI freezes, calls time out | Convert to an action |
| Topic for a command that needs acknowledgement | Robot misses commands silently | Use a service or action |
| Reliable QoS on a camera | Latency grows, buffers fill | Best effort with depth 1–5 |
| No timeout on service calls | Node hangs when server restarts | Add a timeout and a retry policy |
| Custom message for a simple flag | Build and versioning overhead | Use std_msgs or std_srvs |
| One global namespace for two robots | Topics collide, commands cross | Namespaces per robot |
A ten-minute debugging order
ros2 node list— are both ends running?ros2 topic info /topic --verbose— do publisher and subscriber see each other, and do QoS profiles match?ros2 topic hz /topic— is data arriving at the expected rate?ros2 topic echo /topic --once— is the content sane?ros2 service list -torros2 action list -t— does the interface exist under the name you expect?ros2 doctor— any environment or middleware warnings?
Related: ROS 2 for beginners, ROS 2 launch files, Nav2 tutorial, URDF tutorial, ROS 2 vs ROS 1.
What is the difference between a topic and a service in ROS 2?
A topic is a one-way stream that any number of subscribers can read without replying. A service is a request that waits for a single response. Use topics for continuous data and services for short, bounded queries.
When should I use an action instead of a service?
When the task takes more than a fraction of a second, needs progress feedback, or must be cancellable. Navigation, docking and arm moves are actions; clearing a fault is a service.
Why does ros2 topic echo show nothing when nodes are running?
Usually a QoS mismatch, a namespace or topic name difference, or the publisher not actually publishing. Check ros2 topic info –verbose, then compare reliability and durability settings.
What QoS should a camera use in ROS 2?
Best effort with a small queue, usually depth 1 to 5. Reliable delivery on a high-rate image stream causes latency to grow when the network or subscriber falls behind.
Do actions use topics and services internally?
Yes. An action is built from a goal service, a result service and feedback topics, wrapped in a client-server pattern you normally interact with through the action API.
When the publisher lives on a microcontroller instead of a Linux host, micro-ROS is the way to join the same graph.
To inspect real topic traffic rather than guess, record it with ros2 bag and replay it later.
If a topic connects but no messages arrive, the cause is usually QoS. The QoS tutorial covers reliability and durability compatibility in detail.
Hardware plugins skip topics entirely, as the hardware interface tutorial shows.
When the built-in types do not carry the fields you need, define your own with ROS 2 custom messages and interfaces.
Sources and further reading
- ROS 2 beginner client library tutorials — publishers, subscribers, services and actions.
- ROS 2 QoS settings — reliability, durability and history explained.
- ROS 2 design documents — why the communication model changed from ROS 1.
- Nav2 documentation — a production example of actions used for navigation.


