Files
code-test-drone/legacy/docs/双目相机模组到位作业指导.md
T
keita df91b1110e 精简仓库结构并增强任务链路:归档双目可选后端、新增LOS判据与自定义返航
归档 legacy/:stereo_yolo/stereo_ranger/target_tracker 三包 + 175 条测试 + demo/配置/权重/三份规格;运行链路不再依赖,默认 pytest 446 条,归档测试按需运行。

目标有效性第二判据改为 LOS 运动学一致性(pod_bridge/los_consistency.py),删除 require_vision;pod_locked() 叠加该判据,状态机随之后退重搜。

自定义返航(task_runner/return_home.py):保持转场高度回起飞点 → 恢复初始航向 → 垂直降落,不再爬 RTL_RETURN_ALT;未起飞/无起飞点/超时/异常仍退回 PX4 原生 RTL。

任务链安全兜底:主循环异常→紧急返航、stop 幂等、landing_stop 保留遥测、in_air 流复用+超时、解锁/起飞与吊舱识别仅执行一次、rtl_timeout 上限。

入口共享件拆到 utils/sitl_support.py;pod_sitl_test.py→l1_sitl_test.py;删除旧架构 test.py;相机脚本移入 tools/。

新增 .gitignore 并剔除历史误跟踪的 59 个 .pyc;requirements 按实际依赖重写;文档全面对齐,新增 legacy/README.md 与 tools/README.md。
2026-10-21 14:48:41 +08:00

