热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Apollo2.0框架及源码分析(一)|软硬件框架

原文地址:https:zhuanlan.zhihu.comp33059132前言如引言中介绍的,这篇软硬件框架多为现有消息的整合加一些个人的想法。关于

原文地址:https://zhuanlan.zhihu.com/p/33059132

 

前言

如引言中介绍的,这篇软硬件框架多为现有消息的整合加一些个人的想法。关于 Apollo 介绍的文章已经有许多,很多要点大家都已经足够了解,这些点在本篇中会被略写。本篇文章如有错误、不足之处,还请大家多多指教。

Apollo 官方 GitHub 链接:Apollo Auto


在历经1.0,1.5 两个版本更新之后,百度无人驾驶平台 Apollo 2.0 在2018年初正式发布。其技术框架如下图所示 [1]。

图片来源:微信公众号:自动驾驶干货铺

如上图所示,Apollo 技术框架主要由四部分组成,从下往上,依次为:

  • Reference Vehicle Platform参考汽车层,用于对汽车实现电子化的控制。这一层涉及到的 CAN 协议一般由主机厂制订,且严格保密。百度早期使用了 AutonomouStuff 公司改装的 Lincoln MKZ 来规避这一问题[2]。
  • Reference Hardware Platform: 参考硬件层,为 Apollo 推荐的硬件设备,如: 计算单元(工控机),GPS/IMU,LiDAR,Radar 等等。
  • Open Software Platform开放软件平台, 为 Apollo 的核心部分。
  • Cloud Service Platform云端服务层,为百度可提供的数据,高精度地图等各项云服务,应该也是百度之后盈利的主要来源。


本文重点叙述 Reference Hardware Platform 和 Open Software Platform 这两层。

Reference Hardware Platform

百度建议的硬件安装示意图如下所示 [3]:

 

侧视图 (图片来源:Apollo 技术社区)

右视图 (图片来源:Apollo 技术社区)

可见其采用的感知方案还是为 LiDAR, Radar,摄像头相配合的传统方案。Apollo 推荐的核心部件为:

推荐的硬件配置

从价格上看,百度 Apollo 2.0 不可能是一个量产的方案。作为大脑的工控机价格在 $2000 美元左右,Velodyne HDL-64E 的售价至少在 $75,000 美元。 这些过于昂贵的传感器使得 Apollo 更像是一个 Demo 的解决方案。

值得一提的是,从 Apollo 感知模块的代码中可以看到,Apollo 2.0 也同时为 Velodyne 16线激光雷达留下接口。

enum SensorType {VELODYNE_64 = 0,VELODYNE_16 = 1,RADAR = 2,CAMERA = 3,UNKNOWN_SENSOR_TYPE = 10,
};

联想到最近 Velodyne 宣布16线激光雷达最高降价50%的消息,售价可能会低至 $4000 美元[4]。那么随着激光雷达价格近一步的降低,Apollo 感知融合算法的进一步完善,从传感器的成本来看,在特定场景下的自动驾驶还是有望实现的。

另外 Apollo 的传感器配置也显得不太丰富,在车身侧面和后面都没有安放雷达。相比较奥迪A8 几乎武装到牙齿,Apollo 传感器上的冗余度总觉得是有些不足 (虽然这样比可能有点不公平,奥迪A8是量产车型,且使用的是4线的激光雷达)。

另外摄像头安装在了车顶而不是车窗内,那么如何在雨天保证摄像头不受影响也是一个问题。

 

Open Software Platform

Apollo 的 Open Software Platform 分三个部分 RTOS,Runtime Framework 及各个功能模块 Modules。

RTOS

Apollo RTOS的主体部分是为 Ubuntu 14.04 + ApolloAuto/apollo-kernel 的组合。 Apollo 安装指南上推荐的在工控机上安装的软件及版本如下表所示。

IPC 安装的软件

Apollo-kerne 的存在是因为 Ubuntu 并不是一个实时系统。

实时系统的定义如下:

实时操作系统(RTOS)是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统做出快速响应,调度一切可利用的资源完成实时任务,并控制所有实时任务协调一致运行的操作系统。提供及时响应和高可靠性是其主要特点。[实时操作系统_百度百科]

简单说,实时系统保证了某任务在 deadline 之前被完成。系统的实时性在汽车上的重要性是不言而喻的,我用一个视频来说明下其重要程度 (最早看到这段视频是在学校实时系统课的官网上,十分震撼,二话没说直接就去上课了...)。

 

