回放并入主窗口,并修掉开场尖峰 / 录制时长 / 录制帧率 / 回放被摄像头覆盖等 9 项评审问题 - What: 回放不再是独立窗口——删除 PlaybackDialog,拆成 replay.py::ReplayController(读盘、游标、深度重算,只发信号)与 ui/replay_bar.py(录制选择、可拖拽进度条、单位、重算深度、提示行),品牌轨「历史回放」直接换主窗口布局,文件菜单两条入口都切到该视图,曲线改读 RecordingCurveSource(区间按需读盘 + 缓存包络),2D 面板切「原始图像 / 深度图」;传感器与标定合并到 SensorDialog(类型/配置下拉 + 当前生效标定 + 最近导出系数),标定面板加纵向滚动区、九按钮两行、六列表头 ResizeToContents。评审 9 项:1) 开场尖峰两个根因——push() 遇单位变化只记 _unit 而保留旧单位样本(raw 计数被画在牛顿轴上),改为「切换即换单位」:清缓冲按新单位重建、触发切换的那一帧仍刷数值卡;_start_run 先 session_store.reset() 再 set_store(),新会话不再带上次的尾巴(复现脚本 .repro/probe_item1.py:旧 39 样本峰值 9.841 → 新 37 样本峰值 2.390)。2) 箭头页脚改为「箭头按位移放大 ×{factor}」。3) 表头单位芯片由只读 QLabel 改为可点按钮,一次点击同时改曲线、数值卡与设置区下拉。4-6) 全程总览/框选/返回最新 改为 ui/icons.py 按主题令牌运行时绘制的图标,tooltip 与 accessibleName 保留文字,全程总览区域名仍是文字。7) stats() 在录制进行中即返回 _last_t - _t0,记录条开始计时(此前只在 _finalise 写、整场停在 00:00.0)。8) 容器 fps 改用传感器配置的速率(packet.fps 是"每秒完成多少帧"的计数器,突发/文件源会读到 48),视频按 1/fps 节流并把超前的帧计入 resampled_video(frames.csv/forces.csv 一行不少,报告写明原因),session.json 同时记 fps 与 measured_fps。9) _replay_owns_image() 让回放视图独占 2D 面板,实时帧不再覆盖;push() 在录制源挂载时连单位都不切,曲线/数值卡/单位一并归录制。附带:数值卡改读游标处样本(_readout_at_cursor)、回放按录制实际有的单位打开(_replay_unit_for + ReplayController.set_unit,避免 raw-only 录制在 newton 偏好下画三张空图)、视频速率下限。 - Why: 用户评审 9 点,其中 1/7/8/9 是代码缺陷(开场尖峰、录制时长不更新、录制 48fps 与实际 30fps 不符、回放时 2D 面板仍被摄像头刷新),2-6 是可读性问题(×2 含义不明、单位与视图控制应可点/应符号化)。 - Verification: ui_check.py 524 项 0 失败(新增 chart header and unit chip / acquisition correctness / replay owns the 2D pane 三段)、test_ui_smoke.py 69 项 0 失败(新增 7 个回归用例:单位切换不混单位、单位芯片、图标语义、录制中时长、传感器帧率+节流、回放独占面板、回放游标读数与单位回退)、drive_shared.py 146 项 0 失败、locale_studio.py(268 键齐全、zh==en、prefs 对齐)、reproduce.py、ui_snapshot.py 四张复核图(深色实时/回放、浅色 1280x720 实时与标定)。 - Not in this change: 录制文件格式(forces.csv 列序、frames.csv、session.json 路径与分段规则)不变,节流只影响"哪些帧进视频",并显式计数上报;三维面板仍是占位符。
This commit is contained in:
@@ -157,6 +157,26 @@ outputs/recordings/<UTC 时间戳>_session<NNNN>/
|
||||
- `raw_frame` 在入队时**必须拷贝**:packet 里的帧可能复用 SDK 的采集缓冲,直接持有引用
|
||||
会让录制内容随后续帧改变。
|
||||
|
||||
### 6.1 录制速率与时长(视频 30 fps、时长实时递增)
|
||||
|
||||
`session.json` 的 `video.fps` 是**容器速率**,必须等于传感器的采集速率,取自传感器配置
|
||||
(`config/sensors/<type>/sensor.json` 的 `fps`,box 为 30),**不是** packet 里那个
|
||||
`fps` 字段 —— 后者是"管线每秒完成多少帧"的计数器,开流瞬间的缓冲突发或视频文件源会让
|
||||
它读到 48,用它写 30 fps 的容器就等于把回放播成了快进。这是"传感器 30 fps、录制结果
|
||||
48 fps"的直接原因。
|
||||
|
||||
- `StudioMainWindow._video_fps()`:实时相机 → 传感器配置的 `fps`;视频文件源 → 实测值;
|
||||
实时相机的实测值另存 `video.measured_fps`,两者都进 `session.json`,对不上时看得见。
|
||||
- **视频按速率节流,CSV 一行不少**(`ExperimentRecorder._video_frame_due`):比
|
||||
`1/fps` 提前超过 `VIDEO_PACING_TOLERANCE`(0.5 个周期)到达的帧**只进
|
||||
`frames.csv` / `forces.csv`,不进视频**,并计入 `stats.resampled_video`;报告里会写成
|
||||
"N frame(s) were delivered faster than the 30 fps recording rate, so they are in
|
||||
frames.csv but not in the video"。这不是丢数据,是显式记账。
|
||||
- 节流表的调度基准取"上一帧排定时刻 + 周期"与"当前时间戳"的**较晚者**,所以卡顿之后不会
|
||||
用一串补帧追进度。
|
||||
- `stats()` 的 `duration_s` 在录制**进行中**就返回 `_last_t - _t0`(此前只有 `_finalise`
|
||||
才写,界面上的录制时长因此整场停在 00:00.0);`forces.csv` 的行数与时间轴不受影响。
|
||||
|
||||
### 已知环境限制
|
||||
|
||||
本机未安装 pytest,且沙箱拒绝写入工作区之外的路径,`conftest.py` 的 `tmp_path` 因此
|
||||
@@ -274,11 +294,21 @@ outputs/recordings/<UTC 时间戳>_session<NNNN>/
|
||||
|
||||
### 回放界面
|
||||
|
||||
`ui/playback_dialog.py`,入口在「文件 → 打开录制回放…/回放最近一次录制」。
|
||||
回放**不再是一个独立窗口**:`ui/playback_dialog.py` 已删除,拆成
|
||||
`replay.py::ReplayController`(读盘 + 游标 + 深度重算)与 `ui/replay_bar.py::ReplayBar`
|
||||
(录制选择 + 进度条 + 单位 + 提示),入口在「文件 → 打开录制目录…/回放最近一次录制」
|
||||
与品牌轨的「历史回放」。布局与关闭流程见 `docs/shell-lifecycle.md` §2。
|
||||
|
||||
- **一个游标驱动三处**:移动位置同时更新视频帧、深度面板与三张曲线的游标线;
|
||||
并且通过 `cursor_moved` 信号同步到主界面的曲线面板。
|
||||
- 单位可切换(raw/N),数据直接来自录制目录的 `forces.csv`。
|
||||
- **回放按录制实际有的单位打开**:录制里 `FN_N` 等列全空(没有标定)时退回 raw,
|
||||
否则选 N 会画出三张空图;`raw` 一定存在(那是设备测到的值)。
|
||||
单位由 `ReplayController.set_unit` 一处决定,回放条、曲线与设置区下拉同时改。
|
||||
- **数值卡读的是游标处的那一帧**(`ForcePlotsPanel._readout_at_cursor`):浏览历史或回放
|
||||
时,三个大数字是播放头所指的样本,而不是实时采集的最后一个样本 —— 否则一张 7.5e5
|
||||
原始计数的曲线旁边会写着实时的 `0.0`,看起来就像"回放根本没打开"。
|
||||
实时视图仍是"最新样本就是游标",所以跟随状态下不额外读盘。
|
||||
- 帧未被写入视频时(记录队列曾溢出)明确提示,而不是显示上一帧冒充当前帧。
|
||||
- **深度重算在守护线程上执行**,UI 线程立即返回。实测 `_on_recompute_depth` 返回耗时
|
||||
0.001 s,而 SDK 调用仍在后台跑。
|
||||
|
||||
Reference in New Issue
Block a user