☰
自动驾驶决策算法工程实践:从分层架构到安全兜底的落地经验
2026/10/26 4:13:30 网站建设 项目流程

1. 从感知到决策:自动驾驶真正难啃的骨头在哪

很多人聊自动驾驶,第一反应都是激光雷达、摄像头像素、算力多少TOPS这些硬件指标。但真正在一线做过系统落地的人心里都清楚,感知决定的是"能不能看见",而决策决定的是"看见了之后敢不敢走、怎么走"。前者是工程问题,后者更接近博弈和判断问题。我接触过几个做自动驾驶决策模块的团队,大家有个共识:感知的bug往往能通过数据回灌和标注修复,但决策的bug经常是"这次改好了,换个场景又冒出来",因为它面对的是一个开放、动态、充满不确定性的世界。

决策算法要解决的核心问题,说白了就是在有限时间内,从一堆可能的动作里挑出一个既安全又合理、还符合交规和乘坐体验的方案。这个"合理"非常微妙。比如前方有个行人站在路边犹豫要不要过马路,你作为人类司机可能会减速观察,也可能稍微往左打一点方向留出余量。但机器怎么判断这个行人"犹豫"?减速到多少算合适?留多少余量算安全?这些问题没有标准答案,却直接决定了决策系统的上限。

这篇文章我想从实际工程的角度,把决策算法拆开来讲。不堆公式,也不吹概念,主要聊清楚几件事:决策模块在整个系统里到底承担什么角色,主流的几种技术路线各自适合什么场景,为什么很多团队最后都走向了"分层+兜底"的混合架构,以及在真实调试中那些文档里不会写的坑。如果你正在做决策相关的工作,或者准备进入这个方向,希望这些内容能帮你少走点弯路。

2. 决策模块的定位:它到底在替谁做决定

2.1 决策不是孤立的一层,而是承上启下的翻译官

刚入行的时候我一度以为决策就是"输入感知结果,输出油门刹车方向盘"。后来才发现这个理解太粗糙了。真实的决策模块更像一个翻译官,它要把上游感知给出的、带有不确定性的世界描述,翻译成下游控制能执行的、确定性的动作指令。这个翻译过程里,最麻烦的是"不确定性"这三个字。

感知给你的从来不是"前方50米有一辆车",而是"前方大概50米的位置,有85%的概率是一辆车,它的速度估计是30km/h,误差正负5km/h"。决策模块必须在这种模糊信息下做判断。如果太保守,把所有不确定都当成危险,那车基本没法开,动不动就急刹;如果太激进,把不确定当成确定,那迟早出事。所以决策的第一要务不是"算出最优解",而是"在信息不完整的情况下做出可接受的次优解"。

这就引出一个很重要的设计原则:决策模块必须对上游的噪声有鲁棒性。我见过一些团队把感知和决策耦合得太紧,感知一抖动决策就跟着抽风,结果整车行为像得了帕金森。正确的做法是在决策层做一层"信息平滑和置信度过滤",对低置信度的目标先降权处理,而不是直接采信。

2.2 决策要同时满足安全、效率、舒适、合规四个目标

人类开车其实一直在做多目标权衡。你跟前车太近不安全,但离太远又会被加塞,效率下降;急加速能抢时间,但乘客体验差;完全按限速走合规,但可能被后车按喇叭。决策算法要做的就是把这种权衡显式化、可量化。

实际工程里常见的做法是设计一个代价函数,把安全、效率、舒适、合规分别做成不同的惩罚项或奖励项,然后求总代价最小。听起来很优雅,但真正难的是权重怎么定。安全权重给太高,车就变得极其保守,在复杂路口永远等不到机会;效率权重给太高,又会牺牲安全边际。我见过一个团队为了调这几个权重,专门搭了一套仿真回放系统,把同一段路的数据反复跑,人工标注"这个行为像人""这个行为太怂""这个行为太莽",然后反推权重。这个过程非常耗人力,但确实有效。

提示:权重调参不要指望一次到位。建议先定一个保守基线,保证安全兜底,再逐步放开效率项,每次只动一个维度,观察仿真和实车表现。

2.3 决策的时间预算比想象中紧张

很多人忽略了一点:决策是有硬实时要求的。控制周期通常在10到100毫秒级别,意味着决策必须在几十毫秒内给出结果。这个时间预算下,很多理论上很漂亮的全局优化算法根本跑不完。所以工程上常见的做法是"分层决策":高层做粗粒度的行为选择(比如"跟车""换道""让行"),低层做细粒度的轨迹优化。高层可以用规则或学习模型快速出结果,低层再用优化方法在局部细化。

这种分层的好处是每层的时间预算可控,坏处是层与层之间的接口设计很讲究。高层给低层的是一个"行为意图",低层要能理解这个意图并生成符合意图的轨迹。如果接口设计得不好,高层说"换道",低层却因为局部障碍生成了一条换不过去的轨迹,整个系统就卡住了。我踩过这个坑,后来在接口里加了"可行性反馈",低层如果发现意图不可行,会回传给高层要求重新决策,形成一个闭环。

