自动驾驶分布式仿真平台

1 引言

自动驾驶系统通常由感知、感知、决策、控制及其他功能模块组成,每个模块都有其复杂的结构和算法[1]。在大多数情况下,系统或算法开发人员在测试过程中难以评估庞大的设计空间。为了测试任何算法变更,开发人员需要单独测试某个功能模块,随后还需搭建包含多个其他模块的完整物理测试环境,导致测试成本极高。幸运的是,许多测试任务可以通过使用模拟器来完成。仿真的成功关键在于模拟器对物理现实的模拟精度。

有两种主要的仿真技术:第一种是基于合成数据来模拟环境,这类仿真器主要用于控制和规划,特别是在算法开发的初期阶段。第二种是基于真实数据回放来测试不同功能和性能组件,主要用于算法开发的迭代过程。在本文中,我们主要讨论基于数据回放的仿真器。

为了尽可能真实地模拟环境,我们的模拟器基于机器人操作系统(ROS)构建,该系统被用于物理自动驾驶系统[2, 17]。ROS是一种基于消息传递的分布式计算框架,它使开发者更容易进行模块化编程。其模块化设计对于模拟器的设计至关重要,因为我们通常需要独立测试各个模块。在自动驾驶系统中,ROS中的每个功能模块都部署在一个节点中,节点间的通信依赖于格式明确定义的消息,例如包含图像的消息。因此,开发者只需使用相同的通信格式,为每个功能模块开发仿真模块,最后根据测试需求将真实功能模块与仿真模块进行匹配。例如,如果我们希望协调决策模块和控制模块的功能,则需要将决策模块、控制模块以及其他仿真模块安装到模拟器中进行测试。如果决策模块需要单独测试新的决策算法,我们可以仅将最新的决策模块与其他仿真模块一起安装到模拟器中。该测试的结果仅针对决策模块。

1.1 自动驾驶仿真器的构成

首先,自动驾驶汽车仿真器包含汽车动力学模型,用于加载自动驾驶系统的测试并模拟自动驾驶汽车自身的行为。其次,需要对外部环境进行仿真,包括静态场景和动态场景。静态场景包括多种固定交通标志,如停止线、交通标志等。

动态场景主要指车辆周围的动态交通流模型,如车辆、行人、交通信号灯等。所有这些元素共同构建了一个与真实世界相对应的模拟世界。

1.2 自动驾驶模拟器的应用程序

在真实世界中,自动驾驶车辆面临复杂多变的外部环境。一个好的模拟器将外部环境分解为基本元素,然后重新组合以生成多种测试用例,每个测试用例模拟一个特定场景。以一组简单测试用例为例。 示意图0 显示了一个简单仿真场景,其中我们需要测试自动驾驶汽车对前方车辆,即障碍车的响应。障碍车的初始位置是一个仿真变量,在本例中,它可能相对于自动驾驶汽车出现在左前、左、左后、前、后、右前、右、右后,共八个方向。接下来,障碍车的速度是另一个仿真变量,可分为三类:比自动驾驶汽车快、与自动驾驶汽车速度相等、比自动驾驶汽车慢。障碍车的下一个运动步骤是又一个仿真变量,可分为直行、向左转和向右转。通过将所有这些仿真变量相乘并去除所有不需要的情况,我们得到一组测试用例。

1.3 自动驾驶模拟器的挑战

模拟器的核心问题在于我们能够将实际驾驶环境模拟得多么逼真。无论模拟器多么先进,人工模拟的场景与真实场景之间仍然存在差异。真实场景中仍有许多无法在模拟器中复现的意外事件。因此,如果能够利用真实交通数据重现真实场景,相比人工模拟场景,将获得更好的测试结果。然而,回放真实世界数据的主要问题是处理海量真实世界数据所需的计算能力。如果我们希望在模拟器上重现真实世界每一段道路的场景,就需要让自动驾驶车辆收集每段道路的信息。这些信息量无法在单台机器上进行处理。此外,在每个场景中,我们还可以将其进一步分解为基本片段,并通过重新组合这些片段来生成更多的测试用例。但这会产生更多数据,给本已承受压力的仿真平台增加更大的负担。本文中,我们提出了首个通用的自动驾驶分布式仿真平台。

