万字详解Apollo,整理全网Apollo笔记学习
Posted 爱是与世界平行
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了万字详解Apollo,整理全网Apollo笔记学习相关的知识,希望对你有一定的参考价值。
0 参考资料
0.1 Apollo各模块系列笔记记录
0.2 Apollo优秀教程合集
1 什么是Apollo
参考文章 |
---|
百度Apoll无人驾驶高精度地图的制作和opendrive格式详细讲解 - 知乎 (zhihu.com) |
apollo高精地图的数据元素分类以及阿波罗地图规范和opendrive规范的区别 - 知乎 (zhihu.com) |
社群分享内容 Apollo相对地图:基于人工驾驶路径的实时地图生成 (qq.com) |
1.1 简介
Apollo是百度的自动驾驶开源框架,根据自动驾驶的功能划分为不同的模块。
- 定位 - 比如GPS,但是GPS的精度只有米级别。有几个场景会不太合适,比如你在桥洞里,GPS信号不好的情况,另外还有一种情况是,停车的时候,你要知道前后车的距离,另外比如在雪天或者路况复杂的情况,这些情况下,仅有的GPS信号可能不能满足我们的要求,因此无人车又增加了激光雷达来测量周围环境的距离,而且可以精确到厘米。 因此产生了高精地图的需求,高精地图可以把周围的3D环境都记录下来,这样我们就可以通过3D图像来匹配周围的场景,来找到自己的位置,而且高精地图还可以记录比地图多的多的东西,比如红绿灯的位置,交通标志,左转还是右转道.通过高精地图我们不仅可以知道道路情况,还可以知道车辆需要获取的一些其他信息,让车辆知道自己的实时位置。
- 感知 - 我们总是希望车辆行驶在马路中间,这样更加安全,这就需要追踪到道路的路牙线,而道路随时会出现拐弯,那么追踪路牙线就用到了图像处理技术,另外还要感知到什么是车辆,什么是行人,主要涉及到图像的语义分割,感知是自动驾驶中最难,而且最具有挑战性的一块,因为只有感知到周围的行人,车辆,以及突发状况,才能为后面规划线路。
- 规划 - 目前已经知道当前道路情况,而且也已经感知到前面的车辆或者行人,如何去规划我们的行驶线路呢,这里需要解决的就是2个点之间的线路,而且行驶中途可能会出现新的情况,又需要重新规划线路,还有一种情况是,通过高精地图,我们已经知道前面需要转弯了,我们可以提前调整线路来适应这种需求。
- 控制 - 现在已经规划出了一条线路,剩下的就是控制汽车,按照已经规划好的线路行驶,而且如果遇到突发状况,需要立即停车,而且控制汽车能够按照预定的线路不会出现很大的偏离,这就是控制要做的事情。
1.2 结构目录
|-cyber 消息中间件,替换ros作为消息层
|-docker 容器相关
|-docs 文档相关
|-modules 自动驾驶模块,主要的定位,预测,感知,规划都在这里
|-calibration 校准,主要用于传感器坐标的校准,用于感知模块做传感器融合
|-canbus 通讯总线,工业领域的标准总线,CanBus 是将控制命令传递给车辆硬件的接口。它还将机箱信息传递给软件系统。
|-common 本模块中的代码不是针对某一模块的,各个模块得一些共性方法吧
|-contrib
|-control 控制模块,根据planning生成的路径对车辆轨迹进行控制,再底层就是发送命令到can总线,实现车辆的控制。控制模块通过产生油门、刹车和转向等控制命令来执行计划的时空轨迹。
|-data 地图等生成好的数据放在这里
|-dreamview 仿真,能够对自动驾驶过程中的数据进行回放
|-drivers 雷达,lidar,GPS, canbus,camera等驱动
|-guardian 新的安全模块,用于干预监控检测到的失败和action center相应的功能。 执行操作中心功能并进行干预的新安全模块应监控检测故障。
|-localization 定位,获取汽车的当前位置
|-map 地图模块
| -HD-Map 模块类似于库。它不是发布和订阅消息,而是经常用作查询引擎支持,以提供关于道路的特定结构化信息。
定位——定位模块利用各种信息源(如 GPS、LiDAR 和 IMU)来估计自动驾驶汽车的位置。
|-monitor 监控模块,主要是监控汽车状态,并且记录,用于故障定位,健康检查等
|-perception 感知,获取汽车当前的环境,行人,车辆,红绿灯等,给planning模块规划线路,感知模块识别自动驾驶汽车周围的环境。感知模块内部包含两个重要的子模块:障碍物检测和交通灯检测。
|-planning 规划,针对感知到的情况,对路径做规划,短期规划,只规划100-200M的距离,生成好的路径给control模块,规划模块规划自动驾驶汽车要采取的时空轨迹。
|-prediction 预测,属于感知模块,对运动物体的轨迹做预测,预测模块用来预测与感知障碍物未来的运动轨迹。
|-routing 导航线路,就是百度地图上查询2点之间的线路,生成的线路短期规划还是planning模块,路由模块告诉自动驾驶汽车通过全局路径到达目的地。
|-third_party_perception 第三方感知模块
|-tools 工具
|-transform 坐标转换,不同坐标系的坐标转换
|-v2x 顾名思义就vehicle-to-everything,其希望实现车辆与一切可能影响车辆的实体实现信息交互,
目的是减少事故发生,减缓交通拥堵,降低环境污染以及提供其他信息服务。车路协同技术
|-scripts 脚本
|-third_party 第三方库
|-tools 工具目录
1.3 各模块架构
Apollo 无人驾驶平台是以高精地图和定位模块作为核心。其他的模块都是以这两个模块为基础。
1.3.1 定位
一种是结合GPS和IMU信息的RTK(Real Time Kinematic实时运动)方法,另一种是融合GPS、IMU和激光雷达信息的多传感器融合方法。
1.3.2 感知
1.3.3 预测
预测模块从感知模块接收障碍物,其基本感知信息包括位置、方向、速度、加速度,并生成不同概率的预测轨迹。
1.3.4 路由
路由模块依赖于路由拓扑文件,通常称为Apollo中的routing_map.*。路由地图可以通过命令来生成。
1.3.5 规划
1.3.6 控制
- https://github.com/ApolloAuto/apollo/blob/master/modules/control/README_cn.md
- 本模块基于规划和当前的汽车状态,使用不同的控制算法来生成舒适的驾驶体验。控制模块可以在正常模式和导航模式下工作。
- 输出:给底盘的控制指令(转向,节流,刹车)。
1.4 编译
apollo采用的是bazel来进行编译。
2 Cyber
Cyber是百度Apollo推出的替代Ros的消息中间件,自动驾驶中的各个模块通过Cyber进行消息订阅和发布,同时Cyber还提供了任务调度、录制Bag包等功能。
2.1 Cyber实现的功能
cyber提供的功能概括起来包括2方面:
- 消息队列 - 主要作用是接收和发送各个节点的消息,涉及到消息的发布、订阅以及消息的buffer缓存等。
- 实时调度 - 主要作用是调度处理上述消息的算法模块,保证算法模块能够实时调度处理消息。
除了这2方面的工作,cyber还需要提供以下2部分的工作:
- 用户接口 - 提供灵活的用户接口
- 工具 - 提供一系列的工具,例如bag包播放,点云可视化,消息监控等
总结起来就是,cyber是一个分布式收发消息,和调度框架,同时对外提供一系列的工具和接口来辅助开发和定位问题。其中cyber对比ROS来说有很多优势,唯一的劣势是cyber相对ROS没有丰富的算法库支持。
3 Audio
audio模块是Apollo 6.0新增加的模块,主要的用途是通过声音来识别紧急车辆(警车,救护车,消防车)。目前的功能还相对比较简单,只能识别单个紧急车辆,同时需要环境风速低于20mph。
4 Canbus
4.1 Canbus模块介绍
控制器局域网 (Controller Area Network,简称CAN或者CAN bus) 是一种车用总线标准。被设计用于在不需要主机(Host)的情况下,允许网络上的节点相互通信。采用广播机制,并利用标识符来定义内容和消息的优先顺序,使得canbus的扩展性良好,同时不基于特殊类型(Host)的节点,增加了升级网络的便利性。 这里的Canbus模块其实可以称为Chassis模块,主要的作用是反馈车当前的状态(航向,角度,速度等信息),并且发送控制命令到车线控底盘,可以说Canbus模块是车和自动驾驶软件之间的桥梁。由于这个模块和”drivers/canbus”的联系紧密,因此也一起在这里介绍。 Canbus模块是车和自动驾驶软件之间的桥梁,通过canbus驱动(drivers/canbus)来实现将车身信息发送给apollo上层软件,同时接收控制命令,发送给汽车线控底盘实现对汽车的控制。
那么canbus模块的输入是什么?输出是什么呢?
可以看到canbus模块:
- 输入 - 1. ControlCommand(控制命令)
- 输出 - 1. Chassis(汽车底盘信息), 2. ChassisDetail(汽车底盘信息详细信息)
Canbus模块的输入是control模块发送的控制命令,输出汽车底盘信息,这里apollo的上层模块被当做一个can_client来处理,实现接收和发送canbus上的消息。
Canbus模块的目录结构如下:
├── BUILD // bazel编译文件
├── canbus_component.cc // canbus主入口
├── canbus_component.h
├── canbus_test.cc // canbus测试
├── common // gflag配置
├── conf // 配置文件
├── dag // dag依赖
├── launch // launch加载
├── proto // protobuf文件
├── testdata // 测试数据
├── tools // 遥控汽车和测试canbus总线工具
└── vehicle //
5 Control
5.1 Control模块简介
Apollo控制模块的逻辑相对比较简单,控制模块的作用是根据规划(planning模块)生成的轨迹,计算出汽车的油门,刹车和方向盘信号,控制汽车按照规定的轨迹行驶。采用的方法是根据汽车动力和运动学的知识,对汽车进行建模,实现对汽车的控制。目前apollo主要用到了2种控制方式:PID控制和模型控制。
首先我们需要搞清楚control模块的输入是什么,输出是什么?
可以看到control模块:
- 输入 - Chassis(车辆状态信息), LocalizationEstimate(位置信息), ADCTrajectory(planning模块规划的轨迹)
- 输出 - ControlCommand(油门,刹车,方向盘)
Control模块的目录结构如下:
├── BUILD // bazel编译文件
├── common // PID和控制器的具体实现 --- 算法具体实现
├── conf // 配置文件 --- 配置文件
├── control_component.cc // 模块入口
├── control_component.h
├── control_component_test.cc
├── controller // 控制器 --- 具体的控制器实现
├── dag // dag依赖
├── integration_tests // 测试
├── launch // launch加载
├── proto // protobuf文件,主要是各个控制器的配置数据结构
├── testdata // 测试数据
└── tools // 工具类
6 Guardian
6.1 简介
Guardian模块的主要作用是监控自动驾驶系统状态,当出现模块为失败状态的时候,会主动切断控制命令输出,并且刹车。
7 Localization
7.1 Localization模块简介
localization模块主要实现了以下2个功能:
- 输出车辆的位置信息(planning模块使用)
- 输出车辆的姿态,速度信息(control模块使用)
其中apollo代码中分别实现了3种定位方法:
- GNSS + IMU定位
- NDT定位(点云定位)
- MSF(融合定位)
7.2 代码目录
下面是localization的目录结构,在查看具体的代码之前最好看下定位模块的readme文件:
├── common // 声明配置(flags),从conf目录中读取相应的值
├── conf // 配置文件存放目录
├── dag // cyber DAG流
├── launch // cyber的配置文件,依赖DAG图(这2个和cyber有关的后面再分析)
├── msf // 融合定位(gnss,点云,IMU融合定位)
│ ├── common
│ │ ├── io
│ │ ├── test_data
│ │ └── util
│ ├── local_integ
│ ├── local_map
│ │ ├── base_map
│ │ ├── lossless_map
│ │ ├── lossy_map
│ │ ├── ndt_map
│ │ └── test_data
│ ├── local_tool
│ │ ├── data_extraction
│ │ ├── local_visualization
│ │ └── map_creation
│ └── params
│ ├── gnss_params
│ ├── vehicle_params
│ └── velodyne_params
├── ndt // ndt定位
│ ├── map_creation
│ ├── ndt_locator
│ └── test_data
│ ├── ndt_map
│ └── pcds
├── proto // 消息格式
├── rtk // rtk定位
└── testdata // imu和gps的测试数据
通过上述目录可以知道,定位模块主要实现了rtk,ndt,msf这3个定位方法,分别对应不同的目录。proto文件夹定义了消息的格式,common和conf主要是存放一些配置和消息TOPIC。
8 Map
8.1 Map模块简介
其实我们只需要知道map模块的主要功能是“加载openstreet格式的地图,并且提供一系列的API给其他模块使用”。
8.2 Map目录结构
本章主要介绍下apollo代码的map模块,map的代码目录结构如下:
├── data // 生成好的地图
│ └── demo
├── hdmap // 高精度地图
│ ├── adapter // 从xml文件读取地图(openstreet保存格式为xml)
│ │ └── xml_parser
│ └── test-data
├── pnc_map // 给规划控制模块用的地图
│ └── testdata
├── proto // 地图各元素的消息格式(人行横道,车道线等)
├── relative_map // 相对地图
│ ├── common
│ ├── conf
│ ├── dag
│ ├── launch
│ ├── proto
│ ├── testdata
│ │ └── multi_lane_map
│ └── tools
├── testdata // 测试数据?
│ └── navigation_dummy
└── tools // 工具
apollo的高精度地图采用了opendrive格式,opendrive是一个统一的地图标准,这样保证了地图的通用性。其中map模块主要提供的功能是读取高精度地图,并且转换成apollo程序中的Map对象。直白一点就是说把xml格式的opendrive高精度地图,读取为程序能够识别的格式。 map模块没有实现的功能是高精度地图的制作。
8.3 HD-Map
由于apollo的hd map制作没有开放,所以目前hd map的生成是需要向百度提需求的。 如果想自己制作的话,apollo有提供建议如下:
- 原始数据采集(视觉、激光雷达、GPS等)以及处理。
- 地图数据生成。从步骤一生成的数据通过算法或者人工的方式获取地图数据。
- 地图格式组织。将地图数据转换为Apollo的高精度地图格式(可以参照base_map.xml格式,其他的地图都可以从base_map.xml生成)。
- 注意:这三个步骤的工具均需要自己开发,如果只是小规模的简单测试,也可以参照base_map.xml格式手工组织数据。
- 将HD map加入apollo1.5:
有两个方法,一个是通过添加一个新的目录,使用apollo系统;一个是替换原有目录下的地图文件。
- 新加一个hd map:
- 在/apollo/modules/map/data目录下,创建一个目录new_map。
- 将生成的hd map放入new_map中,如有配置文件,可以参考sunnyvale_office目录下的配置文件。
- 编译,执行bash apollo.sh build。
- 然后执行bash scripts/hmi.sh。
- 打开ip:8887,在选择地图的下拉框中就可以看到新加入的hd map了。
- 直接copy new_garage 重命名为new_garage_2测试的,测试通过。
- 注1:编译的时候,应该相当于将/apollo/modules/map/data/new_map注册到系统中去,以便启动hmi时,前端网页可以定位到/apollo/modules/map/data/new_map目录,进而加载其中的文件。也因此,可以有第二个方法加入hd map。
- 利用现有的地图目录,加入地图:
- 假设apollo1.5中,已经添加了new_map,此时只需要替换目录下的hd map所有的文件,这样不需要编译,即可使用新的hd map。
9 Monitor
9.1 简介
monitor模块主要是监控硬件和软件状态,当出现故障的时候,显示故障原因,并且输出状态给guardian模块进行紧急处理。
10 Perception
参考文章 |
---|
Apollo学习笔记7-感知融合_hello1268的博客-CSDN博客_感知融合 |
10.1 Perception模块简介
主要用到的传感器类型包括相机、激光雷达和毫米波雷达,相机和激光雷达的目标检测部分都是利用深度学习网络完成,然后都进行了目标跟踪,最后设计了一个融合模块,用来融合三种传感器跟踪后的目标序列,获得更加稳定可靠的感知结果。
首先简单看下perception的目录结构:
.
├── BUILD
├── Perception_README_3_5.md
├── README.md
├── base // 基础类
├── camera // 相机相关,相机检测 --- 子模块流程
├── common // 公共目录
├── data // 相机的内参和外参
├── fusion // 传感器融合
├── inference // 深度学习推理模块
├── lib // 一些基础的库,包括线程、时间等
├── lidar // 激光雷达相关 --- 子模块流程
├── map // 高精度地图
├── model // 深度学习模型
├── onboard // 各个子模块的入口,组件文件结构和组件类的实现 --- 子模块入口
├── production // 感知模块入口(深度学习模型也存放在这里)--- 通过cyber启动子模块
├── proto // 数据格式,protobuf
├── radar // 毫米波 --- 子模块流程
├── testdata // 上述几个模块的测试数据
└── tool // 离线测试工具
下面介绍几个重要的目录结构:
- production目录 - 感知模块的入口在production目录,通过lanuch加载对应的dag,启动感知模块,感知模块包括多个子模块,在onboard目录中定义。
- onboard目录 - 定义了多个子模块,分别用来处理不同的传感器信息(Lidar,Radar,Camera)。各个子模块的入口在onboard目录中,每个传感器的流程大概相似,可以分为预处理,物体识别,感兴趣区域过滤以及追踪。
- inference目录 - 深度学习推理模块,我们知道深度学习模型训练好了之后需要部署,而推理则是深度学习部署的过程,实际上部署的过程会对模型做加速,主要实现了caffe,TensorRT和paddlepaddle3种模型部署。训练好的深度模型放在”modules\\perception\\production\\data”目录中,然后通过推理模块进行加载部署和在线计算。
- camera目录 - 主要实现车道线识别,红绿灯检测,以及障碍物识别和追踪。
- radar目录 - 主要实现障碍物识别和追踪(由于毫米波雷达上报的就是障碍物信息,这里主要是对障碍物做追踪)。
- lidar目录 - 主要实现障碍物识别和追踪(对点云做分割,分类,识别等)。
- fusion目录 - 对上述传感器的感知结果做融合。
整个模块的流程如图:
可以看到感知模块由production模块开始,由fusion模块结束。
10.2 融合流程
主要流程如下:
比较全的流程如下:
11 Planning
11.1 Planning模块简介
规划(planning)模块的作用是根据感知预测的结果,当前的车辆信息和路况规划出一条车辆能够行驶的轨迹,这个轨迹会交给控制(control)模块,控制模块通过油门,刹车和方向盘使得车辆按照规划的轨迹运行。 规划模块的轨迹是短期轨迹,即车辆短期内行驶的轨迹,长期的轨迹是routing模块规划出的导航轨迹,即起点到目的地的轨迹,规划模块会先生成导航轨迹,然后根据导航轨迹和路况的情况,沿着短期轨迹行驶,直到目的地。这点也很好理解,我们开车之前先打开导航,然后根据导航行驶,如果前面有车就会减速或者变道,超车,避让行人等,这就是短期轨迹,结合上述的方式直到行驶到目的地。
11.2 routing与planning的关系
routing模块规划的路径是planning模块规划轨迹的输入信息 来源之一,能够协助planning规划出安全,可靠的行驶轨迹。
planning模块通常根据传感器输入(激光雷达、视觉摄像头等)规划出车辆当前时刻需要的一条行驶轨迹,但是一些特殊场景下,如大雾天气、夜晚、匝道进出口等,由于输入信息缺失,不能规划出安全行驶轨迹,此时可以根据routing规划导航路径,结合高精地图信息,能够得到一条满足行驶的轨迹。
11.3 planning 的输入输出
熟悉Apollo CyberRT框架的小伙伴都知道在该框架下,输入输出由Reader和Writer构成,并定义在每个模块的component文件中。除此之外,CyberRT框架定义了两种模式,分别为消息触发和时间触发,而planning中采用的为消息触发,因此必须接到特定的上游消息后,才会进入内部主逻辑,而消息触发的上游消息,定义为component中Process()函数的入参。
planning的上下游关系总结为下图:
这里再重复一下,planning的输入分为Reader和Process()入参的原因在于,planning依赖于Process()的三个上游输入,只有同时接到这三个输入,才会触发planning的主逻辑,即是planning正常启动的必要条件。而Reader则不是,其中部分上游还依赖于配置参数是否打开,具体可以查看Apollo的源码。
planning的输出就比较简单了,主要是给控制的ADCTrajectory数据,包含了一条带时间、速度的轨迹点集,具体的格式定义可以查看对应的proto文件。
12 Prediction
参考文章 |
---|
如何学习百度apollo无人驾驶预测模块? - 知乎 (zhihu.com) |
apollo预测模块分享(二十一) - 知乎 (zhihu.com) |
12.1 简介
预测模块是直接接收的感知模块给出的障碍物信息,这和CV领域的传统预测任务有区别,CV领域的预测任务不需要先识别物体,只需要根据物体的特征,对比前后2帧,然后得出物体的位置,也就说甚至不需要物体识别,业界之所以不这么做的原因是因为检测物体太耗时了。 当然也有先检测物体再做跟踪的,也就是说目前apollo中的物体检测实际上是采用的第二种方法,这也可以理解,反正感知模块一定会工作,而且一定要检测物体,所以何不把这个信息直接拿过来用呢?
以上是关于万字详解Apollo,整理全网Apollo笔记学习的主要内容,如果未能解决你的问题,请参考以下文章