Files
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

74 lines
2.9 KiB
Python
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.
"""视差取点器(§6.1):同侧(左)边缘为主方案,边缘视差越窗时回退框中心。
纯函数、无状态(§4 构件表)。为什么用同侧边缘:同一物理目标在两目中的
检测框宽并不严格相等,框中心视差会混入框宽差的一半,同侧边缘视差可抵消
框宽项。
注:§6.1 的"左右两边缘各算一次视差取中值"精化在数学上恒等于框中心视差
(两支的 median = 均值),与"中心视差混入框宽差"的理由矛盾,属原文笔误,
v1.0 不实现;规格 §6.1 已删除该项并注明(见包 README「实现决策」)。
"""
import math
from dataclasses import dataclass
from .config import StereoConfig
from .types import Detection, DisparitySource
@dataclass(frozen=True)
class SamplePoint:
"""单目单框取点结果:同侧边缘候选与框中心(§6.1/§6.6)。
finite=False 表示坐标非有限值:该框不可参与解算,由调用方丢弃并告警。
"""
box: Detection
edge_x: float # 同侧(左)边缘 x = box.x1
center_x: float
center_y: float
finite: bool
@dataclass(frozen=True)
class Disparity:
"""配对后的视差取点结果。"""
d_px: float
source: DisparitySource
fallback_used: bool # 边缘视差越窗、回退中心(需告警节流,§6.1)
in_domain: bool # d ∈ [D_min, D_max](含边界,§11.2)
positive: bool # d > 0(正视差是物理前提,§6.3)
def sample_point(detection: Detection) -> SamplePoint:
"""逐框取点(§5 第 ② 步,每目每框一次)。"""
finite = all(math.isfinite(value) for value in (detection.x1, detection.y1, detection.x2, detection.y2))
return SamplePoint(
box=detection,
edge_x=detection.x1,
center_x=detection.cx,
center_y=detection.cy,
finite=finite,
)
def select_disparity(left: SamplePoint, right: SamplePoint, config: StereoConfig) -> Disparity:
"""在同侧边缘视差与框中心视差之间选择(§6.1 主取点 + 越窗回退)。
规则:边缘视差在域内取边缘;否则若中心视差在域内则回退中心(告警节流);
两者均越窗时保留边缘值(供诊断与违例告警),由有效性门判无效。
"""
d_edge = left.edge_x - right.edge_x
if _in_domain(d_edge, config):
return Disparity(d_edge, DisparitySource.LEFT_EDGE, False, True, d_edge > 0.0)
d_center = left.center_x - right.center_x
if _in_domain(d_center, config):
return Disparity(d_center, DisparitySource.CENTER_FALLBACK, True, True, d_center > 0.0)
d = d_edge if math.isfinite(d_edge) else d_center
return Disparity(d, DisparitySource.LEFT_EDGE, False, False, d > 0.0)
def _in_domain(d_px: float, config: StereoConfig) -> bool:
return config.disparity_min_px <= d_px <= config.disparity_max_px