5.8. Services and Actions#

Services and actions provide alternative methods of communication for nodes in the ROS graph for situations where the publisher-subscriber model of topics are not well-suited.

  • services are the name given to short, synchronous robot behaviors that can be done quickly, like turning on lights and switching components on or off. Services are based on a request-reply model versus the publisher-subscriber model of topics. While topics allow nodes to subscribe to data streams and get continual updates, services only provide data when they are specifically called by a client.

../_images/Service-SingleServiceClient.gif ../_images/Service-MultipleServiceClient.gif
  • actions are longer term, asynchronous, tasks that may have intermediate steps. Actions are built on topics and services, and consist of three parts: a goal, feedback, and a result. Their functionality is similar to services, except actions can be canceled. They also provide steady feedback, as opposed to services which return a single response. Actions thus correspond to a client-server model. An “action client” node sends a goal to an “action server” node that acknowledges the goal and returns a stream of feedback and a result.

../_images/Action-SingleActionClient.gif

Actions are intended for long running tasks. A classic example of an action is navigation: a robot is provided a goal position and asked to navigate to that goal. Try as the robot might, since it cannot move infinitely fast, it takes time to move to a goal and sometimes its path may become blocked.

These two primitives are the backbone of most robotic systems using ROS and learning how to use them via the command line will allow you quickly and easily command a robot to complete a task for you.

5.8.1. Finding all actions and services of all nodes#

We can use the CLI to list all available services and actions provided by all currently running ROS nodes and even to call a node’s service or an action using a single command. While typically such services and actions are called by other nodes as part of the automated workflow of the robot, having the ability to make such calls from the command line is convenient for debugging and testing.

The command line interface for services and actions are very similar, in fact they both have only four sub commands. Let’s run the action and service commands and compare them:

$ ros2 action --help
usage: ros2 action [-h]
                   Call `ros2 action <command> -h` for more detailed usage.
                   ...

Various action related sub-commands

options:
  -h, --help            show this help message and exit

Commands:
  info       Print information about an action
  list       Output a list of action names
  send_goal  Send an action goal
$ ros2 service --help
usage: ros2 service [-h] [--include-hidden-services]
                    Call `ros2 service <command> -h` for more detailed usage.
                    ...

Various service related sub-commands

options:
  -h, --help            show this help message and exit
  --include-hidden-services
                        Consider hidden services as well

Commands:
  call  Call a service
  find  Output a list of available services of a given type
  list  Output a list of available services
  type  Output a service's type

  Call `ros2 service <command> -h` for more detailed usage.

We can see that both commands have a list command that gives a list of available services or actions from all nodes in the grouph.

Tip

If you just want to know the services and actions from one particular running node, remember you can also just use the ros2 node info <node-name> command, e.g.

$ ros2 node info /turtlesim
/turtlesim
  Subscribers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /turtle1/cmd_vel: geometry_msgs/msg/Twist
  Publishers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /rosout: rcl_interfaces/msg/Log
    /turtle1/color_sensor: turtlesim/msg/Color
    /turtle1/pose: turtlesim/msg/Pose
  Service Servers:
    /clear: std_srvs/srv/Empty
    /kill: turtlesim/srv/Kill
    /reset: std_srvs/srv/Empty
    /spawn: turtlesim/srv/Spawn
    /turtle1/set_pen: turtlesim/srv/SetPen
    /turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute
    /turtle1/teleport_relative: turtlesim/srv/TeleportRelative
    /turtlesim/describe_parameters: rcl_interfaces/srv/DescribeParameters
    /turtlesim/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
    /turtlesim/get_parameters: rcl_interfaces/srv/GetParameters
    /turtlesim/list_parameters: rcl_interfaces/srv/ListParameters
    /turtlesim/set_parameters: rcl_interfaces/srv/SetParameters
    /turtlesim/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
  Service Clients:

  Action Servers:
    /turtle1/rotate_absolute: turtlesim/action/RotateAbsolute
  Action Clients:

We already saw this command and its output in the Nodes and the Graph section, but now this information should appear more familiar. We can see all the topics that the node subscribes to, as well as all topics the nodes it publishes to.

We can also see a number of “Service Servers” and “Service Clients”. It is worth noting the client and server relationship here. Since ROS may have multiple nodes running some nodes may offer services (these are servers), and other ROS nodes may call those servers (these are the clients).

5.8.2. Using ROS 2 Services#

Let’s begin digging into inspecting and controlling services using the CLI. Running the ros2 service list command in a new terminal will return a list of all the services currently active in the system:

