结论:座舱 DMS 的链路是 camerad 座舱帧经固定 1440×960 luma warp 进入 tinygrad 编译模型,输出一维向量再按元数据切片解码为左右驾驶员的脸姿态、位置与八类概率。发布消息的顶层 valid 恒为真,它只表示组包正常,不是摄像头视角、帧年龄、标定有效性与模型置信度都合格。本文为固定源码快照 c8fb906 的静态分析,未运行模型或图像回放。
进程、构建与消息链
manager 进程表在驾驶员视角条件下启动模型进程,非 webcam 的 PC 默认禁用。main() 等待 camerad 的座舱 VisionIPC,连接后按流报告的宽高加载模型和 warp 产物;每次 recv() 返回缓冲才运行并发布 driverStateV2。模型输出服务名义 20 Hz,真正频率由相机帧与推理耗时决定。进程只订阅 extrinsicsCalibration,没有在循环中对该主题做 SubMaster.all_checks() 门。
构建侧 SConscript 从 dmonitoring_model.onnx 编译 dmonitoring_model_tinygrad.pkl,并为源码列出的两组座舱相机尺寸生成独立 dm_warp_<宽>x<高>_tinygrad.pkl。warp 目标为 DM_INPUT_SIZE=(1440,960),只使用亮度平面、边界填充值 16、变换矩阵放在 NPY 设备;NV12 stride/高度/缓冲大小由 get_nv12_info() 计算。缺少匹配尺寸的 warp 产物时,模型初始化会在打开文件处失败,而不是自动支持任意 USB 摄像头。
| 组件/函数 | 实现功能 | 边界 |
|---|---|---|
ModelState.__init__() |
读取 OOB 模型,解析输入形状/输出切片元数据,预分配模型输出及相机尺寸对应 warp。 | load_oob() 依平台选 QCOM/METAL/CPU:LLVM,构建产物与后端必须兼容。 |
ModelState.run() |
写入外参 calib,用 VisionBuf 内存指针建立 tinygrad 张量,执行 warp 与模型,拷贝一维 float32 输出。 |
按缓冲指针缓存零拷贝张量;前提是上游环形缓冲布局和生命周期稳定。 |
slice_outputs() |
按 OOB 元数据中的切片把一维输出分为各预测头。 | 分割布局不硬编码在 Python 中;模型升级必须同步元数据。 |
parse_model_output() |
sigmoid 转概率,脸部描述向量末六维经 safe_exp 变为标准差。 |
safe_exp() 裁上界 11 抑制指数溢出;这里不做完整 isfinite 校验。 |
fill_driver_data() |
将左右侧各自的姿态、脸位置/标准差和八类概率写入消息。 | 姿态取描述向量前三维,位置取第 4-5 维。 |
main() |
接流、读取最新外参、逐帧推理、解码并发送。 | 只在有新外参消息时复制 rpyCalib,未显式检查其顶层 valid。 |
图像几何与内参选择
首次收到帧后,main() 按 buf.width 是否等于 _os_fisheye.width 选择 _os_fisheye 或 _ar_ox_fisheye 内参,并计算目标模型内参到原相机内参的逆变换;其后不随外参变化重算图像 warp。八项原 main() 假 VisionIPC/模型探针确认:首个非空帧按宽度是否等于 _os_fisheye.width 选择内参、不检查高度,生成的 model_transform 此后锁存,后续缓冲宽度变化也不重算。recv() 为空时立即继续,既不轮询外参也不发布。
外参 rpyCalib 被单独送进模型 calib 输入,不是这个固定的图像 warp 矩阵。外参长度不匹配会在推理前抛错;推理抛错则本帧不发布。SEND_RAW_PRED 判断的是非空字符串,值为 '0' 同样会携带原始输出字节。两组相机的宽高/焦距来自硬编码配置,源码还提示其中一组鱼眼焦距近似值可能不精确。自制相机不能只通过改 VisionIPC 流名完成适配,需重做标定/warp 与质量验证。
输出切片与不确定度解码
slice_outputs() 仅按元数据切片并加 batch 轴,切片超出原向量时得到短数组而不报长度错误。parse_model_output() 把每侧描述向量的末六维经 safe_exp 转标准差,其余前段作为姿态/位置;fill_driver_data() 只取前三项姿态和第 4-5 项位置及对应五项标准差。极大标准差 logit 在 11 截顶,NaN 仍传播;sigmoid 借用这个截顶指数,因此极负 logit 的概率下限约为 1/(1+exp(11)),不是精确零。
解码同时输出 LHD/RHD 两套人脸结果及 wheelOnRightProb。下游 DriverMonitoring._update_states() 按 RHD 学习结果选择一侧,然后根据脸概率/姿态标准差决定是否把分心类型纳入提醒。因此 driverStateV2 是预测,不是已完成的驾驶员状态判定。八项原切片/解析/组包探针确认:合成的九维脸描述可在位置切片为空时仍由 get_driverstate_packet() 组出顶层 valid=True 消息,这只证明缺少形状校验,不代表真实模型会输出九维描述。
| 构造输入 | 原函数观察结果 | 验证范围 |
|---|---|---|
| 切片超出原向量 | 得到短数组,不报长度错误 | 只证明切片函数不独立校验长度。 |
| 极负 logit 概率 | 下限约 1/(1+exp(11)),非精确零 |
sigmoid 借用 11 截顶指数。 |
| 位置切片为空的九维描述 | 仍组出顶层 valid=True 消息 |
缺少字段完整性校验。 |
改变 location_ts |
假消息各字段不受影响 | 发布结构不含相机 SOF 时刻。 |
发布函数直接创建 valid=True 的顶层消息;它表示此函数正常组包,不是摄像头视角、帧年龄、标定有效性、模型置信度均合格的保证。main() 调用时传入 vipc_client.timestamp_sof,但 get_driverstate_packet() 不使用该参数;消费者只有消息总线自己的 logMonoTime、帧 ID 和模型耗时,不能从这个字段推断原始相机 SOF。策略端的脸姿态转换使用固定 1928×1208 参考尺寸和焦距 598,而相机配置中的 cabin 焦距为 567;自制镜头/warp 不能只替换上游像素流而保留这套转换假设。
验证现状与插件边界
本地 dmonitoring_model.onnx 只有 Git LFS 指针,目录未有运行所需的座舱 tinygrad .pkl/warp 文件,故不能在当前归档执行真实推理或验证数值精度。process_replay 定义座舱模型回放,使用 cabinCameraState/VisionIPC 帧作为输入并忽略运行耗时字段;这仅证明仓库有回放入口,不代表当前快照已通过。环境变量 SEND_RAW_PRED 非空时把原始浮点输出写进 rawPredictions;此数据可能含座舱行为信息,日志/插件应考虑隐私和存储边界。
插件化时,可先把座舱采集和推理作为只读影子插件,契约至少包含像素格式、宽高/stride/缓冲生命周期、内参与 warp 版本、外参来源、模型/输出切片版本、SOF 时间戳、帧年龄、概率及标准差校验、隐私分级。权威 driverStateV2 只能有一个发布者;插件不能把缺帧或低质量预测宣称为「驾驶员注意」,也不能绕开 dmonitoringd 安全策略与独立执行网关。
常见问题
driverStateV2 的 valid=True 能说明什么?
它只表示 get_driverstate_packet() 这个函数正常组包,不是摄像头视角、帧年龄、标定有效性、模型置信度均合格的保证。探针确认合成的九维脸描述在位置切片为空时仍可组出顶层 valid=True 消息。
座舱相机换成别的分辨率还能直接用吗?
不能。warp 目标是固定的 DM_INPUT_SIZE=(1440,960),构建脚本只为源码列出的两组座舱相机尺寸生成 dm_warp_<宽>x<高>_tinygrad.pkl。缺少匹配尺寸的 warp 产物时,模型初始化会在打开文件处失败。
为什么极负的 logit 概率不是 0?
因为 safe_exp() 把指数上界裁到 11,而 sigmoid 借用了这个截顶指数,所以极负 logit 的概率下限约为 1/(1+exp(11)),并非精确零。
帧 ID 能用来还原相机的原始时刻吗?
不能。main() 虽然传入 vipc_client.timestamp_sof,但 get_driverstate_packet() 不使用该参数,发布结构里只有帧 ID、CPU/模型耗时与总线时间戳,不能据此推断原始相机 SOF。
延伸阅读
- 驾驶员监测策略:从 driverStateV2 到分心告警的判定顺序 —— 消息被消费后才形成的最终判定。
- 车载传感器曝光与 ISP:图像链路的输入从哪来 —— 座舱帧上游的成像条件。
- 几何变换与硬件:相机内参、外参怎么落到变换矩阵 —— warp 与标定假设的工程背景。
- 进程回放验证:怎么用录制帧检查一条推理链 —— 座舱模型回放入口的意义与局限。
参考资料
- 项目 02 ——
openpilot-research/DRIVER_MONITORING_MODEL_PIPELINE_DEEP_DIVE.md(座舱图像、模型推理与预测契约、输出解码与几何假设)。 - 项目 02 —— 同目录探针记录:六项初始化产物、八项主循环帧、七项缓冲缓存、八项切片/解析/组包、七项脸姿态几何隔离探针结论。
说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。
更新记录
首次发布 2026-10-11 最近核对:2026-10-11