攻城狮说 #02期

工程师 | 王轩


本期划重点

»  基础架构团队做什么?

»  车载系统

»  仿真平台

»  数据基础架构

»  其他基础架构服务


1.基础架构团队做什么?

首先给大家介绍一下小马智行(Pony.ai)的基础架构团队做什么。

互联网公司的基础架构往往会在业务规模扩展时通常会在一些方面遇到技术挑战,比如存储系统、计算平台还有 Web 服务治理。对于 Pony.ai 而言,作为一家专注于自动驾驶技术研发的公司,我们同样也会在这些方面遇到不小的技术挑战。

除了上述提到的互联网公司会遇到的一些通用的技术挑战之外,还有很多与自动驾驶本身相关的技术挑战。例如自动驾驶车上的车载系统、支持自动驾驶测试的仿真平台等等。对于 Pony.ai 来说,我们的目标是运行具有一定规模的自动驾驶车队。这也就意味着需要有一套完善的配套车队运营基础架构。我们的自动驾驶车辆需要和乘客进行交互,意味着需要一个人机交互的接口。提到的这些都是 Pony.ai 的基础架构团队正在做的事情。

自动驾驶车队的建立,使得自动驾驶的方方面面都存在不小的技术挑战,对基础架构的挑战同样是巨大的。一支成熟的大规模自动驾驶车队要求整个自动驾驶的基础架构有足够的可扩展性。

这里的可扩展性体现在,随着车辆数量的增加,运营区域会扩大、数据量会大量增加、工程师数量会增加以及系统各个模块数量也在增加、内部代码量的增长……所有这些都会给基础架构的演进中带来非常多的技术问题。接下来会详细介绍在我们各方面的基础架构演进过程中遇到的实践和挑战。


2.车载系统

车载系统的基础认识

首先介绍的是自动驾驶车载系统。一般来说,自动驾驶系统上有很多传感器代替人类收集信息,车载系统需要处理这些数据信息,最终转化为对车辆的控制决策,如踩刹车、转多少方向盘,做出决策后传递给车辆。

简单介绍一下我们的自动驾驶系统的构成。上图是一个自动驾驶车载系统示意图,每一个方块对应系统中的一个模块。

首先,车载系统通过一些传感器去感知真实世界,有激光雷达、摄像头等驱动收集真实世界的信息,这些信息会传递给 Perception(感知)模块,该模块会实时感知车辆行驶中周围的环境,比如车辆周围有哪些车辆以什么样的状态在行驶,车辆周围有哪些行人等。

Perception 模块收集到这些信息后,会将其传递给 Prediction(预测) 模块。因为我们不能只依据当前车辆周围环境信息做决策,需要对车辆周围的任何物体或者人、障碍物接下来的行为预计,比如前面路口的车是转弯还是直行对接下来车辆的决策也很重要。

当 Prediction 模块生成这些信息后会传递给 Planner (规划)模块,这个模块会规划接下来车辆一段时间的行驶轨迹、做出什么样的决策。比如前面有行人,需要踩刹车等待行人先过去,前面车行驶比较慢可能需要变道超车。

Planner 模块规划好轨迹后,传递给 Control(控制) 模块,计算出车辆需要进行操作的参数指标,如打多少方向盘,踩多少刹车等,最后传递给自动驾驶车辆。在模块运行中,可能需要其他一些模块,例如高精度地图、实时定位;还有 Router(寻路) 模块,当指定起点终点时,它需要计算出一条合理的路线。

车载系统的功能

自动驾驶系统是协调上面提到的各个模块运行的系统。它需要做到以下几件事情。

首先,车载系统需要去调度各个模块的运行,实现模块间的消息通信(一个模块的输入可能是另一个模块的输出)。

不仅如此,自动驾驶汽车上计算资源十分多样,不同的模块可能也需要不同的计算资源,一些感知的算法可能需要很大的 GPU,有些模块可能是 CPU 计算多一些,因此需要车载系统合理分配不同模块的计算资源。

日志记录也是车载系统须具备的重要功能,在自动驾驶的过程中,系统记录车辆运行过程。出现非预计的情况时,我们可以通过日志信息进行 debug(除错),以帮助系统持续演进。

