结论:相机链路里同时存在三个不同的编号——request_id(req_mgr 队列请求号)、内核 IFE frame_id(每次 SOF 递增的内核计数)与归一化后的published frame_id。只有第三个才是跨相机配对可用的键;直接拿原始 IFE 计数当配对键,在座舱与路面这类错相路之间会整体错位。三路 SOF 的预期关系是:非错相路之间相差 0,座舱与路面路之间相差 25 ms,误差阈值 0.2 ms。此外 timestamp_eof 是「SOF 加读出时间」推算的值,不是硬件 EOF 事件,processing_time 也不能当作曝光时长。以下均为固定快照的静态结构分析,未运行相机、模型或实板测试。
三个编号:request_id、IFE 帧号与发布帧号
handle_camera_event()从 req_mgr 的 SOF 事件里一次读出三样东西:request_id、内核 IFE frame_id 和内核 IRQ 时间戳。request_id 是队列请求号,IFE frame_id 是每次 SOF 递增的内核计数,两者都不是最终发布给模型的帧号。validateEvent()在 skip_expected 为假时分别检查两种序号是否各自连续;request_id == 0 会被跳过,连续无效超过环深加二就触发重排。
真正决定跨相机对齐的是 syncFirstFrame():它为每一路记录首次 SOF 时间,并把 ife_frame_id + 1 存为该路的帧号偏移;等所有已启用相机都到齐且时间关系满足后,才设置共享的同步完成标志。processFrame()此后才计算 published frame_id = ife_frame_id - frame_id_offset。换句话说,进入同步状态的那一次调用仍返回 false,下一帧才可能成为首个发布帧。
| 编号 | 来源 | 是否可作跨相机配对键 |
|---|---|---|
request_id |
req_mgr SOF 事件读出的队列请求号 | 否;request_id == 0 会被跳过,仅供本路连续性检查。 |
IFE frame_id |
每次 SOF 递增的内核计数 | 否;三路 IFE 计数可以不同,不能直接当配对键。 |
published frame_id |
ife_frame_id - frame_id_offset |
是;偏移在首帧对齐时按路记录。 |
还有一条恢复边界:若某路的 IFE 帧号已超过 40 且仍未对齐,代码会记错误并把共享同步标志置为已同步,但没有在该分支证明各路满足了 0.2 ms 关系。此时若某已启用路尚无首帧记录,它后续首次进入已同步分支时用的偏移状态需要另行动态验证。
时间域:SOF、推算 EOF 与处理时间
发布出去的几个时间字段语义差别很大。timestamp_sof 来自内核 SOF IRQ,是 modeld 配对窄路与广路图像的依据;timestamp_eof 则是 processFrame() 用 SOF 加 readout_time_ns 推算出来的,读出的只是估计值而非硬件 EOF 事件。
| 字段 | 来源与含义 | 下游影响 |
|---|---|---|
timestamp_sof |
handle_camera_event()读取的 SOF IRQ 时间 |
modeld 按它配对窄/广路图像。 |
timestamp_eof |
processFrame() 用 SOF 加 readout_time_ns 推算 |
cameraOdometry 携带它,locationd 再减模型姿态延迟并做时间校验。 |
processing_time |
等待 fence 后,以当前单调时间减估计 EOF | 写入相机状态;不能当曝光时长或端到端控制延迟。 |
VisionIpcBufExtra |
sendFrameToVipc() 附带归一化帧号、SOF、EOF |
encoderd 核对缓冲帧号与通知帧号,失配时跳帧。 |
读出时间本身是传感器相关常量:OS04C10 与 OX03C10 各有自己的取值。开发版的 webcamerad._send_yuv() 把 frame_id * 0.05 s 同时当作 SOF 和 EOF,状态消息只带帧号和单位变换——它能替代输入用于开发,却不能验证硬件时钟同源、真实读出时间或三路同步。
同步建立:25 ms 错相、0.2 ms 阈值与 40 帧兜底
同步阈值集中在一处配置里,含义需要分清「预期差值」与「允许误差」。非错相路之间预期相差 0;座舱路与路面路之间预期相差 25 ms;可接受的误差是 0.2 ms。这些是当前实现与测试里的常量,不是任意硬件的通用标准。
| 量 | 取值 | 说明 |
|---|---|---|
| 非错相路预期差 | 0 | 同相两路应同时曝光。 |
| 座舱与路面预期差 | 25 ms | 错相路的标称错位。 |
| 同步误差阈值 | 0.2 ms | 判断某路是否满足时间关系。 |
| 未对齐放弃门 | 40 帧 | 超过后置同步标志,但不证明各路满足 0.2 ms。 |
重排会记录 last_requeue_ts,并允许预期中的序号空洞出现。收到过旧 SOF、故障注入跳过、序号不连续,或 waitForFrameReady() 等待 IFE/BPS fence 失败时,当前帧都不会发布。这些行为的共同点是:链路并不保证「图像流始终连续」。
消费者各用各的同步策略
同一个相机流,三个消费方用的对齐策略并不统一。modeld 先取得比上一广角 SOF 至少晚 25 ms 的主帧,再读取广角帧;两路 SOF 相差超过 10 ms 时记录错误日志,但该分支仍会进入后续推理,没有直接丢弃这对图像。模型 frameId 来自 VisionIPC 主帧,frameIdExtra 来自另一路,而 frameAge 是拿异步收到的 narrowRoadCameraState.frameId 与主帧比较,不能误读成同一缓冲的自身年龄。
encoderd.sync_encoders() 在启动时选跨路共同起始帧,并在 encoder_thread() 里按帧号决定切段,它不按 SOF 重新校正物理曝光时刻。因此相机帧号重置、断流重连或缺一路时,编码器启动门与模型配对门是否仍符合预期,需要单独验证。相机状态消息则先发布 VisionIPC、再填充发送状态消息,两条传输路径不应仅凭到达顺序关联,而应以帧号和时间戳核对。
硬件插件接口与验收
建议相机插件输出同一采集 epoch 下的 stream_id、request_id、原始硬件帧号、归一化帧号、单调时钟域 SOF、EOF 来源(实测或估计)、读出时间、缓冲有效性和同步状态,并把 sync_lost、重排代数与丢帧原因作为可观测事件。平台适配器负责时钟换算、帧号归一化和缓冲所有权;模型与编码插件只消费明确标注时间质量的帧,不可把 webcam 合成时间或日志发布时间暗中转成硬件 SOF。
现有 test_camerad.py 是硬件门控测试,检查帧号连续、窄/广路 SOF 差小于 1.1 ms、座舱错相 20–30 ms、EOF 晚于 SOF,并有故障注入下的序号跳变检查;这些测试本轮未运行。新硬件还应在台架与实车分别测试启动缺一路、40 帧超时、掉帧与重排、时钟漂移、读出时间误差、IPC 复用以及编码与模型重连。
常见问题
IFE 帧号能直接当两路相机的配对键吗?
不能。IFE frame_id 是三路各自递增的内核计数,彼此可以不同;跨相机配对要用减去首帧偏移后的 published frame_id,而偏移由 syncFirstFrame() 在首帧对齐时逐路记录。
timestamp_eof 是硬件 EOF 事件吗?
不是。它是 processFrame() 用 SOF 加 readout_time_ns 推算出来的估计值,读出时间随传感器不同(OS04C10、OX03C10 各有取值);processing_time 也不是曝光时长。
座舱与路面路的错相预期是多少?
非错相路之间预期相差 0,座舱路与路面路之间预期相差 25 ms,误差阈值 0.2 ms。这是当前实现与测试的常量,不是任意硬件的通用标准。
两路 SOF 相差超过 10 ms,模型会丢帧吗?
源码在该分支记录错误日志,但仍进入后续推理,并没有直接丢弃这对图像。实际的丢帧根因需要区分采集、IPC 与模型消费落后三种情况。
延伸阅读
- VisionIPC 缓冲契约 —— 承接
VisionIpcBufExtra的帧号、SOF、EOF 与缓冲所有权。 - 相机请求缓冲的生命周期 —— 对照
request_id与请求队列的重排语义。 - 车载信号为什么会说谎:TTL、源时间与 500 ms 新鲜度阈值 —— 同一类「源时间与发布时间不是一回事」的问题。
- openpilot 的 100 Hz 控制回路 —— 承接下游消费者对时间戳质量的依赖。
- 相机与 IMU 的时间关系 —— 另一条对时间戳同源与顺序敏感的链路。
参考资料
- 项目 02 ——
openpilot-research/CAMERA_FRAME_TIME_SYNC_CONTRACT_DEEP_DIVE.md(取用了三个编号的定义、首帧对齐偏移、25 ms/0.2 ms/40 帧阈值、SOF 与推算 EOF 字段表、消费者同步策略差异与硬件测试项)。
说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。
更新记录
首次发布 2026-10-11 最近核对:2026-10-11
发表回复