4. ADAS决策层数据:规划、控制、执行器状态记录
各位工程师朋友,今天我们聊聊ADAS决策层的数据记录。说实话,这个层面是EDR数据中最容易被忽视,但又是最关键的环节。为什么?因为传感器看得再准,感知层算得再快,最终车辆怎么动,全看决策层怎么发号施令。
我个人习惯把决策层数据分成三块:规划数据、控制数据、执行器状态数据。这三块数据串起来,才能完整还原事故前车辆到底想干什么、实际干了什么。
4.1 规划数据:车辆想怎么走
规划层,说白了就是车辆的「大脑」。它根据感知结果,决定接下来几秒钟的行驶轨迹。EDR需要记录哪些规划数据?我列一下关键项:
- 目标路径点序列:未来3-5秒的期望轨迹,通常每100ms一个点
- 期望车速曲线:每个时间点对应的目标车速
- 期望加速度:纵向和横向的期望加速度值
- 变道意图标志:是否正在执行变道、汇入、避让等操作
- 规划时间戳:每个规划周期的绝对时间
我在项目中遇到过一个问题:某次事故分析时,发现规划层明明输出了「紧急制动」指令,但车辆没有减速。后来查EDR数据才发现,规划时间戳和实际执行时间戳差了200ms。嗯,这就是典型的规划延迟问题。
关键点:规划数据必须包含时间戳,而且时间戳精度要到毫秒级。否则你根本分不清是规划没输出,还是执行没跟上。
4.2 控制数据:车辆实际怎么动
控制层是规划的「执行者」。它把规划轨迹转换成具体的油门、刹车、转向指令。EDR需要记录的控制数据包括:
| 数据项 | 说明 | 记录频率 |
|---|---|---|
| 方向盘转角指令 | 控制层发出的目标转角 | 50Hz |
| 制动压力指令 | 目标制动主缸压力 | 50Hz |
| 驱动扭矩指令 | 目标电机/发动机扭矩 | 50Hz |
| 控制模式状态 | 如:ACC、LKA、AEB等模式 | 10Hz |
| 控制输出限幅值 | 当前允许的最大/最小输出 | 10Hz |
你想想看,如果只记录规划数据,不记录控制数据,你根本不知道车辆实际执行了没有。我曾经处理过一个案例:EDR显示规划层发出了「向左避让」指令,但控制层因为某个安全限幅条件,实际只输出了很小的转角。结果车辆没躲开障碍物。这就是控制限幅导致的问题。
避坑指南:我曾经在调试时发现控制输出限幅值被意外设成了0。原因是某个标定参数在OTA升级后被覆盖了。所以EDR一定要记录限幅值,这是排查「指令发了但没执行」的关键线索。
4.3 执行器状态:车辆实际做了什么
执行器状态,是决策层数据的最后一环。它告诉你车辆实际响应了多少。说白了,控制层发了100%的制动指令,但执行器可能只响应了80%。为什么?因为制动系统有延迟、有磨损、有温度影响。
需要记录的执行器状态数据:
- 实际方向盘转角:传感器测量的真实转角
- 实际制动压力:轮缸压力传感器实测值
- 实际驱动扭矩:电机/发动机实际输出扭矩
- 执行器响应时间:从指令发出到执行器开始动作的时间差
- 执行器故障状态:如制动系统故障、转向系统故障等
注意:执行器状态数据必须和指令数据对齐。我见过最坑的情况是:EDR里指令数据是50Hz,执行器状态数据是10Hz。分析时根本对不上时间轴。所以记录频率一定要一致,或者至少能通过时间戳精确对齐。
4.4 决策层数据的时间对齐
这是整个决策层数据记录的核心难点。规划、控制、执行器三个层面的数据,各自有不同的时间基准和采样频率。怎么对齐?
我建议的做法是:
- 统一时间源:所有数据使用同一个GPS时间或网络时间
- 记录发送-接收时间戳:每个指令记录「发送时间」和「接收时间」
- 插值对齐:对于不同频率的数据,使用线性插值对齐到统一时间轴
下面是一个简单的数据对齐伪代码:
// 决策层数据对齐示例
struct DecisionData {
uint64_t timestamp; // 统一时间戳
float target_steering; // 规划目标转角
float cmd_steering; // 控制指令转角
float actual_steering; // 实际转角
float target_brake; // 规划目标制动
float cmd_brake; // 控制指令制动
float actual_brake; // 实际制动压力
uint8_t control_mode; // 控制模式
uint8_t actuator_status; // 执行器状态
};
// 对齐函数:将不同频率数据插值到统一时间轴
void align_decision_data(
const vector<PlanningData>& plan,
const vector<ControlData>& ctrl,
const vector<ActuatorData>& act,
uint64_t align_interval_ms,
vector<DecisionData>& output
) {
// 以10ms为间隔对齐
for (uint64_t t = start_time; t < end_time; t += align_interval_ms) {
DecisionData d;
d.timestamp = t;
// 线性插值规划数据
d.target_steering = interpolate(plan, t);
d.target_brake = interpolate(plan, t);
// 查找最近的控制指令
d.cmd_steering = find_nearest(ctrl, t);
d.cmd_brake = find_nearest(ctrl, t);
// 查找最近的执行器状态
d.actual_steering = find_nearest(act, t);
d.actual_brake = find_nearest(act, t);
output.push_back(d);
}
}
个人经验:我建议对齐间隔不要超过20ms。因为ADAS控制周期通常是10-20ms,间隔太大你会丢失关键信息。另外,插值算法建议用线性插值就够了,高阶插值反而可能引入虚假数据。
4.5 决策层数据的典型故障模式
根据我多年的EDR数据分析经验,决策层数据最常见的故障模式有这几种:
- 规划-控制不匹配:规划输出紧急制动,但控制模式还在ACC巡航状态
- 控制-执行器延迟:控制指令发出后,执行器响应时间超过100ms
- 执行器饱和:控制指令要求100%制动,但执行器只能输出80%
- 模式切换冲突:AEB和ACC同时请求控制权,导致控制混乱
我记得有个案例特别典型:一辆车在高速上突然加速,司机说是「刹车失灵」。我们调出EDR数据一看,规划层输出的是「减速」,控制层也发了「制动指令」,但执行器状态显示「制动压力为0」。再往下查,发现制动系统的CAN总线在事故前3秒出现了通信故障。这就是执行器状态数据立功了。
总结一下:决策层数据是EDR分析中最能还原「车辆意图」的部分。规划数据告诉你车辆想干什么,控制数据告诉你车辆指令了什么,执行器状态告诉你车辆实际干了什么。三个层面缺一不可,而且必须精确对齐时间轴。
好了,关于决策层数据记录,核心就是这三层结构。记住:规划是意图,控制是指令,执行器是结果。三个数据串起来,才能完整还原事故前车辆的决策和执行过程。