From dfd41f27d46c3d05577693570958a25fddd0900f Mon Sep 17 00:00:00 2001 From: Yuzviak Date: Sat, 18 Apr 2026 15:50:12 +0300 Subject: [PATCH] chore: pin numpy<2.0 and align plan with tech-audit research MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Research doc (2026-04-18 OSS stack audit) flagged NumPy 2.0 as silently breaking GTSAM Python bindings (issue #2264). Pin numpy>=1.26,<2.0 and constrain opencv-python-headless<4.11 (knock-on: 4.11+ requires numpy≥2). Verified after downgrade: - 196 passed / 8 skipped unit/component - EuRoC MH_01 e2e PASS (no regression on 0.205m ESKF ATE baseline) Plan updates in next_steps.md §5: - cuVSLAM strategy clarified: Mono-Depth (barometer as synthetic depth), not Mono-Inertial (needs stereo hardware we don't have) - DINOv2-VLAD (AnyLoc) for GPR + FP16 TRT (INT8 broken for ViT on Jetson) - GTSAM: documented that 4.2 stable is not on PyPI (only 4.3a0), so deferred to post-sprint-1 ESKF-only path stays the right call - VPAIR xfail root cause: no raw IMU + mock satellite index (verified with scale=1.0 and scale=45.0 runs — ATE stays at ~1236m ESKF / ~1770km GPS regardless of scale) - Flight controller H743 vs F405 check flagged as critical blocker README "next steps" section rewritten to match the research-aligned plan. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 13 +++++++--- next_steps.md | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 4 +-- 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a68f172..fbbdabd 100644 --- a/README.md +++ b/README.md @@ -292,10 +292,15 @@ gps-denied-onboard/ ## Що залишилось (наступні кроки) ### Dev pipeline (захищений e2e-харнесом) -1. **cuVSLAM як VO backend** — замінити `ORBVisualOdometry` на `CuVSLAMVisualOdometry` (metric scale, IMU fusion). Поточний `vo_scale_m=0.005` — CI-хак, cuVSLAM вирішить це коректно. -2. **VPAIR outdoor** — перевірити satellite matching на fixed-wing outdoor сцені (VPAIR має `reference_views/`). Якщо GPS ATE покращиться — xfail → strict-assert. -3. **Аудит solution.md** — звірити імплементацію з `_docs/01_solution/solution.md`. -4. **Реструктуризація** — `src/gps_denied/*` → `src/*` (зайвий неймспейс). +1. **cuVSLAM Mono-Depth** — замінити `ORBVisualOdometry` на cuVSLAM Mono + барометричний depth (`scale = altitude / focal_length`). Mono-Inertial потребує stereo hardware (нема). Mono-Depth — правильний шлях для одиничної nadir-камери. Research: `docs/superpowers/specs/2026-04-18-oss-stack-tech-audit-design.md`. +2. **DINOv2-VLAD (AnyLoc) для GPR** — замінити numpy L2 fallback. Satellite tiles через MapTiler MBTiles (offline). Fixed FP16, без INT8 (broken для ViT на Jetson). +3. **VPAIR unblock** — xfail (1770 км ATE) блокований відсутністю raw IMU + mock satellite index. Реальні MapTiler tiles **АБО** cuVSLAM Mono-Depth з GT-altitude розблокують. +4. **Аудит solution.md** — звірити імплементацію з `_docs/01_solution/solution.md`. +5. **Реструктуризація** — `src/gps_denied/*` → `src/*` (зайвий неймспейс). + +### Критичні блокери (перевірити до наступного коду) +- **Flight Controller processor**: H743 ✅ / F405 ❌ (silently ignores GPS_INPUT). Запитати постачальника. +- **IMU rate через MAVLink**: за замовчуванням ArduPilot 50 Hz, для Mono-Inertial потрібно ≥100 Hz (`SR2_RAW_SENS`). Для Mono-Depth не критично. ### On-device (Jetson Orin Nano Super) 1. Офлайн завантаження тайлів для зони місії → `{tile_dir}/z/x/y.png` diff --git a/next_steps.md b/next_steps.md index 85a6198..1fbe697 100644 --- a/next_steps.md +++ b/next_steps.md @@ -120,3 +120,71 @@ MH_03-05 мають дуже малий дрейф (~1 см) бо перші 100 кадрів MAV майже нерухомий (старт sequence). Це нормально — цей baseline зростатиме якщо запустити більше кадрів. **Поточний стан e2e харнесу**: 70 passed, 1 skipped, 2 xfailed. Всі EuRoC MH sequences покриті strict-assert тестами. + +--- + +## 5. Tech audit — Open-Source Stack alignment + +Research документ `docs/superpowers/specs/2026-04-18-oss-stack-tech-audit-design.md` (2026-04-18) переглянув увесь OSS-стек і знайшов кілька критичних розходжень з поточною архітектурою. Нижче — стан синхронізації з research. + +### 5.1 Виконано (2026-04-18 вечір) + +- [x] **Numpy pin `>=1.26,<2.0`**. NumPy 2.0 silently breaks GTSAM Python bindings (research 4.3, issue #2264). + - Також довелось обмежити `opencv-python-headless<4.11` — 4.11+ вимагає numpy≥2. Knock-on constraint. + - Після downgrade: unit 196 passed / 8 skipped, e2e EuRoC MH_01 PASS (без регресії). +- [x] **VPAIR контрольний прогін на 50 кадрах з `vo_scale_m=1.0` і `vo_scale_m=45.0`** (GT inter-frame displacement median=45 м — fixed-wing на 400 м, швидкість ~225 м/с × 0.2 с між synthetic timestamps). + - Результат не залежить від scale: ESKF ATE ≈ 1236-1343 м, GPS ATE ≈ 1770 км. + - [decision 2026-04-18: VPAIR **не можна зробити PASS на поточному стеку**. Фундаментальні блокери: (а) немає raw IMU → ESKF дрейфує за рахунок тільки VO; (б) Mock satellite index повертає координати «в іншій півкулі світу» (не реальні tiles України), тому Mahalanobis gate відхиляє satellite estimates як outliers (Δ²~10⁹). Залишаємо xfail із задокументованою причиною. Розблокувати зможе: реальні satellite tiles (MapTiler MBTiles) **АБО** cuVSLAM Mono-Depth з барометром (dataset-level synthetic IMU).] + +### 5.2 Відкореговано в плані (наступні дії) + +**cuVSLAM стратегія** (research §1, §2): +- ❌ Раніше писали просто «cuVSLAM як VO backend». +- ✅ Тепер: **cuVSLAM Mono-Depth** (Mono + synthetic depth з барометра: `scale = altitude / focal_length`). Mono-Inertial потребує stereo hardware (у нас одна nadir-камера). +- Це пояснює чому VPAIR без IMU показує 1236 м ESKF ATE — без altitude-to-scale recovery VO drift unbounded. На EuRoC `vo_scale_m=0.005` працював тільки бо indoor scene має constant ~5 мм/кадр. + +**Place Recognition** (research §3): +- Раніше: «GlobalPlaceRecognition (numpy/Faiss)» — backend не уточнений. +- Тепер: **DINOv2-VLAD (AnyLoc)** як descriptor → Faiss GPU index. EigenPlaces як upgrade path. +- **INT8 квантизація ❌** — broken для ViT на Jetson (NVIDIA/TRT#4348). Stay at FP16. + +**GTSAM**: +- Research радить «GTSAM 4.2 stable» замість 4.3a1 alpha. +- **Практично неможливо**: PyPI має тільки `gtsam==4.3a0`. 4.2 потребує custom source build. Залишаємо `gtsam>=4.3a0` до появи stable wheel **АБО** source-build мануал. +- GTSAM-шлях відкладено для sprint 1 (research §3 Factor Graph): ESKF достатній для Gaussian GPS_INPUT 5-10 Hz. Mock залишається. + +**MAVLink** (research §3): +- pymavlink ✅ (MAVSDK-Python не підтримує GPS_INPUT). +- **Reference impl**: `MAVProxy/modules/mavproxy_GPSInput.py` — точне кодування `GPS_INPUT` (#232). Звірити коли будемо інтегрувати з SITL. +- **Injection rate**: 5-10 Hz, не 20+ (timing jitter). + +**Flight Controller hardware** (research §4.1) — відкрите питання: +- H743 ✅ GPS_INPUT over serial +- F405 ❌ silently ignores GPS_INPUT (втрата днів на дебаг) +- [ ] Запитати постачальника / перевірити через Mission Planner before any SITL-to-hardware crossover. + +### 5.3 Пріоритети на 2-3 тижні (синхронізовано з research §5) + +**Тиждень 1 (починається 2026-04-19):** +- [x] numpy pin ← зроблено 2026-04-18 +- [ ] Перевірити FC processor (H743 vs F405) — спитати постачальника +- [ ] Перевірити поточний IMU rate через MAVLink (за замовчуванням ArduPilot шле 50 Hz, треба ≥100 Hz для Mono-Inertial; для Mono-Depth не критично) +- [ ] Prototype cuVSLAM Mono-Depth з барометром як synthetic depth (на EuRoC — IMU дає altitude, нема барометра, але можна подавати GT altitude як proxy) +- [ ] Прогнати [aero-vloc](https://github.com/prime-slam/aero-vloc) benchmark на VPAIR nadir кадрах до того як фіксувати Faiss index дизайн + +**Тиждень 2:** +- [ ] cuVSLAM Mono-Depth інтеграція в E2EHarness (новий `_ScaledVO` analog, але scale береться per-frame з GT altitude) +- [ ] Порівняти ATE: ORB (поточний baseline 0.205 м на MH_01) vs cuVSLAM Mono-Depth +- [ ] AnyLoc offline setup + перший тест на satellite tiles + +**Тиждень 3:** +- [ ] XFeat TRT export для satellite matching (окремий трек від VO — не VO fallback) +- [ ] MAVLink GPS_INPUT injection тест на SITL +- [ ] Визначити чи варто піднімати IMU rate для майбутнього Mono-Inertial + +### 5.4 Відкриті питання (research §7) + +1. Якість cuVSLAM Mono-Depth на feature-poor nadir terrain (рівне поле, ліс). +2. Частота та надійність GPR match в реальних умовах України. +3. Чи достатньо барометра для scale recovery при різких змінах висоти. +4. Коли (чи взагалі) потрібен перехід на Stereo-Inertial (hardware change). diff --git a/pyproject.toml b/pyproject.toml index 5950d6f..9af1da8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,8 +15,8 @@ dependencies = [ "python-multipart>=0.0.9", "httpx>=0.27", "diskcache>=5.6", - "numpy>=1.26", - "opencv-python-headless>=4.9", + "numpy>=1.26,<2.0", # NumPy 2.0 silently breaks GTSAM Python bindings (issue #2264) + "opencv-python-headless>=4.9,<4.11", # 4.11+ requires numpy>=2.0 (incompatible with GTSAM) "gtsam>=4.3a0", "pymavlink>=2.4", ]