目标
在ROS2中对动作进行深入探究和分析。
背景知识
动作是ROS2中的一种通信类型,适用于长时间运行的任务。它们由三个部分组成:目标(goal)、反馈(feedback)和结果(result)。
动作是基于话题(topics)和服务(services)构建的。其功能与服务类似,不同之处在于动作可以被取消。它与只返回单个响应的服务相比,还能提供持续的反馈。
动作采用的是客户端/服务器模型,类似于发布者/订阅者模型(这在理解话题的文章中有描述)。一个 "动作客户端" 节点向一个 "动作服务器" 节点发送目标(goal),动作服务器节点会确认该目标(goal),并返回一系列反馈信息(feedback)和最终结果(result)。

前提条件
跟往常一样,在每次打开新终端时,别忘了对ROS2进行环境变量设置。
bash
# Replace ".bash" with your shell if you're not using bash
# Possible values are: setup.bash, setup.sh, setup.zsh
source /opt/ros/jazzy/setup.bash
操作步骤
1. 环境设置
启动 turtlesim的两个节点:/turtlesim和 /teleop_turtle。 打开一个新终端并运行以下命令:
arduino
ros2 run turtlesim turtlesim_node
再打开另一个终端并运行:
arduino
ros2 run turtlesim turtle_teleop_key
2. 使用动作
当你启动 /teleop_turtle 节点时,你会在终端中看到以下消息:
css
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" 话题,在之前的理解话题的文章中描述过。)
需要注意的是,在美式 QWERTY 键盘上,字母键 G|B|V|C|D|E|R|T 在 F 键周围形成一个 "方框"。F 键周围每个键的位置对应于 turtlesim 中乌龟的朝向。例如,按下 E 键会将乌龟的朝向旋转到左上角。
这时请留意运行 /turtlesim 节点的终端。每次按下这些键中的一个时,你就是在 /turtlesim 节点的一个动作服务器发送一个目标。该目标是将乌龟旋转到特定的方向。一旦乌龟完成旋转,应该会显示一条传达目标结果的消息:
css
[INFO] [turtlesim]: Rotation goal completed successfully
按下 F 键将在目标执行过程中取消该目标。
尝试按下 C 键,然后在乌龟完成旋转之前按下 F 键。在运行 /turtlesim 节点的终端中,你会看到以下消息:
css
[INFO] [turtlesim]: Rotation goal canceled
不仅客户端(你在 teleop中的输入)可以停止一个目标,服务器端( /turtlesim 节点)也可以。当服务器端选择停止处理一个目标时,我们称其 "Abort" 了该目标。 尝试按下 D 键,然后在第一次旋转完成之前按下 G 键。在 /turtlesim 节点的终端中,你会看到以下消息:
less
[WARN] [turtlesim]: Rotation goal received before a previous goal finished. Aborting previous goal
因为动作服务器收到了一个新目标,它选择中止第一个目标。它也可以选择其他操作,比如拒绝新目标或者在第一个目标完成后再执行第二个目标。需要注意的是,不要因为这次实验认为每个动作服务器在收到新目标时都会选择中止当前目标。
3. ros2 node info 命令
要查看一个节点(这里是 /turtlesim)所提供的动作列表,打开一个新终端并运行以下命令:
bash
ros2 node info /turtlesim
该命令将返回 /turtlesim的订阅者、发布者、服务、动作服务器和动作客户端的列表:
bash
/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动作属于 "动作服务器" 部分。这意味着 /turtlesim 对 /turtle1/rotate_absolute动作做出响应并提供反馈。
对应的,/teleop_turtle 节点在 "动作客户端" 部分则有会 /turtle1/rotate_absolute,这意味着它作为动作客户端发送这个动作目标。要查看这一点,可以运行以下命令:
bash
ros2 node info /teleop_turtle
该命令将返回:
bash
/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
4. ros2 action list 命令
要识别 ROS 图中的所有动作,需要运行以下命令:
ros2 action list
该命令将返回:
bash
/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
该命令将返回:
bash
/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]
在每个动作名称(在这种情况下只有 /turtle1/rotate_absolute)右边的方括号中是动作类型 turtlesim/action/RotateAbsolute。当你想从命令行或代码中执行一个动作时,你就会需要这个动作类型。
5. ros2 action type 命令
如果你想检查某个动作的动作类型,运行以下命令:
bash
ros2 action type /turtle1/rotate_absolute
该命令将返回:
bash
turtlesim/action/RotateAbsolute
6. ros2 action info 命令
你可以使用以下命令进一步深入探究 /turtle1/rotate_absolute
动作:
bash
ros2 action info /turtle1/rotate_absolute
该命令将返回:
bash
Action: /turtle1/rotate_absolute
Action clients: 1
/teleop_turtle
Action servers: 1
/turtlesim
从返回结果我们同样可以看到之前对每个节点运行 ros2 node info
所了解到的信息:/teleop_turtle
节点有一个针对 /turtle1/rotate_absolute
动作的动作客户端,而 /turtlesim
节点有一个针对该动作的动作服务器。
7. ros2 interface show 命令
在你自己发送或执行动作目标之前,还需要了解的一个信息是动作类型的结构。
回想一下,你在运行 ros2 action list -t
命令时, 确定了 /turtle1/rotate_absolute
的类型。在终端中输入以下带有动作类型的命令:
kotlin
ros2 interface show turtlesim/action/RotateAbsolute
该命令将返回:
yaml
# 以弧度为单位的航向
float32 theta
---
# 以弧度为单位的到起始位置的角位移
float32 delta
---
# 以弧度为单位的剩余旋转
float32 remaining
这条消息中第一个 ---
上面的部分是目标请求的定义(数据类型和名称)。接下来的部分是结果的定义。最后一部分是反馈的定义。
8. ros2 action send_goal 命令
现在让我们在命令行中使用以下语法发送一个动作目标:
xml
ros2 action send_goal <action_name> <action_type> <values>
在这里需要采用 YAML 格式。
留意一下 turtlesim窗口,然后在终端中输入以下命令:
bash
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"
你应该会看到乌龟在旋转,并且在终端中会看到以下消息:
yaml
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选项:
bash
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedback
你的终端将会返回以下消息:
yaml
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
你将会持续收到反馈,即剩余的弧度,直到目标完成。
总结
动作类似于服务,它允许你执行长时间运行的任务,提供定期反馈,并且可以被取消。 一个机器人系统很可能会使用动作来进行导航。一个动作目标可以告诉机器人前往某个位置。在机器人导航到该位置的过程中,它可以沿途发送更新(即反馈),然后在到达目的地时发送一个最终的结果消息。
Turtlesim有一个动作服务器,动作客户端可以向其发送用于旋转乌龟的目标。在本文中,你对 /turtle1/rotate_absolute 这个动作进行了深入探究,更好地理解了动作是什么,以及它们是如何工作的。
关注【智践行】公众号,发送 【机器人】 获得机器人经典学习资料