我们花了九个月,让一辆遥控车学会自动驾驶…

· 2026-09-08 13:32 · 6 阅读

原创 王方远 2026-09-08 13:32 上海

让一辆遥控车学会自动驾驶,需要分几步?

点击蓝字

关注我们

🏁 本文无任何AI生成文本内容

00

前言

大家好,我们是来自复旦大学软件工程实验室智能汽车与工业软件组的CodeWisdom智能汽车战队

这篇推文原本的目的是以点带面地宣传我们组在长达九个月的时间里做出的一个工作成果,但在看了茫茫多的充斥着AI文字的推文和广告以后,我转而希望以人的文笔将整个工作的过程与心得完整地记录一下。我想这在AI生成的故事当道的年代,是一种对工作、读者的珍惜与尊重。

复旦大学软件工程实验室 

CodeWisdom 智能汽车战队

01

天门山的回忆

在2025年的十月份,我们前往湖南省张家界市天门山景区的“天门山99道弯”参与了HitchOpen世界AI竞速锦标赛,用一辆真车大小的电动线控底盘在11公里的蜿蜒山路上竞速行驶。我们战队在仿真复赛取得了第一名的成绩,在实车决赛中取得了第五名的成绩。

那些披着天门山巅薄雾或星光的日夜,让团队里的同学们第一次认识到了代码世界和物理世界之间的分歧与差异。我们作为软件工程实验室的同学,在软件和Coding方面的技术有着良好的基础,然而当工作的任务从我们手中的笔记本电脑转移到真实的物理设备上时,我们所面临的问题接踵而至。我们遇到的问题包括但不限于:传感器设备在雨雾条件下的电气问题,线缆物理损坏,GNSS信号漂移,RTK丢失,激光雷达NDT偶现失效,底盘电气问题等等。

因此即便我们在仿真赛事中的LGSVL模拟赛道上游刃有余,在良好的校园路况下反复成功测试,当面对天门山上真实的极限环境时,依然是处处踩坑、处处碰壁。相比其他高校来自汽车学院的同学,我们的“物理”经验显然不足,像《铁甲小宝》里的没有变身的卡布达,拥有很强的软件头脑,却忽视了重要的物理行动能力。因此,在比赛的过程中我们也出现了“雨中推车”这一类名场面,最终也没有拿到我们理想中的比赛结果,这对我们而言不免有些遗憾。

追赶天门山的云——复旦大学CodeWisdom 战队世界 AI 竞速锦标赛纪实

02

灵感:“实车经验”从何而来

但是这次赛事也并非没有收获,同学们在提升了团队凝聚力的同时也意识到了我们“实车经验不足”的问题。我们开始思考:有什么办法可以让我们获得更多的“实车”经验?我们不像其它高校来自汽车学院的战队那样,立即能够有独立的车库和赛道,有专业的台架和汽修工具。在这种条件下,我们应该选择一个什么样的真实物理平台来开展软件层的研究?此时我们的师兄想到了儿时的伙伴——遥控车

他进一步地说道:“遥控车也分为很多种,里面就有和真车非常接近的等比缩放型号,我们可以定制一辆真车等比缩放的遥控车(专业名词叫RC车),然后将它手搓成自动驾驶。”这个想法瞬间激发了团队成员们的兴趣,每个人都回忆起自己的童年,自己做一辆自动驾驶遥控车的尝试更是畅想与专业的灵感碰撞。

想法确定,实践开始:团队成员聚在一起选择了RC车的型号,在实验室老师们的支持下我们火速下单。没过多久,我们就收到了一辆全新的越野款RC车整车套组,包括底盘、轮组、车架、外壳。于是,同学们立刻开始分工考虑智驾的修改方案。

