结论:Volkswagen MEB 的 panda safety 不是「按品牌名放行」,而是一组可逐帧核对的约束:MEB 选择 volkswagenMeb 安全模式与曲率转向,MEB_GEN2 额外设置 MEB_ALT_CRC;所有必需 RX 在 bus 0,使用 CRC-8H2F、四位计数器与存活检查;发送侧只放行 HCA_03、ACC_18、LDW_02、KLR_01、ACC_19、TA_01 六类地址。其中最容易被误读的一点是 Gen2 的替代 CRC:它不是「Gen2 一律不校验尾部」,标准整帧 CRC 仍可能被接受。
一、车型资格与 RX 格式
CarInterface._get_params() 为 MEB 选择 volkswagenMeb 安全模式和曲率控制;MEB_GEN2 设置 MEB_ALT_CRC。网关接线还由指纹判断,不能从品牌名推断物理总线。volkswagen_meb_init() 初始化 Gen1/Gen2 的 RX 长度与统一 TX 白名单,其中 Gen2 的 Motor_51 由 32 字节变为 48 字节,ESC_51 由 48 字节变为 64 字节。
| RX 报文 | 频率 | Gen1 / Gen2 长度 | 作用 |
|---|---|---|---|
| LH_EPS_03 | 100 Hz | — | 驾驶员扭矩。 |
| Motor_14 | 10 Hz | — | 制动状态,再由通用 RX 规则参与退出。 |
| GRA_ACC_01 | 33 Hz | — | Set/Resume 释放沿且主开关开时使能;Cancel 位使其退出。 |
| QFK_01 | 50 Hz | 32 字节 | 测量曲率;本模式 max_curvature_error=0,不运行相对误差限幅。 |
| ESP_21 | 50 Hz | — | 独立速度源。 |
| Motor_51 | 50 Hz | 32 / 48 字节 | ACC 状态 2 表示主开关可用,3/4/5 表示巡航接合;否则撤销 controls_allowed。 |
| ESC_51 | 50 Hz | 48 / 64 字节 | 四轮原始速度判断移动并形成主速度。 |
频率是检查配置,并非对每帧的实时 deadline 保证;计数器从字节 1 低四位、报文 CRC 从字节 0 读取。双车速这条链尤其要谨慎:ESC_51 形成一个速度源,ESP_21 提供独立速度源,曲率安全 helper 调用 speed_mismatch_check(),但不能用任一消息单独证明双源一致。
二、Gen2 替代 CRC 的真实边界
Gen2 替代 CRC 只影响 QFK_01、ESC_51 和 Motor_51。其逻辑是:先按整帧算标准 CRC;若开启替代标志,再按 28/60/44 字节前缀和另一组 salt 计算,只有前缀计算值等于字节 0 时才返回该值。因此标准整帧 CRC 仍可能被接受,前缀算法的接受范围则要结合车辆实报文确认。
源文档给出的三项离线探针把这条边界说得很具体:对 QFK_01 的 32 字节帧,写入前缀 CRC 后修改索引 30 仍被接受,修改索引 20 则被拒;写入整帧 CRC 的帧修改索引 30 被拒。原因是 QFK_01 前缀长度 28 含校验字节,因此前缀算法不保护尾部索引 28..31。该结论只针对本机构造的 QFK_01 报文,不能外推为 Gen2 所有消息都忽略尾部或真实 ECU 会产生这种变异。
三、TX 白名单与安全门
| 地址 | bus/长度 | 专属载荷检查 |
|---|---|---|
| 0x303 HCA_03 | 0/24 | 曲率、请求状态为 4 时的激活位、转向功率;共享曲率 helper。 |
| 0x14D ACC_18 | 0/32 | 加速度、HMS 停车状态、起步/保持位与 ACC 活动状态。 |
| 0x397 LDW_02 | 0/8 | 无本模式专属载荷分支。 |
| 0x25D KLR_01 | 0/8 与 2/8 | 无本模式专属载荷分支;仅 bus 2 项带 check_relay。 |
| 0x300 ACC_19 | 0/48 | 无本模式专属载荷分支。 |
| 0x26B TA_01 | 0/8 | 无本模式专属载荷分支。 |
通用 safety_tx_hook() 先按地址、bus、长度白名单过滤,再调用车型 TX 钩子,最终还受继电器故障阻断;静态转发只在 bus 0↔2 间,阻断目的总线中带 check_relay 的地址。TX 准入不是 ECU 已接受、仪表内容正确或原车 AEB 不受影响的证明。
ACC_18 的加速度量纲为 0.001 m/s²,活动范围 -3.5 至 2.0,未激活专用码为 3.01;停车请求 HMS=1(保持)或 4(起步)仅在允许控制时可发,0(无请求)与 5(坡道释放)可在退出后发。HCA_03 采用有符号曲率、请求位和功率三类输入,最大绝对曲率 29105、功率 125、名义频率 50 Hz;未请求转向时曲率必须为 0、功率必须为 0。一个关键细节:控制许可撤销后,带请求位的严格递减功率可作为退出时的降功率路径,不能把它误写成「失能后所有请求位帧必拒」。
四、自制硬件与插件边界
车型插件须提交 MEB 代际、DBC、接线位置和 CRC 变体的证据;未经确认时保持只读,不能仅按 ID.4/Born 名称自动授予 TX。感知/定位插件应分别报告 ESC_51 与 ESP_21 的来源、时间戳及健康;控制插件不能自行合并双车速再宣称冗余检查已通过。纵向控制插件应输出带语义的「加速度 / 保持 / 起步 / 坡道释放 / ACC 状态」,由可信任网关负责编码与状态序列,MCU 保留独立的字段检查和失联门。
HUD、TA 与 KLR 白名单帧缺专属载荷检查,插件网关需给这些帧最小模板、速率和所有权,不能开放任意原始 CAN 写入。验证顺序应包含 Gen1/Gen2 CRC 尾部变异、错长度/计数、双车速失配、按钮沿、失联时保持/释放与功率降阶。现有 test_volkswagen_meb.py 覆盖两代配置、计数/校验、双车速、曲率功率、加速度与停车状态;本机运行该模块 90 项,7 项跳过,其余通过,但它不代替上述 Gen2 前缀/整帧 CRC 尾部变异探针,也未验证目标硬件。
常见问题
Gen2 是不是「不校验尾部 CRC」?
不是。Gen2 替代 CRC 只影响 QFK_01、ESC_51 和 Motor_51,且先按整帧算标准 CRC;只有前缀计算值等于字节 0 时才返回该值,所以标准整帧 CRC 仍可能被接受。QFK_01 前缀长度 28 含校验字节,故前缀算法不保护尾部索引 28..31,这只是一个具体探针结论,不能外推为所有消息都忽略尾部。
两条车速报文能互相证明冗余吗?
不能。ESC_51 从四轮原始速度形成主速度,ESP_21 提供独立速度源,曲率 helper 调用 speed_mismatch_check(),但源文档明确不能用任一消息单独证明双源一致。控制插件也不能自行合并双车速再宣称冗余检查已通过。
失能后所有带请求位的转向帧都会被拒吗?
不是。源文档指出控制许可撤销后,带请求位的严格递减功率可作为退出时的降功率路径,相邻测试 test_power_without_control() 为此设了专门断言,不能把它误写成「失能后所有请求位帧必拒」。
按车型名 ID.4/Born 就能自动授予发送权限吗?
不能。车型插件须提交 MEB 代际、DBC、接线位置和 CRC 变体的证据,未经确认时保持只读;源文档明确不能仅按 ID.4/Born 名称自动授予 TX。网关接线位置还由指纹判断,不能从品牌名推断物理总线。
延伸阅读
- Ford panda safety mode:另一套 RX/TX 约束的对照 —— 横向比较不同品牌的 TX 白名单设计。
- Toyota panda safety mode —— 同为经典 CAN 车型的安全模式样本。
- Hyundai 经典 CAN panda safety —— 同一厂商多平台安全分支的对照。
- CAN FD 与经典 CAN 的安全模式差异 —— 承接 Gen2 长帧与长度约束的语境。
- 从使能到车轮:执行链上的八道门,以及它们各自不保证什么 —— 说明 TX 准入之后仍由 MCU 独立检查。
参考资料
- 项目 02 ——
openpilot-research/VOLKSWAGEN_MEB_PANDA_SAFETY_DEEP_DIVE.md(取用了 MEB 车型资格、RX 格式与使能链、Gen2 替代 CRC 边界、TX 白名单与安全门、硬件插件边界)。
说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。
更新记录
首次发布 2026-10-11 最近核对:2026-10-11
发表回复