车载硬件状态:300 秒驻车、11.8 V 与 45 W 的关机链

作者:

在

结论:硬件状态的信任缺口集中在两处:缺测被静默当成 0(ThermalZone.read() 在温度文件不存在时返回 0,HardwareBase 多数方法是空操作或零值默认),以及慢速链没有采样时间戳(hw_state_thread() 消费端无采样时间,旧网络/USB 状态可能继续出现在 deviceState)。此外驻车容量是估算值而非车载 BMS 实测电量。以下基于固定源码快照 c8fb906 的静态分析与离线探针,不是实板验证。

平台抽象与 hardwared 线程

平台选择在导入时就固定:有 /AGNOS 文件则用 HardwareComma,否则用 HardwarePc,并非运行时可插拔发现。HardwareBase 除 get_device_type() 外多数方法有空操作或零值默认实现——移植时不能把「继承成功」等同于「能力可用」。

组件 / 函数 输入与输出 实际职责
HARDWARE 选择 /AGNOS 文件 → HardwareComma 或 HardwarePc 导入时固定平台实例,并非运行时可插拔发现
ThermalZone.read()、ThermalConfig.get_msg() sysfs 温区 → *TempC 字段 按温区名称查找并读取;温度文件不存在返回 0,不是显式失效标志
hw_state_thread() 网络、调制解调器、USB → 容量 1 的队列 每约 10 秒或 USB 拓扑变化时抓取慢速状态;队列满或采集失败会消耗本次触发,主线程沿用旧值
hardware_thread() pandaStates、peripheralState、温度、Params → deviceState 点火边沿和约 2 Hz 周期更新,处理启动门、热状态、风扇目标、功耗与关机请求
FanController.update() 温度、点火 → 目标风扇百分比 积分 PID 加前馈,点火变化重置
PowerMonitoring.calculate() 车端电压、点火 → 累计耗电 / 剩余容量估计 驻车按设备功率积分,点火时按固定 45 W 充电率估计;约 10 秒保存 CarBatteryCapacity

点火、热状态与行车资格

pandaStates 中任一已知 panda 的点火线或 CAN 点火信号可建立点火;超过 5 秒未收到状态则清除点火,但线束连接状态 in_car 仅在收到 panda 状态时更新。行车资格分两层:已有行车状态要求点火、无 onroad cycle、未达到 critical;从驻车新启动还要求条款/培训、空间、设备已启动、温度低于 overheated、非卸载等启动条件。

因此热状态迟滞允许「过热但未严重」的在途状态暂时保持,不能把「禁止进入行车」误写成「立即退出行车」。温度源分两组:驻车危险检查用内存、CPU、GPU 的最大值,行车热状态再加入 PMIC,两者都经 5 秒一阶滤波;mici 与其他设备采用不同热带阈值,驻车高温可直接升到 critical。风扇目标在温度告警时被强制为 100%,随后经 pandad 发给 panda;panda 回报的转速另由 selfdrived 检查。

风扇 PID 与温度带

风扇与温度构成一条闭环:温度决定目标百分比,panda 执行并回报转速,故障事件则由 selfdrive 侧产生。关键参数如下。

项目 参数 / 行为
风扇控制 积分 PID 加前馈,点火变化时重置
行车风扇范围 30–100%
驻车风扇范围 0–30%
温度告警 风扇目标强制 100%
温度滤波 5 秒一阶滤波
温度源 驻车用内存/CPU/GPU 最大值;行车再加入 PMIC

电源估算与关机条件

普通关机不是单条件触发,而是「前置状态 + 多个触发之一」的组合;ForcePowerDown 能绕过普通条件,但仍受末尾约束。

条件 阈值 / 机制
普通关机前置 驻车、连接车辆、未禁用关机、驻车超过 300 秒
触发之一 驻车超过 30 小时
触发之二 低通电压低于 11.8 V
触发之三 估计容量耗尽
点火充电率 按固定 45 W 估计
ForcePowerDown 绕过上述普通条件,但仍受末尾的 started_seen / 最短开机时间约束

hardwared 只写 DoShutdown;真正调用关机的是 manager.main()。

缺测的零值风险与插件契约

两个具体风险值得单独记住:hw_state_thread() 消费端无采样时间戳,旧网络/USB 状态可能继续出现在 deviceState;ThermalZone.read() 把缺失温区当 0。这类慢速状态之所以能继续沿用旧值,正是因为消费端没有采样时刻可供判断新鲜度;新平台应给每条状态附上采样时间与失效哨兵。这些是移植设计风险,需要在目标平台上显式处理,而不是沿用零值默认。

因此新平台要显式声明能力与缺测状态:标定 sysfs 温区名、单位、采样频率、失效哨兵;定义电压测点、功率方向与关机电气动作;点火、温度、关机和风扇属于可信任设备服务,需要时效性、故障降级和唯一发布者。硬件插件不得自行宣布 deviceState.started 或绕开独立 panda 安全门。

外置计算模块与触摸记录

同一条 hardwared 线程里还挂着外置计算模块与触摸记录两条支线。Chestnut.update() 在驻车时限次刷固件,并对外置 GPU 的丢电、链路、过热、模型失败分别生成不同告警;chestnut_state_thread() 读取供电与 PCIe 状态,并按有效位合并 GPU 状态。也就是说「外置模块可用」本身也是一组需要区分失效类型的判定位,而不是一个布尔值。

触摸记录则只属诊断路径:touch_thread() 仅在 comma 硬件启动,按事件帧分组发布到原始 touch 主题,UI 交互另由 raylib 采集,两者不应混为一谈。此外,hardware_thread() 里的 ign_edge 是「已启动状态」与 onroad 条件的持续差异,不一定是单次点火边沿:启动条件受阻而 onroad 条件仍真时,它会持续绕过约 2 Hz 的周期门,device_booted 一旦为真也会在本进程锁存。

常见问题

温度读不到会怎样?

ThermalZone.read() 在温度文件不存在时返回 0,这不是显式失效标志。缺测不能被静默当作 0 °C,新硬件平台必须明确失效处理。

普通关机需要满足哪些条件?

前置是驻车、连接车辆、未禁用关机且驻车超过 300 秒;再由超过 30 小时、低通电压低于 11.8 V、或估计容量耗尽三者之一触发。

驻车容量是车载 BMS 实测电量吗?

不是。它是估算值:无点火时按平台报告的设备功率积分,有点火时按固定 45 W 充电率估算,并非测得的真实电量。

过热会立即退出行车吗?

不一定。热状态迟滞允许「过热但未严重」的在途状态暂时保持;「禁止进入行车」与「立即退出行车」是两条不同的判定。

延伸阅读

参考资料

  • 项目 02 —— openpilot-research/HARDWARE_STATE_DEEP_DIVE.md(硬件状态、供电与热管理,含源码行号索引)
  • 项目 02 —— openpilot-research/probes/test_power_monitoring_contract.py(电源估算与关机条件的离线探针)
  • 项目 02 —— openpilot-research/probes/test_fan_controller_contract.py(风扇 PID 上下限与积分的离线探针)

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

更新记录

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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注