标签: CAN FD

  • Ford 构帧:CAN FD 校验不是 CRC,名义频率不是负载预算

    结论:Ford 的 fordcan.py 只负责生成候选帧:横向、纵向、界面与按钮四类构帧函数把 CarControl 变成带计算器/校验的 CAN 载荷,是否真正上总线由独立固件白名单与继电器门裁决。CAN FD 校验 calculate_lat_ctl2_checksum() 是「原始位求和取反」的专用算法,不是通用 CRC;而函数注释里的 33/20/50/5/1 Hz 只是名义频率,不能当作总线最大负载预算。

    本文基于固定源码快照,从 fordcan.py 的公开构帧函数出发,追踪 CarController.update() 与 panda 安全钩子,属于静态结构分析,未连接车辆或发送 CAN。完整固件侧规则见 Ford panda safety 专题,本文只解释主机侧「构帧了什么、依赖了什么」。

    构帧函数与报文契约

    四类输出分工明确:横向有 create_lka_msg()(空 Lane Assist)、create_lat_ctl_msg()(经典 CAN 曲率与路径)、create_lat_ctl2_msg()(CAN FD 曲率、计数、校验);纵向是 create_acc_msg();界面与按钮是 create_acc_ui_msg()、create_lkas_ui_msg()、create_button_msg()。它们只产出候选帧,不提供安全许可。

    函数 控制器调用 输出与关键限制
    create_lka_msg() 33 Hz 名义节拍 对 Lane_Assist_Data1 传空信号字典;panda 要求其动作字段必须为零,不能当额外转向通道
    create_lat_ctl_msg() 经典 CAN 分支 构造 LateralMotionControl,LatCtl_D_Rq 随横向活动位切换;曲率取限幅后符号反转值
    create_lat_ctl2_msg() CAN FD 分支 先以校验字段零值打包同名帧,算完校验再以实际 CAN.main 构帧;计数器按节拍 modulo 16,当前只用 mode=0/1
    create_acc_msg() 纵向控制分支 ACCDATA 带加速度、油门、预充/减速、停车与目标速度;仅自控纵向配置下按名义 50 Hz 发送
    create_acc_ui_msg() 5 Hz 或 UI 变化 从相机 ACCDATA_3 复制多项字段,再覆盖 TJA 状态、自控纵向显示与 FCW 告警
    create_lkas_ui_msg() 1 Hz 或 UI 变化 从相机 IPMA_Data 复制配置/告警字段,再改写车道线状态与握盘提示
    create_button_msg() 按钮分支 从主总线 Steering_Data_FD1 复制开关状态,只覆盖 cancel/resume/TJA 三个位;取消和恢复同时送 camera/main,TJA toggle 只送 camera

    CanBus 定下总线映射:main=offset、radar=offset+1、camera=offset+2,基类以 len(CP.safetyConfigs) 推导 4 路一组的偏移。不能硬编码所有车辆为 bus 0,偏移取决于安全配置数量。

    CAN FD 校验:专用算法,不是通用 CRC

    calculate_lat_ctl2_checksum() 从已编码的 8 字节中抽取曲率、曲率率、路径角、路径偏移的原始位值,加模式和计数器,再取 0xFF - (sum & 0xFF)。它与固件侧从相同位置提取字段的做法对应,所以构帧器依赖所选 DBC 的位布局与物理总线映射——把该函数当成跨平台字节数组插件会失效。

    两步打包的原因也在这里:先打包零校验占位帧是为了让校验字段取值稳定,计算后再用实际 CAN.main 构帧。计数器和校验只保证字节自洽,不保证 ECU 接受,也不替代安全门。

    环节 做法 边界
    校验算法 原始位求和后取 0xFF - (sum & 0xFF) 专用算法,非通用 CRC;依赖 DBC 位布局
    计数器 按发送节拍 modulo 16 节拍来自 100 Hz 控制帧计数与状态变化时的额外发送
    模式字段 当前只用 mode=0/1 不代表其余模式在实车被验证

    横向与纵向:控制器负责限幅,构帧器不查许可

    CarController 在横向发送前计算当前曲率、按车速施加曲率误差/速率限制,然后对 CAN FD 与经典 CAN 分别构帧。两条路径的 path_offset、path_angle、curvature_rate 在当前调用中都传零——源码中对多项式完整操控的描述不是当前已启用能力。

    纵向方面,自控纵向的 gas 和 accel 分开限幅;若非 longActive 或油门低于门槛,油门设为中性原始值。制动预充/减速请求根据坡度补偿后的加速度在 >0.3 与 <0 之间迟滞,位状态由控制器记忆。构帧器不自行检查这些状态是否与 panda 许可一致:限幅是主机策略,许可在固件。

    两种 UI 构帧和按钮构帧从 CarState.update() 缓存的原车解析字典复制字段。字典存在不等于所依赖 CAN 帧足够新鲜;插件接口应保留总线、时间戳和健康信息,并在台架验证失联后的透传行为。panda 对 ACCDATA_3/IPMA_Data 有白名单但无逐字段专属限制,对按钮仅专门约束 cancel/resume 权限。

    名义频率不能当负载预算

    fordcan.py 的 docstring 所列 33/20/50/5/1 Hz 是名义频率,实际来自 100 Hz 控制帧计数和状态变化时的额外发送。create_button_msg() 自身写 10 Hz,但 cancel 可以随每次控制更新发送。不能拿函数注释当作总线最大负载预算。

    新硬件或插件化验收至少要分别验证:车型 flags、CAN FD/经典 DBC、总线偏移、帧长度、计数器/校验、原车 UI 字段的新鲜度,以及 panda TX 拒帧。Ford 构帧插件只能交付候选帧;白名单、曲率/纵向限值及原车 AEB 禁止位必须继续由独立安全层执行。

    固定快照附带两份离线探针用于核对契约:原版 DBC 构帧探针把经典 CAN 与 CAN FD 两种格式各验证一次,界内帧通过、主机速度突变候选被拒;此前的手工帧探针用正的曲率 CAN 单位测试对称安全限值,但控制器实际在调用 fordcan 前将曲率取负,原版探针按该符号链送入 CANPacker,并包含 DBC 精度位与 CAN FD 校验。需要记住边界:它未覆盖 CarController.update() 的前置测量裁剪、状态迁移或车辆 ECU 响应。

    常见问题

    calculate_lat_ctl2_checksum 是 CRC 吗?

    不是。它从已编码的 8 字节中抽取曲率、曲率率、路径角、路径偏移的原始位值,加模式和计数器,再取 0xFF - (sum & 0xFF),是与固件同位置取值对应的专用算法,不是通用 CRC,也不能当作跨平台字节数组插件。

    Ford 的 CAN 总线一定是 bus 0 吗?

    不是固定值。CanBus 用 main=offset、radar=offset+1、camera=offset+2 映射,偏移由基类按 len(CP.safetyConfigs) 以 4 路一组推导,所以不能硬编码所有车辆为 bus 0。

    控制器已经限幅,为什么还要固件安全门?

    因为构帧器不检查状态是否与 panda 许可一致。主机侧只负责曲率/纵向限幅与状态记忆,白名单、曲率与纵向限值、原车 AEB 禁止位仍由独立固件层裁决;构帧器只交付候选帧。

    函数注释里的发送频率能当负载预算吗?

    不能。33/20/50/5/1 Hz 是名义频率,实际来自 100 Hz 控制帧计数和状态变化时的额外发送;create_button_msg() 虽写 10 Hz,cancel 仍可随每次控制更新发送。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/FORD_CAN_FRAME_CONSTRUCTION_CONTRACT_DEEP_DIVE.md(取用了 fordcan.py 构帧函数契约、CAN FD 校验算法、总线映射与名义频率边界)。
    • 项目 02 —— openpilot-research/FORD_PANDA_SAFETY_MODE_DEEP_DIVE.md(仅用于确认固件侧白名单与限值边界,未取用其未公开内容)。

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

    更新记录

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

  • Hyundai 车辆输入:经典 CAN、CAN FD 与按钮意图的边界

    结论: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 已接受,也不是硬件执行确认。

    延伸阅读

    参考资料

    • 项目 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

  • BYD Atto 3 档案:Chassis 与 Private 双总线分工

    结论:这份档案的对象是一台 2024 年款、右舵出口版的 BYD Atto 3(元 PLUS EV)。它的数据特征是双总线分工:在 P13 摄像头连接器处接入后,Chassis CAN(引脚 4/8)为 500 kbit/s 经典 CAN、8 字节帧,承载转向、车速、踏板、挡位等整车状态,读与写都在这里;Private CAN(引脚 3/7)为 CAN-FD、数据段近 2 Mbit/s,承载摄像头、前向雷达与约 72 个来源未确认的经典格式 ID。整车消息在发送前需补一个字节校验,纵向与横向命令只允许三条报文。以下所有结论仅来自这一台车,中国国内版本与其他年款可能不同。

    车辆与适用范围

    源文档明确:全部数据来自一辆车——2024 年款右舵出口版 Atto 3;并把「换车前的检查项」单列一节。以下范围只对应这一辆。

    项 内容
    车型 BYD Atto 3 / 元 PLUS EV,2024 年款,右舵出口版(VIN 世界厂商标识 LGX)
    年款 / 市场版本 2024 右舵出口版;中国国内版本与其他年款可能不同(源文档明示)
    ECU / 改装状态 P13 摄像头连接器处旁接;以红熊猫板作 CAN 接口;无原厂设备,因此无 IMU,改用 CAN 桥接
    采集跨度 源文档未给出日志时长或帧数;给出整车质量 1750 kg、轴距 2.72 m、转向比 19.8
    适用范围 仅这一台 2024 右舵出口车;换车须重新测量连接器(BYD 用过两个摄像头供应商,连接器不同)

    总线与寻址

    数据来自 P13 摄像头连接器,共 8 个腔位、6 个接线。两条 CAN_H 同为粉色、两条 CAN_L 同为紫色,源文档要求按引脚位置而非颜色识别总线。

    项 内容
    Chassis CAN 引脚 4/8;经典 CAN,500 kbit/s,8 字节帧;本系统的读与写都在此
    Private CAN 引脚 3/7;CAN-FD,数据段近 2 Mbit/s;承载摄像头、雷达与约 72 个来源未确认的经典格式 ID
    寻址 / 帧格式 整车消息为经典 11 位 ID 格式;私有总线为 FD 帧,含 32 字节与 64 字节两类
    终端 在旁接点处为 Chassis CAN 增加终端,因为接入设备会在摄像头连接器处断开总线
    供电 引脚 1 = 摄像头地,引脚 2 = IG1(受控 12V);点火状态也可从 CAN 推断

    已解码信号

    下表抽取源文档中带明确报文、缩放或位域的信号。位置与解码保留原文写法;证据一列注明来源,凡源文档标注为「未确认」的均原样保留。

    信号 位置(报文 ID / 字段) 解码 证据
    转向角 STEER_MODULE_2 0x11F / STEER_ANGLE_2 0.1 度 / LSB 源文档状态解码表
    驾驶员力矩 STEERING_TORQUE 0x1FC / DRIVER_TORQUE 0.1 Nm / LSB;用于人工接管判定,阈值 18 Nm 源文档;符号正值为左
    EPS 电机力度 0x1FC / MAIN_TORQUE 电机输出,非驾驶员输入 源文档
    EPS 状态 0x1FC 低半字节(位而非枚举) bit0 LKS_PREPARED、bit1 CRUISE_ACTIVATED、bit3 恒 1;0x318 恒 0xFF 源文档;状态 11 需 0.5 s 去抖
    车速 WHEELSPEED_CLEAN 0x1F0 16 位原始计数,0.0713 km/h 每计数 源文档
    单轮转速 WHEEL_SPEED 0x122 / WHEELSPEED_BR 14 位;bit 62 为有效位 源文档
    挡位 / 点火 DRIVE_STATE 0x242 任意有效挡位即视为点火接通 源文档
    制动状态 DRIVE_STATE 0x242 / BRAKE_PRESSED 已去抖;须与安全模块读同一信号 源文档
    油门 PEDAL 0x342 / GAS_PEDAL 不采用 DRIVE_STATE.RAW_THROTTLE 源文档
    转向灯 STALKS 0x133 — 源文档
    方向盘按钮 PCM_BUTTONS 0x3B0 SET / RES / LKAS / 车距 / ACC 开 源文档
    巡航状态 ACC_HUD_ADAS 0x32D / ACC_STATE 2 可用、3 与 5 已启用、7 错误(摄像头总线) 源文档
    偏航角速度 YAW_RATE 0x222 / YawRate 0|12@1+ × 0.002133 − 2.094 rad/s;另含偏置字段需相减 源文档 IMU 桥接节
    平面加速度 AXAY 0x223 / Ax、Ay 0|12@1+ 与 24|12@1+,× 0.027167 与 × 0.027127 m/s² 源文档;Ay 需反号
    雷达目标 私有总线 0x280–0x289 轨道含 TRACK_ID、LONG_DIST、LAT_DIST、VLEAD 等 源文档;COUNTER12_1/2 字段已修正

    读取方法与注意事项

    接入前先做识别。源文档指出:查询固件版本要用 0xF195(SUPPLIER_SOFTWARE_VERSION),因为 BYD 的 ECU 拒绝本平台默认的 0xF188;总线 0 上有 24 个 ECU 应答 0xF195,其中六个返回固件版本(摄像头、制动/IPB、EPS、前向雷达、驱动单元、安全气囊),版本载荷是 6 个原始字节而非 ASCII。摄像头 ECU 不应答固件查询,须设为非必需。

    发送前必须补校验:Chassis CAN 上被签名的 12 条消息,其校验是最后一字节,data[7] = (~sum(data[0:7])) & 0xFF;本系统只发送三条——转向角命令 0x1E2、HUD 帧 0x316、纵向命令 0x32E。0x1E2 按 50 Hz 发送(每两帧中的一帧为 100 Hz),而原车摄像头是 33 Hz。转向命令须在启用期间持续发送,包括静止时也要发请求位为 0 的空闲帧——出现间隙会让 EPS 进入状态 11 并闭锁,单靠随后发 STEER_REQ = 1 无法解除。

    私有总线的完整性另有一套:每条帧的第 0 字节是校验,形式为 CRC8(poly=0x1D, init=0x00, data[1:32]) XOR K[id];64 字节 ID 的两半各自独立保护,K 是逐报文常量、并入 init/xorout/DataID,不是 CAN ID 的函数,需从本车日志逐 ID 采集。另需注意:源文档修正了雷达 DBC 中两个字段的解读——COUNTER12_1/COUNTER12_2 并非 12 位计数器,第 0 与第 32 字节是帧校验、计数器是第 1 与第 33 字节的低半字节。

    还有一处几何修正:雷达 LONG_DIST 以后轴中心(ISO 8855 车体坐标系)为原点,而非传感器面,需减去 3.60 m(前悬 885 mm + 轴距 2720 mm)后才是相对车头距离;不修正会让每个前车读数偏远 3.6 m,修正后雷达与视觉在 12 m 内一致到 0.5 m 以内。

    证据等级与边界

    本文属于单台实车观测:报文、缩放与位域都在源文档里按车辆实测列出,并标注了去抖时间、保活与几何修正等工程条件。但证据范围的边界同样清楚:源文档在末尾单列一节强调,全部数据来自一辆 2024 右舵出口版;中国国内版本与其他年款可能不同,BYD 还使用过两个摄像头供应商、连接器不同,换车必须重新测量连接器。此外,若用不带继电器直通的旁接线束,本系统运行时没有硬件回退;源文档建议使用带直通继电器的线束盒。

    一处不确定性必须原样保留:EPS 掉线前的状态字段被某份未合并的草稿 DBC 命名为 TORQUE_TEMP_FAILED(取值 1 "TooLarge"、2 "TooFast"),但源文档明确——没有 BYD 官方文档、没有 EPS 诊断码、也没有其他分支能确认该命名,应视为未确认;文档给出的转角上限结论并不依赖该命名。另据源文档,ABS/ESP 侧的转向限值表现为一个恒定的偏航率:EPS 在乘积约 3155 及以上放弃车道保持,故取 3000 留余量,不要抬高到 3155 或观测均值 3578。

    关于安全访问,源文档未提供任何绕过方法,且不建议尝试;本文只整理源文档记录的可读信号与发送约束。

    常见问题

    为什么查询固件版本要用 0xF195 而不是 0xF188?

    因为源文档记录 BYD 的 ECU 会拒绝 0xF188(本平台默认的那个)。改用 0xF195 后,总线 0 上有 24 个 ECU 应答,其中六个返回固件版本;版本载荷是 6 个原始字节而非 ASCII,摄像头的 MPC ECU 不应答、须设为非必需。

    Chassis CAN 上发送报文要注意什么?

    两条硬约束。其一,被签名的 12 条消息必须补末字节校验 data[7] = (~sum(data[0:7])) & 0xFF;其二,本系统只允许发送 0x1E2、0x316、0x32E 三条。转向命令还要 50 Hz 连续发送、静止时发请求位为 0 的空闲帧,避免 EPS 进入状态 11 并闭锁。

    雷达距离为什么要减 3.6 m?

    因为 LONG_DIST 的原点是后轴中心(ISO 8855 车体坐标系),不是传感器面。需减去前悬 885 mm 加轴距 2720 mm 共 3.60 m 才得到相对车头距离;不修正每个前车会偏远 3.6 m,修正后在 12 m 内与视觉一致到 0.5 m 以内。

    TORQUE_TEMP_FAILED 这个信号名可信吗?

    不可信。源文档明确:该命名来自一份未合并的草稿 DBC,没有 BYD 文档、没有 EPS 诊断码、也没有其他分支能确认,应视为未确认。文档给出的转角上限(约 3000 / 车速)并不依赖这个命名。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/shemps-byd-atto3/README.md(本项目车型档案主来源:线束与总线拓扑、指纹、状态解码、校验、横向与纵向控制、雷达与 IMU 桥接、适用性边界)。

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

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

  • Hyundai 接口的 CAN FD 判别、能力位与 ECU 静默恢复边界

    结论:Hyundai 车型接口的能力位是软件决策,不等于目标 ECU 已按请求改变状态。接口按指纹与固件把平台分成 CAN FD 与经典 CAN 两条判别路径,再由相机总线上是否出现 0x50 或 0x110 决定 LKA 还是 LFA 转向,并据此交换 A-CAN / E-CAN;纵向 ECU 静默只在「自控纵向且非相机 SCC」路径发起,且通用 disable_ecu() 的返回布尔值没有在 Hyundai init() 中被汇总,card 在其返回后直接写 ControlsReady。固定快照基线为 c8fb906,未执行 UDS 请求或实车验证。

    入口与函数链

    CarInterfaceBase.get_params() 先装载平台规格和静态 flags,再调用 Hyundai _get_params(),最后计算车辆惯量与轮胎刚度。Hyundai _get_params() 负责分 CAN FD / 经典 CAN,由指纹与固件推导动态标志、纵向能力和 safety 配置。HyundaiFlags 记录车型 / 检测特征,HyundaiSafetyFlags 编码给 MCU 的控制策略,二者不可互换。

    组件 职责
    CarInterfaceBase.get_params() 先装载平台规格与静态 flags,再调用 Hyundai _get_params(),最后算惯量与轮胎刚度。
    CarInterface._get_params() 分 CAN FD / 经典 CAN,由指纹与固件推导动态标志、纵向能力与 safety 配置。
    CanBus.__init__() / CanBusBase.__init__() LKA / LFA 使 A-CAN / E-CAN 互换;安全配置数量决定四路总线偏移。
    CarInterface.init() / deinit() 条件性发 UDS 通信控制禁发 / 恢复请求。
    disable_ecu() 先进入扩展会话,再请求通信控制;返回布尔值,但上层 Hyundai 接口未消费。
    card.controls_update() 首次进入控制时调用接口 init(),其返回后写 ControlsReady。

    CAN FD:相机地址驱动的分支

    _get_params() 先由 CanBus(None, fingerprint).CAM 找相机总线;该总线上出现 0x50 或 0x110 时判为 LKA 转向,否则判为 LFA。随后 CanBus(None, fingerprint, lka_steering) 重新计算 A-CAN / E-CAN:LKA 平台与 LFA 平台交换两条总线。

    CanBusBase 在指纹阶段按非空 bus 最大编号推导四路偏移;运行阶段 CanBus(CP) 则按 safetyConfigs 数量算偏移。因此识别出的拓扑必须与实际 panda / 线束配置一致,不能由车型名称单独推断 E-CAN 号。CAN FD 的 0x1ba、0xFA、0x1cf、0x130、0x40 等地址参与 BSM、混动、备用按钮和档位报文推断。

    LKA 平台若相机有 0x110,再加 ALT LKA 标志;非 LKA 平台在没有 CANFD_RADAR_SCC 静态标志时,推导相机 SCC。CANFD_NO_RADAR_DISABLE 会关掉实验纵向可用性;LKA 平台若 car_fw 未列出 ADAS ECU,也会关掉。这些是保守能力判据,但空固件列表与「已证明车辆无 ADAS ECU」不能画等号。CAN FD 默认以 hyundaiCanfd 作为执行 safety;若推导出的 E-CAN 编号至少为 4,则在安全配置列表前插入一个 noOutput,由后一个配置承载 Hyundai safety 参数。

    经典 CAN、共同能力与雷达状态

    经典 CAN 在动力总线 0 / 相机总线 2 上按地址判断 BSM、LFA 图标、FCA 报文及 LDA 按钮。LEGACY 平台选 hyundaiLegacy safety,因为旧报文缺计数 / 校验;其他经典平台选 hyundai,相机 SCC 再追加相应 safety 参数。LEGACY 或 UNSUPPORTED_LONGITUDINAL 会使实验纵向不可用。

    两条路径共同设置 0.1 秒转向执行延迟、0.4 秒限制计时器、扭矩标定,以及 ALT_LIMITS / ALT_LIMITS_2 安全标志;后者还使车型 dashcamOnly。特定平台型号另改延迟或设 dashcamOnly。

    概念 边界说明
    openpilotLongitudinalControl 等于 alpha_long and alphaLongitudinalAvailable,pcmCruise 取其反值;只有真正启用时才给 MCU 设 LONG。
    radarUnavailable 仅在 CAN 指纹 bus 1 有雷达起始地址且平台 DBC 提供 Bus.radar 时为假;不是实时雷达在线或诊断静默结果。
    被动回退 card 可因开关关闭、无控制器或 dashcamOnly 把接口设为被动并把安全模式改为 noOutput。
    动力类型 EV / HEV / FCEV 映射为安全参数,但不改变上述能力判定层级。

    车型参数里的 LONG 不是最终上路授权:card 仍可能把接口设为被动并把安全模式改为 noOutput。

    ECU 静默与恢复的实际边界

    CarInterface.init() 仅在自控纵向且非相机 SCC 路径静默纵向 ECU:经典 CAN 及普通 CAN FD 目标为 0x7d0,LKA 转向 CAN FD 改为 E-CAN 的 0x730。默认通信控制请求带 UDS 0x28 的 suppress-positive-response 位;它表示请求 ECU 不发送正响应,不是已经收到确认。若 CANFD_ENABLE_BLINKERS 置位,接口另对 0x7b1 发独立请求;该 flag 在本快照的静态平台项中未见设置。

    通用 disable_ecu() 先要求扩展会话的有效前缀响应,随后以空期望前缀调用通信控制查询并丢弃查询结果;只要后者没有抛异常,就可记录成功。因此其返回真也不等于已验证 0x28 正响应或实际 ECU 停发。Hyundai init() 又没有返回 / 汇总这个布尔值;card 在它返回后直接写 ControlsReady。这是一条源码确认的状态回执缺口,不是对特定车辆雷达或 ADAS ECU 实际行为的断言。

    deinit() 构造启用收发请求并复用 init() 的条件与地址。在本快照的主运行链未检出 CI.deinit() 调用,所以不能说正常退出一定主动恢复 ECU。控制器每 100 帧的 tester-present 也仅在自控纵向、非 CAN FD 相机 SCC 时形成。禁用雷达可能使原车 AEB 不可用,必须逐硬件架构独立验证。

    面向新硬件与插件化的接口建议

    车型插件只应给出期望能力、指纹 / 固件证据、DBC 和拓扑;受信任 ECU 管理服务独占诊断写权限,并单独报告请求已发送、预期正响应或可观测行为、持续存活和恢复结果。不同车型的相机 SCC 与雷达 / ADAS ECU 静默对原车 AEB 的影响,不得合并为一个通用开关。非上车验证矩阵应覆盖 LKA / LFA、相机 / 雷达 SCC、双 panda 总线偏移、备用按钮 / 档位、缺失 ADAS 固件、CANFD_NO_RADAR_DISABLE、负 UDS 响应、超时、掉电恢复及 AEB / FCW。

    常见问题

    为什么不能用车型名直接推断 E-CAN 号?

    因为 E-CAN 号由拓扑推导:指纹阶段 CanBusBase 按非空 bus 最大编号算四路偏移,运行阶段 CanBus(CP) 按 safetyConfigs 数量算偏移;而 LKA 与 LFA 平台会交换 A-CAN / E-CAN。识别出的拓扑必须与实际 panda / 线束配置一致。

    车型参数里 LONG 为真就代表能上纵向控制吗?

    不代表。只有 openpilotLongitudinalControl(即 alpha_long and alphaLongitudinalAvailable)真正启用时才给 MCU 设 LONG;card 还可能因开关关闭、无控制器或 dashcamOnly 把接口设为被动并把安全模式改为 noOutput。

    接口静默雷达 ECU 成功了吗?

    无法从返回值判断。默认请求带 UDS 0x28 suppress-positive-response 位,只是让 ECU 不回正响应;disable_ecu() 丢弃查询结果,返回真也不等于已验证 0x28 正响应或 ECU 实际停发。Hyundai init() 更没有汇总该布尔值。

    退出时会自动恢复被静默的 ECU 吗?

    不能这样假设。deinit() 会构造恢复请求并复用 init() 的条件与地址,但在本快照的主运行链未检出 CI.deinit() 调用。恢复是否发生需按具体运行路径与硬件架构单独验证。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/HYUNDAI_INTERFACE_CAPABILITY_ECU_LIFECYCLE_DEEP_DIVE.md(取用了 CAN FD / 经典 CAN 判别、能力位推导、ECU 静默与恢复边界分析)。

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

    更新记录

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

  • Hyundai 控制输出:经典 CAN 与 CAN FD 两条构帧路径与独立安全门

    结论:Hyundai 的控制输出不是一条「转向命令」链路,而是同一份车型控制器代码按经典 CAN / CAN FD、原车纵向 / 自控纵向、LKA / LFA 架构分支,形成不同候选帧,再交给 panda 固件的 hyundai_tx_hook 或 hyundai_canfd_tx_hook 独立复核。主机侧 CANPacker 编码成功、CarOutput.accel 回报正确、tester-present 发出,都不等于 ECU 接受。下述节拍以 card 目标 100 Hz 且每轮调用一次控制器为前提,是代码名义节拍,不是实测总线频率。

    公共控制周期:力矩、加速度与请求位

    每一控制轮,CarController.update() 先把 actuators.torque 乘以车型 STEER_MAX,再以最近一次软件输出和 CS.out.steeringTorque 调用驾驶员力矩/变化率限制。横向未活动时力矩清零;经典 CAN 分支在横向活动但请求位被切断时还会设置 torque_fault,CAN FD 分支没有这个额外字段。这是两条分支在同一控制器里的第一处实现差异。

    common_fault_avoidance() 在转角绝对值达到 85 度时管理请求位,目的在于避免 EPS 长时间大角度带扭矩故障。加速度只做 [-3.5, 2.0] m/s² 夹限,再传给具体纵向报文;CarOutput 回报的 accel 就是这一软件夹限值,不是 CAN FD 内部 aReqValue、MCU 发送回执或车辆实测加速度。

    诊断保活方面,若启用 openpilot 纵向且非 CANFD_CAMERA_SCC,每 100 帧向经典 CAN 雷达 0x7d0、CAN FD E-CAN 雷达 0x7d0 或 LKA 架构 ADAS ECU 0x730 形成一条 tester-present 候选。它的目的是维持此前请求的 ECU 静默,不能证明 ECU 已静默;CarInterface.init() 使用通用 disable_ecu(),其成功/失败返回值没有被 card.ControlsReady 闭环消费。取消请求持续时 cancel_counter 逐轮加一,解除请求即归零——源码注释指出部分车辆的取消键也可能是暂停/恢复键,因此原车纵向的按钮取消被延迟。

    经典 CAN 输出:LKAS11 与 SCC 家族

    LKAS11 每控制轮形成候选:继承 CS.lkas11 中一批原车相机字段,覆盖转向力矩、请求位、HUD 警告、车道线和计数,再按车型选择 CRC8、前 6 字节和、或前 6+末字节和三种校验之一。它不是泛用的「转向命令」结构,不同车型的显示字段也有例外,process_hud_alert() 对部分 Genesis 警告采用不同编码。原车纵向下,持续取消超过 10 帧后发送一条 CLU11 取消候选;恢复请求则在距上次按钮帧大于 0.1 秒时一次追加 25 个相同恢复候选,而 last_button_frame 只在间隔至少 0.15 秒时更新。

    自控纵向每偶数帧形成 SCC11、SCC12、SCC14;USE_FCA 且非 CAMERA_SCC 时还生成 FCA11。SCC12 的 aReqRaw / aReqValue 都取软件加速度,计数器及 nibble checksum 由构帧函数处理;SCC14 传入 jerk 上限和 HUD 前车状态。非 FCA 路径在 SCC12 设置 AEB disabled 字段,FCA 路径在 FCA11 设置相应禁用状态。

    经典 CAN 报文 触发条件与节拍 关键边界
    LKAS11 每控制轮 覆盖力矩/请求位/HUD;校验方式按车型三分支
    CLU11 取消 原车纵向且持续取消超过 10 帧 「最多 10 Hz」注释不等于严格上限
    恢复候选 ×25 距上次按钮帧 > 0.1 秒 不构成 25 条 ECU 接受证明
    SCC11 / SCC12 / SCC14 自控纵向每偶数帧 SCC12 双加速度字段;SCC14 传 jerk 与前车状态
    FCA11 USE_FCA 且非 CAMERA_SCC 设置制动执行禁用状态
    SCC13 / FCA12 5 Hz 选项帧 额外选项帧,非原车 AEB 保留保证
    FRT_RADAR11 2 Hz 选项帧 同上,单独验证
    LFA 图标 SEND_LFA 平台每 5 帧 仅图标候选

    经典 panda hook 对 LKAS11 限扭矩/请求位,对 SCC12 检查两路加速度并禁止 AEB 执行字段,对 FCA11 阻止制动执行位;诊断地址只允许固定 tester-present 载荷。不同 hyundai、hyundaiLegacy、相机 SCC 和纵向模式选择不同 RX 检查与 TX 白名单,软件字段编码正确仍可能被 MCU 拒绝。

    CAN FD 输出:LKA/LFA 路由与 SCC_CONTROL

    CanBus 按 LKA/LFA 转向架构决定 A-CAN 或 E-CAN。LKA 平台生成 LKAS / LKAS_ALT,仅在自控纵向时同时补 LFA,其他平台直接生成 LFA。LKA 平台每 5 帧还用最近缓存的 CAM_0x2a4 / CAM_0x362 字段构造「无车道线」报文来抑制原车 LFA——这属于 ADAS 能力修改,应单独验证缓存年龄与原车功能影响。图标候选按 LKA/纵向组合每 5 帧输出;若 flag 开启,LKA 平台可生成 SPAS1 / SPAS2 转向灯候选。

    自控纵向每偶数帧生成一条 SCC_CONTROL:aReqRaw 用夹限后的目标,aReqValue 用与上次记录 accel_last 相差不超过 5/50 的值;accel_last 随后记录当前原始目标,而不是编码出的 aReqValue。所以这个运算不能简单称为持续的输出速率限制,阶跃目标须回放核对两个字段和 ECU 响应。LKA 架构另发 ADRV 系列报文以配合禁用 ADAS ECU,LFA 架构按偶数帧生成 AEB disabled 图标报文。

    CAN FD 路径 生成条件 需单独验证的点
    LKAS / LKAS_ALT LKA 架构每轮 总线归属(A-CAN/E-CAN)
    LFA 自控纵向补发,或非 LKA 平台直接生成 架构判定是否正确
    无车道线抑制报文 LKA 平台每 5 帧 缓存 CAM 报文年龄、原车功能影响
    SCC_CONTROL 自控纵向每偶数帧 aReqRaw 与 aReqValue 的 5/50 差值语义
    ADRV 系列 LKA 架构 与禁用 ADAS ECU 的配合
    AEB disabled 图标 LFA 架构每偶数帧 仅图标,不等于 AEB 状态
    SPAS1 / SPAS2 flag 开启且 LKA 平台 本快照未见设置该 flag 的车型

    原车纵向 CAN FD 用按钮或 SCC_CONTROL 取消:备用按钮平台直接复用最近 CS.cruise_info 的计数/校验及状态字段,把 ACCMode 改为 4、加速度置零;标准按钮平台须取消持续超过 10 帧、距上次按钮超过 0.25 秒,才一次追加 20 个相同的取消按钮候选。标准按钮的恢复也可一次追加 20 个候选;备用按钮平台的恢复分支只是 pass,本快照未实现。MCU safety 仍要求原车纵向 SCC_CONTROL 为取消模式且加速度为零。

    插件化与硬件验收边界

    把转向、纵向、巡航按钮、HUD、ADAS 抑制和诊断保活声明为不同能力,各自绑定平台、DBC、线束、节拍及安全模式,是这套实现的自然结论。车型控制插件只提交结构化候选;唯一受信任网关验证 CAN 地址、物理总线、长度、年龄、限幅和 ECU 静默状态,并由独立 MCU 保留不可绕过的 TX safety。禁止把 CANPacker 成功、CarOutput 回报或 tester-present 发送等同于 ECU 接受。

    无车验证应覆盖经典 CAN/CAN FD、LKA/LFA、原车/自控纵向、相机 SCC、备用按钮、AEB 图标、缓存断流、大转角请求位、加速度阶跃和诊断失效,再逐帧与 DBC、panda hook 对照。CANFD_ENABLE_BLINKERS 还存在对 0x7b1 的保活及 SPAS 构帧代码,但本快照静态平台表未见设置该 flag 的车型,不能把代码分支当成已启用的实车能力。

    常见问题

    为什么 CAN FD 里的 aReqValue 不能当作真实加速度限幅?

    因为 SCC_CONTROL 的 aReqValue 取的是与上次记录 accel_last 相差不超过 5/50 的值,而 accel_last 记录的是当前原始目标而非编码结果。这个运算在阶跃目标下不是持续速率限制,须回放核对两字段与 ECU 响应;CarOutput 回报的 accel 也只是软件夹限值,不是车辆实测加速度。

    tester-present 发出去,是否说明雷达 ECU 已被静默?

    不代表。每 100 帧形成的 tester-present 候选只用于维持此前请求的 ECU 静默状态,本身不能证明 ECU 已进入静默;CarInterface.init() 使用的 disable_ecu() 返回值也没有被 card.ControlsReady 闭环消费,因此不能由「帧已构造」推断「ECU 已接受」。

    经典 CAN 与 CAN FD 的转向输出差在哪?

    经典 CAN 每控制轮形成 LKAS11,并在横向活动但请求位被切断时设置 torque_fault;CAN FD 按 LKA/LFA 架构生成 LKAS/LKAS_ALT 或 LFA,没有这个额外字段。此外 CAN FD 的 LKA 平台还会每 5 帧构造「无车道线」报文抑制原车 LFA,属于 ADAS 能力修改。

    备用按钮平台的恢复功能是否已实现?

    未实现。源文档明确:原车纵向 CAN FD 中,标准按钮平台的恢复可一次追加 20 个候选,而备用按钮平台的恢复分支只是 pass,本快照未实现。取消分支则复用最近 CS.cruise_info 的字段并把 ACCMode 改为 4、加速度置零。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/HYUNDAI_CONTROLLER_CAN_OUTPUT_DEEP_DIVE.md(取用了公共控制周期、经典 CAN 与 CAN FD 构帧节拍、panda hook 复核点与插件化边界)。
    • 项目 02 —— openpilot-research/CAR_PROTOCOL_IMPLEMENTATIONS.md(仅用于确认 Hyundai 品牌目录与 CAN/CAN FD 链路的总体位置)。

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

    更新记录

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

  • 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