新增 Autocal 标定采集页重构计划与代理分工
整理采集页流程、录像选项和汇总入口的分阶段方案,供 DeepSeek 执行;文档门禁通过。
This commit is contained in:
@@ -0,0 +1,118 @@
|
|||||||
|
# Autocal 标定采集页重构实施计划
|
||||||
|
|
||||||
|
状态:2026-10-18 计划,未实施。目标是把“选点 → 对准 → 逐档加载 → 记录”收成一条流程:一个测点队列、一个不依赖 Qt 的状态控制器、一个随步骤变化的主按钮;同时加入录像选项、打开文件夹和平铺汇总。执行分工见[任务分工](capture-workflow-tasks.zh.md)。本计划不改变运动安全规则、不自动加载、不写回 SDK 系数。
|
||||||
|
|
||||||
|
## 基线与问题
|
||||||
|
|
||||||
|
调查基线:app `main`、HEAD `7607653`;工作树已有 `motion/service.py`、`record_diagnostics.py` 改动,实施时不得覆盖。结论来自源码、界面截图和 `D:/orisys_ws/data/dd02-gl`,未运行程序或硬件。
|
||||||
|
|
||||||
|
| 位置(相对 `apps/autocal/src/orisys_autocal/`) | 问题 |
|
||||||
|
|---|---|
|
||||||
|
| `ui/calibration_panel.py: _confirm/_sync` | “到达目标”按钮与参考力输入框按隐藏的 `campaign.phase` 在单点与多点之间切换 |
|
||||||
|
| `ui/multipoint_panel.py: _levels/_hold` | 多点读取右栏载荷档位,又自带 Min/Max force,存在两套载荷设置 |
|
||||||
|
| `ui/calibration_panel.py` 子页 | UV 图与实时图互斥;输入源配置藏在实时图子页;开始试验会自动切页 |
|
||||||
|
| `ui/multipoint_panel.py: bind_finger` | 求解器借用 Finger debug 的 `stack`;该页另有测点表、导出和执行,测点有两份 |
|
||||||
|
| 两个面板共 10 条状态文字 | 报错落点取决于代码路径,禁用按钮没有原因 |
|
||||||
|
| `trial.py:157`、`multipoint.py:1476` | `RecordConfig` 默认 `mp4v`,实测约 27 Mbit/s;同画面 H.264 样例约 5 Mbit/s |
|
||||||
|
| `capture_guard.capture_verdict`、`summary.py:264` | 无视频必判 `video_missing`,多点汇总还要求帧在视频内,因此无法安全提供“不录视频” |
|
||||||
|
| `summary_export.publish_summary` | 汇总藏在 `derived/summary_<UTC>_<id>/`;用户手工拼出 dd02-gl,已出现 site_id 重名 |
|
||||||
|
|
||||||
|
## 需先确认的决定
|
||||||
|
|
||||||
|
| 编号 | 决定 | 建议默认 | 阻塞阶段 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| D1 | 新采集的单点是否改为“一个点的多点会话”(`sites/` 格式) | 是;旧 `trials/` 会话继续可读,`ManualTrial` 暂留不删 | P3 |
|
||||||
|
| D2 | 默认视频编码及等效门槛 | 保持 `mp4v` 直到 P2b 证明 H.264 重放差异可接受;门槛由用户给出 | P2 默认值 |
|
||||||
|
| D3 | Test sequence 页与测点队列的关系 | 本计划不改该页 | 无 |
|
||||||
|
| D4 | 只录保持窗口前后 | 不做:违背“每 trial 连续录像”契约 | 无 |
|
||||||
|
|
||||||
|
未确认的决定由主代理暂停相应阶段,不得自行选择。
|
||||||
|
|
||||||
|
## 阶段
|
||||||
|
|
||||||
|
每阶段的入口条件不满足就不开始;出口条件全部有证据才算完成。
|
||||||
|
|
||||||
|
### P0 基线(主代理)
|
||||||
|
|
||||||
|
- 入口:本计划及 D1、D2 已确认。
|
||||||
|
- 内容:记录 app 与工作区根的分支、HEAD、index、工作树;建立 `.scratch/autocal-capture-workflow/` 和 `.active`;跑基线全量测试与 `panel_check.py`,记录已知失败(finger 页 `QDoubleSpinBox` 高度 2 项)。
|
||||||
|
- 出口:基线命令与结果写入 scratch;之后任何失败须与基线对比后才能归因。
|
||||||
|
|
||||||
|
### P1 打开文件夹与平铺汇总
|
||||||
|
|
||||||
|
- 入口:P0。
|
||||||
|
- 内容:
|
||||||
|
1. 将 `ui/window.py: _reveal` 提取为 `ui/reveal.py: reveal(path, select=None)`,Windows 用 `explorer /select,<文件>`;菜单与采集页共用。
|
||||||
|
2. 采集页会话行加“打开会话文件夹”“打开汇总”“复制路径”;无目录时禁用并写明原因。
|
||||||
|
3. `publish_summary` 在原子替换 `summary-latest.json` 之后,把同一份四件文件写到会话根 `summary/`:先写临时目录再替换。副本失败只报告,不回滚指针、不改采集结果。
|
||||||
|
- 出口:`summary/` 文件哈希与指针所指版本一致;副本失败时旧 `summary/` 和指针保持不变;`reveal` 参数由测试模拟 `subprocess` 断言;两份格式文档更新目录说明。
|
||||||
|
|
||||||
|
### P2 录像选项
|
||||||
|
|
||||||
|
- 入口:P0;D2 已确认。
|
||||||
|
- 内容:
|
||||||
|
1. 新增 `recording_options.py`:`video: bool`、`codec`、`lossless_frames: bool`;默认值进 `preferences.py` 和 `config/preferences.default.json`。
|
||||||
|
2. 用一个工厂 `make_record_config(options, fps)` 替换 `trial.py` 与 `multipoint.py` 两处 `RecordConfig(...)`;不改 shared 默认值(Studio 也在用)。
|
||||||
|
3. 选项写入根 `session.json` 的 `recording` 块,会话建立后锁定。
|
||||||
|
4. `capture_verdict` 增加 `video_expected`;为 False 时跳过视频相关判定。`summary.py` 和 `session_review.py` 从 `recording` 块读取;缺该块的旧会话按 `video_expected=True` 处理。
|
||||||
|
5. 启动时用 cv2 向 scratch 写 3 帧探测编码器;不可用的编码在界面上禁用并说明,绝不静默回退。
|
||||||
|
6. 界面显示按码率与计划时长估算的体积和磁盘剩余空间(`shutil.disk_usage`),不足两倍估算时警告。
|
||||||
|
- 出口:关视频时 trial 为 complete、汇总行 eligible、复核显示“按设置未录视频”;旧会话结果不变;编码不可用在开始前拒绝。
|
||||||
|
|
||||||
|
### P2b 编码等效验证(只出报告,不改代码)
|
||||||
|
|
||||||
|
- 入口:P0。
|
||||||
|
- 内容:同一视频文件作为输入,分别用 `mp4v` 与 H.264 录制,各自经 SDK 重放,按 `frame_id` 比较 `FN_raw`/`FX_raw`/`FY_raw` 的逐帧差和各保持窗口均值差。脚本与结果只放 scratch。
|
||||||
|
- 出口:报告给出差值相对 1 N 档阶跃响应的比例,交用户按 D2 决定是否切换默认编码。
|
||||||
|
|
||||||
|
### P3 采集状态控制器
|
||||||
|
|
||||||
|
- 入口:P0;D1 已确认。
|
||||||
|
- 内容:新增 `capture_controller.py`,不导入 Qt 或运动服务,内部包一个 `Campaign`。
|
||||||
|
1. 队列即 `campaign.sites`;单点就是只有一行的队列。
|
||||||
|
2. `readiness()` 返回检查项:标定包、输入出帧、总线已初始化且轴映射无问题、输出目录可写、SN、最大力。
|
||||||
|
3. `primary_action()` 返回 `(key, label_key, enabled, blocked_reason)`;`perform(key, **inputs)` 执行;`secondary_actions()` 返回重测、跳过、停止;`poll()` 推进保持与收尾。
|
||||||
|
4. 对准只发出请求,仍走 `window._on_align_multipoint → plan_pose_move`。
|
||||||
|
5. 求解器由构造参数注入 `PlatformStack`,不再取 Finger 面板。
|
||||||
|
- 出口:表驱动测试覆盖完整加载阶梯、确认离开、换点、重测、复采、任意状态停止;每个禁用的主动作都有非空原因;录制中拒绝对准;直接驱动 `Campaign` 与经由控制器写出的 `session.json`、`reference.csv` 结构一致;`test_binding_purity.py` 通过。
|
||||||
|
|
||||||
|
### P4 新采集页界面
|
||||||
|
|
||||||
|
- 入口:P1、P3 完成(P2 可并行合入)。
|
||||||
|
- 内容:按设计稿重排 `CalibrationPanel`:
|
||||||
|
1. 会话行和 Ready 标签行;输入源与标定包放入“更改输入/标定包…”对话框。
|
||||||
|
2. 左侧 UV 图与实时图并排,下方是基于控制器模型的队列表。
|
||||||
|
3. 右侧当前点卡片(步骤标签、提示、参考力或六维力输入、主按钮、次要按钮)和力曲线;底部一行消息。
|
||||||
|
4. 控件只渲染控制器给出的内容,不读 `campaign` 内部字段;中英文 locale 同步。
|
||||||
|
- 出口:`panel_check.py` 在 1440×900、1920×1080 下无新增失败;在模拟模式下用界面测试走完两个点;用 grep 证明 `ui/` 中没有 `campaign.phase` 判断;离屏截图存 scratch 供人工查看。
|
||||||
|
|
||||||
|
### P5 合并 Finger debug
|
||||||
|
|
||||||
|
- 入口:P4。
|
||||||
|
- 内容:Finger debug 改名为“几何与安装”,保留安装偏置、工具 XY、行程限制、3D 预览和单点试选;删除其测点表,“导出测点操作表”迁到队列的导入/导出;`stackChanged` 触发控制器重新求解,不可达行标出;删除未使用的 `multipoint.import_points` 文案或实现它。
|
||||||
|
- 出口:修改安装偏置后队列位姿更新、不可达行禁止对准;导出的操作表字段与[数据格式](calibration-data-format.zh.md)一致;`test_finger_panel.py` 更新后通过。
|
||||||
|
|
||||||
|
### P6 收尾与可选的跨会话导出
|
||||||
|
|
||||||
|
- 入口:P5。
|
||||||
|
- 内容:更新[数据格式](calibration-data-format.zh.md)、[多点格式](multipoint-data-format.zh.md)、[汇总契约](recording-summary-contract.zh.md)和 README 的操作流程。可选:Records 页“导出批次…”,把多个会话合并成一个 dd02-gl 式文件夹,每行带 `session_id`、`trial_id`,不按 site_id 合并。
|
||||||
|
- 出口:文档门禁通过;如做批次导出,用两会话同名 site_id 夹具证明不混行。
|
||||||
|
|
||||||
|
## 统一验证
|
||||||
|
|
||||||
|
所有命令在 `D:\orisys_ws\orisys-app` 下执行,`$pythonExe` 指 `.venv-build\Scripts\python.exe`,basetemp 每次新建。
|
||||||
|
|
||||||
|
| 编号 | 检查 | 何时 | 通过条件 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| V1 | 各阶段新增测试 | 每个任务交付 | 先在旧行为上失败、修复后通过(可行时) |
|
||||||
|
| V2 | `pytest apps/autocal/tests` | 每阶段出口 | 0 失败;跳过项须解释 |
|
||||||
|
| V3 | `tools/lint_gate.py` | 每阶段出口 | `status: clean` 或仅既有抑制 |
|
||||||
|
| V4 | `apps/autocal/tools/panel_check.py` | P1、P4、P5 | 与 P0 基线相比无新增失败 |
|
||||||
|
| V5 | `test_binding_purity.py`、`test_locales_autocal.py` | P3、P4 | 通过 |
|
||||||
|
| V6 | shared 测试 | 仅当改到 `shared/` | 记录器、生命周期、回放测试通过 |
|
||||||
|
| V7 | `D:\orisys_ws\scripts\doc_lint.py` | 改文档时 | 无新错误 |
|
||||||
|
| V8 | 离屏截图人工检查 | P4、P5 | 用户或验收代理确认 |
|
||||||
|
| V9 | P2b 编码报告 | 切换默认编码前 | 用户按 D2 接受 |
|
||||||
|
| V10 | 实机验收 | 全部完成后 | 需指定设备、运动与载荷范围、停机条件;代理不执行 |
|
||||||
|
|
||||||
|
V1–V9 是软件证据,不代表实机可用;V10 未执行前状态只能写“仅软件验证”。
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
# 标定采集页重构:DeepSeek 代理执行清单
|
||||||
|
|
||||||
|
状态:2026-10-18 计划,未实施。阶段定义、入口与出口条件、统一验证见[主计划](capture-workflow-plan.zh.md);本页只规定由谁执行、按什么顺序执行、交付什么。复选框记录实际完成情况。
|
||||||
|
|
||||||
|
## 主代理指令
|
||||||
|
|
||||||
|
开始前先读工作区 `AGENTS.md`、`docs/AUTHORING.md`、`docs/platform/engineering-workflow.md` 和主计划,再重新检查 app 与工作区根的分支、HEAD、index 和工作树。已有的 `motion/service.py`、`record_diagnostics.py` 改动以及根仓库 `scripts/finger_multical/` 的改动都不属于本任务,不得覆盖。
|
||||||
|
|
||||||
|
不得连接真实控制器、移动平台或加载;不得提交、推送、暂存或改写历史。D1、D2 未经用户确认时,停在相应阶段并报告。
|
||||||
|
|
||||||
|
scratch 统一放在 `.scratch/autocal-capture-workflow/`;运行期间保留 `.active` 标记,每次 pytest 用新的 `--basetemp` 并加 `-p no:cacheprovider`。
|
||||||
|
|
||||||
|
主代理负责以下文件的最终合并:
|
||||||
|
- 接口:`capture_controller.py` 的公共 API、`recording_options.py` 的结构;
|
||||||
|
- 共享文件:`ui/window.py`、`preferences.py`、`config/preferences.default.json`、两份 locale 文件、`docs/`。
|
||||||
|
|
||||||
|
子代理需要改这些文件时,先把改动交给主代理,由主代理串行合入。
|
||||||
|
|
||||||
|
## 角色
|
||||||
|
|
||||||
|
| 角色 | 负责阶段 | 可改文件 | 不可改 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 主代理 | P0、接口冻结、合并、P6 文档、交接 | 上面列出的共享文件 | — |
|
||||||
|
| A 数据与文件 | P1、P2 | `ui/reveal.py`、`summary_export.py`、`recording_options.py`、`capture_guard.py`、`summary.py`、`session_review.py`,`trial.py` 与 `multipoint.py` 中构造 `RecordConfig` 的两行,以及相应测试 | 状态机、界面布局、`shared/` |
|
||||||
|
| B 控制器 | P3 | `capture_controller.py`、`tests/test_capture_controller.py`;`multipoint.py` 只允许为控制器暴露只读属性 | 任何 `ui/` 文件 |
|
||||||
|
| C 界面 | P4,之后 P5 | `ui/calibration_panel.py`、`ui/multipoint_panel.py`、`ui/sensor_panel.py`、`ui/finger_source_panel.py`、新增的 `ui/*` 组件,以及相应 UI 测试 | 控制器逻辑、数据格式 |
|
||||||
|
| D 编码验证 | P2b | 只在 scratch 中写脚本和报告 | 产品代码 |
|
||||||
|
| V 验收 | 最终验收 | 只读;可在 scratch 中写报告 | 任何产品文件 |
|
||||||
|
|
||||||
|
同一时间最多 3 个实现子代理在工作。控制器 API 冻结前,C 只能对着主代理给出的桩接口开发。
|
||||||
|
|
||||||
|
## 执行顺序
|
||||||
|
|
||||||
|
```text
|
||||||
|
W0 主代理 P0 + 冻结 CaptureController / RecordingOptions 接口
|
||||||
|
W1 A: P1 → P2 B: P3 D: P2b (三者并行)
|
||||||
|
W2 C: P4(需要 P1、P3;P2 合入后补 Ready 行的录像标签)
|
||||||
|
W3 C: P5 主代理: P6 文档;可选的批次导出交给 A
|
||||||
|
W4 V: 独立验收 → 主代理修复 → V 复核修复项
|
||||||
|
```
|
||||||
|
|
||||||
|
检查点 1 在 W1 结束时:P1、P2、P3 的 V1–V3 全部通过,才允许开始 W2。检查点 2 在 W3 结束时:V1–V8 全部通过,才交给 V。
|
||||||
|
|
||||||
|
## 任务清单
|
||||||
|
|
||||||
|
### W0 主代理
|
||||||
|
|
||||||
|
- [ ] P0 基线:记录 HEAD、工作树状态和基线测试结果到 `scratch/baseline.md`。
|
||||||
|
- [ ] 冻结接口,写入 `scratch/interfaces.md`:`readiness()`、`primary_action()`、`perform()`、`secondary_actions()`、`poll()` 的签名、返回结构和动作键清单;`RecordingOptions` 的字段与 `session.json` 中 `recording` 块的结构。
|
||||||
|
|
||||||
|
### A 数据与文件
|
||||||
|
|
||||||
|
交接提示:你负责让用户能找到数据、能控制视频体积。不得改变原始目录结构、不得删除或移动已有录像;summary 副本只是方便查看,指针仍是唯一权威。
|
||||||
|
|
||||||
|
- [ ] P1:`reveal` 提取与三个按钮(按钮的布局由 C 在 P4 完成;A 在 P1 先接到现有会话行),`summary/` 平铺副本及失败处理。测试:`test_summary_export.py` 增加副本一致性、副本失败两项,新增 `test_reveal.py`。
|
||||||
|
- [ ] P2:录像选项、工厂函数、`recording` 块、`video_expected` 判定、编码探测、体积估算。测试:`test_multipoint_recording.py` 增加关视频完成、编码不可用两项;`test_summary.py` 增加关视频行 eligible、旧会话不变两项;`test_preferences_isolation.py` 覆盖新的偏好键。
|
||||||
|
|
||||||
|
### B 控制器
|
||||||
|
|
||||||
|
交接提示:你负责把流程判断从界面中移出。控制器不得发出运动命令、不得导入 Qt;对准只发出请求。每个禁用的动作必须带原因,原因文字通过 locale 键给出。
|
||||||
|
|
||||||
|
- [ ] P3:实现控制器及表驱动测试;用同一组输入比较“直接驱动 `Campaign`”与“经由控制器”写出的文件结构。
|
||||||
|
|
||||||
|
### C 界面
|
||||||
|
|
||||||
|
交接提示:你负责重排界面,依据是设计稿与主计划 P4、P5。界面只渲染控制器的输出;不得在 `ui/` 中判断 `campaign.phase`。实时图与 UV 图必须能同时看到。
|
||||||
|
|
||||||
|
- [ ] P4:新布局、更改输入对话框、队列表模型、当前点卡片、消息行;在模拟模式下用界面测试走完两点;截图存 scratch。
|
||||||
|
- [ ] P5:Finger debug 改名并瘦身,测点表迁移,安装偏置变化后重新求解。
|
||||||
|
|
||||||
|
### D 编码验证
|
||||||
|
|
||||||
|
- [ ] P2b:按主计划完成对比并写报告,内容包括输入文件、编码参数、逐帧差值统计和窗口均值差占 1 N 阶跃的比例。不给结论性推荐,由用户决定。
|
||||||
|
|
||||||
|
### V 验收
|
||||||
|
|
||||||
|
- [ ] 用新进程跑完主计划 V1–V8;按严重度列出发现,每条附复现步骤;不修改代码。
|
||||||
|
|
||||||
|
## 子代理交付格式
|
||||||
|
|
||||||
|
每个任务结束时交回以下内容:
|
||||||
|
1. 改动文件清单;
|
||||||
|
2. 新增测试,以及它们在修复前失败的证据(可行时);
|
||||||
|
3. 实际执行的命令和结果(复制输出摘要,不改写);
|
||||||
|
4. 未验证项及原因;
|
||||||
|
5. 接口变化;没有就写“无”。
|
||||||
|
|
||||||
|
不得把跳过、未运行或环境缺失写成通过。
|
||||||
|
|
||||||
|
## 主代理最终交接
|
||||||
|
|
||||||
|
- [ ] 所有改动保持未暂存;每个改动过的仓库各写 `.scratch/autocal-capture-workflow/commit-message.txt`,按 AGENTS 第 7 条给出单行的 `git add` 和 `git commit -F` 命令。
|
||||||
|
- [ ] 列出需要排除的既有改动。
|
||||||
|
- [ ] 状态写为“仅软件验证,待实机验收”;V10 实机验收需要用户指定设备、运动与载荷范围以及停机条件。
|
||||||
Reference in New Issue
Block a user