【ROS2 Humble】第一课 - CLI工具
硬件可以类比成饭店各个干活的员工,ROS2 就是那个管消息分发、任务派发、协调所有人干活的总调度,让一堆零散硬件 / 算法模块能够互相配合,变成完整能干活的机器人。
ROS2 框架是实现机器人不同部件之间通信的“基础架构”。它包括消息传递、标准接口,以及对多种编程语言和平台的支持。在使用 ROS2 开发或维护应用程序之前,需要先了解框架的基本概念。
ROS2 提供了一套 turtlesim 工具用于快速入门,通过终端调用即可完成简易 demo,这个 CLI 就是终端的意思。
1 使用 turtlesim 小海龟和 rqt
turtlesim 小海龟这玩意儿基本上可以说是贯穿了 ROS2 的学习了。ROS2 提供的这个小海龟其实就是可以将它视为虚拟的仿真的机器人,在一个简单的 2D 可视化仿真界面学习 ROS2。
rqt 是 ROS2 提供的一个图形化用户交互工具,rqt 可以做所有终端能做的事,而且提供了友好的用户交互界面。
1.1 安装 turtlesim 和 rqt
sudo apt update
sudo apt install ros-humble-turtlesim ros-humble-rqt ros-humble-rqt-common-plugins
安装完成后在终端输入 ros2 pkg executables turtlesim,输出以下内容说明小海龟安装成功。

输入 rqt 可以出现一个图形化界面说明 rqt 安装成功。

1.2 启动小海龟
通过 ros2 run turtlesim turtlesim_node指令启动小海龟,小海龟的颜色是随机生成的, 每一次启动都不一样。

1.3 控制小海龟
ros2 提供了一个键盘工具,可以通过键盘来控制小海龟的移动。再打开一个终端,输入这个指令就行
ros2 run turtlesim turtle_teleop_key
鼠标点击新开的这个控制的终端,使其保持在最上层,通过键盘的上下左右就可以控制小海龟的移动和方向了

那么,玩这个小海龟有什么意义呢?不妨想想,明明是开了两个不同的终端,为什么在新开的这个终端输入上下左右就可以控制小海龟移动?这里就可以引出 ROS2 的核心概念:node 节点、topic 话题、service 服务以及 action 动作的几大知识点了。
再打开一个终端,输入以下指令可以分别查看都有哪些相关的信息:
ros2 node list
ros2 topic list
ros2 service list
ros2 action list

-
node:可以看到只有 2 个,对应的就是刚才通过两个终端指令启动的 node 节点,一个是小海龟,另一个是监听键盘输入的节点。
-
topic:可以看到
/turtle1开启了 3 个话题,另外 2 个话题先不管 -
service:可以看到有大量的服务
-
action:可以看到小海龟有一个动作
上面这些内容现在还不需要深入了解,只要知道通过终端开启了这个小海龟,就默默帮我们在后台启动了这么多的节点、话题、服务、动作等内容。
1.4 使用 rqt 操作
前面提到过,rqt 就是方便使用的一套可视化工具,集成了所有的终端指令工具,相当于一台上位机程序。在新建终端中输入 rqt 启动工具,但是启动后会看到其实没有内容,这时候需要选择 Plugins > Services > Service Caller 会开启一个 service caller 界面,可以选择各种服务,点击右侧的 call 即可进行服务的调用。

service 选择 /clear,点击一下 call 调用,会发现小海龟之前行走的路径被清除了,下方还有返回的结果

例如将 service 切换到 /spawn,可以在 request 中配置相关的参数,点击 call 调用,就会发现生成了一个新的小海龟。

这些服务对应的就是前面 ros2 service list 中罗列出来的所有服务,可以再试试调用别的服务来玩玩,加深对于 service 的理解。
所以目前可看出,服务相当于是一个函数,给这个服务提供指定的参数就可以实现相应的功能。
2 ROS2 的主要通信组件
2.1 节点 Node
在 ROS 中,每个节点都负责一个单一的模块化的功能。类比饭店的例子,后厨就是一个 node 节点,主要负责炒菜;前台也是一个 node 节点,主要负责引导。对应到机器人中,控制车轮电机的任务可以视为是一个节点,发布激光传感器数据的任务可以视为一个节点。 我的理解是,节点不是对应某一个硬件设备,而应该是对应一项任务,但是也许既可以对应一项任务,也可以对应一个具体的硬件设备,好像没有人对节点应该对应什么有一个明确的定义,或许需要有经验的人来做个总结吧。
每个 node 节点都可以使用 topic、service、action 进行通信,下图就能很好地描述这个过程。右上角这个 node 作为一个 publisher 可以将 message 发送到 topic,再转发给所有订阅了这个 topic 的 subscriber。