2 基于AROS的自动驾驶模拟器

ROS是一种基于消息通信的机器人操作系统。其通信方式可以抽象为消息池架构,消息发送节点通过发布方法将ROS消息发送到指定主题,消息接收节点通过订阅方法从指定主题接收ROS消息。

2.1 Rosbag

Rosbag是一种利用该架构从主题记录并回放ROS消息到主题的工具,用于无人车辆的数据收集过程。其功能分为两类:记录和回放。记录功能是在ROS中创建一个记录节点,并调用订阅方法接收所有主题或指定主题的ROS消息,然后将消息写入包中。

示意图1

文件。虽然播放功能是在ROS中建立一个播放节点,并根据时间线调用发布方法将包中的消息发送到指定主题。

Rosbag生成的数据格式是Bag,这是一种具有两层逻辑结构的文件格式。如图2所示,Bag类的上层为用户提供对文件进行抽象操作的方法,下层类则将操作方法封装到ChunkedFile中。ChunkedFile类主要用来分别存储数据,所存储的数据为一段段的数据块,后者主要包含由自动驾驶车辆传感器采集的图像或三维点云扫描文件数据。因此,借助ROS,我们可以方便地处理、理解和持久化多媒体数据。然而,这对默认仅处理基于文本的数据的分布式计算框架提出了挑战。我们将在下一节中详细讨论这一问题。

2.2 仿真数据集

正如我们之前提到的,我们主要关注基于真实数据回放的仿真器。第一个问题是现实世界数据的规模。为了理解这一点,我们可以从KITTI数据集[12]开始。在该数据集中,KITTI研究人员记录了6小时的真实数据,数据量为720 GB。然而,这6小时的数据仅足以对算法进行一些简单的验证测试,远不足以进行完整生产级仿真。为了进行大规模的生产级仿真,例如,谷歌自动驾驶项目在过去几年中收集了超过4万小时的真实数据,总数据量估计超过5 PB。单台机器无法处理如此规模的数据,因此我们必须基于真实数据回放仿真器设计一个高效分布式计算平台。

2.3 对计算能力的需求

海量数据处理给计算平台带来了巨大压力。例如,KITTI数据集6小时的原始数据包括超过1亿张1.4亿像素的彩色图表,我们使用单机仿真系统进行基于深度学习的分割任务,每张图像处理耗时约0.3秒。因此,仅分析KITTI数据集就需要超过100小时,而如果我们以谷歌自动驾驶项目整个图像数据集为例,则在单台机器上完成一轮完整的仿真处理将耗时超过60万小时。

3 基于Spark的分布式仿真平台

我们决定采用分布式计算来并行处理仿真,并选择Spark作为我们的分布式计算平台。Spark是由加州大学伯克利分校AMPLab开源的通用并行计算框架[3]。Spark的分布式计算基于内存,相比将中间数据持久化到磁盘的Hadoop具有显著的性能优势[13]。与Hadoop不同,Spark作业的中间输出和结果可以存储在内存中,因此无需读写HDFS[14],这使得Spark更适用于需要密集迭代计算的Map-Reduce算法。

示意图2

如图3所示,我们设计并实现了一个基于Spark的分布式仿真平台框架,以高效地进行自动驾驶汽车回放仿真。我们使用Spark来管理资源分配、数据输入输出以及ROS节点的管理。在Spark驱动器上,我们可以启动不同的仿真应用程序,例如处理激光雷达原始数据的定位算法、处理图像数据的目标识别算法、车辆决策与控制算法等。Spark驱动器根据所需的数据量和计算量从Spark工作节点分配资源。每个Spark工作节点首先将Rosbag数据读入内存,然后启动一个ROS节点来处理输入的数据。