此外,大家都可以理解,自动驾驶安全要求很高,因此系统应具备非常完善的监控和报警系统,当系统出现一点点问题都需要及时报警,使得安全员可以进行正确的反应来避免潜在的危险。

面对的挑战

在实现对车载系统的众多要求中,也须面对和处理各类挑战。

首先是可靠性。代码逻辑设计错误会出现各种问题,在车载系统上更可能引起交通事故和严重后果,不稳定的系统也会严重影响车队运营效率。因此,车载系统对代码可靠性要求极高。可靠性同样还体现我们在系统监控和异常报警的方面。

第二个系统设计的要求就是高性能。各模块间消息通信的数据量很大。最新一代车载系统中包含6个1080P摄像头,当以每秒10-20帧的帧率获取数据,每秒会产生的数据量是非常大的。要使这么大的数据量高效地在各个模块之间传输,对于设计上的挑战也是很大的。性能的要求除了吞吐量之外,模块通信延迟也必须很低,想象一下如果识别到车辆前方的行人之后需要一秒才能作出反应,将可能会造成严重的后果。

最后一点是系统需要保持较高的灵活性。计算资源有多种多样,车上的模块对计算资源的利用也不尽相同。这意味着需要车载系统需要灵活地支持各种不同计算资源的接入,以及不同类型模块的接入。

针对这些系统设计上的需求,小马智行早期决定放弃知名的开源系统 ROS(机器人操作系统),自主研发 PonyBrain。做出决策的主要原因有以下这些:首先 ROS 作为开源系统,代码质量可能不受控制,不能很好地保证代码质量;另外一点是 ROS 作为一个通用的机器人操作系统,架构上不太契合一些特殊的自动驾驶系统的需求。基于上面这些因素,我们选择自研 PonyBrain 系统。

实践

对于之前提到的系统设计上的挑战,我们在工程实践上采用了一系列针对性的措施去解决。

首先可靠性挑战方面,只有高质量的代码才有可能让系统足够可靠。为了提高代码质量,我们执行了非常严格的 Code review (代码审查)和 Unit test(单元测试) 的机制来保证代码质量,确保不会有意外状况出现。同时,我们还会使用一些工具来及时发现问题,如静态分析和ASAN,以及监测内存泄露的工具。

车载系统运行时,也会有多重系统可靠性检查。在系统启动前会校验系统启动环境;系统运行时也会有实时监控检查,监控系统运行是否符合预期;系统运行后也会对收集到的所有数据执行数据分析,监测系统运行是否存在潜在问题。

小马智行还设有持续的集成与发布平台来保证每一册代码改动后的系统可靠性,最终发布稳定的Release版本给车队测试。

对于高性能方面,首先,我们不可能设计一个通用的高性能系统,而是依据车载系统的实际需求做出架构设计上的取舍,以达到在需要的地方榨干系统的性能。设计系统的时候,我们会充分考虑模块消息通信中需要支持的一些特殊场景,尽可能避免大数据拷贝影响性能的逻辑。其次,我们也会预计不同模块资源需求合理的分配计算资源,保证不同模块高效运行。最后,我们会对系统定期进行Profile分析,通过数据统计的方式分析系统瓶颈,优化系统性能。

在系统灵活性方面,我们一开始就需要定义好通用的模块接口和通用的消息通信接口,以支持不同类型的模块和不同的消息通信,尽可能去适配更多的模块。


3.仿真平台

日常开发为什么需要仿真?

仿真平台在日常开发的重要性不言而喻。

首先,仿真平台相对于路测开销少,不需要路测和人力的介入来评价系统性能变化;第二点就是低风险,不会对实际中的任何车辆产生影响;第三点提供了基于数据驱动的快速迭代算法的可能性,新算法直接可以在仿真平台上评估。

仿真平台的挑战与实践

下面来谈谈仿真平台的挑战与实践。首先是如何保证仿真结果的足够可靠。服务器的环境不可能和车辆的环境完全一致,机器配置和服务器配置可能存在区别,如何在仿真平台上模拟车载计算平台的环境并不容易。仿真平台里有缺乏真车的控制反馈的机制,因此需要对真实车辆的动力学模型进行仿真建模来支持仿真平台。

