车辆消息字段契约:请求、软件回报与硬件执行的三层之分

作者:

在

结论:车端消息契约里最容易混淆的是「请求、软件回报、硬件执行」三层。CarOutput.actuatorsOutput 只是软件计算后的回报,不表示 panda TX 钩子接受、ECU 已执行或车辆真实响应;CarState.valid 直接取 CS.canValid,不自动合并全部逐字段新鲜度;SafetyConfig 虽是列表,但当前所读 setSafetyMode() 只取 safetyConfigs[0]。schema 注释是意图,运行时许可必须以代码及 panda 固件为准。本文为固定源码快照 c8fb906 的静态阅读,未运行回放或测试。

生产和消费链

card.state_update() 从 CAN 批次构造 CarState,card.state_publish() 发 carState、carOutput 和周期性 carParams;controlsd 用 CarState、selfdriveState 与计划形成 CarControl,再由车型控制器转成候选 CAN 帧。CarParams 还在启动时写入 Params,pandad 需等待 FirmwareQueryDone 和 ControlsReady 后读取其安全配置。

消息 生产者 主要消费者
CarState card.state_update() 状态机、控制器
CarControl controlsd 车型控制器 apply()
CarOutput card(取上次保存值) 控制器饱和逻辑参考
CarParams 启动时写入 Params pandad 读取安全配置

把这条链当成单向管道同样不准确。同一轮里 controlsd 既消费 CarState,又把自己的输出回报成 CarOutput 供下一轮饱和判断使用;CarParams 虽在启动时写入,却是 pandad、控制器与规划层共同读取的配置来源。理解这种「请求—回报—配置」的多向关系,是判断某个字段能否作为执行依据的前提。

CarState:归一化车况

字段簇 schema 语义 运行时注意点
CAN 健康 canValid、canTimeout、canErrorCounter 前两者由车型接口汇总解析器健康;canErrorCounter 累计的是空 CAN 接收周期,不是校验和错误计数;顶层 carState.valid 直接取 CS.canValid
速度与巡航 vEgo 估计、vEgoRaw 原始轮速、vEgoCluster 仪表速度 单位/估计来源有别,不能把仪表显示值直接反馈给动力学控制;CruiseState 区分可用、已启用和静止
驾驶员与转向 踏板为用户输入;驾驶员扭矩和 EPS 扭矩使用原生 CAN 单位,另有 steeringPressed、steeringDisengage 与暂时/永久故障 跨车型不得把原生扭矩直接比较;原车 AEB/LKAS/FCW 故障与功能状态是不同字段
交互与车身 档位、按键边沿、转向灯、门、安全带、盲区 ButtonEvent 应在变化时发送;布尔默认假值不代表传感器已观测到安全无障碍

车型基类先更新所有 CANParser,再调用品牌 CarState.update(),最后计算 canValid/canTimeout、仪表速度迟滞及 buttonEnable。需要明确:canValid 并不是所有源的数字签名。

逐字段看,vEgo、vEgoRaw、vEgoCluster 三者单位相同但含义不同:一个是估计值,一个是原始轮速,一个是经迟滞处理的仪表速度。把它们当作可互换的「车速」会导致控制层用到被截零或迟滞过的值。同理,驾驶员扭矩与 EPS 扭矩使用原生 CAN 单位,跨车型直接比较会得到错误结论。

CarControl 与 CarOutput:请求和回报

CarControl.enabled 是总使能,latActive/longActive 分别表达横纵向活动。controlsd.state_control() 从 selfdriveState、车况故障、低速门、纵向覆写事件及 CarParams.openpilotLongitudinalControl 计算它们,三者不应合成一个开关。Actuators 中 torque、steeringAngleDeg、curvature 是按控制类型选用的横向请求,accel 是纵向 m/s² 请求;另有 gas、brake、torqueOutputCan、speed 用于记录车型控制器实际计算的下层值。

字段 含义 不能推断的结论
CruiseControl 取消/恢复/覆写意图 不能等同具体 CAN 帧,需品牌控制器映射
HUDControl 发给原车仪表的提示数据 同样是请求,不代表仪表已响应
CarOutput.actuatorsOutput 车型控制器计算值,注释称反映发送前的车型限幅/特性 不是 panda TX hook 接受、ECU 已执行或车辆真实响应的确认
carOutput.valid 取 carControl 的 all_checks 不能升级成物理回执

