标签: CAN总线

  • panda Python 设备 API:连接副作用、CAN 传输与健康协议

    结论:panda 的 Python API 不是一组只读查询函数,而是一条会改变设备状态的维护接口:Panda() 构造时立即调用 connect(),连接成功后会读取健康与协议版本、重置 CAN 通信、关闭三路总线的 CAN FD 自动切换并写入默认速率。CAN 传输层用六字节头加 XOR 校验组织报文,返回帧把总线号加 128、被拒帧加 192。XOR 与版本检查只检测传输格式与意外损坏,不是对报文来源的密码学认证,也不能替代 panda MCU 的车型 TX 约束。本文为固定源码快照 c8fb906 的静态阅读,未连接设备、未发送 CAN。

    连接不是只读操作

    Panda.__init__() 可按序列号或命令行选择设备,并立即调用 connect()。连接先试 USB 后试 SPI:USB 侧匹配 VID/PID、读取序列号并可能独占接口;SPI 侧检查 bootstub 状态与协议版本。没有设备时 connect() 抛异常,wait=True 会重试。close() 关闭句柄及 USB context,reset() 发送设备复位请求并可重连。

    连接成功后,驱动会读取 MCU 的健康与 CAN 包版本;默认 disable_checks=True 会禁用心跳检查和省电,随后重置 CAN 通信、关闭三个总线的 CAN FD 自动切换并写入默认 CAN 速率。因此普通 Panda() 本身就带有设备状态副作用,不适合作为插件的「探测对象」。正式 pandad 的 Python 包装器只在健康检查与固件维护时临时打开设备,运行时收发由 C++ pandad 承担。

    get_packets_versions() 读取两个协议版本,短响应时返回 (0,0);health()、can_health() 和 CAN 收发入口都用装饰器对比本地与设备版本,不匹配则拒绝解释数据或发送。这意味着自制 MCU 固件不能只实现同名端点,还必须保持头格式、健康结构布局与版本 hash 一致。

    CAN 包格式与传输

    pack_can_buffer() 只接受 DLC_TO_LEN 中列出的长度;头部编码 DLC、总线、FD、地址及 XOR 校验。USB 写入时按约 256 字节分块,SPI 不走这条分块开关。unpack_can_buffer() 验证校验和,跨传输的不完整帧会留在 can_rx_overflow_buffer 等下次拼接;返回帧把 bus 加 128,被拒绝帧加 192,不能误认作真实物理总线编号。

    can_send_many() 经版本检查后调用底层 bulkWrite,在短写时重复提交剩余字节;默认写超时为 10 ms,源码注明 timeout=0 意味无限。can_recv() 读取后重组帧,对 USB IO 与 overflow 错误会无限重试并休眠,函数自身没有总重试上限。发送函数没有处理 bulkWrite 返回零但不抛异常的情况,按控制流可能不前进,是否发生需用具体传输实现验证。

    环节 实现事实 边界
    pack_can_buffer() 头部含 DLC、总线、FD、地址与 XOR 未对车型允许地址、速率或驾驶状态裁决
    USB 写入 按约 256 字节分块 SPI 不走这条分块开关
    unpack_can_buffer() 验证校验和,残帧留待下次拼接 返回帧 bus 加 128,被拒帧加 192
    can_recv() IO/overflow 错误无限重试并休眠 函数本身没有总重试上限

    健康与配置 API

    health() 解码点火、controls_allowed、安全模式与参数、心跳丢失、RX 校验无效、缓冲溢出、故障和温度等,它是点时状态,不证明下一帧仍允许发送,也不能只看 controls_allowed 而忽略 safety mode 与 fault。can_health() 报告每总线的 bus-off、错误被动、收发丢帧、校验错误与速率/CAN FD 信息,其计数器是硬件/固件视角,不能代替车型信号新鲜度。

    配置类方法与维护类方法有明确的能力差别:set_safety_mode()、set_alternative_experience() 向 MCU 发送安全模式与体验标志请求,但 Python 方法本身不做车型许可判断;send_heartbeat() 会重新开启心跳检查。get_signature() 读取设备签名字节并与本地固件尾部比对,属于版本一致性比较,并不是单凭 Python 层就完成的固件可信启动验证。

    函数簇 返回/动作 信任边界
    health() 点火、控制许可、安全模式、心跳、溢出、故障、温度 点时状态,不能只看 controls_allowed
    can_health() 每总线 bus-off、错误被动、丢帧、校验错误、速率 计数器是硬件/固件视角,协议版本须一致
    set_safety_mode() 发送安全模式与体验标志控制请求 Python 方法未做车型许可,插件不应直接获得
    set_obd() 与 CAN 配置 切 OBD 复用、收发器使能、CAN/CAN FD 速率 对布线与收帧可见性有副作用
    get_signature() 读设备签名并与本地固件尾部比对 版本一致性比较,不等于固件可信启动

    面向自制硬件与插件的约束

    源码给出的设计建议(不是现有代码已实现)是:把设备接口分成枚举与只读健康、接收 CAN、发送 CAN、改写总线与安全模式、固件维护五级能力,只有受信任的单一网关持有发送、心跳和 safety mode 权限。自制网关至少要复现包格式、残帧处理、返回/拒绝标记、版本握手、错误计数和独立的 MCU TX 安全策略,并在异常时由硬件默认停止自动控制,而不是依赖 Python 进程及时恢复。

    还需要注意,pandad.py 的 Python 包装器会在固件签名不同或处于 bootstub 状态时调用 flash/recover,之后再启动 C++ pandad;它是会改写固件的恢复链,因此研究时不应把实例化 Panda 或运行包装器视为无害操作。协议 ABI、线束拓扑、CAN 速率及固件镜像应绑定到具体硬件版本,设备发现不得自动刷写或切换安全模式。

    常见问题

    为什么说 Panda() 一实例化就有副作用?

    因为它按序列号或 CLI 选设备后立即调用 connect();连接成功会读取运动健康与协议版本,默认 disable_checks=True 时禁用心跳检查与省电,并重置 CAN 通信、写入默认 CAN 速率。所以它不适合作为插件的「只读探测」入口。

    can_send_many() 与 can_recv() 会无限重试吗?

    can_recv() 对 USB IO 与 overflow 错误会无限重试并休眠,函数自身没有总重试上限;can_send_many() 在短写时重复提交剩余字节,默认写超时 10 ms,源码注明 timeout=0 表示无限。因此需要调用方自己设定超时与失败处理。

    CAN 包的 XOR 校验能证明报文来源可信吗?

    不能。XOR 与包版本检查用于检测传输格式错误或意外损坏,不是对 CAN 报文来源的密码学认证,也不能替代 panda MCU 的车型 TX 约束。pack_can_buffer() 本身不对车型允许地址、速率或驾驶状态做裁决。

    自制 MCU 固件只实现同名端点就够了吗?

    不够。Python 层用装饰器对比本地与设备协议版本,不匹配就拒绝解释或发送,所以固件还须保持头格式、健康结构布局及版本 hash 一致;此外还应复现残帧处理、返回/拒绝标记、错误计数与独立的 MCU TX 安全策略。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/PANDA_PYTHON_DEVICE_API_DEEP_DIVE.md(取用了连接副作用、CAN 包格式与传输、健康与配置 API 分层、自制硬件约束)。
    • 项目 02 —— openpilot-research/PANDA_BOARD_DEEP_DIVE.md(关联的板级安全链专题,用于区分 Python 层能力与 MCU 执行门,本文未展开其函数细节)。

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

    更新记录

    首次发布 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

  • 方程式赛车总线档案:53 条报文与多设备 DBC 合并

    结论:这份档案的对象是一支大学生方程式车队的赛车总线,不是量产车:源文档以 11 位标准帧、8 字节为主的 DBC 文本,逐条给出 ECU、变速箱控制、IMU、电源分配、车轮与制动传感器等设备的报文定义。它的数据特征是「多设备 DBC 合并成一份 master」——config.dbc 是自动生成的整车总览(当前 53 条报文),单独设备定义在 devices/ 下,两者按设计存在重叠,不可当作彼此独立的车辆覆盖。源文档未提供比特率、日志数或采集跨度,也未独立验证各供应商组件定义的年份与适用性,因此下述结论只限这份 DBC 快照本身。

    车辆与适用范围

    源文档是一份随车项目公开的 DBC 配置仓库:根目录一份 config.dbc 作为「master calibration」,各设备定义放在 devices/,通过合并脚本汇总。它描述的是车队赛车的整车总线,而非某一款市售车型。

    项 内容
    车型 大学生方程式赛车队的赛车及车上组件(源文档未给出具体车号或平台名)
    年款 / 市场版本 源文档未确认;仓库中同时保留历史 2019-2021/config.dbc
    ECU / 改装状态 赛车总线,含 ECU、变速箱控制(GCM)、IMU、电源分配模块(PDM)、GPS/圈速记录(SDM550)、制动红外测温与车轮力传感器等
    采集跨度 源文档未提供(无日志数、事务数或时长记录)
    适用范围 仅覆盖该 DBC 快照内定义的设备与报文;各供应商组件定义的年款适用性未独立验证

    总线与寻址

    源文档以 DBC 文本形式给出全部报文,未包含物理层描述,因此比特率与终端电阻等条件无法从本档案确认。

    项 内容
    物理层 / 比特率 源文档未给出
    寻址方式 逐条报文均标注 Extended: No,即 11 位标准帧
    帧长度 以 8 字节为主;个别报文 2 / 4 / 6 字节(如 SDM550_LapTrigger 为 2 字节、GCM_Queue 与 GCM_Error 为 4 字节)
    CAN FD 源文档未提供任何 CAN FD 报文
    组织方式 按设备分文件定义,再由脚本合并为 config.dbc 总览
    字节序 同一设备内混用:既有 big_endian 也有 little_endian,须逐信号核对

    已解码信号

    下表从源文档的信号定义中抽取最有代表性的条目(发动机、底盘、IMU、圈速与耗材传感器)。位置一列保留源文档的报文 ID 与字节位/长度写法,解码一列保留其原始缩放与单位;「证据」一列注明该条目出自合并总览还是组件定义。

    信号 位置(ID / 起始位·长度) 解码 证据
    nmot 0x300 / bit 7·16 大端有符号,缩放 1,0–20000 rpm;同一信号亦出现在 0x20、0x3fb config.dbc 及组件定义
    ath 0x300 / bit 23·16 大端有符号,缩放 0.1,0–110 % config.dbc
    lambda 0x300 / bit 39·16 大端有符号,缩放 0.001,0–5 config.dbc
    ub(电压) 0x300 / bit 55·16 大端有符号,缩放 0.01,0–25.5 V config.dbc
    tmot / toil / tint / tfuel 0x301 / 各 8 位 缩放均为 1 °C;tmot 为小端,其余大端 config.dbc
    texh 0x301 / bit 32·16 小端无符号,1 °C,0–1250 °C config.dbc
    poil / pfuel 0x302 / 16 位 大端有符号,缩放 0.001,0–10 bar config.dbc
    gear / pbrake_f / pbrake_r 0x20 / 字节 5–7 区 挡位 -1–12;前后制动压力 0–150 bar config.dbc
    speed(变速箱控制) 0x3fb / bit 0·16 小端无符号,缩放 0.01,0–400 km/h config.dbc
    四轮速 + 车速 0x3aa / 各 8 位 vwheel_fl/fr/rl/rr 与 speed,0–400 km/h config.dbc
    Laptrigger_laptime_dls 0x69a / bit 32·32 小端无符号,缩放 0.01,0–500 s config.dbc
    lapctr / outctr 0x69c / 各 8 位 小端无符号,0–255 config.dbc
    IMU_Yaw_Rate 0x174 / bit 0·16 小端,缩放 0.005,单位 deg/s config.dbc
    IMU_X_Accel 0x178 / bit 32·16 小端,缩放 0.0001274,「g」量纲 config.dbc
    Kistler_S350_Vel 0x7fa / bit 23·16 大端无符号,缩放 0.036,0–400 km/h config.dbc

    读取方法与注意事项

    源文档给出了一条明确的工程纪律:不要直接修改 config.dbc。它的定位是「master calibration」,主要供某类商业诊断工具在接入车辆时总览整条总线;正确的做法是编辑 devices/ 下各设备的 DBC——这样更容易批量重命名信号、整体调整某设备的所有 ID。

    合并流程是:在 devices/ 目录下运行合并脚本 python merge_can.py,把各设备定义汇总生成根目录的 config.dbc。源文档并提示 devices/ 下的隐藏文件 .dbc 并非空占位,而是一份有效的五报文制动红外传感器定义。

    解析时须注意两点。第一,同一逻辑量会在多条报文里重复出现(例如 nmot 同时出现在 0x300、0x20、0x3fb),是否一致、以哪条为准,源文档未给出仲裁规则。第二,字节序在同一设备内混用,大端与小端并存,任何解析器都必须逐信号读取其 Byte Order 字段,不能假定全局一致。

    证据等级与边界

    本档案属于「源码/配置静态记录」:全部信号定义都能在 DBC 文本里逐字核对,属于源文档直接证据;但源文档没有任何实车观测,也没有比特率、节拍或日志作为间接支持。文件层面,源文档说明该快照归档了 21 个字节互不相同的 DBC:当前 config.dbc(53 条报文)、历史 2019-2021/config.dbc(23 条报文)以及 devices/ 下 19 个组件文件。

    两点不能外推。第一,当前 master 与组件定义按设计重叠,把两者相加并不能得到更大的车辆覆盖,只能得到同一辆车的重复描述。第二,源文档明确这些是车队赛车与组件定义、不是量产车型 DBC,且各供应商组件定义的具体年份与适用性未独立验证;把某条信号外推到其他年份的其他车上,超出了源文档证据。此外,该仓库快照未声明也未发现许可证,部分组件名指向第三方供应商、原始权利未核实,源文档要求保留为私有离线研究副本、再分发前先确认权利。

    关于安全访问,源文档未提供任何绕过方法,且不建议尝试。

    常见问题

    config.dbc 为什么不能直接改?

    因为它是自动生成的整车总览,单独设备定义在 devices/ 下。直接改 master 会与组件定义脱节;源文档要求改组件 DBC,再用合并脚本生成 master,这样便于批量重命名与整体改 ID。

    把 master 和组件 DBC 的信号加起来,覆盖会不会更大?

    不会。源文档明确当前 master 与组件定义按设计重叠,两者不是独立的车辆覆盖;相加只是重复描述同一辆车,不能当作更全的信号集。

    这些信号能直接套到其他年份的赛车上吗?

    不能。源文档未确认车辆年份,也未独立验证各供应商组件定义的适用性;同一逻辑量还会在多条报文里重复出现且未给仲裁规则。外推超出源文档证据范围。

    为什么同一设备的字节序会混用?

    源文档如实记录:部分信号为 big_endian、部分为 little_endian(例如 0x301 的 tmot 为小端、toil 为大端)。这是源定义的实际状态,解析器必须逐信号读取字节序字段,不能假定全局一致。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/illini-motorsports-can-configuration/UPSTREAM_README.md(本项目车型档案主来源:config.dbc 与 devices/ 的组织方式及全部报文信号定义)。
    • 项目 01 —— public-can-dbc-datasets/additional/illini-motorsports-can-configuration/SOURCE.md(仓库修订、21 个字节互不相同 DBC 的归档说明、许可证与适用性边界)。

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

    更新记录

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

  • Indian Springfield 2017:J1939 摩托车 CAN 档案

    结论:Indian Springfield(2017 款)是一辆主动用 J1939 广播数据的摩托车:源文档用只监听(listen-only)方式在 4 次采集中抓到 42,365 个变化事件,并按 PGN / SPN / SA 体系拆出 30 个参数组。它有两个特殊之处:采集做了「变更去重」,帧数并不等于发送次数;车厂还在 DM1 故障报文里用 FMI 9(Abnormal Update Rate)间接承认了部分信号的存在。以下所有结论仅限源文档记录的这一台车及其固件。

    车辆与适用范围

    本文数据来自第三方开源项目对一台 Indian Springfield 摩托车的 CAN 日志整理。项目采用只监听模式,不向总线发送任何帧,采集后按 J1939 的参数组、可疑参数与源地址体系做拆分,并对每个参数组标注了是否已发布。

    项 内容
    车型 Indian Springfield,2017 款
    年款 / 市场版本 源文档标注为 2017 款;具体市场版本未确认
    发动机 风冷 V 型双缸;源文档指出该车没有水温传感器,标准参数组里位置原本留给水温的字节,在本车上装的是缸头温度
    采集跨度 4 次采集,累计 42,365 个变化事件,采集日期 2026-08-15
    适用范围 仅限源文档记录的这一台车;不保证适用于其他年款或排量的 Indian 车型

    总线与寻址

    这辆车用的是 J1939 而非「按 ID 广播原始布局」的常见乘用车 CAN。理解它的数据,先要理解 J1939 的三层语义:PGN 是参数组,SPN 是组内的可疑参数,SA 是发送该组的源地址。

    项 内容
    物理层 / 速率 单条 CAN,J1939(29 位扩展帧);源文档未给出该车波特率
    协议语义 PGN(参数组)+ SPN(可疑参数)+ SA(源地址)
    源地址名册 SA 0 = 发动机;SA 11 = ABS;SA 23 = 仪表;SA 39 = 管理电脑;SA 136 = 第二个仪表(厂商码 146,但源文档记录它从不发数据)
    传输层 TP / BAM(长报文分段传输)
    参数组总数 30 个 PGN,分四组:20 个已发布、4 个传输层、1 个已知不发、5 个未知
    采集方式 只监听(listen-only),硬件为 ESP32-S3 加 MCP2518FD;采集器不对总线做任何应答

    已解码信号

    下表从源文档的参数组与逐字节清单中抽取。项目把未闭环的条目明确标为「候选」或「开放线索」,本文原样保留这些标注,不做拔高。

    信号 位置(ID / DID / 字节) 解码 证据
    缸头温度(标准 SPN 110 位置) PGN 65262 SA0 B0 摄氏度 已发布参数组;源文档注明本车为风冷,该字节实装缸头温度而非水温
    引擎需求扭矩 PGN 61444 SA0 B7 offset −125 已发布参数组
    油门踏板位置 PGN 65266 SA0 B7 SPN 51;源文档记录到两个静止值 开放线索
    相对后轮速 PGN 65215 SA11 B4 与后轮速相关(r=+0.84) 候选
    巡航状态 PGN 65265 SA0 B3[1:0] 位线索 开放线索
    续航里程 PGN 65382 SA0 B3:B4 u16 小端,km 开放线索
    侧撑(standDown) PGN 65381 SA0 B7 bit0 位标志 候选
    熄火开关(killSwitch) PGN 65381 SA0 B4 bit6 位标志 候选
    最忙未解字节 PGN 65382 SA0 B0 共出现 255 个不同取值 未解(源文档列为待解字节)

    读取方法与注意事项

    第一条是采集方式。源文档全程使用只监听模式,硬件不参与总线仲裁、不做应答,因此不会扰乱车辆。这对摩托车尤其重要:摩托车的 CAN 往往只有少数几个节点,任何主动发送都可能被整车当作异常输入。源文档没有描述任何主动请求或写入操作。

    第二条是「变更去重」。项目的采集脚本只记录 payload 发生变化的帧,因此日志里的 42,365 是「变化事件数」,不是「发送次数」。同一个信号静止时不会产生新记录,所以不能拿日志条数反推某个报文的实际周期;要算频率必须回到未去重的原始采集。

    第三条是语义陷阱。J1939 的标准参数组里,某个字节在标准中定义的是 A 参数,在具体车型上可能被车厂改成 B 参数。本车把标准为水温的位置改成了缸头温度,就是典型例子——按标准名直接套用会得到错误结论。

    证据等级与边界

    源文档把结论分成几档:已发布(对应 J1939 标准参数组)、传输层、已知不发、未知。信号层面则以「候选」与「开放线索」标注尚未闭环的推断。本文只把候选条目当作「值得进一步验证的方向」,不作为可直接引用的结论。

    项目有一条很有价值的旁证方法:J1939 的 DM1 故障报文会用 FMI 9(Abnormal Update Rate,更新速率异常)来表示「某个本该定期广播的信号没有按时到达」。源文档列出的 7 条相关记录中有 6 条已落到已发布参数组——换句话说,车厂自己在故障报文里承认了这些信号在总线上被广播。这为「某信号确实存在于该车」提供了来自车厂侧的间接证据。

    边界上必须强调:以上结论全部来自这一台 2017 款 Indian Springfield 与这 4 次采集。不同年款、不同固件、不同排量的车型,参数组布局与源地址分配都可能不同。任何外推前都必须重新采集验证。

    常见问题

    为什么日志里只有 4 万多个「帧」?

    因为项目采用了变更去重采集:只记录 payload 发生变化的帧。42,365 是变化事件数,不是发送次数。要计算某个报文的实际周期,必须使用未去重的原始采集,而不能用日志条数反推。

    怎么知道某个信号真的存在于这辆车上?

    除了日志相关分析,源文档还借助 DM1 故障报文里的 FMI 9(Abnormal Update Rate):车厂用它表示「某个应定期广播的信号没按时到」。源文档中 7 条 FMI 9 记录有 6 条对应已发布参数组,相当于车厂侧间接承认了这些信号的存在。

    J1939 的标准信号名能直接套用吗?

    不能。标准参数组只规定了「某个位置通常放什么」,车厂可以改。本车把标准里水温的位置改成了缸头温度,若按标准名直接解析就会得到错误结论。必须先在本车上复核。

    只监听会不会漏掉数据?

    不会漏掉「被广播的数据」,但拿不到任何需要主动请求的模块数据。本车的关键信息都是周期广播,因此只监听足以覆盖;如果某辆车存在「要问才答」的模块,只监听就会缺失那部分。

    延伸阅读

    参考资料

    • 项目 03 —— public-can-dbc-datasets/additional/prinsessen-indian-springfield-2017/docs/DECODE-PLAN.md(本项目车型档案主来源:参数组分组、源地址名册与已撤回信号)
    • 项目 03 —— public-can-dbc-datasets/additional/prinsessen-indian-springfield-2017/docs/UNEXPLORED-BYTES.md(逐字节清单与开放线索)
    • 项目 03 —— public-can-dbc-datasets/additional/prinsessen-indian-springfield-2017/README.md(硬件与 listen-only 采集说明)

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

    更新记录

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

  • Tesla 与 Rivian 不能共用一套插件:转角控制 vs 动态扭矩的两条链路

    结论:Tesla 与 Rivian 都属于电动车,但不能共用一套「电动车插件」:Tesla 是转角控制加选择性原车报文转发,Rivian 是动态扭矩加原车 ACC 状态取消,两者在总线拓扑、原车辅助系统与安全策略上均不同。两品牌的纵向参数读取都受 ALLOW_DEBUG 限制,车型/固件识别是执行前提;未识别、无法确认固件或未接线时保持被动。本文为源码静态分析,没有实车、线束、固件构建或 HIL 验证。

    Tesla:转角控制与选择性转发

    CarInterface._get_params() 选择 tesla 安全模式和转角控制,并通过指纹识别缺失 DAS_settings、新 3-bit DAS_steeringControlType 固件;Model X 或旧固件条件可标为 dashcamOnly。雷达支持需要特定 Continental 雷达、DBC 与物理接入 bus 1,不能只凭车型名推断。alpha_long 可写纵向安全参数,但固件实际纵向启用受 ALLOW_DEBUG 限制。

    CarState.update() 与 update_autopark_state() 从 party 与 autopilot-party 两条总线解析车速、踏板、EPS 手握级别/接管、巡航、Autopark、原车 AEB/LKAS,并保留 DAS_control 副本用于取消报文;状态机只在未巡航的上升沿锁存 Autopark。输出侧,CarController.update() 在 hands_on_level >= 3 时停用横向,每 2 帧按速度和车辆模型限制目标转角并定期发送允许转向报文;纵向启用时发送加速度,否则仅构造符合取消语义的 DAS_control。get_safety_CP() 以 Model Y 参数匹配固件转角限制。

    雷达接口读取 40 对 A/B 目标消息,要求索引一致,按状态删除旧目标并报告 CAN、遮挡及传感器故障;无物理雷达/未接线时退回基础接口。tesla_checksum() 实现发送帧校验,但编码器不是发送许可。

    层 关键入口 已核对行为
    安全 RX tesla_rx_hook() 从 EPAS、DI、ESP 采样转角、双车速、油门/制动、巡航与手动接管,识别原车 AEB、LKAS 与 Autopark
    安全 TX tesla_tx_hook() Autopark 锁存时拒绝所有候选;转向检查角度/速率/控制类型;原车 LKAS 运行时禁止主机转向
    纵向限制 tesla_tx_hook() 禁止主机 AEB 事件;原车 AEB 运行时拒绝纵向/取消帧;非纵向模式只允许无执行量的取消
    原车转发 tesla_fwd_hook() 按 Autopark、原车 LKAS、原车 AEB 选择性屏蔽相机/Autopilot 总线的转向与纵向报文
    初始化 tesla_init() 构造不同纵向白名单;先假定 Autopark/Summon 激活,直到状态消息澄清

    需要强调的是,tesla_fwd_hook() 的转发是根据状态选择性屏蔽,不能把「拦截原车控制帧」写成一条恒定规则。tesla_init() 启动先假定 Autopark/Summon 激活,是为降低上电时与原车系统争用而设的保守起点。

    Rivian:动态扭矩与原车 ACC 状态取消

    CarInterface._get_params() 选择 rivian 模式,以 0x321 消息是否存在区分 Gen2,并配置扭矩控制。本快照设 radarUnavailable=True;Gen2 自控纵向默认不开放,docs 可影响能力字段。即使软件选择纵向,固件白名单也仅在 ALLOW_DEBUG 接受参数。输入侧 CarState.update() 从 PT、相机、ADAS 三路解析车速、踏板、转向、巡航、AEB 和故障;Gen2 缺部分车门/安全带 CAN 信号,源码说明依赖原车 ACC 处理,不能等同软件已观测到这些状态。另外 cruiseState.speed 的注释说明当前是检测到的限速替代值,不是已核对的目标巡航速度。

    Rivian 会复制 ACM_lkaHbaCmd、Gen1 触摸方向盘帧,并保留每次 VDM_AdasSts 更新;后者可能一轮收到两帧,所以控制器逐帧重发以保留时序。输出侧,CarController.update() 根据速度插值得到扭矩上限,再按驾驶员扭矩限幅;Gen1 可发送触摸方向盘消息。自控纵向生成加速度帧;原车纵向取消时先发送数帧 available 再发 unavailable 状态,让 ACM 接受切换。

    层 关键入口 已核对行为
    参数 _get_params() 以 0x321 区分 Gen2;本快照设雷达不可用
    编码 riviancan.py create_lka_steering()、create_wheel_touch()、create_longitudinal()、create_adas_status() 复用原车字段并重算校验
    雷达 RadarInterface.update() 有目标解析器,但参数层总设不可用,通常走基础接口;只保留 LRR 或 SRR+LRR 模式有效目标
    安全 RX rivian_rx_hook() 从 ESP 与 VDM 双车速检查失配;CRC/质量位函数对特定地址独立验证
    安全 TX rivian_tx_hook() 转向扭矩设速度相关上限、驾驶员抵消及变化率;纵向加速度另设限值
    模式选择 rivian_init() 原车 ACC 与自控纵向使用不同 TX 白名单;纵向选择仅在 ALLOW_DEBUG 编译块读取

    对硬件与插件化重构的四条约束

    1. 车型/固件识别是执行前提。Tesla 的 steering-control 字段代际、Rivian Gen1/Gen2、雷达物理接入和发布/调试固件选择必须进入受审计的能力清单;不能把 alphaLongitudinalAvailable 直接映射为「允许发送」。
    2. 原车系统仲裁不能外包给普通插件。Tesla 的 Autopark、原车 LKAS/AEB 转发优先级和 Rivian 的 ACC 状态取消时序应与板级安全门、主机状态机共同验证,在不明状态下不放行控制。
    3. 传感器数据必须携带来源与有效性。Tesla/Rivian 的双车速、CAN 质量位和雷达模式不是普通数值字段;新硬件要保留总线、时间戳、计数器/校验及故障标志,防止旧值伪装成实时观测。
    4. 发布固件单独验收。这两个模式本身可在注册表中找到,但纵向参数读取受 ALLOW_DEBUG;不能用调试固件跑通的纵向测试宣称发布版可用。

    把两条链路放在一起看,可以发现共性:软件层「能构造帧」与硬件层「允许发送」始终是两件事,而原车辅助系统(Autopark、LKAS、AEB、ACC)的在场状态会随时改变这条边界。跨品牌流程可参考车型协议总览,板级执行可参考 panda 专题。

    常见问题

    Tesla 与 Rivian 都是电动车,为什么不能共用一套插件?

    因为两者控制类型不同:Tesla 采用转角控制并选择性转发原车报文,Rivian 采用动态扭矩并依赖原车 ACC 状态取消。它们的总线拓扑、原车辅助系统与安全策略都不同,源文档明确「不能共用一套电动车插件」,必须按平台分别声明能力。

    为什么代码里有纵向控制,实车却不一定能启用?

    因为两品牌的纵向参数读取都受 ALLOW_DEBUG 限制:Tesla 的 tesla_longitudinal 仅在 ALLOW_DEBUG 读取安全参数,Rivian 的纵向选择也只在 ALLOW_DEBUG 编译块读取。因此不能用调试固件跑通的纵向测试宣称发布版可用。

    Tesla 雷达支持能否只凭车型名判断?

    不能。源文档指出雷达支持需要特定 Continental 雷达、DBC 与物理接入 bus 1,不能只凭车型名推断;Rivian 侧参数层在本快照总设 radarUnavailable=True,即使代码有目标解析器,也不会据此宣称实车雷达链已启用。

    Rivian 的原车纵向取消为什么要先发 available 再发 unavailable?

    源文档说明这是为了让 ACM 接受切换:取消时先发送数帧 available 再发 unavailable 状态。这属于原车系统仲裁时序,应与板级安全门、主机状态机共同验证,而不是当作普通的功能开关。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TESLA_RIVIAN_DEEP_DIVE.md(取用了 Tesla/Rivian 的参数、输入、输出、安全 RX/TX、转发与初始化行为,以及四条插件化约束)。
    • 项目 02 —— openpilot-research/CAR_PROTOCOL_IMPLEMENTATIONS.md(仅用于确认两品牌目录与跨品牌安全主链路的总体位置)。

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

    更新记录

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

  • Hyundai 经典 CAN panda safety:三模式权限矩阵

    结论:Hyundai 经典 CAN panda safety 把「标准雷达 SCC / 标准相机 SCC / Legacy」三种模式做成一张权限矩阵:同一辆车的按钮 RX 固定在 bus 0,而 TX 可能落在 bus 0 或 bus 2,纵向能力只在调试构建生效。Legacy 也不是全面关闭 RX 校验,放宽的只有 0x386 与 0x394,0x260、0x4F1、0x421 仍保留各自的校验或计数门。以下为固定源码快照 c8fb906 的函数级静态分析,不是目标固件或实车验证;bus 号指单个 safety 实例的本地总线编号,车型、线束与 ECU 版本需另行确认。

    初始化与模式选择

    CarInterface._get_params() 在 hyundai 与 hyundaiLegacy 之间选择,并设置相机 SCC 与纵向能力。需要注意的是 openpilotLongitudinalControl 只是上层请求,不是固件准入证明。hyundai_init() 再依据纵向、相机 SCC、FCEV 标志选择 RX 检查表与 TX 白名单;hyundai_legacy_init() 使用 Legacy RX 表,并强制关闭纵向和相机 SCC,仅保留基础 TX 表。

    共享的 hyundai_common_init() 在非调试构建中强制 hyundai_longitudinal=false。也就是说纵向链在源码层面就带着 ALLOW_DEBUG 编译门,不能由 Python 侧 CarParams 位推定量产固件可发。

    模式 SCC12 RX CLU11 TX 纵向/附属 TX 关键差异
    标准雷达 SCC、非纵向 bus 0 bus 0,4 字节 无 SCC TX 巡航接合沿使能;按钮只许受门控的 Resume/Cancel。
    标准相机 SCC、非纵向 bus 2 bus 2,4 字节 无 SCC TX 按钮 RX 仍是 bus 0,不能把 TX 所在总线误当按钮输入来源。
    标准雷达 SCC、纵向 不列为必需 RX bus 0,4 字节 SCC11/12/13/14、FRT_RADAR11、FCA11/12、0x7D0 在 bus 0 LONG 仅 ALLOW_DEBUG 有效;不经原车 SCC 接合沿使能。
    标准相机 SCC、纵向 不列为必需 RX bus 2,4 字节 SCC11/12/13/14、FRT_RADAR11 在 bus 0 相机 SCC 纵向不使用雷达静默诊断白名单。
    Legacy bus 0 bus 0,4 字节 无 SCC TX 强制非纵向、非相机 SCC;仅部分 RX 的完整性检查放宽。

    所有模式均可发送 bus 0 的 0x340 LKAS11 与 0x485 LFAHDA_MFC。纵向 TX 表中的 SCC11/12/13/14 对 bus 0 标记 check_relay=true;若原 ECU 在该总线继续发送同地址帧,共享继电器故障逻辑可阻断 TX。safety_fwd_hook() 只提供通用 bus 0↔2 转发,并静态阻断将 check_relay 地址送往本机 TX 总线,这不是 ECU 已被成功静默的证明。

    RX 完整性与状态消费

    各地址使用不同的计数位与半字节校验:0x386 使用位计数/XOR,其余适用帧使用半字节和。RX 完整性检查先于车型钩子执行,通用 safety_rx_hook() 只在消息匹配、校验有效且属于 RX 表时才调用 hyundai_rx_hook()。

    帧 检查表 实际消费
    0x260 EMS16 或 0x371 E_EMS11 同一备选组;0x260 检查 2 位计数和校验,0x371 忽略二者 ICE 从 0x260 读油门,EV/HEV 从 0x371 读油门。
    0x386 WHL_SPD11 标准模式校验加 4 位计数;Legacy 忽略二者 只用左前、右后轮速判断移动,阈值原始值 12。
    0x394 TCS13 标准模式校验加 3 位计数;Legacy 忽略二者 字节 5 的 DriverOverride 等于 2 判制动。
    0x251 MDPS12 忽略校验/计数,但监视存活 11 位驾驶员扭矩进入共享采样窗口。
    0x4F1 CLU11 忽略校验、检查 4 位计数 bus 0 上解析按钮和主开关,更新近期交互或纵向按钮边沿。
    0x421 SCC12 只在非纵向为必需;校验加 4 位计数 按相机 SCC 标志从 bus 2 或 bus 0 读取 ACC 模式。
    0x91 FCEV 油门 仅特定标准雷达 SCC 或纵向分支附加;忽略校验/计数 FCEV 标志下读取字节 6;标准相机 SCC 非纵向表没有该附加检查。

    FCEV 分支中 0x91 更新油门,但 0x260 的 ICE 回退条件仅排除 EV/HEV;若车辆也出现 0x260,后续该帧仍可能改写油门状态,须用目标车报文核对,不能把单帧观测当成最终状态。

    TX 字段边界与使能条件

    转向 0x340 从 11 位字段还原扭矩与请求位:普通/ALT_LIMITS/ALT_LIMITS_2 的最大扭矩分别为 384/270/170,每帧上升分别为 3/2/2、下降为 7/3/3,均使用实时差 112、驾驶员扭矩余量 50 与请求位节拍容忍;两种替代标志同时存在时 ALT_LIMITS_2 优先。非纵向的 0x4F1 只允许 controls_allowed 时 Resume,或 cruise_engaged_prev 时 Cancel;纵向模式跳过整个按钮 TX 分支,白名单内的 0x4F1 不受该专属按钮码限制,这是插件权限设计必须额外收紧的差异。

    纵向加速度 0x421 同时核对 aReqRaw 与 aReqValue,单位是 0.01 m/s²,活动范围为 -350 到 200,并禁止 AEB 减速度命令、AEB 请求和停止请求。共享加速度检查允许未激活编码,不能仅用数值落在范围内推断准入。雷达 SCC 纵向表包含 0x38D FCA11,专属钩子禁止其减速度/AEB 激活字段;0x483 FCA12 仅有地址/总线/长度白名单;0x7D0 仅雷达 SCC 纵向可发送,载荷必须是 02 3E 80 00 00 00 00 00。SCC11/13/14、FRT_RADAR11 和 HUD 没有该模式的逐字段校验,白名单准入不代表 ECU 接受,也不代表原车 AEB、FCW 或仪表状态保持不变。

    面向自制硬件的插件契约

    源文档给出的是一组建议设计而非已实现能力:车型身份插件应输出带证据的标准/Legacy、SCC 来源、动力类型与转向限制,未知或冲突组合不授予 TX;总线插件同时报告 RX/TX 的物理接口与本地 bus,尤其记录相机 SCC 模式下按钮 RX bus 0、TX bus 2 的差异。

    纵向插件只能提交控制意图;可信任网关需核对构建类型、MCU mode/param 读回、ECU 静默回执、原车 AEB 功能与失联降级,再交由独立 MCU safety 门裁决。对纵向 CLU11、FCA12、HUD 与 SCC 附属帧应另设最小载荷模板和速率配额,不能因原模式白名单存在就向普通插件开放原始 CAN 写入。现有 test_hyundai.py 覆盖标准/Legacy、替代转向限值、相机 SCC、FCEV 与纵向 AEB/诊断路径,但本文未运行这些单测,模型实体、目标固件、台架及实车行为仍未验证。

    常见问题

    Hyundai Legacy 模式是不做 RX 校验吗?

    不是。Legacy 只放宽 0x386 和 0x394 的校验与计数检查;0x260、0x4F1、0x421 仍保留各自的校验或计数门。同时它强制关闭纵向和相机 SCC。

    相机 SCC 模式下按钮输入在哪个总线?

    按钮 RX 仍是 bus 0,只是 CLU11 的 TX 落在 bus 2。源码明确说明不能把 TX 所在总线误当成按钮输入来源。

    Hyundai 纵向控制是不是打开参数就能用?

    不是。LONG 仅在 ALLOW_DEBUG 编译条件下有效,共享 hyundai_common_init() 在非调试构建中强制关闭纵向。Python 侧 CarParams 位不能作为量产固件可发的证明。

    0x7D0 的载荷能自由填吗?

    不能。源文档说明 0x7D0 仅雷达 SCC 纵向可发送,载荷必须是固定的 02 3E 80 00 00 00 00 00。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/HYUNDAI_CLASSIC_PANDA_SAFETY_DEEP_DIVE.md(模式权限矩阵、RX 完整性表、TX 字段边界与插件契约)。
    • 项目 02 —— openpilot-research/ 同目录 Hyundai/Honda 品牌总览(SCC 与纵向能力作为相邻边界参考)。

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

    更新记录

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

  • Honda 车辆输入:四轮混速与 Bosch/Nidec 巡航分支

    结论:Honda 的 CarState 不直接使用基类的四轮均速 helper:它把四轮 WHEEL_SPEEDS 求均并换算为 m/s,再用 1 到 6 m/s 的插值权重,把低速更依赖的 ENGINE_DATA.XMISSION_SPEED 与轮速混合后送入 KF1D 得到 vEgo/aEgo;standstill 另按变速箱速度小于 1e-5 单独判断。刹车开关信号按源码注释可能含单次噪声,非 BOSCH_ALT_BRAKE 车型要求当前与前值连续两样本同为真。本文为固定源码快照 c8fb906 的静态阅读,未做车型回放、CAN FD 台架或实车验证。

    解析器与总线边界

    动力和相机解析器的物理总线由 CanBus(CP) 指定,不能把 Bus.pt 恒等为 0。有雷达的 Bosch 平台把动力放在偏移加 1、雷达放在偏移;无雷达或 CAN FD 的 Bosch 与 Nidec 采用另一组映射。HAS_BSM 仅由特定 CR-V 指纹分支动态设置,状态层为此另建 Bus.body 解析器,物理输入使用 CanBus(CP).radar,源码注释说明 B-CAN 要先经 panda 转发——缺少这条物理路径时,软件支持 BSM 字段不等于盲区信息可用。

    三个解析器创建时都没有显式报文列表,cp.vl[...] 第一次读取才动态注册报文。由于 CarInterfaceBase.update() 已先调用 parser 更新,新注册报文在第一轮的值与时间戳初始为零,本轮此前到达的帧不会被它解析;此后 vl 保存最近成功值,不保证本轮有新样本。接口对已注册报文做 can_valid 全路聚合、对总线空窗做 bus_timeout 聚合,但若新硬件要以刹车、车速或盲区作为安全条件,仍需逐信号检查来源、时间戳与采样年龄。

    入口 作用
    CarState.__init__() 按变速箱/平台选择报文与 DBC 枚举,初始化刹车开关、仪表速度与巡航缓存
    CarState.update() 把动力、相机与条件性车身总线信号归一化为 CarState
    CarState.get_can_parsers() 建动力/相机解析器,BSM 车型额外建 body 解析器
    CanBus.__init__() 区分有雷达 Bosch 的动力/雷达交换、纵向模式下的 LKAS 路由与其他平台总线
    update_speed_kf() 对 Honda 已混合的 vEgoRaw 做 KF1D 速度/加速度估计
    create_button_events() 按本轮/上轮按钮值构造按下与释放事件

    速度混合与仪表值锁存

    Honda 先把四轮 WHEEL_SPEEDS 平均并换成 m/s,再用 1 到 6 m/s 的插值权重把变速箱速度与轮速混合;CP.wheelSpeedFactor 在这段代码里只乘变速箱速度项,高车速主要由轮速项决定。混合值进入 KF1D 形成 vEgo/aEgo,而 standstill 单独按变速箱速度小于 1e-5 判断,不能简单用 vEgo 是否为零替代。轮速与变速箱速度矛盾时的物理可信度尚需目标车型回放验证。

    CAR_SPEED.ROUGH_CAR_SPEED_2 首次大于阈值后 dash_speed_seen 永久锁存,之后每轮都把当前解析器缓存经 kph/mph 转换写入 vEgoCluster;在锁存前,基类接口用 vEgo 回退显示速度。台湾 Odyssey 特例不走该字段。状态侧没有单独的仪表速度年龄判据,若报文停发,解析器健康与显示缓存需要分别解读。

    车身、转向与刹车

    车门可来自四门 DOORS_STATUS、SCM_BUTTONS 驾驶门位或 SCM_FEEDBACK 驾驶门位,安全带用警告灯或未锁扣任一条件。自动/CVT 档位通过 DBC 枚举,手动挡只由倒车灯在倒车与前进之间二选一,无法在这里识别空挡或所有换挡中间态。方向灯调用拨杆型 250 次调用保持器;驾驶员转向直接以 STEER_TORQUE_SENSOR 绝对值对车型阈值比较,不使用基类去抖。STEER_STATUS 的 DBC 数值先转字符串,未知值映射 UNKNOWN,永久与临时故障有独立映射:BOSCH_ALT_RADAR 对预期低速锁定给例外,MDX 4G 的 TJA_LOW_SPEED_LOCKOUT 还单独清除故障位。

    有 BOSCH_ALT_BRAKE 时刹车直接读 BRAKE_MODULE.BRAKE_PRESSED;其他车型把 POWERTRAIN_DATA.BRAKE_PRESSED 与刹车开关并联,只有本轮 vl_all 有开关样本时才更新开关状态,单轮有多样本则用倒数第二条作为前值,要求当前和前值都为真。若没有新开关帧,brake_switch_active 保持上次状态;解析器健康是另一层,不应把保留布尔值当成新鲜采样。

    巡航、原车 ADAS 与下游

    POWERTRAIN_DATA.ACC_STATUS 和选定 SCM 报文主开关决定巡航 enabled/available。Bosch 原车纵向的设定速度读 ACC_HUD.CRUISE_SPEED,遇大于 160 的特殊值就沿用 v_cruise_pcm_prev;源码说明设置时可能脉冲到 254/255,252 又表示 standstill。带动态单位的 Bosch 平台才在英制时使用 mph 转换,其他情况按 kph;Nidec 则读 CRUISE.CRUISE_SPEED_PCM。这些特殊值是软件解码规则,不是一般范围检查。

    原车 AEB/FCW 来源也分 Bosch 与 Nidec:Bosch 有雷达且未启用自控纵向时才从动力 ACC_CONTROL 判定原车 AEB;Nidec 从相机 BRAKE_COMMAND 判 AEB/FCW,并保留 ACC_HUD 与刹车字段供控制器构帧;Bosch 无雷达车型另保存相机 LKAS_HUD。这些字段是 parser 的最近缓存引用,CarState 未给每个字段附单独采样年龄,因此不能把有 HUD 字典当作原车 AEB 仍可用的证明。按钮事件来自 SCM_BUTTONS 的巡航/设置字段当前与上次值,下游再由车辆事件层决定取消、启用和故障告警。

    信号类别 来源与处理 版本分支
    车速 四轮均速 + 变速箱速度按 1~6 m/s 插值权重混合,随后 KF1D 台湾 Odyssey 不锁存仪表速度字段
    刹车 直接读 BRAKE_MODULE,或与刹车开关并联并要求连续两样本 BOSCH_ALT_BRAKE 走直读分支
    巡航设定速度 Bosch 读 ACC_HUD.CRUISE_SPEED,Nidec 读 CRUISE.CRUISE_SPEED_PCM 大于 160 特殊值沿用上轮;252 表示 standstill
    原车 AEB Bosch 读 ACC_CONTROL,Nidec 读相机 BRAKE_COMMAND Bosch 无雷达保存 LKAS_HUD
    盲区 BSM 车型经 B-CAN 转发后由 body 解析器读取 HAS_BSM 由特定 CR-V 指纹动态设置

    硬件插件验收

    车型输入插件应为轮速四路、变速箱速度、刹车开关与压下、EPS 故障、巡航、原车 AEB 与 BSM 分别声明物理总线、DBC、采样时戳、年龄、校验/计数器结果和缺测状态。速度融合参数、仪表速度锁存和刹车连续样本门应按车型版本冻结并在回放中量化。无车测试至少覆盖第一轮动态注册、单轮异常、速度来源矛盾、刹车短脉冲与断流、ACC 特殊速度码、未知 EPS 状态、BSM 路由缺失及 Bosch/Nidec 分支,再与安全钩子的独立 RX 判据对照。

    常见问题

    Honda 的车速为什么不是简单的四轮平均?

    因为低速时四轮均速不够可靠。CarState 先求四轮均速并换算为 m/s,再用 1 到 6 m/s 的插值权重把变速箱速度 XMISSION_SPEED 与轮速混合,混合值才进入 KF1D 形成 vEgo/aEgo;CP.wheelSpeedFactor 只乘变速箱速度项,高车速主要由轮速项决定。

    为什么刹车开关需要连续两个样本?

    源码注释指出开关信号可能有单次噪声,且驻车挡未必有效。非 BOSCH_ALT_BRAKE 车型把 POWERTRAIN_DATA.BRAKE_PRESSED 与刹车开关并联,只有本轮有开关样本时才更新状态,单轮多样本用倒数第二条作为前值,并要求当前和前值都为真。

    巡航设定速度出现 254/255/252 是什么意思?

    这是软件解码规则而非一般范围检查。Bosch 原车纵向读 ACC_HUD.CRUISE_SPEED,遇大于 160 的特殊值就沿用 v_cruise_pcm_prev;源码说明设置时可能脉冲到 254/255,而 252 又表示 standstill,因此不能按普通数值范围直接采信。

    解析器聚合通过就代表每个信号都新鲜吗?

    不代表。接口只对已注册报文做 can_valid 聚合、对总线空窗做 bus_timeout 聚合,而 vl 保存的是最近成功值,不保证本轮有新样本;CarState 也未给原车 HUD 等字段附单独采样年龄,因此仍要逐信号核对来源与年龄。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/HONDA_CARSTATE_SPEED_BRAKE_CRUISE_INPUT_DEEP_DIVE.md(取用了 Honda 速度混合、刹车去噪、Bosch/Nidec 巡航分支、BSM 路由与插件验收清单)。
    • 项目 02 —— openpilot-research/CAN_PARSER_HEALTH_DEEP_DIVE.md(仅用于确认解析器健康聚合与总线空窗的语义位置)。

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

    更新记录

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

  • Tesla Model3 CAN 仿真档案:67 条报文与 5 个锚点信号

    结论:这份「车型 CAN 数据档案」的对象是 Tesla Model3 的一台 CANoe / CAPL 仿真工程,不是一台真实车辆:它用三份逆向得来的 DBC(Battery / Thermal / Drive)和一条「电池异常 → 热管理响应 → 扭矩降额」的因果链,在总线上造出约 67 条报文、其中 8 条为核心周期报文。总线为 500 kBaud 经典 CAN、11 位标准帧,另叠加一条 Ethernet / DoIP 诊断通道,CAN 侧用标准 ISO-TP(CanTp)承载 UDS。关键结论——例如硬切断后扭矩以 kHardCutoffTau=0.4s 衰减、集中式架构下 bmsContactorState 稳定在 80.500s——全部来自仿真,不能当作实车测量,也不能外推到其他 Model3 车或年款。

    车辆与适用范围

    源文档是一套围绕仿真节点搭建的工程:三个业务 ECU(Battery / Thermal / Drive)实现核心因果链,一个独立的 SafetyMonitor 节点只监听总线,外加测试驱动与 DoIP 网关/以太网诊断。以下范围只对应这套仿真的内部设定。

    项 内容
    车型 Tesla Model3(仿真建模对象,非实车采集)
    年款 / 市场版本 源文档未确认;DBC 名称仅区分 Battery / Drive / Thermal 三个域
    ECU / 改装状态 仿真态:Battery_ECU、ThermalCtrl_ECU、DriveInverter_ECU、SafetyMonitor_ECU 四个 CAPL 节点
    采集跨度 约 121.5 分钟的四阶段自动化场景(Phase0 正常基线 / Phase1 冷被动 / Phase2 热被动软限 / Phase3 热主动硬切断)
    适用范围 仅限该仿真工程产出的 .asc 日志与其下游分析;不代表真实 Model3 的任何总线行为

    总线与寻址

    总线侧为经典 CAN,叠加以太网诊断扩展。源文档给出的寻址与帧格式信息如下;需要注意,DBC 本身是逆向产物,其对报文周期的标注并不完整。

    项 内容
    物理层 / 比特率 CAN 500 kBaud;另设一条 Ethernet 通道(DoIP / OSEK_TP 节点层 DLL)
    寻址 / 帧格式 经典 CAN;总线负载按 CAN 2.0A 标准帧 47 位开销计算,即 11 位标识符
    CAN FD 源文档未使用 CAN FD;诊断走 CAN 侧 ISO-TP(CanTp)与以太网 DoIP
    报文规模 三份 DBC 去重后共 67 条报文;CAPL 仿真实际周期发送 8 条核心报文
    周期标注完整性 67 条中 45 条没有 GenMsgCycleTime,为原始逆向 DBC 的数据缺口

    已解码信号

    下表抽取源文档中最有代表性的条目。位置一列尽量保留源文档的 ID 与消息名写法;「证据」一列注明来自 DBC、CAPL 设定还是分析脚本的输出口径。凡源文档标注为「未完全根因」或「数据缺口」的,均原样保留。

    信号 位置(ID / 字节域) 解码 证据
    BMSmaxPackTemperature Battery 域锚点信号 电池包最高温度,跨域因果链的温度锚点 anchor_signals.csv;Phase0 拟合归一化
    BMS_maxDischargePower ID252BMS_powerAvailable(十进制 594) 最大放电功率,驱动域软限跟踪的输入 DBC;CAPL 设定
    VCFRONT_coolantFlowBatActual Thermal 域锚点信号 电池冷却液实际流量 anchor_signals.csv
    CMP_speedRPM ID227CMP_state 压缩机转速档位;三级压缩机转速状态机 CAPL 设定;故障注入用例
    DIR_torqueCommand Drive 域锚点信号 驱动扭矩指令;硬切断后按指数衰减到近零 anchor_signals.csv;kHardCutoffTau=0.4s
    BMS_contactorState Battery 域广播 接触器状态;==1 时 Thermal 冻结全部热信号 CAPL 设定;SafetyMonitor Rule 1/5
    ID312BMSthermal 广播 ID312BMSthermal(十进制 786) 电池热报文;被抑制即触发 SafetyMonitor 通信超时 CAPL 设定;故障注入用例
    gFlowRequest Simulink 信号链(1000 ms 周期) 流量请求;延迟/量化行为最高约 1.92s Simulink 验证;已调查未完全根因
    gCompressorRPM Simulink Drive 分支 随机游走驱动的压缩机转速 Stateflow;随机序列复现问题见边界
    gTorqueCommand Simulink Drive 分支 随机游走驱动的扭矩指令 Stateflow;同上
    targetPower(稳态) Simulink 两架构对照 稳态目标功率,两架构均为 40.0000 Verify_key_metrics.m 校验
    HardCutoff.Opening 时长 状态机(Battery_ECU) 硬切断 OPENING→OPEN 过渡,精确 200ms CAPL 设定;Simulink 复核
    UDS 0x22 ReadDataByIdentifier Battery_ECU 诊断栈 5 个 DID,含两个由其他 ECU 拥有的网关式 DID(被动缓存) CAPL;UDS_DiagnosticsTest 14 个检查点
    UDS 0x19 / 0x14 与 0x7F Battery_ECU 诊断栈 读/清 DTC(子功能 0x02/0x04);7 种否定响应场景 CAPL;Freeze Frame 用例

    读取方法与注意事项

    解析链以 cantools 为基础。源文档明确:默认采用流式解析以适配大日志,小于 200 MB 时才用 --in-memory;解码后的长表可再重采样到 100ms 均匀网格,但真实逐帧时间戳只在长表里,做周期核验必须用长表而非重采样结果。引用因果滞后结论时,源文档要求只引用 causal_lag_analysis_HIGH_CONFIDENCE_ONLY.csv。

    数据完整性有专门的检查脚本,给出三种判定:CLEAN(可直接使用)、ISOLATED, LIKELY OK(不超过 5 个孤立点,建议抽查)、CORRUPTED(存在大段连续异常,不可直接使用)。源文档建议在 LSTM 训练或引用因果滞后结论之前先跑这一检查,用于识别已知的 CAPL/CANoe 信号解码缺陷是否复现。

    异常检测模块有一处容易踩的坑:训练与评估的 --val-fraction、--block-size、--seed 必须完全一致,否则 Phase0 基线会落在模型已训练过的窗口上,静默低估基线误差。归一化只在 Phase0 上拟合,以避免把异常期统计量泄漏进「正常」基线。总线负载侧,长表须先按 (timestamp_s, frame_id) 去重,否则到达帧会被按信号重复计数,严重高估发送频率。

    时延分析脚本不接收命令行参数,输入文件名固定为 CAN.asc 与 Eth.asc;它以两个文件各自的时间戳相减来定义时延,而不是信任 UDP 载荷内的 Timestamp 字段(后者存在约 0.5ms 的整毫秒截断偏置)。匹配采用精确 RawValue 相等、平分时取最近在前的策略,源文档明确这是尽力而为、不保证唯一的匹配。

    证据等级与边界

    本档案的全部信号都是仿真观测,没有任何实车旁证。DBC 是逆向结果,45/67 条报文缺少周期标注,因此总线负载只能给出「未填充下界」与「+20% 填充上界」两个口径,30%/50% 也只是业界经验阈值、非强制标准。Simulink 侧两架构对照给出确定性结论:集中式架构的 bmsContactorState 在 11 次重复仿真中稳定到达 80.500s(零方差),分布式架构则落在 0–110ms、10ms 栅格的延迟窗内,且在受控变量测试下确认延迟来自接收域自身采样节拍。

    已知缺陷必须原样保留。其一,Battery_ECU.can 内部使用了两个互不同步的 100ms 定时器,CAPL 不定义其相对触发顺序,在窄时序巧合下会令 SafetyMonitor 的 Rule 1 在模拟上电复位后短暂重触发,源文档将其记为未修复的开放问题(低优先级、影响面窄),根因已分析但未获得带时间戳的证据确认。其二,Simulink 中 Stateflow 的随机游走函数在独立 sim() 调用间复现同一随机序列,机制未定位,只影响随机游走驱动信号,不影响上述确定性结论。其三,1000ms 周期的 gFlowRequest 链出现最高约 1.92s 的延迟/量化,与其余信号的 0–110ms 模式不一致,已调查但未完全根因、被降级搁置。

    不能外推的部分:本文所有数值限定在这套仿真的设定与日志;40.0000、200ms、80.500s 等均属工程参数,不构成对任何真实 Model3 的描述。源文档未提供对车辆安全机制的绕过方法,且不建议尝试;本文只讨论仿真工程的公开文档。

    常见问题

    这是不是一台真实 Model3 的数据?

    不是。它是 CANoe/CAPL 仿真工程:三个业务 ECU 加一个独立监听节点,用逆向 DBC 复现「电池异常 → 热响应 → 扭矩降额」的因果链。所有信号与节拍都来自仿真设定,源文档未包含任何实车采集。

    为什么 67 条报文里只有 8 条能算总线负载?

    因为逆向 DBC 中 45 条报文没有 GenMsgCycleTime,且核心 8 条里还有两条在 DBC 里根本没有周期。源文档的做法是以 CAPL 的 setTimer() 调用作为周期的唯一真实来源,并逐行标注对应的 CAPL 源码位置以便追溯。

    引用因果滞后结论时要注意什么?

    源文档要求只引用 HIGH_CONFIDENCE_ONLY 的结果文件,并在引用前先跑数据完整性检查以排除已知的解码缺陷;LSTM 训练/评估的 val-fraction、block-size、seed 必须一致,否则基线会被静默低估。峰值与时长在本数据集中还存在部分混淆。

    SafetyMonitor 的 Rule 1 为什么会误触发?

    因为 Battery_ECU.can 内部两个不同步的 100ms 定时器相对顺序未定义,在窄时序巧合下会在模拟上电复位后短暂重触发。源文档标记为开放且未修复,根因已分析但未经带时间戳的证据确认,影响面窄。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/model3-can-simulation/README.md(本项目车型档案主来源:节点与因果链、DBC 与锚点信号、总线负载、时延分析与 Simulink 对照)。

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

    更新记录

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

  • 2014 丰田 Yaris Hybrid XP130 的 CAN 信号地图

    结论:这份档案记录的是 2014 款丰田 Yaris Hybrid(第 3 代 XP130,THS-II NoDSU)的 CAN 信号逆向成果:从车机 28 针连接器的第 9/10 脚(500 kbit/s)被动监听,而不是 OBD-II 口,已确认 12 个与仪表相关的信号(车速、转速、挡位、油门、刹车、转向灯、里程、环境温度、混动电池 SOC、EV 行驶位、CHG/ECO/PWR 指针)。关键结论是混动电池 SOC 与 EV 状态是普通广播,不需要主动诊断轮询。但 HV 电池电流/电压与剩余续航经确认不在总线上。下列结论仅限源文档记录的这一台车,不能外推到其他配置、年款或市场版本。

    车辆与适用范围

    源文档是一个「用逆向出的 CAN 数据驱动自制数字仪表」的项目,主线工作是信号逆向,附带完整的方法学与交叉验证记录。信号只有在两段独立的实车行驶日志上都能复现,才被标记为「confirmed」。

    项 内容
    车型 Toyota Yaris Hybrid(第 3 代 / XP130,THS-II NoDSU),2014 年
    年款 / 市场版本 2014;源文档未给出市场版本
    采集点 原厂车机 28 针连接器(p/n 90980-12555),第 9 脚 CAN-H / 第 10 脚 CAN-L,500 kbit/s,不是 OBD-II 诊断口
    采集跨度 两段独立实车日志:session_0044.log(约 430s)与 session_0047.log(约 440s)
    适用范围 仅限这一台 Yaris Hybrid;源文档说明映射可能不适用于其他配置/市场/年款

    总线与寻址

    文档把车机连接器视为干线高速 CAN(HS-CAN)的同一逻辑总线,理由是它看到的报文集合(SPEED、RPM、GEAR、BRAKE、TURN_SIGNALS、ODOMETER 等)与预期一致。这也正是后装第三方 CAN 盒通常接入的位置。

    项 内容
    物理层 车机连接器 CAN-H/CAN-L 双线,500 kbit/s
    链路层 / 比特率 500 kbit/s(源文档明示)
    寻址方式 报文为 11 位标准 ID(如 0x0B4、0x1C4、0x4A7 等)
    CAN FD 源文档未提及 CAN FD
    读取方式 ESP32 被动监听(TWAI_MODE_LISTEN_ONLY,不发送、不应答)

    已解码信号

    下表合并源文档的两张清单:前 12 行为两段日志都复现的「confirmed」信号,后 5 行为语义成立但精确标度未最终确认的「strong hypotheses」。置信度标注原样保留。

    信号 ID / 字段 解码 证据 / 置信度
    车速 0x0B4 / SPEED (byte5 << 8 | byte6) * 0.01 km/h 两段日志复现;与里程/其他 3 个速度字段一致(≤0.5%)
    发动机转速 0x1C4 / RPM 有符号 16 位 * 0.78125 rpm 两段日志复现(0→60→0 与怠速/轰油)
    挡位 P/R/N/D/B 0x127 / GEAR 4 位枚举,byte5 高半字节 五个状态全部观测到
    油门踏板 0x245 / GAS_PEDAL byte2 * 0.005(0–1 对应 0–100%) 两段日志复现(观测 0–35%)
    ICE 运行位 0x245 / ICE_RUNNING byte3 bit4 与 RPM>50 一致率 98–99%
    刹车按下位 0x230 / BRAKE_PRESSED 单个 bit 与换挡、车速变化对得上
    转向灯 0x614 / TURN_SIGNALS 2 位枚举 + 双闪位 左/右/无三态均观测到
    总里程 0x611 / ODOMETER 20 位,含 km/miles 单位位 确认为总里程(99552→99555 km),非续航
    环境温度 0x442 / AMBIENT_TEMP byte0 – 40 = °C 两天实测 37 °C / 27 °C 对照确认
    混动电池 SOC 0x4A7 / BATTERY_SOC byte2 * 0.5 = % 观测 54.0–71.5%,符合 THS-II NiMH 工作带;标度沿用 Toyota/Techstream 惯例,未与参考工具读数核对
    EV 行驶位 0x498 / EV_DRIVE byte5 bit7 与「行驶中且 ICE 停机」100% 一致
    CHG/ECO/PWR 指针 0x247 / HSI_VALUE + HSI_ZONE byte1 为量程百分比;符号取自 HSI_ZONE zone/value 相关性 n=32779、零例外
    刹车踏板(模拟量) 0x224 / BRAKE_VALUE 16 位,与刹车位强相关 假设:中位 0(松开)对 62(按下);单位与量程未确认
    冷却液温度 0x618 / TEMP_RAW byte3;猜测量程 * 0.375 假设:暖机曲线合理,无参考温度计标定
    第二温度(机油/CVT/电池包?) 0x3B9 / TEMP2_RAW byte0,约 1 Hz 假设:与时间/冷却液强相关(r≈0.95);量纲未提
    纵向加速度/扭矩需求 0x320 / ACCEL_DEMAND 有符号 byte4,约 20 Hz 假设:加速正、制动/滑行负、稳态≈0;标度未确认
    燃油消耗计数器 0x3A0 / FUEL_COUNTER_RAW byte7,10 Hz 假设:随 ICE 运行递减,不是油位表;疑为更宽寄存器的低位字节

    读取方法与注意事项

    源文档的全部信号都靠被动监听获得,固件以 TWAI_MODE_LISTEN_ONLY 运行,不向车辆发送任何报文。判定的门槛是「两段独立日志都复现」才算 confirmed;单段日志里的现象只进「假设」或「排除」清单。

    CHG/ECO/PWR 指针有一个容易踩的坑:符号位住在 HSI_ZONE(byte0),不在 HSI_VALUE(byte1)里。CHG 侧 byte1 用二进制补码并在 -100 处钳位,ECO/PWR 侧用无符号幅值且在全油门时会扫过 155,两侧原始范围重叠。早期固件只凭 byte1 判断符号,结果全油门的强 PWR 被误读成强 CHG,上车实测确认后改为按 HSI_ZONE 分支。此外 PWR 侧显示做了对折(PWR% = raw/2),因为 ECO/PWR 分界只是真实量程的中点而非顶点。

    车速不做修正是有意为之:SPEED 是真实车速,里程、GPS 与总线上另外 3 个速度字段都对它。仪表自身的指针读数偏高(含法规性偏置,UNECE R39 要求指示值不得低于真值,上限 10% + 4 km/h),而这个偏置值只在仪表内部计算、不上总线。

    证据等级与边界

    证据分三层。第一层是实车观测:12 个 confirmed 信号来自两段真实行驶日志;速度刻度还用里程绝对锚定(整公里区间积分误差 +0.01%,方法自身不确定度 ±0.82%)。第二层是外部旁证:速度/转速等沿用公开参考 DBC(跨 Prius/Camry/Highlander 变体核对),SOC 的 0.5%/bit 标度沿用已知的 Toyota/Techstream 惯例。第三层是推测:冷却液、第二温度、加速度与燃油计数器的量纲都属猜测。

    两处不能外推。第一,所有映射来自单一车辆,源文档明确「可能不适用于其他配置/市场/年款」;CHG/PWR 的 zone 编码尤其如此——文档记录后来一次实车硬加速还出现了 8、9、14 三个日志中没有的 zone,说明 4/6/12/15 对这批日志穷尽、对整车并不完整。第二,剩余续航与 HV 电池电流/电压/温度经确认不在本总线上,只能靠对电池 ECU 的主动 UDS 请求,源文档未提供任何绕过安全访问的方法,且不建议尝试。

    常见问题

    Yaris Hybrid 的 OBD 口能读到这些信号吗?

    源文档没有用 OBD-II 口,而是从车机 28 针连接器的第 9/10 脚取数。这正是后装 CAN 盒通常接入的位置,文档据此把它当作同一逻辑总线处理。

    混动电池 SOC 是主动问出来的吗?

    不是。SOC 在 0x4A7 的 byte2 上被动广播,EV 行驶位、ICE 运行位同样是广播;仅靠被动监听就能重建后装盒子的能量流显示。HV 电池电流/电压/温度则确认不在总线上。

    车速显示和真实车速差多少?

    源文档记录:在仪表指示 140 时真值约 130,差值约 +10 km/h(单次指针读数,可视为 +5~+15)。这是法规性偏置,不是解码错误;固件有意不做修正。

    为什么全油门时功率条会翻到 CHG?

    因为符号取自 HSI_ZONE 而非 byte1。只凭 byte1 判断时,PWR 侧扫过 155 会被误读成大负值。按 zone 分支后即可修正。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/fellettigiacomo-yaris-xp130/re/docs/signal_findings.md(本项目车型档案主来源:完整方法学与验证证据)。
    • 项目 01 —— public-can-dbc-datasets/additional/fellettigiacomo-yaris-xp130/re/docs/decoded_signals_summary.md(已确认/假设/排除信号的快速参考表)。
    • 项目 01 —— public-can-dbc-datasets/additional/fellettigiacomo-yaris-xp130/README.md(项目背景、硬件与被动监听安全说明)。

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

    更新记录

    首次发布 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