Files
gps-denied-onboard/next_steps.md
T
2026-04-18 14:52:58 +03:00

15 KiB
Raw Blame History

Next Steps — дорожня карта

Живий документ. Галочки заповнюються у міру виконання. Коментарі в квадратних дужках [decision: …] фіксують рішення, щоб через місяць можна було зрозуміти чому ми зробили саме так.


1. Аудит відповідності солюшну

Весь девелопмент зроблений не з цільового _docs/01_solution/solution.md, а з сукупності документів у _docs/01_solution/. Треба звірити імплементацію саме з цільовим солюшном.

  • Порівняти поточну імплементацію з _docs/01_solution/solution.md (не з усією текою)
  • VO треба зробити на cuVSLAM (якщо не буде явних перепон)
    • Rationale: SP+LG (SuperPoint+LightGlue) rejection: 1533× повільніше за cuVSLAM. Немає built-in IMU fusion, loop closure, tracking-failure detection. Побудова цих фіч навколо SP+LG — значний час, і все одно повільніше. XFeat (~30–50 мс) — кращий fallback для VO якщо cuVSLAM не зайде на nadir-камеру.
  • Прогнати cuVSLAM через e2e-харнес (див. пункт 3) — перевірити що VO+ESKF разом дають адекватну точність на EuRoC/VPAIR
  • Якщо cuVSLAM підходить → видалити SP+LG з кодбейса. Залишити XFeat як fallback

Цей крок треба робити ПІД захистом e2e-харнеса, не до нього, щоб відразу бачити регресії (див. пункт 3).


2. Реструктуризація коду

