结论:Hyundai 的车辆输入不能按「同品牌即同契约」理解:经典 CAN 把 Bus.pt 映射到物理 0、Bus.cam 映射到 2,而 CAN FD 的动力/相机总线取决于 CanBus(CP).ECAN/CAM,LKA 转向平台还会交换 A-CAN 与 E-CAN,所以不能把「E-CAN 总是 0」写死到线束或接口。另一个易误解点是按钮意图:recent_button_interaction() 检查的是最近八个报文样本而非固定八帧或 80 ms 窗口,无新样本时旧交互可能跨多个调用继续被视为「最近」。本文为固定源码快照 c8fb906 的静态阅读,未运行回放、未连接 CAN FD 硬件。
组件与关键函数
CarState.__init__() 根据车型 flags 选择档位、踏板、按钮报文及 DBC 枚举,建立八样本按钮队列、仪表速度采样器和控制参数;CarState.update() 做经典 CAN 车辆状态归一化,CAN FD 车型转给 update_canfd()。总线与解析器由 get_can_parsers()/get_can_parsers_canfd() 分别建立,CarInterfaceBase.update() 先更新解析器再归一化,并汇总 canValid、canTimeout。
| 入口 | 职责 | 边界 |
|---|---|---|
CanBus.__init__() |
依据 LKA 转向架构交换 A-CAN/E-CAN,并按安全配置数计算端口偏移 | 插件不能把「E-CAN 总是 0」写死 |
recent_button_interaction() |
判断八个最近巡航/主开关样本是否出现驾驶员启用意图 | 是样本数而非固定帧数或固定时间窗 |
create_button_events() |
由当前/上次状态合成按下和释放事件 | 中间报文过渡不会自动逐个转成事件 |
CarEvents.update() |
在 PCM 巡航启用上升沿,结合 blockPcmEnable 决定是否生成启用事件 |
仅上升沿且未被阻断时才生成 |
总线与解析健康
车型接口先用相机/动力 fingerprint 推导 LKA、备用按钮、档位及 SCC flags,状态解码依赖这些参数已经正确生成。经典 CAN 的两个解析器起初都不预注册报文;CAN FD 非备用按钮路径仅将 CRUISE_BUTTONS 以 1 Hz 预注册,源码注释说明它名义 50 Hz、但 ECU 可停止约半秒;备用按钮路径则不预注册该报文。其余读取 cp.vl[...] 会动态注册 DBC 报文,而 vl_all 自身不具有动态注册能力。
| 概念 | 确切含义 | 常见误读 |
|---|---|---|
| 动态注册时机 | 发生在本轮 CANParser.update() 之后 |
首轮此前到达的新报文不在缓存中,零初值不代表物理零测量 |
vl_all 本轮样本 |
每轮清空,只加入成功解码的帧;最近值 vl 保留到下次成功帧 |
不能用 vl 推断某值采自当前周期 |
canValid |
所有已注册报文的聚合活性/计数器判据 | 不是逐字段新鲜度证明 |
canTimeout |
总线空窗判据 | 不能说明某个 vl 值恰好来自当前周期 |
1 Hz 预注册只是调整该按钮报文的超时判据,不表示发送频率真的 1 Hz。
经典 CAN 状态路径
CLU11 决定 kph/mph,四轮 WHL_SPD11 通过基类 parse_wheel_speeds() 进入 vEgoRaw 和 KF1D;但 standstill 只比较左前与右后两轮,阈值为 12 * 0.03125,不是四轮均值。CLU15 仪表车速初始在第一次更新被采样,之后计数器从 0 增至大于 20 才再采一次,即正常每 21 次 CarState.update() 重采;非 Sorento 的英制仪表分支另作向下取整换算,再由基类接口对 vEgoCluster 做迟滞/低速截零,这不是轮速 KF1D 的原始速度。
SAS11 给方向盘角与角速度,MDPS12 给驾驶员/电机扭矩和临时转向故障。驾驶员施力调用基类计数去抖(阈值 5),方向灯则按灯状态延续 50 次调用,二者与 Toyota 的直接扭矩阈值不同。巡航来源由 CAMERA_SCC 决定:原车纵向读动力或相机 SCC11/SCC12,自控纵向则从动力 TCS13 得到 available/enabled,并明确这些字段不用于实际启停按钮判决。刹车 DriverOverride==2 包含混动/电动车驾驶员再生制动;油门和档位再按 ICE/EV/HYBRID/FCEV flags 分报文。USE_FCA 决定原车 AEB/FCW 来源,HAS_BSM 才读 LCA11。相机 LKAS11 和动力 CLU11 被浅拷贝作为控制器构帧模板,它们是解析器最新缓存,状态函数没有单独验证每个字段的年龄。
CAN FD 状态路径
CAN FD 的档位消息在 ACCELERATOR、GEAR_ALT、GEAR_ALT_2、GEAR_SHIFTER 中选;踏板消息也分 EV/HYBRID/其他。CRUISE_BUTTONS_ALT.DISTANCE_UNIT 决定仪表单位,轮速四轮全低于阈值才视为停止;转向/扭矩/故障分别来自 STEERING_SENSORS 与 MDPS。TCS.ACCEnable 决定巡航可用,自动纵向用 TCS.ACC_REQ 作启用状态;原车纵向则按 CANFD_CAMERA_SCC 从相机或动力 SCC_CONTROL 读取启用、停止和设定速度。EV 平台另以 MANUAL_SPEED_LIMIT_ASSIST.MSLA_ENABLED 标记 nonAdaptive,与自适应 ACC 启用不是同一个概念。LKA 转向车还缓存相机 CAM_0x2a4/0x362 供后续 LFA 抑制帧保留原字段,同样没有逐字段新鲜度检查。
按钮历史、边沿和下游
经典 CAN 从 CLU11、CAN FD 从选定 CRUISE_BUTTONS 报文的 vl_all 取得本轮可能多条按钮样本,追加到最长 8 条的队列。recent_button_interaction() 检查最近八个报文样本是否有 RES/SET/CANCEL 或任意主开关非零;无新样本时队列不前进,旧交互可能跨多个调用继续被视为「最近」。另一方面,buttonEvents 只比较队列本轮前的末尾与追加后的末尾,一轮内多个中间跳变不会逐个变成事件。blockPcmEnable 取该意图判据的反值,CarEvents 仅在 PCM 巡航由未启用变启用且未被阻断时生成 pcmEnable。CAN FD 还保留按钮 COUNTER,控制器构造原车巡航取消/恢复按钮候选时以 CS.buttons_counter + 1 作为输入;缓存字段是最近成功解析值,能构帧不等于 ECU 已接受。
新硬件与插件契约
车型输入插件应明确声明 DBC、物理总线与线束拓扑、每个报文的原始样本时间、校验/计数器结果和有效期。驾驶员按钮需要同时提供逐条边沿序列与当前状态;blockPcmEnable 的意图窗口要用样本年龄或实际时间约束,不能让无新帧的旧按钮无限代表当前意图。原车 AEB/FCW、BSM、刹车与转向故障必须保留各自来源和缺测状态,无法验证的关键输入不能默认为安全。非上车验收应按经典 CAN/CAN FD、LKA/LFA 线束、相机/动力 SCC、四类动力踏板、备用按钮及档位组合建立参数矩阵,并注入首轮报文、按钮突发/断流、单轮速度异常、SCC 丢失、相机缓存过期与总线映射错误。
常见问题
Hyundai 同品牌车型的 CAN 总线映射是一样的吗?
不一样。经典 CAN 与 CAN FD 的物理总线不同,LKA 转向平台还会交换 A-CAN 与 E-CAN 并叠加安全配置偏移,所以不能把「E-CAN 总是 0」写死,需按线束与 DBC 核对。
recent_button_interaction() 是固定八帧窗口吗?
不是。它检查最近八个报文样本,既不是固定八帧也不是固定 80 ms;无新样本时队列不前进,旧交互可能跨多个调用仍被视为「最近」。
1 Hz 预注册 CRUISE_BUTTONS 代表该报文真的 1 Hz 吗?
不代表。预注册只是调整该按钮报文的超时判据;源码注释说明它名义 50 Hz,但 ECU 可停止约半秒。
能构出取消/恢复巡航帧就代表 ECU 已接受吗?
不代表。控制器用的是缓存字段(如 CS.buttons_counter + 1)与最近成功解析值,能构帧不等于 ECU 已接受,也不是硬件执行确认。
延伸阅读
- 同一个「转向灯」在三家车厂是三种实现:车辆状态归一化的坑 —— 承接本文品牌间信号实现差异的来源。
- CAN 报文解析的「健康位」在说什么:校验、计数器与总线空窗 —— 解释本文
canValid/canTimeout的确切含义。 - 车载信号为什么会说谎:TTL、源时间与 500 ms 新鲜度阈值 —— 与本文「
vl值不保证采自当前周期」相互印证。 - 车辆消息字段契约:CarState、CarControl、CarOutput 与 CarParams —— 说明本文归一化结果进入的消息结构。
- ECU 探测与 ISO-TP:在场、固件候选与可执行是三件事 —— 另一处「报文来源与身份需分层校验」的例子。
参考资料
- 项目 02 ——
openpilot-research/HYUNDAI_CARSTATE_CLASSIC_CANFD_INPUT_DEEP_DIVE.md(取用了组件索引、总线与解析健康、经典 CAN/CAN FD 状态路径、按钮边沿与下游、插件契约)。 - 项目 02 ——
openpilot-research/CAR_MESSAGES_FIELD_CONTRACT_DEEP_DIVE.md(仅用于确认归一化结果进入的消息结构位置)。
说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。
更新记录
首次发布 2026-10-11 最近核对:2026-10-11