当前位置: 代码迷 >> 综合 >> 【Apollo】AutoDrive Apollo5.0感知模块学习
  详细解决方案

【Apollo】AutoDrive Apollo5.0感知模块学习

热度:96   发布时间:2023-12-17 15:47:17.0

目录结构

    • 一、无人驾驶介绍
    • 二、源码下载
    • 三、概念汇总
    • 四、数据
    • 五、modules整体介绍
    • 六、对Apollo 3.0的更改
    • 七、障碍物识别
      • camera部分介绍
          • (1)流程介绍
          • (2)物体检测
          • (3)2D-to-3D的转换
          • (4)物体追踪
          • (5)后处理
          • (6)app模块
    • 八、车道线识别
    • 九、红绿灯感知
    • 十、感知算法整体介绍
      • 1)Lidar感知
      • 2)视觉感知
        • (1)介绍
        • (2) CNN检测
        • (3) CNN分割
    • 十一、感知中的机器学习
    • 十二、安全问题
    • 十二、高精地图的作用
    • 十三、参考链接
    • 十四、写在后面

一、无人驾驶介绍

无人驾驶是一个复杂的系统,如图1所示,系统主要由三部分组成:算法端Client端云端。其中算法端包括面向传感、感知和决策等关键步骤的算法;Client端包括机器人操作系统以及硬件平台;云端则包括数据存储、模拟、高精度地图绘制以及深度学习模型训练。
算法子系统从传感器原始数据中提取有意义的信息以了解周遭环境情况,并根据环境变化做出决策。Client子系统融合多种算法以满足实时性与可靠性的要求。举例来说,传感器以60HZ的速度产生原始数据,Client子系统需要保证最长的流水线处理周期也能在16ms内完成。云平台为无人车提供离线计算以及存储功能。通过云平台,我们能够测试新的算法、更新高精度地图并训练更加有效的识别、追踪、决策模型。

二、源码下载

百度的自动驾驶项目Apollo有好几个版本,我目前在学习的是5.0版本。源码是从Github上找的,链接为apollo源码。但是整个项目实在是有些大,就算是我翻墙出去下载也一直显示下载失败。所以我只好先下载其中的perception也就是感知模块先进行学习。但是Github本身是只能下载整个项目的,也是意外的发现了DownGit这个东西,直接把项目中需要下载的文件链接copy到DownGit的框框中,点击Download就可以下载需要的文件了。
感知模块的输入包括:图像数据(front_6mm和front_12mm),128通道的Lidar数据(velodyne 128),16通道的Lidar数据(lidar_front, lidar_rear_left, lidar_rear_right),Radar数据(radar_front, radar_rear),radar校准数据(来自YAML文件),front camera校准数据(来自YAML文件),车辆的速度和角速度
感知模块的输出
(1)对象输出
1)3D长方体
2)相对速度和方向
3)类型:CIPV,PIHP,其他
4)分类:汽车,卡车,自行车,行人
5)Drops:物体的轨迹
(2)车道线输出
1)折线和/或多项式曲线
2)车道类型按位置:L1(左下车道线),L0(左车道线),R0(右车道线),R1(右下车道线)
(3)红绿灯输出
目前还没做红绿灯部分,后面做到这部分再补充

三、概念汇总

