Actions are one of the communication types in ROS 2 and are intended for long running tasks. They consist of three parts: a goal, feedback, and a result.

Actions are built on topics and services. 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 use a client-server model, similar to the publisher-subscriber model of topics. 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.

Example: Keyboard Control

When we are trying to control the turtle via keyboard, we ran two nodes /turtlesim and /teleop_turtle in two terminals

ros2 run turtlesim turtlesim_node

And

ros2 run turtlesim turtle_teleop_key

When you launch the /teleop_turtle node, you will see the following message in your terminal:

Use arrow keys to move the turtle.
Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation.

Each time you press one of these keys, you are sending a goal to an action server that is part of the /turtlesim node. The goal is to rotate the turtle to face a particular direction. A message relaying the result of the goal should display once the turtle completes its rotation:

[INFO] [turtlesim]: Rotation goal completed successfully

And the F key will cancel a goal mid-execution, which outputs the following message

[INFO] [turtlesim]: Rotation goal canceled

Not only can the client-side (your input in the teleop) stop a goal, but the server-side (the /turtlesim node) can as well. When the server-side chooses to stop processing a goal, it is said to "abort" the goal.

Try hitting the D key, then the G key before the first rotation can complete. In the terminal where the /turtlesim node is running, you will see the message:

[WARN] [turtlesim]: Rotation goal received before a previous goal finished. Aborting previous goal

This action server chose to abort the first goal because it got a new one. It could have chosen something else, like reject the new goal or execute the second goal after the first one finished. Don't assume every action server will choose to abort the current goal when it gets a new one.

Commands

ros2 node info

Besides the introduction in nodes, this time we focus on the information related to actions. If we run

ros2 node info /turtlesim

We will get:

/turtlesim
  Subscribers:
    ...
  Publishers:
    ...
  Service Servers:
    ...
  Service Clients:
	...
  Action Servers:
    /turtle1/rotate_absolute: turtlesim/action/RotateAbsolute
  Action Clients:

Notice that the /turtle1/rotate_absolute action for /turtlesim is under Action Servers. This means /turtlesim responds to and provides feedback for the /turtle1/rotate_absolute action.

And then we run

ros2 node info /teleop_turtle

Which will return:

/teleop_turtle
  Subscribers:
	...
  Publishers:
    ...
  Service Servers:
    ...
  Service Clients:

  Action Servers:

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

So the /teleop_turtle node has the name /turtle1/rotate_absolute under Action Clients meaning that it sends goals for that action name.

ros2 action list

To identify all the actions in the ROS graph, run the command

ros2 action list

Which will return:

/turtle1/rotate_absolute

This is the only action in the ROS graph right now. It controls the turtle's rotation, as you saw earlier. You also already know that there is one action client (part of /teleop_turtle) and one action server (part of /turtlesim) for this action from using the ros2 node info <node_name> command.

If we run ros2 action list -t, then we will get the type of the actions, which in this case will return:

/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]

In brackets to the right of each action name.

ros2 action info

You can further introspect the /turtle1/rotate_absolute action with the command:

ros2 action info /turtle1/rotate_absolute

Which will return

Action: /turtle1/rotate_absolute
Action clients: 1
    /teleop_turtle
Action servers: 1
    /turtlesim

This tells us what we learned earlier from running ros2 node info on each node: The /teleop_turtle node has an action client and the /turtlesim node has an action server for the /turtle1/rotate_absolute action.

ros2 interface show

One more piece of information you will need before sending or executing an action goal yourself is the structure of the action type.

Recall that we identified /turtle1/rotate_absolute's type when running the command ros2 action list -t. Enter the following command with the action type in your terminal:

ros2 interface show turtlesim/action/RotateAbsolute

Which will return:

# The desired heading in radians
float32 theta
---
# The angular displacement in radians to the starting position
float32 delta
---
# The remaining rotation in radians
float32 remaining

The section of this message above the first --- is the structure (data type and name) of the goal request. The next section is the structure of the result. The last section is the structure of the feedback.

ros2 action send_goal

Send an action goal from the command line with the following syntax:

ros2 action send_goal <action_name> <action_type> <values>

<values> need to be in YAML format.

Keep an eye on the turtlesim window, and enter the following command into your terminal:

ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"

You should see the turtle rotating, as well as the following message in your terminal:

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

All goals have a unique ID, shown in the return message. You can also see the result, a field with the name delta, which is the displacement to the starting position.

To see the feedback of this goal, add --feedback to the ros2 action send_goal command:

ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedback

Your terminal will return the message:

Sending goal:
   theta: -1.57

Goal accepted with ID: e6092c831f994afda92f0086f220da27

Feedback:
  remaining: -3.1268222332000732

Feedback:
  remaining: -3.1108222007751465

…

Result:
  delta: 3.1200008392333984

Goal finished with status: SUCCEEDED

You will continue to receive feedback, the remaining radians, until the goal is complete.