ExplorRobo

ROS 2 topics vs services vs actions

By ExplorRobo Editorial · · 11 min read

Three interfaces, one framework

Nodes in ROS 2 exchange data through one of three interfaces: topics, services and actions. The documentation summarises the split in a single page: topics for continuous data streams, services for synchronous request and response interactions, and actions for long-running tasks with feedback (interfaces).

All three are described with the same interface definition language, and ROS 2 generates source code for each of them from those definitions (About interfaces). The choice between them is therefore a design decision rather than a technical limitation, and it is one of the harder decisions to reverse. A service that blocks a control loop, or a subscription that silently receives nothing, are usually symptoms of picking the wrong interface or the wrong settings.

If the framework itself is new to you, start with What is ROS 2?, which covers nodes, the middleware layer and the tooling.

Topics

A topic is a named bus. Publishers and subscribers find each other through that common name, and the documentation is explicit that there may be zero or more publishers and zero or more subscribers on any topic (About topics). When data is published to the topic by any publisher, all subscribers receive it. Nothing in the model requires a subscriber to exist at all, which is what makes the pattern a bus rather than a connection.

The bus is anonymous: when a subscriber receives a message, it does not generally know or care which publisher sent it, although it can find out. The practical benefit is that either side can be swapped out without touching the rest of the system.

It is also strongly typed, in two senses. The type of each field is enforced, and the semantics of the core types are defined. An IMU message carries a three dimensional vector for angular velocity, specified in radians per second, and the documentation notes that other interpretations should not be placed into that message. Tools rely on this: ros2 topic list -t prints the type next to each name so you can tell which interface a running system actually uses.

Because subscribers are additive, observing a topic is cheap. ros2 bag record creates a new subscriber to whatever topic you name without interrupting the flow of data to the rest of the system, and the same holds for ros2 topic echo and for visualisation. Sensor streams, joint states, odometry, transforms and logs all fit this pattern.

Services

A service is a remote procedure call: one node asks another to perform a computation and return a result. The message definition reflects that shape, with request fields in the top half of the file and response fields below a written separator line.

The documented constraint is blunt. Services are expected to return quickly, because the client is generally waiting on the result, and they should never be used for longer running processes, in particular processes that might need to be preempted for exceptional situations (About services). If the work has an unbounded duration, it is a candidate for an action.

There should only ever be one service server per service name. If several servers share a name, it is undefined which one receives a client request. The client side carries no such restriction: any number of clients can call the same service.

Actions

An action is a long-running remote procedure call with feedback and the ability to cancel or preempt the goal. The canonical example in the documentation is a high-level state machine telling the navigation subsystem to travel to a waypoint. That may take seconds or minutes, the navigation subsystem can report how far along it is, and the caller can cancel the goal in between (About actions).

The trade is overhead. The documentation notes that actions are expected to be long running because there is overhead in setting up and monitoring the connection, and recommends a service when a short call is all that is needed. As with services, there should be only one action server per action name, while any number of clients may send goals to it.

What an action is made of

Actions are built on topics and services, and the action design specification spells out the machinery: under the hood, an action is made up of three services and two topics (action design).

The three services are send goal, cancel goal and get result. The two topics carry goal status and feedback. Names are generated by prefixing the action name, giving /_action/status and /_action/feedback as topics, and /_action/send_goal, /_action/cancel_goal and /_action/get_result as services. The _action token, with its leading underscore, keeps those names hidden from casual listing while letting tools identify them.

The goal status topic exists for introspection. It is published by the server when a goal changes state, the action client does not use it, and the specification says the default Quality of Service for a DDS middleware should be transient local with a history size of one, so a late subscriber still sees the latest state. Each goal then moves through a state machine with three active states (accepted, executing, canceling) and three terminal states (succeeded, aborted, canceled). The client is the only entity responsible for generating the goal ID, which is a UUID.

Side by side

TopicsServicesActions
PatternPublish/subscribeRequest/responseGoal, feedback, result
DirectionOne-wayTwo-wayTwo-way with feedback
Typical useContinuous dataQuick queriesLong-running tasks
CancellableNoNoYes

Naming and definitions

Definitions live in msg, srv and action directories inside a package, in files with a matching extension. A type is written as package/msg/Type, package/srv/Type or package/action/Type, so geometry_msgs/msg/Twist, std_srvs/srv/Empty and turtlesim/action/RotateAbsolute are all the same kind of name applied to different interface kinds.

Message files contain fields and constants. Field names must be lowercase alphanumeric characters with underscores separating words, must start with an alphabetic character, and must not end with an underscore or contain two in a row. Constant names have to be uppercase. Any two message files concatenated with the separator are a legal service description, and a service cannot be embedded inside another service. An action file is three message declarations in one file: goal, result and feedback.

Inspecting a live system

