Hyundai CAN FD safety:LKA 与 LFA 的总线矩阵差在哪

作者:

在

结论:Hyundai CAN FD safety 的「模式」不是一个开关,而是LKA/LFA × 纵向/非纵向 × 按钮格式 × SCC 来源的组合,每一组对应不同的 RX 检查表与 TX 白名单。纵向(LONG)只在 ALLOW_DEBUG 构建下生效:无该宏的构建强制 hyundai_longitudinal=false,因此上层设置 openpilotLongitudinalControl 不会自动改变固件事实。此外,替代转向地址是条件性接口不匹配,不能靠扩充普通插件的 CAN 发送权限来规避。

车型资格与总线编号:LKA 与 LFA 是两套拓扑

资格判定在 CarInterface._get_params():根据相机指纹判定 LKA/LFA,确定按钮、SCC 来源和 safetyParam。源文档特别强调,alphaLongitudinalAvailable、实际启用和 ECU 静默成功是三个不同状态,不能混为一谈。

总线编号由 CanBus.__init__() 决定,而且两种模式恰好相反:

模式 A-CAN E-CAN 相机
LKA 0 1 2
LFA 1 0 2

相机总线固定为 2,再叠加多设备偏移。这里要注意:表中 bus 号是单个 panda safety 实例的本地编号,多 panda 场景的偏移由上层配置处理,不能把逻辑编号硬编码成自制板引脚。

模式与总线矩阵

hyundai_canfd_init() 用 LKA/LFA、LONG、替代按钮、相机 SCC 和替代转向地址选择 RX 检查与 TX 白名单。下面这张表是整篇的核心:

模式 动力总线 / 原车 SCC RX 关键 TX 白名单
LKA 非纵向 1 / 1 0x50+0x2A4 或替代 0x110+0x362 在 bus 0;0x1CF 在 bus 1
LKA 纵向 1 / 不检查原车 SCC LKA 0x50+0x2A4 在 bus 0;LFA、HUD、SCC、若干 ADRV 与 0x730 在 bus 1;0x51 在 bus 0
LFA 雷达 SCC 非纵向 0 / 0 LFA、HUD、0x1A0 在 bus 0;0x1CF 在 bus 2
LFA 相机 SCC 非纵向 0 / 2 上行相同,另有 0x160 在 bus 0
LFA 雷达 SCC 纵向 0 / 不检查原车 SCC LFA、HUD、SCC、0x160、0x7D0 在 bus 0;0x1CF 在 bus 2
LFA 相机 SCC 纵向 0 / 不检查原车 SCC LFA、HUD、SCC、0x160 在 bus 0;0x1CF 在 bus 2

表头里的「原车 SCC RX」指的是 safety 必需 RX 检查与巡航状态消费,不是该总线上物理帧是否存在。几个细节:LKA 两种分支的按钮 RX 固定使用 0x1CF;LFA 分支依据替代按钮标志,选择动力总线上的 0x1CF 或 0x1AA。所有配置均监视油门备选组、制动 0x175、轮速 0xA0、驾驶员扭矩 0xEA——油门三种地址是同一检查组的备选格式,不等于三种都必须到达。

构建门:LONG 参数只在 ALLOW_DEBUG 下生效

hyundai_common_init() 只在 ALLOW_DEBUG 下读取 LONG 参数;无该宏的构建强制 hyundai_longitudinal=false。这是一道编译期门,而不是运行期开关。

校验侧码分布同样要记住:hyundai_canfd_get_counter() 对 8 字节普通按钮取字节 1 高四位的计数,其余帧取字节 2;校验值取前两字节。hyundai_common_canfd_compute_checksum() 对字节 2 起的载荷与地址执行 CRC16,24/32 字节分别异或长度常数。特别之处在于:按钮 RX 明确忽略 checksum,但仍检查计数。

权限与失效边界