3. 几条主流技术路线的真实适用边界

3.1 有限状态机:老派但依然是很多量产系统的骨架

有限状态机(FSM)是最经典的决策方法。把驾驶行为拆成一个个状态,比如"巡航""跟车""换道""路口通行",然后定义状态之间的转移条件。它的优点是逻辑清晰、可解释性强、容易做安全验证。量产项目里,很多系统的决策骨架仍然是状态机,因为出了问题能查、能复现、能向监管解释。

但状态机的短板也很明显。状态和转移条件都是人写的,面对没见过的场景就容易僵住。比如一个复杂的无保护左转路口,对向车流、行人、非机动车交织,状态机很难穷举所有情况。而且状态一多,转移条件之间的耦合会变得极其复杂,改一个条件可能影响十几个状态,维护成本很高。

我的经验是,状态机适合作为"行为管理层",负责那些逻辑明确、边界清晰的行为切换,但不适合处理连续的、需要精细博弈的场景。把它和后面的优化方法结合,才是比较务实的用法。

3.2 基于采样的方法:用撒点的方式逼近可行解

采样类方法(比如RRT、Lattice Planner)的思路是:在动作空间或状态空间里撒一堆候选点,然后评估每条候选轨迹的代价,挑最好的那条。它的好处是不依赖梯度,能处理非凸、不连续的约束,适合复杂环境。

实际用下来,采样方法的瓶颈在"撒多少点"和"怎么撒"。撒得太少,可能错过好解;撒得太多,计算量爆炸。工程上常见的优化是"引导采样",根据当前场景把采样集中在更可能出好解的区域。比如在跟车场景,重点采样纵向的加减速;在换道场景,重点采样横向的偏移。

采样方法还有个隐性问题:它给出的解往往不够平滑,因为是从离散候选里挑的。直接拿去控制会导致方向盘抖动。所以通常还要接一个平滑或优化层,把采样结果修一修再用。

3.3 基于优化的方法:数学漂亮,但工程落地要过好几道坎

优化类方法(比如MPC、二次规划)把决策建模成一个带约束的最优化问题,求一条满足动力学约束、避障约束、舒适性约束的最优轨迹。理论上它是最优雅的,能同时处理多个目标和约束。

但落地时有几个坎。第一是实时性,非线性MPC在复杂场景下求解时间可能超过预算,得做各种简化或热启动。第二是可行性,约束太严可能无解,约束太松又失去意义,实际中要设计"软约束+惩罚"的机制,允许轻微违反某些约束来保证有解。第三是调参,优化问题的权重和约束边界对结果影响巨大,调起来很费劲。

我个人的体会是,优化方法适合作为"轨迹生成层",在行为意图明确的前提下做精细轨迹规划。让它单独承担整个决策,在开放场景下还是吃力。

3.4 学习类方法:潜力大,但离量产还有距离

这几年用强化学习、模仿学习做决策的研究很多。模仿学习直接从人类驾驶数据里学策略,理论上能学到很接近人的行为。强化学习则通过仿真环境里的试错来优化策略。

学习方法的吸引力在于它能处理规则难以描述的复杂场景,而且有泛化潜力。但工程上顾虑也不少:可解释性差,出了事故很难说清楚为什么这么决策;安全边界难保证,学出来的策略可能在极端场景下做出危险动作;训练数据的分布和真实世界有偏差,仿真里表现好不代表实车稳。

目前比较务实的做法是"学习+规则兜底":学习模型负责常规场景下的行为生成,规则模块负责安全监控和紧急干预。一旦学习模型输出的动作超出安全边界,规则模块立刻接管。这样既利用了学习方法的灵活性,又守住了安全底线。

4. 为什么混合架构成了大多数团队的最终选择

4.1 单一方法都有硬伤,组合才能互补

把上面几条路线摆在一起看,会发现没有哪一种是万能的。状态机可解释但不够灵活,采样灵活但不够平滑,优化平滑但实时性和可行性有挑战,学习灵活但安全难保证。真实项目里,几乎没有一个团队敢只用一种方法。

常见的混合架构是三层:最上层是行为决策层,用状态机或规则做宏观行为选择;中间是轨迹生成层,用采样或优化方法生成候选轨迹;最下层是安全监控层,用独立的规则模块做碰撞检查和紧急干预。这三层各司其职,层与层之间通过明确的接口通信。

这种架构的好处是每一层都可以独立测试和验证。行为层可以用场景库做逻辑测试,轨迹层可以用仿真做批量评估,安全层可以用形式化方法做边界证明。出了问题也容易定位是哪一层的责任。

4.2 安全兜底必须是独立的,不能和主决策共用逻辑

这一点我想特别强调。很多事故的根源不是主决策算法不够好,而是安全兜底和主决策用了同一套逻辑,主决策犯错时兜底也跟着错。正确的做法是安全监控模块独立实现,用最简单、最保守的规则,比如"前方多少米内有障碍物且相对速度超过阈值就触发紧急制动"。这套逻辑不需要聪明,只需要可靠。

