| 编辑推荐: |
文章主要介绍了ROS在自动驾驶中的应用相关内容。希望对您的学习有所帮助。
本文来自于微信公众号汽车电子与软件,由火龙果软件Alice编辑、推荐。 |
|
#01 ROS和RTOS都在自动驾驶存在
首先不要混淆ROS和RTOS。RTOS,全称为Real Time Operating System,即实时操作系统,它是一种专为实时应用程序设计的操作系统。实时操作系统的主要特点是其能对外部事件作出快速、可预测的响应,确保在规定的时间内完成特定任务。所以RTOS在车辆和无人机电控用的特别多,因为要即时响应,晚一点就车毁人亡了。
而ROS是一种专为机器人技术设计的框架和软件集合,也是本文的主角。
车辆行业和无人机行业又需要ROS来做高层的智能控制,又需要RTOS在底层执行实时操作。所以经常混在一起,大家一看这不行啊,所以专门给实时操作系统加个T字母。
ROS代表机器人操作系统,但它实际上不是一个操作系统,而是构建在真正操作系统上的一个中间件,旨在加快机器人平台开发时间的框架。要了解ROS是什么,先了解ROS的动机----软硬件解耦,让软件与算法人员聚焦编程就行了。
大多数新手程序员认为,你必须对电子学甚至机械学有深入的了解才能编程机器人。他们认为硬件和软件是如此紧密地结合在一起,你必须深入地了解两者才能构建任何有用的东西。这吓退了很多程序员,包括老手,都是只敲键盘不拿焊枪的。
从笔者使用经验,ROS就是一个伪装成操作系统的微服务框架,也很类似于消息队列kafka。或者说可以直接把ROS理解为沟通各个硬件的消息队列。

图 1 ROS架构图,来自互联网
| 概念 |
描述 |
| 节点(Node) |
执行特定任务的程序。每个节点都有自己的功能,如发布消息、订阅主题或提供服务。 |
| 主控(Master) |
一个特殊的节点,负责管理网络中的所有节点之间的通信。它维护节点注册表并提供名称解析服务。 |
| 参数(Parameters) |
节点之间共享的动态配置值。参数可以在运行时进行修改,以便灵活调整节点的行为。 |
| 消息(Messages) |
在发布者和订阅者之间交换的数据结构。消息通常包含传感器数据、命令或其他信息。 |
| 服务器 (Server) |
提供服务的节点。服务是一种请求-响应机制,允许客户端发送请求并接收响应。 |
| ROS计算图 (ROS Computational Graph) |
表示ROS系统中所有节点及其相互关系的抽象表示。它包括节点、主题、服务和参数。 |
| 级别(Level) |
指节点在ROS系统中的层次结构。节点可以组织成层次结构,以更好地管理和理解复杂性。 |
| 主题(Topics) |
一种消息传递机制,发布者发布消息到某个主题,订阅者从该主题接收消息。 |
| 服务(Services) |
一种请求-响应机制,允许客户端发送请求并接收响应。服务通常用于更复杂的交互。 |
| 数据袋(Bags) |
用于记录和回放ROS消息的文件格式。数据袋可以捕获ROS系统的运行状态,便于调试和测试。 |
表 1 ROS操作系统的元素解析
#02 ROS的一个实践举例
假设自动驾驶车辆或者无人机上有一个摄像头。还有两个过程需要这个摄像头的图像作为输入。比如,一个机器学习程序和一个位置估计程序。传没有ROS时,需要手动将图像序列化(压缩)并流式传输到其他两个程序可以读取的端口。但如果端口改变或者摄像头改变,很多东西都需要重新配置。这在程序员圈子称为“级联修改”,是最头疼的事情之一,是无数加班的来源。
然而,在ROS中,这种交互可以变得更加流畅。让我们考虑我们有的程序作为ROS节点,即负责单一模块化目的的程序,具有特定的输入或输出:
1. 摄像头图像流节点
a. 输出(OUT):摄像头图像
2. 用于识别物体的机器视觉系统
a. 输入(IN):摄像头图像
b. 输出(OUT):识别对象的列表
3. 同时定位与地图(也就是SLAM)构建系统
a. 输入(IN):摄像头图像
b. 输出(OUT):车辆位置
在ROS中,这些组件被视为节点——设计用于执行特定任务的独立程序,具有定义的输入和输出。
以下是ROS如何简化交互的过程:
发布者和订阅者:摄像头图像流节点发布摄像头图像。机器视觉系统和同时定位与地图构建系统订阅该主题以接收摄像头图像。
主题和消息:ROS 使用主题来发布消息。在这个例子中,摄像头图像在一个主题上发布,而机器视觉系统和SLAM系统订阅该主题以获取最新的摄像头图像。
服务和服务动作:虽然在本例中不直接适用,但ROS也支持服务和服务动作,用于更复杂的交互。
通过利用ROS,你不需要担心手动管理数据流或硬件变化时重新配置端口。相反,你可以专注于开发和集成执行特定任务的节点,而ROS则处理它们之间的通信和同步。
这些节点的输出定义了ROS主题,即单一类型数据的单一流。每个主题都有一个特定的名称,可以引用。在我们的示例中,一些主题可能是:
/drone/camera 用于相机图像
/drone/recognised_objects 用于机器视觉系统
/drone/slam_position 用于SLAM系统
看到从这些节点的输入和输出创建了两条通信路径。
A[相机] -->|out| node1[drone/camera]
node1 --in--> C[机器视觉系统]
node1 --in--> D[SLAM系统]
现在,ROS遵循发布/订阅模型进行通信。这意味着节点作为输出将数据发布到主题。但是,只有当其他节点也订阅相同的主题时,数据才会在网络上传输。
因此,在我们的示例中,我们最终有:
一个发布相机图像的节点:发布到 /drone/camera
一个用于识别对象的机器视觉系统:订阅 /drone/camera发布到 /drone/recognised_objects
一个同时定位与地图构建系统:订阅 /drone/camera发布到 /drone/slam_position
很明显的,ROS不像can总线是广播的(ROS中只有参数是广播的),而是谁订阅发给谁。原因也很简单,can总线发的都是一些小参数。ROS的数据包很多都是大家伙,点云或者图像等等。

