【ROS2】Beginner : CLI tools - 理解 ROS 2 话题
目标:使用 rqt_graph 和命令行工具来查看 ROS 2 话题。
难度级别:初学者
预计时间:20 分钟
目录
- 背景
- 前提条件
- 任务
- 设置
- rqt_graph
- ros2 topic list
- ros2 topic echo
- ros2 topic info
- ros2 interface show
- ros2 topic pub
- ros2 topic hz
- ros2 topic bw
- ros2 topic find
- 清理
- 总结
背景
ROS 2 将复杂系统分解为许多模块化节点。话题是 ROS 图中的重要元素,充当节点交换消息的总线。
一个节点可以发布数据到任意数量的话题,同时也可以订阅任意数量的话题。
话题不仅限于点对点通信;它可以是一对多、多对一或多对多的通信模式。
话题是节点之间(因此也是系统不同部分之间)传递数据的主要方式之一。
前提条件
前一篇教程提供了关于节点的有用背景信息,本教程将在此基础上继续。
和往常一样,不要忘记在每个新打开的终端中执行 ROS 2 的 setup 文件。
任务
1. 设置
现在你应该已经熟悉如何启动 turtlesim 了。
打开一个新终端并运行:
ros2 run turtlesim turtlesim_node
打开另一个终端并运行:
ros2 run turtlesim turtle_teleop_key
回顾上一篇教程,这些节点的默认名称是 /turtlesim
和 /teleop_turtle
。
2. rqt_graph
在本教程中,我们将使用 rqt_graph
来可视化不断变化的节点和话题,以及它们之间的连接。
turtlesim 教程已经告诉你如何安装 rqt 及其所有插件,包括 rqt_graph
。
要运行 rqt_graph,打开一个新终端并输入命令:
rqt_graph
你也可以通过打开 rqt
并选择 Plugins > Introspection > Node Graph 来打开 rqt_graph。
你应该能看到上述节点和话题,以及图边缘的两个动作(暂时忽略它们)。如果你将鼠标悬停在中心的话题上,会看到如上图所示的高亮效果。
这个图展示了 /turtlesim
节点和 /teleop_turtle
节点如何通过话题进行通信。/teleop_turtle
节点将数据(你输入的移动乌龟的按键)发布到 /turtle1/cmd_vel
话题,而 /turtlesim
节点订阅该话题以接收数据。
rqt_graph 的高亮功能在检查具有许多节点和话题的复杂系统时非常有用。
rqt_graph 是一个图形化的查看工具。现在我们来看看一些用于查看话题的命令行工具。
3. ros2 topic list
在新终端中运行 ros2 topic list
命令,将返回当前系统中所有活跃话题的列表:
ros2 topic list
/parameter_events
/rosout
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
ros2 topic list -t
会返回相同的话题列表,但这次会在括号中附加话题类型:
ros2 topic list -t
/parameter_events [rcl_interfaces/msg/ParameterEvent]
/rosout [rcl_interfaces/msg/Log]
/turtle1/cmd_vel [geometry_msgs/msg/Twist]
/turtle1/color_sensor [turtlesim_msgs/msg/Color]
/turtle1/pose [turtlesim_msgs/msg/Pose]
这些属性(尤其是类型)是节点能够理解它们在话题上传递的是相同信息的依据。
如果你想知道这些话题在 rqt_graph 中的位置,可以取消勾选 Hide 下的所有选项。
不过现在,保持这些选项勾选以避免混淆。
4. ros2 topic echo
要查看在话题上发布的数据,使用:
ros2 topic echo <topic_name>
既然我们知道 /teleop_turtle
通过 /turtle1/cmd_vel
话题向 /turtlesim
发布数据,让我们用 echo
来查看这个话题:
ros2 topic echo /turtle1/cmd_vel
起初,这个命令不会返回任何数据,因为它在等待 /teleop_turtle
发布内容。
回到运行 turtle_teleop_key
的终端,使用方向键移动乌龟。同时观察运行 echo
的终端,你会看到每次移动都会发布位置数据:
linear:x: 2.0y: 0.0z: 0.0
angular:x: 0.0y: 0.0z: 0.0
---
现在返回 rqt_graph 并取消勾选 Debug 选项。
/_ros2cli_26646
是我们刚刚运行的 echo
命令创建的节点(数字可能不同)。现在你可以看到发布者正在通过 cmd_vel
话题发布数据,而有两个订阅者订阅了它。
5. ros2 topic info
话题不仅限于一对一通信;它们可以是一对多、多对一或多对多的。
另一种查看方式是运行:
ros2 topic info /turtle1/cmd_vel
Type: geometry_msgs/msg/Twist
Publisher count: 1
Subscription count: 2
6. ros2 interface show
节点通过话题发送数据时使用消息。发布者和订阅者必须发送和接收相同类型的消息才能通信。
我们之前运行 ros2 topic list -t
看到的话题类型告诉我们每个话题使用的消息类型。回想一下,cmd_vel
话题的类型是:
geometry_msgs/msg/Twist
这意味着在 geometry_msgs
包中有一个名为 Twist
的 msg
。
现在我们可以运行 ros2 interface show <msg_type>
来查看这个类型的详细信息,特别是消息期望的数据结构:
ros2 interface show geometry_msgs/msg/Twist
返回结果:
# 表示自由空间中的速度,分为线速度和角速度部分
Vector3 linearfloat64 xfloat64 yfloat64 z
Vector3 angularfloat64 xfloat64 yfloat64 z
这告诉你 /turtlesim
节点期望的消息包含两个向量:linear
和 angular
,每个向量有三个元素。如果你回想我们用 echo
命令看到的 /teleop_turtle
传递给 /turtlesim
的数据,它具有相同的结构:
linear:x: 2.0y: 0.0z: 0.0
angular:x: 0.0y: 0.0z: 0.0
---
7. ros2 topic pub
现在你知道了消息结构,可以使用以下命令从命令行直接向话题发布数据:
ros2 topic pub <topic_name> <msg_type> '<args>'
<args>
参数是你要传递给话题的数据,按照上一节发现的结构。
使用 pub
命令主要有四种方式,如下所示。不过,c 和 d 中描述的自动补全功能在 Windows 上不受支持。
发布字典字符串:
要向话题发布数据,需要以 YAML 字符串的形式传递数据。
ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
不过,你不需要指定完整的消息,如果你只想改变线速度或角速度,可以只指定你想要改变的值。
例如,如果你想将线速度改为 2.0,保持角速度为 1.8,可以这样做:
ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0}, angular: {z: 1.8}}"
发布空消息:
ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist
这将以 1 Hz 的频率发布消息类型的默认值。在这种情况下,等同于以下命令:
ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}" --rate 1
使用自动补全:
你可以通过以下方式触发终端的自动补全功能:
ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist <TAB>
所有选项都可以在输入选项的前几个字符后按 Tab 键自动补全。但是,话题消息原型只有在输入 \'<TAB>
后才会自动补全。
这是因为终端不将单引号视为自动补全字符串的一部分,因此需要使用 \'
来转义,使其被识别为字符串的一部分。
最终自动补全的字符串看起来像这样:
ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist 'linear:x: 0.0y: 0.0z: 0.0
angular:x: 0.0y: 0.0z: 0.0
'
这个字符串是可编辑的,你可以根据需要修改消息类型的值。
使用原始自动补全字符串:
如上所述,geometry_msgs/msg/Twist
的自动补全字符串看起来像这样:
\'linear:\^J\ \ x:\ 0.0\^J\ \ y:\ 0.0\^J\ \ z:\ 0.0\^Jangular:\^J\ \ x:\ 0.0\^J\ \ y:\ 0.0\^J\ \ z:\ 0.0\^J\'
这可以直接用于命令行中代替 YAML 字符串:
ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist \'linear:\^J\ \ x:\ 0.0\^J\ \ y:\ 0.0\^J\ \ z:\ 0.0\^Jangular:\^J\ \ x:\ 0.0\^J\ \ y:\ 0.0\^J\ \ z:\ 0.0\^J\'
乌龟(以及它通常模拟的真实机器人)需要稳定的命令流才能持续运行。所以,要让乌龟移动并保持移动,可以使用以下字典字符串:
ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
有时你可能只想向话题发布一次数据(而不是持续发布)。要只发布一次命令,可以添加 --once
选项:
ros2 topic pub --once -w 2 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
--once
是一个可选参数,表示"发布一条消息后退出"。
-w 2
是一个可选参数,表示"等待两个匹配的订阅者"。这是因为我们既有 turtlesim 又有 topic echo 订阅。
你会在终端看到以下输出:
Waiting for at least 2 matching subscription(s)...
publisher: beginning loop
publishing #1: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=2.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=1.8))
你会看到乌龟像这样移动:
你可以刷新 rqt_graph 来图形化地查看正在发生的事情。你会看到 ros2 topic pub ...
节点(/_ros2cli_30358
)正在通过 /turtle1/cmd_vel
话题发布数据,而 ros2 topic echo ...
节点(/_ros2cli_26646
)和 /turtlesim
节点现在都在接收这些数据。
最后,你可以在 pose
话题上运行 echo
并重新检查 rqt_graph:
ros2 topic echo /turtle1/pose
你可以看到 /turtlesim
节点也在向 pose
话题发布数据,而新的 echo
节点已经订阅了该话题。
当发布带有时间戳的消息时,pub
有两种方法可以自动用当前时间填充它们。对于带有 std_msgs/msg/Header
的消息,可以将 header 字段设置为 auto
来填充 stamp
字段:
ros2 topic pub /pose geometry_msgs/msg/PoseStamped '{header: "auto", pose: {position: {x: 1.0, y: 2.0, z: 3.0}}}'
如果消息不使用完整的 header,而只有一个类型为 builtin_interfaces/msg/Time
的字段,可以将其值设置为 now
:
ros2 topic pub /reference sensor_msgs/msg/TimeReference '{header: "auto", time_ref: "now", source: "dumy"}'
8. ros2 topic hz
你还可以使用以下命令查看数据发布的频率:
ros2 topic hz /turtle1/pose
average rate: 59.354min: 0.005s max: 0.027s std dev: 0.00284s window: 58
它会返回 /turtlesim
节点向 pose
话题发布数据的频率。
回想一下,你使用 ros2 topic pub --rate 1
将 turtle1/cmd_vel
的发布频率设置为稳定的 1 Hz。如果你用 turtle1/cmd_vel
代替 turtle1/pose
运行上述命令,你会看到反映该频率的平均值。
注意:这个频率反映了
ros2 topic hz
命令创建的订阅的接收频率,可能会受到平台资源和 QoS 配置的影响,可能与发布者的频率不完全匹配。
9. ros2 topic bw
可以使用以下命令查看话题使用的带宽:
ros2 topic bw /turtle1/pose
Subscribed to [/turtle1/pose]
1.51 KB/s from 62 messagesMessage size mean: 0.02 KB min: 0.02 KB max: 0.02 KB
它返回 /turtle1/pose
话题的带宽利用率和消息数量。
注意:这个带宽反映了
ros2 topic bw
命令创建的订阅的接收带宽,可能会受到平台资源和 QoS 配置的影响,可能与发布者的带宽不完全匹配。
10. ros2 topic find
要列出给定类型的所有可用话题,使用:
ros2 topic find <topic_type>
回想一下,cmd_vel
话题的类型是:
geometry_msgs/msg/Twist
使用 find
命令,输入消息类型会输出可用的话题:
ros2 topic find geometry_msgs/msg/Twist
/turtle1/cmd_vel
11. 清理
此时你可能运行了很多节点。别忘了在每个终端中按 Ctrl+C
来停止它们。
总结
节点通过话题发布信息,这使得任意数量的其他节点都可以订阅并访问这些信息。在本教程中,你使用 rqt_graph 和命令行工具检查了多个节点之间通过话题的连接。现在你应该对 ROS 2 系统中数据的流动方式有了很好的理解。
下一步
接下来,你将通过《理解服务》教程学习 ROS 图中的另一种通信类型。