这些边界在源文档里逐条列出,直接决定「白名单里有这帧」和「这帧会被执行」之间的差距:

  1. 按钮:普通按钮 TX 0x1CF 仅允许「原车巡航已接合时 Cancel」或「controls_allowed 时 Resume」。替代按钮 RX 0x1AA 不在 TX 白名单中;但设置替代按钮并不会从全部 TX 表删除 0x1CF,不能误写成「该模式彻底禁止发送任何按钮帧」。
  2. 转向:非纵向 LKA 对 0x50/0x110 检查扭矩;LKA 纵向及全部 LFA 对 0x12A 检查。共享扭矩门限制最大 270、实时变化 112、每帧增加 2/减少 3,并含驾驶员反扭矩与转向请求位节拍。
  3. SCC:非纵向 LFA 的 0x1A0 仅允许 ACCMode=4 且 aReqRaw/aReqValue 同时为零;该钩子未逐位审核 0x1A0 的其它信号。
  4. 诊断与附属帧:0x730/0x7D0 的 8 字节数据仅可为 02 3E 80 00 00 00 00 00,且仅相应模式在白名单中。0x51、0x160、0x1EA、0x200、0x345、0x1DA、HUD 和相机抑制帧没有同等级的专属载荷校验。
  5. 转发:Hyundai CAN FD 没有专属 fwd 钩子,使用通用 0↔2 转发规则及 check_relay 静态阻断;bus 1 不在该通用转发对内。

第 4 条尤其重要:白名单准入不等于 ECU 接受,也不等于 AEB 不受影响。缺少逐字段校验的帧,只能保证「被允许发送」,不能保证「被接受后效果正确」。

替代 LKA 与纵向的跨层组合

CarInterface._get_params() 可从相机指纹识别 0x110 替代 LKA,并把该标志传到 safety 参数;若有 ADAS ECU 且未被其他条件禁止,纵向能力仍可能开启。此时主机侧 create_steering_messages() 继续生成 0x110 LKAS_ALT,create_suppress_lfa() 继续生成 0x362。

但 hyundai_canfd_init() 的纵向 LKA 分支固定选择普通 0x50/0x2A4 白名单,而非按替代标志切换;原测试只有普通 LKA 纵向类,没有替代 LKA 纵向类。离线探针确认:同一替代标志加 LONG 后,调试构建拒绝 0x110/0x362、接受 0x50/0x2A4;无调试宏构建则忽略 LONG,采用非纵向替代 LKA 白名单。也就是说该组合在两类构建中的失败形态不同,均不能仅凭主机 CarParams 宣称纵向或替代转向可执行。

源文档对此的定性是关键:这是条件性接口不匹配,不应通过扩充普通插件的 CAN 发送权限来规避;正确做法是先确定该车型/纵向组合是否应被允许,再联合修订主机消息选择、固件白名单、转向限制和回归测试。现有 test_hyundai_canfd.py 在测试基座默认编译 ALLOW_DEBUG;本机运行该模块共 981 项、117 项跳过,跳过项及未覆盖的替代 LKA 纵向组合不能视为验证通过。

常见问题

LKA 和 LFA 的总线编号为什么会相反?

因为 CanBus.__init__() 明确按模式分配:LKA 时 A-CAN/E-CAN 为 0/1,LFA 时为 1/0,相机固定为 2。这是逻辑编号,多 panda 场景的偏移由上层配置处理,不能直接当作物理引脚。

启用纵向控制后,固件就一定允许吗?

不一定。hyundai_common_init() 只在 ALLOW_DEBUG 下读取 LONG 参数,无该宏的构建会强制 hyundai_longitudinal=false。所以上层设置 openpilotLongitudinalControl 不会自动改变固件事实,alphaLongitudinalAvailable、实际启用和 ECU 静默成功是不同状态。

0x1A0 在白名单里就可以自由发送吗?

不可以。非纵向 LFA 的 0x1A0 仅允许 ACCMode=4 且 aReqRaw/aReqValue 同时为零;纵向则分别调用共享加速度检查。而且该钩子并未逐位审核 0x1A0 的全部其它信号。

为什么设置「替代按钮」不等于禁用 0x1CF?

因为替代按钮 RX 0x1AA 虽不在 TX 白名单,但设置替代按钮并不会从全部 TX 表删除 0x1CF。现有 test_button_sends() 构造的是替代格式 0x1AA,因此没有证明 0x1CF 被禁用。

延伸阅读

参考资料

  • 项目 02 —— openpilot-research/HYUNDAI_CANFD_PANDA_SAFETY_DEEP_DIVE.md(取用了模式与总线矩阵、构建门、权限与失效边界、替代 LKA 与纵向跨层组合)。
  • 项目 02 —— openpilot-research/CAR_PROTOCOL_IMPLEMENTATIONS.md(仅用于确认 Hyundai CAN FD 分支与 set_safety_hooks() 的注册位置)。

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

更新记录

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

评论

发表回复

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