实现预定流程全链路: 任务状态机 + 编排器 + 地面站 + 真机/SITL入口

- utils/task_runner: 6态状态机(WAIT→ARM_TAKEOFF→GOTO(L2)→TRACK(L1)→APPROACH→RTL)
  + 编排器(快照采集/状态动作) + 双层日志(事件JSONL/遥测CSV) + 吊舱控制指令(0x07/0x0F/0x0E/0x08)
- pod_bridge: ground_link 地面坐标UDP注入(超龄判无效,无激光替代表4);
  set_heading_servo_enabled() 运行时L1/L2切换(切换即reset清积分防输出跳变);
  pod_locked 提为公共门控; config 新增 ground_inject 段
- virtual_pod 模拟吊舱(无电机语义) + verify_px4 增量④仅飞控验证 +
  pod_sitl_test L1 SITL全流程(飞行编排不塞进 run_bridge, 保持纯offboard闭环入口)
- 入口: task_runner_sitl(VirtualPod+虚拟目标, SITL端到端跑通约1m24s) /
  task_runner_real(真串口+UDP注入+吊舱控制)
- 地面站 ground_station: 坐标注入 + 状态可视化(Flask)
- S1标定回填(2026-10-09): beta_sign=+1 / alpha_sign=-1, 加标定回归测试守护
- 新增测试: task_runner x4 + ground_link/virtual_pod*/bridge/px4_gateway 增量; 全量 483 passed
- 文档: 预定流程(需求) + 预定流程-操作指南(操作/待办) + L1方案补S1结论与实现状态
This commit is contained in:
keita
2026-10-13 15:50:32 +08:00
parent 5a944af4f5
commit ded17d7995
30 changed files with 3552 additions and 27 deletions
+163
View File
@@ -0,0 +1,163 @@
# 预定流程 · 操作指南与待办事项
> 更新日期:2026-10-12
> 覆盖:任务级状态机全链路(`utils/task_runner/`)+ 地面站页面 + 真机/仿真入口
>
> 本链路对应 `预定流程.md` 的「地面给坐标 → 天空解锁/接受坐标引导/追踪打击」,
> 已在 **PX4 SITL 端到端跑通**。架构与铁律见 `.workbuddy/memory/MEMORY.md` / `ARCHITECTURE.md`。
---
## 一、本次落地了什么
| 模块 | 文件 | 作用 |
|------|------|------|
| 任务状态机 | `utils/task_runner/state_machine.py` | 6 状态纯逻辑转移:WAIT→ARM_TAKEOFF→GOTO(L2)→TRACK(L1)→APPROACH→RTL |
| 编排器 | `utils/task_runner/runner.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 接收地面站坐标(超龄判无效) |
| SITL 入口 | `task_runner_sitl.py` | 仿真全流程(VirtualPod + 虚拟目标) |
| 真机入口 | `task_runner_real.py` | 真串口吊舱 + UDP 注入 + 吊舱控制 |
| 地面站 | `ground_station/app.py` + `templates/index.html` | 坐标注入 + 状态可视化(Flask) |
控制律本体复用既有 `visual_track_control.TrackingControlLaw`(L1 角度直入)与
`pod_bridge.GuidanceLaw`(L2 地理引导),**运行时通过 `bridge.set_heading_servo_enabled()` 切换**。
---
## 二、操作指南
### 2.1 纯软测试(无硬件,最快验证)
```bash
cd "D:/ProgramData/code_drone-test/utils"
"C:/Users/yimiao/.workbuddy/binaries/python/envs/drone-test/Scripts/python.exe" -m pytest -q
# 预期:483 passed
```
> ⚠ conda `pytorch` 环境缺 pytest(见 §三 待办 P2-2),测试用隔离 venv `drone-test`。
### 2.2 SITL 仿真全流程(独立模式,内置虚拟目标自动注入坐标)
前置:WSL 里启动 PX4 SITL(监听 14540)。
```bash
# 1. WSL 内启动 PX4 SITL
cd ~/PX4-Autopilot && make px4_sitl jmavsim
# 2. Windows 侧跑全流程(内置虚拟目标 home 北30m/东15m)
cd "D:/ProgramData/code_drone-test"
"D:/program file/conda/envs/pytorch/python.exe" task_runner_sitl.py --conn udp://:14540
```
预期:`wait → arm_takeoff → goto → track → approach → rtl`,全程约 1m24s。
### 2.3 SITL 仿真(地面站联动模式,坐标由地面站 UDP 注入)
```bash
# 终端 A:无人机(--ground-station 表示坐标走 UDP 接收,不再内置自动注入)
"D:/program file/conda/envs/pytorch/python.exe" task_runner_sitl.py --conn udp://:14540 --ground-station
# 终端 B:地面站页面
"D:/program file/conda/envs/pytorch/python.exe" ground_station/app.py --udp-port 14555 --log-dir logs
# 浏览器打开 http://127.0.0.1:5000,输入坐标点「注入坐标」
```
⚠ 地面站需**持续**发坐标(每 0.5~1s 一次),否则 `ground_inject.timeout_ms`(默认 5s)
超龄后 GOTO 判「坐标失效」返航。页面上手动点一次只发一次,联调时建议用脚本循环注入。
### 2.4 真机联调(增量流程,标定前不得实飞)
按顺序逐级验证,每级过了再进下一级:
| 级 | 动作 | 命令 | 通过判据 |
|----|------|------|---------|
| ① 纯软单测 | 全量 pytest | `pytest -q` | 483 passed |
| ② 串口回环 | 吊舱自环 | 台架工具 | 收发一致 |
| ③ 仅吊舱 | 干跑(不发 offboard) | `python utils/pod_bridge/run_bridge.py --config utils/config/pod_bridge.json --port /dev/ttyAMA0 --dry-run` | β→yaw_rate 符号/量级正确 |
| ④ 仅飞控 | 飞控遥测/offboard | — | 遥测新鲜、offboard 可启停 |
| ⑤ 地面联调 | 真机全流程 | `python task_runner_real.py --target-type 1` | 完整走完 |
真机全流程前置:
1. 填 `utils/config/pod_bridge.json` 的 `pod_serial.port`(如 `/dev/ttyAMA0`)、`px4.connection_string`;
2. 地面站往 `ground_inject.port`(默认 14555)持续发 `{"lat":..,"lon":..,"alt":..}`。
真机关键命令参数:
```bash
python task_runner_real.py --target-type 1 # 1=无人机,0=人/车
python task_runner_real.py --port /dev/ttyAMA0 # 覆盖吊舱串口
python task_runner_real.py --conn serial:///dev/ttyS1:57600 # 覆盖飞控连接串
```
### 2.5 硬件铁律(真机必读,来自厂商确认 + 实测)
- 🔴 **本吊舱无激光 → 表4 目标经纬度永不出**,目标坐标必须走地面注入(`ground_link`),
`guidance` 吃注入坐标而非表4。
- **0x0F「发现目标自动锁定」是常驻模式**,`0x0E` 只停当前这次跟踪、不退出自动锁定;
只有 `0x08 目标识别关` 才真正退出识别。
- **bit2 锁定位在目标丢失后不复位**,且脱靶量无无效标志位(丢失表现为 0)——单靠 bit2
会朝过期坐标继续飞,必须加第二判据(我方视觉,`require_vision`)。
- **自动解锁(`--auto-unlock`)在本设备禁用**(表4 恒不发导致误解锁),解锁一律用按键 `u`。
---
## 三、待办事项(按优先级)
### P0(实飞前必须)
- [ ] **真机增量验证**:按 §2.4 的 ②~⑤ 逐级跑,尤其 ③ 干跑确认 β→yaw_rate 符号/量级。
- [ ] **状态机参数标定**:`task_runner_real.py` 里 `build_sm_config()` 的
`switch_radius_m`(GOTO→TRACK 切换半径)、`center_threshold_deg`(居中阈值)、
`center_hold_s`、`takeoff_altitude_m` 全是占位值,须台架标定后回填。
- [ ] **L1/L2 增益标定**:`pod_bridge.json` 里 `heading.gain`、`guidance.speed_kp/yaw_kp`
等仍为占位,`beta_sign`/`alpha_sign` 已按 S1 标定(+1/-1),其余待标定。
### P1(落地后尽快)
- [ ] **摄像头可视化接真视频流**:当前地面站是「脱靶量模拟视野」,真机需接吊舱视频流
(吊舱视频输出 → 采集 → 页面叠加追踪框)。
- [ ] **任务级状态机配置 JSON 化**:`TaskStateConfig` 目前是 dataclass 默认值 + 脚本内构造,
应外置到配置(铁律「配置全外置」)。
- [ ] **地面站与 runner 状态实时打通**:当前地面站读日志文件(秒级延迟),可改为 runner
直接 UDP 上报遥测到地面站(低延迟)。
### P2(工程收尾)
- [ ] **仓库补 `.gitignore`**:`logs/`、`__pycache__/`、`.codegraph/`、`models/*.pt`、
`stereo_calib_params.npz` 等长期未跟踪项,提交时显式列路径、勿 `git add .`。
- [ ] **conda `pytorch` 回填 pytest**:README 声明有 pytest 但实测缺失,测试目前走
隔离 venv `drone-test`;回填后使 README 与实际一致。
- [ ] **C++ 侧构建验证**:`reference-c++/target_tracker` 与 `visual_track_control` 无
`build/`,若以 C++ 为验收基准需 `cmake .. && make && ctest` 跑 11 个测试。
---
## 四、关键配置速查(`utils/config/pod_bridge.json`)
| 段 | 关键字段 | 说明 |
|----|---------|------|
| `pod_serial` | `port` | 吊舱串口设备号(真机填 `/dev/ttyAMA0`) |
| `px4` | `connection_string` | 飞控连接串(SITL `udp://:14540`,真机串口) |
| `link` | `require_laser_valid` | 无激光吊舱必须 `false` |
| `heading_servo` | `enabled` / `beta_sign` / `alpha_sign` | L1 开关 + 符号(±1,已标定 +1/-1) |
| `ground_inject` | `enabled` / `port` / `timeout_ms` | 地面坐标注入开关 / UDP 端口 / 超龄门限 |
---
## 五、一键命令汇总
```bash
# 测试
cd utils && "C:/Users/yimiao/.workbuddy/binaries/python/envs/drone-test/Scripts/python.exe" -m pytest -q
# SITL 独立全流程
"D:/program file/conda/envs/pytorch/python.exe" task_runner_sitl.py --conn udp://:14540
# SITL 地面站联动
"D:/program file/conda/envs/pytorch/python.exe" task_runner_sitl.py --conn udp://:14540 --ground-station
"D:/program file/conda/envs/pytorch/python.exe" ground_station/app.py --udp-port 14555 --log-dir logs
# 真机全流程(填好配置后)
"D:/program file/conda/envs/pytorch/python.exe" task_runner_real.py --target-type 1
```