归档 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。
19 KiB
工作进度
更新日期:2026-10-21 项目:无人机视觉目标追踪与控制系统 (
reference-c++/C++ 参考实现 +utils/Python 移植与新实现)本文只记「做完了什么 / 卡在哪 / 下一步怎么走」。 架构全貌与必须遵守的铁律见
.workbuddy/memory/ARCHITECTURE.md; 「预定流程」全链路的操作指南与待办清单见预定流程-操作指南.md; 权威规格见docs/下各技术路线 md(代码注释用§章节号反向引用)。⚠ 架构口径(2026-10-19):光电吊舱已取代双目 + YOLO,成为唯一目标源; 双目三包已归档到
legacy/(见 §1.8),运行链路测试 446 条、归档测试 175 条。
1. 已完成工作
1.1 C++ → Python 移植(2 个模块)
| C++ 源工程 | Python 目标包 | 状态 |
|---|---|---|
reference-c++/target_tracker |
utils/target_trackerlegacy/utils/target_tracker |
✅ 完成(28 条用例,已归档) |
reference-c++/visual_track_control |
utils/visual_track_control |
✅ 完成(86 条,运行链路复用) |
- 逐构件对照移植:测试断言逐条搬运(
EXPECT_DOUBLE_EQ→ 精确==,EXPECT_NEAR→pytest.approx)。 visual_track_control与追踪器互不依赖,唯一转换点是胶水层 (胶水 demo 已归档到legacy/utils/demo_track_control.py)。- MAVLink 部分改为 MAVSDK 语义映射(offboard API,非字节透传), 三分支映射保留 C++ A2 回归语义。
- 行为修复项(C1/C2/C4、A1/A2/A4、S6)已在测试文件头注明对应章节。
1.2 双目链路实现(非移植,按规格新写)—— 📦 已归档
2026-10-20 起三包与配套测试/demo/配置/权重/规格全部移到
legacy/(默认不跑测试)。 原因:吊舱已成为唯一目标源,这套链路无生产调用方;保留是为了日后接回"独立旁证/距离源"。 详见legacy/README.md。
| Python 包 | 原位置 → 现位置 | 状态 |
|---|---|---|
stereo_ranger(稀疏目标测距) |
utils/ → legacy/utils/ |
✅ 完成(111 条,随包归档) |
stereo_yolo(双目 YOLO 检测前端) |
utils/ → legacy/utils/ |
✅ 完成(36 条,随包归档) |
target_tracker(多目标追踪) |
utils/ → legacy/utils/ |
✅ 完成(28 条,随包归档) |
stereo_ranger按规格五步流程实现,纯标准库,无第三方依赖; 越界即有效性门、视差域权威,偏差项已在其包 README 记录。stereo_yolo推理口径为 ultralytics 直跑.pt,letterbox/解码/NMS/坐标回映均在库内完成; 输出直接作为stereo_ranger的输入(仅复用其types.py纯值类型)。
1.3 吊舱 ↔ PX4 桥接与 L1 航向伺服(utils/pod_bridge)
- 协议桥接(09-22 起):
protocol(表2/表3 解析)、px4_gateway(offboard 速度闭环)、pod_serial、guidance(L2 地理引导)、run_bridge.py --dry-run干跑入口。 - L1 航向伺服(10-09 落地,路线 A1):吊舱角度直入——β/α 直接吃吊舱角度
(配置双路
beta_from_frame/beta_from_off_target;本版未装电机,恒用脱靶量路径), 复用TrackingControlLaw的无距离降级路径;bridge.set_heading_servo_enabled()支持运行时 L1/L2 切换(切换即 reset 清积分,防输出跳变)。 - 硬件结论(厂商答复 + 实测):本吊舱不允许二次开发;无激光 → 表4 永不出,
目标坐标改走地面注入;
0x0F自动锁定是常驻模式(0x0E只停当次,0x08才退出识别); bit2 锁定位目标丢失后不复位 → 第二判据已改为 LOS 运动学一致性 (pod_bridge/los_consistency.py,2026-10-19 取代旧「我方视觉」方案)。 - S1 台架标定已完成(10-09):
beta_sign=+1、alpha_sign=-1已回填pod_bridge.json,并有标定回归测试守护(test_deployed_config_has_calibrated_signs)。 - 配套工具:
virtual_pod(模拟吊舱,无电机语义)、verify_px4(仅飞控验证,增量④)、pod_sitl_test.py(L1 SITL 全流程)。
1.4 预定流程全链路(utils/task_runner,10-12 落地;10-15 状态链重构;10-19 自定义返航 + LOS 判据)
「地面给坐标 → 天空飞向参考点 → 搜索 → 缓慢靠近 → 自定义返航」全链路, 已在 PX4 SITL 端到端跑通,并完成真吊舱(COM5)+ SITL 硬件在环验证:
状态链(10-15 重构后):WAIT → ARM_TAKEOFF → GOTO(L2) → SEARCH(原地扫视) → TRACK(L1 缓慢靠近) → RTL
| 模块 | 文件 | 作用 |
|---|---|---|
| 任务状态机 | utils/task_runner/state_machine.py |
状态纯逻辑转移;参考点=搜索起点,搜索超时/追踪超时→RTL |
| 编排器 | utils/task_runner/runner.py |
状态机驱动 + 快照采集 + 状态动作(起飞/扫视/切律/返航)+ 异常兜底返航 |
| 返航控制 | utils/task_runner/return_home.py |
自定义返航:回起飞点 → 恢复初始航向 → 垂直降落(不爬高) |
| 日志模块 | utils/task_runner/log.py |
事件 JSONL + 遥测 CSV 双层结构化日志 |
| 吊舱控制 | utils/task_runner/pod_control.py |
真机吊舱识别/锁定指令(0x07/0x0F/0x0E/0x08,只下发一次) |
| 地面注入 | utils/pod_bridge/ground_link.py |
UDP 接收地面站坐标(超龄判无效,替代表4) |
| 目标有效性 | utils/pod_bridge/los_consistency.py |
LOS 运动学一致性第二判据(10-19 取代 require_vision) |
| SITL 入口 | task_runner_sitl.py |
仿真全流程(VirtualPod + 虚拟目标) |
| 真机入口 | task_runner_real.py |
真串口吊舱 + UDP 注入 + 吊舱控制 |
| 地面站 | ground_station/ |
坐标注入 + 状态可视化(Flask) |
「缓慢靠近」由既有 TrackingControlLaw 的无距离降级通道实现:distance.no_distance_action = slow_approach + no_distance_approach_limit_mps=0.2(SITL 实测 vx_body 稳定 0.2 m/s),
不需要新写控制律。
自定义返航(10-19 新增):RTL 不再交给 PX4 原生 return_to_launch()(会先爬到
RTL_RETURN_ALT=30m 再降),改为 utils/task_runner/return_home.py 驱动:
RETURN(保持转场高度飞回起飞点)→ YAW(原地转回起飞时刻航向)→ LAND(垂直降落)。
SITL 实测:全程 4.91–5.06 m,距起飞点 16.1→1.6 m,航向恢复到 4° 内,高度 5.01→-0.03 m。
兜底(未起飞/无起飞点/转场超时/主循环异常)仍退回 PX4 原生 RTL;--land 就地降落。
目标有效性第二判据(10-19 换成 LOS 一致性):吊舱取代双目后"我方视觉"不存在,
旧 require_vision 已删除(要么恒假、要么自证)。改为 pod_bridge/los_consistency.py:
本吊舱无电机、相机刚性固连 → 机头转 Δψ 时真实目标脱靶量必变 ≈−Δψ;以 Δβ+Δψ
(3s 窗口 / 20° 激励 / 8° 残差)判"角度是活的还是冻住的",超限即 tracked=False
且 pod_locked() False(状态机随之退出 TRACK 重搜)。
⚠ 局限:只证"角度活着",不证"是那个目标";锁错物体但角度正常变化无法识别。
1.5 测试
运行链路 446 条全部通过(实测,2026-10-20;归档包另 175 条):
| 测试组 | 用例数 | 覆盖内容 |
|---|---|---|
tests/visual_track_control |
86 | 对应 C++ gtest + L1 角度直入增量 |
tests/pod_bridge |
208 | 协议/网关/桥接/L1 + virtual_pod/ground_link + 节流 + LOS 一致性 |
tests/task_runner |
122 | 状态机(含 SEARCH)/编排器/日志/吊舱控制/自定义返航 |
tests/ground_station |
30 | 地面站页面与日志解读 |
| 运行链路合计 | 446 | 默认 cd utils && pytest 只跑这些 |
(归档)legacy/utils/tests/{stereo_ranger,stereo_yolo,target_tracker} |
175 | 见 legacy/README.md,默认不跑 |
架构口径(2026-10-19 / 10-20):双目 + YOLO 三包已归档到
legacy/; 运行链路(task_runner_*/pod_bridge)不依赖它们 —— 吊舱是唯一目标源。 目标有效性第二判据为 LOS 运动学一致性(pod_bridge/los_consistency.py),require_vision已删除。
- 归档的双目测试不需要真实图像、模型权重或硬件。
- ⚠ codegraph 报告
AssociateDetections/SelectPrimary等“无测试”属调用图误报,勿据此判断。
1.6 仿真 / 运行入口
| 脚本 | 内容 | 结果 |
|---|---|---|
task_runner_sitl.py(PX4 SITL) |
全链路 goto→search→track→rtl + 自定义返航 |
✅ 端到端跑通(10-19 复跑) |
task_runner_real.py(真吊舱 COM5 + SITL 飞控) |
同上,真串口吊舱在环 | ✅ 无目标安全路径 + 强制锁定 TRACK 路径(10-19) |
l1_sitl_test.py(PX4 SITL) |
只覆盖 L1 控制律闭环(原 pod_sitl_test.py) |
✅ SITL 实跑 |
(归档)legacy/utils/demo_*.py |
双目/追踪演示 | 📦 移入 legacy,默认不跑 |
- 共享件
now_ms/wait_until_ready/TelemetryHub等已从"测试脚本"拆到utils/sitl_support.py,两个入口不再 import 测试文件。 - 吊舱硬件在环实测(10-19,COM5/CH340):表2-2 60.0 Hz、
self_check=0x00; 表3 20Hz 下发不打断上行;表2-1 指令帧校验和与协议样例一致。 无目标时status1=0x00恒定(bit2=0)→ 全链路走"搜索 20s 超时→返航"安全路径。 ⚠ 仍未验证:吊舱真实目标识别(bit2 0→1),需视场内放目标。
1.7 文档与索引
docs/现有 7 份(3 份双目规格已归档到legacy/docs/):视觉跟踪控制律技术路线、 视觉追踪技术路线、物理追踪思路、吊舱解算验证方案(模拟飞控喂表3)、树莓派 4B 部署注意事项、 L1 航向伺服实现方案、光电吊舱控制协议 G 版-PB(docx)。- 根目录:
预定流程.md(需求)+预定流程-操作指南.md(操作指南与待办,链路权威)+README.md(总览)。 legacy/README.md(归档说明)、tools/README.md(临时脚本说明)。.workbuddy/memory/ARCHITECTURE.md+MEMORY.md:完整架构参考与精简铁律(已对齐新架构)。.codegraph/已于 10-20 重建(旧索引过期,清理后重新索引)。- 相机标定脚本已移到
tools/;标定结果归档在legacy/stereo_calib_params.npz。
1.8 仓库结构精简(2026-10-20 完成,2026-10-21 提交)
动机:子项目堆积了大量文件,其中双目/YOLO 一套在"吊舱取代双目"后已无生产调用方, 旧架构脚本与生成物也混在根目录,影响阅读与使用。
做了什么:
| 处理 | 内容 |
|---|---|
归档 legacy/ |
stereo_yolo / stereo_ranger / target_tracker 三包 + 175 条测试 + 3 个 demo + stereo_*.json + 素材 + models/yolo26n-drone.pt + 三份双目规格 + stereo_calib_params.npz |
| 删除 | test.py(旧架构双目闭环,未实跑)、trajectory_plot.png、新建 文本文档.txt、空目录、全部 __pycache__ / .pytest_cache |
移入 tools/ |
camera.py / camera_test.py / video_test.py(台架相机脚本) |
| 拆分改名 | pod_sitl_test.py → utils/sitl_support.py(入口共享件)+ l1_sitl_test.py(L1 测试);两个入口不再 import 测试文件 |
| 从索引剔除 | 59 个历史误跟踪的 .pyc(已被 .gitignore 覆盖) |
新增 .gitignore |
__pycache__/、.pytest_cache/、logs/、.codegraph/、.workbuddy/、.idea/、legacy/models/*.pt 等 |
| 依赖清单 | requirements.txt 按实际 import 重写(去 ultralytics/matplotlib,补 flask);requirements-pod.txt 更新条数 |
| 文档 | 所有现行文档同步新路径/新计数(README、操作指南、ARCHITECTURE、MEMORY、utils/README、L1 方案、树莓派部署);新增 legacy/README.md、tools/README.md |
| codegraph | 删除过期索引并重建(143 文件 / 2667 节点 / 6470 边) |
结果:
- 根目录从 18 个文件减到 10 个(3 个入口/测试脚本 + 4 份 md + 2 份 requirements +
.gitignore) utils/从 6 个包 + 3 个 demo 减到 4 个包 +sitl_support.py(体积 3.39MB → 1.78MB)- 测试口径:运行链路 446 passed;归档 175 passed(
cd legacy/utils && PYTHONPATH="../../utils" pytest) - 运行链路代码对已归档包的引用:0 处
2. 未完成工作
2.1 真机增量验证(P0,实飞前必须)
按 预定流程-操作指南.md §2.4 逐级进行,每级过了再进下一级:
② 串口回环 → ③ 仅吊舱干跑(验 β→yaw_rate 符号/量级)→ ④ 仅飞控(verify_px4)→
⑤ 地面联调(task_runner_real.py)。
2.2 数值参数未标定(阻塞飞行决策)
- 状态机(
build_sm_config()):arrival_radius_m/goto_timeout_s/search_timeout_s/track_timeout_s/sweep_rate_dps/sweep_reverse_s/takeoff_altitude_m均为占位。 - 返航(
build_return_config()):speed_mps/arrival_radius_m/yaw_align_tolerance_deg/alt_kp及各类超时均为占位。 - 控制律:
heading.gain、guidance.speed_kp/yaw_kp为占位 (beta_sign/alpha_sign已按 S1 标定回填;LOS 判据阈值los_min_yaw_change_deg/los_max_residual_deg亦待台架实测调整)。 - 标定回填前不得实飞。
- (归档)
legacy/utils/config/stereo_ranger.json几何参数为占位;若日后接回双目, 解禁路径见legacy/docs/双目相机模组到位作业指导.mdP0→P6(标定未走完)。
2.3 任务级状态机规格对齐
- 「预定流程」版状态机已实现并 SITL + 真吊舱在环跑通(
WAIT→ARM_TAKEOFF→GOTO→SEARCH→ TRACK→RTL,2026-10-19 口径); - 但
docs/物理追踪思路.md引用的 S5~S8 版规格(docs/状态机设计.md等)仍缺失, 两套状态集是否对齐/合并需总项目侧确认(见 §3.1)。
3. 阻塞项与风险
3.1 本仓库缺失 4 份被引用的上游规格
docs/物理追踪思路.md 引用了下列文档,但它们在本仓库不存在(应在总项目或飞控工程侧):
| 被引文档 | 被引内容 | 影响 |
|---|---|---|
docs/状态机设计.md |
S6/S7/S8 切换守卫、§4.2 目标丢失转移、§7 策略接口 | S5~S8 版状态机与「预定流程」版对齐 |
docs/感知与避障设计.md |
标定流程、稳定锁定、雷达关联、降级原则 | 阻塞 S8 障碍接管与雷达联动 |
docs/系统架构设计.md |
数据流、控制单出口、时间与控制周期 | 影响状态机与控制律的接线方式 |
docs/需求分析.md |
FR-034/FR-044/FR-051、NFR-007 | 需求追溯无法本地闭环 |
另 docs/开发进度.md(总项目开发进度)亦被引用,本仓库没有。
3.2 C++ 侧未复跑
reference-c++/target_tracker 与 visual_track_control 下均无 build/ 目录,
未构建、未执行 ctest。C++ 测试用例文件齐全(11 个),
需先 cmake .. && make && ctest。若以 Python 侧为验证基准,此点可暂不处理。
3.3 环境口径(已统一,曾不一致)
现行唯一口径:conda env pytorch(D:\program file\conda\envs\pytorch\python.exe),
pytest 9.1.1 可用,全量 621 passed 直接跑。
历史:曾一度认为该环境缺 pytest、改走隔离 venv
drone-test。该结论已过时, 隔离 venv 不再需要;文中若见旧 venv 路径一律以 condapytorch为准。
3.4 真机安全红线
标定回填前不得实飞;S3 起必须:不装桨 / 空旷场地 / RC 随时可切手动 / 有人值守。
3.5 帧周期算力不可外推(归档项)
stereo_yolo 实测帧周期 25~35 ms 为台架开发机数据,与 30 fps 预算同量级,
结论不可外推到机载平台(这也是当前不接双目、距离优先用雷达的原因之一)。
该包已归档到 legacy/。
4. 下一步(建议顺序)
- 接距离源(激光雷达):给
PodBridge加距离注入点 → 填distance_valid→ 打开d_exp_m距离 PID,并把 TRACK 的"到点"判据从纯超时改为距离判据。 (低算力、收益最大;双目暂不接。) - 真机目标识别验证:视场内放目标(人/无人机)+ 0x07,确认 bit2 0→1 与 TRACK 真实闭环;顺带复核 LOS 判据阈值是否合适。
- 占位参数标定回填:状态机 6 项 + 返航 6 项 + L1/L2 增益 + LOS 两阈值。
- P1:摄像头接真视频流;
TaskStateConfig/ReturnConfig外置 JSON;地面站与 runner 实时打通。 - P2:C++
cmake && ctest;codegraph 定期sync(本次已重建)。 - 相机模组到位后按作业指导走 P0→P6(脚本在
tools/,文档在legacy/docs/); 确认 §3.1 四份上游规格可获取位置。
5. 验证命令(实测所用)
PY="D:/program file/conda/envs/pytorch/python.exe"
# 运行链路测试(446 条)
cd "D:/ProgramData/code_drone-test/utils"
"$PY" -m pytest -q
# 归档的可选后端测试(175 条,按需)
cd "D:/ProgramData/code_drone-test/legacy/utils"
PYTHONPATH="../../utils" "$PY" -m pytest -q
# 吊舱台架 / SITL 全流程 / 地面站 / 真机:见 预定流程-操作指南.md §五「一键命令汇总」
6. 一页状态汇总
| 工作项 | 状态 | 备注 |
|---|---|---|
C++ target_tracker → Python |
✅ 完成 | 28 条用例;已归档 legacy/ |
C++ visual_track_control → Python |
✅ 完成 | 86 条(含 L1 增量);运行链路复用 |
stereo_ranger 双目测距 |
📦 归档(10-20) | 111 条随包;几何参数待标定 |
stereo_yolo 检测前端 |
📦 归档(10-20) | 36 条随包;真实素材待联调 |
| 三路 demo 仿真验证 | 📦 归档(10-20) | 移入 legacy/utils/ |
pod_bridge 桥接 + L1 航向伺服 |
✅ 完成(10-09) | S1 符号已标定;增益待标 |
| 预定流程全链路(task_runner) | ✅ SITL 跑通(10-12);10-15 重构;10-19 真吊舱在环 | 状态链含 SEARCH + 自定义返航 |
| LOS 运动学一致性判据 | ✅ 完成(10-19) | 取代 require_vision;阈值待台架调整 |
| 自定义返航(回点+复位航向+垂直降落) | ✅ SITL 验证(10-19) | 全程 4.91~5.06 m,不爬高 |
| 真机增量验证 ①②③③b | ✅ 已过 | 串口链路/干跑/真吊舱+SITL 全流程 |
| 真机增量验证 ④⑤(仅飞控 / 实飞地面联调) | ❌ 未开始 | P0;实飞前必须 |
| 吊舱真实目标识别(bit2 0→1) | ❌ 未验证 | 需视场内放目标 |
| 距离源接入(激光雷达) | ❌ 未开始 | 打开距离 PID 与到点判据 |
| 状态机/返航/L1/L2 占位参数标定 | ❌ 未开始 | 回填前不得实飞 |
| S5~S8 版状态机(物理追踪思路) | ⚠ 规格缺失 | 待对齐(§3.1) |
| 相机模组标定 P0~P6 | 📦 归档 | 脚本移到 tools/,标定数据在 legacy/ |
| C++ 侧构建与 ctest | ⚠ 未执行 | 无 build 目录 |
| ✅ 已解决 | 运行链路测试统一走 conda pytorch(446 条) |