# 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: 15–33× повільніше за 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.X` → `from 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**: `.planning/brainstorms/2026-04-16-e2e-datasets-design.md` **Plan**: `.planning/brainstorms/2026-04-16-e2e-datasets-plan.md` [decision 2026-04-16: замість збору власних даних з Mavic-а — використати публічні UAV датасети. Причина: блокер на проприєтарні дані (Денис, мавікісти), а нам треба рухатись вже зараз. Public датасети: VPAIR (fixed-wing, downward, 300–400 м) + EuRoC (indoor MAV, IMU+GT, індустрійний benchmark) + MARS-LVIG (rotary, featureless сіквенси як stress-test). Деталі — у design-doc.] - [x] Побудувати `DatasetAdapter` ABC + capability flags (has_raw_imu, has_rtk_gt, platform_class) — `src/gps_denied/testing/datasets/base.py` - [x] `SyntheticAdapter` для harness self-test (`synthetic.py`) - [x] Trajectory метрики — RMSE, ATE, RPE (`metrics.py`) - [x] `E2EHarness` — жене адаптер через `FlightProcessor`, збирає estimated positions, порівнює з GT (`harness.py`) - [x] SHA256-verified dataset downloader + registry (`download.py`, `scripts/download_dataset.py`) - [x] `EuRoCAdapter` + unit-тести з fabricated fixture - [x] `VPAIRAdapter` + unit-тести з fabricated fixture (**реальний формат**: poses_query.txt, ECEF xyz, Euler rad) - [x] `MARSLVIGAdapter` + unit-тести (очікує pre-extracted layout з ROS bag) - [x] `coord.py` helpers: ECEF→WGS84 (Heikkinen closed-form), Euler→quaternion (ZYX aerospace) - [x] Integration тести з skip-when-absent fixtures (EuRoC, VPAIR, MARS-LVIG) - [x] Pytest markers `e2e`, `e2e_slow`, `needs_dataset` у pyproject.toml - [x] **Перший реальний 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.] - [ ] Запустити EuRoC MH_01 через e2e (потребує `machine_hall.zip` — 12 GB bundle; завтра) - [decision 2026-04-16: замість старого `robotics.ethz.ch` URL (TCP timeout) — новий ETH Research Collection DOI `10.3929/ethz-b-000690084`. Окремого `MH_01_easy.zip` там немає, лише bundle з усіма 5 MH-сіквенсами. Витягнемо MH_01 локально, пушимо тільки конфігурацію.] - [ ] Замінити xfail на strict-assert у VPAIR тесті (коли VO+GPR почнуть давати притомні числа) - [ ] **IMU з SITL для початку** — ArduPilot SITL може літати mission з waypoints, генерувати 200 Hz IMU через MAVLink. Для піднять пайплайну цього достатньо. Реальний IMU треба так чи інакше, але це паралельна гілка роботи. ### Патерн гілок для e2e-роботи - `feat/e2e-vpair` — сьогоднішня робота (VPAIR адаптер під реальний формат + coord helpers + registry). **Поточний статус**: 4 коміти, пушнуто, PR у stage1 відкритий - `feat/e2e-euroc` — завтра (EuRoC MH_01 реальний прогін) - Інтеграція у stage1 через послідовні PR-и (VPAIR → stage1, потім EuRoC branch off з оновленого stage1) --- ## 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 (`a2620ae` → `0062323`), пушнуто. 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).