1. 问题诊断方法论

建立系统化的问题定位思维

做规划控制这些年,我踩过的坑真不少。有一次车辆在路口突然急刹,明明前面什么都没有。排查了三天,最后发现是感知模块传过来的一个障碍物ID飘了。嗯,这种问题,光靠拍脑袋是找不到根因的。

所以我一直强调:问题诊断,得有方法论。说白了,就是一套从现象到根因的推理链条。你想想看,没有这套链条,你就是在黑箱里乱摸。

第一步:现象描述要精准

很多工程师一上来就说「车跑偏了」。这太模糊了。我习惯问三个问题:

  • 什么场景下发生的? 直道、弯道、上下坡?
  • 什么工况下触发的? 加速、减速、匀速?
  • 复现概率是多少? 每次必现,还是十次一次?

举个例子。有一次测试反馈「车辆在车道保持时频繁抖动」。我追问了一句:「抖动频率是多少?方向盘转角有没有记录?」结果发现,抖动频率刚好和车道线检测的刷新率一致。这就把问题范围缩小到了感知层。

核心原则: 现象描述必须包含「时间、地点、工况、频率」四个维度。少一个,推理链条就可能断掉。

第二步:建立假设树

拿到现象后,别急着改代码。我建议先画一棵「假设树」。把可能的原因全部列出来,然后逐条验证。

比如车辆在弯道中突然减速:

  • 感知层: 弯道曲率检测异常?前方障碍物误检?
  • 决策层: 速度规划曲线不合理?安全距离参数过小?
  • 控制层: 转向不足导致横向误差过大,触发保护性减速?
  • 执行层: 线控底盘响应延迟?制动系统故障?

我曾经遇到一个案例,车辆在高速上频繁触发AEB(自动紧急制动)。排查了所有传感器和算法,最后发现是雨刮器的电机干扰了毫米波雷达的信号。你想想看,这种问题,如果不按假设树一层层排除,根本找不到。

我的习惯: 每次排查问题,先在白板上画一棵树。根节点是现象,叶子节点是可能原因。然后从最可能的叶子节点开始验证。这样不会漏掉任何分支。

第三步:数据驱动的验证

假设树画好了,接下来就是验证。我见过太多人靠「我觉得」来下结论。这不行。必须用数据说话。

常用的验证手段:

验证手段 适用场景 注意事项
回放Log 所有场景 确保时间戳对齐,不同模块的时钟可能不同步
仿真复现 确定性场景 注入同样的输入,看输出是否一致
实车复现 偶发问题 注意安全,建议在封闭场地进行
单元测试 算法模块 写测试用例时,要覆盖边界条件

我个人最常用的是回放Log。有一次车辆在十字路口左转时,突然往右打了一把方向。回放Log发现,决策模块在那一瞬间收到了一个「右转优先级更高」的指令。但实际场景中,根本没有右转车辆。最后定位到是V2X通信模块的一个数据包序号错乱,导致指令被错误执行。

避坑指南: 我曾经因为Log时间戳没对齐,白白浪费了两天时间。不同模块的时钟可能差了几毫秒,但在高速场景下,这几毫秒足以让问题定位完全跑偏。所以,第一步永远是检查时间同步。

第四步:根因确认与修复

找到根因后,别急着改。先问自己三个问题:

  1. 这个根因是唯一的吗? 有没有可能多个原因叠加?
  2. 修复方案会不会引入新问题? 比如调大安全距离,虽然解决了误触发,但会不会导致通行效率下降?
  3. 如何验证修复有效? 写一个自动化测试用例,确保回归测试能覆盖这个场景。

我记得有一次,为了解决车辆在坡道起步时溜坡的问题,我修改了坡度补偿算法。结果修复后,车辆在平地上起步反而变「肉」了。这就是典型的「修了一个bug,引入另一个bug」。所以,修复方案一定要经过充分的回归测试。

知识体系总览

下面这张图,是我总结的问题诊断方法论框架。你可以把它当作排查问题的「地图」:

问题诊断方法论框架 现象描述 建立假设树(感知/决策/控制/执行) 数据驱动验证(Log/仿真/实车/单元测试) 根因确认与修复 回归验证与闭环 第1步 第2步 第3步 第4步 第5步 时间/地点/工况/频率 逐层排除,不遗漏 用数据说话,别靠感觉 唯一性?副作用?验证方法? 自动化测试,防止回退

总结一下

问题诊断,说白了就是一套「现象 → 假设 → 验证 → 根因 → 修复」的闭环。我见过太多人跳过假设树这一步,直接改代码。结果往往是「修好了A,坏了B」。

记住:没有系统化的方法论,你就是在碰运气。而自动驾驶这种系统,碰运气的代价,可能是事故。

嗯,这一章就到这里。方法论是基础,后面的章节我们会深入到具体的算法模块,看看每个模块常见的坑和对应的诊断技巧。