乐于分享
好东西不私藏

机器人系统——ROS2文档—认识动作

机器人系统——ROS2文档—认识动作

目标:内省 ROS 2 中的动作。教程级别:入门级时间: 15 分钟

目录

  • 背景
  • 前置条件
  • 任务
    • 环境准备
    • 使用动作
    • 3 ros2 node info
    • 4 ros2 action list
    • 5 ros2 action type
    • 6 ros2 action info
    • 7 ros2 interface show
    • 8 ros2 action send_goal
    • 9 ros2 action echo
  • 总结
  • 后续步骤
  • 相关资料

背景

    动作是 ROS 2 中的一种通信类型,专为长时间运行的任务而设计。它们由三部分组成:目标、反馈和结果。

    动作基于话题服务构建。它们的功能类似于服务,但区别在于动作可以被取消。此外,动作提供持续的反馈,而服务只返回单个响应。

    动作使用客户端服务器模型,类似于发布订阅模型(在话题教程中描述)。一个动作客户端节点向一个动作服务器节点发送目标,该服务器确认目标并返回一个反馈流和一个结果。

前置条件

    本教程建立在之前教程中介绍的概念之上,如节点话题。本教程使用turtlesim功能包。和往常一样,别忘了在打开的每个新终端中加载 ROS 2 环境。

任务

环境准备

    启动两个 turtlesim 节点:/turtlesim/teleop_turtle

    打开一个新终端并运行:

$ ros2 run turtlesim turtlesim_node

    打开另一个终端并运行:

$ ros2 run turtlesim turtle_teleop_key

2使用动作

    当你启动/teleop_turtle节点时,你会在终端中看到以下消息:

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键的一个方框(如果你不使用 QWERTY 键盘,请参阅此链接了解)。每个键相对于F的位置对应 turtlesim 中的那个方向。例如,E会使乌龟的方向旋转到左上角。

    注意运行/turtlesim节点的终端。每次你按下这些键中的一个,你就在向一个动作服务器发送一个目标,该服务器是/turtlesim节点的一部分。目标是旋转乌龟使其面向特定方向。一旦乌龟完成旋转,一条传递目标结果的消息应该会显示出来:

[INFO] [turtlesim]: Rotation goal completed successfully

    F键会在执行过程中取消一个目标。

    尝试按下C键,然后在乌龟完成旋转之前按下F键。在运行/turtlesim节点的终端中,你会看到消息:

[INFO] [turtlesim]: Rotation goal canceled

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

    尝试按下D键,然后在第一次旋转完成之前按下G键。在运行/turtlesim节点的终端中,你会看到消息:

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

    该动作服务器选择中止第一个目标,因为它收到一个新目标。它本可以选择其他方式,比如拒绝新目标,或者在第一个目标完成后执行第二个目标。不要假定每个动作服务器在收到新目标时都会选择中止当前目标。

3 ros2 node info

    要查看节点提供的动作列表,这里以/turtlesim为例,打开一个新终端并运行命令:

$ 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_msgs/msg/Color
/turtle1/pose: turtlesim_msgs/msg/Pose
Service Servers:
/clear: std_srvs/srv/Empty
/kill: turtlesim_msgs/srv/Kill
/reset: std_srvs/srv/Empty
/spawn: turtlesim_msgs/srv/Spawn
/turtle1/set_pen: turtlesim_msgs/srv/SetPen
/turtle1/teleport_absolute: turtlesim_msgs/srv/TeleportAbsolute
/turtle1/teleport_relative: turtlesim_msgs/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_msgs/action/RotateAbsolute
Action Clients:

    该命令返回/turtlesim的订阅者、发布者、服务、动作服务器和动作客户端的列表。

    注意/turtlesim/turtle1/rotate_absolute动作位于动作服务器下。这意味着/turtlesim响应并为/turtle1/rotate_absolute动作提供反馈。

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

$ ros2 node info /teleop_turtle
/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_msgs/action/RotateAbsolute

4 ros2 action list

    要列出 ROS 计算图中的所有动作,运行命令:

$ ros2 action list
/turtle1/rotate_absolute

    这是当前 ROS 计算图中唯一的动作。如您之前所见,它控制乌龟的旋转。通过使用ros2 node info<node_name>命令,您已经知道此动作有一个动作客户端(/teleop_turtle的一部分)和一个动作服务器(/turtlesim的一部分)。

