自动驾驶这个话题聊了很多年,感知算法也已经卷到了相当成熟的高度。但如果你真正在行业里做过一两个落地项目,大概率会有同样的感受:感知只是第一公里,真正让车“像人一样开车”的,是决策算法。我在这块断断续续摸爬滚打了几年,踩过的坑比写过的代码还多,今天就把我对自动驾驶决策算法的一些思考整理出来,不聊那种飘在空中的概念,全部落到具体的工程问题和取舍上,希望对正在做相关方向的朋友有点帮助。
先说清楚这篇东西适合谁。如果你刚入行,想在决策算法方向建立系统认知,这里面会有完整的技术路线梳理和选型逻辑;如果你已经在做某个模块,比如预测、规划、控制,想理解决策模块怎么跟上下游咬合,我的实操经验和踩坑记录应该能给你一些参考。总之,这篇文章的核心就一句话:自动驾驶决策算法不是某一个模型、某一个公式,它是一整套在不确定性、多目标、实时约束下做选择的工程系统,怎么把这套系统搭出来、调稳、让它真正能跑,才是真正值得思考的事。
1. 自动驾驶决策算法,为什么绕不开这堵墙
1.1 决策算法在自动驾驶链路中的位置
先看整条链路。一套典型的自动驾驶系统大致可以拆成:感知、预测、决策、规划、控制五个环节。感知负责从传感器数据里读出“现在周围有什么”:车道线在哪里、前方有没有车、行人站在什么位置、红绿灯是什么状态。预测负责推断“这些东西接下来会怎么动”:前车是否会减速、行人是继续走还是停下来、旁边车道的车会不会突然并线。决策则负责回答“我下一步应该做什么”:是保持当前车道跟车,还是打灯变道超越慢车,或者在路口让行侧向来车。规划把决策意图转成一条几何上可执行的轨迹,控制再去跟随这条轨迹。
决策在这条链路里的位置相当微妙。它往上游吃进感知和预测的信息,往下游直接指挥规划和控制,但又不直接产生方向盘转角或油门开度——它产出的更多是一层“驾驶意图”和“行为约束”。这层意图选得对不对,决定了整车行为的合理性和安全性。感知错了还可以靠决策兜底,决策错了,后面规划和控制再精准也救不回来。
1.2 决策问题的本质:在不确定性中做选择
决策为什么难?因为它本质上是在高不确定性环境下做序列选择。传感器的测量有噪声,目标的检测可能有漏检和误检,预测模块给出的轨迹带有置信概率,其他交通参与者——尤其是人类驾驶的车辆和行人——其行为是不可穷举的。你再怎么提升感知精度,世界对于车里这台计算平台来说,永远是一个带概率的近似模型。
同时决策还要满足多目标约束。安全是第一优先级的,车不能撞东西;效率也不能不管,不能在空旷道路上龟速蠕行;乘客感受要考虑,频繁急加速急减速会让人晕车;交通规则要遵守,压实线、逆行这些行为必须规避。这些目标之间往往存在冲突:在拥挤的城区道路,想高效就免不了要贴近前车、见缝插针,安全边际就被压缩;想绝对安全,就只能在路口等所有车都走完再启动,效率和体验又会崩盘。
再加上实时性约束,情况就更麻烦了。决策模块通常被要求在100毫秒甚至更短的时间内输出结果,而复杂场景下可选动作空间可能非常大。要在这么多因素之间快速找到一个可落地的选择,本身就是一件非常反直觉的工程难题。这也是为什么纯靠堆规则、堆if-else一定会在某个场景组合面前爆掉,因为决策问题在本质上就不是穷举能够覆盖的。
1.3 一个容易被低估的事实:场景组合爆炸
我接触过不少还在学校、或者刚转行进这个领域的朋友,很多人会把决策算法想得比较“单纯”:不就是一个从输入到动作的映射吗?前车慢了就跟着慢,前车停了就停下来,旁边没车就打灯变道——看起来很符合直觉,但实际跑起来根本不是这么回事。
问题在于真实场景的组合是开放的。同样是“前车慢”,要区分它是在巡航慢速开,还是在减速准备靠边停车,或者正在找路口要转弯;同样是“旁边车道没车”,要区分这是普通的旁边车道,还是公交专用道、应急车道,以及这条车道前方是不是有障碍物。道路结构、交规、其他车辆意图、天气光照、传感器遮挡状态交织在一起,可能组合出数以万计的交通情境。任何一个情境考虑不周,在测试中都是事故隐患。
所以我常说一句话:决策算法的复杂度不在某个单独的场景里,而在场景与场景之间的边界和跳跃上。守住这个认识,再去看各种技术方案,你就能理解为什么业界会演化出那么多种不同的路线。
2. 决策算法的几条技术路线,怎么选
2.1 规则派:有限状态机与决策树
先聊最经典、也最容易被低估的路线——基于规则的方法,典型代表是有限状态机FSM和决策树。
FSM的思路很直观:把车辆驾驶行为抽象为若干个有限状态,比如“巡航”、“跟车”、“变道”、“超车”、“让行”、“停车”、“通过路口”等,然后定义状态之间的转移条件。当感知和预测的数据满足某个转移条件时,状态就发生切换,再根据当前状态去生成具体的驾驶行为约束。
这套方案的优势非常突出:状态和行为一一对应,逻辑清晰,出了问题可以直接定位到是哪个状态、哪个转移条件写错了,调试效率极高。对于一个状态规模控制在几十个以内、场景定义清晰的路段——比如高速公路——FSM完全可以跑得又稳又可靠。很多量产L2级辅助驾驶系统中的决策逻辑,核心骨架依旧是这种结构。
但FSM的天花板也明显。随着功能扩展,状态数量会快速膨胀,状态之间跳转关系呈网状交织,维护成本飙升。更麻烦的是,真实场景中很多决策无法离散成干净的状态,比如“拥堵道路中轻微左侧偏移为后车让出空间”和“变道超越前车”之间,边界是模糊的。你写规则的时候,稍不留意就会出现两个状态都无法覆盖的真空地带。我在早期做的一个模拟项目里就吃过这个亏,死磕了一个“相邻车道车辆同时减速”的边界场景,状态机加了几十条补丁之后依然有漏网之鱼,后来不得不换思路。
2.2 学习派:端到端与模仿学习
既然规则写不完,那能不能让模型自己学?这就是学习派的思路。端到端方案直接把传感器输入映射到控制输出,中间不显式建模任何语义概念;模仿学习则通过大量人类驾驶数据,学习人类驾驶员在对应场景下的操作策略。
这类方法的强项是省心——不需要人类穷举规则,模型能从数据里自己总结出隐含的驾驶模式,对复杂和模糊场景的适应能力理论上更强。而且人类驾驶数据里天然包含了安全、效率、舒适的权衡经验,这是规则很难写出来的东西。
但问题同样尖锐。首先是可解释性差。模型输出一个“向左变道”的决策,你很难说清楚它到底是因为前车太慢,还是因为看到了更右侧车道的空隙,甚至是数据里某种统计偏差导致的误判。这在安全攸关的系统里是不可接受的。其次是安全性难以证成。“没撞”和“撞了”之间没有过渡,你不能指望模型在 corner case 里自动做出正确的保守行为。最后是数据需求极其庞大,而且数据分布稍微偏一点,模型在开放场景的表现就会崩。
我在做某段环路测试时试过一版模仿学习的换道决策头,仿真和已标注数据上表现很好,但在一个没见过的“前车骑线行驶”场景里,模型反复在“跟随”和“变道”之间震荡,输出行为非常不可靠。那次经历让我彻底明白:纯学习方案在当前工程体系里只能作为参考信号或者部分模块出现,不能直接扛起决策大旗。
2.3 混合架构:规则兜底加学习增强
聊到这里,结论基本就浮出来了:真正能在工程里落地、且让团队睡得着觉的,是混合架构——用规则的逻辑骨架保证基本行为可解释、可测试、可控,用学习方法或者优化方法来处理那些规则难以显式刻画的部分。这套思路在业界已经有相当多的实践。
一个比较常见的做法是:决策模块仍然采用状态机作为顶层骨架,但在状态内部嵌入更聪明的策略选择器。比如跟车状态下,安全距离参考值用规则计算,但“这个场景下是否需要更早开始减速”由策略模型给出一个建议,规则层对建议做安全检查和约束,通过就采纳,不通过就回退到保守策略。
还有一种混合方式是把优化类算法引进来。比如用蒙特卡洛树搜索或强化学习在连续决策空间里搜索更优的行为序列,再用规则层做安全约束和最终裁决。这种架构下,学习算法负责“找更好”,规则层负责“保不死”,二者各司其职,问题边界就清晰得多。我在实际项目中采用的也是这个思路,体验下来最大的感受是:出了问题你知道该去查哪一层,不会像纯端到端那样整个模型黑成一片。
2.4 我的选型建议
技术选型这件事,一定要回到你手头的资源和目标去看。如果做的是限定场景的高速导航辅助驾驶,状态空间相对封闭、场景模式有限,成熟的状态机加上配套的参数调校,性价比极高;如果做的是城区开放道路的复杂场景,那就必须上混合架构,纯规则顶不住长尾,纯学习又不能保证安全;如果是学术研究、前沿探索,可以大胆试强化学习或者端到端,但心里要清楚,工程落地还差着安全验证和可解释性这两座大山。
我自己做选型时有三个考量维度:第一是可解释性,任何决策都必须能回溯到明确的原因;第二是可测试性,要能为每一个决策行为构造对应的测试用例;第三是迭代效率,方案要允许快速接入新的场景和新的规则补丁。哪个方案在这三件事上表现更好,我就倾向哪个,这套标准帮我避了不少坑。
3. 数据是决策算法的燃料:自动驾驶数据集的关键作用
3.1 为什么决策模型离不开高质量自动驾驶数据集
无论你选学习路线还是混合路线,数据都是绕不开的基础设施。决策模型要学到“什么场景该做什么”的映射关系,靠的是大量标注好的驾驶场景数据;决策评测要验证“这个策略到底靠不靠谱”,靠的也是有标签的测试场景集合。没有高质量的数据集,决策算法就是纸上谈兵。
数据的作用主要体现在三个层面。训练层面,模仿学习、强化学习的策略模型都依赖数据或数据驱动的仿真交互来优化策略;验证层面,一套覆盖充分的数据集能帮助我们发现策略在哪些场景会失效,避免在新场景上翻车;回归层面,每次改动策略之后,都要在固定的数据集上跑回归测试,确保没有引入新的行为退化。可以说,数据集的质量和覆盖度直接决定了决策算法迭代的天花板。
3.2 数据集构建中的几个关键环节
很多人以为做一个数据集就是装个传感器去路上跑一圈,把数据录下来就行。真做起来完全不是这么回事。我梳理一下关键环节:
场景采集环节,要考虑传感器配置与标定的一致性。相机、激光雷达、毫米波雷达的数据必须是时空对齐的,否则模型学到的是错位的特征。采集路线规划也要讲究,不能只在固定园区转圈,要有意识地覆盖城市快速路、窄道、环岛、无标线路口、施工区域等各种结构,还得在不同天气和光照条件下采集。这个过程极其耗时,一辆采集车跑一天可能也就产出几百个小时的数据,而其中真正有价值的长尾场景可能只占几个百分点。
数据切片与去重环节,这是经常被忽略但实际工作量巨大的步骤。连续的原始数据流不能直接拿去训练或测试,要按场景片段切成若干小段,每段对应一个完整的交通交互事件。同时要处理近似重复样本——同一路段同一时段反复绕圈产生的数据高度相似,如果不加去重,会严重扭曲训练分布,导致模型在重复场景上过拟合、在多样性场景上欠拟合。
场景标注环节,直接决定数据集的可用度。决策相关的标注远比感知标注要复杂。感知只需要标出物体框和类别,决策标注则需要表达行为意图、道路结构关系、车辆交互逻辑——比如“前车在减速并开启左转灯,主车选择跟停”这种语义信息。我见过不少团队在这块偷懒,用感知标注的规格去标注行为数据,结果做模仿学习的同事拿到数据后一脸茫然,因为里面缺少关键的意图和交互标签,模型完全不知道该学什么。
3.3 数据不平衡与长尾场景补足
数据集构建中最头疼的问题是不平衡。正常行驶时,车辆大部分时间都在执行“稳定跟车”和“车道保持”,这类样本占绝对多数。而真正考验决策能力的危险交互场景——旁车强行加塞、行人突然横穿、路口对向车违章左转——出现的概率极低,可能一万公里都碰不上一次。
这种不平衡如果不处理,训练出来的模型会变成一个“只敢跟车巡航的老实人”,遇到稍微激进一点的场景就不知所措。我在实际项目里做了三件事来补救:一是数据增强,在仿真环境里对已有场景做参数扰动,生成大量变体,比如改变插入车辆的切入时机、初始距离、相对速度;二是难例挖掘,在测试过程中收集所有决策失败或策略置信度低的片段,补充标注之后重新投入训练;三是仿真生成,针对已知的长尾场景类型,直接在仿真器里批量构造。三管齐下,长尾覆盖度才能拉到一个可接受的水平。
这里还要多说一句:自动驾驶数据集不光是给学习算法用的。在规则和混合架构下,数据同样扮演核心角色——规则触发阈值的标定、策略参数的自适应调整、场景回归测试集的构建,都依赖带标签的数据支撑。它就像整个决策模块的地基,地基不稳,上面盖什么楼都白搭。
4. 从仿真到实车的落地过程
4.1 仿真环境怎么搭才贴近真实
决策算法跑起来第一步是仿真。但仿真和真实之间的差距,是很多人一开始严重低估的坑。我见过不少团队在仿真里把策略调到“完美”,拿到实车上路却接连出问题,原因往往就是仿真环境太“假”,没有覆盖到真实世界的关键复杂度。
搭建决策仿真环境,我一般重点关注三件事。第一是传感器模型,不需要把信号处理细节全部仿真,但传感器噪声、遮挡、有限视场角这些影响决策输入质量的因素必须模拟到位。决策模块本身不处理原始点云或图像,它消费的是感知融合之后的抽象目标列表,所以仿真的重点是目标检测的漏检率、误检率、位置噪声,这些要足够真实。第二是道路结构与交规模型的完备性,车道连接关系、交通灯相位、各种路权关系都要能表达,否则你测的换道策略在仿真里是合法操作,在真实道路上却违反了交规。第三是虚拟交通参与者的行为模型,这也是最容易被做“假”的地方。如果仿真里其他车辆的行为总是规规矩矩不犯错,那么你的决策算法就永远学不会如何应对人类的犹豫、误判和违章驾驶。我现在的做法是给虚拟车预置多种行为风格,有保守型、激进型、分心型,并且允许一定比例的随机违规行为,这样仿真出来的交互才足够“真实”。
4.2 实车部署时要命的性能与安全约束
仿真通过只是第一步,真正把决策算法搬到实车计算平台上,又是另外一场战斗。部署约束总结起来就是三件事:延迟、资源和安全。
延迟方面,决策模块必须在一个严格控制的计算周期内完成推理。常见的周期设定在50到100毫秒,这意味着从感知模块送出目标列表,到决策模块输出行为意图,中间留给你做算法计算的时间窗口非常短。如果你的策略模型是一个几十层的大网络、还带着一整棵搜索树,稍有膨胀就会把整个链路的时间预算拖垮。所以我在设计算法时就特别强调“计算量预算化”——每个模块分到多少毫秒、多少FLOPs,事先就要想清楚。
资源占用方面,实车平台往往同时运行着感知、预测、决策、规划、控制等多个模块,CPU、GPU、内存资源竞争非常激烈。决策模块必须控制内存拷贝和峰值占用,尽量避免在决策周期内触发大的内存分配。这些细节在服务器仿真时完全看不出来,一上车就暴露无遗。我遇到过决策模块因为偶尔的内存申请延迟,导致输出周期抖动超过200毫秒,差点触发安全降级的严重问题,后来把所有频繁调用的数据容器都改成预分配,问题才彻底消失。
安全机制方面,决策模块的输出是驾驶行为意图,一旦出错直接影响车辆控制,所以必须有严格的输入合法性校验、输出合理性检查和多级降级策略。输入合法性校验要看感知目标列表是否完整、是否有跳变;输出合理性检查要看决策结果是否符合基本物理约束和交规约束;多级降级策略则是一旦发现算法内部状态异常、推理超时或结果不合法,能够自动切换到保守的安全模式,比如减速靠边停车。这套机制任何时候都不能省,它是实车决策系统最重要的最后防线。
4.3 决策算法如何与上下游模块协同
决策算法在系统中从来不是孤立存在的,它跟预测、规划、控制模块之间是一个紧密协动的闭环。这个协同关系处理得好不好,直接决定最后车辆行为是流畅还是别扭。
先说与预测的协同。预测模块给出的不是单一条轨迹,而是带概率的多模态预测——前车可能有三个候选意图:继续巡航、减速停车、变道。决策算法不能只挑概率最大的那一个去做出发点,而要在多个假设下评估动作的安全性。我维护过一个内部通用接口,预测模块同时输出各候选意图的概率值和对应的安全距离评估,决策模块在这个接口之上做策略选择,效果比单纯取最大概率稳定很多。
与规划的协同也容易出问题。很多团队的规划算法是纯粹的几何优化器,只考虑避障和舒适性,不理解行为意图。比如决策决定“允许缓行通过路口”,规划层如果不知道这个语义,可能仍然按照停车等待来规划,导致车辆在路口出现踩一脚刹车又马上松开再走的诡异行为。解决思路是决策模块不仅输出行为ID,还输出行为的语义约束——目标速度范围、可行驶区域、优先级列表,规划层在这些约束下求解轨迹,行为才可能与轨迹一致。
与控制层的协同同样关键。控制模块关心的是轨迹跟踪精度和车辆动力学状态,决策的高频切换会直接传成控制指令的剧烈变化。我一般会在决策输出端加一个行为持续抑制器:同一行为意图必须在连续若干个周期内保持稳定才能输出切换,否则维持上一周期行为。这个简单的机制能滤掉绝大部分决策抖动,让车辆行为平滑很多。
5. 常见问题与排查技巧实录
5.1 典型问题一:决策抖动
决策抖动是我在调试中遇到最多、也最让人头疼的问题。车辆在行驶过程中,决策意图在几个候选行为之间来回切换,前一刻还在跟车,后一刻想变道,再过一刻又想切回来,控制模块被指挥得无所适从,车辆表现就是频繁修正方向、加减速突兀,乘客体感很糟糕。
抖动根因通常是两类。一类是输入信号噪声,感知目标的位置、速度在帧间存在微小抖动,如果决策阈值恰好落在噪声区间附近,状态就会反复横跳。另一类是策略结构的连续化问题——概率型决策在多个行为得分接近时,微小扰动就会改变排序结果。
我的排查思路分三步。第一步,记录所有决策输入和输出,做时间对齐回放,看抖动发生时输入到底发生了什么变化——先区分是输入噪声导致的还是逻辑本身不稳定。第二步,对所有决策切换加迟滞判断:进入某个行为需要满足阈值A,退出该行为需要满足阈值B,且B比A更严格,也就是所谓的施密特触发器思想。第三步,增加行为持续时间下限:任何新建行为至少要持续N个周期,防止瞬时切换。这套组合拳打下来,九成以上的抖动问题都能压住。
5.2 典型问题二:换道犹豫
换道犹豫是另一个高频痛点。策略模型计算变道收益和风险,在安全距离临界位置时得分非常接近,导致车辆长时间停留在目标车道边缘,反复打灯又不执行,后车压力很大,体验极差。
这个问题的本质,是我们的决策算法没有充分考虑“变道窗口的时间价值”。如果算法只看当前时刻的间隙是否安全,那么接近阈值的间隙会让它进退两难。我在实际工程里加了一个“机会成本评估”逻辑:不只是评估此刻变道是否安全,还要评估如果此刻不变道,未来多长时间内可能出现下一个可接受的窗口。如果预测窗口在可接受时间范围内不会再出现,那么算法会适当放宽安全裕度、果断完成变道。这个逻辑让换道行为明显更果断,也更接近人类驾驶员的真实心理。
另一个辅助手段是给换道决策引入“尝试性动作”——先打灯并小幅横向偏移,观察旁车是否礼让。这是很多人类司机的策略,在决策算法里也可以实现:打灯之后如果旁车减速让行,就继续完成变道;如果旁车加速逼近,就取消变道回到原车道。这个交互机制极大提升了换道成功率,也减少了犹豫。
5.3 典型问题三:过拟合于数据集
决策模型在训练集和验证集上表现都很好,一到真实开放道路或新的仿真场景就明显退化,这是典型的过拟合问题。我在早期一个模仿学习项目里栽过跟头:模型在自有数据集上换道成功率高得惊人,结果换到另一个开放世界测试场景,面对一辆毫无章法乱开的模拟车辆,策略立刻失效。
排查过拟合,我会先检查数据多样性。之前说过,数据分布天然倾斜,如果不对长尾场景做增强和重采样,模型很容易学到“在高速公路环境跟车巡航”这一个套路,然后把这个套路硬套到所有场景里。处理方式是做场景重加权,在训练时对稀有场景样本提高采样权重,同时引入仿真数据混合训练,强制模型看到更广的行为覆盖。
还要检查特征设计是否合理。如果模型依赖的特征在训练集里几乎恒定、在开放场景里才会发生变化,那么它根本没学会用这些特征做决策。比如训练数据里“旁车距离”几乎总是大于某个值,模型就可能忽略这个特征,真实场景里旁车贴近时它就完全没有反应。最有效的排查手段是把模型在多个测试场景里的关键特征激活度可视化出来,一眼就能看出它到底在“看”什么东西。
5.4 排查工具箱与工作方法论
除了具体问题,我一直很重视决策模块的排查工具建设。实车和仿真中跑出的问题,如果只能靠肉眼盯log来找原因,效率太低了。我推荐的标配工具组合是:全量数据记录器,录下所有模块的输入输出、状态量、时间戳,这是问题复现的基础;场景回放引擎,能把记录的数据在仿真环境里原样还原,还能调整视角、放慢速度逐帧分析,这是理解问题的最短路径;决策可视化面板,把决策状态、候选行为得分、触发阈值、抑制器状态实时画出来,能让你一眼看出决策模块“心里在想什么”。
在方法论上,我更倾向于“先锁条件,再二分定位”。遇到一个问题,先固定复现条件,把天气、场景、周围车辆行为、主车状态全部锁住,保证每次跑出来都是同样的问题;然后按输入边界、策略逻辑、输出后处理三个环节逐层二分,快速定位故障是在数据入口、核心决策还是输出链路。这套方法虽然朴素,但面对复杂的决策系统,是最可靠的排障路径。
另外提醒一点,修改决策算法时一定要做好回归测试。决策算法牵一发动全身,同时涉及安全性、舒适性、通行效率等多维指标,我会在每次修改后,先在固定数据集上跑一遍全量回归,对比修改前后的行为差异和指标变化,确认没有把原有的稳定行为改坏。这个习惯帮我避免了很多次“修一个bug引入两个新bug”的尴尬。
6. 一些更深的反思与后续方向
做自动驾驶决策这几年,我最大的体会是:这个问题的核心难点不在单点技术,而在“系统权衡”。你优化安全性,可能损害通行效率;你提升通行效率,乘客体验可能下降;你让行为更像人类,又可能在可解释性和合规性上打折扣。真正成熟的决策系统,一定是在安全优先的约束下,兼顾效率、体验、规则和产品目标的平衡。
所以每次有人问我说,决策算法用什么最新的模型效果好,我都会反问他:你的系统里,安全边界是怎么定义的?失败降级路径是否清晰?模块之间的接口约束是否完备?这些问题想不清楚,换再强的模型也是白搭。
后续我觉得有几个方向值得持续关注。一个是数据驱动的安全验证,如何让大规模自动驾驶数据集自动挖掘潜在危险场景,让决策算法在交付前就经过充分的安全论证;另一个是与大模型的结合,用大模型的常识推理能力辅助决策模块理解复杂开放场景,但解决实时性、确定性和可验证性,还有很长的路要走;再一个就是多模态交互决策,让车与车之间通过V2X通信达成协同意图,这可能是突破单车智能瓶颈的重要补充。
最后再分享一个我在实际项目里的心得:做决策算法不要闭门造车,多去开真车。你会发现很多你觉得理所当然的决策逻辑,真在方向盘后面体验一遍,感受完全不一样。比如旁边车加速时你到底该不该变道,地图上看间隙挺大,但实际车速、盲区感知和司机心理完全会改变判断。这些“路上学来的感觉”,比任何论文里的公式都更能帮助你设计出真正合理的决策策略。