还是看之前小海龟的例子,通过 ros2 run turtlesim turtlesim_node 启动小海龟
-
ros2 run <package_name> <executable_name>使用 ros2 run 指令,输入对应的 包名 和 可执行命令 的名称,就可以执行相关的功能,关于小海龟这玩意,turtlesim 就是小海龟这个包名,turtlesim_node 就是这个包提供的一个可行性的命令。
-
再新建一个终端输入
ros2 node list,可以看到一个/turtlesim的 node 节点 -
ros2 node info <node_name>该指令可以查看节点的详细信息,例如输入
ros2 node info /turtlesim,可以看到这个节点有 subscribers、publishers、service servers、service clients、action clients 等内容。这些都是对应这个节点所包含的 topic 话题、service 服务与 action 动作的配置情况。
2.2 话题 topic
ROS 2 将复杂系统分解为许多模块化节点,topic 话题充当节点之间交换消息的总线。

从图中可以很直观看出,一个节点可以作为发布者也可以作为订阅者,发布者和订阅者都关注了某个话题,发布者可以在话题上推送消息,推送的消息会被发送给所有订阅者。
我感觉这个图只是做了简化,实际上一个节点既可以是发布者也可以是订阅者,也可以同时关注非常多的话题。其实这个话题相当于是一个微信公众号,这样就好理解了。
看看小海龟里面的话题订阅情况,启动小海龟 ros2 run turtlesim turtlesim_node,启动键盘监听事件:ros2 run turtlesim turtle_teleop_key。
通过 ros2 topic list 可以看到当前启动的话题:

使用 rqt_graph 可以直接看到话题的订阅情况:

椭圆是一个 node 节点,单独一个矩形就是对应一个 topic 话题,话题外层套了一层命名空间 /turtle1 将话题包起来,用于和其他可能出现的同名的话题做区分。
不过
/turtle1/cmd_vel我理解,是控制小海龟移动的话题,为啥 color_sensor 还有 pose 的话题怎么就没出现呢?反而多了什么 rotate_absolute。不管了。
-
topic 话题的一些 CLI 指令的使用
-
话题传输的消息类型
ros2 topic list -t 在列举话题列表的时候加入-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/msg/Color] /turtle1/pose [turtlesim/msg/Pose] -
订阅话题,获取实时数据
ros2 topic echo <topic_name>例如想看键盘实时输入的数据,那就
ros2 topic echo /turtle1/cmd_vel
-
查看话题信息
ros2 topic info <topic_name>例如:
ros2 topic info /turtle1/cmd_vel,输出的内容就是这个话题的消息类型、发布者数量、订阅者数量Type: geometry_msgs/msg/Twist Publisher count: 1 Subscription count: 1如果要看更加详细的信息,加上一个
--verbose(这个--verbose在很多 Linux 指令中都是代表详细信息的意思,verbose 实际上是冗长的意思),输入ros2 topic info /turtle1/cmd_vel --verbose,输出结果如下:Type: geometry_msgs/msg/Twist Publisher count: 1 Node name: teleop_turtle Node namespace: / Topic type: geometry_msgs/msg/Twist Endpoint type: PUBLISHER GID: 01.0f.27.28.e5.1e.9c.88.00.00.00.00.00.00.12.03.00.00.00.00.00.00.00.00 QoS profile: Reliability: RELIABLE History (Depth): UNKNOWN Durability: VOLATILE Lifespan: Infinite Deadline: Infinite Liveliness: AUTOMATIC Liveliness lease duration: Infinite Subscription count: 1 Node name: turtlesim Node namespace: / Topic type: geometry_msgs/msg/Twist Endpoint type: SUBSCRIPTION GID: 01.0f.27.28.98.1e.90.0f.00.00.00.00.00.00.1b.04.00.00.00.00.00.00.00.00 QoS profile: Reliability: RELIABLE History (Depth): UNKNOWN Durability: VOLATILE Lifespan: Infinite Deadline: Infinite Liveliness: AUTOMATIC Liveliness lease duration: Infinite这里面信息量很多,都会在后续慢慢学到,简单了解一下即可。
-
消息的具体数据类型
前面虽然是列出了消息的数据类型,但是还是很抽象怎么办?
geometry_msgs/msg/Twist谁能看得懂?所以可以通过一个查看接口信息的指令来了解数据类型:
ros2 interface show geometry_msgs/msg/Twist输出内容如下:
# This expresses velocity in free space broken into its linear and angular parts. Vector3 linear float64 x float64 y float64 z Vector3 angular float64 x float64 y float64 z这也是为什么在
ros2 topic echo /turtle1/cmd_vel的时候返回的数据类型是那样的了 -
在话题发布消息
ros2 topic pub <topic_name> <msg_type> '<args>'前面知道了话题,也知道了话题传输的消息的数据类型,那么通过
pub就可以往话题发送消息,例如: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}}"上面的指令会一直往话题发送消息,默认是
1Hz的频率,如果只想发送一下,只要加一个--once的参数即可。 -
监听话题消息频率
ros2 topic hz <topic_name>该指令可以监听话题的消息的频率,最短间隔多长时间、最长间隔多长时间。
-
话题数据带宽
ros2 topic bw <topic_name>返回话题消息的带宽,现在传的都是较短的数据,如果后续需要传输图像、视频数据,那就很有意义,可以看出有多少的带宽了。
-
根据话题类型查找话题
ros2 topic find <topic_type>可以罗列出用到了这个消息类型的话题。不过不知道可能什么时候能用到。
-
2.3 服务 service
service服务是 ROS 节点之间的另一种通信方式。服务采用请求‑应答模型,这与话题的发布‑订阅模型有所区别。话题允许节点订阅数据流并持续获取更新,而服务仅在被客户端显式调用时才提供数据。简而言之就是,可以多对多连接,但是通信时候是一对一的,且有请求才有相应。

