onroad 验收测试:25 秒日志、相机 SOF/EOF 与模型耗时各断言了什么

作者:

在

结论:test_onroad.py 是需要 comma 硬件的设备测试,不是实车驾驶测试:它启动 manager、跑 25 秒、读首段 rlog.zst,再对服务频率、日志大小、相机时序、模型耗时和资源占用做断言。它的边界很明确——只分析短时日志、不测驾驶动态与安全限幅,且部分断言因算式问题无法触发、部分后备分支不可达。本文基于固定源码快照的静态分析,没有运行 manager、相机、panda、模型或车辆 I/O。

启动链与副作用

TestOnroad 设置 COMMA_HARDWARE_TEST=True;继承的 OpenpilotTestCase.setUpClass() 在非 comma 硬件跳过,然后调用小写的 setup_class()。普通路径先删 CurrentRoute、开启 RecordFront、写启用/条款/标定参数并设置 REPLAY、MSGQ_PREALLOC、TESTING_CLOSET,随后 Paths.log_root() 指向的目录若存在就被递归删除。在 AGNOS 设备上该路径位于设备本地介质目录,不随 per-test OPENPILOT_PREFIX 隔离。

类级准备通过 subprocess.Popen() 启动 manager,最多等 30 秒收到 carState,要求 CurrentRoute 存在且日志目录中恰有一个匹配路段,然后睡眠 25 秒;终止 manager 后读取首段 rlog.zst。TestOnroad.setUp() 直接调用 unittest.TestCase.setUp(),没有调用每测试硬件初始化的那层,但继承的 run() 仍对各测试包裹环境快照、Prefix 和 manager 清理——类级准备发生在 per-test Prefix 之前,不能把它的 Params 和日志删除视为测试命名空间内的动作。

并行运行时有隐患:通用 test_runner.make_batches() 只按类自身的大写 fixture 合批,而该类只定义小写 setup_class。若用多 worker 运行该文件,类级 manager 启动与日志目录删除可能在多个批次重复甚至并发;发布脚本和 Jenkins 直接调用本文件的 unittest.main(),不走这条并行分组路径。另外 finally 中判断 proc.wait(60) is None,而 Popen.wait() 正常返回退出码、超时抛 TimeoutExpired、不会返回 None,故这条 proc.kill() 后备分支不可达。

主要验收断言与实际覆盖

测试函数 有效检查 覆盖边界
test_service_frequencies() 对已在日志中出现的非 GPS/init/sentinel 主题要求至少约 frequency * 20 * 0.8 条 未出现的主题不进循环;不是全服务存在性证明
test_manager_starting_time() manager 启动到首条 managerState 小于 15 秒 只约束首消息,不证明所有进程就绪
test_cloudlog_size() logMessage 总字节数小于 350 kB spam 判据 n / sum > 30 左侧至多 1,额外断言无法触发
test_log_sizes() 文件落在 60 秒量按 25 秒缩放后的 0.5~1.5 倍 未知文件名访问会报错;不验证内容可解码
test_ui_timings() 跳过约前 8 秒;最大绘制 CPU <250 ms、均值 <20 ms、>40 ms 帧少于 5 用 uiDebug.cpuTimeMillis,不是屏幕端到端延迟
test_cpu_usage() 每进程上限 max(expected*1.8, expected+5) 总预算只求静态表之和;缺样本时上限可能未赋值
test_memory_usage() 跳过前 8 秒,检查 deviceState 内存均值与增量 25 秒窗口不是长期泄漏证明

相机与模型相关断言如下,它们共同的特点是只检验录入日志的元数据,不解码视频像素、不判断预测准确率:

测试函数 有效检查 覆盖边界
test_camera_frame_timings() 三路相机相邻 SOF 与 50 ms 的最大偏差 <5 ms 只检验日志帧时间戳
test_camera_sync() 帧号连续、EOF 在 SOF 后 50 ms 内;道路/宽角同帧差 <2 ms、座舱错开 20~30 ms、编码器起始帧一致 相机状态只要求最早帧号 <100;仅对三路共同帧号比较
test_camera_encoder_matches() 编码索引帧号对应相机状态的 SOF/EOF 完全相等 只核对元数据,不解码视频像素
test_model_execution_timings() 8 秒后道路模型最大/均值 <60/40 ms,驾驶员模型 <300/50 ms 比较执行时间,非模型输出数值或最坏闭环时延
test_timings() 预设服务消息间隔均值在目标频率 3% 内 独立于实际执行器安全约束
test_startup()/test_engagable() RELEASE 存在时比较启动告警;8 秒后 engageable 全为真 release_only 只检查变量存在;可接管不等于真正 engage

