结论:在固定快照 c8fb906 中,body、BYD、MG、PSA 与 mock 这五个平台各有完全不同的执行语义:body 是双轮开发平台而非乘用车,只做左右轮速度与差速;BYD 与 PSA 走转角链,MG 走扭矩链;mock 返回空状态与空发送,只在无法识别车型时回退。BYD、MG、PSA 在快照中均被标记 dashcamOnly,其 panda 安全模式仅在 ALLOW_DEBUG 注册,因此不能把代码路径解读为发布固件可用功能。本文为静态代码分析,未运行测试、未做实车验证。
平台资格:notCar、dashcamOnly 与调试注册
同一套接口在不同平台上可能只是「能加载」而不是「允许执行」。body 通过 CarInterface._get_params() 设置 notCar=True,它并不是乘用车;BYD、MG、PSA 与 mock 都设置了 dashcamOnly=True,且它们的安全模式只出现在调试注册表里。插件清单必须把这几类资格分开标注。
| 平台 | 控制语义 | 资格标记 |
|---|---|---|
| body | 双轮差速、速度控制 | notCar=True,非乘用车 |
| BYD | 角度转向、原车纵向 | dashcamOnly=True,调试注册 |
| MG | 扭矩转向、原车巡航 | dashcamOnly=True,调试注册 |
| PSA | 角度转向、EPS 重使能 | dashcamOnly=True,调试注册 |
| mock | 空状态、空发送 | dashcamOnly=True,未知车型回退 |
body:开发用双轮平台
CarState.update() 从电机数据读取左右电机速度并估算速度,电机错误会形成永久转向故障,同时读取充电与电量,且巡航状态被设为可用且已启用。CarController.update() 与构帧函数把 actuators.accel 与 torque 转成期望前进速度与左右差速,使用两个 PID,经过死区、变化率及幅度限制,最终编码双轮扭矩;代码明确注明加速度字段并非真实加速度语义。
body_rx_hook() 在 RX 有效后允许控制,body_tx_hook() 只开放指定 TX 地址与长度并关闭转发。需要注意两处例外:未允许控制时仍可发送 0x1,且 0x250 的特定魔数刷写帧也被放行。固件没有乘用车式的双轮扭矩逐字段限制,因此它的安全策略不能移植到车辆。
| 层 | 关键函数 | 实现事实 |
|---|---|---|
| 参数 | _get_params() |
notCar=True、body 安全模式、纵向开启、角度控制类型 |
| 输入 | CarState.update() |
左右电机速度估算速度;电机错误形成永久转向故障 |
| 输出 | CarController.update() / create_control() |
accel 与 torque 转差速,经死区与限幅编码双轮扭矩 |
| 固件 | body_rx_hook() / body_tx_hook() |
仅白名单与长度;未允许时仍可发 0x1,0x250 刷写帧为例外 |
BYD 与 MG:转角链与扭矩链
BYD 走角度转向:CarController.update() 用车辆模型限制目标转角,每两帧发转角与 HUD,取消时每十帧发按钮候选帧;byd_tx_hook() 检查转角与速率,按钮只接受取消或释放,且取消需有先前巡航接合状态。其部分 RX 项显式忽略校验和与计数器,不能泛称全链路完整性校验。驾驶员 EPS 扭矩分别用于软覆盖与硬退出。
MG 走扭矩转向:CarController.update() 每两帧按驾驶员施力与变化率对期望扭矩限幅,未激活时置零,只构造 LKAS 转向帧;mg_tx_hook() 的 TX 白名单仅一条转向帧,固件再次检查最大扭矩、速率、实时变化与驾驶员扭矩。其安全注册只在调试编译中。
| 平台 | 输入来源 | 输出与固件门 |
|---|---|---|
| BYD | 动力总线取速度、转角、扭矩、踏板、车门;相机总线取 ACC 与原 LKAS HUD | 车辆模型限幅转角;TX 检查转角与速率,按钮只接受取消/释放 |
| MG | 状态来自 PT 与相机两路,含巡航故障与临时转向故障 | 每两帧限幅扭矩、未激活置零;TX 仅一条转向帧并复检扭矩/速率 |
PSA 与 mock:EPS 重使能与未知车型回退
PSA 设转角控制与 dashcamOnly=True,主、ADAS、相机三总线共同提供速度、驾驶员与 EPS 状态、巡航、制动与安全带。CarController.update() 每五帧做转角限幅并发 LKAS;在 EPS 覆盖后按 READY 到 AUTHORIZED 再到 ACTIVE 的状态序列尝试重使能,实际策略必须在目标平台验证。psa_tx_hook() 的白名单只含 LKAS 转角帧,并限制目标角度与速度相关变化率;部分 RX 项忽略校验与计数。
mock 是明确的隔离边界:_get_params() 设 dashcamOnly=True,CarState.update() 返回空状态,CarController.update() 返回空 CAN 列表。get_car() 在无法识别车型时回退到它,被动路径还会把安全配置设为 noOutput。因此 mock 可用于只读、仿真与未知车型隔离,不能用来推定车辆控制可用。
对硬件与插件化的含义
插件清单必须区分 notCar、dashcamOnly、发布与调试固件注册状态、控制语义和总线拓扑;加载实现并不等于允许执行。车型控制插件只能产出候选帧,独立安全 MCU 仍需按车型验证 RX 有效性、TX 白名单与转角或扭矩限制。body 的刷写例外不能进入乘用车固件。
BYD 的相机 HUD 保留、PSA 的 EPS 重使能状态机及各平台的巡航接合语义,都应放入明确的能力与风险契约,不能抽成无条件的通用按钮或转向插件。相关测试入口包括 body、BYD、MG、PSA 的专项测试与通用车型接口测试,本次只确认文件存在,未运行也未验证实车行为。
常见问题
body 是乘用车平台吗?
不是。body 是开发平台,其接口设置 notCar=True,执行方式是双轮差速与速度控制,代码还明确注明加速度字段并非真实加速度语义。它的固件安全策略不能移植到乘用车。
dashcamOnly 与调试注册意味着什么?
意味着这些路径在固定快照中不作为发布可用功能。BYD、MG、PSA 都设了 dashcamOnly=True,其 panda 安全模式只在 ALLOW_DEBUG 下注册,因此不能把代码路径解读为发布固件可用功能。
mock 会不会真的发控制帧?
不会。mock 的 CarState.update() 返回空状态,CarController.update() 返回空 CAN 列表,被动路径还把安全配置设为 noOutput。它用于只读、仿真与未知车型隔离,不能用来推定车辆控制可用。
插件加载了某平台实现就代表可以执行控制吗?
不代表。插件清单要区分 notCar、dashcamOnly、发布或调试固件注册状态与控制语义;加载实现不等于允许执行,最终 TX 仍由独立安全 MCU 按车型校验。
延伸阅读
- 同一个「转向灯」在三家车厂是三种实现:车辆状态归一化的坑 —— 承接本文各平台 RX 来源与控制语义的差异。
- 从使能到车轮:执行链上的八道门,以及它们各自不保证什么 —— 解释本文候选帧之后为何仍有独立安全门。
- 横向限幅的插件契约:意图、限值与执行边界 —— 对照本文转角链与扭矩链的限幅位置。
- Toyota panda safety 模式:车型白名单与转发边界 —— 作为另一车型安全模式的对照。
参考资料
- 项目 02 ——
openpilot-research/OTHER_PLATFORMS_DEEP_DIVE.md(取用了 body/BYD/MG/PSA/mock 五平台的参数、输入、输出与固件事实,以及插件化含义)。 - 项目 02 ——
openpilot-research/BYD_PANDA_SAFETY_MODE_DEEP_DIVE.md(关联的 BYD Atto 3 safety 专题,用于补充转角链与按钮门细节,本文未展开其探针)。
说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。
更新记录
首次发布 2026-10-11 最近核对:2026-10-11
发表回复