类似的,service 也有和 topic 类似的 CLI 指令,如:
ros2 service list # 列举运行的服务
ros2 service type <service_name> # 某个服务的消息类型
ros2 service list -t # 列举运行的服务,并显示数据类型
ros2 service find <type_name> # 根据服务数据类型找到服务
ros2 interface show <type_name> # 查看服务数据类型的详细信息
不同于 topic,service 要使用的时候是通过调用的方式:
ros2 service call <service_name> <service_type> <arguments>
ros2 service call /clear std_srvs/srv/Empty
这个指令和 1.4 使用 rqt 操作 提到的使用可视化界面发送的 /clear 指令是一样的效果。
2.4 参数 parameter
参数是节点的配置值,可以把参数理解为节点的设置项。节点可以将参数存储为整数、浮点数、布尔值、字符串以及列表。在 ROS 2 中,每个节点维护属于自己的一套参数。
ros2 param list # 查看有哪些参数
ros2 param get <node_name> <parameter_name> # 获取某个节点的参数值
ros2 param set <node_name> <parameter_name> <value> # 给某个节点设置参数值
ros2 param dump <node_name> # 将某个节点的参数打印出来,结合 >> xxx.yaml 可以输出到文件
ros2 param load <node_name> <parameter_file> # 给节点加载参数
# 节点启动的时候加载参数值
ros2 run <package_name> <executable_name> --ros-args --params-file <file_name>
2.5 动作 action
动作(Actions)是 ROS 2 中的一种通信类型,专门用于处理长时间运行的任务。动作由三部分组成:目标(goal)、反馈(feedback)和结果(result) 。这三个部分需要牢记,后续编写程序也会用到。
目标(goal):某个动作的目标
反馈(feedback):动作执行过程中的反馈值
结果(result):动作执行完成后返回的结果
动作基于话题与服务实现。它的功能和服务类似,但动作支持取消任务;同时动作可以持续输出反馈,而服务仅返回单次应答。Action 动作实际上就是用 topic 和 service 拼出来,因为该功能比较常用,所以 ROS 专门封装了 Action 这套机制如果要手动来实现对应的功能也行,但是有点重复造轮子,不提倡了。
动作采用客户端‑服务器模型,和发布‑订阅模型有相似之处。动作客户端节点向动作服务端节点发送目标;动作服务端接收确认目标后,会持续返回反馈数据流,最后给出最终结果。

在小海龟的例子中,通过 ros2 action list可以看到系统当前正在运行的 action 动作,根据名称可以看出这是一个旋转的案例,通过前面查看节点信息的指令查看小海龟 /turtlesim的相关节点 ros2 node info /tutlesim 可以看到启动了一个 action 服务器

