Files
gps-denied-onboard/docs/superpowers/specs/2026-04-18-oss-stack-tech-audit-design.md
T
Yuzviak 352d5e59ed docs(tech-audit): OSS stack audit and sprint-1 technology decisions
Records architectural gap (cuVSLAM Mono has no metric scale),
chosen path (Mono-Depth + barometer), and per-layer decisions
for VO, ESKF, GTSAM, Place Recognition, and MAVLink.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 15:29:02 +03:00

9.3 KiB
Raw Blame History

Tech Audit — Open-Source Stack для GPS-Denied Navigation

Дата: 2026-04-18
Горизонт: 23 тижні (sprint 1)
Контекст: Fixed-wing БПЛА, Jetson Orin Nano Super, nadir камера ADTI 20L V1, ArduPilot FC


1. Архітектурний розрив — головна знахідка

Проблема з cuVSLAM Inertial mode

Поточна архітектура планує cuVSLAM у режимі "Inertial" (з IMU). Але:

  • cuVSLAM Inertial/Visual-Inertial mode потребує стерео камеру (дві камери поряд, як очі)
  • У нас одна nadir камера — Mono режим
  • cuVSLAM Mono дає лише кут повороту, без metric scale (без відстані)
  • Без scale неможливо побудувати GPS_INPUT — це useless для ArduPilot

Важливо: камера пілота (вперед) + nadir камера (вниз) — це не stereo. Stereo = дві камери в одному напрямку на відстані 10–20 см.

Чому це не критично для sprint 1

Scale для nadir камери над рівною місцевістю — детермінований:

scale = altitude / focal_length

Барометр дає висоту → ESKF рахує scale → VO потребує лише точний 2D planar tracking. Це і є перший шлях.


2. Вибрана архітектура (sprint 1)

VO: cuVSLAM Mono-Depth + барометр

Рішення: cuVSLAM Mono-Depth режим, де барометрична висота подається як synthetic depth для відновлення metric scale.

Точність між GPR корекціями: ~0.30.5 м
Drift на маршруті: обмежений — GPR скидає накопичену похибку

Чому drift не критичний

Архітектура має три рівні корекції:

VO (drift між кадрами)
    ↓
ESKF ← IMU (короткострокова стабілізація, ~ms)
    ↓
Place Recognition ← satellite tiles (глобальна корекція, ~сотні метрів)
    ↓
GTSAM loop closure (довгострокова консистентність)

Якщо GPR впізнає місцевість кожні ~500 м → загальна похибка на 10 км маршруту: 15 м. Це прийнятно для GPS-denied.

Ризик GPR: не спрацює при хмарах, однорідній місцевості (поле без орієнтирів), застарілих тайлах. В цих випадках drift накопичується до наступного успішного match.


3. Технологічний стек — рішення по шарах

VO Layer

Компонент Dev/CI Production (Jetson) Статус
Visual Odometry ORBVisualOdometry (OpenCV) cuVSLAM Mono-Depth Залишаємо, фіксуємо Mono-Depth
XFeat Satellite tile matching (майбутнє) Не VO fallback, окремий трек
SuperPoint+LightGlue Відхилено: 15–33× повільніше за cuVSLAM

Відхилені альтернативи:

  • ORB-SLAM3 Mono-Inertial (~0.08 м) — потребує IMU ≥100 Hz по MAVLink. Типово ArduPilot шле 50 Hz (SR*_RAW_SENS). Можна підняти до 200 Hz зміною одного параметра, але не пріоритет зараз.
  • cuVSLAM Stereo-Inertial (0.054 м) — потребує hardware зміни (друга камера). Довгостроково.

ESKF