要让一辆原来只能被遥控的RC车能够“自己上路”,其实并不简单。和真车一样,RC车虽小,车辆的主要功能部件一个不少,想要完成“自动驾驶”这个行为,不管是传统的规则化方法还是端到端的架构,都至少需要经历“感知输入-内部逻辑-控制输出”这个固定的过程。现在的RC车正是要解决这三方面的问题,才能够算基本获得了自动驾驶的能力。感知方面,我们需要在外部安装所有我们需要的传感器;内部逻辑方面,我们需要给车安装主控计算设备;控制方面,我们需要思考车辆的控制方式以及信号的处理与传递。[1]此外,RC车本身要能够给所有的车载设备供电,以及为了实验操作的安全和便捷,我们还需要手动控制接管的功能权限,因此可编程遥控器也是一个不可或缺的设备。

03

选择什么样的自动驾驶方案

在真正开始工作之前,作为软件工程实验室的同学,我们习惯性地遵循软件工程的基本原则,做好高层的需求分析与设计方案。选择什么样的自动驾驶方案是我们最先要考虑的问题,为此我们需要充分考虑团队的需求、RC车自身的特性以及人员的分配。我们的需求是“在实践中学习近似真车的自动驾驶经验,开发出可以自动驾驶的RC遥控车”,同时RC车本身体量较小,承重有限,供电压力大,可改造灵活性较低,而我们团队彼时人数不多。

因此,我们制定了敏捷的开发计划,制定了“感知-规则化、模块化系统-控制闭环”的自驾策略。这种策略有些类似于我们曾经有过相关开发经验的、市面上可以见到的阿克曼底盘机器人上的软件,但区别在于机器人从出厂的时候就已经制定了各式各样的任务功能,而我们要给RC车赋予的是自动驾驶的“机魂”。同时,Autoware Universe作为规则化智驾的权威开源仓库也是我们策略的重要参考。[2]但是它过于庞杂,并不适合直接搬上我们车辆的计算设备,功能上也只适用于真实城市道路,并不适配RC车可能存在的室内行驶场景和实验环境。综合上述两点,我们选择使用ROS2作为通信中间件,并编写一套轻量级的,自定义的,模块化的RC车自动驾驶软件,涵盖感知、定位、规划、控制等基本模块。

根据初步想到的这几个要求,团队成员立即完成了分工,一部分同学关注传感器和计算设备的选型BOM、安装,设计自动驾驶软件架构,另一部分同学则考虑整车的电气架构和驱动方法,解决供电、控制、遥控器编程问题。

04

RC车如何感知世界

这部分讨论的是传感器的选型问题,选什么传感器主要取决于想用什么样的思路和方法。我们的策略是不考虑太多,因为传感器的使用在模块化的架构下可以被自由地选择。因此我们选取了Lidar + 深度相机 + 6axis IMU + 毫米波Radar + GNSS RTK套件 + 自制霍尔轮速计,配合Jetson AGX Orin主控的大满贯组合。除了不可或缺的工控、Lidar和深度相机以外,其余传感器的重量都相对车身很轻,因此没有载荷的相关风险。

上装传感器之后,自动驾驶RC车正式亮相,进入下一步开发阶段。

05

RC车如何控制自己

在下层的输出端,需要考虑的则是自动驾驶的控制指令如何被传递到车体并表现在物理的动作上。RC车在原本的遥控控制下,控制路径是“无线控制器-接收机-ESC(电机)/舵机”这个闭环,ESC和舵机都根据PWM信号控制驱动自身。[1]根据以往的机器人开发经验,我们选择在主控和电机之间增加一块STM32控制板,它接受主控自动驾驶系统发送的UART串口控制数据,进行解析,生成对应的PWM信号输出给ESC和舵机,从而实现脱离遥控的“自动驾驶遥控车”。

06

调试时遇到的各种问题

在上述方案的配合之下,整体的RC车自动驾驶软件架构从上到下就非常明确了。但能够想到的是,实际的开发过程一定不会和理想情况下一样顺利。

比如有一次的开发测试过程中,我们从高边4S给降压板供电,但是没注意它的负极其实是串接点。我们接上接收机和STM32的共地线之后,低边的4S就直接短路了。一上电就瞬间出现了大电流,导致信号线、接插件和STM32地线都一起受损。排查后才发现问题出在弱电系统的地电位选错了。

