在《新程序员004》中,我们邀请到了扎根于互联网 20 载的资深技术人,立足于他
从互联网后端转型做自动驾驶车端基础架构研发的亲身经历,深度分享转型做自动驾驶的软硬件、入门与成长经验,也希望本文能够对更多的同行有所裨益。
作者 | 卡林仙人(笔名)
出品 | 《新程序员》编辑部
作为一个2000年就进入IT行业、从事后端研发超过十年的互联网程序员,我在五年前经过慎重考虑,转向了自动驾驶车端基础架构研发领域,决定在一个全新的行业和一个全新的技术方向重新开始。
当我从每天面对着终端和浏览器,变成与各类嵌入式开发板、各种型号的传感器打交道,经常需要实车上路调试,最终亲眼看到一辆汽车按照代码预期自主行驶的时候,确实能感受到和之前工作完全不同的体验和成就感。
从进入自动驾驶行业至今,已有数款我参与研发配备辅助驾驶系统(ADAS,Advanced Driver Assistance Systems)的量产车型上市,在此,我也希望把这几年来的心得总结出来,给有意参与自动驾驶研发,但是还在观望犹豫的同行们参考,帮助大家更快找到适合自己的定位。
自动驾驶技术入门,必知的分工与岗位职能
车辆的自动驾驶系统运行环境与互联网服务有很大区别,既没有服务器集群那么丰富的系统资源,也没有浏览器和移动端那么多样性的开发工具。
自动驾驶系统需要工作在车辆已有的数据和控制接口之上,先读取车身和传感器的各项输入,经过系统处理之后,再转化为对底盘控制接口输出的纵向(加减速)和横向(转向)控制指令,最后车辆执行这些指令,完成动作。
按照自底向上的顺序,首先将自动驾驶汽车广泛地分为硬件方向和软件方向。
自动驾驶之硬件平台
车辆平台
对于车辆自身的车身、驾舱、底盘的控制器和软件系统,当前汽车行业已经具备非常成熟的ECU(Electronic Control Unit)控制器产业链和汽车开放系统架构(Automotive Open System Architecture,简称AUTOSAR)软件体系。
它们负责处理车辆底层控制逻辑,为上层自动驾驶系统提供数据和控制接口,是自动驾驶系统能够控制车辆的基础。
自动驾驶硬件平台
自动驾驶系统的算力需求远高于汽车行业常用的低功耗芯片,需要专用的高算力低功耗嵌入式计算平台。目前行业普遍使用64位ARM架构芯片(aarch64),自动驾驶还依赖了各种型号的摄像头和各个频段的雷达传感器,都需要专业人员来负责各类硬件和传感器的驱动适配,以及GPU、FPGA、DSP等专用运算加速设备的算子开发,这部分工作都是由嵌入式硬件工程师来负责。
因为行业背景知识差异比较大,互联网背景的程序员通常不会选择参与硬件方向工作,所以我们需要关注的是软件方向的岗位。
自动驾驶之软件平台
车端基础架构
自动驾驶车端基础架构在广义上涵盖了「硬件驱动之上,算法应用之下」的所有部分,车端基础架构贯通硬件层和应用层,发挥着承上启下的作用。
车端基础架构工程师经常需要解决软硬件因素混杂又难于重现的复杂问题,某友商类似岗位的招聘要求就非常直白:“Use your expertise to debug hard-to-reproduce whole-system problems”。比较适合熟悉C++技术栈的互联网后端程序员,根据近几年的招聘经验,我认为通信行业C++工程师也普遍比较适合。
车端基础架构主要包含下面这些方向:
中间件:为上层应用提供通信、任务管理等基础服务,同时保证了不同车型、传感器和操作系统的接口统一。
工具链:与车端中间件及云端数据平台配套的数据采集、回放和调试工具集,开发迭代效率和问题定位效率的倍增器。
操作系统:目前车端自动驾驶域以商业实时操作系统和定制版本Linux为主,预计未来会有专用的自动驾驶操作系统出现。
车端算法和应用
自动驾驶车端算法按照目前的行业共识,一般分为感知、定位、决策、规划、控制等若干方向,比较适合互联网行业算法策略背景的工程师考虑。
通俗地比喻一下,每个算法方向解决的是下面这些问题:
感知:根据各个方向摄像头和各种雷达的输入,确定自己看到的是什么,有多远。
定位:根据卫星定位、惯性导航、高精地图和环境特征,确定自己在哪条道路的哪个车道。
决策和规划:自己应该去哪里,以及怎么安全到达。
控制:在保证乘客体验的前提下控制车辆转向和加减速。
云端服务
除了车端以外,自动驾驶云端业务重要度也非常高,云端系统的完善度与成熟度是直接影响车端系统迭代效率的关键因素。因为不受车端硬件环境的限制,可以直接沿用成熟的互联网技术栈,所以自动驾驶云端是最适合互联网程序员转型自动驾驶的技术方向。云端服务有以下这些业务:
数据平台:自动驾驶开发和运行过程中都会产生非常大量的数据,是保证研发迭代和排查问题的关键因素,与车端工具链共同构成核心基础设施。
虚拟仿真和自动化测试:实车上路测试成本高昂,可以大量并行运行的虚拟仿真场景,能够提升测试效率和降低测试成本。
OTA远程更新:车辆对远程更新软件的安全性和可靠性要求远高于手机,对远程更新服务的健壮性也提出了更高的要求。
远程监控:基于5G基础设施的远程监控和接管是比较新的技术方向,有可能是Robotaxi(自动驾驶出租车)服务落地的关键性因素。
智能驾舱
智能汽车驾舱方向虽然不参与车辆控制,但是承担着用户与自动驾驶系统之间桥梁的职责,直接关系着车辆乘客的全程体验。
目前驾舱普遍使用基于安卓系统的大屏车机和语音控制作为主要人机界面,所以比较适合互联网行业移动端或者前端开发人员考虑。
高精地图
预计在今后相当长的时间内,高精地图都是自动驾驶系统的一个关键依赖,高精地图业务包括数据采集处理、云端服务、车端服务等方面,本身已经涵盖了从车端到云端的各个技术环节,如果具备GIS(Geographic Information System)专业背景,或者互联网地图服务项目经验,就比较适合高精地图方向的岗位。
除了上面提到的这些,自动驾驶对信息安全、配置管理、系统集成、软件测试等研发配套岗位同样有招聘需求,建议有兴趣的同行可以保持关注。
显而易见,自动驾驶系统对代码的稳定性、安全性和性能都有更高的要求。除此之外,还需要适应以下这些差异:
作为互联网程序员,日常工作环境是后端服务器或者客户端浏览器,开发、测试和运行环境都非常成熟、稳定,越来越标准化。作为开发者只需要关注到操作系统接口层面,通常来说不需要也没有必要进一步深入到硬件层面。
当从事自动驾驶系统开发时,软件系统与车辆平台、车端硬件和传感器紧密耦合,所有特性都必须经由软硬件系统的协调一致配合才能正常运行,而且自动驾驶行业正处于剧烈进化的高速成长阶段,车型与传感器型号繁多,技术标准和接口多变,所以需要我们从底向上、从硬件到系统,对各个层面、各个环节的知识都要有一定的了解,最好是能有机会自己亲自参与硬件配置和软件部署调试的全过程,才能加深整体认识,避免盲人摸象。
以我个人的看法,如果具备一定年限的驾龄,会更有助从司机角度理解用户的关注点和诉求。
每个新进入自动驾驶行业的互联网程序员最多关注到的新名词必然是“车规”和“功能安全”。
简要地说,车规是汽车行业多年来积淀的从代码规范到开发过程的一系列行业标准和行业规范的统称,功能安全(Functional Safety)是一个专业术语,特指汽车行业一整套避免伤亡和损失的研发流程方法论。
这其中与自动驾驶系统关系最密切的有国际标准《ISO26262-道路车辆功能安全》、C/C++代码规范MISRA C和MISRA C++(Motor Industry Software Reliability Association)。因为最新一版MISRA C++规范是2008年制定的,无法覆盖C++11以来天翻地覆的语言标准变化,所以也可以选择参考支持更高语言标准的代码规范AUTOSAR C++14。
ISO26262 V研发流程模型
如果遵照功能安全标准和方法论,最终的成果是软件的车辆安全完整性等级(ASIL,Automotive Safety Integrity Level),分为ASIL-A、ASIL-B、ASIL-C、ASIL-D四个级别,安全等级逐级递增,如果通过了ASIL-D,就代表符合了最高级别的功能安全等级,例如目前微内核实时操作系统QNX的功能安全版本QNX OS for Safety的部分组件(系统内核、部分系统服务、C编译器和标准库)就通过了ASIL-D标准认证。
这里从ASIL-D标准里摘取几条要求,我相信业界从业者都能体会到通过ASIL-D认证的复杂度和工作量:
形式化验证
限制使用指针
无隐藏数据流或者控制流
测试的分支覆盖率、函数覆盖率、调用覆盖率都要求100%
软件功能安全是一个专业性比较深的话题,通常自动驾驶团队都会配备专业的功能安全工程师,开发人员需要做的主要是了解标准概要和熟悉配套工具,遵循专业人员的要求和建议。另外因为通过最高级别认证的成本相当高,所以实际操作中一般都会根据项目需求,针对不同模块,选择适用的功能安全级别。
在互联网行业,实时系统一般泛指处理或者响应足够快速的系统,并没有的明确的定义和定量的指标。
在自动驾驶行业,实时性(real-time)是特指系统具备在承诺的时间窗口或者调度周期内,不受任务调度、资源争抢等外部因素干扰,准时完成运算的能力。我个人认为更恰当的描述应该是“确定性”。
举例来说,一个设计指标为20Hz(即每秒20次)输出运算结果的任务模块,如果能精确地做到每两次输出间隔都是50毫秒,那就满足了设计要求的实时性指标。但是如果输出间隔不均匀或者明显抖动,那即使能够实现30Hz甚至更高的输出频率,也是不满足实时性指标的。
要提升软件系统的实时性,首先要使用支持实时调度策略的操作系统,例如黑莓QNX或者风河VxWorks,或者至少是升级了内核实时性补丁的定制版本Linux。其次应用层代码要通过池化策略预分配好各项资源,避免运行时动态资源分配和缓存失效引发的抖动,科学调配每个计算任务的亲和性(affinity)和优先级(priority),降低被操作系统任务调度服务切换的频率。
很多互联网程序员在刚进入自动驾驶行业时,可能都听到过“车规代码不允许在运行时动态申请内存”的传言,其实就是源自实时性要求。所有的new/delete和malloc/free调用,包括C++11之后的创建智能指针对象操作,都会在代码静态扫描时被标记为违反MISRA C/C++代码规范。
除了功能安全和实时性,自动驾驶也正在逐步从航空航天等传统高可靠性软件领域借鉴行业成熟经验。
当前业界已经有了ROS2、Apollo等高质量开源项目,项目文档足够丰富,有基础的同行可以参考学习,了解技术细节:
ROS2:https://docs.ros.org/
Apollo:https://github.com/ApolloAuto/apollo
以下书籍分别从行业背景和技术概述角度介绍了自动驾驶,比较适合初学者阅读:
《无人驾驶》:https://book.douban.com/subject/27058912/
《自动时代:无人驾驶重塑世界》:https://book.douban.com/subject/35101057/
《第一本无人驾驶技术书》:https://book.douban.com/subject/27038410/
《无人驾驶汽车概论》:https://book.douban.com/subject/26629406/
汽车行业已经有百年历史,自动驾驶又是一个全新的方向,所以如果你刚刚进入这个行业,必然会天天听到新名词,天天看到新缩写。
在最开始的几个月,要充分利用互联网丰富的信息资源,高强度补充行业知识。要做到勤搜索,勤提问,勤动手(写代码),自动驾驶又是软件和硬件,代码和体验都深度结合的学科,所以必须还要再加上一条:勤上车。
作为一门刚刚诞生不久的技术,没有人能提前知道自动驾驶应该怎么做,所有人都是在同一个起跑线,从头开始探索的。
记得五年前,我还在犹豫要不要从互联网转型自动驾驶,担心自己能不能在一个新方向从头开始的时候,一位行业前辈曾经热情的召唤:“不要担心自己什么都不会,我们都是从什么都不会开始做自动驾驶的。”
另外,作为一个曾经经历互联网行业多次起伏的过来人,也要提醒大家,虽然当下自动驾驶正火,钱多机会也多,仍然要对周期性波动做好心理准备。我刚刚转型自动驾驶后就遭遇了整整两年的行业低谷,如果你仅仅是为了投资下一个风口,那这两年必然会非常煎熬,甚至悔不当初。但是如果你和我一样,想清楚了自己想要的是什么,那所有的困难就不再是阻碍,而是达成目标之前的考验。
作者介绍:卡林仙人(笔名),2000年至2017年间从事互联网后端技术研发,2017年起从事自动驾驶车端基础架构研发,先后工作于新浪、百度等公司。
—END—
本文为《新程序员004》内容,《新程序员004》即将上市,敬请期待。