从零开发一个自动驾驶汽车感知系统(CRN作者项目总结)

本文根据Youngseok Kim博士个人主页项目整理而来。

1. Prologue

在攻读博士学位期间,我深入研究了自动驾驶中的三维感知算法,特别是基于传感器融合的三维物体检测。在开发了几个最先进的网络并在KITTI和nuScenes排行榜上取得良好成绩后,我发现自己渴望获得超越排行榜排名的更广阔视野。

在这里插入图片描述
在三月末成功完成答辩后,我成为了博士后研究员并负责实验室项目。同时,我旨在验证我最近开发的摄像头-雷达传感器融合网络(CRN)是否能在真实场景中有效工作。

凭借几年的经验,我很快意识到,与现实世界中部署模型相比,仅仅在精心处理的数据集上开发模型可能会大不相同。在真实世界中部署模型需要仔细考虑数据收集(决定收集哪些数据以及如何收集和标注数据)和工程实施(规划如何有效部署模型)。

鉴于我已经在利用多传感器开发稳健的三维物体检测网络上投入了大量时间,我的主要重点转向了优化数据收集、数据标注和模型部署的过程。最重要的是,我旨在使这一整个流程实现成本高效并便于人工操作。

在接下来的文章中,我将非常简要地概述我旨在解决的问题、我在这一过程中遇到的挑战以及我解决问题的方法。(我不喜欢重复造轮子)


2. Introduction

开发数据驱动模型的过程可以大致抽象为三个关键步骤:

  1. 定义目标和整理数据
  2. 开发和训练模型
  3. 评估性能

然后重复步骤1至3,直到达到所需的性能。
在这里插入图片描述

三个步骤听起来可能直接且简单,但其中会涉及许多有趣的研究课题。

  • 我们不知道哪些数据更具信息量,以及模型需要多少数据才足够。这时,我们可以使用主动学习来衡量数据的信息量并整理数据集。
  • 如果我们想利用未标记的样本来降低标注成本,可以使用自监督或半监督方法来训练模型,同时节省成本。
  • 考虑到重复的数据收集和模型训练,计算资源可能会成为一笔巨大的开销。这时,我们可以有利地采用元学习或持续学习来处理新增加的数据。

虽然没有明确提及,但良好的工程实践应该是所有流程中必不可少的。在我自己的历程中,我不得不在性能和时间限制之间做出平衡选择。在资源有限的情况下,我选择在可用的时间范围内专注于开发一个最小可行产品(MVP),而不是花费大量时间和精力去追求理想的模型。重要的是要注意,这个选择并不一定适合所有情况,情境在决策中起着至关重要的作用。


3. Building Dataset

3.1 Sensor Configuration

我想要部署的模型是摄像头雷达网络(CRN)。显然,我需要一个摄像头和雷达传感器来部署它。此外,为了获取真实值、进行标注和评估,激光雷达(LiDAR)和差分全球定位系统(DGPS)也是所需的。

在这里插入图片描述
幸运的是,实验室的自动驾驶车辆平台上已经安装了摄像头、激光雷达(LIDAR)和差分全球定位系统(DGPS),而我不能更换激光雷达和差分全球定位系统的传感器。因此,重点就放在了选择最适合我们需求的摄像头和雷达上。

摄像头:当我们最初安装摄像头及其外壳时,我们设计了摄像头支架,以便可以更换为其他摄像头。(当然,我们必须确保摄像头的位置不会因车辆的振动而改变。)平台上最初安装的摄像头是USB摄像头,它们存在动态范围有限、缺乏PTP同步以及数据传输速度慢等缺点。我特别担心USB摄像头的数据传输速度慢可能会在使用多个摄像头时成为潜在的瓶颈,因此我考虑过切换到带有GMSL接口的汽车摄像头。但是,由于我将我们最小可行产品(MVP)模型的视野(FoV)固定为使用单个摄像头和雷达的前视图,因此我决定继续使用来自Leopard Imaging的USB摄像头。