RTOS:实时操作系统(RTOS)是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统做出快速响应,调度一切可利用的资源完成实时任务,并控制所有实时任务协调一致运行的操作系统。提供及时响应和高可靠性是其主要特点。使用apollo-kernel保证系统的实时性(2.0版本)。
**对ROS的改动:**去中心化(使用FAST RTPS),共享内存以提升节点间的传输效率(通过socket进行结点间的通信),原生支持 Protobuf(将Google的Protobuf和ROS深度集成,从而提高数据的版本兼容性。其优势在于当模块接口升级以后,通讯的数据也可以相互兼容。另一个好处是宝贵的自动驾驶的历史数据在模块升级后也可以一直被使用。https://blog.csdn.net/heyc861221/article/details/80123570)。使用了 PREEMPT_RT 内核来增强了 ROS 所在的 linux 环境的实时性
CIPV: CIPV是当前车道中最接近的车辆。对象由3D边界框表示,其从上到下视图的2D投影将对象定位在地面上。然后,检查每个对象是否在当前车道中。在当前车道的对象中,最接近的一个将被选为CIPV。
protobuf文件:
使用 protobuf 来替换 ROS 中的 Message 来作为消息定义的格式。protobuf 本身有良好的兼容性支持,只需要在使用中定义好 required 字段,后续新增 optional 字段并不会对消息的解析造成影响。

#include "modules/perception/proto/perception_obstacle.pb.h"//这里就是调用protobuf文件
#使用的protobuf编译器版本为v2
syntax = "proto2";
#声明了一个包名,类似于C++中的namespace
package apollo.perception.camera.yolo;
#message是protobuf中的结构化数据,类似有C++z中的类,可以在其中定义要处理的数据
#protobuf中有三个字段:required(值必须要设置),optional(字段可以由0个或者1个),repeated:该字段可以重复任意多次(包括0次),类似于C++中的list(数组)
message YoloParam {
    optional ModelParam model_param = 1;optional NetworkParam net_param = 2;optional NMSParam nms_param = 3;
}

ProtoBufCodeGen是proto文件的编译器,可以将proto文件编译成**.pas代码**文件,编译格式如下:

procedure PrintHelp;
begin
Writeln('Usage:');
Writeln('ProtoCodeGen <input .proto file> [ <options> ]');
Writeln('<options>');
Writeln(' --proto_path=<import path for .proto files>');
Writeln(' -I same as as --proto_path');
Writeln(' --pas_out=<output path for .pas files>');
Writeln(' -O same as --pas_out');
Writeln(' --help');
end;

IMU:IMU全称是惯性测量单元,主要用于定位。

四、数据

数据分为以下几类:
**原始数据,**各种传感器、车辆、驾驶员行为等。数据种类繁多,维度不同,数据量大,而且大多是非结构化数据,对于存储、传输、处理提出非常大的挑战。
**标注数据,**视觉的2D障碍物数据、红绿灯数据、3D点云数据等。
**逻辑数据,**包括完美感知、环境的抽象以及车辆动力学模型等。
**仿真数据,**包括参数模糊化数据、三维重建数据等。
Apollo开放了六类训练数据:
2D红绿灯,用来识别交叉路口红绿灯数据,可以用做训练、测试和验证。
2D障碍物,比如车辆、行人、自行车,还有其他未知类别的图像数据。
3D障碍物,其实是激光雷达点云。
端到端的数据,提供适合end-to-end模块的数据。
场景解析,像素级的语义标注,比如车辆、背景、交通指示牌、障碍物等,可以用来做整体环境的识别。
障碍物预测,用来训练预测算法的数据集。
此外,Apollo还发布了一个叫Apollo Scape的学术性项目。Apollo Scape开放的数据在量级、复杂程度和精度方面都比业界有名的Kitty、citi scapes大一个数量级,目的是推动整个自动驾驶行业的发展。

五、modules整体介绍

这里的图不是Apollo5.0版本的,好像是3.0版本,但是目前网上5.0版本资料很少,几个版本还是有很多共通之处的,所以我也放在这里,对照
在这里插入图片描述下面是Apollo5.0中的感知模块结构分支,参考的链接附在文末:
├── base // 基础类
├── BUILD // 编译testdata,用于测试
├── camera // 摄像头 — 子模块流程
├── common // 公共目录
├── data
├── fusion // 融合
├── inference // 深度学习推理相关
├── lib // lib库
├── lidar // 雷达 — 子模块流程
├── map // 地图
├── onboard // 各个子模块的入口 — 子模块入口
├── production // Cyber加载模块入口 — Cyber加载入口
├── proto // 数据格式,protobuf
├── radar // 毫米波 — 子模块流程
├── README.md
└── testdata // 上述几个模块的测试数据,包括训练好的模型
感知模块的入口在production目录,通过lanuch加载对应的dag,启动感知模块。可以看到感知启动了多个子模块,来处理不同的传感器信息(Lidar,Radar,Camera)。各个子模块的入口在onboard目录中,各个子模块会订阅不同的传感器Topic,然后进行统一的流水线(Pipeline)作业。每个子模块的流水线作业分别在不同的文件夹中(camera, lidar, radar)。这就是感知模块总体的目录结构。(面向对象的20几种设计模式可以去学习一下)
inference目录 - 深度学习推理相关的库,主要实现了加载创建caffe深度学习模型,TensorRT深度学习优化器等。
lib目录 - 提供注册类和线程池。
根据kitti的例子,对camera做完整流程的识别,如果需要入门,可以把这个例子先跑通,同时也可以拿这个例子进行性能调优。
感知依赖LiDAR点云数据和相机原始数据。除了这些传感器数据输入之外,交通灯检测依赖定位以及HD-Map。由于实时ad-hoc交通灯检测在计算上是不可行的,因此交通灯检测需要依赖定位确定何时何地开始通过相机捕获的图像检测交通灯。

六、对Apollo 3.0的更改

CIPV检测/尾随 - 在单个车道内移动。
全线支持 - 粗线支持,可实现远程精确度。相机安装有高低两种不同的安装方式。
异步传感器融合 – 因为不同传感器的帧速率差异——雷达为10ms,相机为33s,LiDAR为100ms,所以异步融合LiDAR,雷达和相机数据,并获取所有信息并得到数据点的功能非常重要。
在线姿态估计 - 在出现颠簸或斜坡时确定与估算角度变化,以确保传感器随汽车移动且角度/姿态相应地变化。
视觉定位 – 基于相机的视觉定位方案正在测试中。
超声波传感器 – 作为安全保障传感器,与Guardian一起用于自动紧急制动和停车。

七、障碍物识别

camera部分介绍

camera得到的是图像,图像仿真是相对困难的,点云仿真相对简单。
输出包括障碍物的类别,位置,尺寸和朝向
一个广角摄像头,一个长距离摄像头
障碍物的识别是由camera,lidar和radar一起完成的。camera部分的流程为:物体检测->2D到3D的转换->camera物体追踪。
摄像机对横向距离的贡献更大,雷达对纵向距离测量的贡献更大。

(1)流程介绍

参考链接:https://blog.csdn.net/xiangxianghehe/article/details/82222857
(原链接:https://github.com/ApolloAuto/apollo/blob/r5.0.0/docs/specs/perception_apollo_3.0.md)

(2)物体检测

YOLO被用作对象和车道线检测的基础网络。该对象具有车辆、卡车、骑车人和行人类别,并由表示成具有方向信息的2-D边界框。YOLO检测物体,图像分割检测车道线(同样也是使用YOLO)
静态物体:检测车道线和交通信号灯
动态物体:关心乘用车,卡车,骑自行车者,行人或任何其他物体,包括动物或身体部位。

(3)2D-to-3D的转换

给定一个2D盒子,其3D大小和相机方向,该模块搜索相机坐标系统中的3D位置,并使用该2D盒子的宽度,高度或2D区域估计精确的3D距离。此部分由CNN来完成(是为了减少人工干预)

(4)物体追踪

跟踪问题通过有效地组合线索来表达为多个假设数据关联,以提供路径和检测到的对象之间的最正确关联,从而获得每个对象的正确ID关联。此部分由CNN来完成(是为了减少人工干预)
追踪采用Kalman滤波。跟踪必须是轻量化,必须速度要快(因为前面的Detection模块已经耗费很多时间了)。从Detection的model最后输出来的是一个feature map,feature map理解是对图像高层语义的刻画。对feature map做一些roi pooling,得到障碍物级别的feature。此时得到的障碍物级别的feature才能做跟踪,做关联,把传统的跟踪模块的计算量很大的提特征的这一部分给消化了。要充分利用CNN的输出(例如类别等)。可以考虑轻量化的Metric learning,做专门针对instance的feature(跟踪里面用Metric learning也是很悠久的)

(5)后处理

一个完整的系统除了深度学习模型,还需要做一些后处理,后处理是直接针对下游模块,对后续的影响比较直接。在视觉感知中,后处理主要分为三个部分:
第一是2D-to-3D的几何计算。需要考虑的因素包括:相机pose的影响,接地点,稳定性。第二是时序信息计算,主要是针对跟踪处理,需要注意以下几点:对相机帧率和延时有要求,要求跟踪必须是一个轻量级的模块,因为检测已经占据大部分时间,充分利用检测模型的输出信息(特征、类别等)进行跟踪,可以考虑轻量级Metric Learning。第三是多相机的环视融合,相机布局决定融合策略,要做好视野重叠 。后处理阶段是由公式表示的几何计算问题。
在这里插入图片描述

(6)app模块

其中的.cc文件是Linux下的后缀,相当于.cpp。

八、车道线识别

分割(Segmentation)与detection在本质上是一样的,是对一个目标的不同力度的刻画。分割是一种更细粒度刻画物体边界信息的检测方法,不再是画框,而是进行边缘分割。在感知中,对于不规则物体,往往需要进行分割处理。例如场景分割和可行驶区域感知。场景分割可以用于多传感器融合,例如对绿植进行分割,结合LiDAR点云,就可以测出绿植的类别和距离。可行驶区域则可以对一些非结构化道路的路径规划提供支持。在车道线感知中,应视具体情况使用分割或者检测方法。
我们有两种类型的车道线,车道标记段和整个车道线。
车道标记段用于视觉定位,整个车道线用于使车辆保持在车道内。
该通道可以由多组折线表示,例如下一个左侧车道线,左侧线,右侧线和下一个右侧线。
给定来自深度网络的车道线热图,通过阈值化生成分段的二进制图像。
该方法首先找到连接的组件并检测内部轮廓。
然后,它基于自我车辆坐标系的地面空间中的轮廓边缘生成车道标记点。
之后,它将这些车道标记与具有相应的相对空间(例如,左(L0),右(R0),下左(L1),下(右)(L2)等)标签的若干车道线对象相关联。
车道线识别的过程(CNN分割):先进行CNN分割,再进行后处理,在做曲线拟合(比如拟合出一个曲线),最后投射到3D上。(Apollo采用这个)
现在在尝试采用CNN检测对车道线进行识别

九、红绿灯感知

红绿灯感知的任务是在距离停止线50~-2米的范围内精准识别红绿灯亮灯状态。它的难点在于检测精度要求非常高,必须达到三个九(99.9%),否则会出现闯红灯,违法交规的情况。另外召回也不能太低,假设一直是绿灯,但是一秒只召回一帧绿灯,其他都认为是识别错的红灯,则通不过路口,影响通过率和体验。第二是红绿灯感知需要应对各种环境,包括天气和光照。最后是红绿灯的制式非常多,包括距离、高度、横纵、信号状态等,红绿灯感知都需要识别。
自动驾驶中使用深度学习进行红绿灯感知模块的构建,主要分为以下几步:
第一是相机选择和安装,第二是高精地图的交互。最后使用深度学习识别灯颜色的变化。主要分为检测和颜色分类两步。

十、感知算法整体介绍

1)Lidar感知

(1)Lidar感知:启发式方法Ncut,DL方法CNNSeg
(2)视觉感知:DL检测和分割,跟踪,2d-to-3d,多相机融合,红绿灯(感知和地图交互)

2)视觉感知