又例如一次,我们将直流电源通过Type C线直接接到NVIDIA AGX的计算设备上,误把Type C接口当做普通直流电源输入,导致了供电异常,最终烧坏了计算板。由此我们也吸取了教训,接口的供电方式和设备的预期需要匹配,而供电也分为各种各样的协议,直接接入显然会存在较大的硬件风险。

还有时候,GNSS与NDT在软件层的定位结果匹配失准,导致系统定位出现明显跳变偏差,进一步影响了后续的路径规划与车辆控制。两套系统在坐标系、时间同步或匹配条件上都需要保持一致。

又比如说,轻量的车身搭载的电池往往只能支撑两个小时的室外测试时间,我们不得不让所有的备用电池们轮流充电,轮流上阵,在每一个披星戴月的夜晚。

这些故事都只是我们开发时遇到的种种问题的冰山一角,让我们平时只运行在笔记本上的代码,接触现实世界,难度并不小。我们要跨越的,便是这条二进制和三维空间之间的鸿沟。

07

成果展示

令人欣喜的是,在经历了9个月的从0到1、从无到有的开发之后,我们终于拥有了一辆集感知、建图、定位、规划、导航、平滑控制功能于一体的、真正意义上的自动驾驶RC遥控车。它走在路上之时,往往会吸引校园内外路人的目光,但是却很少有人知道,就算把这些目光都加在一起,都不及我们在开发和调试时对它的注视来得长久和认真。

08

一些经典的提问

在开发的过程中,我们也被问到过、考虑过一些经典的问题:

首先是我们的自动驾驶为什么不做一个端到端的架构?我们不得不承认端到端的方法确实有优势,可以直接从传感器的输入得到车辆的控制指令,省去了中间模块化、规则化的过程,系统会比较简洁。[3]但是对于我们目前的需求和平台来说,数据量和场景覆盖都难以保证,问题定位也会比较困难。我们的目的是为了熟悉真车的平台和物理世界的开发规则,所以对于这辆RC车,我们最终还是采用了模块化规则化的方案。因为模块化以后,感知、定位、规划、控制,各自负责明确的任务,出现问题的时候比较容易定位、容易分工,也方便后续替换和迭代。[2]所以现阶段更适合作为我们的基础架构。后续我们也许会考虑部署有关的端到端模型,做一些更大胆的尝试。

而后是关于高精地图的问题现在的自动驾驶技术已经可以在一定程度上做到脱离高精地图运行[4],但我们目前还是希望保留建图。一方面,由点云SLAM生成的地图可以作为整个系统统一的空间基准,把GNSS、NDT、IMU等定位信息都放到同一个坐标系下。[5]另一方面,地图能够提供道路、可行驶区域等先验信息,帮助定位和路径规划。对于我们这个实验平台来说,建图的成本也比较可控,同时可以最大程度地发挥LiDAR的作用,让整个系统的状态更加稳定、可验证。同时我们也规划了脱离建图的视觉方案,毕竟高精地图虽然能够减少计算,让定位更准确,但难以处理经常变化的外部场景。

最后是关于具身智能的热点问题。从具身智能的角度来看,我觉得自动驾驶RC车是具身智能系统的一个实例,具有感知、决策、行动、环境反馈的完整闭环,解决的是自动驾驶的问题。[6]RC车可以作为一个低成本的具身平台,在这个平台上验证感知、决策和控制与真实物理环境之间的闭环关系。

09

开发中Agent的使用经验

也许有人会问:“在现在这个时代,AI Agent的能力已经超乎了很多人的想象,新名词同样也层出不穷,这样一个自动驾驶遥控车的工作,让Agent来干岂不是非常容易?” 对此我要给出我的否定态度,Agent的能力与潜力毋庸置疑,对于经常从事开发工作的我们而言,这种能力的发展显然也对我们的态度和习惯造成了激烈的冲击。对于接受AI的态度或激进或保守的同学来说,使用AI Coding都成为了不可或缺的一种技能。夸张一些来说,有的同学甚至于一行代码不写,从设计到开发、调试到测试的全过程都使用Coding Agent完成,配合各类Skills、Harness以及Workflow,代码的数量呈指数级膨胀。