Весь код у src/gps_denied/, але весь проект і так про gps_denied — зайвий рівень неймспейсу.

  • git mv src/gps_denied/* src/ (або через rename imports, що чистіше)
  • Оновити імпорти у всіх файлах (from gps_denied.Xfrom X чи залишити як неймспейс, вирішити)
  • Оновити pyproject.toml: [tool.setuptools.packages.find]
  • Прогнати повну test suite — має бути зелено
  • Оновити CI скрипти, Docker, docs

Робити під захистом e2e-харнеса — одна велика рефакторинг-зміна з багатьма PR → легко поламати щось непомітно. Зелений e2e (на тих самих числах що до рефакторингу) — sign-off.


3. Autopilot existing-code flow — e2e-харнес

Всі проекти в azaion приводяться до механізму девелопменту з .cursor/skills/autopilot (flows/existing-code для існуючого коду, flows/greenfield для нового).

Коротко алгоритм: питаємо вимоги до e2e-тестів і даних → рефакторимо для можливості e2e-покриття → пишемо e2e-підсистему що запускає продукт як black-box → переконуємось що працює → тоді ітеративно рефакторимо під захистом e2e.

Статус виконання

Design (локально, gitignored): .planning/brainstorms/2026-04-16-e2e-datasets-design.md Plan (локально, gitignored): .planning/brainstorms/2026-04-16-e2e-datasets-plan.md In-repo docs: src/gps_denied/testing/README.md (harness architecture), _docs/01_solution/decisions/0001-e2e-dataset-strategy.md (ADR — selection rationale)

[decision 2026-04-16: замість збору власних даних з Mavic-а — використати публічні UAV датасети. Причина: блокер на проприєтарні дані (Денис, мавікісти), а нам треба рухатись вже зараз. Public датасети: VPAIR (fixed-wing, downward, 300400 м) + EuRoC (indoor MAV, IMU+GT, індустрійний benchmark) + MARS-LVIG (rotary, featureless сіквенси як stress-test). Деталі — у ADR 0001.]

  • Побудувати DatasetAdapter ABC + capability flags (has_raw_imu, has_rtk_gt, platform_class) — src/gps_denied/testing/datasets/base.py
  • SyntheticAdapter для harness self-test (synthetic.py)
  • Trajectory метрики — RMSE, ATE, RPE (metrics.py)
  • E2EHarness — жене адаптер через FlightProcessor, збирає estimated positions, порівнює з GT (harness.py)
  • SHA256-verified dataset downloader + registry (download.py, scripts/download_dataset.py)
  • EuRoCAdapter + unit-тести з fabricated fixture
  • VPAIRAdapter + unit-тести з fabricated fixture (реальний формат: poses_query.txt, ECEF xyz, Euler rad)
  • MARSLVIGAdapter + unit-тести (очікує pre-extracted layout з ROS bag)
  • coord.py helpers: ECEF→WGS84 (Heikkinen closed-form), Euler→quaternion (ZYX aerospace)
  • Integration тести з skip-when-absent fixtures (EuRoC, VPAIR, MARS-LVIG)
  • Pytest markers e2e, e2e_slow, needs_dataset у pyproject.toml
  • Перший реальний e2e-прогін на VPAIR sample (200 кадрів fixed-wing, 300-400 м над Bonn/Eifel)
    • Результат: пайплайн завершується без падінь, ATE RMSE ~1 770 км → xfail
    • [decision 2026-04-16: це очікувано. VO сам по собі без IMU і без supплементарного supплутникового anchoring розходиться. VPAIR не має raw IMU → ESKF-шлях не активується. Xfail-branch документує цю deгадацію; перейде у strict-assert коли VO+GPR будуть тюновані для high-altitude nadir + знайдемо датасет з raw IMU.]
  • Перший реальний e2e-прогін на EuRoC MH_01 (перші 100 кадрів indoor MAV, ASL формат)
    • Результат: пайплайн завершується за ~30 с, ATE RMSE ~10 871 м → xfail за ceiling 5 м
    • [decision 2026-04-17: замість старого robotics.ethz.ch URL (TCP timeout) — новий ETH Research Collection DOI 10.3929/ethz-b-000690084. Окремого MH_01_easy.zip там немає, лише 12.6 GB bundle з усіма 5 MH-сіквенсами. Витягнули тільки MH_01_easy.zip у /home/yuzviak/Azaion/Data/machine_hall/MH_01/, symlink з datasets/euroc/MH_01/. Registry entry перейменована на euroc_machine_hall (bundle-level SHA256).]
    • [decision 2026-04-17: harness отримав параметр max_frames — CI-tier гонить 100 кадрів за ~30 с. Повна sequence (3682) — ~3 години, не CI-tier.]
    • Pipeline diff vs VPAIR: raw IMU є → ESKF активний; але satellite-anchoring для indoor-сцени не релевантний, VO+ESKF без якоря дрейфує на кілометри.
  • Замінити xfail на strict-assert у VPAIR і EuRoC тестах (коли VO+GPR+ESKF-anchoring почнуть давати притомні числа)
  • IMU з SITL для початку — ArduPilot SITL може літати mission з waypoints, генерувати 200 Hz IMU через MAVLink. Для піднять пайплайну цього достатньо. Реальний IMU треба так чи інакше, але це паралельна гілка роботи.

Патерн гілок для e2e-роботи

  • feat/e2e-vpairmerged у stage1 через PR #1 (2026-04-16, rebase)
  • feat/e2e-euroc — поточна робота (2026-04-17): harness max_frames, перший реальний прогін EuRoC MH_01, реєстр перейменовано на euroc_machine_hall
  • Інтеграція у stage1 через послідовні PR-и. Політика: наступні merge без --delete-branch (гілки лишаються на GitHub)

4. Збір реальних UAV-даних

[decision 2026-04-16: деприйорити цей пункт на користь пункту 3 (публічні датасети). Причина: публічні датасети вже є, дають реальний fixed-wing сценарій, не вимагають координації людей. Повернемось до цього коли:

  • (а) потрібно буде валідувати на нашому конкретному дроні (intrinsics, спектр вібрації IMU, camera model відрізняються від VPAIR/EuRoC);

  • (б) готовий буде VO+ESKF-тюнінг і захочеться "фінальний" датасет саме під envelope tactical fixed-wing 200-1500 м.]

  • Денис Попов — логи Mavic (камера вниз, висока висота). Призупинено.

  • Штатні мавікісти — пара тестових вильотів з nadir-камерою. Призупинено, потребує переконати.

  • DJI Mavic флайт у /home/yuzviak/Azaion/Data/ (MP4 + SRT + Airdata CSV)

    • [decision 2026-04-16: НЕ інтегруємо зараз. Причини: (1) DJI не публікує raw IMU, є лише attitude/speeds (результат фʼюжену) — ESKF-шлях не активується; (2) потрібні camera intrinsics конкретної моделі; (3) sync SRT@30Hz + CSV@5Hz потребує окремого alignment-кроку. Залишаємо як qualitative demo пізніше, коли інфраструктура стабілізується.]

Хронологія рішень

  • 2026-04-16 ранок: Аудит інфраструктури, pull upstream, вирішили взяти публічні датасети замість чекати на Дениса. Brainstorm + spec + plan: VPAIR (Tier 1), MARS-LVIG (Tier 2), EuRoC (Tier 3 CI).
  • 2026-04-16 день: Реалізовано e2e-харнес з DatasetAdapter pattern. 12 комітів у stage1 (a2620ae0062323), пушнуто. 233 passed, 13 skipped.
  • 2026-04-16 вечір: Спробували скачати EuRoC MH_01 — старий URL лежить, знайшли новий DOI (12 GB bundle, завтра). Переключились на VPAIR (вже скачаний). Реальний формат відрізняється від припущеного: ECEF+Euler+no timestamps. Написали coord.py (ECEF→WGS84 Heikkinen + Euler→quat), переписали VPAIRAdapter. Гілка feat/e2e-vpair, 5 комітів. Перший реальний прогін: ATE ~1770 км (очікувано, задокументовано в xfail).
  • 2026-04-17: Завантажили 12.6 GB machine_hall.zip, витягли MH_01 (2.6 GB). Додали max_frames у E2EHarness (TDD, 3 нових тести). Перший реальний прогін EuRoC MH_01 на 100 кадрах: пайплайн завершується за ~30 с, ATE RMSE ~10.87 км → xfail. Registry entry перейменовано euroc_mh01euroc_machine_hall з реальним SHA256 5ed7d07…; URL порожній (ETH Research Collection не дає direct link, ручне завантаження). Гілка feat/e2e-euroc.
  • 2026-04-18: Три PR підряд у stage1:
    • PR #4 feat/e2e-trace — додали per-frame JSONL трасування в E2EHarness (trace_path параметр). Запустили EuRoC MH_01 з трасуванням: виявлено vo_success=0/100, eskf_initialized=0/100, alignment_success=77/100. Всі оцінки — fallback satellite matching без ESKF/VO.
    • PR #5 feat/e2e-vo-only — ORB VO-only діагностика. Запустили ORBVisualOdometry напряму на EuRoC кадрах: 99/99 tracking rate (100%). Висновок: проблема була не в VO-алгоритмі, а в тому що SequentialVisualOdometry (Mock random keypoints → RANSAC failure) використовувалась у харнесі.
    • PR #6 feat/e2e-harness-orb-vo — замінили VO-бекенд у _build_processor з SequentialVisualOdometry(ModelManager()) на ORBVisualOdometry(). Новий результат: vo_success=99/100. Залишилась проблема: eskf_initialized=0/100 — ESKF потребує init_flight() зі start_gps, харнес цього не робить.
    • [decision 2026-04-18: VO-бекенд у харнесі має бути ORBVisualOdometry (реальні OpenCV фічі), а не Mock SP+LG (random keypoints). Для Jetson-production cuVSLAM залишається метою — але харнес валідує pipeline логіку незалежно від бекенду.]
    • Наступний крок: ініціалізувати ESKF у харнесі з синтетичним GPS-origin (середня координата GT або перша GT-поза). Це увімкне ESKF-шлях і дасть змогу виміряти реальний VO+ESKF дрейф без satellite fallback.
  • PR #8 feat/e2e-eskf-init — ESKF ініціалізується з першої GT-пози адаптера. Результат: eskf_initialized: 0→100/100, eskf_has_position: 100/100. ATE RMSE 10.7 км. Satellite measurements відхиляються Mahalanobis gate (Δ²10⁶ >> 16.3). Root cause: ORB scale_ambiguous=True → unit-scale VO translations → ESKF position diverges → satellite outlier gate срацює коректно.
    • Наступний крок: VO metric scale. ORB переводить (R, t̂) де — одиничний вектор, реальна відстань невідома. Варіанти: (а) передавати IMU timestamps у ESKF щоб він сам рахував scale через velocity; (б) перейти на cuVSLAM (metric backend); (в) хак — фіксований scale для EuRoC indoor (~0.3 м між кадрами). Правильний шлях — (б) cuVSLAM, але для CI-діагностики можна (в).