无人驾驶感知智能
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.5 基于ROS的无人驾驶技术

ROS是一个功能强大、灵活的机器人编程框架,从软件构架的角度来看,它是一个基于消息传递通信的分布式多进程框架。机器人行业长期以来一直在使用开源贡献者开发的许多著名机器人开源库,如基于quaternion的坐标转换、3D点云处理驱动和定位算法SLAM。

由于ROS本身基于消息机制,开发者可以根据功能将软件分解成模块,每个模块只负责读取和分发消息,模块间通过消息关联。如图3所示,最左边的节点可能负责读取硬件驱动(如Kinect)中的数据,该驱动器被打包为消息,ROS底层识别并分发到消息的用户。本书主要使用的是ROS的melodic版本,各版本的ROS如图1.15所示。

图1.15 各版本的ROS

ROS 1.0源自Willow Garage PR2项目,由ROS Master、ROS Code和ROS Service三大部分组成。其中,ROS Master的主要功能是为服务命名,它存储启动运行时所需的参数、消息发布的上游节点和接收的下游节点的连接名与连接方式,以及现有ROS服务的连接名;ROS Code是真正的执行模块,它处理传入消息并向下游节点释放新消息;ROS Service是一个特殊的ROS节点,它相当于一个接受请求并返回请求结果的服务节点。

对ROS 2.0的改进主要是为了使ROS能够达到工业级的操作标准,采用了数据分发服务(DDS),这是一种工业级别的中间件,负责可靠的通信、动态发现通信节点,以及通过共享内存(Shared Memory)提高通信效率。采用DDS技术,所有节点的通信拓扑结构都依赖于动态P2P的自发现模式,从而消除了中间中心节点Master。

在无人车驾驶系统中,仍然可以选择ROS 1.0而不是ROS 2.0,主要考虑以下几点。

(1)ROS 2.0是一个正在开发的框架,许多功能仍然不完整,需要更多的测试和验证。在无人驾驶环境中,稳定性和安全性是最重要的,必须在经过验证的稳定系统的基础上,确保系统的稳定性、安全性和性能,以满足无人车的要求。

(2)DDS本身成本较高。我们发现在一般的ROS通信场景(100K发送端接收通信)中,DDS的ROS吞吐量不如ROS,这主要是因为DDS框架本身比ROS更昂贵,而且使用DDS后CPU的占用率明显较高。然而,随着DDS的使用,ROS的高优先级吞吐率和组播能力显著提高。

(3)DDS接口的复杂性。DDS本身是一个庞大的系统,具有极其复杂的接口定义和薄弱的文档支持。

如上所述,系统可靠性是无人驾驶系统最重要的特征。我们来看几个场景:

(1)ROS Master在系统运行过程中出现错误,导致系统崩溃;

(2)其中一个ROS节点出现错误,导致系统功能部分丧失。

这些情况中的任何一种都可能在无人驾驶环境中造成严重后果。在工业领域应用中,可靠性是ROS的一个非常重要的设计考量,但目前的ROS设计并没有充分考虑到这一点。下文将讨论实时系统所涉及的一些要素。

ROS的重要节点需要热备份,以便在停机时可以切换。在ROS 1.0的设计中,主节点维护系统工作所需的连接、参数和主题信息。如果ROS 1.0的主节点崩溃,系统可能无法正常工作。有许多去中心化的解决方案可以在一个主从节点(类似于ZooKeeper)中实现,它需要对主节点的书面信息进行备份,然后将其切换到主备份节点,并在主节点关闭时使用备份主节点的信息进行初始化。

对运行中的节点进行实时监控,发现严重错误信息及时报警。目前,ROS没有对监控进行很多结构性思考,但这是最重要的方面。对于运行时的节点,监视它们的运行数据,如应用层统计信息、运行状态等,有利于将来的调试、错误追踪等。

从软件构架来看,实时监控主要分为3个部分。

(1)ROS节点层监控数据API,允许开发人员通过统一的API需要记录的统计信息。

(2)监控服务端定期接收节点的监控数据(用于紧急警报,节点可以将消息推送到监控服务)。

