标签: Toyota

  • Toyota 雷达适配:A/B 槽聚合触发与健康发布的边界

    结论:Toyota 雷达接口不是「每帧到达就出结果」,而是跨轮聚合 A 槽、以最后一个 B 槽作为发布触发的观测链:只有 B 槽到达时才调用 _update() 并清空集合,否则返回 None。这带来三个可复核边界:触发长期缺失时不会生成新 RadarData 或错误事件;can_valid 只在 _update() 时被读取;无解析器时基类每五次调用输出空点,且外层 valid 为真并不代表实体雷达正常。ECU 禁用是独立的通信控制动作,与雷达观测插件必须分权。

    可用性由 DBC 决定,与 ECU 通信控制是两件事

    radarUnavailable 由 DBC 配置决定:TSS2 配置默认含雷达 DBC,而 RADAR_ACC 平台配置会移除雷达总线 DBC。源文档明确,radarUnavailable 表示当前适配没有可解析的雷达 DBC,不等于物理雷达不存在。该路径实例化的 RadarInterface 没有解析器,落入基类定期输出空点的路径。

    与可用性并列、但属另一层的是 ECU 通信控制:RADAR_ACC 且打开实验纵向时设置 DISABLE_RADAR,初始化时向 ECU 发通信控制,控制器周期发送 tester present。源文档强调这是车辆通信与纵向配置动作,不是 RadarInterface 的运行时健康开关,不能在没有车型、线束和安全审查时照搬。

    A/B 槽聚合与发布触发

    _create_radar_can_parser() 按车型选地址组与总线:TSS2 用 A 0x180..0x18f、B 0x190..0x19f;传统用 A 0x210..0x21f、B 0x220..0x22f。A/B 注册 20 Hz,STATUS_MSG 注册 10 Hz,总线为 1。

    解析组 地址范围 名义频率 总线
    TSS2 A 槽 0x180..0x18f 20 Hz 1
    TSS2 B 槽 0x190..0x19f 20 Hz 1
    传统 A 槽 0x210..0x21f 20 Hz 1
    传统 B 槽 0x220..0x22f 20 Hz 1
    STATUS_MSG 源文档未给出具体地址 10 Hz 1

    RadarInterface.update() 把解析器本轮成功解析地址并入跨轮集合;仅当最后一个 B 槽出现时才调用 _update() 并清空集合,否则返回 None。_update() 查询 can_valid 与状态/预故障,只处理累计集合里的 A 槽,按 VALID、LONG_DIST、NEW_TRACK、valid_cnt、对应 B 槽 SCORE 新建、延续或删除点。

    两处细节值得单独指出:B 的 SCORE 从 vl 当前缓存读,源文档指出它未要求 B 与 A 同周期;VALID 为真时直接满足发布条件,SCORE>50 仅为替代路径。A 槽中 NEW_TRACK 或距离越界会先清 valid_cnt,有效近距测量再加一;NEW_TRACK 新建 trackId,否则保留槽位现有点。

    健康与发布的三个缺口

    缺口 静态表现 结论边界
    B 触发长期缺失 无 B 触发时不发布新消息,也不生成错误事件;历史地址仍在集合里 适配层不会主动汇报该故障
    健康门只在 _update() 读取 can_valid 与 STATUS_MSG 只在生成结果时变成 RadarData.errors 触发丢失时错误来不及成为事件
    无解析器的空点路径 基类每五次调用产生空 RadarData;card 仅非 None 时发布 外层 valid 为 errors 全假,不代表实体雷达正常

    CANParser.update() 只返回本轮成功解析地址集,vl 保留各信号最近值;can_valid 检查注册消息缺失/超时和计数器,并有失效计数门。源文档明确 can_valid 只在 _update() 时被读取。无解析器时,RadarInterfaceBase.update() 每五次调用产生空 RadarData,card 仅在返回非 None 时发布 radarTracks,外层 valid 为 errors 全假。因此空点且外层 valid=True 不是「实体雷达正常」的证明,订阅者还要同时看 CarParams 与数据年龄。

    几何约定与插件重构验收

    几何输出为 dRel=LONG_DIST、yRel=-LAT_DIST、vRel=REL_SPEED。插件移植要锁定坐标约定、单位、测量时刻和传感器安装位姿,不能只复制数值字段。上游 radard 以 modelV2 为轮询源,读取最近的 radarTracks 和车况后发布 radarState;源文档提醒,上游不发布时融合循环仍按模型帧推进,不能把输出频率理解成雷达采样频率。

    插件输出应包含 sensor_id、车型/DBC 版本、采样时戳、扫描周期 ID、A/B 配对依据、点年龄、健康原因码和观测状态,并区分「不适用、被禁用、未收到、CAN 不健康、状态故障、正常空点」。接入 radard 前,用只读回放验证 16 组 A/B 顺序错乱、B 槽丢帧、状态报文丢失、NEW_TRACK 复用、距离 255 门槛、VALID 与低 SCORE 组合以及总线超时。

    源文档还给出触发缺失时的要求:应由独立 deadline 产生超时健康事件,而不是等待某个 B 地址恢复后才汇报;历史槽位与 SCORE 必须有最大年龄。这与「以最后一个 B 槽作为发布触发」的机制互补,提醒订阅者不能只依赖适配层的自行汇报。

    最后是分权:ECU 禁用/恢复与雷达观测插件分权,属受信任车辆网关能力,不要把诊断写操作授权给普通传感器插件。本篇未运行测试;上述风险是源码条件推论,不是已复现的实车缺陷。

    常见问题

    radarUnavailable 是不是代表车上没有雷达?

    不代表。源文档明确 radarUnavailable 由 DBC 配置决定:RADAR_ACC 平台配置移除了雷达总线 DBC,所以该路径没有可解析的 DBC,这不等于物理雷达不存在。

    为什么雷达偶发不出结果却不报故障?

    因为发布触发是最后一个 B 槽。源文档指出,B 触发长期缺失时不会生成新的 RadarData 或错误事件,历史地址仍在集合里;can_valid 也只在 _update() 时被读取,所以触发丢失时适配层不主动发布故障。

    没有雷达解析器时输出空点且 valid 为真,能认定雷达正常吗?

    不能。无解析器时基类每五次调用产生空 RadarData,card 仅在返回非 None 时发布,外层 valid 为 errors 全假。源文档明确这不能作为实体雷达正常的证明。

    DISABLE_RADAR 是雷达观测的健康开关吗?

    不是。源文档指出它是车辆通信与纵向配置动作:RADAR_ACC 且打开实验纵向时设置,并向 ECU 发通信控制、周期发送 tester present,与 RadarInterface 的运行时健康状态是两件事。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TOYOTA_RADAR_ADAPTER_DEEP_DIVE.md(取用了地址组与名义频率表、A/B 槽聚合触发语义、健康发布缺口与插件重构验收清单)。

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

    更新记录

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

  • Toyota panda safety:LKA/LTA 与纵向模式矩阵

    结论:Toyota panda safety 是MCU 本地规则,不验证 SecOC CMAC、雷达静默的正响应或车辆 ECU 是否接受命令。同一套 safety 代码按「原车 / 自控纵向 × 非 SecOC / SecOC × LKA / LTA」组合出不同模式,各模式允许的 TX 帧、长度与字段门都不同,不能把两个标志当成可随意组合。SecOC 相关位只在 ALLOW_DEBUG 构建下生效,上层即便能构帧也不能绕开普通固件或发布版 dashcamOnly 的能力边界。固定快照基线为 c8fb906,没有目标固件、车辆密钥、ECU 或实车验证。

    关键函数与调用顺序

    CarInterface._get_params() 配置 Toyota safety 参数、LTA / 替代制动 / SecOC、原车或自控纵向——注意上层参数和目标 ECU 已接受控制不是同一事实。toyota_init() 从 safetyParam 低八位读取 EPS 扭矩比例,高位选择替代制动、原车纵向、LTA;SecOC 位只在 ALLOW_DEBUG 下生效。

    toyota_rx_hook() 更新 EPS / 驾驶员扭矩、测量角、巡航 / 油门 / 制动和轮速;toyota_tx_hook() 分别检查 ACC、LKA 扭矩、LTA 角度 / 请求位、SecOC LTA2、AEB 和诊断保活。更外层,safety_tx_hook() 与 safety_fwd_hook() 先做地址 / 总线 / 长度白名单,继电器状态与静态转发阻断是独立的最终门。

    模式矩阵

    维度 选择与实际影响
    原车纵向 STOCK_LONGITUDINAL 非 SecOC 的 TX 仅含基础 LKA / LTA / HUD 与 0x343 取消;0x343 必须置 CANCEL_REQ 且加速度为零。
    自控纵向,非 SecOC 在基础 TX 上增加 DSU bus 0/1、PCS_HUD、0x750、0x283;0x343 可携带受限加速度,并另以 check_relay=true 登记。
    SecOC + 原车纵向 0x2E4 长度由 5 改 8,增加 0x131;0x343 仍只准零加速度取消;没有 0x183。
    SecOC + 自控纵向 0x2E4 长度 8,增加 0x131 和 0x183;0x343 只许零加速度,实际加速度走 0x183;没有非 SecOC DSU / 雷达诊断扩展表。
    LTA 标志 0x191 是否可执行受限角度由 LTA 位决定,即使同时设置 SecOC 位也如此;0x2E4 必须零扭矩 / 无请求。LKA 模式相反,0x191 必须无角度执行。SecOC 的 0x131 LTA2 在当前钩子中始终不准执行。
    替代制动 仅非 SecOC、非 LTA 的 RX 分支选择 0x224;普通分支用 0x226。LTA 分支固定普通 RX 表,SecOC 固定 0x101。

    自控纵向表里 0x343 同时经基础宏以 check_relay=false、扩展项以 check_relay=true 列出;通用继电器和转发代码遍历整个表,所以后者仍会触发对应故障 / 静态阻断,不能只看第一条白名单记录。

    RX 信号与健康

    所有 safety RX 均在总线 0。0x0AA 轮速 83 Hz,忽略 checksum / counter,但四个轮速故障位必须为零;0x260 转向传感器 50 Hz 检查 Toyota 累加校验,非 SecOC 的 LTA RX 表还要求 STEER_ANGLE_INITIALIZING=0。SecOC 初始化优先选择 TOYOTA_SECOC_RX_CHECKS,即使 LTA 位同时设置,该质量位也不作为 RX 有效性门。忽略某一完整性字段不等于不要求报文存活。

    报文 频率与门
    0x0AA 轮速 83 Hz,忽略 checksum / counter,四路故障位必须为零
    0x260 转向传感器 50 Hz,检查累加校验;非 SecOC LTA 表要求转角初始化位为 0
    0x1D2 巡航 / 油门 普通车 33 Hz,检查校验
    0x226 / 0x224 制动 40 Hz,忽略校验 / 计数;替代制动改用 0x224
    SecOC 路径 使用 0x176 巡航、0x116 油门和 0x101 制动

    toyota_rx_hook() 从 0x260 读取 16 位 EPS 扭矩,乘 safetyParam 低八位比例后采样,并把窗口最小值减 1、最大值加 1 以覆盖整数取整;驾驶员扭矩和测量角分别取独立字段。测量角仅在初始化位关闭时更新,不能把上一样本当成当前有效角。0x0AA 四轮原始值各减 6767 后求和,和不为零即视为移动。

    TX 权限与未覆盖载荷

    1. 扭矩 LKA:非 LTA 时 0x2E4 检查最大 1500、每帧上升 15 / 下降 25、相对 EPS 实测误差 350、实时差 450 与请求位切断节拍;LTA 模式仅允许零扭矩且请求位为零。SecOC 的 0x2E4 长度为 8,普通车为 5。
    2. 角度 LTA:非 LTA 时 0x191 的两个请求位、角度、TORQUE_WIND_DOWN 都必须不执行;LTA 时角度受速度相关变化率、最大 1657 原始单位及测量角邻域约束,两个请求位必须一致,wind-down 只可为 0 / 100,且驾驶员 / EPS 扭矩过高时禁止 100。SecOC 的 0x131 只允许请求位和角度字段均为零——这不是车辆认证成功的证明。
    3. 纵向:0x343 或 SecOC 0x183 的有符号加速度活动范围 -3.5 至 2.0 m/s²,未激活码为 0;共享门还要求允许控制且未踩油门。
    4. AEB 与诊断:仅非 SecOC 自控纵向白名单包含 0x283,前六字节必须全零,避免主机执行 AEB;0x750 仅允许固定载荷 0F 02 3E 00 00 00 00 00,用于雷达 tester-present。

    自制硬件与插件化契约

    车型插件提交 DBC / 平台、LKA / LTA、SecOC、制动地址及 EPS 比例的证据;未知 / 矛盾组合保持 noOutput。受信任网关独占 SecOC 密钥与签名、UDS 雷达静默、DSU / HUD 模板及节拍;普通插件只提交高层转向 / 加速度 / 取消意图,MCU safety 保留独立限幅。验证分层覆盖模式参数组合、错误 CRC / 质量位、双请求位不一致、wind-down、油门覆盖、非零 AEB、诊断错误载荷、签名失败与失联降级;随后是无负载台架和受控场地。当前没有这些目标车证据。

    常见问题

    LKA 和 LTA 模式能随便组合吗?

    不能。0x191 是否可执行受限角度由 LTA 位决定,即使同时设置 SecOC 位也如此;LKA 模式相反,0x191 必须无角度执行。0x2E4 在 LTA 模式必须零扭矩 / 无请求。未知或矛盾组合应保持 noOutput。

    「四个轮速故障位为零」是不是意味着数据都可信?

    不等于。0x0AA 忽略 checksum / counter,只用四个故障位做门;0x260 才检查 Toyota 累加校验并要求转角初始化位为 0。忽略某一完整性字段不等于不要求报文存活,健康判定要按报文明细区分。

    AEB 帧在 safety 里怎么处理?

    仅非 SecOC 自控纵向白名单包含 0x283,且前六字节必须全零,以避免主机执行 AEB。其它 DSU、PCS_HUD、0x1D2 / 0x412 等白名单帧没有同等级的逐字段门。

    panda safety 通过就等于车辆 ECU 接受命令了吗?

    不等于。这些只是 MCU 本地规则,不验证 SecOC CMAC、雷达静默的正响应或车辆 ECU 是否接受命令。SecOC 相关位只在 ALLOW_DEBUG 构建下生效,也不能绕开 dashcamOnly 等能力边界。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TOYOTA_PANDA_SAFETY_MODE_DEEP_DIVE.md(取用了模式矩阵、RX 健康门、TX 权限与插件化契约分析)。

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

    更新记录

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

  • Toyota 接口:能力参数怎么算,雷达静默事务又证明了什么

    结论:Toyota 车型接口把能力参数构建与雷达静默事务分成两件不同的事:前者在 _get_params() 里派生安全参数、转向模式与纵向能力,后者由 init() 通过 UDS 0x28 通信控制向总线 0 地址 0x750 发请求。源文档指出 disable_ecu() 的返回值只反映「本函数的请求路径判定」,而 Toyota.init() 丢弃该返回值、card.controls_update() 在 CI.init() 返回后直接设置 ControlsReady——这是一个确认状态缺口,但不等于任何具体车辆 ECU 实际未静默。本文为静态追踪,没有车辆、台架、UDS 抓包或回放结果。

    参数生成的先后次序

    get_car() 在指纹和固件识别后,把 alpha_long_allowed、is_release 传给车型 get_params(),再实例化接口。基类 CarInterfaceBase.get_params() 先装配平台质量、轴距、转向比和静态 flags,再调用 Toyota _get_params(),随后增加标准载荷并计算惯量和轮胎刚度。末尾的质量、惯量和轮胎刚度计算依赖 Toyota 已设置的 centerToFront 等值,所以单独调用 _get_params() 或只复制 values.py 的标志,不能重建最终 CarParams。

    Toyota safety model 固定为 toyota,safetyParam 先装载该车型 EPS_SCALE,再按动力 DBC、SecOC、角度控制和原车纵向模式叠加标志;ToyotaSafetyFlags 从第 9 位起定义,低字节留给 EPS 比例。换 DBC 或线束地址时,必须同步核对 MCU hook 的解析/白名单,不能把 CarParams 能力位看成安全策略的唯一实现。

    参数分支 取值 边界
    角度车型 steerControlType=angle、启用 LTA 标志、延迟 0.18 秒、steerLimitTimer=0.8 秒 与扭矩车型的标定不同
    其他车型 扭矩横向标定、默认延迟 0.12 秒、0.4 秒限制 按车型逐项核对
    旧 Prius 特例 非指定 EPS 版本时 0.25 秒延迟、0.2 度死区;另一不支持版本标 dashcamOnly 固件列表为空或未命中时不能推断该特例已验证
    混动标志 固件列表中存在 Ecu.hybrid;TSS2 混动纵向执行器延迟 0.05 秒 按固件列表判定
    BSM 能力 TSS2 且动力 fingerprint 中存在 0x3F6 不由所有静态配置直接推断
    radarUnavailable 仅测试该车型 DBC 映射是否包含 Bus.radar 不是运行时雷达在线/健康检测

    注意 TSS2 且 RADAR_ACC 的平台配置还会移除雷达 DBC,因此「未提供雷达解析器」与「已经成功静默雷达 ECU」是两个不同状态。get_pid_accel_limits() 按 CarControllerParams 给出加速度最小/最大值,函数签名中的当前/巡航车速并没有用于动态调整。

    纵向能力决策

    纵向能力由源码布尔表达式决定,不是对全部平台的实车适用性声明:

    输入条件 参数结果 运行含义
    TSS2 且非 RADAR_ACC 默认 openpilotLongitudinalControl=True 相机侧 ACC 路径,源码不调用 Toyota 雷达静默请求
    RADAR_ACC 且 alpha_long=True 加 DISABLE_RADAR,允许自控纵向;alphaLongitudinalAvailable=True 需走 ECU 通信控制
    RADAR_ACC 且 alpha_long=False 不加 DISABLE_RADAR,原车纵向;safety 加 STOCK_LONGITUDINAL 不应发自控加速候选
    非 TSS2 / 其他组合 由 DISABLE_RADAR 是否设置决定 逐平台核对

    autoResumeSng 在 Toyota 分支直接设为 openpilotLongitudinalControl。最低启用速度由 stop-and-go 能力选择 -1 或 19 mph 换算值;TSS2 加 RAISED_ACCEL_LIMIT 时,控制参数上限从 1.5 提升到 2.0 m/s²。发布版 SecOC 车型 dashcamOnly=is_release;card 若判为被动,会把 safety 配置改为 noOutput——这是上线许可门,不是 SecOC 密钥校验。

    雷达静默事务:证明了什么、没证明什么

    Toyota init() 仅在 DISABLE_RADAR 时调用 disable_ecu(),目标为总线 0、地址 0x750、子地址 0xF;默认请求是 UDS 0x28 的「使能接收/禁用发送」,作用于正常消息。disable_ecu() 最多尝试 10 次,每次先要求扩展会话 0x10 0x03 的 0x50 0x03 前缀响应,再发送通信控制请求。该函数自身注释明确警告此操作会禁用 AEB,应把原车主动安全能力变化纳入车型准入,而非当作普通功能开关。

    关键缺口在于:通信控制阶段把期望响应前缀设置为空字节串,调用 query.get_data(0),却丢弃该调用的返回字典;只要前置扩展会话查询产生条目且通信控制调用没有抛异常,disable_ecu() 就记录「ecu disabled」并返回真。get_data() 对非空响应使用 startswith(expected_response),空前缀无法鉴别 UDS 正响应内容。加之 Toyota.init() 丢弃 disable_ecu() 返回值,card.controls_update() 在 CI.init() 返回后直接设置 ControlsReady,即便诊断静默请求返回假,也没有从这条返回链阻断就绪。

    控制器在 DISABLE_RADAR 时按 20 帧节拍发送 tester-present 候选,但该帧生成并不证明 ECU 进入目标会话,也不证明会话保持或 AEB 真实状态。Toyota.deinit() 定义了相反的「使能接收/使能发送」请求,复用同一路径;但在本快照的运行链检索中未找到它的调用,因此不能把函数存在视为正常退出一定恢复 ECU。

    硬件与插件重构边界

    车型能力插件应产出期望配置而非宣称已经完成 ECU 改写,至少包含车型/固件/DBC 身份、纵向权限、AEB 影响、safety 模式及版本摘要。受信任诊断服务独占 UDS 写权限,把「请求接受」「正响应校验」「目标 ECU 读回/总线行为确认」「tester-present 存活」「恢复结果」设为独立状态;不满足确认条件时不得授予需要静默雷达的纵向执行能力。这一建议比当前源码多了安全门,属于拟议重构,不是现有实现描述。

    验证路径上,可先在无车环境用 alpha_long、RADAR_ACC、SecOC 发布版、不同 Prius EPS 固件和 0x3F6 指纹构造参数矩阵,再用模拟 ISO-TP 正/负响应、无响应及超时检查请求与回执,最后在隔离台架核对 ECU 静默、AEB/FCW、重启与恢复时序。

    常见问题

    disable_ecu() 返回真,是否说明雷达 ECU 已被静默?

    不代表。源文档指出该返回值只反映「本函数的请求路径判定」:通信控制阶段把期望响应前缀设为空字节串并丢弃返回字典,只要前置扩展会话查询产生条目且调用没有抛异常就返回真;get_data() 的 startswith 对空前缀无法鉴别正响应内容。因此这是确认状态缺口,不能断言具体车辆 ECU 的实际状态。

    radarUnavailable 是不是在检测雷达是否在线?

    不是。radarUnavailable 仅测试该车型 DBC 映射是否包含 Bus.radar,不是运行时雷达在线或健康检测;而 DISABLE_RADAR 反映的是参数层是否要发起诊断静默请求。源文档明确「未提供雷达解析器」与「已经成功静默雷达 ECU」是两个不同状态。

    为什么单独调用 _get_params() 复现不了最终 CarParams?

    因为基类 get_params() 先装配平台质量、轴距、转向比和静态 flags,再调用 Toyota _get_params(),末尾的质量、惯量和轮胎刚度计算依赖 Toyota 已设置的 centerToFront 等值。所以只复制 values.py 的标志或单独调用 _get_params(),都不能重建最终结果。

    两种 EPS 固件的 Prius 为什么处理不同?

    因为源码把旧 Prius 由 EPS 固件字节作例外:非指定版本时设 0.25 秒延迟和 0.2 度死区;明确识别到另一不支持的 EPS 版本时标记 dashcamOnly。源文档同时说明,固件列表为空或版本未命中时,不能据此推断该特例得到验证。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TOYOTA_INTERFACE_CAPABILITY_RADAR_DISABLE_DEEP_DIVE.md(取用了参数生成次序、纵向能力决策表、雷达静默事务的确认状态缺口与插件重构边界)。
    • 项目 02 —— openpilot-research/CAR_PROTOCOL_IMPLEMENTATIONS.md(仅用于确认 Toyota 品牌目录与启动识别门的总体位置)。

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

    更新记录

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

  • Toyota 固件指纹:子版本不同也能命中同一车型的三级匹配

    结论:Toyota 的固件指纹识别是三级顺序匹配:先精确固件匹配,再通用「至少两个唯一 ECU」模糊匹配,最后才调用品牌自定义的平台码回退。平台码只比较「零件号-平台-主版本」键,不比较子版本,所以小版本更新仍可能命中旧车型数据库;而「模糊」只是容忍子版本差异,并不容忍任意 ECU 集合。候选不唯一时必须保持被动或人工核验,不能在控制插件里猜。

    平台配置不是运行时健康

    CAR 的每个枚举成员包含 CarSpecs、车型文档、动力/雷达 DBC 映射和静态 flags。构造平台时执行配置 init(),创建 CAR 枚举时写入平台名并冻结配置对象——这是一份冻结的静态表,不是运行时健康状态。

    几个容易混淆的映射:TSS2 配置默认指向 toyota_nodsu_pt_generated 和 toyota_tss2_adas;SecOC 配置改用 toyota_secoc_pt_generated。若配置含 RADAR_ACC,两个配置类都只留下动力 DBC,表示本快照不按对应雷达 DBC 解析该路径——不能推论车辆没有物理雷达。

    同理,ToyotaCarDocs 默认标注 Toyota A 线束,SecOC 车型文档另用 CUSTOM 支持类型。源文档强调:文档展示字段、DBC 可用性、CarParams.radarUnavailable 和实车传感器健康是四个不同维度。EPS_SCALE 对大多数车型默认 73,少数车型显式覆盖;它进入 Toyota safety 参数低字节与状态侧 EPS 扭矩缩放,不能作为插件自报的可信运行标定。

    固件查询的实际覆盖

    FW_QUERY_CONFIG 声明三组总线 0 诊断请求,各组有独立 ECU 白名单:

    组别 请求流程 边界
    KWP tester-present 后查询 0x1a8801 与其他组共享 ECU 白名单机制
    OBD 版本 短 tester-present 后查询 OBD 版本 独立白名单
    UDS 版本 tester-present / 默认会话 / 扩展会话后查询 UDS 版本 独立白名单

    其中 extra_ecus 只列出额外可查地址,并不表示都参与模糊匹配;部分车型的 ABS 或发动机 ECU 被列为 non_essential_ecus,用来处理缺报或多地址。源文档特别提醒:不能把「可缺席」理解成「该 ECU 的所有错误版本都允许通过」,具体精确匹配语义由通用的 match_fw_to_car_exact() 实施。

    匹配顺序:精确、通用模糊、品牌回退

    通用识别顺序是固定的三级,越靠后越宽松,但每一级都不做「最像的一款」打分:

    阶段 条件 结果处理
    精确固件匹配 固件版本与数据库精确命中 返回是否精确及候选集
    通用唯一 ECU 模糊匹配 「至少两个唯一 ECU」 可返回多个候选
    Toyota 平台码回退 仅当前品牌在模糊阶段尚无候选时调用 返回所有通过的候选

    关键规则在 get_car():只有固件候选恰好一个时,才用它覆盖 CAN 指纹结果;零个或多个候选则保留 CAN 识别结果,显式固定车型设置又可覆盖两者。源文档明确这里没有把唯一固件候选与 CAN 指纹做一致性合取。此外,match_fw_to_car_fuzzy() 虽然接收 vin 参数,但 Toyota 此实现没有读取该参数——VIN 字符串不能消解平台码歧义。

    平台码算法逐步拆解

    get_platform_codes() 从固件字节提取零件号/平台/主版本键,并保留子版本集合。它的步骤可以逐条核对:

    1. 检查首字节是否为 0x01 至 0x03 的块数;未命中则按单块处理。
    2. 总字节长度必须等于块数乘 16,否则跳过该固件。
    3. 每块去掉头尾零和空格,但仅解析第一块;第一块长度 8、10、12 时分别尝试 short、medium、long 正则,且正则使用 search(),不是额外的全字节锚定校验。
    4. 返回字典键为 platform-major(短格式)或 part-platform-major(中/长格式),值是子版本集合。
    5. 第二块和子版本可被保留或解析出来,却不参与最终车型键比较——因此小版本更新可以命中旧车型数据库。

    在模糊匹配阶段,match_fw_to_car_fuzzy() 对每个候选车型遍历数据库里类型属于 fwdCamera、fwdRadar、eps 的 ECU,以地址/子地址从实车固件表取版本;每个预期 ECU 至少要找到一个平台键,否则该候选失败;通过的部分必须覆盖候选的这些预期地址。最后减去 FUZZY_EXCLUDED_PLATFORMS——该集合在本快照为空。

    歧义与插件契约

    跨地址、漏回包、固件格式异常会导致匹配缺席;共享平台/主版本键则可能导致多个候选。源文档对此的定性很直白:这里的「模糊」是容忍子版本差异,不是容忍任意 ECU 集合,更不是把单条相机固件当作充分身份凭证。

    对于硬件自制或插件化平台,错误识别会连带选择错误的 DBC、转向模式和 safety 参数。因此源文档提出一条比现状更严格的拟议契约:车型识别服务应返回 CAN 候选、固件候选及其交叉一致性、证据 ECU/地址/原始回包、精确或模糊等级、冲突原因和数据集版本;安全核心在候选唯一、且 DBC/固件/safety 组合得到验证前,保持 noOutput。这是重构建议,不是当前行为。

    测试层面,test_toyota.py 检查角度/RADAR_ACC 标志属于 TSS2、当前 LTA 车型集合、TSS2 动力 DBC、必要 ECU 项和固件格式,并遍历数据库版本检查专属回退的唯一性与排除集合。但这只证明「现有固件数据库样本」受到约束,不能证明未知地区、替换 ECU 或故意构造的相似固件不会误识别;且本轮未运行这些测试。

    常见问题

    为什么小版本固件更新后还能识别成同一车型?

    因为 get_platform_codes() 返回的键只到「零件号-平台-主版本」,值是子版本集合,而子版本不参与最终车型键比较。第二块和子版本可被保留或解析出来,却不会被用来区分车型,所以小版本更新可以命中旧车型数据库。

    固件匹配失败一定会退回到品牌专用逻辑吗?

    不一定。顺序是精确固件匹配、通用模糊匹配,最后一层才调用 Toyota 自定义平台码回退,而且仅当当前品牌在模糊阶段尚无候选时才调用。若前面的阶段已经返回候选,就不会进入品牌回退。

    VIN 能帮助消除固件候选歧义吗?

    在这份实现里不能。match_fw_to_car_fuzzy() 虽然接收 vin 参数,但 Toyota 该实现没有读取该参数,因此 VIN 字符串不能消解平台码歧义。

    多个固件候选时,最终选哪个车型?

    get_car() 只有在固件候选恰好一个时才用它覆盖 CAN 指纹结果;零个或多个候选则保留 CAN 识别结果,显式固定车型设置又可覆盖两者。源文档说明这里没有把唯一固件候选与 CAN 指纹做一致性合取,因此歧义不会被自动「合取」消解。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TOYOTA_PLATFORM_FIRMWARE_MATCHING_DEEP_DIVE.md(取用了 FW_QUERY_CONFIG 三组请求、三级匹配顺序、平台码算法步骤与拟议插件契约)。
    • 项目 02 —— openpilot-research/CAR_PROTOCOL_IMPLEMENTATIONS.md(仅用于确认 match_fw_to_car() 与 get_car() 在整条识别链中的位置)。

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

    更新记录

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