雷达:我的摄像头雷达融合模型是在nuScenes数据集上开发和测试的,该数据集使用的是大陆集团(Continental)的ARS408-21雷达,该雷达提供点状数据。在提供点云的雷达传感器方面,我们没有太多选择,因此我们选择了大陆集团的ARS430雷达。ARS430与ARS408-21具有相同的硬件,但提供了改进的I/O接口(从CAN升级到以太网)。这意味着两款雷达在硬件方面的领域差异会更小,我们可以更好地利用nuScenes数据集进行预训练。在设计雷达的安装位置和角度时,我考虑了雷达的视野(FoV),以覆盖360度的车辆范围,同时遵守韩国交通法规。

以下是摄像头(绿色)、雷达(红色)、激光雷达(橙色)和差分全球定位系统(DGPS,蓝色)的最终传感器配置。

在这里插入图片描述


3.2 Sensor Connection

下一步是决定如何连接传感器以接收和保存数据。如果时间充裕,我可能会开发自己的代码来与激光雷达(LiDAR)和差分全球定位系统(DGPS)系统进行接口连接,但我选择了更便捷的方法,即采用机器人操作系统(ROS)。

驱动程序:幸运的是,摄像头、激光雷达(LiDAR)和差分全球定位系统(DGPS)传感器已经提供了官方的ROS驱动程序。然而,雷达传感器却没有,因此我需要创建一个自定义驱动程序来建立连接。我们使用WATonomous团队的代码作为基线,Hot Truong在提升代码效率方面给予了我很大的帮助。具体来说,我们重写了代码,将捕获的雷达数据包处理成点数组,同时确保雷达周期的完整性,并编写代码将点数组发布为ROS的PointCloud2消息。

可视化:所有传感器连接完成后,我能够无缝接收数据。使用ROS(机器人操作系统)的一个优势就是其可视化和记录操作的简便性。我只需付出极小的努力,就可以录制、回放和可视化摄像头图像、激光雷达点和雷达点。

在这里插入图片描述

保存与解析:在数据保存方面,我的目标是记录包含特别有趣场景的数据序列。例如,包含罕见类别物体(如施工车辆、救护车)的场景或车辆频繁变道的场景。为了实现这一目标,我编写了代码,在接收到键盘输入时,将主题保存到rosbag中,每个rosbag包含22秒的数据。由于我一直不喜欢nuScenes数据集不包含第一个关键帧之前的数据,因此我保存了第一个关键帧的“前”数据和最后一个关键帧的“后”数据。最后,20秒的数据(从录制文件的1秒到21秒)准备以2Hz的关键帧频率解析为40帧。为了解析和保存数据样本,我遵循了nuScenes的数据结构,但按场景级别管理数据。与nuScenes使用一个单独的JSON信息文件和整个数据集使用一个巨大的文件夹不同,我为每个场景分别保存了信息文件和文件夹,因为数据集需要经常更改。我简单地修改了模型的数据加载器(使用mmdet3D代码库),以便加载JSON文件列表。以下是我使用的数据(和文件夹)结构:

在这里插入图片描述


3.3 Calibration & Time Synchronization

在这里插入图片描述
为了确保所使用的摄像头、激光雷达(LiDAR)、雷达和差分全球定位系统(DGPS)之间的正确对齐,外参标定至关重要。即使是像上面那样的看似简单的投影,也需要付出一定的努力才能准确实现。最初,激光雷达和差分全球定位系统之间的外参标定是在安装过程中通过激光扫描获得的。此外,激光雷达与雷达之间的外参标定也相对容易获得。因此,重点放在了标定摄像头和激光雷达上。

