Skip to content

ROS2主要创新的3/3:动作(actions)通信

学会提问:

01. 背景知识

动作是 ROS 2 中的通信类型之一,适用于长时间运行的任务。它们由三个部分组成:目标、反馈和结果。

动作基于主题和服务构建。它们的功能类似于服务,但可以取消动作。它们还提供稳定的反馈,而不是返回单个响应的服务。

动作使用客户端-服务器模型,类似于发布者-订阅者模型。“action client” 节点将目标发送到 “action server” 节点,该节点确认目标并返回反馈流和结果。

动作通信的工作示意图

02. 准备工作

本教程基于前面教程中介绍的节点主题等概念。

本教程使用 turtlesim 包。

不要忘了每次打开一个新终端时都要 source ROS 2 的 setup 文件:

bash
source /opt/ros/jazzy/setup.zsh

然后,作为本节教程的准备工作,我们需要启动两个 turtlesim 节点: /turtlesim/teleop_turtle。:

打开新终端并运行:

bash
ros2 run turtlesim turtlesim_node

打开另一个终端并运行:

shell
ros2 run turtlesim turtle_teleop_key

03. 学习任务

3.1 关于actions的日常操作

启动 /teleop_turtle 节点时,您将在终端中看到以下消息:

shell
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.

让我们关注第二行,它对应于一个动作。(第一条指令对应于 “cmd_vel” 主题,之前在主题教程中讨论过。

请注意,字母键 G|B|V|C|D|E|R|T 在美式 QWERTY 键盘上的 F 键周围形成一个“框”。每个键在 F 附近的位置对应于 turtlesim 中的该方向。例如,E 会将海龟的方向旋转到左上角。

注意运行 /turtlesim 节点的终端。每次按下其中一个键时,您都会将目标发送到属于 /turtlesim 节点的动作服务器。目标是旋转海龟以面向特定方向。一旦 turtle 完成旋转,应该会显示一条消息来中继目标的结果:

shell
[INFO] [turtlesim]: Rotation goal completed successfully

此动作服务器选择中止第一个目标,因为它获得了一个新目标。它可以选择其他内容,例如拒绝新目标或在第一个目标完成后执行第二个目标。不要假设每个 action server 都会在获得新目标时选择中止当前目标。 F 键将在执行过程中取消目标。

尝试按 C 键,然后按 F 键,然后海龟才能完成旋转。在运行 /turtlesim 节点的终端中,您将看到以下消息:

shell
[INFO] [turtlesim]: Rotation goal canceled

不仅客户端(您在 teleop 中的输入)可以停止目标,服务器端(/turtlesim 节点)也可以。当服务器端选择停止处理目标时,称为 “abort” 该目标。

尝试按 D 键,然后按 G 键,然后才能完成第一次旋转。在运行 /turtlesim 节点的终端中,您将看到以下消息:

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

此动作服务器选择中止第一个目标,因为它获得了一个新目标。它可以选择其他内容,例如拒绝新目标或在第一个目标完成后执行第二个目标。不要假设每个 action server 都会在获得新目标时选择中止当前目标。

3.2 ros2 node info

要查看节点提供的动作列表(在本例中为 /turtlesim),请打开一个新终端并运行命令:

shell
ros2 node info /turtlesim

这将返回 /turtlesim 的订阅者、发布者、服务、动作服务器和动作客户端的列表:

shell
/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:

请注意,/turtlesim/turtle1/rotate_absolute 动作位于 Action Servers 下。这意味着 /turtlesim 响应 /turtle1/rotate_absolute 动作并提供反馈。

/teleop_turtle 节点在 Action Clients 下的名称为 /turtle1/rotate_absolute这意味着它发送该动作名称的目标。要查看这一点,请运行:

shell
ros2 node info /teleop_turtle

这将返回:

shell
/teleop_turtle
  Subscribers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
  Publishers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /rosout: rcl_interfaces/msg/Log
    /turtle1/cmd_vel: geometry_msgs/msg/Twist
  Service Servers:
    /teleop_turtle/describe_parameters: rcl_interfaces/srv/DescribeParameters
    /teleop_turtle/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
    /teleop_turtle/get_parameters: rcl_interfaces/srv/GetParameters
    /teleop_turtle/list_parameters: rcl_interfaces/srv/ListParameters
    /teleop_turtle/set_parameters: rcl_interfaces/srv/SetParameters
    /teleop_turtle/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
  Service Clients:

  Action Servers:

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

3.3 ros2 action list

要识别 ROS graph 中的所有动作,请运行以下命令:

shell
ros2 action list

这将返回:

shell
/turtle1/rotate_absolute

这是目前 ROS 图中唯一的动作。它控制着海龟的旋转,正如你之前看到的。您还已经知道,通过使用 ros2 node info <node_name> 命令,有一个动作客户端(/teleop_turtle 的一部分)和一个动作服务器(/turtlesim 的一部分)可用于此动作。

动作具有类型,类似于 topics 和 services。要查找 /turtle1/rotate_absolute 的类型,请运行以下命令:

shell
ros2 action list -t

这将返回:

shell
/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]

每个动作名称右侧的括号(在本例中仅为 /turtle1/rotate_absolute)是动作类型 turtlesim/action/RotateAbsolute 。当您想从命令行或代码执行动作时,您将需要此“路径”。

3.4 ros2 action type

如果要检查动作的动作类型,请运行以下命令:

shell
ros2 action type /turtle1/rotate_absolute

这将返回:

shell
turtlesim/action/RotateAbsolute

3.5 ros2 action info

您可以使用以下命令进一步检查 /turtle1/rotate_absolute 动作:

shell
ros2 action info /turtle1/rotate_absolute

这将返回:

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

这告诉我们之前从每个节点上运行 ros2 node info 中学到的内容:/teleop_turtle 节点有一个动作客户端,/turtlesim 节点有一个用于 /turtle1/rotate_absolute 动作的动作服务器。

3.6 ros2 interface show

在自己发送或执行动作目标之前,您需要的另一条信息是动作类型的结构。

回想一下,您在运行命令 ros2 action list -t 时识别了 /turtle1/rotate_absolute 的类型。在终端中输入以下命令和动作类型:

shell
ros2 interface show turtlesim/action/RotateAbsolute

这将返回:

shell
# 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

此消息中第一个---上方的部分是目标请求的结构(数据类型和名称)。下一部分是结果的结构。最后一部分是反馈的结构。

3.7 ros2 action send_goal

现在,让我们使用以下语法从命令行发送动作目标:

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

<values> 需要采用 YAML 格式。

请留意 turtlesim 窗口,并在您的终端中输入以下命令:

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

您应该会在您的终端中看到 turtle 旋转,以及以下消息:

shell
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

所有目标都有一个唯一的 ID,显示在返回消息中。您还可以看到结果,一个名为 delta 的字段,它是到起始位置的位移。

要查看此目标的反馈,请将 --feedback 添加到 ros2 action send_goal命令中:

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

您的终端将返回以下消息:

shell
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

您将继续收到反馈,即剩余的弧度,直到目标完成。

04. 总结

动作类似于服务,允许您执行长时间运行的任务、提供定期反馈并且可取消。

机器人系统可能会使用动作进行导航。动作目标可以告诉机器人移动到某个位置。当机器人导航到该位置时,它可以沿途发送更新(即反馈),然后在到达目的地后发送最终结果消息。

Turtlesim 有一个动作服务器,动作客户端可以向该服务器发送旋转海龟的目标。在本教程中,您 introspect 了动作 /turtle1/rotate_absolute,以更好地了解什么是动作以及它们的工作原理。