/clear
/kill
/reset
/spawn
/teleop_turtle/describe_parameters
/teleop_turtle/get_parameter_types
/teleop_turtle/get_parameters
/teleop_turtle/list_parameters
/teleop_turtle/set_parameters
/teleop_turtle/set_parameters_atomically
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
/turtlesim/describe_parameters
/turtlesim/get_parameter_types
/turtlesim/get_parameters
/turtlesim/list_parameters
/turtlesim/set_parameters
/turtlesim/set_parameters_atomically

Note

You will see that both nodes have the same six services with parameters in their names. Nearly every node in ROS 2 has these infrastructure services that parameters are built off of. There will be more about parameters in a later section. In this section, the parameter services will be omitted from the discussion.

For now, let’s focus on the turtlesim-specific services, /clear, /kill, /reset, /spawn, /turtle1/set_pen, /turtle1/teleport_absolute, and /turtle1/teleport_relative. Using ros2 service list, there seem to be quite a few services listed.

5.8.2.1. Understanding service types#

Services have types that describe how the request and response data of a service is structured. ROS services and actions use messages similar to those used in topics to communicate. In fact, actions and services are built on top of messages. Service types are defined similarly to topic types, except service types have two parts: one message for the request and another for the response.

We can use the service type sub command to determine the message type used by a particular service. To find out the type of a service, use the command ros2 service type <service_name>. For example, let’s take a look at the /spawn service, which will create more turtles.

$ ros2 service type /spawn
turtlesim/srv/Spawn

5.8.2.2. Inspecting a Service message type#

Just as with regular topic message types, we can find specifics of the message by using the interface show command.

$ ros2 interface show turtlesim/srv/Spawn
float32 x
float32 y
float32 theta
string name # Optional.  A unique name will be created and returned if this is empty
---
string name

The output above shows that the spawn message takes three float32 values for its position and orientation as well a string for its name. The --- indicate the return value of the services. Unlike topics, services have a return value, which enables them to do things like perform computations and calculations.

Note

Sometimes a service does not really need to provide a return value. In those cases, services can use the Empty type as return value. Empty means the service call sends no data when making a request and receives no data when receiving a response.

To see an example, take a look at turtlesim’s /clear service. In a new terminal, enter the command:

$ ros2 service type /clear

Which should return:

std_srvs/srv/Empty

5.8.2.3. Other basic ros2 service sub commands#

The ros2 service --help also showed the sub command find, which is relatively straightforward. Try it out yourself!

If you want to find all the services in your ROS graph of a specific type, you can use ros2 service find <type_name>. For example, you can find that there are two services with the Empty like this:

$ ros2 service find std_srvs/srv/Empty
/clear
/reset

5.8.2.4. Calling a service from the CLI#

Let’s examine the help for calling a service by running ros2 service call --help:

$ ros2 service call --help
usage: ros2 service call [-h] [-r N] service_name service_type [values]

Call a service

positional arguments:
  service_name    Name of the ROS service to call to (e.g. '/add_two_ints')
  service_type    Type of the ROS service (e.g. 'std_srvs/srv/Empty')
  values          Values to fill the service request with in YAML format (e.g.
                  "{a: 1, b: 2}"), otherwise the service request will be
                  published with default values

optional arguments:
  -h, --help      show this help message and exit
  -r N, --rate N  Repeat the call at a specific rate in Hz

The syntax here is very similar to publishing to a topic, but instead of using a a topic name we use a service name. The service type is just like the topic type that we used in the past, but instead of using a message type we need a service type. Finally we give it a value in YAML format. Note that a YAML string must be encased in single quotes. Let’s try calling a service by creating a turtle named Larry at a position where all values are zero (use TAB-complete).

$ ros2 service call /spawn turtlesim/srv/Spawn "{x: 0, y: 0, theta: 0.0, name: 'Larry'}"
requester: making request: turtlesim.srv.Spawn_Request(x=0.0, y=0.0, theta=0.0, name='Larry')

response:
turtlesim.srv.Spawn_Response(name='Larry')

If everything is working correctly you should now have a turtle named “Larry” in the lower left hand corner of the screen:

Spawning a second turtle

Tip

Try exploring the other services offered, or creating more turtles at different locations and moving them around. For example, you know that Empty typed services don’t have any arguments:

$ ros2 service call /clear std_srvs/srv/Empty

This command will clear the turtlesim window of any lines your turtle has drawn.

../_images/clear.png

5.8.3. Using ROS 2 Actions#