摄像头内参:对于摄像头-激光雷达的外参标定,我首先需要找到摄像头内参。虽然使用OpenCV或MATLAB的几行代码就可以简单地计算出内部参数,但我还是尽力小心地拍摄了一个棋盘,以确保均匀覆盖所有图像区域。我自己制作了一个棋盘,通过在亚克力板上打印一个图案(我很满意!)。在获得了内部参数(主点、焦距、畸变系数)之后,我就准备进行外参标定了。

摄像头-激光雷达外参:摄像头-激光雷达的标定涉及以下步骤:

  • 同时从摄像头图像和激光雷达点云中捕获目标板。至关重要的是,摄像头图像必须无畸变,且两个传感器必须时间同步。
  • 在图像和激光雷达数据中找到目标板的角点(对应点)。虽然在图像中找到角点相对简单,但在稀疏的激光雷达点中做同样的事情可能会很有挑战性。
  • 通过最小化图像角点与投影到图像平面的激光雷达角点之间的误差来计算旋转和平移。换句话说,给定一组对应点和内参K,我们找到旋转矩阵R和平移向量t,使得像素[u; v; 1] 与K [R|t][x; y; z; 1]之间的像素误差最小。

由于第2步的难度,特别是在激光雷达点中找到角点,导致了一系列额外的处理过程:平面拟合和投影→在约束条件下(固定边长、垂直性)找到四条边→找到角点并进行手动校正

在这个过程中,Sunmyung给了我很大的帮助!

时间同步:在成功获取所有外参后,我发现投影在静态场景下表现良好,但在运动过程中就不太可靠了。问题根源在于时间同步上的差异。由于未使用外部触发器,出现时间误差是很自然的。然而,考虑到摄像头以30FPS运行,而激光雷达以20FPS运行,理论上,即使没有精确同步,最接近的可用图像也应该在激光雷达时间戳的33毫秒内。问题在于我忽略了在处理和保存激光雷达和图像数据时引入的误差。为了解决这个问题,我降低了图像的保存频率,在记录时关闭了可视化(尽管其频率为1Hz),并在Hyeonseo的帮助下使用了实时Ubuntu内核,从而取得了改进。

在这里插入图片描述
如果没有延迟,摄像头和激光雷达帧之间的间隔应为33毫秒至50毫秒。虽然这不是最佳解决方案,但我希望即使存在一定的时间同步误差,网络仍然能够合理运行。在未来,使用支持触发的摄像头将是一个更优雅的解决方案。


4. Labeling

4.1 Annotation Tool

我们需要一个标记好的数据集来训练模型;更重要的是,数据的质量和一致性对于构建一个好模型至关重要。就我个人经验而言,标注公司的质量没有达到我的标准,而且反馈过程也很漫长。虽然我制定了一份20页的标注员操作手册(参考了nuScenes标注员操作手册)以确保高质量的标注,但期望外包公司保持这种高质量水平却颇具挑战性。

因此,我认为建立内部标注流程至关重要。此外,我希望标注流程不要过于耗费人力,尽管研究生的劳动力成本非常低。我的方法是,先仅使用一小部分数据创建一个基本可用的基于激光雷达的3D目标检测器。然后,我会使用一些检测结果(高置信度的)作为伪标签,并手动标注模型未能检测到的实例。随着模型的改进,这个迭代过程将逐渐减少对手动标注的需求。

在这里插入图片描述
首先,我需要选择一个标注工具,而我最终锁定了CVAT和Supervisely。由于我的目标是要上传激光雷达点以及3D边界框(伪标签),然后手动校正和标注这些标签,并最终下载最终数据,我发现Supervisely及其Python API更适合实现这些目标。我利用业余时间(比如看Netflix的时候)标注了几百个样本。与此同时,我也在并行开发一个离线3D激光雷达检测器。


4.2 Auto Labeling

在这里插入图片描述
我迫切希望尽可能减少在重复标注过程上花费的时间。因此,我额外付出努力,开发了一个高效的车外3D激光雷达探测器作为自动标注工具。为了实现这一目标,我需要解决几个关键考虑因素:

  • 使用哪个预训练模型
  • 如何对输入进行预处理
  • 如何对输出进行后处理