针对于此,百度在 Ubuntu 的基础上提供了 apollo-kerne 来保证系统的实时性。Apollo-kerne 主要使用了一个名为 PREEMPT_RT 的 Linux 实时补丁包,并在此基础上做了部分改动。这个实时内核在非生产环境下不是必须的,在生产环境中 Apollo 官方是建议安装这个内核的[5]。

 

Runtime Framework

Runtime Framework 是 Apollo 软件的运行环境,即 ApolloAuto/apollo-platform 的部分。Apollo 的 Runtime Framework 是一个定制版的 Robot Operating System (ROS) 。针对 ROS 系统的不足百度对 ROS 做了以下三方面的改动 [6]

1. ROS Decentralization Feature
2. High Efficient Communication based on Shared Memory Transport Feature
3. Native Support with Protobuf Feature

简单翻译下是

  • 去中心化
  • 共享内存以提升节点间的传输效率
  • 原生支持 Protobuf

这里有篇文章很详细的阐述了 Apollo 对 ROS 的做的改动,我在这里只把这三点再简单叙述一下。

干货曝光(二)|资深架构师首次解密Apollo ROS有何不同!​mp.weixin.qq.com图标

 

去中心化

ROS 在安全性上的一个不足是 ROS 需要有一个节点作为主服务器,用于建立各节点之间的通信连接。这一机制使得ROS节点的容错性增强,各模块的隔离程度增高,但也带来了单点失效(single-point failure)的风险。由于 ROS 本身缺乏针对这种状况的异常恢复机制,当服务器宕机时,整个系统会崩溃。这种情况如果发生在自动驾驶行驶过程中,无疑会造成车毁人忙的后果。针对于此,Apollo 采用了FAST RTPS (real-time Publish/Subscribe)来实现去中心化。

共享内存

ROS节点之间的通信是通过 socket 完成的,在进行数据广播的时候,底层使用的是多个点对点的传送。这种方式速度比较缓慢,且使用了较多的资源。Apollo 使用共享内存的方式对其进行改进,加快了通信速率,减少了CPU损耗。

支持Protobuf

Apollo 将 google 的 Protobuf 与 ROS 深度集成,用于提高数据的版本兼容性。其优势在于当模块接口升级以后,通讯的数据也可以相互兼容。另一个好处是宝贵的自动驾驶的历史数据在模块升级后也可以一直被使用。

 

其实关于 ROS 的优劣和在自动驾驶中的修改解决方案在不少文章中都有被提到。我比较喜欢的一篇是刘少山团队的介绍。

【无人驾驶系列】基于ROS的无人驾驶系统​blog.csdn.net

 

用下面这个表格来对比下百度和刘少山对 ROS 的改进。

ROS 的不足及改进

由表格可以看出,

  • 使用共享内存的方式来提升 ROS 节点之间的通讯是一个常用的方式。
  • 刘少山团队使用了 Zookeeper 的机制来应对 ROS 单点失效的问题。也就是说,当旧的主节点失效之后,其余节点会选举出新的主节点,使得系统可以正常运行。这个问题上 Apollo 使用了 RTPS。
  • 刘少山团队使用了 Linux Container 对 ROS 的节点进行了隔离,确保当某一节点被劫持时,此节点不会影响整个系统。在 Apollo 的文档里,我没找到相对应的信息。

此外再想提一下 ROS 实时性的问题,ROS 本身不是一个实时系统。而在汽车领域,对实时的要求却很高。虽然百度使用了 PREEMPT_RT 内核来增强了 ROS 所在的 linux 环境的实时性,但我不认为这会彻底解决 ROS 本身弱实时性的问题。如果这一问题能这么轻易的被一个补丁包解决的话,ROS 2.0 也不会进展如此缓慢了。想必百度也深知这一点,所以才会寻求和黑莓的嵌入式实时系统 QNX 的合作吧。

或许 Apollo 使用 ROS 也只是为了快速开发和推广宣传,在之后的量产过程中百度改用其他的框架也不是没有可能。

 

Modules

各个功能模块的实现是 Apollo 代码的一个重点。Modules 的代码在 Apollo/apollo/modules中,如下表所示 :

各个模块的简单描述许多文章都有介绍,这里就不再赘述了,具体可参考以下两篇文章。

李科男:百度Apollo1.5 自动驾驶开源模块分析​zhuanlan.zhihu.com图标xinhe sun:百度无人驾驶系统Apollo 2.0小解析​zhuanlan.zhihu.com图标