第二个是仿真数据的选择和管理。我们需要对路测数据进行管理,提取数据类型,仿真流水线可依据不同需求运行不同的feature和case。

第三点就是仿真的系统性能很重要,快速得到仿真结果可以帮助工程师更快地验证新的算法。因此自动驾驶需要一个分布式高性能的仿真平台,能够快速的将仿真结果反馈出来供工程师去决策。


4.数据基础架构

数据是自动驾驶技术的核心驱动力,在做仿真、模型验证,解决路测不好的case时,皆依靠数据支持。因此我们需要解决数据的存储和访问、数据处理机制、数据同步机制等问题。

对于数据基础架构而言,面临的核心挑战是数据量的庞大(PB 级)。同时自动驾驶产生的数据的属性不同于互联网数据,自动驾驶有大量客户端产生的数据(互联网是用户累计数据量大,单个用户数据量不大),有大量传感器数据和模块运行日志数据,因此并不能完全照搬互联网公司常用的数据处理框架。

数据存储的挑战

首先,我们的数据存储需要依据特定的数据使用场景设计一些合理的存储格式。这类格式便于车载系统记录,进行大规模数据分析,还能满足某些数据的部分访问和随机访问的需求,例如一个8个小时路测数据,我们可能关心的只是路测过程出现异常的时间段,这就需要数据系统能够方便我们获取感兴趣的数据。不可忽视一点是,文件系统的选择比较有限,我们设计的数据格式还需要便于文件系统存储。

确定了存储格式之后,还需要选择合适的存储系统。这里需要考虑包括冷热数据不同选择方案,存储系统高可用,容易水平扩展,控制成本等等方面。

数据处理的挑战

数据需要处理来帮助收集性能指标,如MPI、模块运行效率、乘客舒适度体验等;更利于挖掘有趣路测场景,如接管、急刹、感知算法识别、不合理的变道策略等用于模型训练和仿真。

在数据处理的架构设计上,我们注重减少从数据采集到数据处理完成的延迟,因为这直接影响了解决路测问题的效率。另外就是依据不同类型数据处理的任务,选择合适的处理系统,如有些数据处理任务是CPU密集型,有些则适合IO密集型,要区分不同需求用不同的机制去完成;与车载系统一样,数据处理系统同样需要有通用的任务定义以支持灵活的添加新任务。

特别说一说数据同步,Pony.ai在三地研发且拥有多个测车地,但这并不意味着需要多个系统。我们使用同一整套的技术解决方案去部署在多个不同的测车地点,这样让系统具有足够的泛化能力而不会过拟合到某一个地点的场景上。这要求我们的数据需要在不同测车地点和研发中心之间按需同步服务,由于数据同步服务也会受到带宽等网络条件的限制,设计起来还是非常有挑战的。


5.其他基础架构服务

车队运营基础平台

自动驾驶车队运行会有很多业务需求,车辆增长快,人员增长也快。为了高效运行这支车队,我们对配套服务的要求很高。我们有一套完整的车队运营基础平台,帮助进行车辆状态管理、路测任务管理,以及车队运行实时监控,帮助实时观测车辆状态。

至于车队运营基础平台面临的挑战,基于web的产品开发和迭代的速度很快,业务逻辑复杂。相关的基础架构需要去承受快速变化的复杂需求以及大量 Web 服务的部署与管理。

为了支持各种各样的计算和服务,我们需要统一的服务调度管理平台,充分利用服务器集群。我们选择了在Kubernetes平台上构建我们的平台。

可视化平台

随着技术团队规模扩大,不同的团队会产生不一样可视化需求,帮助工程师理解自动驾驶车辆系统看到的世界。因此,我们需要维护一个通用的可视化工具,满足不同工程师通用和定制化的可视化需求。我们的渲染场景很复杂,这个可视化平台特别需要注重3D实时渲染性能。可视化平台也需要尽可能支持桌面/移动/Web等多平台,以及人机交互接口(方便乘客使用的用户界面),以满足不同的需求。