尽管Coding Agent配合参与了我们各个模块的开发工作,我们依然从中认识到了一个事实:对于一个复杂的软件系统,特别是和物理世界交互的系统来说,Agent无法一次性解决所有事。如果从一开始忽视系统的复杂性,忽视明确的需求,缺少人为干预的设计和反馈,开发者非常容易陷入Agent设置的token漩涡,容易被AI反向误导甚至欺骗。这种现象的原因一方面来自于大模型本身的Laziness特性,另一方面来源于软件工程的基本原理——系统的复杂性在设计之初就应该被考虑。我们曾尝试将整个上层智驾模块化仓库丢给各种高级的国内外Coding Agents,也常常使用Grill-me等热门的Skills,使用公认合理的上下文管理和subagent配合,引入外部模型Review,让Agent读取真实传感器feedback做回环测试。结果证明,如果没有结合我们自己的思考,Coding Agent让车跑偏,出现各种未定义行为的概率很高,同时代码将变成一个完全无法接手的黑盒。此时,项目的所有者也不再是作为开发者的我们自身,因为所有的代码已经膨胀成我们不认识的样子,它已经被AI“模糊”了。

因此,从一开始就从软件工程的视角将Agent的工作区域限制在一个范围内,才是一种正确的使用方式我们人为根据ROS2 RQT的架构图去详细设计Workflow,每个模块内部的Agent都需要有明确的开发-测试-Review行为定义,模块之间的通信耦合也需要具体地设计供Agent阅读的XML/MD文档等等。即便如此,最终呈现的冒烟测试也不能保证百分之百的成功率,我们依然可以发现RC车出现的问题,能够排查到代码和参数的缺陷,依然需要经历若干轮的重复。

实际上这样的开发过程从结果上和所谓的“古法编程”没有本质区别,仍然是一个不断debug的过程。但是这个过程中“人的参与”已经不同了。即便如此,我们依然需要遵循软件工程的一些原则性的方法,概括来说就是“把控系统的复杂性,知道Agent在做什么”,否则极其容易迷失在庞大的代码仓库里。因此所谓的“有了Agent就能实现无门槛Coding,软件工程不再重要,编程工作将会变得非常简单”这种观点我们并不认可,这种观点所推崇的方法也许可以做出一些精巧的demo,但在我们的故事里是完全行不通的,与物理世界的交互并非理想中那么简单。

10

关于Sim-to-Real的思考

Sim-to-Real在机器人与具身智能、自动驾驶、World Model研究方向上一直是一个被广泛讨论的重要问题,而这次对于RC车的开发工作也让我们对Sim-to-Real问题有了自己的一些思考。用直白的话说,这个问题可以理解成“仿真能降低实验成本,但仿真器大概永远不可能和现实一样‘真’,那么如何让对象在仿真中的表现尽量接近现实”。[7]在我们的工作过程中,我们选取了IPG旗下的专业汽车仿真器Carmaker来辅助RC车自动驾驶软件的开发。作为仿真器,Carmaker已经足够专业,我们在其中一比一地设置了RC车的URDF,还原传感器数据状态,模拟道路信息,几乎做到了某种程度的车辆“数字孪生”,因此仿真对我们的自动驾驶算法模块开发和测试提供了非常大的帮助。但是这并不代表现实中的表现也能和仿真中一样一切正常,仿真目前还无法简单快速地模拟传感器的异常抖动,无法感受真车运行时各个设备耦合的压力状态。因此在实车测试时,那些隐藏的,长尾的问题才会真正地暴露出来。

从这个层面我们可以回答这个Sim-to-Real的问题:在仿真器还不是无所不能的今天,它可以是无数次低成本的赛道试验场,但是真正可靠的自动驾驶,还得是真车在物理世界中“撞”出来的。就像我们去年比赛时那样,仿真器中的行驶依旧是“纸上得来终觉浅”,而“绝知此事”,要把四个轮胎真正放到地面上。