Apollo 工作的整体流程也可参考上面提到的这篇文章 xinhe sun:百度无人驾驶系统Apollo 2.0小解析 。为方便阅读,这里把它摘过来。

首先,用户输入目的地,routing模块就可以根据终点位置计算出具体的导航信息。激光雷达、毫米波雷达和摄像头拍摄到的数据配合高精度地图由percepting模块计算出3D的障碍物信息并识别交通标志及交通信号,这些数据进入perdiction模块,计算出障碍物的可能轨迹,如此就可以结合以上信息并根据车辆定位模块localizationg提供的车辆位置由planning模块得到车辆应该走的具体车道。

得到车道后车辆control模块结合车辆的当前状态计算加速、刹车和方向的操作信号,此信号进入CAN卡后输出到车内,如此实现了车辆的自动驾驶。

在整个流程中,monitor模块会及时监测硬件及系统的健康状况,出现问题肯定就会中止驾驶过程。对于驾驶中的信息,用户可以通过web应用dreamview来查看

对于各个模块的源码实现,可以参考这篇文章。这篇文章侧重分析各模块中函数的含义代码技巧。虽然 Apollo 1.0 稍微旧了一点,但代码量相对小,阅读一下有助于理解系统的代码框架。

slamcode:百度 自动驾驶框架 Apollo 1.0 -源码分析​zhuanlan.zhihu.com图标

 

几个重要的功能的模块之间的关系如下图所示 [7]

Apollo 2.0 Software Architecture (图片来源:Apollo 技术社区)

从此图可以看出定位高精度地图是 Apollo 整个软件体系的基石,在代码中也会看到高精度地图起到极其重要的作用。比如在感知环节,摄像头会通过高精度地图知道交通灯所在的位置,确定 ROI 区域,从而减少计算量。这个构架也佐证了,百度一定会试图在高精度地图上分一杯羹[8]。

为了后面方便叙述各模块的工作,这里简单介绍两个名词。在实时系统中一个任务的调度方式通常可大致分为两类:时间驱动(timer-triggered) 和 事件驱动(event-triggered)。

所谓时间驱动是指该任务的触发条件是时间,通常该任务为周期性的任务。比如某任务每 10ms 执行一次,那么该任务为时间驱动的任务。顺便安利嵌入式的一本书 《时间触发嵌入式系统设计模式》,思路清晰,相当实用。在 Apollo 的代码里,以时间为触发条件的模块都会提供 OnTimer 这样的一个接口。

事件驱动是指任务的触发条件为某一事件。例如驾驶员看到红灯会踩刹车,在这一操作中,踩刹车举动是由于红灯亮这一事件触发的。

了解这两个概念更有助于进一步了解每个模块是如何被调用的。接下来选几个重要的模块简单分析一下。

 

Localization

Localization

在这个模块里,Apollo提供了两种定位模式

  1. RTK-based,即 GNSS+IMU的传统定位方式。 该模式属于 timer-triggered, 该模式下的定位应该会被周期性的调用。
  2. 多传感器融合 (Multi-sensor Fusion Localization),即 GNSS, IMU 和 Lidar 三者配合使用,完成定位。如下图所示,大体原理应该是这样的:首先比对 Lidar 采集的点云事先建好的地图,得到 Lidar 的定位结果。之后 Lidar 定位 ,GNSS 定位,IMU 三者用卡尔曼滤波做融合。实现的具体原理参见这篇论文 [1711.05805] Robust and Precise Vehicle Localization based on Multi-sensor Fusion in Diverse City Scenes 。

Robust and Precise Vehicle Localization based on Multi-sensor Fusionin Diverse City Scenes

 

Perception

Preception

Perception 模块有两个重要的内容,即 3D障碍物感知 和 交通灯感知

需要交通灯感知是因为 Apollo 2.0 是简单城市路况下的自动驾驶。在高速公路之类的限定场景的自动驾驶中,交通灯的检测就不是必须了。在这个部分中,摄像头只负责感知交通灯的状态,而不负责其他障碍物的检测。

3D 障碍物感知部分使用卡尔曼滤波,融合了 lidar 和 radar 检测的结果。正常情况下,视觉检测障碍物应该也是一个很重要的部分。Apollo 2.0 没有做视觉的融合,可能是因为时间有限,该功能要在下一个版本才出现?