controlsd 会比较 CarOutput 与本轮 CarControl.actuators,估计转向受限以影响控制器饱和逻辑。controlsd 发布 carControl 时把外层 Event.valid 设为 CS.canValid;card.controls_update() 的本地门控是 carControl 存活后调用品牌 apply(),并用 CS.canValid 标记 sendcan 的外层有效位。它不在这一函数再次以 carControl.valid 为硬许可条件;完整许可仍依赖上游状态机、车型控制器及 panda 安全层。

这里存在一个容易忽略的非对称:carControl 的外层 Event.valid 取 CS.canValid,而 card.controls_update() 在调用品牌 apply() 时并不再以 carControl.valid 为硬条件,只要求 carControl 存活。也就是说,消息层有效性、上游状态机、车型控制器与 panda 安全层各自负责一段,任何单一有效位都不能代表整条链已获授权。

CarParams:跨进程配置

字段簇 作用及信任界限
身份/证据 brand、carFingerprint、VIN、carFw、fingerprintSource、fuzzyFingerprint 记录识别结果;来源标记不是身份认证或执行许可
动力学/调参 质量、轴距、重心、转向比、惯量、轮胎刚度、PID/扭矩调参、执行器延迟进入规划控制;标称值需按目标车辆验证
执行配置 pcmCruise、最低速度、横纵向控制能力、steerControlType、safetyConfigs、alternativeExperience、passive、dashcamOnly 决定不同层行为;任意单字段都不是最终执行许可
认证状态 secOcRequired、secOcKeyAvailable 记录车型需求和密钥可用状态;不能把「存在密钥」理解为报文已通过对端认证

SafetyConfig 是 (safetyModel, safetyParam) 列表,但当前所读 PandaSafety::setSafetyMode() 对其连接的 panda 只取 safetyConfigs[0] 并设置 alternativeExperience;多 panda 的分配须看上层设备编排。card 在被动模式会把列表替换成 noOutput。

身份/证据类字段尤其需要小心:fingerprintSource 与 fuzzyFingerprint 只是来源标记,说明识别结果是如何得到的,而不是身份认证;secOcKeyAvailable 说明密钥可用,也不表示对端报文已通过认证。两者都不能升级为执行许可。动力学与调参字段同理,它们是标称值,进入规划控制前必须按目标车辆验证。

RadarData 与扩展边界

RadarData.errors 包含 CAN 错误、雷达故障、错误配置及临时不可用;点数据包含轨迹 ID、相对距离/横移/速度。schema 注释称这些点字段必需,但 Cap’n Proto 默认值仍可能存在,消费者应结合生产者健康和点轨迹年龄;card 只在收到 RD 时发 radarTracks,外层 valid 由错误位汇总。对自制硬件和插件化,建议将字段单位、坐标系、采样频率、时间戳、最大年龄、缺失值与信号来源做成版本化契约,并把外层 valid、字段默认值、软件输出回报和硬件执行确认分别建模。

常见问题

CarOutput 能证明车辆真实执行了吗?

不能。它来自车型控制器 apply() 的计算值,注释称反映发送前的车型限幅/特性,是软件计算后的回报;不是 panda TX 钩子接受、ECU 已执行或车辆真实响应的确认。

carState.valid 为真代表所有字段都新鲜吗?

不代表。顶层 carState.valid 直接取 CS.canValid,并不自动合并全部逐字段新鲜度;消费关键字段时仍需结合解析器健康与字段年龄判断。

SafetyConfig 列表里的每个配置都会生效吗?

不能直接推断。当前所读 setSafetyMode() 只取 safetyConfigs[0] 并设置 alternativeExperience;多 panda 的分配须看上层设备编排。

CarControl 里的计划字段等于具体 CAN 帧吗?

不等于。CruiseControl、HUDControl 等是意图与提示数据,需要品牌控制器映射为具体帧;schema 字段不能直接等同 CAN 报文。

延伸阅读

参考资料

  • 项目 02 —— openpilot-research/CAR_MESSAGES_FIELD_CONTRACT_DEEP_DIVE.md(取用了生产消费链、CarState/CarControl/CarOutput/CarParams 字段簇、RadarData 与扩展边界)。
  • 项目 02 —— openpilot-research/ECU_DIAGNOSTIC_TRANSPORT_DEEP_DIVE.md(仅用于确认指纹与固件证据进入 CarParams 的位置)。

说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

更新记录

首次发布 2026-10-11 最近核对:2026-10-11

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注