(1)介绍

在这里插入图片描述如何评估保证安全:模型会有goodcase和badcase
2D到3D感知的渗透: 无人驾驶中的detection会输出后面后处理需要的3D信息(障碍物的尺寸,朝向,当前帧的检测要加入历史帧也就是局部end-to-end),跟踪需要的信息,障碍物属性的识别(尾灯和车门)。(传统的是2D的,只输出bounding box和类别)
检测部分可以参考何恺明,是做检测方向的。
传统只需要前向,现在是需要环视。目前的论文都是基于cv,不能完全应用于ad(autonomous driving)
视觉感知的逻辑结构如图所示:
在这里插入图片描述

(2) CNN检测

在这里插入图片描述

(3) CNN分割

CNN分割和CNN检测本质上是一样的。对于刚体如车辆使用CNN检测,如果对于一些不规则物体使用CNN分割(因为如果采用CNN检测会框住很过背景信息),对于车道线,可行驶区域等都采用CNN分割。

十一、感知中的机器学习

在这里插入图片描述

十二、安全问题

视觉感知要保证稳定性,不能这一帧距离10m,下一帧距离20m。

十二、高精地图的作用

(1)减少无人车的计算算力,比如出现一个红绿灯,不需要无人车自己计算,通过高精地图可以看到。
(2)可以提前知道前面会有什么,我个人觉得这里就跟地图差不多了

十三、参考链接

(1)很详细的介绍了感知模块
感知模块介绍文档
(2)官方Github文档
Apollo的Github官方文档
(3)感知模块结构
感知模块框架结构

十四、写在后面

最近参与的这个自动驾驶项目还是比较难的,每周都要花很多时间学习,每次将自己找到的资料以及自己的理解和思考写在博客上,便于后面的查看。现在已经把感知模块的代码架构,camera部分用到的算法,实现流程都搞清楚了,下一步是一边思考怎么单独运行感知模块,运行camera模块查看结果,一边实践攻击方案。之后会持续更新这个项目的每一个阶段所学所思在博客中。