有趣的是当我们观察 apollo 官方库的时候,会发现有个分支叫 "mobileye_radar", 该分支4个月前就停止更新了,但该版本中也未看到 mobileye 或者视觉检测障碍物的影子。这个名称说明百度曾经也考虑过使用 mobileye 的方案?不知道基于什么样的考虑,百度没有继续采用这个方案。这些背后的事情,想想很有趣啊。

Apollo/apollo,branches: mobileye_radar

个人倾向于百度藏拙了。因为在百度其自定位模块 elo (见下图) 已经使用了摄像头来提取环境特征。那么用摄像头来完善感知部分,技术上肯定可以实现的。或者百度觉得现有的感知方案已经足够,即使再融合视觉对整体性能提高也有限。

百度自定位模块:aka Ego Localization (图片来源:Apollo 技术社区)

 

Planning

Planning 模块是 timer-triggered的, 以固定的频率被调用,该模块提供了两种方案:

1. RTK replay planner (since Apollo 1.0)
2. EM planner (since Apollo 1.5)

这里引用下 

@xinhe sun

 的回答 [9]

规划车道有两种方式,一种是提前把轨迹存入程序,然后根据车辆状态和位置提取轨迹,另外一种是实时计算。

Apollo 最新在开发的是 lattice planner 决策算法[10] (应该不属于 Apollo 2.0 的范畴了)。

Lattice Planner是基于斯坦福大学在DARPA挑战赛中使用过的一种路径规划算法,优势在于更好地理解交通情况,降低规划的复杂性,高速情况表现优异。感兴趣的同学可以参考Moritz Werling等人所著论文:

https://pdfs.semanticscholar.org/0e4c/282471fda509e8ec3edd555e32759fedf4d7.pdf

 

Control & Canbus

 

Control & Canbus

 

如图所示,Control 控制模块提供了三个主要的数据接口: OnPad,OnMonitor 和 OnTimer。 其中 OnPad 和 OnMonitor 用于仿真和人机交互,OnTimer 用于周期性的指令传递。

控制模块以决策模块生成的轨迹为输入,计算出底层所需的具体的指令,比如加速,减速,转向等等,并通过OnTimer 接口,周期性的向 Canbus 传递控制指令。Canbus 一旦接收到具体的指令之后就会调用对应的函数执行此操作。与此同时,Canbus 也会周期性的向 Control 模块发送汽车当前的信息。

我比较好奇的一点是,Apollo 会怎么使用这些汽车底盘信息。光从图中的信息的流动上看,Control 端并没有继续向 Planning 或者其他上层模块发送底盘信息。但根据技术文档,在Planning 模块中这些信息有被使用 [7]。

Finally, the planning module needs to know the location (Localization: where I am) as well as the current autonomous vehicle information (Chassis: what is my status).

我的一个猜测是这些信息目前只被用于监控汽车的当前状况。从这一点看,Apollo 也许可以考虑在将来结合更多的底盘信息来进一步优化整个系统。譬如结合汽车的里程数、轮速等等来提高汽车定位的精度。


以上,感谢阅读。

如需转载,请注明出处。

 

该系列的汇总链接见:

Apollo 2.0 框架及源码分析(零) | 引言

 

参考来源:

[1] 无人驾驶技术入门(二)——不会写代码也能做无人驾驶工程师

[2] 无人驾驶技术入门(一)| 百度无人驾驶的引路人

[3] apollo_2_0_hardware_system_installation_guide_v1

[4] 新年伊始,Velodyne带来利好消息:16线激光雷达价格减半 | 雷锋网

[5]【Apollo直答号】Apollo的实时内核必须安装吗?安装和不安装有什么区别?

[6] ApolloAuto/apollo-platform

[7] Apollo_2.0_Software_Architecture

[8] 大家都在关注百度Apollo,但你们的重点选错了 【图】- 车云网

[9] 百度无人驾驶系统Apollo 2.0小解析

[10] 【Apollo直答号】Apollo2.0的定位模块中LiDAR定位使用的预建地图是LiDAR-SLAM地图吗?


