什么是ROS2?
ROS(机器人操作系统)是用于机器人应用的开源软件开发工具包。ROS 为各行业的开发者提供了一个标准的软件平台,帮助他们从研究和原型设计一直推进到部署和生产,从驱动程序到最先进的算法,再到强大的开发工具,无需重复造轮子。
ROS的前身源自斯坦福大学人工智能实验室的STAIR项目和PR项目。2007年,Eric Berger和Keenan Wyrobek为了构建个人服务机器人,他们在Kenneth Salisbury机器人实验室开始开发ROS的核心组件。到了2014年,ROS推出首个长期支持版(LTS),这标志着ROS进入成熟阶段。
而ROS2则是在2017年推出,主要是为了解决ROS的实时性、分布式系统等局限,同时引入了DDS通信协议,增强对工业、自动驾驶等场景的支持。ROS2支持Linux、Windows 和 macOS,并且能通过micro-ROS支持各种嵌入式平台,这使得在机器人自主性、后端管理和用户界面方面的无缝开发与部署。它的分层支持模式使得新的平台(如实时和嵌入式操作系统)在获得关注和投资时,能够引入对它们的移植。
到了2022首个LTS版本ROS 2 Humble推出,技术体系逐渐稳定。2024年,ROS2 Jazzy发布,进一步优化了稳定性和功能性。到目前为止,ROS已成为机器人领域的事实标准,其覆盖服务机器人、工业自动化、医疗等领域,并催生全球机器人创业公司。而ROS2持续优化实时性、安全性,逐步向边缘计算和AI集成方向演进,极大的推动了智能机器人规模化应用。
主要基本概念
ROS2是一个基于强类型和匿名发布/订阅机制的中间件,它支持不同进程间的消息传递。
任何ROS2系统的核心都是ROS图谱。ROS图谱是指ROS系统中节点的网络以及通信连接形成的拓扑结构。
以下基本概念是ROS2基础知识的起点:
节点(Node)
节点(Node)是ROS2图谱中的参与者,它通过客户端库(Client libraries)与其他节点进行通信。节点可以在同一进程中,也可以在不同的进程,甚至在不同的机器上与其他节点进行通信。节点通常是ROS图谱中的计算单元;每个节点都应该完成一个逻辑上的任务。
节点可以向已经命名的主题(Topic)发布消息,将数据传递给其他节点,或者订阅命名的主题,从订阅的节点获取数据。它们还可以充当客户端(Service Client),让另一个节点代表自己执行计算操作,或者作为服务器(Service Server),为其他节点提供功能。对于长时间运行的计算,节点可以作为动作客户端(Action Client),让另一个节点代表自己执行计算操作,或者作为动作服务器(Action Server),为其他节点提供功能。节点可以提供可配置的参数用于运行时改变行为。
节点通常是由发布者、订阅者、服务的服务器、服务的客户端、动作服务器以及动作客户端等多种元素共同构成的复杂组合体,它们可以同时存在于同一个节点之中。节点间的连接通过分布式发现机制(通常是DDS)自动建立,无需显式配置。
示例场景,一个图像处理节点可能:
- 订阅camera/rgb/image_raw主题获取摄像头数据(订阅者)。
- 发布detected_objects主题传递检测结果(发布者)。
- 调用服务calibrate_camera校准相机参数(服务客户端)。
- 接收动作请求track_person并返回追踪状态(动作服务器)。
发现机制(Discovery)
ROS2的节点发现通过底层中间件自动完成,其过程可总结如下:
- 节点启动广播:当节点启动时,它会向同一个ROS域(由环境变量ROS_DOMAIN_ID设置)内的其他节点广播它的存在。其他节点也会响应此广播,发送自身信息以便建立连接并实现通信。
- 周期性保持活性:在初始发现阶段后,节点会定期广播其存在,从而与新加入的实体建立连接。
- 离线通知机制:当节点关闭时,它会主动通知其他节点自己已下线,确保网络中的节点状态始终同步。
- 基于QoS的连接过滤:只有当两个节点的服务质量QoS(Quality of Service)设置兼容时,才会建立连接。这是为了保障通信的可靠性和效率。
以ROS2内置的talker-listener示例为例:
- 在一个终端中运行C++编写的发布者节点,它会在某个主题上持续发送消息。
- 另一个终端中运行Python编写的订阅者节点,它会监听同一主题的消息。
你会观察到以下现象:
- 两个节点会自动发现彼此而无需手动配置IP地址或端口。
- 它们会立即建立连接,并开始双向消息传输。
- 如果关闭其中一个节点,另一个节点会检测到它离线并自动断开连接。
通信接口(Interfaces)
ROS2有三种类型的通信接口主题(topics)、服务(services)或动作(actions),使用一种简化的描述语言来描述这些接口,叫做接口定义语言(IDL)。这种描述方式使得ROS2能够轻松地针对几种目标语言自动生成该接口类型的源代码。
- 消息(msg):消息是ROS2节点在网络上向其他节点发送数据的一种方式,且不期望得到响应。主题(Topic)发布者使用消息来发布数据。消息在ROS2软件包msg/目录下的.msg文件中进行描述和定义。.msg文件由两部分组成:字段和常量。它们被用来为不同语言的消息生成源代码。例如:
csharp
# 消息
int32 my_int
string my_string
- 服务(srv):服务在ROS2软件包的srv/目录下的.srv文件中进行描述和定义。.srv由两部分组成:一个请求和一个响应。请求和响应都是消息声明, 中间用三个分隔符分隔。例如:
csharp
#请求
string str
---
#响应
string str
- 动作(action):与服务不同,动作可以是长时间运行的(持续数秒或数分钟),在执行过程中可以提供反馈信息,并且可以被中断。ROS2使用.action文件描述动作。它们由三个部分组成:一个目标、一个结果和反馈信息。每个部分本身都是一个消息声明。
csharp
#请求
bool enable
---
#结果
bool finish
---
反馈信息
int32 state
主题(Topic)
主题(Topic)是ROS2提供的三种主要通信接口类型之一,它适用于持续数据流的传输,例如传感器数据、机器人状态等信息。
ROS2是一个强类型匿名发布/订阅(Publish/Subscribe)系统。
发布/订阅(Publish/Subscribe)系统是一种数据生产与消费的模型,包含数据的生产者(发布者)和消费者(订阅者)。发布者与订阅者通过被命名的主题(Topic)进行通信,实体间使用共同名称相互发现。例如,创建发布者时需指定其发布的主题名称,订阅者需要使用同样名称订阅特定主题。同一主题名称下的所有发布者与订阅者可以直接通信。
核心特性:
- 一个主题可以有零个或多个发布者,也可以有零个或多个订阅者。
- 任一发布者向主题发送数据时,所有订阅者都会接收到该数据。
- 类似于电气工程,数据通过"总线"(Bus)在发布者与订阅者之间流动。
- 发布者或订阅者可以随时加入或离开系统,而不会影响其他组件的运行。
发布者或订阅者可以根据需要自由加入或退出,这意味着调试和内部分析检查是系统自然的延伸功能。比如使用ros2 bag record命令可以记录特定主题的数据流,其底层机制是为该主题创建一个新的订阅者,而不干扰系统原有数据流向。再比如通过ros2 topic echo等工具,可以随时查看主题的实时数据,而无需修改代码或重启节点。
服务(Service)
在ROS2中,服务指的是远程过程调用。换句话说,一个节点可以向另一个节点发起远程过程调用,后者会进行计算并返回结果。
在ROS2中,由于客户端通常是在等待服务返回结果,一个服务应当迅速返回。服务绝不应该用于长时间运行的进程,尤其是那些可能因特殊情况需要被抢占的进程。如果你有一个会进行长时间计算的服务,请考虑使用动作(action)来替代服务。
服务同样也通过服务名称来标识,这个名称看起来很像主题名称,但是属于不同的命名空间。
一个服务包括两部分:服务器和客户端。
服务器是一个会接收远程过程请求的实体,它会进行一些例如计算这样操作。需要注意的是,对于同一个服务名称而言,应当只有一个服务器。如果存在多个服务器,则无法确定哪一个服务器会接收客户端请求。
客户端是一个会请求远程服务器代其执行操作的实体。比如客户端创建创建并发送包含a和b的初始消息,并等待服务器计算出总和然后返回结果。与服务器不同的是,可以有任意数量的客户端使用相同的服务名称。
动作(Actions)
在ROS2中,动作是一个长时间运行的远程过程的调用,它是具有反馈功能,能够取消(Cancellation)或者抢占(Preemption)目标。
例如,机器人运行的高层状态机可能会调用一个动作,告知导航子系统前往一个航点,这可能需要数秒(或数分钟)才能完成。在此过程中,导航子系统可以提供关于其进度的反馈,而高层状态机则可以选择取消或抢占前往该航点的行程。
在ROS2中,动作应当是长时运行的程序,因为设置和监控连接会存在一定的开销。如果你需要的是短时间运行的远程程序调用,请考虑使用服务来替代动作。动作同样通过一个动作名称来标识,这个名称看起来也很像主题名称,但属于不同的命名空。
一个动作由两部分组成:动作服务器和动作客户端。
动作服务器是接收并处理远程过程请求的实体,负责执行相关操作。它在动作执行过程中持续发送反馈信息,并且响应取消(Cancellation)和抢占(Preemption)请求。同样的,每个动作名称应该始终只对应一个动作服务器。在存在多个相同名称的动作服务器的情况下,无法确定哪个动作服务器会接收到客户端请求。
动作客户端是一种会请求远程动作服务器代表它执行一个过程的实体。例如,动作客户端创建并发送包含订单信息的初始消息,并等待动作服务器计算出(订单处理)序列并返回该序列,同时它还会在处理过程中不断提供反馈信息。
参数(Parameter)
在ROS2中,参数与各个节点相关联。参数用于在节点启动时(以及运行时)对节点进行配置,而无需更改代码。参数的生命周期与节点的生命周期相关联,但是节点也可以实现某种持久性机制,以便在重启后重新加载之前保存的参数值。
参数通过节点名称、节点命名空间、参数名称和参数命名空间来定位。参数命名空间是可选的。
每个参数由一个键、一个值和一个描述符组成。键是一个字符串,值是以下类型之一:bool、int64、float64、string、byte、bool[]、int64[]、float64[]、string[]。描述符可以包含参数描述、取值范围、类型信息以及其他约束条件,默认情况下,所有描述符都是空的。
内部分析检查命令行工具
在ROS2中,提供了一套命令行工具(如ros2 node info、ros2 topic list)动态查看节点、主题、服务的实时状态 可以用--help命令查看所有命令。
bash
ros2 --help
以下是常用的子命令:
action:与ROS动作进行分析、检查和交互
bag:录制播放rosbag文件
component:管理组件容器
daemon:分析检查配置守护进程
doctor:检查ROS设置中可能存在的问题
interface:显示有关接口的信息
launch:运行、分析、检查launch文件
lifecycle:分析、检查、管理生命周期的节点
multicast:多播调试命令
node:分析、检查节点
param:分析、检查、配置节点上的参数
pkg:分析、检查包
run:运行节点
security:配置安全设置
service:分析、检查、调用服务
test:运行启动测试
topic:分析、检查、发布主题
trace:用于获取有关节点执行信息的跟踪工具(仅在 Linux 上可用)
wtf:doctor的别名
启动系统(Launch)
ROS2系统通常由运行在多个不同进程(甚至不同机器)上的众多节点组成。虽然可以分别运行每个节点,但这种方式很快就会变得繁琐。
而启动系统的作用是通过一条命令自动运行多个节点。它帮助用户描述系统的配置,然后按照描述执行。系统配置包括要运行哪些程序、在何处运行它们、向它们传递哪些参数,以及ROS特有的一些约定,这些约定通过为系统中的每个组件赋予不同的配置,让它们更容易在整个系统中被复用。启动系统还负责监控所启动进程的状态,并对这些进程的状态变化进行报告或者做出反应。
上述所有内容都在一个启动文件中进行指定,该文件可以用Python、XML或YAML编写。然后可以使用ros2 launch命令运行这个启动文件。
资源汇总
-
ROS官网:
-
ROS Wiki:
-
ROSCon年度开发者大会:
-
ROS Robots:
-
ROS2 文档:
-
ROS2 Github:
-
ROS2自主导航:
-
Gazebo:三维物理仿真平台:
-
自动驾驶:
-
路径规划:
-
Ubuntu Wiki:
-
斯坦福大学公开课 ------ 机器人学:
-
台大机器人学之运动学:
-
Self-Driving Cars with ROS2 & Autoware
关注【智践行】,我们一起成长