4.1 ros2 action list -t

动作具有类型,类似于话题和服务。要查找/turtle1/rotate_absolute的类型,运行命令:

$ ros2 action list -t
/turtle1/rotate_absolute [turtlesim_msgs/action/RotateAbsolute]

在每个动作名称右侧的方括号中(这里只有/turtle1/rotate_absolute)是动作类型turtlesim_msgs/action/RotateAbsolute。当您想要从命令行或从代码执行动作时,将需要这个类型。

5 ros2 action type

    如果您想检查动作的动作类型,运行命令:

$ ros2 action type /turtle1/rotate_absolute
turtlesim_msgs/action/RotateAbsolute

6 ros2 action info

    您可以通过以下命令进一步内省/turtle1/rotate_absolute动作:

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

    这告诉我们之前通过对每个节点运行ros2 node info得到的信息:/teleop_turtle节点有一个动作客户端,/turtlesim节点有一个动作服务器,用于/turtle1/rotate_absolute动作。

7 ros2 interface show

    在您自己发送或执行动作目标之前,还需要了解的一件事是动作类型的结构。

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

$ ros2 interface show turtlesim_msgs/action/RotateAbsolute

    将返回:

# 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

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

8 ros2 action send_goal

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

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

<values>需要使用 YAML 格式。

    注意 turtlesim 窗口,然后在终端中输入以下命令:

$ ros2 action send_goal /turtle1/rotate_absolute turtlesim_msgs/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

    您应该会看到乌龟旋转。

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

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

$ ros2 action send_goal /turtle1/rotate_absolute turtlesim_msgs/action/RotateAbsolute "{theta: -1.57}" --feedback
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

    您将持续收到反馈(剩余弧度),直到目标完成。

9 ros2 action echo

    要查看动作客户端和动作服务器之间的数据通信,您可以使用以下命令echo动作数据:

$ ros2 action echo <action_name> <optional arguments/action_type>

ros2 action    echo依赖于动作客户端和服务器的动作内省,该功能默认是禁用的。要启用它,用户必须在创建动作客户端或服务器后调用configure_introspection

启动fibonacci_action_serverfibonacci_action_client,并为演示启用action_server_configure_introspection参数:

$ ros2 run action_tutorials_cpp fibonacci_action_server --ros-args -p action_server_configure_introspection:=contents
$ ros2 run action_tutorials_py fibonacci_action_client --ros-args -p action_client_configure_introspection:=contents

    现在我们可以通过ros2 action echo查看fibonacci_action_serverfibonacci_action_client之间的动作通信。

$ ros2 action echo /fibonacci example_interfaces/action/Fibonacci --flow-style
interface: GOAL_SERVICE
info:
event_type: REQUEST_SENT
stamp:
sec: 1742070798
nanosec: 400435819
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 20, 4]
sequence_number: 1
request: [{goal_id: {uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]}, goal: {order: 10}}]
response: []
---
interface: GOAL_SERVICE
info:
event_type: REQUEST_RECEIVED
stamp:
sec: 1742070798
nanosec: 400706446
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 20, 4]
sequence_number: 1
request: [{goal_id: {uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]}, goal: {order: 10}}]
response: []
---
interface: RESULT_SERVICE
info:
event_type: REQUEST_SENT
stamp:
sec: 1742070798
nanosec: 401486678
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 24, 4]
sequence_number: 1
request: [{goal_id: {uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]}}]
response: []
---
interface: FEEDBACK_TOPIC
goal_id:
uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]
feedback:
sequence: [0, 1, 1]
---
interface: STATUS_TOPIC
status_list: [{goal_info: {goal_id: {uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]}, stamp: {sec: 1742070798, nanosec: 401146752}}, status: 2}]
---
...

注意:此功能在 Kilted Kaiju 或更高版本中可用。

总结

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

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

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

后续步骤

    现在您已经涵盖了所有核心 ROS 2 概念。本系列的后面几个教程将向您介绍一些工具和技术,使 ROS 2 的使用更加容易,从使用 rqt_console 查看日志开始。

相关资料

    您可以在此处阅读有关 ROS 2 中动作设计决策的更多信息

    本文档完整翻译自 ROS 2 Lyrical 官方文档,仅用于学习交流。