Рішення Обґрунтування
Залишаємо numpy 15-state ESKF IMU preintegration не критичний на 5–10 Hz VO для повільного fixed-wing
Пінити numpy==1.26.4 NumPy 2.0 ламає GTSAM Python bindings (issue #2264) — критично
manifpy — опційно pip-installable Lie group math, додати тільки якщо знайдемо баги в quaternion коді

Factor Graph (GTSAM)

Рішення sprint 1: пропустити GTSAM, використовувати ESKF.

ESKF достатній для Gaussian GPS_INPUT 510 Hz. Factor graph дає перевагу (~15 vs 34 см) лише при non-Gaussian noise з outliers — не наш сценарій зараз.

Коли повернутись: GTSAM 4.2 stable (не 4.3a1 alpha). miniSAM — стейл з 2019, g2o Python — experimental. Єдиний живий варіант.

Place Recognition

Компонент Рішення Обґрунтування
Descriptor DINOv2-VLAD (AnyLoc) 1012 мс TRT FP16 на Jetson, offline-capable
Index Faiss GPU Залишаємо
INT8 квантизація Не робити Broken для ViT на Jetson (NVIDIA/TRT#4348, dinov2#489)
Довгостроково EigenPlaces (ICCV 2023) Кращий ONNX export, viewpoint-robust
NetVLAD Deprecated DINOv2-VLAD краще на 2.4% R@1 (MSLS 2024)
Satellite tiles MapTiler offline MBTiles Україна zoom 013, JPEG, offline

Перевірити: aero-vloc — benchmark на aerial nadir imagery до того як фіксувати Faiss index дизайн.

Рішення Обґрунтування
pymavlink залишаємо MAVSDK-Python не підтримує GPS_INPUT (PX4-first)
Reference impl MAVProxy/modules/mavproxy_GPSInput.py — точне кодування GPS_INPUT (#232)
Частота injection 510 Hz (не 20 Hz — timing jitter при вищих rate)
Yaw extension field Не використовувати — ArduPilot 4.x ігнорує

4. Критичні перевірки перед кодом

Три речі, які треба знати до того як писати будь-який код:

4.1 Процесор Flight Controller

  • H743 — підтримує GPS_INPUT over serial
  • F405 — мовчки ігнорує GPS_INPUT (втрата днів на дебаг)
  • Перевірити: Mission Planner → Help → About (показує назву FC), або питати у постачальника дрона
  • За замовчуванням ArduPilot: 50 Hz
  • Для ORB-SLAM3 Mono-Inertial потрібно: ≥100 Hz
  • Параметр для зміни: SR2_RAW_SENS (або SR0/SR1 залежно від порту)
  • Для sprint 1 (cuVSLAM Mono-Depth) — не критично

4.3 numpy версія

  • Зафіксувати numpy==1.26.4 в pyproject.toml негайно
  • NumPy 2.0 ламає GTSAM silently — важко дебажити

5. Пріоритети на 2–3 тижні

Тиждень 1

  • Зафіксувати numpy==1.26.4 в pyproject.toml
  • Перевірити FC processor (H743 vs F405)
  • Перевірити поточний IMU rate по MAVLink
  • Prototype cuVSLAM Mono-Depth з барометром як synthetic depth
  • Запустити aero-vloc на наших nadir кадрах

Тиждень 2

  • cuVSLAM Mono-Depth інтеграція в E2EHarness
  • Порівняти ATE: ORB (поточний baseline) vs cuVSLAM Mono-Depth
  • AnyLoc offline setup + перший тест на satellite tiles

Тиждень 3

  • XFeat TRT export для satellite matching (окремий трек від VO)
  • MAVLink GPS_INPUT injection тест на SITL (Software-in-the-Loop)
  • Визначити чи варто піднімати IMU rate для майбутнього Mono-Inertial

6. Аналоги нашої системи

Для розуміння де ми знаходимось відносно SOTA:

Система VO Fusion Scale Статус
Наша cuVSLAM Mono ESKF Барометр Sprint 1
VINS-Fusion Mono-Inertial Factor graph IMU Open-source, ROS
OpenVINS MSCKF Mono EKF IMU Open-source, ~0.08м EuRoC
PX4 EKF2 UKF GPS Вбудований в PX4
ArduPilot EKF3 EKF GPS Вбудований в ArduPilot

Наша архітектура унікальна тим що замінює GPS через Place Recognition (satellite matching) — не просто VIO, а VIO + global anchor. Це правильний підхід для тривалих маршрутів.


7. Відкриті питання

  1. Якість cuVSLAM Mono-Depth на feature-poor nadir terrain (рівне поле, ліс) — потребує льотних тестів
  2. Частота та надійність GPR match в реальних умовах України
  3. Чи достатньо барометра для scale recovery при різких змінах висоти (маневри, вітер)
  4. Перехід на Stereo-Inertial (hardware) — коли і чи потрібен взагалі