The ros2 command line treats each interface as its own kind of entity, which is the fastest way to find out what a robot is actually doing:

To capture what those interfaces carry over time rather than watching them live, see recording and replaying ROS 2 bags with rosbag2.

  • ros2 topic list -t, then ros2 topic echo, ros2 topic info, ros2 topic hz, ros2 topic bw and ros2 topic find
  • ros2 service list -t, then ros2 service type, ros2 service info, ros2 service find and ros2 service call
  • ros2 action list -t, then ros2 action type, ros2 action info and ros2 action send_goal
  • ros2 interface show for the structure of any message, service or action type
  • ros2 node info <node> to see publishers, subscribers, service servers, service clients, action servers and action clients in one place
$ ros2 topic list -t
/parameter_events [rcl_interfaces/msg/ParameterEvent]
/rosout [rcl_interfaces/msg/Log]
/turtle1/cmd_vel [geometry_msgs/msg/Twist]
$ ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
requester: making request: turtlesim.srv.Spawn_Request(x=2.0, y=2.0, theta=0.2, name='')

response:
turtlesim.srv.Spawn_Response(name='turtle2')
$ ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"
Waiting for an action server to become available...
Sending goal:
   theta: 1.57

Goal accepted with ID: f8db8f44410849eaa93d3feb747dd444

Result:
  delta: -1.568000316619873

Goal finished with status: SUCCEEDED

The examples above come from the beginner command line tutorials for topics, services and actions.

Quality of Service is a separate decision

Each interface has a second layer of configuration that catches people out. Quality of Service profiles can be set for publishers, subscriptions, service servers and clients independently, and a connection is only made if the pair is compatible (QoS settings).

Compatibility follows a request versus offered model. A subscription requests the minimum quality it is willing to accept, a publisher offers the maximum quality it can provide, and a connection is made only when every policy in the requested profile is not more stringent than the offered one.

For reliability, a best effort publisher and a best effort subscription communicate, a reliable publisher communicates with either subscription type, but a best effort publisher and a reliable subscription do not communicate at all. For durability, a volatile publisher and a transient local subscription also fail to communicate, while a transient local publisher works with both subscription types, though a volatile subscription only sees messages published after it joined. The documentation notes that the same rules apply to service servers and clients.

This is why a topic can appear in ros2 topic list and still deliver nothing. Sensor drivers commonly publish best effort, and a subscription using a stricter default will never match it.

Common pitfalls

  • Putting real work inside a service. The client waits on the response, so anything that can take seconds or minutes, or may need to be preempted, belongs in an action.
  • Running two servers on one service or action name. It is undefined which one receives a request, so the system appears to work until it does not.
  • Expecting to cancel a service call. There is no cancellation path, and the client is already waiting. Actions exist for exactly this reason.
  • Treating a service like a queue. It is one request and one response. Repeated updates are a topic.
  • Inspecting an action through its underlying services and topics by hand. ros2 action presents the goal, feedback and result as a single unit, which is the documented intent of the tooling.
  • Forgetting that Quality of Service is negotiated per endpoint, not per topic name.

Choosing

  • Continuous data, possibly several consumers, no reply expected: a topic.
  • A question with an answer that is ready almost immediately: a service.
  • Work that takes time, benefits from progress reporting, or may need to be aborted: an action.

If the choice is between a service and an action, look at the worst case duration and whether any caller might need to abort. That usually decides it, and the cost of being wrong is a caller that blocks when it should have been able to walk away.

Sources

Frequently asked questions

What is the difference between a ROS 2 topic, a service and an action?
Topics are an anonymous publish/subscribe bus for continuous data streams such as sensor readings and robot state. Services are synchronous remote procedure calls that pair one request with one response and are expected to return quickly. Actions are long-running remote procedure calls that stream progress feedback and can be cancelled or preempted.
When should I use a service instead of an action in ROS 2?
Use a service when the caller needs an answer now and the work finishes quickly, because the client is generally waiting on the result. Use an action when the work may take many seconds or minutes, when progress feedback is useful, or when the goal might need to be cancelled or preempted.
Are ROS 2 actions built on topics and services?
Yes. The documentation states that actions are built on topics and services, and the action design specification describes an action as three services and two topics. The services are send goal, cancel goal and get result, and the topics carry goal status and feedback.
Why does my ROS 2 topic publish data but my subscription receives nothing?
Most often the Quality of Service profiles are incompatible. A subscription requests the minimum quality it will accept and a publisher offers the maximum it can provide, and a connection is only made when every requested policy is not more stringent than the offered one. A best effort publisher and a reliable subscription, or a volatile publisher and a transient local subscription, do not communicate.
Can a ROS 2 service call be cancelled?
No. Services are a request and response interaction with no cancellation path. If the operation may take a long time or a caller may need to abort it, model the interaction as an action instead, which supports cancelling or preempting a goal.

Related reading