Files
code-test-drone/legacy/docs/双目测距技术路线.md
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

755 lines
40 KiB
Markdown
Raw Permalink 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.
# 双目测距技术路线
> 本文档把双目测距(立体目标测距)抽象为**与编程语言、硬件平台无关**的技术路线:
> 只讲几何模型、数据结构、算法流程与质量语义,不依赖任何语言特性、加速器
> 型号或操作系统。可作为任意语言(C++/Rust/Python 仿真/嵌入式 C)在任意
> 算力平台上重新实现或移植的规格说明。
>
> **文档分工**(各司其职,不重复抄录):
>
> | 文档 | 定位 | 与本文的分工 |
> |------|------|--------------|
> | `docs/双目深度估计思路.md` | 平台工程路线 + 原稿对照 | **平台与工程细节权威**:采集/解码链路、加速器预算、线程与文件落点、原稿缺陷对照;本文一律不涉及 |
> | 本文 | **算法路线** | **算法与语义权威**:几何、取点、匹配、有效性、滤波、方位源、误差模型、职责与缺点 |
> | `docs/视觉跟踪控制律技术路线.md` | 距离/方位的消费者 | 其距离通道与方位源如何消费本文输出,见其 §1.2/§2/§6.4 |
> | `docs/双目测距方案讨论纪要.md` | 决策索引 | D2/D4/D5/S1~S3 等拍板结论的唯一索引,本文只落实、不重新讨论 |
>
> 三份技术路线若出现表述分歧:拍板结论以《双目测距方案讨论纪要》为准,
> 算法语义以本文为准,平台工程以《双目深度估计思路》为准。
>
> **参考实现**:`utils/stereo_ranger/`(Python,构件划分与本文逐条对应)。
> 实现时冻结的补充决策与发现的原文矛盾已回填本文(§4/§6.1/§6.2/§6.4/
> §6.7/§9/§11),两文档以本文为准。
>
> ⚠️ **全部数值均为占位值**:焦距/标定参数待厂商数据(P1/P2),各阈值未整定。
> 标定与地面真值验证完成前,本模块输出**仅限静态标靶/回放/台架验证,
> 不得作为飞行控制决策依据**(见 §12.3 红线)。
---
## 目录
1. [概述与系统定位](#1-概述与系统定位)
2. [输入输出接口定义](#2-输入输出接口定义)
3. [坐标系与符号约定](#3-坐标系与符号约定)
4. [核心构件与状态清单](#4-核心构件与状态清单)
5. [单周期处理流程(主流程伪代码)](#5-单周期处理流程主流程伪代码)
6. [各环节算法细节](#6-各环节算法细节)
7. [误差模型与有效距离域](#7-误差模型与有效距离域)
8. [职责、边界与已知缺点](#8-职责边界与已知缺点)
9. [配置参数全量表](#9-配置参数全量表)
10. [设计取舍记录(为什么不是别的做法)](#10-设计取舍记录为什么不是别的做法)
11. [实现与重写指引](#11-实现与重写指引)
12. [验证路线与待定项](#12-验证路线与待定项)
---
## 1. 概述与系统定位
### 1.1 模块职责
本模块是**目标距离与方位的机载唯一来源**(决策 D2:双目替代激光雷达,
与提交 b96111e 一致)。它对**同一时刻**左右两幅已立体校正图像上的目标
检测框做立体几何解算,输出**少量目标的**距离与方位(不是稠密深度图)。
职责四件事:
1. **匹配**:把左右两目的检测框按"同一物理目标"配对(硬约束筛选 +
贪心代价排序);
2. **测距**:同侧边缘视差 D → `Z = F·B / D` 前向距离(斜距 R 仅参考输出);
3. **方位源**:输出**虚拟双目中心**像素 `c_mid`(两目框中心等权平均,
消除单目近场视差偏差,§6.6);
4. **质量语义**:输出有效性标志与置信度(有效域内 + 匹配成功 + 一致性
正常),对距离做轻量时间滤波;域外/失配/异常时**明确输出无效**,
不得强行估计。
### 1.2 在系统中的位置
```text
平台采集/解码/立体校正(平台相关,见《双目深度估计思路》第 3/8 章)
→ 校正后左/右图像(同帧)
→ 左/右目标检测(外部模块,输出原图坐标系的检测框)
→ 本模块:匹配 + 测距 + 方位源 + 有效性 + 滤波 → 目标距离记录
├─ 距离 Z(valid)──▶ 控制律距离通道(Δd → PID → 前向速度,域内闭环)
├─ 方位 c_mid ──────▶ 接入层填入控制律目标中心(虚拟中心相机像素)
└─ valid / 置信度 ──▶ 接入层降级语义:
域外/失配 → "无距离"策略(方位闭环 + 定速接近,D4)
持续无距离 → exit 档降级(S1 门限,消费侧实现)
```
**上游**:同帧校正图像对与左右检测框(检测、采集、解码、校正均为外部
模块);**下游**:跟踪控制律与接入层。"域外定速接近"的远场补偿策略
属消费侧行为,本文只负责提供诚实的有效性标志与持续的方位。
### 1.3 设计特点
| 特点 | 含义 | 带来的约束 |
|------|------|-----------|
| **稀疏输出** | 只算检测到的目标,不做逐像素匹配 | 无检测即无输出;距离精度受框质量制约(§8) |
| **纯值输入/输出** | 每帧传入同帧框对 + 参数,输出纯值记录列表 | 无隐藏输入、可离线回放 |
| **纯函数构件** | 取点、测距、域判定均为无状态纯函数 | 可独立单元测试(合成框对即可,无需真实图像) |
| **有状态部分极小** | 仅滤波器、一致性监控与目标隔离状态,且按目标隔离 | 重写时状态清单见 §11.1,漏一个就变行为 |
| **参数全外置** | 几何、阈值、滤波参数全部来自配置 | 代码内不得写死任何相机参数或阈值 |
| **诚实降级** | 域外/失配输出 `valid = false` 而非勉强给值 | 消费侧的远场策略建立在"不撒谎"的有效性上 |
### 1.4 明确不做的事(边界)
- **不做采集/解码/立体校正**:消费校正后的图像与框;校正与自标定属
平台工程(v1.1 备选),不在本文范围;
- **不做稠密匹配**:不做 SGBM 类逐像素立体匹配,不输出深度图;
- **不做环境感知/避障**:环境深度由避障侧深度模型负责,与本模块并存
互不替代;
- **不做目标跟踪**:不维护轨道与运动滤波;上游 track_id 只用作目标
状态隔离键(§4),不参与匹配打分与连续性先验(后者留 v1.1);
- **不做运动/IMU 补偿**:帧间运动引起的虚假视差靠帧同步契约与一致性
监控兜底,不做解算级补偿;
- **不做多传感器融合**:双目是目标距离机载唯一来源(D2),无交叉校验
基准;数据质量靠内部一致性监控自检(§6.7);
- **不在域外强行估计**:超出有效距离域一律输出 `valid = false`。
---
## 2. 输入输出接口定义
### 2.1 输入(每帧一次,由平台层供给)
| 分组 | 项 | 语义与约束 |
|------|----|-----------|
| 帧对 | 左帧、右帧 | 各含**帧标识**;两帧标识必须一致(同帧契约,见下) |
| 检测 | 检测框数组 ×2 | 每框含:类别、置信度、框(左上/右下角像素);**已映射回校正图像坐标系** |
| 几何 | 基线 `B`、焦距 `F`、主点 `cx, cy` | 校正后内参(`fx = fy = F`);来自标定配置,禁止写死 |
| 参数 | 匹配/有效性/滤波阈值 | 配置外置(§9),启动期加载并校验 |
| 时钟 | 当前单调时刻 | 用于输出打戳 |
**契约要点**:
- **同帧契约**:左右帧必须来自同一曝光时刻(同步与配对由平台层保证,
形态差异见《双目深度估计思路》§3.2)。本文把"左右帧标识一致"作为
输入违约检查:不一致直接拒收本帧、输出空、告警节流——**不同帧的
框配对解算没有物理意义**;
- **校正契约**:检测框位于**已立体校正**的图像上("两目 y 对齐"是校正
的结果而非假设,§3);未校正图像上的框不得进入本模块;
- **坐标基准一致**:检测若在缩放/裁剪图上运行,框必须先映射回校正图像
基准,且几何参数 `F/cx/cy` 使用同一基准的内参——否则视差与几何失配,
距离系统性错误;
- **时间戳纪律**:输出取样时刻以**平台接收时刻的单调时钟**为准,
不伪造采集时刻。
### 2.2 输出:目标距离记录(每帧每目标一条,纯值)
| 字段 | 单位/类型 | 语义 |
|------|-----------|------|
| 帧标识 | — | 继承自输入帧对 |
| 类别 | 枚举 | 目标类别 |
| 轨道关联 | 整数或"无" | 检测侧 track 关联(如有;v1.0 可无) |
| `Z` | m | 前向距离(沿光轴分量,**距离通道唯一消费量**) |
| `R` | m | 斜距(参考值,不进控制回路;与已发布的 `Z` **同基准**——按滤波后 Z 换算,保证 `R ≥ Z`) |
| `D` | px | 本次视差(调试与交叉校验用) |
| `c_mid` | 像素 (x, y) | **虚拟双目中心**框中心:方位控制源(§6.6) |
| 参考目框 | 像素框 | 左目(参考目)检测框,供交叉校验与调试 |
| `confidence` | [0,1] | 匹配质量与一致性综合置信度 |
| `valid` | 布尔 | 是否落在有效距离域且匹配成功且一致性正常(§6.4) |
| 退化标记 | 枚举 | `完整`(距离+方位)/ `仅方位`(单目检出,§5 第 ⑤ 步) |
| 取样时刻 | 单调时钟 | 平台接收时刻打戳(§2.1 时间戳纪律) |
**记录两态**:
- **完整记录**(匹配成功):距离 + 方位 + 有效性;
- **仅方位记录**(仅一目检出,v1.0 允许):发布该目框中心作方位,
`valid = false`,无距离;单目方位存在近场视差偏差(§6.6,v1.0 接受)。
### 2.3 输出语义与消费侧衔接
- `valid == true` 的 `Z` 才可作为控制律距离通道输入;消费侧另有自己的
"有效性 + 正值 + 未超龄"三重门(见《视觉跟踪控制律技术路线》§6.4);
- `valid == false`(域外/失配/一致性异常)→ 消费侧进入"无距离"策略
(方位闭环 + 定速接近,默认档),持续无距离达门限才退出近距操作
(消费侧 exit 门限,S1);
- **`c_mid` 始终随检测发布**(域外仍有方位)——这是远场"方位闭环 +
定速接近"策略得以成立的输入基础;
- 消费侧以 `track_id` 一致性校验本记录与追踪主目标对应(调用方约定
S3,库内不实现)。
---
## 3. 坐标系与符号约定
### 3.1 符号表
| 符号 | 含义 | 单位 |
|------|------|------|
| `B` | 基线长度(左右光心间距) | m |
| `F` | 像素焦距(校正后 `fx = fy`) | px |
| `cx, cy` | x/y 方向主点 | px |
| `xL, yL` | 目标点在**左目(参考目)**图像中的像素坐标 | px |
| `xR` | 同一目标点在右目图像中的像素坐标 | px |
| `D` | 视差 = `xL − xR` | px |
| `Z` | 前向距离(沿光轴分量) | m |
| `X, Y` | 相机(左目)坐标系横向/纵向偏移 | m |
| `X_C` | 目标在**模组中心系**的横向偏移 | m |
| `R` | 斜距 | m |
| `cL, cR` | 同一目标在左/右目中的**检测框中心** | px |
| `c_mid` | 虚拟双目中心框中心(方位源) | px |
**统一约定**:校正后**以左目为参考系**,视差 `D = xL − xR > 0`
(正视差是物理前提;`D ≤ 0` 视为违例,§6.3)。
### 3.2 公式(校正后坐标系)
```text
D = xL − xR (同一物理特征点的 x 坐标差)
Z = F × B / D
X = (xL − cx) × Z / F (左目系)
Y = (yL − cy) × Z / F
R = sqrt(X² + Y² + Z²)
```
- **距离通道使用 Z(前向分量)而非 R**:与机头前向的期望射程语义对齐,
也与地面真值仪(手持激光测距仪)的测量方向一致(决策 D8);
小角度下 `Z ≈ R`,大偏航角目标时二者差异增大,地面验证解读数据须注意;
- **X/Y 以左目系表达**;模组中心系下 `X_C = X − B/2`(左目光心在模组中线
−B/2 侧,符号与 §6.6 一致;原文 `+B/2` 为笔误),`B/2` 对 `Z`、`R` 的
影响可忽略(本机型 3cm)。
---
## 4. 核心构件与状态清单
| 构件 | 职责 | 运行期持久状态 | 备注 |
|------|------|---------------|------|
| 流程编排 | 单周期五步流程(§5) | 无 | 每帧一次 |
| 视差取点器 | 框 → 取点 x(同侧边缘,回退中心) | 无(纯函数) | §6.1 |
| 匹配器 | 左右框配对 | 无(纯函数) | **接口注入**,默认贪心;可替换为匈牙利等而不动调用方 |
| 测距计算 | `(D, 框)` → `(Z, X, Y, R, c_mid)` | 无(纯函数) | §3.2/§6.6 |
| 有效性判定 | 域内 + 误差预算判定 | 无(纯函数) | §6.4 |
| 一致性监控 | 时序层面质量自检 | **每目标**:上次视差 + 连续异常计数 | §6.7 |
| 时间滤波器 | 距离低通 + 跳变重置 | **每目标**:上次滤波值、初始化标志、连续失效计数 | §6.5 |
| 目标状态容器 | 隔离键解析 + 帧末老化清理 | **每目标**:最近框中心、最近出现帧 | 隔离键见下;连续 `filter_reset_frames` 帧未出现则整体清理 |
| 告警节流器 | 异常日志限频 | 每类异常:首见标记 + 累计计数 | 第 1 次 + 每满 100 次 |
**目标隔离键(v1.0 冻结)**:`track_id` 优先——左右目的 track_id 一致且
为正时,用 `(轨道, 类别, id)` 作键(v1.1 语义提前启用,上游追踪库已在
链路中);否则回退**框位置最近邻**(同类别、门限 `isolation_gate_px` 内、
本帧尚未被占用的最近状态,一一归属)。
重写/移植时最容易漏的是**每目标隔离**的一致性计数与滤波状态——按
"全局单份"实现会在多目标下互相污染。
---
## 5. 单周期处理流程(主流程伪代码)
```text
函数 单周期处理(左帧, 右帧, 参数, now_ms) -> 目标距离记录列表:
# ---- ① 输入违约检查 ----
若 左帧.帧标识 ≠ 右帧.帧标识:
告警节流("左右帧非同帧,拒收")
返回 空列表
# ---- ② 取点(每目每框一次,纯函数) ----
左点表 ← 对 左帧.框列表 逐框取点(同侧边缘 x) # §6.1
右点表 ← 对 右帧.框列表 逐框取点(同侧边缘 x)
丢弃 坐标非有限值 的框(不参与匹配,也不发布记录;告警节流)
# ---- ③ 左右匹配(接口注入,默认贪心) ----
配对表 ← 匹配器.匹配(左点表, 右点表, 参数.匹配) # §6.2
# ---- ④ 配对成功的目标:测距 + 方位源 + 有效性 + 滤波 ----
对 配对表 中每个 (左框, 右框, 代价):
D ← 视差选择(左框, 右框) # 同侧边缘;越窗且中心在域内→回退中心(§6.1)
(Z, R) ← 测距(D, 参数.几何) # §3.2
c_mid ← (左框.中心 + 右框.中心) / 2 # §6.6
域内 ← 有效性判定(D, Z, 代价, 参数.有效性) # §6.4 门①②
一致性 ← 一致性监控(目标键).推进(D) # §6.7
置信度 ← 置信度映射(代价, 一致性) # §6.4 映射
有效 ← 域内 且 一致性 正常
若 有效:
Z_out ← 滤波器(目标键).推进(Z, 参数.滤波) # §6.5
否则:
滤波器(目标键).记失效() # §6.5 失效策略
Z_out ← 无
发布 记录(帧标识, 类别, Z_out, R, D, c_mid, 左框,
置信度, 有效, 完整, 取样时刻 = now_ms)
# ---- ⑤ 单目退化(仅一目检出) ----
对 未匹配的左框:
发布 记录(仅方位 = 左框.中心, valid = false, 退化 = 单目)
对 未匹配的右框:
发布 记录(仅方位 = 右框.中心, valid = false, 退化 = 单目)
# ---- ⑥ 空输入 ----
若 两目框列表均为空:
发布 无目标记录(或空列表);不告警(正常空帧)
```
**失败路径语义**:
| 情形 | 行为 | 日志 |
|------|------|------|
| 左右帧标识不一致 | 拒收本帧,输出空 | WARN 节流 |
| 单目检测为空 | 另一目发布仅方位记录 | 不告警(正常退化) |
| 匹配全部失败 | 全部按仅方位发布 | 不告警 |
| 视差违例(`D ≤ 0` 或超界) | 该目标 `valid = false`,仍配对并发布 `D`/`c_mid` | WARN 节流 |
| 边缘视差越窗、中心回退 | 该目标用中心视差解算(框宽差可能混入,§6.1) | WARN 节流 |
| 框坐标非法(非有限值) | 丢弃该框,不参与匹配也不发布 | WARN 节流 |
| 两目均无检测 | 无目标记录 | 不告警 |
高频热路径(每帧执行的数学)不打日志;所有异常日志按节流规范
(第 1 次 + 每满 100 次,带累计计数)。
---
## 6. 各环节算法细节
### 6.1 视差取点:同侧边缘(v1.0 主方案)
同一物理目标在两目中的检测框宽并不严格相等(检测抖动、外观差异),
**框中心**视差会混入框宽差的一半,**同一侧边缘**视差可抵消框宽项:
| 取点方式 | 误差来源 | 结论 |
|----------|----------|------|
| 框中心 | 两目框宽差直接进入视差 | 作对照/回退 |
| **同侧边缘(v1.0)** | 边缘定位噪声 | **v1.0 主方案** |
| 多边缘 + 亚像素精化(灰度重心/抛物线拟合) | 实现复杂度 | v1.1 |
```text
取法: D = 左框.左上角x − 右框.左上角x (同取左侧边缘)
回退: 边缘视差越窗 且 中心视差在域内 → 回退框中心并告警节流
两者均越窗 → 保留边缘值(供诊断与违例告警),由 §6.4 门 ① 判无效
```
> **不做"左右两边缘各算一次取中值"(v1.0 冻结)**:两边缘视差的中值恒
> 等于二者均值,即 `(cL.x − cR.x)`——**框中心视差**,与本表"同侧边缘
> 抵消框宽差"的理由自相矛盾(早期原文笔误),故不实现;亚像素精化留
> v1.1(§8.3)。
### 6.2 左右匹配:硬约束 + 贪心代价
**硬约束**(任一不满足直接拒绝配对,不进代价排序):
- 类别一致;
- `|yL − yR| ≤ τ_y`(校正后 y 应对齐;这是校正质量的运行期体现);
- 框高相近:`|hL − hR| / max(hL, hR) ≤ τ_h`。
**视差域不是配对硬约束(v1.0 冻结)**:越界目标仍应配对、仍发布 `D` 与
`c_mid`(远场"方位闭环 + 定速接近"的输入基础),仅由 §6.4 门 ① 判
`valid = false`。若把域并入硬约束,越界目标会退化为无方位的失配记录,
与 §2.3/§5 失败路径表的语义冲突。
**代价与贪心**:
```text
cost = |Δy| / τ_y + |Δh| / (τ_h × max(hL, hR))
按 cost 升序逐一配对,cost < 1 才接受,一一配对(一个左框至多配一个右框)
```
- 本场景目标数极少(1~2 个),O(n²) 贪心足够(§10.3);
- 失败处理:任一目未匹配 → 该目标本帧无距离(仅方位发布),
不阻塞其他目标。
### 6.3 测距计算与违例处理
```text
Z = F × B / D (D ≤ 0:物理违例 → valid = false,告警节流)
R = sqrt(X² + Y² + Z²) (参考输出)
```
- `D ≤ 0` 在校正正确的正视差几何下不应出现;出现说明匹配错误或校正
残差过大,宁可无效不可给值;
- `D ≤ 0` 时**不出解算结果**(无 `Z`、无 `R`);超界(`0 < D < D_min`
或 `> D_max`)仍解算 `Z`/`R` 供诊断与告警,同样 `valid = false`;
- 边缘取点为像素级整数(取整/插值规则由实现自定,但**左右目必须一致**);
- 所有除法分母(`D`)在使用前校验为正。
### 6.4 有效性判定:三道门(缺一不可)
| 门 | 判据 | 拦截什么 |
|----|------|---------|
| ① 域内 | `D ∈ [D_min, D_max]`(含边界);距离域由 `Z = F·B/D` 派生 | 远场小视差病态 + 近场大视差盲区 |
| ② 误差预算 | `δZ(δD=1px) = Z²/(F·B) ≤ δZ_max` | 有效域边界处的精度下限 |
| ③ 一致性正常 | §6.7 监控未判异常 | 持续视差跳变(标定漂移/同步故障/匹配错误) |
```text
valid = 域内 且 误差预算内 且 匹配成功 且 一致性正常
```
匹配成功由第 ③ 步保证(只有配对目标才进入本节判定)。
**门 ① 以视差域为唯一真源(v1.0 冻结)**:配置只存
`disparity_min_px / disparity_max_px`,`Z_min / Z_max` 由 `Z = F·B/D`
派生为只读量——`D` 是直接观测量,`Z` 是导出量,用 `D` 判域可避免
"距离阈值反推视差阈值"的舍入不一致;两处冗余存储正是该不一致的根源
(原文 §9.2 占位值即不自洽:`D_min = 3px` ⇔ 19.2m ≠ 20m),故不再
"互推并校验自洽"。
**门 ② 的 δD 基准固定为 1px(⚠占位,v1.0 冻结)**:δD 的真实构成
(边缘定位噪声 + 校正残差 + 帧不同步 + 压缩伪影,§7.1)留待地面真值
拟合(§12.2),当前不做估计、不随目标状态变化。
**置信度映射(⚠占位,v1.0 冻结)**:基值 = `clamp(1 − 匹配代价, 0, 1)`;
连续跳变 ≥ N 帧(§6.7)时乘降级系数(⚠0.5);判 invalid(≥ M 帧)时置 0。
### 6.5 时间滤波与跳变重置(每目标独立)
```text
推进(Z_new):
若 未初始化: 状态 ← Z_new; 返回 Z_new
若 |Z_new − 上次| > 跳变门限:
状态 ← Z_new # 直接重置而非滤波,防止拖尾
否则:
状态 ← 上次 + α × (Z_new − 上次) # 一阶低通,α ∈ (0,1]
返回 状态
记失效(): # 无效帧与"目标本帧缺席"均记失效(§6.5 失效策略)
连续失效计数 +1
若 连续失效 ≥ filter_reset_frames: 清空滤波状态(下次有效帧重新初始化)
```
- **单帧毛刺由跳变重置处理,持续性异常由 §6.7 一致性监控处理**,
两者职责不同不得合并;
- `α = 1` 等效不滤波;滤波只在**有效帧**之间进行,无效帧不参与平滑;
- 清理门限 `filter_reset_frames` **独立配置**(不复用 §6.7 的 M,⚠占位
5 帧),防"陈旧状态平滑新测量";
- 参考斜距 `R` 与**滤波后**的 `Z_out` 同基准(`X/Y/Z ∝ Z`,按
`Z_out/Z_raw` 精确换基,保证 `R ≥ Z`,§2.2);
- 滤波引入的群延迟约 `1/α` 帧(⚠占位 α=0.3 → 约 3 帧 ≈ 0.1s),
接近阶段的距离滞后由消费侧 PID 与限幅吸收。
### 6.6 方位源:虚拟双目中心 `c_mid`
**问题**:双目模组两枚相机分列模组中线两侧(各偏 ±B/2),都不在机身
中轴上。校正后严格成立的只有 **y 对齐**(垂直方向不受两目差异影响);
水平方向上直接以某一目(如左目)的像素做方位控制,收敛后对准的是
**该相机的光轴**,相对模组中线存在恒定视差偏差:
```text
β_bias ≈ atan( (B/2) / Z )
```
| 距离 Z | 角度偏差 | 像素等效(F≈960px,⚠占位) |
|-------:|-------:|-------:|
| 3 m | 0.57° | ≈10 px |
| 10 m | 0.17° | ≈2.9 px |
远距离可忽略,**近场不可忽略**;偏差方向恒定、随距离减小。
**精确修正(零额外成本)**:校正后几何下,位于基线中点的**虚拟相机**
对任一物理点 P 的投影恰为该点在两目投影的**等权平均**:
```text
xL = cx + F·(X_C + B/2)/Z (左目光心在模组中线 −B/2 侧)
xR = cx + F·(X_C − B/2)/Z (右目光心在模组中线 +B/2 侧)
(xL + xR) / 2 = cx + F·X_C/Z (= 虚拟相机投影,逐点精确,无近似)
```
检测框的每条边缘都是物理点、逐点满足上式,因此:
```text
虚拟框 = 两目框逐边平均 ⇒ 虚拟框中心 c_mid = (cL + cR) / 2
c_mid.y = (cL.y + cR.y) / 2 (校正后两目 y 天然相等,取平均兼得降噪)
```
即**等权平均等价于把相机搬到模组中线**,方位控制对标的是虚拟中心相机,
与机体中轴的安装偏移(如有)属安装外参,按安装标定处理。
**方位源与视差取点是两个不同的取点,不得混用**:
| 用途 | 取点 | 原因 |
|------|------|------|
| 视差 D(测距) | **同侧边缘** | 抵消两目框宽差(§6.1) |
| 方位 c_mid(控制) | **框中心等权平均** | 瞄点语义 = 虚拟框中心;误用边缘点平均会把瞄点偏到目标边缘(约半个框宽) |
**单目退化**(仅一目检出,v1.0):退化为该目框中心,接受上表偏差;
v1.1 可用最近一次有效 Z 做定值修正 `Δx = F·(B/2)/Z` px。
### 6.7 内部一致性监控(替代原激光交叉校验)
机载激光移除后无外部距离基准,飞行中只能靠自身时序一致性监控数据
质量(**只能降级、不能纠偏**,绝对精度靠地面静态验证,§12.1):
```text
逐目标推进(D):
视差跳变 = |D − 上次 D|(或等效 Z 跳变量;门限 consistency_jump_px)
连续 N 帧跳变超门限 → confidence 降级(⚠×0.5)
连续 M 帧异常 → valid 置 false 并 WARN(节流)
任一正常帧 → 清零连续计数
```
- 匹配层面质量(|Δy| 残差、框高一致性、代价门限)已由 §6.2 硬约束
承担;本节只管**时序层面**;
- 跳变门限 `consistency_jump_px`(⚠占位 3px)、N / M(⚠ 3 / 5 帧)均
为占位,实测后整定(§9.3);
- **推进时机(v1.0 冻结)**:只在配对成功帧推进——仅方位帧没有 `D`
观测量,不推进 D 序列、也不清零;目标缺席/无效帧的**滤波失效**由
§6.5 记,两条状态机职责不混;
- 监控判 invalid 是"质量语义"而非"错误":输出仍正常发布(仅方位),
由消费侧按无距离策略接管。
---
## 7. 误差模型与有效距离域
### 7.1 误差模型
由 `D = F·B/Z` 微分得:
```text
δZ ≈ Z² · δD / (F·B) (绝对误差,随距离平方增长)
δZ / Z ≈ Z · δD / (F·B) (相对误差,随距离线性增长)
```
`δD` 的构成:检测框边缘定位噪声 + 校正残差(|Δy| 失配混入)+ 帧不同步
引入的运动虚假视差 + 有损压缩伪影(平台相关,抽象计入边缘噪声)。
基线与焦距误差(δB/B、δF/F)线性传递、量级小,出厂标定后可忽略。
**这是"双目只能作近场距离源"的定量依据**,也是第 8 章多数缺点的根源。
### 7.2 有效距离域判据
```text
valid 域 ⇔ D ∈ [D_min, D_max](⚠占位 3 ~ 57.6px)
且 δZ(δD = 1px) ≤ δZ_max(⚠占位 2m)
```
- 按占位焦距计算:宽角档(HFOV≈90°)有效域约 **≤15m**、窄角档
(HFOV≈60°)约 **≤20m**(**⚠占位,待厂商实焦距回填后重算**;
数值回填的权威位置在《双目深度估计思路》§5.3 误差表);
- 近界:`D_max`(或 `Z_min`)限定最近可测距离——目标过近时视差超上限、
框占满画面、边缘取点失效(§8 第 3 条);
- 敏感性:误差 ∝ 1/B。更换大基线机型误差按比例缩小、有效域等比扩大
——**换机型(P6)是扩大远场能力的唯一杠杆**。
### 7.3 远场空洞(如实声明)
双目有效域之外(预计 >15~20m,待焦距回填),系统**不存在任何机载
目标距离源**。补偿方式是消费侧的远场策略(方位闭环 + 定速接近,D4),
而非强行使用不可靠的远场估计。本模块的职责边界是:把"测不了"诚实
地表达为 `valid = false` + 持续发布方位。
---
## 8. 职责、边界与已知缺点
### 8.1 职责(一句话版)
> 对同帧左右检测框做立体几何解算:**有效域内给出目标前向距离,
> 全程给出虚拟中心方位,测不了时诚实输出无效**——供控制律做
> 近场距离闭环与远场方位闭环 + 定速接近。
边界(不做什么)见 §1.4;与避障深度模型的分工见《双目深度估计思路》§1.3。
### 8.2 已知缺点与局限(如实声明,不得因文档目的删减)
| # | 缺点 | 根因 | 影响 | 现行对策 / 接受理由 |
|---|------|------|------|---------------------|
| 1 | **误差随距离平方增长** | `δZ ∝ Z²`(§7.1) | 远距离距离值不可用 | 有效域判据硬性拦截(§6.4);域外交给定速接近 |
| 2 | **远场空洞** | 有效域 >15~20m 外无任何机载距离源 | 远场无法距离闭环 | 消费侧 D4 策略(方位闭环 + 定速接近);扩域唯一杠杆是换机型(P6) |
| 3 | **近场盲区** | 视差超 `D_max`、框占满画面、边缘取点失效 | 反制逼近的最后阶段恰是最需要距离时失效 | 消费侧判丢刹车/定速接近兜底;`Z_min` 如实设界 |
| 4 | **检测框是单点依赖** | 全部几何量从框导出 | 无检测即无距离也无方位;框抖动直接进入 δD | 检测置信度门槛在检测侧;追踪库 Coast 补帧兜底 |
| 5 | **框级精度上限** | 取点在框边缘/中心,非特征级匹配 | 精度天花板高于特征级方案 | 接受(几何换算换实时性,§10.1);v1.1 亚像素精化 |
| 6 | **小视差病态** | 远距 D → 1px,量化误差主导 | 远场 δD=1px 假设过于乐观 | 同上由有效域拦截 |
| 7 | **标定与校正依赖** | y 对齐、无畸变是解算前提 | 未标定则系统性偏差,甚至全盘不成立 | P2 出厂标定为 v1.0 首要前置;不达标则 v1.1 自标定提前 |
| 8 | **帧不同步敏感** | 非同瞬曝光 → 运动目标虚假视差 | 快速横移目标距离失真 | 同帧契约(§2.1)+ 13 章快速横移验证;同步形态待 P3 |
| 9 | **固定基线/焦距** | 单一几何配置 | 近盲远废的区间固定 | 参数化配置;换机型只改配置(红线 2) |
| 10 | **贪心匹配局限** | O(n²) 局部最优 | 目标多/邻近/遮挡时错配风险 | 目标数极少(1~2)可接受;匹配器接口注入保留替换空间 |
| 11 | **无飞行中绝对基准** | 激光移除后无外部真值(D2/D8) | 一致性监控只能降级、不能纠偏 | 绝对精度靠地面手持激光测距仪静态验证(§12.1) |
| 12 | **单目退化有瞄偏** | 单目光轴偏离模组中线(§6.6) | 仅方位记录时方位存在 0.5° 量级近场偏差 | v1.0 接受并如实标注退化;v1.1 定值修正 |
**阅读提示**:1/2/3/6/9 是几何固有,只能拦截或换硬件,不能修好;
4/5/8/10/12 是工程折中,有 v1.1/v2.0 改进路径;7/11 是流程前提,
靠标定与地面验证闭环。
### 8.3 缺点对策索引
| 路径 | 覆盖的缺点 |
|------|-----------|
| v1.1(算法) | 亚像素边缘(5)、真值拟合误差修正项(1/6)、track_id 辅助匹配(10)、单目定值修正(12)、自标定(7,视 P2 结论提前) |
| v2.0(远期) | 实例分割替代框(4/5)、端到端立体评估(5)、更大基线/长焦机型(1/2/3/6/9,P6) |
| 消费侧兜底 | 定速接近 + 判丢刹车 + exit 门限(2/3 的安全网) |
| 地面验证 | 7/8/11 的唯一闭环手段 |
---
## 9. 配置参数全量表
全部参数**配置外置、启动期一次加载并校验**:缺项、类型错误、非法取值
一律拒绝进入运行期(fail-fast,语义要求,不绑定具体配置格式)。
所有数值均为占位(⚠),整定后回填。
### 9.1 几何组(来自标定,P1/P2)
| 键 | 单位 | 占位值 | 作用 |
|----|------|-------|------|
| `baseline_m` | m | 0.06 | 基线 B;更换机型只改此项 |
| `fx_px` / `fy_px` | px | 960.0(⚠占位,待 P1) | 像素焦距(校正后 `fx = fy = F`) |
| `cx_px` / `cy_px` | px | 960.0 / 540.0(⚠占位,待 P2) | 主点 |
### 9.2 匹配组
| 键 | 单位 | 占位值 | 作用 |
|----|------|-------|------|
| `tau_y_px` | px | 2.0 | \|Δy\| 硬约束(同时是校正质量的运行期体现) |
| `tau_h_ratio` | — | 0.25 | 框高相对差硬约束 |
| `disparity_min_px` | px | 3.0 | 最小可测视差(远界);**域唯一真源**(§6.4) |
| `disparity_max_px` | px | 57.6 | 最大可测视差(近界);⚠占位:按 F=960/B=0.06 反推 ⇔ 1.0 m |
| `distance_min_m` / `distance_max_m` | m | **不再配置** | v1.0 冻结:距离域由 `Z = F·B/D` 从视差域派生为只读量(§6.4) |
### 9.3 有效性组
| 键 | 单位 | 占位值 | 作用 |
|----|------|-------|------|
| `max_delta_z_m` | m | 2.0 | 误差预算 `δZ(δD=1px)` 上限(δD 基准固定 1px,§6.4) |
| `consistency_N_frames` | 帧 | 3 | 连续跳变降置信度的帧数 |
| `consistency_M_frames` | 帧 | 5 | 连续异常判 invalid 的帧数 |
| `consistency_jump_px` | px | 3.0 | 单帧视差跳变门限(§6.7);**v1.0 补充项**(原文缺项) |
### 9.4 滤波组
| 键 | 单位 | 占位值 | 作用 |
|----|------|-------|------|
| `smooth_alpha` | — | 0.3 | 一阶低通系数(§6.5 定义,1 = 不滤波) |
| `jump_reset_m` | m | 5.0 | 单帧跳变直接重置的门限 |
| `filter_reset_frames` | 帧 | 5(⚠独立配置,不复用 M) | 连续失效多久后清空滤波状态(§6.5) |
### 9.5 目标隔离组
| 键 | 单位 | 占位值 | 作用 |
|----|------|-------|------|
| `isolation_gate_px` | px | 50.0 | 最近邻兜底的匹配门限(§4);**v1.0 补充项**(原文缺项) |
---
## 10. 设计取舍记录(为什么不是别的做法)
### 10.1 两次目标检测代替稠密像素匹配
双目深度最难的是逐像素匹配:稠密立体匹配(SGBM 类)在该分辨率与
嵌入式 CPU 预算下不可行,而系统需求只是**少量目标的距离**。用左右
各一次轻量检测 + 框级几何换算绕开逐像素匹配,以"检测框天然给出 ROI"
换"精度天花板"(§8 第 5 条)。检测算力实测单核 20~30ms,NPU 预算
成立(平台侧见《双目深度估计思路》第 9 章)。
### 10.2 不先上端到端深度网络
需采集标注数据集、可解释性差、误差行为不可解析;先以几何法建立
**可验证的真值基线**,端到端立体/深度网络留 v2.0 评估。
### 10.3 贪心匹配而非匈牙利
目标数 1~2 个,贪心与全局最优几乎必然同解;O(n²) 足够。匹配器做
**接口注入**,保留替换为匈牙利/带连续性先验算法的空间而不动调用方。
### 10.4 同侧边缘而非框中心取视差
框宽差直接污染中心视差;同侧边缘可抵消框宽项(§6.1,原稿缺陷 2 的修正)。
### 10.5 距离通道用 Z 不用 R
与机头前向期望射程语义对齐,也与地面真值仪测量方向一致(决策 D8);
R 仅作参考输出。
### 10.6 方位源取两目框中心等权平均(虚拟中心像素)
两目均偏于模组中线 ±B/2,单目存在近场视差偏差(3m 处约 0.57°);
等权平均是投影几何**精确解**(§6.6,原稿"offset 加权"构想的正确形式,
决策 D5)。注意与视差取点(同侧边缘)分工不同、不可混用。
### 10.7 双目为机载唯一距离源、域外定速接近
替代激光(b96111e / D2);远场误差平方发散,强行估计不可靠——以
"诚实 invalid + 持续方位"支撑消费侧的方位闭环 + 定速接近(D4),
而不是在算法侧掩盖远场空洞。
---
## 11. 实现与重写指引
### 11.1 必须持久化的状态(漏一个就变行为)
| 状态 | 所属 | 初值 | 何时改变 |
|------|------|------|---------|
| 上次视差 + 连续异常计数 ×目标 | 一致性监控 | 无 / 0 | 配对帧写入上次视差;异常 +1 / 正常清零 |
| 上次滤波值 ×目标 | 时间滤波器 | 无(未初始化) | 每有效帧写入 |
| 滤波初始化标志 ×目标 | 时间滤波器 | false | 首个有效帧置 true;清空时回 false |
| 连续失效计数 ×目标 | 时间滤波器 | 0 | 每无效/缺席帧 +1 / 有效帧清零 |
| 最近框中心、最近出现帧 ×目标 | 目标状态容器 | 首帧写入 | 每次解析隔离键时刷新;连续 `filter_reset_frames` 帧未出现则整体清理 |
| 帧序号 | 流程编排 | 0 | 每帧 +1(被拒收的违约帧不加) |
| 告警节流状态 ×异常类 | 节流器 | 首见未打印 + 计数 0 | 每次异常更新 |
构造期预计算量:针孔系数与常量(如 `F·B`)一次算好,热路径只做乘除。
### 11.2 数值与精度注意
| 事项 | 处理方式 | 理由 |
|------|---------|------|
| 除零 | `D ≤ 0` 先判违例再除 | 正视差是物理前提(§6.3) |
| 视差取整 | 左右目规则必须一致 | 不一致会引入系统性 δD |
| 域判定基准 | 用 `D` 判域而非 `Z` | 直接观测量,避免往返舍入(§6.4) |
| 域配置单一来源 | 只配视差域,距离域派生 | 两处冗余存储是互推舍入不一致的根源(§6.4/§9.2) |
| 误差预算基准 | δD 固定 1px(⚠占位),不做在线估计 | 真实 δD 留待地面真值拟合(§12.2) |
| 浮点比较 | 阈值比较用 `≥/≤` 含边界语义 | 边界帧的归类必须确定 |
### 11.3 并发与生命周期
- 本模块是**纯计算单元**:驱动方式(独立线程 / 订阅回调 / 同步调用)
由平台层决定,本文只约定数据契约;
- 同一实例**不得并发调用**单周期处理(含滤波/一致性状态的无锁前提);
- 输出记录为**值拷贝**语义:多消费者各自持有快照,不得共享可变状态;
- 单周期处理应当无阻塞、无 IO(日志走节流通道,不落在数学热路径上)。
### 11.4 可测试性设计(构件边界即测试边界)
| 构件 | 是否纯函数 | 测试要点 |
|------|-----------|---------|
| 取点器 | 是 | 同侧边缘取值;框宽差不进入视差(构造两目等框不同宽断言 D 相同);越窗回退中心;边界含等号 |
| 匹配器 | 是 | 硬约束拦截各一例;贪心排序;一一配对;cost ≥ 1 拒绝 |
| 测距计算 | 是 | 已知 Z 反推 D 构造框对,断言 `Z = F·B/D` 回收;`D ≤ 0` 违例;`c_mid` 等权平均精确性(§6.6 恒等式);`R` 与发布 Z 同基准(`R ≥ Z`) |
| 有效性判定 | 是 | 三道门各一例;边界帧(恰在域界)归类确定;预算门通过/拦截两侧 |
| 时间滤波器 | 否 | 低通收敛;跳变重置不拖尾;失效清理 |
| 一致性监控 | 否 | N 帧降级、M 帧判 invalid、正常帧清零 |
| 目标隔离 | 否 | track_id 一致跨大位移保持状态;最近邻越门限新建;老化清理 |
| 全流程 | 否 | 合成帧对端到端:单目标/多目标/单目退化/非同帧拒收/记录顺序/非有限框/reset |
**无需真实图像**:全部测试用合成框对驱动,几何是解析可断言的。参考实现
的构件级用例已全部通过(§12.1)。
---
## 12. 验证路线与待定项
### 12.1 验证项
| 项 | 方法 | 通过标准 |
|----|------|----------|
| 构件级 | §11.4 合成框对单测 | 全部通过(无硬件依赖);Python 参考实现 `utils/stereo_ranger/` 用例已跑通 |
| 校正质量 | 静态场景统计匹配框 \|Δy\| 分布 | P95 ≤ 1px(⚠占位);不达标触发自标定提前 |
| 测距精度 | 5/10/15/20m 静态标靶,以**地面手持激光测距仪**为真值(非机载,D8),记录误差曲线 | 趋势与 §7 一致;有效域内 δZ ≤ 2m(⚠占位) |
| 帧同步 | 目标横向快速移动,观察视差时序抖动 | 无系统性虚假视差 |
| 控制联动 | 回放/SITL:距离闭环 ↔ 定速接近切换、invalid 持续降级路径 | 《视觉跟踪控制律技术路线》第 7 章场景全覆盖 |
| 日志纪律 | 检查异常路径日志 | 节流规范(第 1 次 + 每 100 次,带累计计数) |
### 12.2 待定项
开放问题(P1 焦距规格、P2 出厂标定、P3 帧同步形态、P6 换机型、
P7 性能实测、P8 避障激光去留)以《双目深度估计思路》第 15 章为权威
清单,本文不另立编号;其中:
- **P1/P2 直接决定本文 §7 结论与 §9 几何组能否从占位变实值**;
- **v1.0 实现补充的占位量**:`consistency_jump_px`(3px)、
`isolation_gate_px`(50px)、置信度降级系数(0.5)、误差预算基准 δD
(固定 1px)——随 P1/P2 回填与实测一并整定(§9.3/§9.5);
- **P6 是扩大有效域的唯一杠杆**(§7.2);
- P8(避障单点激光去留)不影响本链路——目标测距职责已由本模块承担。
### 12.3 红线
1. **占位数值不得用于飞行决策**:§7/§9 中所有 ⚠ 数值未经厂商数据与
整定确认前,本模块输出仅限静态标靶/回放/台架验证;
2. **相机参数与阈值一律配置外置**,禁止写死(后续可能更换机型);
3. **域外/失配必须输出 `valid = false`**,不得强行估计距离(远场策略
的正确性建立在有效性不撒谎之上);
4. **标定与地面真值验证完成前不得接入实飞控制回路**(与消费侧控制律
红线一致,见《视觉跟踪控制律技术路线》§12.3)。