11

总结

在写下这篇文章的时间节点回望,我们发现团队正在悄然成长改变。去年的我们经验不足,试图将所有的工作交给笔记本里的代码与仿真器,却忽视了物理世界的真实特性。而现在,我们有熟悉整车电气架构的同学、有熟悉嵌入式与信号控制的同学、有熟悉自动驾驶仿真与实践的同学,老师和同学们能在一起交流、学习,这是一种全栈式的进步。同时,我们也成功吸引并招募了若干名刚入学的研究生、本科新生加入我们的战队,大家获得了更多实践和动手的机会,这些收获让我们感到发自内心的喜悦。

这不禁让人联想到每个人的成长轨迹,不管是同学,老师,还是行走在不同人生道路上的人们。如果将每个人比作一辆自动驾驶的车,那么每个人的传感器在身体成长到一定阶段就已经安装配置完毕,而各自内部的算法却始终还在迭代之中。我们不清楚什么时候才能弄清自己的定位,不清楚如何规划导航才能到一个更确定的美好未来。每辆车有自己的起步节奏,每个人的花期也不一样,就像昨天你对一个领域还处于懵懂的状态,但今天你可能就一只脚踏入了它的大门。在这个快速的时代,从你准备好的那一刻起,你内心深处的声音总是会对自己说:你已经是一辆成熟的车了,你该学会自己上路跑一跑了。这一路上有路面上扬起的沙石,有乍惊的雷霆和雨雾,有自身机械和电气的故障,有来自各个车道的负面情绪与善意指引,有不能停下的理由,也有随遇而安的休憩。这一切不可避免地发生,不管你有没有到达属于你的目的地,而舷窗外的风景,无一例外地,写在了属于你的行车记录仪里。

以上是我们团队的工作纪实,所有观点都是主观而浅显的,代表团队的一些思考。

谨铭记我们车辙驶过的那些夜色和晨风,感谢阅读。

12

团队介绍

复旦大学软件工程实验室 

CodeWisdom 智能汽车战队

队员:

陈其才 博士生

王方远 博士生

李明辉 硕士生
周敬淞 硕士生
于雪昂 博士生

指导教师:

李弋

13

参考文献

[1] O’Kelly, M., et al. (2019). F1/10: An Open-Source Autonomous Cyber-Physical Platform. arXiv:1901.08567.(缩比自动驾驶车的平台架构、传感器、ROS软件栈,以及ESC、PWM和转向舵机。)

[2] Autoware Foundation. Architecture overview. Autoware官方文档。(模块化架构、模块职责、协作开发与组件替换。)

[3] Chen, L., Wu, P., Chitta, K., Jaeger, B., Geiger, A., & Li, H. (2024). End-to-end Autonomous Driving: Challenges and Frontiers. IEEE Transactions on Pattern Analysis and Machine Intelligence, 46(12), 10164–10183.(端到端与模块化方案的比较,以及数据、可解释性和鲁棒性等挑战。)

[4] Chitta, K., et al. (2022). TransFuser: Imitation with Transformer-Based Sensor Fusion for Autonomous Driving. arXiv:2205.15997.(在CARLA中验证运行时无需预先提供高精地图的驾驶方案,融合相机和LiDAR输入;实验仍提供稀疏导航目标点。)

[5] Autoware Foundation. Localization Component Design. Autoware官方文档。(点云地图定位、多传感器融合与统一地图坐标系。)

[6] NVIDIA. What Is Physical AI?. NVIDIA官方技术说明。(从物理AI的视角讨论机器人、自动驾驶车辆的感知、理解、推理与物理行动。)

[7] Höfer, S., et al. (2020). Perspectives on Sim2Real Transfer for Robotics: A Summary of the R 2020 Workshop. arXiv:2012.03806.(机器人研究者对仿真的价值、现实差距与Sim-to-Real局限的讨论。)

跳转微信打开