标签: 车辆状态

  • 17 个品牌参数怎么构建:CarParams 冻结只到顶层,嵌套字典仍可变

    结论:车型参数不是一张静态表,而是「17 个品牌枚举 → PLATFORMS 候选字典 → CarSpecs 尺寸 + PlatformConfig 文档与 DBC → 品牌 _get_params() 覆写」的多段构建结果。冻结(freeze)只作用于配置对象这一层:flags 被锁定后不可改,但嵌套的 dbc_dict 与 car_docs 仍可原地修改,override() 返回的还是未冻结副本。因此「能生成 CarParams」只说明字典装载成功,既不等于该车型被识别,也不等于控制器获准发送。以下为固定源码快照 c8fb906 的静态结构分析。

    参数构建的顺序与产物

    values.py 汇集 17 个品牌的 CAR 枚举,并生成候选名到平台对象的 PLATFORMS 字典。每个平台带着三样东西:描述整车尺寸的 CarSpecs、记录文档与 DBC 映射的 PlatformConfig,以及一组 flags。枚举构造时给配置填 platform_str 并冻结配置对象;CarSpecs 本身是 frozen dataclass。

    真正把参数拼起来的是两段函数。get_std_params() 先写入车型名、横向最大加速度文档值、控制类型、轮速系数、PCM 巡航与纵向缺省;随后 get_params() 复制平台规格并调用品牌 _get_params()。这个钩子可以依据 CAN 指纹、固件、开发/发布模式设置总线、雷达、纵向与控制调参,是品牌策略的主要落点。

    品牌覆写之后,普通汽车会加 STD_CARGO_KG=136 kg,再按以 Civic 为基准的比例公式估计 rotationalInertia 与 tireStiffnessFront/Rear;notCar 跳过载荷。这里要强调:刚度与惯量是启发式缩放,不是本次车辆的在线辨识结果,自制硬件接入车型时这些动力学参数不保证准确。

    阶段 入口 产出或作用
    平台注册 values.py / PLATFORMS 17 个品牌候选名映射到平台对象与 PlatformConfig。
    共同缺省 get_std_params() 写入车型名、控制类型、轮速系数、巡航与纵向缺省。
    品牌覆写 品牌 _get_params() 按指纹/固件/模式设置总线、雷达、纵向、panda 安全配置。
    载荷与动力学 STD_CARGO_KG 与缩放公式 非 notCar 加 136 kg,估计转动惯量与轮胎刚度。

    冻结边界:顶层不可变,嵌套仍可变

    隔离探针确认了一个容易被误读的边界:创建 Platforms 子枚举时,PlatformsType.__new__() 给配置写入平台名并冻结,随后直接改 flags 会抛异常;但 dbc_dict 的条目与 car_docs 列表仍可原地修改。

    更关键的是 override() 的语义。对已冻结配置调用 override(flags=...) 会通过 dataclasses.replace() 产生一个未冻结的新对象,且新旧配置共用同一 dbc_dict 引用;相对地,CarSpecs.override() 返回的新规格仍是 frozen dataclass。也就是说,「冻结的是配置对象属性」不能被误解为整个嵌套对象图都经过不可变性与签名校验。自制插件若用 manifest 描述车型,需把嵌套映射与列表做不可变快照或深拷贝并纳入签名与哈希,不能只依赖顶层 freeze()。

    扭矩数据与横向回调

    横向能力由三份 TOML 与一组回调共同决定。get_torque_params() 读取 substitute.toml、params.toml、override.toml,以 legend 解释三列数值,结果缓存在进程内;同一候选若直接出现在多个 TOML 会抛异常,替代目标则按 override 优先、params 次之取值。configure_torque_tune() 设置 FRICTION、LAT_ACCEL_FACTOR、零 offset 与角度死区。

    缺省前馈 get_steer_feedforward_default() 约为目标转角乘车速平方,GM 等品牌可重写。缺省的 torque_from_lateral_accel_linear() 与 lateral_accel_from_torque_linear() 按 latAccelFactor 正反映射,品牌同样可替换。要注意 MAX_LAT_ACCEL_MEASURED 用于 CarParams.maxLateralAccel,而摩擦与侧向加速度因子进入扭矩调参,三者不能互换。

    源或函数 实际作用 关注点
    get_torque_params() 读取三份 TOML 并缓存结果 同候选出现在多个 TOML 会抛异常;替代目标按 override 优先。
    configure_torque_tune() 设置摩擦、侧向加速度因子、零 offset 与角度死区 数据表与平台覆写共同决定控制器输入,不能假设热改立即生效。
    get_steer_feedforward_default() 缺省前馈约为目标转角乘车速平方 GM 等品牌可重写,不是跨车型通用标定。
    torque_from_lateral_accel_linear() 按 latAccelFactor 正反映射扭矩与侧向加速度 需验证符号、单位、摩擦与零点。

    实例运行契约与基类扩展点

    CarInterfaceBase.__init__() 创建品牌 CarState、其 CANParser 集合与 CarController,并把解析器的 DBC 名传给控制器。update() 更新所有解析器、调用品牌状态函数、汇总 canValid/canTimeout 并处理仪表速度与按键;apply() 委派品牌控制器生成回报与待发 CAN 帧,但它不负责硬件限幅。

    仓储里还有几个常被忽略的基类语义:RadarInterfaceBase.update() 缺省每五次调用返回空雷达数据、其余返回 None;init()/deinit() 供品牌实施 ECU 初始化或恢复,基类为空,且 deinit() 在 card 退出时不保证被调用;get_interface_attr() 动态导入品牌 values/fingerprints 属性,ImportError/OSError 会被静默跳过,因此它并不是可靠的插件装载审计。

    基类接口 职责与边界
    __init__() 创建品牌 CarState、CANParser 与 CarController;DBC 名传给控制器。
    update() 更新解析器、汇总 canValid/canTimeout、处理仪表速度与按键。
    apply() 委派品牌控制器生成回报与待发帧,不负责硬件限幅。
    RadarInterfaceBase.update() 缺省每五次返回空雷达数据,其余返回 None,有雷达平台须覆写。
    init()/deinit() 品牌可实施 ECU 初始化或恢复;deinit() 不保证在 card 退出时被调用。
    get_interface_attr() 动态导入品牌属性,异常静默跳过,非可靠装载审计。

    插件化边界与验证缺口

    面向自制硬件,源文档给出的是一组建议设计而非已实现能力:平台插件以版本化 manifest 声明车型、硬件拓扑、DBC 哈希、固件证据、单位、参数范围与所需安全模式;参数构建拆成纯函数与受限生命周期钩子,_get_params()、init() 不应由普通诊断或 UI 插件获得原始 CAN 发送权;行车期间冻结参数与插件版本,重启后再重新识别与验证。

    同时应区分四个层级的门:「可生成 CarParams」「CANParser 正常」「控制器允许发送」「MCU 允许执行」;任一失败都应退回只读或 noOutput。需要提醒的是,现有测试只覆盖参数基本范围与空 CAN 下的不崩溃行为,不覆盖真实车型识别、DBC 真实性、全部 _get_params() 分支与实车动力学。自研硬件仍需要离线日志、台架与实车的分级验证。

    常见问题

    冻结后的 PlatformConfig 真的完全不能改吗?

    不是。冻结只锁住配置对象属性:flags 不可改会抛异常,但嵌套的 dbc_dict 条目与 car_docs 列表仍可原地修改。override() 还会通过 dataclasses.replace() 生成未冻结新对象,并且新旧配置共用同一 dbc_dict 引用。插件若依赖不可变性,需自行做深拷贝并纳入签名。

    STD_CARGO_KG 是 136 kg 吗,为什么有的车型不加?

    源文档给出 STD_CARGO_KG=136 kg,普通汽车在品牌覆写后加上,notCar 跳过载荷。转动惯量与轮胎刚度也是按以 Civic 为基准的比例公式估计的启发式缩放,不是本次车辆的在线辨识结果。

    get_non_essential_params() 能当作上车参数吗?

    不能。它用空 CAN 指纹、空固件及关闭的特性开关构建参数,自身文档明确警告缺少真实 FW/指纹时控制必需参数可能不完整或错误,适合文档、测试与离线展示,不是上车控制参数的证明。

    同一个候选车型出现在多个扭矩 TOML 会怎样?

    会抛异常。源文档说明:同一候选若直接出现在多个 TOML 会抛异常;被替换的目标则按 override 优先、params 次之取值。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/CAR_PLATFORM_PARAMS_CONTRACT_DEEP_DIVE.md(参数构建顺序、冻结边界、扭矩 TOML 与基类实例契约)。
    • 项目 02 —— openpilot-research/ 同目录探针记录:四项平台配置冻结契约与假平台枚举隔离探针结论。

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

    更新记录

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

  • 同一个「转向灯」在三家车厂是三种实现:车辆状态归一化的坑

    结论:「转向灯亮了」在代码里不是一个布尔值,而是一套按更新次数计数的状态机——而且同一件事在三家车厂有三种实现:有的从灯泡信号推算、有的从拨杆信号读取、有的直接解枚举。所以做跨车型信号适配时,不能假设「同一个信号名 = 同一种行为」。

    从 CAN 帧到车辆状态:一条固定链路

    不管什么车型,车辆状态都走同一条主干(本文基线为源码快照 c8fb906):

    阶段 做什么 产出
    CAN 接受 等待并取出 CAN 批次 原始帧按总线分组
    接口更新 逐个更新各总线的解析器,再调车型状态 解析后的信号值
    品牌状态 按车型规则解信号含义 车型语义层
    共同处理 统一滤波、去抖、迟滞 可消费的车辆状态
    发布 写入车辆状态消息 下游各进程消费

    关键点在于:健康位是解析器级与总线级的汇总,而不是每个字段各自带有效性和年龄。也就是说,「CAN 有效」不代表「转向灯字段可信」。动态注册、失效累计和空解析器的边界,是理解这个汇总的前提。

    同一个「转向灯」的三种实现

    这是跨车型适配里最容易踩的坑:

    车厂 来源 保持方式 方向盘去抖
    现代系列 灯泡类信号 保持计数 50 次 扭矩阈值加 5 次迟滞去抖
    本田 拨杆信号 保持计数 250 次 直接用车型阈值,无共同去抖
    丰田 直接解枚举 不做灯泡式计数 直接解扭矩阈值

    更要注意两个陷阱。第一,保持计数是「更新次数」,不是时间。代码里的保持值既不是毫秒也不是设备时间戳——如果自制设备以不同频率送 CAN,所有计数保持和滤波动态都要重新标定。第二,灯泡法与拨杆法不等价:前者靠亮灯刷新计数、熄灯逐循环递减,方向快速切换时允许短暂双灯为真;后者靠拨杆上升沿设保持,看到反方向拨杆才清对侧计数。

    速度:三个数不能混成一个数

    车辆状态里同时存在三个速度量,用途完全不同:

    量 怎么来 用途与限制
    原始速度 四轮轮速算术平均,乘单位系数与轮速系数 四轮平均不是鲁棒估计,单轮故障或打滑会直接污染结果
    滤波速度 一维状态滤波,同时输出速度与加速度 原始值与滤波位置差超过 2 m/s 时把加速度重置为零;这是代码策略,不等于该帧测量真实
    仪表速度 先由滤波速度回填,之后应用迟滞并做低速置零 显示与控制的取数口径不同,不能互换

    滤波的采样周期假设是 10 毫秒。自制设备若以其它频率送帧,滤波动态与计数保持会同时失真。

    定速按键与档位:必须按车型核验

    按键生效的判定是「松开沿」而不是「按下」:在非特定巡航模式下,定速加/减按钮的松开瞬间置一个单帧启用请求。但这条共同默认规则会被部分车厂整支覆写——所以「按下按钮」在 A 车生效、在 B 车可能完全无效。档位解析同理:空值或未知枚举会被统一映射为「未知」,而这个映射必须与驾驶许可条件保持一致,否则可能出现「档位未知但被认为可行驶」。

    盲区信号:缺失不等于无障碍

    盲区输入在三家车厂都受配置开关控制——没有对应配置时,字段连赋值都不会发生。这意味着布尔字段的默认值不能解释为「盲区已被验证为空」,它只是「这项没被检查」。盲区信号会进入变道意图门、车道偏离预警的冷却期判定,以及驾驶员介入判断,因此把「未配置」当成「无障碍」是会直接影响行为的误读。

    自制信号适配插件该暴露什么

    如果要接自己的传感器或车型,插件至少应逐项暴露:来源、单位、符号、采样/接收时间、年龄上限、缺失与故障状态。仲裁层再把它映射到既有的车辆状态语义。特别是盲区这类输入,缺失必须显式传播,不能静默塌缩成「无障碍」。车型安全策略、刹车与取消接管、硬件收发检查应留在受信任边界内。

    可复用的交叉验证入口是项目自带的回放测试——它会比较部分车辆状态字段与硬件安全状态(原始车速、刹车、巡航、方向盘角度),但它不是每个信号的穷尽测试。

    常见问题

    「CAN 有效」能代表转向灯字段可信吗?

    不能。有效位是解析器与总线级的汇总,按报文判定,不给每个字段单独的年龄与可信度。要判断具体字段,得看它所在报文的时间戳与超时状态。

    为什么不同车型的转向灯逻辑不能共用一套阈值?

    因为来源就不同:有的从灯泡推算、有的读拨杆、有的解枚举;保持计数分别是 50 次和 250 次,去抖机制也不同。共用阈值在某一车型上就是错的。

    四轮平均速度可以直接当车速用吗?

    不能直接当鲁棒车速。它是算术平均,不是异常值剔除估计,单轮打滑或故障会污染结果。这也是为什么后面还要接一层滤波与迟滞。

    盲区提示没亮,能说明侧后方没车吗?

    不能。没有对应车型配置时该字段根本不会被赋值,默认值表示「未检查」而不是「检查结果为空」。缺失必须单独传播。

    延伸阅读

    参考资料

    • 项目 02 —— NAS 谭健强/openpilot-research/CAR_STATE_NORMALIZATION_DEEP_DIVE.md(车辆状态归一化,含源码行号索引)
    • 项目 02 —— openpilot-research/CAN_PARSER_HEALTH_DEEP_DIVE.md(解析健康与失效累计)
    • 项目 02 —— openpilot-research/ACTUATION_GATE_CHAIN_DEEP_DIVE.md(下游门控与失效矩阵)

    说明:本文为对固定源码快照的静态分析,未运行回放测试、未连接实板、未按车型/年款核验具体信号含义与失效值。共同辅助函数不是所有车型的必经路径。

    更新记录

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

  • 赛道日的准备清单:把自己调到最佳状态

    结论:赛道日准备里最被低估的变量不是硬件,而是驾驶员状态。很多车手在避震、刹车、轮胎上投入大量精力,却忽略了睡眠、补水与热身这三项会直接改变反应时间的因素——而反应时间的变化在赛道上会以「刹车点提前量」的形式直接兑现成圈速。同时,所有硬件调整都必须在赛道日之前完成验证,赛道日当天只做已验证项的微调。

    睡眠是最被低估的变量

    睡眠不足 5 小时,反应时间会显著变长;而赛道上的反应时间直接体现在刹车点提前量上。一个平时很稳定的刹车点,可能因为没睡好就晚了 20 米——这 20 米不会被感知成「我反应慢了」,而会被感知成「今天车不对」,于是你开始误调硬件。

    建议是:赛道日前一天正常作息,不要补觉也不要熬夜。连续熬夜后的「亢奋状态」往往比正常状态更危险,因为主观上的兴奋会掩盖客观的反应迟钝,让人倾向于冒进。

    赛前两小时该做和不该做的事

    事项 该做 不该做 原因
    车辆设定 沿用已验证的设定 尝试新的避震或胎压调整 未验证的改动会把时间浪费在适应上
    补给 补水 补糖 出汗量远超日常,脱水对反应速度的影响比血糖波动更明显
    热身 动态拉伸 冷车状态下做静态拉伸 静态拉伸会短暂降低力量输出
    座椅 调到能承受的最低位置 为了舒适牺牲坐姿 重心低 20 mm 的效果常超过一整套避震

    胎压:不要用静态冷胎压

    冷胎压只是一个起点。随着胎温上升,胎压会上升 0.1–0.2 bar;正确的做法是设定一个热胎目标压,然后在跑几圈之后测量并微调,而不是把冷胎压当作目标值直接设定。

    前后压的平衡比绝对值更重要。偏高的前压会让转向变轻,但推头倾向会增加,在数据上表现为前胎滑移率异常升高。因此调整的顺序是:先定热胎目标压,再调前后平衡,最后才微调绝对值。

    重心:最简单的改装

    座椅降低 20 mm、重心向发动机舱前移一点,效果往往超过一整套避震的调整。原因是身体的横向移动会让重心跟着移,这部分力最终由避震和轮胎承担——降低驾驶者重心等于直接减少这部分负荷转移。

    建议是:赛道日当天就把座椅调到你能承受的最低位置,不要为了舒适牺牲。这是所有调整项里成本最低、收益最确定、且完全可逆的一项。

    结束后该记录的三件事

    每次赛道日结束,凭感觉记下来的东西一周后就失真了。需要固化成文字的是这三件:

    记录项 要写清什么 用途
    最好圈 圈速,以及该圈是在什么条件下跑出来的(胎况、温度、圈序) 判断该圈是否可复制
    最大失分路段 具体分段编号,而非「后段有点慢」这类描述 下次直接定位到该段
    结束时的身体状态 专注度、疲劳程度、有无脱水或饥饿 把驾驶员状态纳入圈速归因

    第三项最容易被跳过,也最有价值:它让「今天慢是因为车」和「今天慢是因为人」这两种归因在事后还能被区分开。

    常见问题

    赛道日当天可以改避震设定吗?

    不建议。任何未在赛道日之前验证过的避震或胎压调整,都会把当天的有效时间浪费在适应上,而且改动之后的数据无法与历史数据对比,等于这次记录作废。当天只做已验证项的微调。

    冷胎压该设多少?

    不应把它当目标值。冷胎压只是起点,随着胎温上升胎压会升高 0.1–0.2 bar。正确做法是先定一个热胎目标压,跑几圈后实测再反推冷胎设定值。

    没睡好还要不要上赛道?

    需要主动降低预期与激进程度。睡眠不足会拉长反应时间,直接体现为刹车点推迟;这种迟钝没有体感,容易被误判成车辆问题,进而导致误调硬件。若当天无法补觉,至少把驾驶强度降一档。

    赛前热身做静态拉伸有什么问题?

    在冷车(身体未热)状态下做静态拉伸,会短暂降低力量输出。赛前热身应以动态拉伸为主,把静态拉伸放到赛后放松阶段。

    延伸阅读

    参考资料

    • 本站赛道库 —— /data/tracks/(赛前确认赛道几何与分段方案)
    • 本站文章 —— /blog/trackday-data-review-segment-method/(失分路段的记录口径)
    • 说明:本文属赛道工程实践经验总结,涉及生理反应的数值为经验量级,个体差异大,非医学结论。

    说明:本文为赛道日准备的经验性方法总结,文中 5 小时、20 米、20 mm、0.1–0.2 bar 等数值为便于说明方法引用的典型量级,非实测统计结果,不同车型与个人体质下差异可能很大。涉及身体状态与生理反应的内容不构成医学建议。任何车辆设定调整请以厂商规格与专业技师意见为准。

    更新记录

    首次发布 2026-10-13(原发布于建站期,本次按本站 GEO 规范重写:补充结论段、赛前两小时对照表与记录项表、常见问题与结构化数据)。最近核对:2026-10-13