我见过一个设计,安全监控模块甚至跑在独立的硬件上,和主决策物理隔离。虽然成本高,但在功能安全要求高的场景下,这种冗余是值得的。软件层面的隔离至少要做到:安全模块不依赖主决策的任何中间输出,只依赖最原始的感知和车辆状态。

4.3 接口设计决定了混合架构的上限

混合架构最容易出问题的地方是接口。行为层给轨迹层的意图描述如果太模糊,轨迹层就不知道该怎么生成;如果太具体,又限制了轨迹层的优化空间。我见过两种极端:一种是行为层只给一个"向左"的指令,轨迹层一脸懵;另一种是行为层直接把轨迹点都算好了,轨迹层沦为摆设。

比较合理的接口是"意图+约束"的形式。行为层告诉轨迹层"我要换到左车道",同时给出时间窗口、舒适性上限等约束,轨迹层在这个框架内自由生成具体轨迹。这样既保证了行为意图的贯彻,又保留了轨迹层的优化能力。

5. 真实调试中那些文档不会写的坑

5.1 感知延迟会让决策"看到过去"

感知模块从采集数据到输出结果是有延迟的,这个延迟在高速场景下影响很大。如果决策直接用感知输出的位置,实际上是在对一辆"过去位置"的车做反应。车速120km/h时,100毫秒延迟意味着3.3米的误差,足够造成误判。

解决办法是做"运动补偿",根据目标的历史速度和延迟时间,把感知结果外推到当前时刻。但外推本身也有误差,速度估计不准时外推反而更糟。实际中要结合置信度,对高置信度目标做外推,低置信度的保守处理。

5.2 仿真里跑得好不代表实车稳

仿真环境再逼真,也和真实世界有差距。仿真里的传感器噪声是建模出来的,真实噪声的分布可能完全不同;仿真里的其他交通参与者是脚本控制的,真实司机的行为千奇百怪。我见过一个策略在仿真里通过率99%,实车测试第一天就遇到一个仿真里从没出现过的场景:一个外卖骑手从视觉盲区突然窜出。

所以实车测试必须留足里程和时间,而且要刻意去跑那些"边缘场景"。有些团队会专门收集真实世界的corner case,回灌到仿真里做回归测试,这个闭环非常重要。

5.3 决策的"抖动"比"错误"更难治

决策抖动指的是在相似场景下,决策结果反复横跳。比如车在跟车时,一会儿想换道一会儿又不想,方向盘来回微调,乘客体验极差。这种抖动往往不是算法错误,而是代价函数在某个临界点附近太敏感,输入的小扰动导致输出大变化。

治抖动的常见手段是加"迟滞"和"平滑"。迟滞就是给状态切换加一个缓冲带,比如换道意图要连续满足条件若干帧才确认;平滑就是对输出做低通滤波,抑制高频变化。但这些手段都有副作用,迟滞太强会导致反应迟钝,平滑太强会导致跟踪误差。调这个平衡很考验经验。

5.4 交互博弈是最难建模的部分

自动驾驶最难的不是自己怎么开,而是预测别人怎么开。人类司机之间有很多默契,比如并线时打个灯、稍微探一下车头,对方一般会让。但机器怎么表达这种意图?怎么解读别人的意图?这是交互博弈的核心难题。

目前主流做法是"预测+博弈"两步走。先预测其他交通参与者可能的轨迹分布,然后在这个分布上做博弈决策。但预测本身就不准,博弈又建立在预测之上,误差会累积。有些团队尝试用博弈论的方法直接建模交互,但计算复杂度和假设的合理性都是挑战。

我的看法是,短期内不要指望机器能完全处理复杂的交互博弈,更现实的做法是"保守优先":在交互不确定时,选择最保守的动作,宁可慢一点、让一点,也不去赌对方会让。等预测和博弈技术更成熟了,再逐步放开。

6. 给正在做决策算法的同行几点实在建议

第一,先把安全兜底做扎实,再谈优化主决策。安全是1,其他都是后面的0。兜底逻辑要简单、独立、可验证,不要和主决策纠缠在一起。

第二,重视数据闭环。决策算法的迭代高度依赖真实场景数据,尤其是那些失败案例。建立一套从实车采集到仿真回灌再到回归测试的闭环,比单纯调算法参数有效得多。

第三,接口设计要早定、要稳定。混合架构里接口是命脉,接口一变上下游都要改。前期多花时间把接口定义清楚,后期能省大量返工。

第四,别迷信单一方法。状态机、采样、优化、学习各有适用场景,组合使用才是常态。关键是想清楚每一层负责什么、边界在哪、怎么验证。

第五,实车测试要趁早。仿真再方便也不能替代实车,很多问题只有在真实道路上才会暴露。早测试、早发现、早修复,比在仿真里憋大招强。

决策算法这个方向,理论上的天花板很高,但工程上的地板很低。能把地板踩实、把边界守住,比追求理论最优更有价值。我做了这些年,最大的感受就是:好的决策系统不是最聪明的那个,而是最让人放心的那个。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询