302 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 双目相机模组到位作业指导
> **定位**:`docs/` 下三份规格(《双目测距技术路线》《双目YOLO目标识别需求说明》
> 《视觉跟踪控制律技术路线》)回答"应该怎样、判据是什么";本文回答"相机模组到货
> 之后按什么顺序做什么、每步怎么判通过、结果回填到哪里"。**本文不新立判据**——
> 所有通过标准一律引用规格原文并注明章节。
>
> **适用范围**:双目相机模组(含厂商标定数据)到货起,至《测距路线》§12.3 四条
> 红线解除为止。飞控/机载平台到位后的工作属《视觉跟踪控制律技术路线》§8 阶段 4~6,
> 本文只在阶段 6 交接。
>
> **编写状态(2026-09-14)**:仓库内几何参数全部为占位值
> (`utils/config/stereo_ranger.json`)、demo 素材为 AI 合成图,本文判据**尚未在
> 任何真实设备上执行过**。首次执行后请把实测偏差与踩坑回填本文,并去掉本行。
---
## 0. 一页速览
| 阶段 | 内容 | 出口判据(出处) | 解除的阻塞 |
|------|------|-----------------|-----------|
| P0 | 开箱登记与数据清点 | 登记表(附录 A.1)填满;缺失项有替代方案 | 厂商数据可用性未知 |
| P1 | 几何参数回填 | fail-fast 校验通过 + 新有效域覆盖任务包线(§9.1/§11.2) | 几何参数为占位 |
| P2 | 校正质量核验 | 静态场景 \|Δy\| P95 ≤ 1 px(§12.1) | 极线对齐不可信 |
| P3 | 真实素材采集入库 | 覆盖 5/10/15/20/25 m 档、元数据齐(§2.3) | 素材只有合成图 |
| P4 | 测距真值验证 | 有效域内 δZ ≤ 2 m、趋势 ∝ Z²(§12.1) | 数值从未对过真值 |
| P5 | 阈值整定 | §9 各表 ⚠ 全部替换为实测值(§12.2) | 阈值全部占位 |
| P6 | 台架/SITL 联动 → 解禁评审 | 控制联动场景全覆盖(§12.1);§12.3 四条逐条勾选 | 红线未解除 |
依赖顺序:P0 → P1 → P2 → P3 → P4 → P5 → P6。P2 必须在 P1 之后(校正质量要在
正确内参下判读),P4 必须在 P3 之后(没有真实素材就没有真值比对)。
---
## 1. 阶段 0:开箱登记与数据清点
### 1.1 向厂商索取的清单
| 数据 | 用途 | 缺失时的替代方案 | 落位 |
|------|------|-----------------|------|
| 校正后内参 `fx_px`/`fy_px`/`cx_px`/`cy_px` | §9.1 几何组,`Z = F·B/D` 的分母来源 | 自标定(张正友);**P2 判据不达标时本就要提前做** | `utils/config/stereo_ranger.json` |
| 基线 `baseline_m`(标称 + 实测公差) | §9.1;`F·B` 常量 | 卡尺/塞规实测,记录不确定度 | 同上 |
| 畸变系数与校正映射(remap maps)或"已做校正"的书面确认 | §2.2 第 4 条:前端输出的是校正后图上的框 | 自标定 + 自建 remap 表 | 采集预处理(不在本仓) |
| 出厂标定报告与不确定度 | P1/P2 的判据依据,**要存档** | 无报告 = 按未标定处理,走自标定 | 本文附录 A.1 |
| 分辨率 / 帧率 / 像素格式 / 位深 | 原生坐标系与算力预算(《需求说明》§5) | — | 附录 A.1 + `stereo_yolo.json` 复核 |
| 同步方式与触发接口(sbs / 双流 / 硬触发) | §2.3 同帧契约的形态选择 | sbs 优先(天然同曝光,§2.3) | 采集端设计 |
| 机械图纸(安装接口、两目光轴平行度要求) | 安装外参、换机型(P6) | — | 附录 A.1 |
### 1.2 到货当天建议实测
1. **基线复核**:卡尺/图纸比对标称值,偏差 >1% 时以实测为准并记录(`F·B` 直接决定距离标定);
2. **同帧性验证**:拍快速横向移动的手/笔,sbs 形态应为同一时刻;双流形态量化两路时间窗抖动并记录(§2.3 要求"残余时序抖动应记录供误差评估");
3. **分辨率与帧率实测**:跑满声称帧率,记录实际值与丢帧情况(供 P5/P6 的算力预算);
4. **图像质量目测**:左右目曝光/增益是否一致(不一致会让同一目标两目置信度与框边缘不对称,污染视差取点)。
---
## 2. 阶段 1:几何参数回填
### 2.1 改哪些字段
只动 `utils/config/stereo_ranger.json` 的 **5 个几何项**:
```
fx_px, fy_px, cx_px, cy_px ← 厂商校正后内参(注意:fx=fy=F 是校正后口径)
baseline_m ← 实测基线
```
`utils/config/stereo_yolo.json` **不含几何参数**(输出框天然位于输入图的原生
坐标系,§4 配置一致性要求)——前端无需回填,只需复核 `imgsz` 与真实分辨率匹配。
**视差域 `disparity_min_px` / `disparity_max_px` 不是标定数据**,是任务决策项:
按任务近界 `Z_near` 反推 `disparity_max_px = F·B / Z_near`,按可测远界定
`disparity_min_px`。回填内参后 `F·B` 变化,两者的距离语义会平移,**必须重算**。
### 2.2 回填后必算的派生量(写进记录表)
| 派生量 | 公式(代码属性) | 用途 |
|--------|-----------------|------|
| `F·B` | `fx_px × baseline_m`(`focal_baseline_px_m`) | 距离解算常量 |
| `z_min_m` | `F·B / disparity_max_px` | 近界(只读派生) |
| `z_max_m` | `F·B / disparity_min_px` | 远界(只读派生) |
| `z_error_budget_max_m` | `sqrt(max_delta_z_m × F·B)` | 误差预算门对应的最远距离(§7.2,δD 基准固定 1 px) |
以上四项**不是配置项**,由 `StereoConfig` 只读派生(v1.0 冻结:视差域权威,
距离域派生,避免两处冗余互推舍入不一致,§6.4)。回填后手算一遍与程序输出比对,
作为回填正确性的一次交叉验证。
### 2.3 判据
1. **fail-fast 校验通过**:JSON 必须含全部 17 个键、无未知键、类型正确
(`consistency_N_frames` / `consistency_M_frames` / `filter_reset_frames`
必须是整数,`3.5` 或 `true` 会被拒);取值约束:`0 < disparity_min_px < disparity_max_px`、
`consistency_M_frames ≥ consistency_N_frames`、`0 < smooth_alpha ≤ 1`、
`cx_px`/`cy_px` 非负、其余数值项一律为正(以 `stereo_ranger/config.py` 为准);
2. **有效域覆盖任务包线**:新的 `z_min_m` / `z_max_m` / `z_error_budget_max_m`
与任务的距离区间逐项比对,**不达标时先改视差域/基线/机型(P6),不要迁就旧数值**;
3. 记录回填前后的 diff 与批准人(附录 A.2)。
### 2.4 连带修改清单(容易漏,会导致测试变红)
| 受影响处 | 现象 | 处置 |
|---------|------|------|
| `utils/tests/stereo_ranger/config_test.py::test_load_from_json_matches_defaults` | **必失败**:该用例断言 JSON 内容与 `StereoConfig()` 占位默认值逐字段相等 | 改为"语义一致性"断言(域关系、派生恒等式、取值约束),或维护一份"当前标定值"副本单独比对;**不要**为了过测试而改 dataclass 默认值——默认值是单测的占位基准 |
| `utils/tests/stereo_yolo/config_test.py::test_load_from_json_matches_defaults` | 同上(仅当改动 `stereo_yolo.json` 时) | 同上 |
| `docs/双目测距技术路线.md` §9 各表的 ⚠ 标记 | 表格仍写占位值 | 回填为实测值并标注日期与来源(保持"以规格为准") |
| `utils/stereo_ranger/README.md`、`utils/stereo_yolo/README.md` 的占位值表 | 同上 | 同步,并撤掉"占位红线"字样(或改为"已标定") |
| `utils/demo_stereo_ranger.py` 的注释(`F·B=57.6 px·m`) | 注释过时 | 同步数值 |
---
## 3. 阶段 2:校正质量核验
**判据(§12.1 校正质量)**:静态场景下,左右匹配框的 \|Δy\| 分布 **P95 ≤ 1 px**(⚠占位)。
不达标 → **触发自标定提前**(§7 风险表第 7 项、《需求说明》§6)。
### 3.1 建议方法
1. 静态标靶(棋盘格或随机纹理板)摆在近/中/远 3 档(如 3 / 8 / 15 m),每档在画面
中心与四角共 5 个区域成像;
2. 每处采 ≥50 帧,用**检测链路本身**(前端 → 两目框)统计 `|y1_L − y1_R|` 与
`|cy_L − cy_R|` 双口径的 P95;
3. 交叉验证:若统计值接近 1 px,改用角点/纹理匹配口径(不依赖检测框边缘)复核,
避免把"检测边缘抖动"误判成"校正误差"。参考量级:本仓合成对(已知零校正误差)
在 1080p 下实测 \|Δy\| ≈ 0.2 px,即**检测链路自身就贡献约 0.2 px 噪声**。
### 3.2 不达标时的排查顺序
1. 内参/remap 是否张冠李戴(最常见:用原始图内参解释校正图);
2. 校正映射是否按原生分辨率生成(缩放过的 map 会引入亚像素偏置);
3. 两目光轴平行度/安装(机械问题,需厂商介入);
4. 仍不达标 → 自标定(P2 不达标即 v1.1 自标定提前,§7 风险表)。
⚠ **工具缺口**:仓库目前**没有**该统计脚本,需新增(建议 `utils/tools/calib_check.py`,
输入左右目图像目录,输出 \|Δy\| 直方图与 P95)。
---
## 4. 阶段 3:真实素材采集与入库
### 4.1 采集清单
| 档位 | 内容 | 用途 |
|------|------|------|
| 5 / 10 / 15 / 20 m | 静态标靶(或无人机目标静置),每档 ≥50 帧,手持激光测距仪同步记录真值 | P4 测距精度(§12.1) |
| ≥25 m(域外档) | 同上 | 验证"域外不撒谎":`valid=false` 且方位照常发布(§12.3 第 3 条) |
| 横向快速移动 | 目标在画面内快速平移 | 帧同步核验(§12.1:无系统性虚假视差) |
| 多目标 | 同画面 2 个同类目标 + 1 个非目标干扰 | P5 的 `isolation_gate_px` 整定 |
| 丢失-恢复 | 目标被遮挡 ≥ `filter_reset_frames` 帧后重现 | P5 的 `filter_reset_frames` / `smooth_alpha` 整定 |
### 4.2 命名与落位(建议)
```
utils/assets/stereo_yolo/<YYYYMMDD>/z05m_01_L.png
z05m_01_R.png # 双流形态
z05m_01_sbs.png # sbs 形态(推荐,§2.3)
z05m_01.json # 元数据
```
元数据必填字段:拍摄时间、距离真值 + 测距仪型号、目标类型、光照/天气、曝光与增益、
同步形态、分辨率、帧号范围、操作人。
### 4.3 注意
- **素材必须是校正后的图**(或同时保存原始图 + 本次使用的 remap 表)——否则 P4 的
误差里混进校正误差,无法归因(§2.2 第 4 条);
- 替换 `utils/assets/stereo_yolo/drone_sky.png` 只能换"单图冒烟"的输入;上面这套
目录结构需要配回放脚本(见 P4 工具缺口)。
---
## 5. 阶段 4:测距真值验证
**判据(§12.1 测距精度)**:以**地面手持激光测距仪**为真值(D8:测距方向与 `Z`
一致,不是斜距 `R`);有效域内 **δZ ≤ 2 m**(⚠占位);误差趋势符合 `δZ ∝ Z²`(§7.1)。
### 5.1 方法与产物
1. 每档 ≥50 组"前端 → `StereoRanger.update()`"输出,与真值比对,输出**误差-距离曲线**;
2. 由曲线拟合实测 δD(视差噪声基准,当前固定 1 px 是占位,§12.2),
并用 `Z_budget = sqrt(max_delta_z_m × F·B / δD_meas)` 反推"预算门"应落在哪;
3. 单独跑域外档,确认 `valid=false` 且 `center_mid_px` 仍发布(§7.3 域外不撒谎,
也不丢方位);
4. 结果记入附录 A.4。
### 5.2 不通过时的归因顺序
| 现象 | 首先怀疑 | 处置 |
|------|---------|------|
| 全档系统性偏置 | 内参/基线错、取点规则 | 复核 P1 回填值;复核 `x1` 取点(§6.1 同侧边缘) |
| 误差随 Z² 放大且系数偏大 | 实测 δD 大于既定基准 | 收紧 `max_delta_z_m` 或缩小有效域;把实测 δD 写回规格(§12.2) |
| 远场随机跳变 | 检测边缘抖动 + 小视差放大 | 属预期(§7.2),确认降级/门限按 §6.4 生效即可 |
| 横向移动时出现虚假视差 | 帧同步 | 回到 P3 复核同步形态(§2.3) |
⚠ **工具缺口**:仓库目前**没有**"真实素材回放"脚本(现 demo 的合成对是解析构造的),
需新增(建议 `utils/tools/replay_stereo.py`,输入 4.2 的目录结构,输出逐帧记录
与误差表)。
---
## 6. 阶段 5:阈值整定清单
§9 表中每个 ⚠ 都要在本阶段被实测值替换。整定依据与建议方法:
| 参数 | 占位值 | 整定输入 | 建议方法 |
|------|-------|---------|---------|
| `tau_y_px` | 2.0 | P2 的 \|Δy\| 分布 | 取 P95 的 1.5~2 倍留余量 |
| `tau_h_ratio` | 0.25 | 真实框高相对差分布 | 同上口径 |
| `disparity_min_px` | 3.0 | 可测远界需求 | 由任务远界反推(P1 已重算) |
| `disparity_max_px` | 57.6 | 任务近界 | 由 `Z_near` 反推(P1 已重算) |
| `max_delta_z_m` | 2.0 | P4 的误差曲线 | 由可接受的最大距离误差定;与 δD 实测联动(P4 第 2 步) |
| `consistency_jump_px` | 3.0 | 静态场景视差噪声 P95 | 取噪声峰值的数倍:太小误判、太大漏检(§6.7) |
| `consistency_N_frames` | 3 | 安全需求 + 误报率 | N/M 决定"异常后多久降级/判无效"(3/5 ≈ 0.17 s @30 fps),与消费侧的降级时延一起定 |
| `consistency_M_frames` | 5 | 同上 | 必须 ≥ N |
| `smooth_alpha` | 0.3 | P4 数据离线拟合 | 在"噪声抑制"与"群延迟"间取平衡(0.3 ≈ 3.3 帧群延迟) |
| `jump_reset_m` | 5.0 | 真实跳变幅度观测 | 用目标切换/大机动场景标定 |
| `filter_reset_frames` | 5 | 丢失-恢复场景 | 与消费侧 coast 策略配合(§6.5) |
| `isolation_gate_px` | 50.0 | 多目标场景 | 由"同帧不同目标的最小像素间距"定,取小于该值的门限 |
前端侧同步复核:`conf_threshold` / `iou_threshold` 与真实素材上的漏检/误检权衡;
`imgsz` 与平台算力(P7)——**这两项不随标定变化,但要与检测质量一起整定**。
---
## 7. 阶段 6:台架/SITL 联动与解禁评审
### 7.1 台架联动(判据见 §12.1 控制联动)
回放/SITL 下跑通:距离闭环 ↔ 定速接近切换、`invalid` 持续降级路径、
远场"方位闭环 + 定速接近"(D4)——场景覆盖要求见《视觉跟踪控制律技术路线》第 7 章。
### 7.2 解禁检查表(§12.3 四条逐条勾选)
- [ ] **红线 1**:§7/§9 中所有 ⚠ 数值已由实测/厂商数据确认,替换记录已归档(附录 A.2/A.3/A.4);
- [ ] **红线 2**:相机参数与阈值全部在配置文件中,代码内无写死(含 demo/工具脚本复核);
- [ ] **红线 3**:域外/失配确实输出 `valid = false`——合成回归(`pytest -q`)+ 真实素材(P4 域外档)两轮都有证据;
- [ ] **红线 4**:地面真值验证完成并归档(P4 全档通过)。
### 7.3 解禁之后仍未解禁的
本文解除的是**测距/检测链路**的红线。实飞还要求控制律侧完成
《视觉跟踪控制律技术路线》§8 阶段 6 的增益与限幅整定——两者都满足才可实飞。
---
## 附录 A:记录表模板
### A.1 开箱登记
| 项 | 值 |
|----|----|
| 型号 / 序列号 | |
| 分辨率 / 帧率 / 像素格式 | |
| 标称基线 / 实测基线(工具、公差) | |
| 校正后内参(fx, fy, cx, cy) | |
| 畸变系数 / remap 表版本 | |
| 出厂标定报告编号与日期 | |
| 同步形态(sbs / 双流 / 硬触发) | |
| 到货日期 / 登记人 | |
### A.2 参数回填记录
| 字段 | 回填前 | 回填后 | 来源 | 日期 / 批准 |
|------|-------|-------|------|------------|
派生量复核(手算 vs 程序):`F·B` = ___,`z_min_m` = ___,`z_max_m` = ___,
`z_error_budget_max_m` = ___。
### A.3 校正质量核验
| 档位 | 区域 | 样本数 | \|Δy\| P95 | 判据 ≤1 px | 备注 |
|------|------|-------|-----------|-----------|------|
### A.4 测距真值验证
| 距离真值 | 样本数 | Z 均值 | δZ | 判据 ≤2 m | valid 率 | 备注 |
|---------|-------|-------|----|----------|---------|------|
---
## 附录 B:判据来源索引
| 本文阶段 | 规格出处 |
|---------|---------|
| P1 回填与派生量 | 《测距路线》§9.1、§6.4、§11.2 |
| P1 连带修改 | `utils/stereo_ranger/config.py`(fail-fast 规则)、两份 `config_test.py` |
| P2 校正质量 | 《测距路线》§12.1、§7 风险表第 7 项;《需求说明》§6 |
| P3 采集与同步 | 《需求说明》§2.3;《测距路线》§12.1 帧同步 |
| P4 真值验证 | 《测距路线》§12.1、§7.1、§7.2、§7.3(D8 真值方向) |
| P5 阈值整定 | 《测距路线》§9 全表、§12.2;《需求说明》§4 |
| P6 联动与解禁 | 《测距路线》§12.1、§12.3;《视觉跟踪控制律技术路线》§7/§8 |
## 附录 C:已知缺口(执行前需补齐)
1. **工具脚本缺三件**(本文标注 ⚠):校正质量统计(P2)、真实素材回放(P4)、
真值-误差曲线拟合(P4)。在它们就位前,P2/P4 只能手工抽样,判据不可复现;
2. **外部参考文档缺档**:《测距路线》§12.2 把开放问题(P1 焦距规格、P2 出厂标定、
P3 帧同步形态、P6 换机型、P7 性能实测、P8 避障激光去留)的**权威清单**指向
《双目深度估计思路》第 15 章,该文档当前不在仓库中——需要它才能核对问题编号与
结论,请补回或改引他处;
3. **P7(性能实测)不在本文范围**:它依赖机载/边缘平台,属平台工程文档。