Spark与ROS之间的接口是我们需要做出的一个设计决策。第一种方法是使用JNI[15]连接Spark工作节点和ROS节点,但这涉及对ROS的修改,使得整个系统难以维护和演进。第二种方法是使用Linux管道[16],它创建一个单向数据通道,可用于进程间通信。写入管道写端的数据由内核进行缓冲,直到从读端读取。我们选择第二种方法,因为这样更易于维护。在管道的设计中,有两个问题需要解决:首先,Spark默认仅支持消费基于文本的数据,不支持多媒体数据的消费,我们需要设计一种高效的方法使其能够消费二进制文件;其次,我们需要通过ROSBag播放功能实现从缓存数据的内存中读取数据,同时通过ROSBag记录功能将数据缓存到内存中。

3.1 二进制数据流

Spark的核心数据结构是弹性分布式数据集(RDD),它允许程序员在大型集群上以容错的方式进行内存计算。为了解决Spark消耗多媒体数据的问题,我们开发了一种新的RDD——BinPipedRDD,如下图4所示。

示意图3

首先,二进制文件的分区经过编码和序列化阶段,形成二进制字节流。编码阶段会将所有支持的输入格式(包括字符串(例如文件名)和整数(例如二进制内容大小))编码为基于字节数组的统一格式。随后,序列化阶段将所有字节数组(每个可能对应一个输入的二进制文件)合并为一个单一的二进制流。然后,用户程序在接收到该二进制流后,会对其进行反序列化和解码,以将字节流解释为可理解的格式。接下来,用户程序将执行目标计算(用户逻辑),其范围从简单的任务(如根据需要将jpg文件旋转90°)到相对复杂的任务(如根据激光雷达扫描仪的二进制传感器读数检测行人)。输出结果随后会被编码和序列化,再以RDD[Bytes] partitions的形式传递。在最后阶段,这些分区可以通过collect操作返回到Spark驱动器,或作为二进制文件存储在HDFS中。通过此过程,我们现在可以将二进制数据处理并转换为用户定义格式,并将Spark计算的输出转换为字节流以供collect操作使用,或进一步将其转换为文本或HDFS中的通用二进制文件,以满足应用程序的需求和逻辑。

3.2 通过ROSBagCache进行数据检索

在本小节中,我们介绍了通过ROSBag播放功能从缓存数据的内存中读取数据的设计,以及通过ROSBag记录功能将数据缓存到内存中的设计。如图5所示,在我们当前的设计中,ROSPlay以Rosbag数据作为输入,该数据通过BinPipeRDD传递给ROS。仿真完成后,ROSRecord可以通过BinPipeRDD将输出持久化为某种自定义数据格式。

示意图4

但在这一过程中仍然存在缺失环节,包括ROSBag播放功能如何从内存中读取缓存数据,以及ROSBag记录功能如何将数据缓存到内存中。为了实现这些功能,我们在原有的Bag和分块文件的两层逻辑结构基础上增加了一个分支逻辑层(详见图2)。如图6所示,MemoryChunkedFile类继承自ChunkedFile类,并重写了分块文件的所有方法。MemoryChunkedFile对下一层的内存进行文件的读写操作,而不是对硬盘进行数据的读写。

示意图5

磁盘与分块文件类相同。这种设计的一个主要优点是,工作节点可以通过标准输入流直接读取传递给仿真器的数据,而无需通过磁盘I/O进行读写。采用这种设计,我们可以直接通过内存传递数据,而不是通过磁盘I/O。因此,由于I/O方面的加速,这种读写模型大大减少了数据处理的时间。

通过添加这一逻辑层,我们现在可以将模拟器部署到Spark集群中的每个工作节点机器上。通过运行不同的配置文件,我们可以使每台机器运行不同的模块。或者,我们可以在不同条件下部署相同的模块和模型,以处理相同的数据,从而比较这些模型之间的差异。此外,我们还可以在相同条件下部署相同的模块和模型,但使用不同的数据进行运行,以比较不同数据之间的差异。因此,分布式系统的使用极大地提升了仿真平台设计的性能和灵活性。

4 性能评估