(3)监控服务端能够访问来自节点的数据。

监控服务端获取监控数据后,对数据进行整合、分析和记录,发现异常信息及时报警。

在发生节点宕机的情况下,需要通过重新启动机制来恢复节点,这种重新启动可能是无状态的,但在某些情况下也必须是无状态的,所以状态的备份尤为重要。节点中断检测也很重要,如果检测到节点中断,必须使用备份数据快速重新启动,该功能已在ZooKeeper框架中实现。

由于无人驾驶系统的模块众多,各模块之间的信息交互频繁,所以提高系统的通信性能将大大提高整个系统的性能。提高性能的方法主要有3种。

(1)同一机器上的ROS节点之间的当前通信使用网络栈的Loop-Back机制,这意味着每个数据包需要经过多层软件栈的多层处理,造成不必要的延时(每次约20μs)和资源消耗。为了解决这个问题,可以使用共享内存将数据memory-map到内存中,然后只传输数据的地址和大小,从而将数据传输延时限制在20μs以内,节省了大量的CPU资源。

(2)现在,当ROS进行数据广播(Broadcast)时,基本的实现实际上是使用多播(Multipleunicast)机制,或多个点对点传输。如果将数据传递给5个节点,则相同的数据将被复制5份,这就造成了资源的极大浪费,尤其是内存资源。此外,这将对通信系统的吞吐量将会造成很大的压力。要解决这个问题,可以使用组播(Multicast)机制:在发送节点和每个接收节点之间进行点对点的网络连接。如果一个发送节点同时向多个接收节点传输相同的数据,只需复制相同的数据包即可。组播机制提高了数据传送效率,降低了骨干网络拥塞的可能性。

(3)通过对ROS通信栈的研究,发现在数据序列化和反序列化的过程中,通信延时的损失很大。序列化将内存中对象的状态信息转换为可以存储或传输的形式。在序列化期间,对象将其当前状态写入临时或持久性存储区,然后通过从存储区中读取或反序列化对象的状态来重新创建对象。要解决这个问题,开发者可以使用一个轻量级序列化程序,将序列化延时降低50%。

如何解决资源的配置和安全问题,是无人驾驶技术中的一大难题。想象一下两个简单的攻击场景:

(1)其中一个ROS节点被劫持,内存被连续分配,导致系统内存不足,导致系统进入OOM,开始关闭不同的ROS节点进程,导致整个无人驾驶系统崩溃。

(2)ROS的主题(Topic)或服务器(Service)被劫持,ROS节点之间的信息传递被篡改,导致无人驾驶系统行为异常。

开发者可以使用Linux Container(LXC)管理每个ROS节点进程。简单地说,LXC提供轻量级的虚拟化以隔离进程和资源,而不需要提供指令解释机制和其他复杂特性,如全虚拟化(相当于C++中的NameSpace)。LXC将由单个操作系统管理的资源有效地划分为孤立的群组,以更好地平衡孤立组之间相互冲突的资源使用需求。LXC在无人驾驶场景中的最大优势是性能损耗小,发现LXC在运行时只造成大约5%的CPU损耗。

除资源限制外,LXC还提供沙盒支持,允许系统限制ROS节点进程的权限。为了防止危险的ROS节点进程干扰其他ROS节点进程的运行,沙盒技术可以限制潜在危险的ROS节点对磁盘、内存和网络资源的访问。为了防止通信劫持,ROS还实现了一个轻量级加密解密机制,以防止黑客重播或更改通信内容。

为了保证一个复杂系统的稳定高效运行,每个模块都能充分发挥其潜力,需要一个成熟有效的管理机制。在无人驾驶场景中,ROS提供了这样一种管理机制,系统中的每个硬件和软件模块都可以有效地交互。原装ROS提供了许多必要的功能,但这些功能并不能满足无人驾驶的所有要求,因此,我们需要在ROS的基础上,提高系统的性能和可靠性,完成有效的资源管理和隔离。随着无人驾驶技术的发展,将提出更多的系统需求,如车车互联、汽车与城市交通系统互联、云汽车互联、加速异构计算硬件等。