图 2 ROS运行图
发送的数据可不是任意的内容。数据或消息是一个特定模板化的数据包,其中包含了为特定使用场景指定的内容,有明确定义的数据结构。在关于
/drone/slam_position 主题topics的例子中,消息的类型可能是来自其定义的geometry_msg:
# 这个消息包含了一个自由空间内点的位置
float64 x
float64 y
float64 z
也就是说/drone/slam_position 主题发布的消息必须具有msg.x、msg.y 和
msg.z 字段,而订阅者只会接收到具有这些字段的消息。标准的ROS库中有许多消息类型,但许多库也会定义自己的消息类型。
如果你将两个主题(请求主题和响应主题互相通信)结合起来,就可以实现双向通信的概念。服务在实现层就是双向主题,由请求主题和响应主题组成,但用户角度来看,它作为一个单一的通信类型来运作。类似于消息,服务有定义好的请求和响应类型(例如,参见
std_srvs/srv/SetBool.srv)。通常情况下,服务请求会等待响应到达后再继续执行。所有这些操作都是异步并且并行发生的。
每个节点都可以通过一组参数进行配置,这些参数会被广播给其他所有节点。参数通常是节点中某些方法的配置值,有时可以在启动时或通过服务动态更改,以允许节点提供可调整的功能。例如,超时时间或循环频率(比如图像多少ms发出一次)的值。
ROS有两个版本:ROS1和ROS2。ROS1最初由Willow Garage在2007年创建,已在开源机器人社区中变得非常庞大。然而多年的实践和用户反馈让他们意识到缺少许多重要功能——而且没法增加这些功能而不破坏ROS1,只好再起炉灶ROS2。此外,最新的ROS1发行版(ROS
Noetic)即将到达其支持生命周期的终点(EOL 2025),此后将不再有ROS1。
#03 RTOS是OS一族的成员,ROS是构建在OS上的中间件
| 特性 |
操作系统(OS) |
机器人操作系统(ROS) |
| 主要用途 |
管理计算机硬件与软件资源,提供用户界面和其他核心功能 |
为机器人应用提供硬件抽象、底层设备控制、常用服务、消息传递机制、软件包管理等 |
| 发布时间 |
1960s 年代起 |
2010 年代起 |
| 核心概念 |
进程管理、内存管理、文件系统、用户界面 |
节点(Node)、主题(Topic)、服务(Service)、参数服务器(Parameter
Server) |
| 编程语言 |
多种,如C、C++、Java、Python |
Python 和 C++ |
| 支持的平台 |
多种计算机架构,如x86、ARM |
多种计算平台,包括嵌入式系统和高性能计算平台 |
| 开发社区 |
多个,如Linux、Windows、macOS |
开源社区,主要由学术界和工业界贡献 |
| 消息传递机制 |
通常通过系统调用实现 |
通过发布/订阅模式实现消息传递 |
| 硬件抽象层 |
提供基本的硬件抽象 |
提供丰富的硬件抽象层,便于不同传感器和执行器的集成 |
| 应用领域 |
计算机操作、文件管理、网络通信等 |
机器人应用,包括导航、感知、规划、控制等 |
| 生命周期 |
不同的发行版有不同的生命周期 |
有长期支持(LTS)版本,如 ROS2 Foxy Fitzroy |
| 更新方式 |
通过软件包管理和更新工具 |
通过软件包管理和更新工具,支持版本控制 |
从表中可见,传统操作系统关心的内存管理,文件系统管理,进程管理,线程管理等等,ROS一概不关心。之所以ROS能够不关心这些,在于它本来就是中间件,是构建在在操作系统上的,底下真正的操作系统替它把这些都干了。
| 特性 |
实时操作系统(RTOS) |
机器人操作系统(ROS) |
| 主要用途 |
实现实时应用,确保任务在确定的时间内完成 |
为机器人应用提供硬件抽象、底层设备控制、常用服务、消息传递机制、软件包管理等 |
| 发布时间 |
1970s 年代起 |
2010 年代起 |
| 核心概念 |
优先级调度、时间片轮转、中断处理 |
节点(Node)、主题(Topic)、服务(Service)、参数服务器(Parameter
Server) |
| 编程语言 |
C、C++ |
Python 和 C++ |
| 支持的平台 |
嵌入式系统、小型计算机、实时控制系统 |
多种计算平台,包括嵌入式系统和高性能计算平台 |
| 开发社区 |
供应商和开源社区 |
开源社区,主要由学术界和工业界贡献 |
| 消息传递机制 |
通过事件队列、信号量、互斥锁等方式实现 |
通过发布/订阅模式实现消息传递 |
| 硬件抽象层 |
提供基本的硬件抽象 |
提供丰富的硬件抽象层,便于不同传感器和执行器的集成 |
| 应用领域 |
工业自动化、航空航天、医疗设备、汽车电子等 |
机器人应用,包括导航、感知、规划、控制等 |
| 响应时间 |
确定性的,能在严格的时间限制内响应 |
非确定性的,响应时间依赖于系统负载 |
| 内存管理 |
通常使用固定内存分配策略 |
动态内存管理,支持多种内存管理策略 |
| 可靠性和稳定性 |
高可靠性,常用于关键任务 |
较高可靠性,但依赖于网络和节点间的通信 |
| 示例 |
FreeRTOS, VxWorks, QNX |
ROS 1, ROS 2 |
整个ROS系统在计算方面被设计为完全分布式的,因此不同的计算机(嵌入式MCU,上位机,云
端服务器等等)可以参与控制过程,并作为一个单一实体(即机器人)协同工作。
由于这些特点,ROS是自动驾驶汽车和无人机以及无人机集群的理想工具。毕竟自动驾驶汽车可以被视为载人载货的机器人,可以使用相同类型的程序来控制它们。
比如从事下一代氢能源重卡开发的中国hybot公司,就是hydrogen + robot,氢能驱动的机器人。
ROS在机器人研究中已经创建了大量的关于各种传感器的代码和大量的感知决策控制的代码。这样的知识宝库当然要利用起来。自动驾驶汽车需要创建能够构建地图、利用激光雷达或GPS定位机器人、沿着地图规划路径、避开障碍物、处理点云或相机数据以融合和识别障碍物等算法……几乎所有为轮式机器人导航所需的算法几乎可以直接应用于自动驾驶汽车。如果说有例外就是汽车的运行路径必须比机器人的更加平滑,不能急拐弯。因此,既然这些算法已经在ROS中创建,自动驾驶汽车可以直接使用现成的解决方案。
另外ROS已经具备了可视化工具。ROS开发了一套图形工具,可以轻松记录和可视化传感器捕获的数据,并以综合方式表示车辆的状态。
使用ROS启动自动驾驶汽车项目相对简单。可以从一个简单的轮式机器人开始,配备一对轮子、一个摄像头、一个激光扫描仪和ROS导航堆栈,几个小时内就可以设置好。这可以作为理解整个系统如何工作的基础。特别对于新组建的团队,现在很多OEM的自驾团队都是刚毕业的年轻人组成的。整个团队都理清脉络后,可以转向更专业的设备,例如采购一辆已经准备好进行自动驾驶实验的汽车,并具有完整的ROS支持(如Dataspeed
Inc. Lincoln MKZ DBW套件)。
很多自动驾驶汽车公司已经意识到这些优势,并开始在他们的开发中使用ROS。使用ROS的公司示例包括宝马(2015年ROSCon上演示过)、博世或nuTonomy(新加坡的自动驾驶公司,2017年,nuTonomy
宣布与新加坡政府合作,在新加坡的公共道路上进行自动驾驶出租车试点项目,这是全球首个公开道路上的自动驾驶出租车服务之一。同年,nuTonomy
被自动驾驶汽车技术公司 Aptiv(当时称为德尔福汽车系统)收购)。
#04 ROS1和ROS2主要用在开发而非量产
如前所述,“很多自动驾驶汽车公司已经意识到这些优势,并开始在他们的开发中使用ROS“,但本文并没有说在量产中使用ROS。量产中限制ROS的主要是ROS实时性和随着实时性而来的法律法规认证,简单说就是ROS12作为消息中间件在自动驾驶的巨大数据量下传递速度是否够。
ROS2已经采用DDS(ROS的DDS)来增强和保证传输速度。有2025年最新文献《Open-Source
Autonomous Driving Software Platforms: Comparison
of Autoware and Apollo》报道最新的autoware就是基于ROS2的,“Autoware
is based on ROS2, which employs Data Distribution
Service (DDS) as middleware ”。
在ROS2(ROS1中没有)中,DDS(数据分发服务,Data Distribution Service)扮演着至关重要的角色。DDS是一种实时数据传输协议,它允许系统中的不同组件以高效且可靠的方式进行通信。通过DDS,ROS节点可以无缝地交换信息,确保数据的实时性和一致性。这种机制主要就是为了提升系统的整体性能。
而这篇文献本身就是用来比较Apollo和Autoware(基于ROS2和DDS)的传输速度的。

