精简仓库结构并增强任务链路:归档双目可选后端、新增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:
@@ -1,7 +1,7 @@
|
||||
"""log_test.py —— 任务日志模块单元测试。
|
||||
|
||||
覆盖:open 建目录/写表头、事件 JSONL、遥测 CSV、telemetry_every_n 节流、
|
||||
disabled 时零副作用、close 收尾。
|
||||
disabled 时零副作用、close 收尾、简洁任务简报(task_brief.log)。
|
||||
"""
|
||||
|
||||
import csv
|
||||
@@ -121,3 +121,84 @@ def test_append_keeps_existing_rows(tmp_path):
|
||||
assert len(rows) == 2
|
||||
assert rows[0]["state"] == "wait"
|
||||
assert rows[1]["state"] == "goto"
|
||||
|
||||
|
||||
# --- 简洁任务简报(task_brief.log)-------------------------------------------
|
||||
def test_brief_log_lines_and_summary(tmp_path):
|
||||
logger = TaskLogger(_cfg(tmp_path))
|
||||
logger.open()
|
||||
logger.log_event(1000, "state", from_state="wait", to_state="wait",
|
||||
reason="任务启动")
|
||||
logger.log_event(2000, "state", from_state="wait", to_state="arm_takeoff",
|
||||
reason="收到地面坐标")
|
||||
logger.log_event(3000, "command", name="rtl")
|
||||
logger.log_event(4000, "fc_status", severity="WARNING", text="Low battery\t")
|
||||
logger.log_event(5000, "takeoff", altitude_m=5.0)
|
||||
logger.log_event(6000, "rtl")
|
||||
logger.log_telemetry(1000, TelemetryRecord(
|
||||
state="wait", relative_altitude_m=0.0, distance_to_target_m=33.5))
|
||||
logger.log_telemetry(1100, TelemetryRecord(
|
||||
state="arm_takeoff", relative_altitude_m=5.2, distance_to_target_m=20.0))
|
||||
logger.log_telemetry(1200, TelemetryRecord(
|
||||
state="arm_takeoff", relative_altitude_m=5.0,
|
||||
distance_to_target_m=float("inf")))
|
||||
logger.close()
|
||||
|
||||
text = (tmp_path / "task_brief.log").read_text(encoding="utf-8")
|
||||
assert "任务开始" in text
|
||||
assert "[00:00.0] 任务启动(当前: 待命)" in text
|
||||
assert "[00:01.0] 阶段: 待命 → 起飞(收到地面坐标)" in text
|
||||
assert "[00:02.0] 地面站命令: rtl" in text
|
||||
assert "[00:03.0] 飞控 WARNING: Low battery" in text # 尾随 tab 已 strip
|
||||
assert "[00:04.0] 起飞至 5.0 m" in text
|
||||
assert "[00:05.0] 开始返航" in text
|
||||
assert "本次运行汇总" in text
|
||||
assert "时长 0.2s" in text # 最后一行遥测的 t_s
|
||||
assert "最高 5.2m" in text
|
||||
assert "最近距目标 20.0m" in text # inf 不计入
|
||||
assert "事件 6 条" in text
|
||||
assert "状态链 待命→起飞" in text
|
||||
|
||||
|
||||
def test_brief_required_no_file_when_disabled_or_closed(tmp_path):
|
||||
logger = TaskLogger(_cfg(tmp_path, enabled=False))
|
||||
logger.open()
|
||||
logger.log_event(1000, "rtl")
|
||||
logger.close()
|
||||
assert not (tmp_path / "task_brief.log").exists()
|
||||
|
||||
|
||||
# --- 遥测落盘节流(2026-10-15:主循环 20Hz 不得每行同步 flush)----------------
|
||||
def test_telemetry_buffered_until_flush_interval(tmp_path):
|
||||
"""telemetry_flush_ms 内只写不 flush;close 兜底落盘,一行不丢。"""
|
||||
logger = TaskLogger(_cfg(tmp_path, telemetry_flush_ms=1000))
|
||||
logger.open()
|
||||
rec = TelemetryRecord(state="track")
|
||||
logger.log_telemetry(1000, rec) # 首行:落盘一次并打戳
|
||||
for i in range(1, 19): # 其后 19 行都在 1s 内 → 不再 flush
|
||||
logger.log_telemetry(1000 + i * 50, rec)
|
||||
logger.close()
|
||||
|
||||
with open(tmp_path / "task_telemetry.csv", encoding="utf-8") as f:
|
||||
rows = list(csv.DictReader(f))
|
||||
assert len(rows) == 19
|
||||
|
||||
|
||||
def test_telemetry_flush_zero_flushes_every_row(tmp_path):
|
||||
"""telemetry_flush_ms=0 保留旧的「每行立即 flush」行为(兼容/调试)。"""
|
||||
logger = TaskLogger(_cfg(tmp_path, telemetry_flush_ms=0))
|
||||
logger.open()
|
||||
logger.log_telemetry(1000, TelemetryRecord(state="goto"))
|
||||
assert logger._last_tel_flush_ms == 1000
|
||||
logger.close()
|
||||
|
||||
|
||||
def test_events_still_flushed_immediately(tmp_path):
|
||||
"""事件(阶段切换)仍即时落盘:地面站页面实时性不受遥测节流影响。"""
|
||||
logger = TaskLogger(_cfg(tmp_path, telemetry_flush_ms=10_000))
|
||||
logger.open()
|
||||
logger.log_event(1000, "state", from_state="goto", to_state="search")
|
||||
with open(tmp_path / "task_events.jsonl", encoding="utf-8") as f:
|
||||
lines = [json.loads(x) for x in f if x.strip()]
|
||||
assert len(lines) == 1
|
||||
logger.close()
|
||||
|
||||
Reference in New Issue
Block a user