本文我们将基于 turtlesim 样例,系统梳理下 ros2 的命令行使用,以及相关概念(基本同 ros1),为后面的编程学习做准备。
本文参考资料如下:
(1)ROS高效入门第二章 – 基本概念和常用命令学习,基于小乌龟样例
(2)ros2 humble tutorials cmd line
(3)ros2 release
(4)fishros 快速安装 ros2
(1)早在2015年,ROS官方就已经启动了ros2的设计开发,并一直与ros1并行前进。直到2022年5月,ROS 官方推出了 ros2 的第一个五年长期支持版 Humble Hawksbill(谦逊的玳瑁龟),搭配 ubuntu22.04使用。humble 的发布标志着 ros2 的成熟,具体见 ros2 的发版历史:ros2 release
(2)本系列文章,我们使用 ros2 humble + ubuntu22.04 的组合。硬件上,本文选择一台 Thinkpad T14 i7 + Nvidia MX450 ,并直接在物理机安装 ubuntu22.04 ,不搞虚拟机,不搞双系统。
(3)有了物理机的 ubuntu22.04 后,本文推荐读者使用 fishros 的一键 ros2 安装脚本,跟着脚本提示,很快就能完成整个 ros2 humble 的安装,非常方便快捷。具体信息读者也可以看原博客:fishros install ros2
wget http://fishros.com/install -O fishros && . fishros
(4)ros2 安装完成后,可以使用如下命令,测试安装结果。从输出截图可以看出,ros2 的安装根目录是:/opt/ros/humble。
printenv |grep ros
(1)1948年,美国人瓦尔特制作了一个形似乌龟的机器人,这是人类历史上第一个自主移动的机器人。后来MIT的实验室也搞过一个像乌龟的机器人。于是,乌龟就慢慢成了机器人的代名词了,ros 的图标就是各种小乌龟。ros2 仍然准备了一个 turtlesim 小样例,让大家用这个直观的体验 ros 。
(2)在 ROS2高效学习第一章 – ros2整体介绍及DDS引入 中,我们讲到了 ros2 最大的升级就是引入了 DDS ,去除了 master 中心节点。因此,在 ros2 启动 turtlesim ,只需要开两个窗口,然后将光标放在 turtle_teleop_key 的窗口上,就可以使用方向键控制小乌龟运动。
ros2 run turtlesim turtlesim_node
ros2 run turtlesim turtle_teleop_key
(1)ros 最重要的一个概念就是节点node,一个节点往往是一个可执行程序(c++,python等),负责执行一个特定的单一任务,比如发送图像数据的节点,控制车辆运动的节点。节点之间可以通过话题topic,服务service,参数parameter和动作action相互通信,形成一个网络拓扑,即 ros graph,最终完成一个复杂的任务,比如自动驾驶车辆。
(2)以2.2节的小乌龟样例为例,学习下几个常用的节点调试命令:
启动节点:
ros2 run turtlesim turtlesim_node
ros2 run turtlesim turtle_teleop_key
# 以重命名的方式启动节点
ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle
查看节点信息,主要是话题,服务,参数,动作信息:
ros2 node list
ros2 node info /my_turtle
(1)两个节点node之间需要通信,最重要的方式就是话题 topic ,其相当于一个公共汽车 bus ,里面装载两个节点间约定好格式的消息 msg。
(2)DDS 采用发布/订阅模型,发出 topic 的叫发布者 publisher,接收 topic 的叫订阅者 subscriber。一个节点 node 可以发布任意多个不同 topic,也可以订阅任意多个不同 topic。通常情况下,系统不允许或者不建议多个节点 node 发送同名 topic,不然下游节点就不知道该听谁的了。
(3)节点 node 之间的话题 topic 通信属于异步通信,即话题的上下游节点并不需要知道对方的存在,各自只管发或收就行,这样就使得系统是松耦合的,健壮性更强。
(4)ros 中消息 msg 以 .msg 文件存储,与语言无关,是通信节点预先约定好的一种格式,消息定义采用三段式(ros1是两段式):
ros2:package-name/msg/type-name
举例:geometry_msgs/msg/Twist
ros1: package-name/type-name
举例:geometry_msgs/Twist
(5)一组话题和消息的调试命令
# 查看话题列表
ros2 topic list
# 查看话题列表以及对应msg
ros2 topic list -t
# 查看消息结构体
ros2 interface show geometry_msgs/msg/Twist
# 实时查看话题内容
ros2 topic echo /turtle1/cmd_vel
# 查看话题具体信息(只能看到订阅和发布个数)
ros2 topic info /turtle1/cmd_vel
# 实时查看话题频率
ros2 topic hz /turtle1/pose
# 命令行发布话题
ros2 topic pub <topic_name> <msg_type> '<args>'
举例:ros2 topic pub --rate 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: 1.8}}"
(6)利用 rqt 可视化查看话题收发节点,例如截图中的topic:/turtle1/cmd_vel
# 输入rqt,然后: Plugins > Introspection > Node Graph
rqt
# 或者直接输入
rqt_graph
(1)不同于话题topic的异步通信,单向通信和广播通信,服务service是同步通信,应答式(请求和回复)通信,同一时间是一对一通信。服务service采用Client/Server模型,支持一个Client对应一个Server,也支持多个Client对应一个Server,但不支持一个服务有多个Server,否则Client不知道该听谁的反馈了。
(2)ros 中服务service以 .srv 文件存储,与语言无关,是通信节点预先约定好的一种格式,消息定义采用三段式(ros1是两段式):
ros2:package-name/srv/type-name
举例:turtlesim/srv/Spawn
ros1: package-name/type-name
举例:turtlesim/Spawn
(3)一组话题和消息的调试命令
# 查看服务列表
ros2 service list
# 查看服务列表以及对应数据结构名
ros2 service list -t
# 查看服务数据结构具体域信息
ros2 interface show turtlesim/srv/Spawn
# 根据服务数据结构名查找当前的服务
ros2 service find turtlesim/srv/Spawn
# 命令行调用服务
ros2 service call <service_name> <service_type> <arguments>
清楚小乌龟轨迹:ros2 service call /clear std_srvs/srv/Empty
生成一个小乌龟:ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
(1)参数parameter可以认为是节点node的配置,适用于那些不会随时间频繁变更的信息,可以是整型(integer)、浮点(float)、布尔(boolean)、字典(dictionaries)和列表(list)等数据类型,并使用 yaml 格式存储记录。不同于 ros1 的 rosmaster 统一管理参数,ros2 中节点参数由节点自己管理。
(2)一组参数parameter的调试命令
# 查看参数列表
ros2 param list
# 获取节点的某个参数
ros2 param get <node_name> <parameter_name>
举例:ros2 param get /turtlesim background_g
# 设置节点的某个参数
ros2 param set <node_name> <parameter_name> <value>
举例:ros2 param set /turtlesim background_r 150
# dump某个节点的所有参数
ros2 param dump <node_name>
举例:ros2 param dump /turtlesim > turtlesim.yaml
# 利用yaml文件批量加载节点参数(可读写参数,只读参数不行)
ros2 param load <node_name> <parameter_file>
举例:ros2 param load /turtlesim turtlesim.yaml
# 启动节点时,利用yaml批量加载节点参数
ros2 run <package_name> <executable_name> --ros-args --params-file <file_name>
举例:ros2 run turtlesim turtlesim_node --ros-args --params-file turtlesim.yaml
(1)话题 topic 是异步通信,是广播通信,通信上下游没有应答机制。而服务 service 是一种应答(请求和回复)的通信机制,采用 C/S 模式,是同步通信。
(2)动作 action 类似服务 service,也有应答机制,也是C/S模式。不同之处在于动作 action
常用于大型任务的通信沟通,通常需要持续一段时间,比如机器人导航任务。在任务执行过程中,动作 server 端可以周期地向动作 client 端发布任务进展,并在任务结束时,发布任务处理结果。而动作 client 可以在任务执行中间发送任务终止请求。
(3)动作 action 复杂的通信机制并不是完全从零搭建,其本质是基于话题 topic 和 服务 service 实现。其中任务 goal 的发布和确认,处理结果 result 的申请和回复,以及任务取消都使用服务 service;任务执行过程中的定期反馈使用话题 topic,具体见下图。
(4)ros2 中动作 action 以 .action 文件存储,与语言无关,是通信节点预先约定好的一种格式,消息定义采用三段式:
ros2:package-name/action/type-name
举例:turtlesim/action/RotateAbsolute
(5)一组动作 action 的调试命令(turtlesim 自带了一个 action 功能,即小乌龟转向)
# 查看动作列表
ros2 action list
# 查看动作列表以及对应的消息类型
ros2 action list -t
# 查看小乌龟转向动作信息,主要是client和server节点信息
ros2 action info /turtle1/rotate_absolute
# 查看动作消息定义
ros2 interface show turtlesim/action/RotateAbsolute
# 手动发布动作指令
ros2 action send_goal <action_name> <action_type> <values>
举例:ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"
# 手动发布动作指令,并要求返回执行进度
举例:ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedback
(1)节点名 node name、话题名 topic name、服务名 service name,参数名 parameter name 和动作名 action name统称为计算图源,使用字符串标识,以 turtlesim 为例:
# 节点名
/teleop_turtle
/turtlesim
# 话题名
/turtle1/cmd_vel
/turtle1/pose
# 服务名
/clear
/spawn
/teleop_turtle/get_parameters
/turtle1/teleport_relative
# 参数名
/teleop_turtle/scale_angular
/turtlesim/background_b
# 动作名
/turtle1/rotate_absolute
(2)ros 为计算图源命名设计了一套规则,先介绍两个概念:全局名称和相对名称。全局名称指以 “/” 开头的名称,对整个软件系统而言没有任何二义性。节点模块内部一般使用相对名称,例如:turtle1/cmd_vel。如果节点模块没有指定命名空间,则默认命名空间就是 “/” 。程序运行时,会将相对名称解析为全局名称,也就是把命名空间和相对名称拼在一块,即:/turtle1/cmd_vel。
相对名称这套机制,最大的好处是为 package 的移植提供便利,用户能方便地将某个节点和话题移植到其他的命名空间,而不用担心命名冲突。
(3)除了全局名称和相对名称,还有私有名称,以波浪号打头 “~ “,如:~max_vel。
ros运行时,也需要将私有名称解析为全局名称。与相对名称不同的是,私有名称不是用当前默认命名空间,而是用的它们节点名称作为命名空间。如节点名为:/turtlesim1,私有名称为:~max_vel,则相应的全局名称为:/turtlesim1/max_vel。
私有名称主要是为大家写代码,移植开源库提供便利。
(1)ros 提供了一套工具,用来记录和回放程序运行时的 topic 数据(服务和参数无法录制),即 ros2 bag,这套工具对测试机器人软件非常高效。在ros1时代,rosbag 采用自定义的二进制文件格式存储,以 .bag 文件保存;到了 ros2 ,ros2 bag 使用 SQLite3数据库文件格式存储,以 .db3 文件保存,通用性和安全性更好。
(2)ros1 支持命令行方式打印 bag 内topic 内容,以及命令行方式对 bag 进行各种过滤处理,样例如下。而 ros2 废弃了这些命令行功能,用户需要自己使用编程接口实现这些功能。
rostopic echo -b square_cmd_1.bag /turtle1/pose
rosbag filter square_cmd_1.bag square_cmd_1_filter.bag "t.to_sec() > 1684977250.80 and t.to_sec() < 1684977450.45"
(3)尽管 ros2 废弃了一些命令行功能,但最常用的命令行 bag 处理三件套保留了下来:bag 录制,bag 统计信息查看,以及 bag 回放功能。
# 录制所有 topic (也可以不指定文件夹名)
ros2 bag record -a -o bag_test
# 录制特定 topic
ros2 bag record -o bag_test /turtle1/cmd_vel /turtle1/pose
# 查看 bag 统计信息
ros2 bag info bag_test
# 回放 bag
ros2 bag play bag_test
(1)节点运行时,运行 log 会打印在当前窗口上,但 ros 也提供了一个可视化工具 rqt_console 帮助更方便的查看 log,其能统一收集当前系统所有节点的日志,并提供过滤,查询等便捷功能,更具体的用法这里暂不深究。
# 启动 rqt_console
ros2 run rqt_console rqt_console
# 让小乌龟撞墙,显示 warn log
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}}"
本文基于小乌龟样例,系统学习了 ros2 命令行以及相关概念。下一章我们将开始学习 ros2 的编程知识,并以第一个 hello_world 样例,学习工作空间,软件包 package,launch文件,两套 API 接口,并体会 ros2 colcon 的使用。