推荐阅读
  • 在拉斯维加斯举行的Interop 2011大会上,Bitcurrent的Alistair Croll发表了一场主题为“如何以云计算的视角进行思考”的演讲。该演讲深入探讨了传统IT思维与云计算思维之间的差异,并提出了在云计算环境下应具备的新思维方式。Croll强调了灵活性、可扩展性和成本效益等关键要素,以及如何通过这些要素来优化企业IT架构和运营。 ... [详细]
  • 在OpenShift上部署基于MongoDB和Node.js的多层应用程序
    本文档详细介绍了如何在OpenShift 4.x环境中部署一个包含MongoDB数据库和Node.js后端及前端的多层应用程序。通过逐步指导,读者可以轻松完成整个部署过程。 ... [详细]
  • 为什么多数程序员难以成为架构师?
    探讨80%的程序员为何难以晋升为架构师,涉及技术深度、经验积累和综合能力等方面。本文将详细解析Tomcat的配置和服务组件,帮助读者理解其内部机制。 ... [详细]
  • javascript分页类支持页码格式
    前端时间因为项目需要,要对一个产品下所有的附属图片进行分页显示,没考虑ajax一张张请求,所以干脆一次性全部把图片out,然 ... [详细]
  • 您的数据库配置是否安全?DBSAT工具助您一臂之力!
    本文探讨了Oracle提供的免费工具DBSAT,该工具能够有效协助用户检测和优化数据库配置的安全性。通过全面的分析和报告,DBSAT帮助用户识别潜在的安全漏洞,并提供针对性的改进建议,确保数据库系统的稳定性和安全性。 ... [详细]
  • Flowable 流程图路径与节点展示:已执行节点高亮红色标记,增强可视化效果
    在Flowable流程图中,通常仅显示当前节点,而路径则需自行获取。特别是在多次驳回的情况下,节点可能会出现混乱。本文重点探讨了如何准确地展示流程图效果,包括已结束的流程和正在执行的流程。具体实现方法包括生成带有高亮红色标记的图片,以增强可视化效果,确保用户能够清晰地了解每个节点的状态。 ... [详细]
  • 本文介绍了如何利用Shell脚本高效地部署MHA(MySQL High Availability)高可用集群。通过详细的脚本编写和配置示例,展示了自动化部署过程中的关键步骤和注意事项。该方法不仅简化了集群的部署流程,还提高了系统的稳定性和可用性。 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • 尽管我们尽最大努力,任何软件开发过程中都难免会出现缺陷。为了更有效地提升对支持部门的协助与支撑,本文探讨了多种策略和最佳实践,旨在通过改进沟通、增强培训和支持流程来减少这些缺陷的影响,并提高整体服务质量和客户满意度。 ... [详细]
  • Java测试服务器调试指南详细介绍了如何进行远程调试,并深入解析了Java Xdebug参数的使用方法。本文首先概述了Java内置的调试功能,重点介绍了JDB这一类似于GDB的强大调试工具。通过实例演示,读者可以掌握在测试环境中高效调试Java应用程序的技巧,包括配置远程调试环境和优化调试参数,以提高开发效率和代码质量。 ... [详细]
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • Spring 切面配置中的切点表达式详解
    本文介绍了如何在Spring框架中使用AspectJ风格的切面配置,详细解释了切点表达式的语法和常见示例,帮助开发者更好地理解和应用Spring AOP。 ... [详细]
  • 本文详细介绍了 InfluxDB、collectd 和 Grafana 的安装与配置流程。首先,按照启动顺序依次安装并配置 InfluxDB、collectd 和 Grafana。InfluxDB 作为时序数据库,用于存储时间序列数据;collectd 负责数据的采集与传输;Grafana 则用于数据的可视化展示。文中提供了 collectd 的官方文档链接,便于用户参考和进一步了解其配置选项。通过本指南,读者可以轻松搭建一个高效的数据监控系统。 ... [详细]
  • 在ElasticStack日志监控系统中,Logstash编码插件自5.0版本起进行了重大改进。插件被独立拆分为gem包,每个插件可以单独进行更新和维护,无需依赖Logstash的整体升级。这不仅提高了系统的灵活性和可维护性,还简化了插件的管理和部署过程。本文将详细介绍这些编码插件的功能、配置方法,并通过实际生产环境中的应用案例,展示其在日志处理和监控中的高效性和可靠性。 ... [详细]
  • Netty框架中运用Protobuf实现高效通信协议
    在Netty框架中,通过引入Protobuf来实现高效的通信协议。为了使用Protobuf,需要先准备好环境,包括下载并安装Protobuf的代码生成器`protoc`以及相应的源码包。具体资源可从官方下载页面获取,确保版本兼容性以充分发挥其性能优势。此外,配置好开发环境后,可以通过定义`.proto`文件来自动生成Java类,从而简化数据序列化和反序列化的操作,提高通信效率。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有