图 3 《Open-Source Autonomous Driving Software Platforms:
Comparison of Autoware and Apollo》的部分比较表
至于我们提到宝马(2015年ROSCon)上演示过开发中使用ROS,可参考https://roscon.ros.org/2015/presentations/ROSCon-Automated-Driving.pdf,这个案例用于BMW
335I GT第二代原型的开发阶段。

图 4 BMW 335I GT,来自/ROSCon-Automated-Driving.pdf

图 5 宝马团队陈述自己选择ROS系统(那时是指ROS1)的原因,来自/ROSCon-Automated-Driving.pdf
ROS在宝马团队2015年研究中的角色主要还是回放录制的数据包来反复训练自动驾驶算法(深度学习模型)。毕竟在试车场上一遍遍跑车成本高昂,而且即使路线完全一样,每一次录制的传感器数据也会微小不同,导致模型不稳定。最好是一次录制(这里的一次是针对一个场景,不是不同场景共用一次),存储为数据包bag,然后在服务器端反复训练自动驾驶算法,最后把训练好的自动驾驶算法进行嵌入式改写,并部署到量产车辆上。目前国内不少OEM的自动驾驶仿真平台就是这个建设思路,而且报价颇高,都是千万级起步。
#05 总结:值不值得学ROS?
既然ROS目前主要用在研发阶段的自动驾驶,而不是量产阶段,从功利角度看值不值得学?
值得,三个简要理由:
1、自动驾驶产业链分工详细,仅仅是算法预研阶段(ROS的用武之地)就贡献大量高薪岗位,笔者经常遇到主要靠matlab和python(pytorch,tensorflow)的高端研究者,而他们不关注下游算法在MCU或者SOC上的嵌入式落地。
2、自动驾驶仿真平台本身本身就是庞大市场。
3、ROS2还在不断进化,而且已经是某些自动驾驶软件平台的骨干通信机制。 |