自动驾驶系统的软件方案包含两部分:自动驾驶算法,和相应的软件平台。
自动驾驶算法通常更受欢迎,一般来说大家不太讨论软件平台。这里我们把市面上常见的软件平台的公开信息收集一下,总结一下常见的自动驾驶软件平台都有什么特点。
首先定义一下这里要讨论的软件平台的方案。这里讨论的软件平台包含狭义的操作系统Kernel和相应的中间件。
另外基于MCU的环境基本上就是autosar cp,是事实上的标准,所以不讨论了,下面讨论到autosar,都是说的autosar ap.
对autosar平台而言,它包含了OS(可以是linux也可以是QNX等)和一套autosar 服务(即前面说的“中间件”)。对于ROS,它包含了Linux和一套上层的中间件。对于TTTech的motionwise则更加奇怪,它包含一套狭义的操作系统、autosar、还有一层autosar之上的东西,非常神奇。
所以一套软件平台的特性一方面取决于选用的操作系统,另一方面也取决于中间件。两者单独一个,都并不能决定整套软件平台的特性。
在操作系统层面,常见的有Linux/QNX等选择。其中linux开源免费,有最多的支持,大家最为熟悉,开发资源最为丰富,不过一般比较少用于安全相关的场景。QNX封闭,掌握的人比较少,理论上asil-d。
另外还有PikeOS/seL4等小众的选择(两者同宗同源),不讨论了。
操作系统kernel这一层面,因为选择少,信息基本都公开,都已经被充分讨论了,所以他们的特性大家大致上都清楚,所以这里也就没必要展开说了。
参考apollo的方案,开发软件平台部分,可以分为RTOS / Cyber RT /(地图引擎、定位……),最下面的RTOS部分上面我们已经提过了,就是狭义的操作系统内核,这里不讨论了。最上层面这一层(地图引擎、定位……), 是一些跟应用有关的东西,比如高精定位,这个功能可能不同应用都要用,所以apollo平台就帮做了一个平台化的统一实现,保证了质量,简化了开发。这一层,套用现在汽车行业的时髦话来说,就是SOA服务层。这一层本质上是一些预置的应用,从我的角度来说,其实不算我理解的“软件平台”的概念。
所以这里讨论的重点,就是中间的apollo cyber rt这一层,以及其他平台上类似的层。估计每个公司其实都有一层这样的架构,但是如果不是开放平台的话,基本都是私有机密,所以我们只能找几个开放的平台来对比,以及一些不开放,但是商业化出售的平台,他们多少得有一些PR材料,能看出一点点东西。
根据平台开放程度以及网上是否能找到资料,选定了下面几种平台来分析:
https://apollo.auto/Apollo-Homepage-document/Apollo_Doc_CN_6_0/%E4%B8%8A%E6%9C%BA%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/%E5%AE%9E%E6%97%B6%E9%80%9A%E4%BF%A1%E6%A1%86%E6%9E%B6CyberRT%E7%9A%84%E4%BD%BF%E7%94%A8/CyberRT%E4%BB%8B%E7%BB%8D
参考官方网站上的介绍,cyber rt主要有以下特点:
在自动驾驶系统中,模块(如感知、定位、控制系统等)在 Cyber RT 下以 Component 的形式存在。不同 Component 之间通过 Channel 进行通信。Component 概念不仅解耦了模块,还为将模块拆分为多个子模块提供了灵活性。
Channel 用于管理 Cyber RT 中的数据通信。用户可以发布/订阅同一个 Channel,实现 P2P 通信。
Task 是 Cyber RT 中异步计算任务的抽象描述。
Node 是 Cyber RT 的基本组成部分。每个模块都包含一个 Node 并通过 Node 进行通信。通过在节点中定义 Reader/Writer 或 Service/Client,模块可以具有不同类型的通信形式。
Reader/Writer 通常在 Node 内创建,作为 Cyber RT 中的主要消息传输接口。
除 Reader/Writer 外,Cyber RT 还提供了用于模块通信的 Service/Client 模式。它支持节点之间的双向通信。当对服务发出请求时,客户端节点将收到响应。
参数服务在 Cyber RT 中提供了全局参数访问接口。它是基于 Service/Client 模式构建的。
作为一个去中心化的框架,Cyber RT 没有用于服务注册的主/中心节点。所有节点都被平等对待,可以通过“服务发现”找到其他服务节点。使用 UDP 用来服务发现。
参考协程(Coroutine)的概念,Cyber RT 实现了 Coroutine 来优化线程使用和系统资源分配。
为了更好地支持自动驾驶场景,Cyber RT 提供了多种资源调度算法供开发者选择。
Message 是 Cyber RT 中用于模块之间数据传输的数据单元。
Dag 文件是模块拓扑关系的配置文件。您可以在 dag 文件中定义使用的 Component 和上游/下游通道。
Launch 文件提供了一种启动模块的简单方法。通过在 launch 文件中定义一个或多个 dag 文件,可以同时启动多个模块。
Record 文件用于记录从 Cyber RT 中的 Channel 发送/接收的消息。回放 Record 文件可以帮助重现 Cyber RT 之前操作的行为。”
架构概念:cyber rt是怎么描述整个系统的,可以看到cyber rt用 compoenent 、channel、task、node,DAG, Launch文件这几种概念来描述这个系统
通信:可以看到cyber rt能支持reader/writer, service/client,parameter,message,服务发现这些通信概念 - >和DDS / SOME/IP非常像,感觉像是某种魔改DDS。
调度:可以看到cyber rt有一个scheduler,还支持协程。可以大胆推测cyber rt支持协程级别的任务调度。
ROS2没有一个特别完善的页面说现在支持的功能,可以从下面几个地方总结出来
ROS2能看到的细节比CyberRT多很多。总的来说,给我的感觉主要是围绕这两个topic:通信和调度
Autosar ap给我的感觉, 一个是通信管理Communication Management,其他的部分我都可以归结于“辅助”,比如Persistency,PHM等,这些确实都是一个平台需要的部分,但是你说它多关键,多重要吧,也不觉得。所以autosar ap总结下来, 就是通信管理+其他辅助组件。事实上,很多公司买autosar ap,他们经常就买一个通信管理communication management,其他的可能就自己开发了。
Nvidia DriveOS & TTTech Motion wise
参考https://mp.weixin.qq.com/s/Pfm0NBPPQ0UmIpFN6kJtZQ
Nvidia DriveOS不是完全开放的,需要有合作关系,但是从上面的佐思的公众号文章可以看到(别的地方看不到这个信息),DriveOS集成了TTTech的Motionwise
可以看到DriveOS也通过Motionwise提供了通信、调度等的功能。然后我们去TTTech的官网看一看
似乎TTTech的产品特点就是任务的调度什么的,都是实时的、确定的。毕竟人家公司的名字就叫time triggered technology
这些方案比较下来,我的一个感觉是,一个自动驾驶软件平台主要需要实现如下内容:
通信的部分, 通信中间件概念这两三年是汽车行业的当红炸子鸡概念,第一次在全车架构层面成为技术基石,SOME/IP技术也迅速地从无人知晓到小甜甜变牛夫人,如今嫌弃SOME/IP独宠DDS成为新的政治正确。通信中间件技术已经得到非常充分的讨论,这里就不再讨论了。只能说如今DDS风头正盛,各家的通信中间件就算不是DDS,也是类似DDS,或者是DDS魔改。
本来,狭义的操作系统,他的核心工作就是任务调度,根据一系列算法来切换不同任务对CPU的占用。
那这种情况下,为什么需要在用户空间重新实现一遍任务调度呢?核心的需求的为了集成。设想假设整个自动驾驶算法都由一个大神在一个进程内写完,他完全熟悉掌握多线程,完全熟悉懂得怎么调配CPU,那他完全可以在这个进程内写一个私有化的CPU资源调配机制,也完全不需要将调度信息暴露出来给集成团队,因为他自己就是集成团队。
但现实生活不是这样的,现实生活中,自动驾驶算法的是由不同的工程师,不同的团队,独立开发出来的。不同的模块一定有上下游逻辑关系,一定有时序关系。所以两个模块之间一定要去协商这样的关系。如果只有两个模块,那也不需要一个平台化的方案来控制这些上下游逻辑和时序关系,两个模块的开发团队完全可以私下去协商一套机制。但是自动驾驶系统有非常多的不同节点,所以不可能都是各个节点的团队独立地去弄私有的逻辑时序关系,因此需要一套平台化的调度解决方案。
其次,即使不考虑平台化地控制逻辑时序关系,还会存在别的问题。以linux为例,Linux其实提供了不错的实时性。但是如果没有一个平台化的调度方案,每个应用都说为了提高我自己的实时性,我都设成sched_fifo + prio99,那最后整个系统的表现仍是混乱的。要充分地利用linux的实时性,不只是说要提高优先级,而是要有一些中心化的方案来统筹,优化这些问题,才能取得整体的好效果。因此,需要一套平台化的调度解决方案。
最后,即使各节点,都按照系统设计好的方案,合理地调用系统的资源,各个模块的私有方案都协调得很好(不存在的,没有这种事情),还有一个驱动因素可能使得我们需要一套用户空间的,中央化的调度方案,就是辅助分析。因为如果没有一个用户空间的中央化的调度方案,我们要看任务调度的情况,就需要从内核打log出来,比较麻烦。用户空间的调度器就可以比较方便地解决这个问题。
综上,自动驾驶平台需要一个平台化的用户空间的任务调度机制,cyberRT,ROS2, Nvidia/TTTech已经做出了表率。
所以接下来的问题是,用户空间的任务调度器要实现什么功能(实现原理就不讨论了)。内核空间的调度器是由社区(Linux)或者开发公司(QNX)自己定义的。用户空间的调度器提供的功能就完全由各个软件平台的开发方来实现了。下面分别介绍一下。
Cyber RT和ROS2开始在用户空间做任务调度的缘由都是吐槽ROS1没有类似机制,没有实时性,于是百度切换成了自己的方案CyberRT,ROS社区则开始了ROS2,不过做法比较不一样。
CyberRT官网有描述它的思路,一个是为了解决任务之间的执行顺序,调度器的配置文件里会说明一个执行链上各任务的逻辑先后关系,调度器会保证按顺序执行。另一个是为了简化多核并行处理的编程难度,开发者只关心各个任务的业务逻辑,然后在配置表里写明白这几个任务是要并行处理的,调度器就知道主动地把这几个任务分配到各个不同的核上去执行。具体可以参见CyberRT官网和github
ROS2则做的事情好像就有点鸡肋。它只是根据报文到达的时间来决定某个任务是否ready,然后顺序执行这些ready的任务。除了能防止任务的互相抢占从而避免不必要的开销外,看不出来有什么用。具体可以参见知乎这一篇
https://zhuanlan.zhihu.com/p/404067881
Nvidia/TTTech做的事情好像就比较简单,把任务按照时间计划排布,从时间上进行隔离。
综上通过对市面上能看到的软件平台的分析,可以知道一个自动驾驶软件平台最核心的事情有两件,一件是通信中间件,一件是任务调度。通信中间件方面,DDS有一统天下的趋势。不过任务调度方面,则各家有各家的想法,没有统一的方案。