DEBUG 分支仅初始化 lr/ts,未设置 manager_st、msgs、log_sizes,只能支持使用到这些字段的定向用例,不能当作完整 suite 的等价运行模式。

资源类断言也各有算式边界。test_cpu_usage() 用 procLog 首末 CPU 时间差与日志时长计算各进程使用率,每进程上限为 max(expected*1.8, expected+5),而总预算断言只求静态 PROCS 表的和,不约束实测使用率总和;缺样本时 max_allowed 可能未赋值或沿用上一进程值。test_memory_usage() 跳过前 8 秒,检查 deviceState 内存占用均值与相邻增量并打印 procLog 报告,但 25 秒窗口与百分比变化不是长期泄漏证明,共享内存区用量也只打印。test_log_sizes() 要求文件落在预设 60 秒量按 25 秒缩放后的 0.5~1.5 倍,未知文件名访问 LOGS_SIZE[f.name] 会报错,且它不验证文件内容可解码或跨段完整性。

Chestnut 独立测试

TestChestnutOnroad 还要求设备类型为 mici,并检查 Chestnut 硬件/编译产物。它写入演示 CarParams,用 mock deviceMotion 和合成 deviceState 驱动 camerad、calibrationd、modeld、dmonitoringmodeld,等到模型有效再收集 25 秒消息。断言包括:五种服务数量在目标频率约 5% 内、Event valid、帧号单调上升、至少 90% 道路模型帧与窄路相机交集、全部 modelV2.big 为真、以及 position.x 有限。

这能证明短时大模型路径没有回落到小模型的可见标志,但不证明预测准确率、整帧像素对齐、车辆控制或长期热稳定性。发布脚本在强推前直接运行此文件的指定 unittest 入口,Jenkins 另把 Chestnut 测试与模型回放放在设备阶段;两者属于不同调用场景,且有分支/环境/硬件门,不能用任意一次绿色结果宣称全部平台通过。

验证范围与插件化含义

已静态核对完整测试文件、相邻 OpenpilotTestCase/Paths/helper 和 CI 入口,但未执行任何测试,未验证真实日志格式、采样分布、模型权重或目标设备。文中不可达/无效断言是直接源码控制流与算式结论,非已在设备上复现的故障。硬件插件验收应补固定日志的数值基准、CAN safety 测试、故障注入与独立台架时序,再进入实车驾驶员监督验证。

常见问题

test_onroad.py 是用来验证实车驾驶表现的吗?

不是。它是需要 comma 硬件的设备测试,只启动 manager、跑 25 秒、读首段 rlog.zst,对服务频率、日志大小、相机时序、模型耗时和资源占用做断言。源文档明确它既不测驾驶动态与安全限幅,也不验证真实驾驶表现;本文也未运行 manager、相机、panda、模型或车辆 I/O。

为什么说 proc.kill() 后备分支不可达?

因为源码判断的是 proc.wait(60) is None:Popen.wait() 正常返回退出码,超时抛 TimeoutExpired,不会返回 None,所以基于该条件的后备分支逻辑上不可达。这是直接源码控制流结论,不是设备上复现的故障。

相机同步测试通过,是否说明视频像素也对齐?

不代表。test_camera_sync() 只比较录入日志的帧号与 SOF/EOF 时间戳,test_camera_encoder_matches() 只核对编码索引帧号与相机状态元数据,都不解码视频像素;且仅对三路共同帧号比较,不证明未记录帧的同步。

Chestnut 测试通过能说明什么?

它能证明短时大模型路径没有回落到小模型的可见标志(如 modelV2.big 全为真、帧号单调上升、服务数量符合目标频率)。但它不证明预测准确率、整帧像素对齐、车辆控制或长期热稳定性,也不能用绿测结果宣称全部平台通过。

延伸阅读

参考资料

  • 项目 02 —— openpilot-research/ONROAD_TEST_ACCEPTANCE_LOG_TIMING_CAMERA_MODEL_CONTRACT_DEEP_DIVE.md(取用了启动链与副作用、验收断言覆盖边界、Chestnut 专项与验证范围)。
  • 项目 02 —— openpilot-research/TEST_RUNNER_PARALLEL_FIXTURE_CONTRACT_DEEP_DIVE.md(仅用于确认测试合批与 fixture 命名的边界)。

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

更新记录

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

评论

发表回复

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