预训练模型:鉴于我没有大量的标记数据,使用预训练模型是非常理想的。虽然考虑到高速公路环境,在DDAD数据集上预训练模型会是最理想的,但我决定使用mmdetection3D中的预训练模型,因此我必须在基于KITTI、nuScenes或Waymo数据集训练的模型中进行选择。

在这些选项中,Waymo的优势在于其更长的检测范围(高达75米)以及与我们激光雷达相似的特性。然而,唯一的问题是它的类别划分较为粗略(汽车、行人、自行车骑行者),而我希望使用nuScenes中的细粒度类别(轿车、卡车、公交车、拖车以及施工车辆)。为了解决这个问题,我复制了“汽车”类别的检测头,并将其复制五次,以对应所需的五个类别。原本预训练用于检测“汽车”类别的检测头,随后被微调以分别检测“汽车”的子类别。

预处理:我决定只标记前方数据,因为MVP模型将仅使用前方摄像头和雷达。此外,我计划标注距离达100米内的物体,以展示相机-雷达相比激光雷达的优越检测范围。虽然标注更远的距离会更理想,但我们激光雷达的性能限制使得这变得具有挑战性,因此我选择了100米作为标注范围。作为一款“离线”检测器,它没有限制只能使用前一帧,我也不需要优先考虑计算效率或实时处理。因此,我使用了关键帧的前3次扫描和随后的(未来)3次扫描,共计7帧。也许更多的扫描次数或更宽的帧间隔可能更有效,但这种配置已经表现良好,因此我没有在这方面投入更多精力。在训练网络时,我特别关注了旋转增强,因为高速公路上大多数车辆都朝同一方向行驶,没有太大的航向角变化。因此,我想通过强烈的旋转增强来确保模型能够有效处理不同的航向角。此外,由于不会出现车辆从相反方向驶来的情况,因此我没有使用垂直翻转增强。

后处理:最后,我在检测结果的后处理上花了一些功夫。我对激光雷达点输入应用了多次旋转增强([-3, -2, …, +2, +3] * π/8)和水平翻转(左右)增强,使得单个输入能够产生14个预测结果。在生成预测后,我对每个预测应用了逆增强处理,然后通过取属性图的平均值将它们合并(参考mmdet3D的CenterPoint TTA,我基于他们的代码库对旋转增强进行了修改)。在未来,我计划探索类似于加权框融合(WBF)的对象级测试时增强方法,以根据预测的置信度来合并预测结果。

在这里插入图片描述

使用400帧数据训练的离线3D激光雷达检测器表现相当出色。我手动校正了该模型生成的伪标签,并重复了几次这个过程,最终得到了总共1600帧数据。这一成就的意义不仅在于数据的数量,更在于能够以最小的努力实现标注的自动化。最初的400帧数据标注花费了几天时间,但到了最后一个周期,所需时间已显著减少。

至此,我已经完成了用于自动标注的离线3D激光雷达检测器的开发。

然而,以下方向值得探索:

  • 从逐帧检测到轨迹段的过渡:序列数据比单帧数据提供的信息要多得多。
  • 确保同一轨迹段内的目标大小保持一致:向模型提供一致的数据至关重要。
  • 通过拟合实现相邻帧之间航向角的平滑变化:这对于后续的跟踪或预测任务可能很重要。

5. Deploying

5.1 Network Modification

尽管CRN已经具备实时处理能力,但我的目标是进一步优化它,以尽可能减少计算和内存需求。此外,考虑到可能在NVIDIA Jetson Orin或Qualcomm RB5等嵌入式平台上进行部署,我还致力于使网络尽可能轻量级且对GPU友好。

