精简仓库结构并增强任务链路:归档双目可选后端、新增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。
This commit is contained in:
+42
-15
@@ -1,19 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
"""task_runner_sitl.py —— 任务级状态机 SITL 全流程集成测试(预定流程.md 天空侧)。
|
||||
|
||||
用状态机驱动完整流程:WAIT → ARM_TAKEOFF → GOTO(L2 坐标引导) → TRACK(L1 航向伺服)
|
||||
→ APPROACH(悬停) → RTL(返航落地)。相比 pod_sitl_test.py(固定场景、人工编排),
|
||||
本脚本把「飞行编排 + 控制律切换」交给 TaskRunner 状态机统一驱动。
|
||||
用状态机驱动完整流程:
|
||||
WAIT → ARM_TAKEOFF → GOTO(L2 飞向参考点) → SEARCH(原地扫视) → TRACK(L1 缓慢靠近)
|
||||
→ RTL(自定义返航:回起飞点 → 恢复初始航向 → 垂直降落)
|
||||
|
||||
相比 `l1_sitl_test.py`(只跑 L1 控制律闭环、人工编排),本脚本把「飞行编排 + 控制律切换」
|
||||
交给 TaskRunner 状态机统一驱动;返航也不再走 PX4 原生 RTL(那会先爬到
|
||||
RTL_RETURN_ALT 再降),而是自定义的低空返航(见 task_runner/return_home.py)。
|
||||
|
||||
场景:
|
||||
* 起飞前注入虚拟目标坐标(模拟地面站给坐标)——目标 = home 北 30m / 东 15m;
|
||||
* VirtualPod 按无电机语义合成表2-2(框架角恒0、无激光、锁定=目标在视场内);
|
||||
* 后台任务持续刷新注入坐标(模拟地面站持续上报),坐标始终新鲜;
|
||||
* GOTO→TRACK 由状态机按「距目标 < switch_radius 且吊舱锁定」守卫切换。
|
||||
* GOTO→SEARCH 按「距参考点 ≤ arrival_radius」切换;SEARCH→TRACK 按「目标锁定」
|
||||
切换(含 LOS 运动学一致性判据,见 pod_bridge/los_consistency.py)。
|
||||
|
||||
运行前:启动 PX4 SITL(默认本机 14540)。用法:
|
||||
python task_runner_sitl.py
|
||||
python task_runner_sitl.py --conn udp://:14540 --config utils/config/pod_bridge.json
|
||||
python task_runner_sitl.py --conn udpin://0.0.0.0:14540 \
|
||||
--config utils/config/pod_bridge.json
|
||||
"""
|
||||
|
||||
import argparse
|
||||
@@ -40,9 +46,10 @@ from pod_bridge.px4_gateway import Px4Gateway
|
||||
from pod_bridge.virtual_pod import (CarrierView, VirtualPod, VirtualTarget,
|
||||
VirtualTargetConfig)
|
||||
from task_runner.log import TaskLogConfig, TaskLogger
|
||||
from task_runner.return_home import ReturnConfig
|
||||
from task_runner.runner import TaskRunner
|
||||
from task_runner.state_machine import TaskStateConfig, TaskStateMachine
|
||||
from pod_sitl_test import (TelemetryHub, now_ms, print_flight_mode,
|
||||
from sitl_support import (TelemetryHub, now_ms, print_flight_mode,
|
||||
set_telemetry_rates, wait_until_ready)
|
||||
|
||||
logger = logging.getLogger("task_sitl")
|
||||
@@ -83,16 +90,35 @@ def build_sm_config() -> TaskStateConfig:
|
||||
"""SITL 状态机参数(占位值,仅用于仿真验证链路)。"""
|
||||
return TaskStateConfig(
|
||||
takeoff_altitude_m=5.0,
|
||||
switch_radius_m=25.0, # 目标在 30m,飞进 25m 内切 TRACK
|
||||
arrival_radius_m=25.0, # 目标在 30m,飞进 25m 内转搜索
|
||||
goto_timeout_s=60.0,
|
||||
track_timeout_s=60.0,
|
||||
center_hold_s=3.0,
|
||||
center_threshold_deg=3.0, # 脱靶量 < 3° 判居中
|
||||
approach_hover_s=5.0, # 悬停 5s 后 RTL
|
||||
search_timeout_s=20.0, # 搜索 20s 未发现目标 → 返航
|
||||
track_timeout_s=20.0, # 追踪/靠近段上限 → 返航
|
||||
center_threshold_deg=3.0, # 脱靶量 < 3° 判居中(仅日志/诊断)
|
||||
sweep_rate_dps=15.0, # 搜索扫视角速度(度/秒)
|
||||
sweep_reverse_s=4.0, # 每 4s 换向
|
||||
loop_frequency_hz=20.0,
|
||||
)
|
||||
|
||||
|
||||
def build_return_config() -> ReturnConfig:
|
||||
"""SITL 自定义返航参数(与真机同口径,仅用于仿真验证)。"""
|
||||
return ReturnConfig(
|
||||
enabled=True,
|
||||
speed_mps=2.0,
|
||||
arrival_radius_m=3.0,
|
||||
timeout_s=120.0,
|
||||
yaw_kp=1.0,
|
||||
yaw_rate_limit_dps=20.0,
|
||||
align_kp=1.0,
|
||||
align_rate_limit_dps=15.0,
|
||||
yaw_align_tolerance_deg=5.0,
|
||||
yaw_align_timeout_s=15.0,
|
||||
alt_kp=0.5,
|
||||
alt_limit_mps=0.5,
|
||||
)
|
||||
|
||||
|
||||
async def inject_loop(ground: GroundLink, lat: float, lon: float,
|
||||
stop: asyncio.Event) -> None:
|
||||
"""后台持续刷新注入坐标(模拟地面站持续上报,保坐标始终新鲜)。"""
|
||||
@@ -111,6 +137,7 @@ async def run(args) -> int:
|
||||
cfg.ground_inject.enabled = True # 启用地面注入(骨架期 JSON 默认关)
|
||||
cfg.guidance.target_stale_ms = 5000 # 注入坐标超时放宽(表4 默认 1000 对低频注入太紧)
|
||||
sm_cfg = build_sm_config()
|
||||
return_cfg = build_return_config()
|
||||
|
||||
drone = System()
|
||||
await drone.connect(system_address=args.conn)
|
||||
@@ -146,7 +173,7 @@ async def run(args) -> int:
|
||||
sm = TaskStateMachine(sm_cfg)
|
||||
task_log = TaskLogger(TaskLogConfig(), now_ms_fn=now_ms)
|
||||
runner = TaskRunner(cfg, sm_cfg, px4, bridge, sm, ground, drone,
|
||||
now_ms_fn=now_ms, logger=task_log)
|
||||
now_ms_fn=now_ms, logger=task_log, return_cfg=return_cfg)
|
||||
|
||||
stop = asyncio.Event()
|
||||
if args.ground_station:
|
||||
@@ -160,9 +187,9 @@ async def run(args) -> int:
|
||||
if args.ground_station:
|
||||
print(f" [地面站模式] 等待 UDP {cfg.ground_inject.port} 注入坐标…")
|
||||
print(f" 状态机: takeoff={sm_cfg.takeoff_altitude_m}m "
|
||||
f"switch_radius={sm_cfg.switch_radius_m}m "
|
||||
f"center={sm_cfg.center_threshold_deg}°/{sm_cfg.center_hold_s}s "
|
||||
f"hover={sm_cfg.approach_hover_s}s")
|
||||
f"arrival_radius={sm_cfg.arrival_radius_m}m "
|
||||
f"search={sm_cfg.search_timeout_s}s@{sm_cfg.sweep_rate_dps}°/s "
|
||||
f"track_max={sm_cfg.track_timeout_s}s")
|
||||
|
||||
# 状态打印 + 总超时保护
|
||||
started = time.monotonic()
|
||||
|
||||
Reference in New Issue
Block a user