在本节中,我们将深入探讨我们仿真平台的性能。由于该平台主要用于加速云上的仿真工作负载,因此我们研究了平台的I/O性能及其可扩展性。

4.1 ROSBag缓存性能

如图6所示,为了测试ROSBag缓存的性能,我们对比了使用和不使用内存缓存时的ROS播放(读取)和ROS记录(写入)性能。我们进行了两个测试用例:小文件测试,即重复读写100万个大小为1千字节的文件;以及大文件测试,即重复读写10万个大小为1兆字节的文件。无缓存情况使用原始的分块文件,而有缓存情况则使用MemoryChunkedFile。我们在一台具有65GB主内存的12核服务器上执行此测试。结果表明,在使用内存缓存的情况下,大文件测试中的写入性能提高了约3倍,读取性能提高了5倍;在小文件测试中读取性能提高了约10倍。该结果证实了MemoryChunkedFile是提高仿真测试中I/O性能的有效方法。

4.2 可扩展性

如图7所示,我们对系统进行了可扩展性评估。随着计算资源的增加,计算时间也呈线性减少,系统表现出较强的可扩展性。在内部图像识别测试集中,使用单机处理图像需要3小时,而使用八个Spark工作节点后仅需25分钟。我们没有谷歌自动驾驶数据集,但让我们将本研究进行外推并应用于谷歌数据集。假设我们使用10000个Spark工作节点对谷歌的无人驾驶汽车数据进行大规模图像识别仿真测试,整个实验可在100小时完成,而在单台机器上则需要超过60万小时才能完成(图8)。

示意图6
示意图7

5 相关工作

本文提出了一种基于Spark分布式计算系统和ROS的通用分布式仿真框架。需要注意的是,我们的平台具有通用性,即本例中的仿真器ROS可以被其他任意仿真器替代。此前已开发出多种自动驾驶汽车仿真器。汽车制造商使用的仿真器包括IPG Automotive GmbH和VEDYNA,它们提供完整的车辆动力学数值仿真,并支持与MATLAB/Simulink的接口。这些仿真器均旨在简化车辆控制器的开发与集成。类似地,ADTF可用于建模有向图,以反映数据流经一系列处理模块的过程。通信通过所谓的通道实现,这些通道本身具有类型,但原则上可传输任意类型的数据,这与软件框架Hesperia所采用的方法不同,后者仅依赖于带类型的消息。除了上述ADTF外,还开发了虚拟测试驾驶工具包,用于管理先前记录的原始传感器数据,或合成生成执行仿真所需的输入数据。TNO PreScan可用于支持所谓碰撞前驾驶辅助系统的开发。另一种方法由IAV提供的工具实现。该工具可为任意传感器生成合成原始数据。因此,用户以二维方式对特定主动传感器的特性进行建模,例如视场角(FOV)、最大距离以及一些误差噪声。然后,软件计算出由特定传感器的电子控制单元(ECU)所提供的预处理后的传感器数据。FastSim是一个开源的轻量级仿真环境,专为城市自动驾驶的运动规划算法开发而设计,可用于模拟自动驾驶车辆的决策算法。

6 结论

传统上,自动驾驶车辆算法仿真在单台机器上运行,完成仿真需要耗费大量时间。此外,随着系统变得越来越复杂,执行仿真的时间也不断增加。因此,为了加速仿真过程,我们采用了一种分布式计算框架。本文提出了一种基于Spark(用于分布式计算)和ROS(用于回放仿真)的生产级分布式仿真框架。为了实现这样的分布式仿真平台,我们需要无缝集成Spark与ROS,并使Spark能够处理多媒体数据。我们还证明了该系统具有良好的可扩展性,即当我们提供更多的计算资源时,仿真时间几乎呈线性下降。需要注意的是,本文仅展示了基于ROS的回放仿真器。然而,所提出的仿真平台具有通用性,因此我们可以接入任何其他模拟器来执行分布式仿真。我们相信,该平台将成为自动驾驶云[11]的标准服务。

更多推荐