在这里插入图片描述
对网络进行的主要修改包括:

  • BEV网格和深度区间大小:鉴于测试环境的范围达到100米,我调整了前方方向的感知范围,同时保持侧面方向50米的范围。此外,由于该环境与城市场景相比缺少小物体且物体间距较大,我增大了鸟瞰图(BEV)网格大小和深度分布中的区间大小,以降低内存使用量和计算负载。
  • 主干网:我减少了透视视图和鸟瞰图特征提取器中的主干网层数数量,以减小整体模型参数大小。
  • 关键帧数量:原论文使用了四个关键帧来整合过去三秒内的信息。为了补偿关键帧之间自车的运动,需要将鸟瞰图特征图对齐到时间t。鉴于高速行驶(约30米/秒)导致的关键帧之间巨大位移,特征图之间的重叠极少,这可能会降低其有效性甚至产生不利影响。因此,我选择仅使用当前帧和一秒前的上一帧。
  • Transformer模块:我用卷积层替换了用于融合摄像头和雷达特征图的Transformer层。虽然Transformer层具有更大的接收域并表现出更稳健的性能,但我无法保证训练过程的稳定性,尤其是在数据量不足的情况下。因此,我决定使用我认为能够可靠工作的卷积层,尽管其性能可能略低。

域差异:我还考虑了nuScenes数据集与我的测试环境在训练时存在的域差异。由于训练数据量有限,最小化域相关问题将有助于提高训练的有效性。

在这里插入图片描述
在筛选雷达点时,我调整了雷达的RCS、SNR和虚警率阈值,以使它们尽可能与nuScenes数据中的特征保持一致。请参考nuScenes雷达数据格式,ARS430提供的数据与ARS408类似。然而,我尚未对nuScenes与我的测试环境之间由于高速行驶差异可能带来的潜在挑战进行深入分析。

关于相机图像,在从图像估计深度时,我遇到了更为显著的领域迁移挑战(可能是由于相机内参和安装位置的不同),并且我需要更多的数据来解决这个问题。幸运的是,训练相机图像以预测深度无需额外的标注成本,因为可以使用投影到图像上的激光雷达点进行监督。

我在两种场景下训练了网络:一种场景是有3D标注,允许对整个网络进行端到端的训练;另一种场景是没有3D标注,仅训练深度网络。由于GPU资源有限和时间紧迫,我无法通过消融测试来验证额外训练深度网络所带来的性能提升。


5.2 ROS Porting

我使用了ROS进行传感器集成,并利用rospy简化了将ROS主题订阅集成到我现有的Python代码中的工作。为了实现实时处理,在Wonjoon的帮助下,我不得不重新编写了代码,用于通过ROS主题对从传感器接收到的数据进行预处理。

在这里插入图片描述
首先,我通过补偿自车的运动,将过去几帧中的多个雷达扫描数据累积到当前帧中,从而使稀疏的雷达点变得更为密集。现在,在实时接收雷达数据时,我修改了代码,借助DGPS提供的精确自车位置信息,来聚集多个雷达扫描数据。(使用CAN总线上的车速和转向信息来计算自车运动可能是一个有前景的方法。)

其次,由于网络必须以0.1秒的周期时间运行,但网络需要一个1秒前的鸟瞰图(BEV)特征图,我需要弄清楚如何部署它。(在离线环境下运行卷积递归网络(CRN)时,我可以达到最高20帧每秒的速度;然而,考虑到潜在的输入/输出瓶颈和其他计算,我选择以10 FPS的速度运行它。)

最理想的方法是使用单帧生成一个BEV特征图,并将其存储在队列中以供后续使用。由于这个BEV特征图每隔0.1秒获得一次,队列中前10个索引存储的数据将允许我们使用1秒前的BEV特征图。然而,我们必须正确地将BEV特征图对齐到当前帧。

相反,作为概念验证,我将图像和雷达点(而不是BEV特征图)保存在队列中,然后批量处理两个关键帧。在这种情况下,特征提取器必须两次处理相同的数据,导致效率低下。然而,在理想情况下,尽管内存消耗更大,批量处理将保持相似的吞吐量。鉴于我们车辆平台上安装的工业个人计算机有足够的内存资源,我主要关注吞吐量,并选择这种方法作为原型,尽管它有些繁琐。