New let’s move on to actions. As mentioned previously, actions differ from services in a few ways and offer a number of advantages. Actions have the following advantages:

  • Actions have a goal. That is to say you send them a goal, and they attempt to complete it.

  • Actions can reject goal requests. This prevents them from becoming too busy.

  • Actions are asynchronous and can perform tasks “while you wait.”

  • Actions will provide you with “updates” with information about their progress while you wait.

  • Actions are preemptable, meaning you can cancel them if you change your mind.

Just like with services, we’ll first figure out how to call the sole action in our ROS system by using the action list and action info commands. Recall, that when we called ros2 action list we got a single service. Now that we have Larry things have changed. Let’s take a look:

$ ros2 action list
/Larry/rotate_absolute
/turtle1/rotate_absolute

Now there are two actions available, one for Larry and one for turtle1. Let’s rotate turtle1 to face Larry. First we’ll call action info using /turtle1/rotate_absolute as the input and see what we get:

$ ros2 action info /turtle1/rotate_absolute
Action: /turtle1/rotate_absolute
Action clients: 0
Action servers: 1
    /turtlesim

Well, that tells us about the client and servers, but it really isn’t helpful for our goal of moving Larry. Why don’t we look at the action send_goal help and see if we can figure out how to use it:

$ ros2 action send_goal --help
usage: ros2 action send_goal [-h] [-f] action_name action_type goal

Send an action goal

positional arguments:
  action_name     Name of the ROS action (e.g. '/fibonacci')
  action_type     Type of the ROS action (e.g.
                  'example_interfaces/action/Fibonacci')
  goal            Goal request values in YAML format (e.g. '{order: 10}')

optional arguments:
  -h, --help      show this help message and exit
  -f, --feedback  Echo feedback messages for the goal

This command needs an action name, an action type, and a goal in YAML. We know the action name, and we know how to write YAML, so all we need is to determine the action type. The best way to get the action type is the same way we published a message.

We see each of our turtles have one service called rotate_absolute. Let’s dig into this action using the info sub command. This command has a -t flag to list the types of messages.

$ ros2 action info /turtle1/rotate_absolute -t
Action: /turtle1/rotate_absolute
Action clients: 0
Action servers: 1
  /turtlesim [turtlesim/action/RotateAbsolute]

The first line lists the action name. The second line gives the current number of clients for the action. The Action servers line gives the total number of action servers for this action. The last line gives the package and message type for the action.

We can see here that we need to know the action name, the type, and the values. Now the only problem is figuring out the format of the action type.

Let’s understand the RotateAbsolute action message

The ros2 interface show command can be used to find the type of action message. Let’s take a look:

$ ros2 interface show turtlesim/action/RotateAbsolute
# The desired heading in radians
float32 theta #< --- This section is the GOAL
---
# The angular displacement in radians to the starting position
float32 delta #< --- This section is the final result, different from the goal.
---
# The remaining rotation in radians
float32 remaining # < --- This is the current state.

What does this say about rotate absolute?

  • There is a float input, theta, the desired heading. This first section is the actual goal.

  • delta is the angle from the initial heading. This is the value returned when the action completes.

  • remaining is the remaining radians to move. This is the value posted by the action while the action is being done.

With this information we can create our call to the action server. We’ll use the -f flag to make this a bit clearer. Keep an eye on your turtle! It should move, slowly.

$ ros2 action send_goal -f /turtle1/rotate_absolute turtlesim/action/RotateAbsolute {'theta: 1.70'}
Waiting for an action server to become available...
Sending goal:
  theta: 1.7

Feedback:
  remaining: 0.11599969863891602

Goal accepted with ID: 35c40e91590047099ae5bcc3c5151121

Feedback:
 remaining: 0.09999966621398926

Feedback:
 remaining: 0.06799960136413574

Feedback:
 remaining: 0.03599953651428223

Result:
 delta: -0.09600019454956055

Goal finished with status: SUCCEEDED

If everything worked correctly we should see our turtle has rotated.

5.8.4. Summary#

Nodes can communicate using services in ROS 2. Unlike a topic - a one way communication pattern where a node publishes information that can be consumed by one or more subscribers - a service is a request/response pattern where a client makes a request to a node providing the service and the service processes the request and generates a response. You generally don’t want to use a service for continuous calls; topics or even actions would be better suited. In this section you used command line tools to identify, introspect, and call services.

Actions are like services that allow you to execute long running tasks, provide regular feedback, and are cancelable. A robot system would likely use actions for navigation. An action goal could tell a robot to travel to a position. While the robot navigates to the position, it can send updates along the way (i.e. feedback), and then a final result message once it’s reached its destination.