在 /teleop_turtle节点中,可以看到是一个 action 的客户端

也就是说,二者之间是通过这个 /turtle1/rotate_absolute 的 action 来进行通信的
看看其数据类型 ros2 interface show turtlesim/action/RotateAbsolute,可以看到返回了三个参数,用 2 个 --- 分隔符分开,这些参数从上到下依次是:goal、feedback、result。

-
同样的,这个 action 也是有类似 topic、serve 相似的指令操作
ros2 action list # ros2 中的所有 action ros2 action list -t # ros2 中的所有 action,并显示数据类型 ros2 action info # 查看ros2的详细信息 -
action 的相关操作
-
往 goal 发送数据
ros2 action send_goal <action_name> <action_type> <values>例如要让小海龟旋转到方向向右,输入的值即为 0。这个 theta 的值是弧度,弧度 0 的时候就是朝向 x 轴方向。
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 0}"输入指令可以看到小海龟旋转,并返回旋转之后的最终朝向

-
3 ROS2 中的日志功能
ros2 中提供了 rqt_console 的 GUI 工具,用于查看有关系统运行状况的信息。借助 rqt_console,你可以持续收集这些消息,以更规整的方式仔细查看、过滤消息,保存消息,甚至重新加载已保存的文件,在其他时间进行分析。
在小海龟中,如果小海龟移动撞墙了,就会有大量的警告,而使用 rqt_console 就可以可视化显示这些警告信息。
执行以下指令:ros2 topic pub -r 1 /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: 0.0}}"
当小海龟撞墙以后,可以看到弹出非常多的 Warn,这就是日志中的警告功能。

但是实际上运行小海龟的终端一样会输出警告的日志,只是更少一点:

日志分为 5 个等级,根据不同的需求使用日志:
- Fatal(致命)消息:表示系统即将终止运行,力求保护自身免受损害。
- Error(错误)消息:代表严重问题,这类问题不一定会损坏系统,但会阻碍系统正常工作。
- Warn(警告)消息:提示出现异常行为或非理想结果,背后可能存在更深层问题,但不会直接破坏功能。
- Info(信息)消息:记录事件与状态更新,用于直观确认系统按预期运行。
- Debug(调试)消息:详细输出系统执行完整的分步过程。
可以通过配置 --log-level来修改日志的等级,执行以下指令将把日志的输出等级修改到 WARN 等级,也就是说,只有 Warn、Error、Fatal 三个等级被使用。
ros2 run turtlesim turtlesim_node --ros-args --log-level WARN
4 使用 launch 文件
在大多数教程中,每运行一个新节点,你都要打开一个新终端。当你构建愈发复杂的系统,需要同时运行大量节点时,反复打开终端、重新输入配置信息就会变得十分繁琐。
启动文件(launch file)可以同时启动并配置多个包含 ROS 2 节点的可执行程序。
例如:ros2 launch turtlesim multisim.launch.py,这是 ROS 的演示样例,该指令将同时启动两个小海龟

launch主要是使用 launch文件进行配置的,这个 multisim.launch.py 文件的内容如下:
from launch import LaunchDescription
import launch_ros.actions
def generate_launch_description():
return LaunchDescription([
launch_ros.actions.Node(
namespace='turtlesim1', package='turtlesim',
executable='turtlesim_node', output='screen'),
launch_ros.actions.Node(
namespace='turtlesim2', package='turtlesim',
executable='turtlesim_node', output='screen'),
])
先不管这个代码,知道可以通过代码来控制 launch 文件来启动多个节点就行了。
5 数据记录和数据回放
ros2 bag 是一款命令行工具,用于记录系统中各个话题上发布的数据。它收集任意数量话题传输的数据,并将其保存到数据库中。之后你可以回放这些数据,复现测试与实验结果。记录话题数据也非常适合用于分享你的工作,方便其他人复现你的实验。
用法:
-
记录指定话题的数据
ros2 bag record <topic_name>- 将在终端当前所在目录下,记录指定话题的产生的数据
-
同时记录多个话题的数据
ros2 bag record -o <记录文件名称> <topic1_name> <topic2_name>
-
查看记录的话题的数据
-
ros2 bag info <bag_file_name>
-
-
复现所记录的话题
-
ros2 bag play subset
-
6 参考文献
评论