该模型采用384x1056大小的图像和雷达点作为输入,以ResNet50为主干网络,检测100米范围内的物体,在使用i7处理器和RTX 3090显卡的情况下,帧率达到了18帧每秒(FPS)。我预计,将该模型转换为TensorRT可以进一步提高推理速度。

在这里插入图片描述
这段视频展示了使用从rosbag文件中重放的摄像头和雷达数据的CRN(卷积递归网络)实时演示。尽管性能可能不是最佳的,但它有效地证明了该系统是可行的。请注意,此视频中的数据完全是新数据,并未包含在训练数据集中。

在这里插入图片描述
此外,我还测试了CRN在雨天场景中的表现,而雨天场景从未包含在我们的数据集中。这个模型以前从未见过雨天,但成功检测到了物体!这证实了经过训练的网络已经能够泛化到以前未见过的数据,现在只剩下将其应用于实际车辆中的任务了。


5.3 Vehicle Deployment

我最初开始写这篇帖子是为了分享这个视频,但当我开始写的时候,我的想法不断扩展,使得帖子比预期的要长。

从视频中我们可以看到,训练后的模型已经泛化,能够在类似高速公路的驾驶环境中运行。此外,训练数据集涵盖了80至120公里/小时的高速环境。然而,CRN在各种场景下都表现出了有效的性能,包括相对较低的40至80公里/小时的速度,甚至是城市驾驶场景!

在这里插入图片描述

总结这个项目的主要方面:

数据收集 → (自动)标注 → 模型训练 → 车辆部署

我旨在以最少的努力和成本实现这些里程碑,以完成概念验证(PoC)。我刚完成了一个勉强可用的PoC,并成功确认其功能正常!然而,要改进这个训练周期和模型,还需要付出更多努力。

最重要的是,我没有设定关键绩效指标(KPI)来定量衡量性能。网络的一些部分并未针对有效推理进行优化。ResNet的跳跃(残差)连接可能最好移除,以降低内存访问成本。视图转换(体素池化)模块可以通过在推理期间使用固定的截头锥体网格来进一步改进。

最后,使用INT8量化的TensorRT移植可以是一种非常有效的方法,能够以最小的努力显著提高推理速度。


6. Conclusion

为了进一步优化已开发的最小可行产品,我总结了应考虑的几个方面:

  1. 多任务能力:扩展模型的能力,使其能够有效处理多个任务。具体而言,利用鸟瞰图(BEV)特征进行车道和可行驶区域检测,并利用点云视图(PV)特征图进行交通信号灯检测。
  2. 性能评估与指标:需要为汽车应用量身定制指标,而不是仅仅依赖计算机视觉领域的指标。除了传统的平均精度(AP)指标外,还强烈强调纳入时间感知(类似于跟踪)的指标,用于下游任务。此外,指标必须考虑物体的位置,因为近距离的假阳性或假阴性对性能的影响与远距离的影响大不相同。
  3. 匹配函数:我个人认为,无论是交并比(IoU)指标(如Waymo和KITTI所用)还是中心距离指标(如nuScenes所用),都不是性能评估的最佳选择。在自动泊车等场景中,即使定位误差只有10厘米,也可能导致重大事故,这凸显了准确检测物体轮廓的重要性。然而,在高速公路驾驶场景中,在100米距离上物体的纵向定位误差为1米是可以忽略不计的,而检测物体的相对速度和横向位置则更为重要。
  4. 实时处理:确保模型能够在嵌入式PC硬件上高效运行。探索TensorRT和INT8量化等技术,以优化推理速度。

通过解决这些考虑因素,我们可以完善MVP,并朝着开发更先进、更强大的产品迈进。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值