mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-23 01:26:37 +00:00
docs(tech-audit): expand design doc with reconciliation, risk budget, aero-vloc plan, SITL decomposition
Adds: solution.md reconciliation (cuVSLAM Inertial→Mono-Depth gap), migration steps through e2e harness, risk budget decision tree, aero-vloc benchmark action plan with pass/fail criteria, and SITL GPS_INPUT test decomposition with MAVProxy reference. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,178 +2,358 @@
|
|||||||
**Дата:** 2026-04-18
|
**Дата:** 2026-04-18
|
||||||
**Горизонт:** 2–3 тижні (sprint 1)
|
**Горизонт:** 2–3 тижні (sprint 1)
|
||||||
**Контекст:** Fixed-wing БПЛА, Jetson Orin Nano Super, nadir камера ADTI 20L V1, ArduPilot FC
|
**Контекст:** Fixed-wing БПЛА, Jetson Orin Nano Super, nadir камера ADTI 20L V1, ArduPilot FC
|
||||||
|
**Regression guard:** 196 passed / 8 skipped (non-e2e). EuRoC ESKF ATE baseline ~0.205 м (100 кадрів).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Архітектурний розрив — головна знахідка
|
## 0. Reconciliation: три джерела
|
||||||
|
|
||||||
### Проблема з cuVSLAM Inertial mode
|
Цей документ синтезує три джерела і де вони суперечать одне одному — фіксує явно.
|
||||||
|
|
||||||
Поточна архітектура планує cuVSLAM у режимі "Inertial" (з IMU). Але:
|
| Джерело | Ключове твердження | Статус |
|
||||||
|
|---|---|---|
|
||||||
|
| `solution.md` | cuVSLAM **Inertial mode** з IMU @200 Hz | ⚠️ Архітектурна помилка — Inertial потребує stereo |
|
||||||
|
| `stage2_ideas/cross_view_place_recognition_stack.md` | SP+LG+FAISS для satellite matching | ✅ Backlog сам каже "порівняй з AnyLoc першим" |
|
||||||
|
| Ресерч (2026-04-18) | cuVSLAM Mono-Depth + barometer; DINOv2-VLAD як baseline GPR | ✅ Консистентний з stage2 backlog |
|
||||||
|
|
||||||
- cuVSLAM Inertial/Visual-Inertial mode потребує **стерео камеру** (дві камери поряд, як очі)
|
**Що НЕ робимо зараз:** переписувати `solution.md`. Це окрема задача з `next_steps.md` ("Аудит відповідності солюшну"). Цей план — migration поверх існуючого ORB baseline, не greenfield.
|
||||||
- У нас одна nadir камера — Mono режим
|
|
||||||
- cuVSLAM Mono дає лише кут повороту, **без metric scale** (без відстані)
|
|
||||||
- Без scale неможливо побудувати GPS_INPUT — це useless для ArduPilot
|
|
||||||
|
|
||||||
**Важливо:** камера пілота (вперед) + nadir камера (вниз) — це не stereo. Stereo = дві камери в одному напрямку на відстані 10–20 см.
|
**Що змінюємо:** фіксуємо cuVSLAM Mono-Depth як sprint 1 production VO (замість Inertial який фізично неможливий без stereo). GPR: AnyLoc як sprint 1 baseline, SP+LG — stage 2 evaluation (консистентно з backlog).
|
||||||
|
|
||||||
### Чому це не критично для sprint 1
|
|
||||||
|
|
||||||
Scale для nadir камери над рівною місцевістю — **детермінований**:
|
|
||||||
|
|
||||||
```
|
|
||||||
scale = altitude / focal_length
|
|
||||||
```
|
|
||||||
|
|
||||||
Барометр дає висоту → ESKF рахує scale → VO потребує лише точний 2D planar tracking. Це і є перший шлях.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Вибрана архітектура (sprint 1)
|
## 1. Архітектурний розрив
|
||||||
|
|
||||||
### VO: cuVSLAM Mono-Depth + барометр
|
### cuVSLAM Inertial mode потребує stereo — у нас mono
|
||||||
|
|
||||||
**Рішення:** cuVSLAM Mono-Depth режим, де барометрична висота подається як synthetic depth для відновлення metric scale.
|
`solution.md` планує cuVSLAM Inertial mode. Але:
|
||||||
|
|
||||||
**Точність між GPR корекціями:** ~0.3–0.5 м
|
- cuVSLAM Visual-Inertial = **stereo камера обов'язкова**. Mono-Inertial режиму не існує у v15.
|
||||||
**Drift на маршруті:** обмежений — GPR скидає накопичену похибку
|
- cuVSLAM Mono дає лише rotation, без metric scale → неможливо побудувати GPS_INPUT.
|
||||||
|
- Camera пілота (вперед) + nadir камера (вниз) ≠ stereo (stereo = дві камери в одному напрямку, ∆x = 10–20 см).
|
||||||
|
|
||||||
### Чому drift не критичний
|
**Рішення для sprint 1:** cuVSLAM **Mono-Depth** — барометрична висота подається як synthetic depth, відновлює metric scale.
|
||||||
|
|
||||||
Архітектура має три рівні корекції:
|
Scale для nadir над рівною місцевістю детермінований: `scale = altitude / focal_length`. Барометр → ESKF → scale. VO потребує лише точний 2D planar tracking.
|
||||||
|
|
||||||
|
### Чому drift на маршруті не критичний
|
||||||
|
|
||||||
```
|
```
|
||||||
VO (drift між кадрами)
|
VO drift між кадрами (~0.3–0.5 м на сотні метрів)
|
||||||
↓
|
↓
|
||||||
ESKF ← IMU (короткострокова стабілізація, ~ms)
|
ESKF + IMU (короткострокова стабілізація, ~мс)
|
||||||
↓
|
↓
|
||||||
Place Recognition ← satellite tiles (глобальна корекція, ~сотні метрів)
|
Place Recognition ← satellite tiles (глобальна корекція кожні ~500 м)
|
||||||
↓
|
↓
|
||||||
GTSAM loop closure (довгострокова консистентність)
|
GTSAM loop closure (stage 2)
|
||||||
```
|
```
|
||||||
|
|
||||||
Якщо GPR впізнає місцевість кожні ~500 м → загальна похибка на 10 км маршруту: **1–5 м**. Це прийнятно для GPS-denied.
|
GPR скидає накопичений drift → загальна похибка на 10 км маршруту: **1–5 м**. Прийнятно для GPS-denied.
|
||||||
|
|
||||||
**Ризик GPR:** не спрацює при хмарах, однорідній місцевості (поле без орієнтирів), застарілих тайлах. В цих випадках drift накопичується до наступного успішного match.
|
**Ризик GPR:** хмари, однорідна місцевість (поле, ліс), застарілі тайли → drift накопичується до наступного match. Це відоме обмеження, не сюрприз.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Технологічний стек — рішення по шарах
|
## 2. Рішення по шарах стеку
|
||||||
|
|
||||||
### VO Layer
|
### 2.1 Visual Odometry
|
||||||
|
|
||||||
| Компонент | Dev/CI | Production (Jetson) | Статус |
|
| Компонент | Dev/CI | Production (Jetson) | Рішення |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| **Visual Odometry** | ORBVisualOdometry (OpenCV) | cuVSLAM Mono-Depth | Залишаємо, фіксуємо Mono-Depth |
|
| **VO backend** | ORBVisualOdometry (OpenCV) | cuVSLAM **Mono-Depth** | Фіксуємо Mono-Depth замість Inertial |
|
||||||
| **XFeat** | — | Satellite tile matching (майбутнє) | Не VO fallback, окремий трек |
|
| **SuperPoint+LightGlue** | — | — | ❌ Відхилено для VO: 15–33× повільніше cuVSLAM, немає IMU fusion |
|
||||||
| **SuperPoint+LightGlue** | — | — | Відхилено: 15–33× повільніше за cuVSLAM |
|
| **XFeat** | — | Satellite tile matching | Не VO fallback — окремий трек (§2.3) |
|
||||||
|
|
||||||
**Відхилені альтернативи:**
|
**Відхилені альтернативи для sprint 1:**
|
||||||
- ORB-SLAM3 Mono-Inertial (~0.08 м) — потребує IMU ≥100 Hz по MAVLink. Типово ArduPilot шле 50 Hz (SR*_RAW_SENS). Можна підняти до 200 Hz зміною одного параметра, але не пріоритет зараз.
|
- **ORB-SLAM3 Mono-Inertial** (~0.08 м EuRoC) — потребує IMU ≥100 Hz по MAVLink. ArduPilot за замовчуванням шле 50 Hz. Можливо після підняття `SR*_RAW_SENS`, але не пріоритет.
|
||||||
- cuVSLAM Stereo-Inertial (0.054 м) — потребує hardware зміни (друга камера). Довгостроково.
|
- **cuVSLAM Stereo-Inertial** (0.054 м) — потребує hardware (друга камера). Довгострокова ціль.
|
||||||
|
|
||||||
### ESKF
|
### 2.2 ESKF
|
||||||
|
|
||||||
| Рішення | Обґрунтування |
|
| Рішення | Обґрунтування |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Залишаємо numpy 15-state ESKF | IMU preintegration не критичний на 5–10 Hz VO для повільного fixed-wing |
|
| Залишаємо numpy 15-state ESKF | Достатній для 5–10 Hz VO на повільному fixed-wing |
|
||||||
| **Пінити `numpy==1.26.4`** | NumPy 2.0 ламає GTSAM Python bindings (issue #2264) — критично |
|
| **Пінити `numpy==1.26.4`** | NumPy 2.0 ламає GTSAM Python bindings silently (issue #2264) |
|
||||||
| `manifpy` — опційно | pip-installable Lie group math, додати тільки якщо знайдемо баги в quaternion коді |
|
| `manifpy` — тільки якщо знайдемо quaternion баги | pip-installable, не додаємо превентивно |
|
||||||
|
| IMU preintegration | Не потрібен на 5–10 Hz — step-by-step propagation еквівалентний |
|
||||||
|
|
||||||
### Factor Graph (GTSAM)
|
### 2.3 Place Recognition
|
||||||
|
|
||||||
**Рішення sprint 1: пропустити GTSAM, використовувати ESKF.**
|
**Поточний стан:** MockInferenceEngine (dev), Faiss numpy fallback. Реального GPR ще немає.
|
||||||
|
|
||||||
ESKF достатній для Gaussian GPS_INPUT 5–10 Hz. Factor graph дає перевагу (~15 vs 34 см) лише при non-Gaussian noise з outliers — не наш сценарій зараз.
|
**Sprint 1 baseline:** AnyLoc-VLAD-DINOv2 (offline-capable).
|
||||||
|
|
||||||
Коли повернутись: **GTSAM 4.2 stable** (не 4.3a1 alpha). miniSAM — стейл з 2019, g2o Python — experimental. Єдиний живий варіант.
|
|
||||||
|
|
||||||
### Place Recognition
|
|
||||||
|
|
||||||
| Компонент | Рішення | Обґрунтування |
|
| Компонент | Рішення | Обґрунтування |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **Descriptor** | DINOv2-VLAD (AnyLoc) | 10–12 мс TRT FP16 на Jetson, offline-capable |
|
| **Global descriptor** | DINOv2-VLAD (AnyLoc) | 10–12 мс TRT FP16 на Jetson, offline |
|
||||||
|
| **Local matching** | XFeat (satellite↔UAV frame) | ~50–100 мс TRT, cross-view gap краще ніж ORB |
|
||||||
| **Index** | Faiss GPU | Залишаємо |
|
| **Index** | Faiss GPU | Залишаємо |
|
||||||
| **INT8 квантизація** | ❌ Не робити | Broken для ViT на Jetson (NVIDIA/TRT#4348, dinov2#489) |
|
| **INT8 quantization** | ❌ Не робити | 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 |
|
||||||
| **NetVLAD** | ❌ Deprecated | DINOv2-VLAD краще на 2.4% R@1 (MSLS 2024) |
|
| **Satellite tiles** | MapTiler offline MBTiles | Zoom 18 (0.6 м/px), Україна, JPEG offline |
|
||||||
| **Satellite tiles** | MapTiler offline MBTiles | Україна zoom 0–13, JPEG, offline |
|
|
||||||
|
|
||||||
**Перевірити:** [aero-vloc](https://github.com/prime-slam/aero-vloc) — benchmark на aerial nadir imagery до того як фіксувати Faiss index дизайн.
|
**Stage 2 evaluation (не зараз):** SuperPoint+LightGlue+FAISS (з `stage2_ideas/`) — backlog сам каже порівняти з AnyLoc першим. Ця оцінка відбудеться після того як AnyLoc baseline зафіксований і виміряний.
|
||||||
|
|
||||||
### MAVLink / ArduPilot
|
**Довгострокова ціль:** EigenPlaces (ICCV 2023) — кращий ONNX export, viewpoint-robust.
|
||||||
|
|
||||||
|
### 2.4 Factor Graph (GTSAM)
|
||||||
|
|
||||||
|
**Sprint 1: пропускаємо.** ESKF достатній для Gaussian GPS_INPUT 5–10 Hz.
|
||||||
|
|
||||||
|
FGO дає перевагу (~15 vs 34 см) лише при non-Gaussian noise з outliers. Коли прийде час — GTSAM 4.2 stable (не 4.3a1 alpha). miniSAM стейл з 2019. g2o Python experimental.
|
||||||
|
|
||||||
|
### 2.5 MAVLink / ArduPilot
|
||||||
|
|
||||||
| Рішення | Обґрунтування |
|
| Рішення | Обґрунтування |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **pymavlink** залишаємо | MAVSDK-Python не підтримує GPS_INPUT (PX4-first) |
|
| **pymavlink** залишаємо | MAVSDK-Python не підтримує GPS_INPUT (PX4-first) |
|
||||||
| Reference impl | `MAVProxy/modules/mavproxy_GPSInput.py` — точне кодування GPS_INPUT (#232) |
|
| Reference: `MAVProxy/modules/mavproxy_GPSInput.py` | Точне кодування GPS_INPUT #232: lat/lon ×1e7, alt мм, vel см/с |
|
||||||
| Частота injection | 5–10 Hz (не 20 Hz — timing jitter при вищих rate) |
|
| Injection rate: 5–10 Hz | Не 20 Hz — timing jitter задокументований при вищих rate |
|
||||||
| Yaw extension field | Не використовувати — ArduPilot 4.x ігнорує |
|
| Yaw extension field | Не використовувати — ArduPilot 4.x ігнорує |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Критичні перевірки перед кодом
|
## 3. Міграційний план через e2e-харнес
|
||||||
|
|
||||||
Три речі, які треба знати до того як писати будь-який код:
|
**Принцип:** кожна зміна VO backend проходить через E2EHarness до merge. Поточний regression guard — 196 passed / 8 skipped. EuRoC ESKF RMSE ceiling = 0.5 м (2× від baseline ~0.205 м).
|
||||||
|
|
||||||
### 4.1 Процесор Flight Controller
|
### Крок 0 — стабілізація baseline (тиждень 1, день 1–2)
|
||||||
- **H743** — підтримує GPS_INPUT over serial ✅
|
|
||||||
- **F405** — мовчки ігнорує GPS_INPUT ❌ (втрата днів на дебаг)
|
|
||||||
- Перевірити: Mission Planner → Help → About (показує назву FC), або питати у постачальника дрона
|
|
||||||
|
|
||||||
### 4.2 IMU rate по MAVLink
|
```bash
|
||||||
- За замовчуванням ArduPilot: **50 Hz**
|
# Зафіксувати numpy
|
||||||
- Для ORB-SLAM3 Mono-Inertial потрібно: **≥100 Hz**
|
pip install numpy==1.26.4
|
||||||
- Параметр для зміни: `SR2_RAW_SENS` (або SR0/SR1 залежно від порту)
|
# Записати в pyproject.toml: numpy>=1.24,<2.0
|
||||||
- Для sprint 1 (cuVSLAM Mono-Depth) — не критично
|
|
||||||
|
|
||||||
### 4.3 numpy версія
|
# Верифікувати що baseline не зламався
|
||||||
- Зафіксувати `numpy==1.26.4` в `pyproject.toml` негайно
|
pytest tests/ -x --ignore=tests/e2e -q # має бути 196 passed
|
||||||
- NumPy 2.0 ламає GTSAM silently — важко дебажити
|
pytest tests/e2e/test_euroc.py -v --dataset-path ./datasets/euroc # ATE ~0.205 м
|
||||||
|
```
|
||||||
|
|
||||||
|
**Gate:** якщо ATE після numpy pin відхиляється > 5% від 0.205 м → зупинитись і дебажити до merge.
|
||||||
|
|
||||||
|
### Крок 1 — cuVSLAM Mono-Depth adapter (тиждень 1, день 3–5)
|
||||||
|
|
||||||
|
1. Додати `CuVSLAMMonoDepthVisualOdometry` backend у `src/gps_denied/core/vo.py`
|
||||||
|
2. Приймає барометричну висоту як `depth_hint_m` параметр
|
||||||
|
3. Mock реалізація для dev/CI (повертає scale-corrected RelativePose)
|
||||||
|
4. Запустити e2e на EuRoC: порівняти ATE з ORB baseline
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pytest tests/e2e/test_euroc.py -v -k "cuvslam_mono_depth"
|
||||||
|
# Записати результат в docs/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Gate:** ATE cuVSLAM Mono-Depth має бути ≤ 0.5 м (поточний ceiling). Якщо гірше → див. Risk Budget (§4).
|
||||||
|
|
||||||
|
### Крок 2 — AnyLoc GPR integration (тиждень 2)
|
||||||
|
|
||||||
|
1. Реалізувати `AnyLocGPR` клас що замінює MockInferenceEngine
|
||||||
|
2. Offline DINOv2-VLAD descriptor, Faiss index на test tile set
|
||||||
|
3. e2e на VPAIR sample (є satellite-like tiles): перевірити GPR hit rate
|
||||||
|
4. EuRoC: GPS-estimate ATE залишиться xfail (indoor, немає реальних тайлів — ок)
|
||||||
|
|
||||||
|
### Крок 3 — SITL MAVLink integration (тиждень 3)
|
||||||
|
|
||||||
|
Деталі в §6.
|
||||||
|
|
||||||
|
### Крок 4 — aero-vloc benchmark (тиждень 2–3, паралельно)
|
||||||
|
|
||||||
|
Деталі в §5.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Пріоритети на 2–3 тижні
|
## 4. Risk Budget: якщо cuVSLAM Mono-Depth гірше ніж ORB
|
||||||
|
|
||||||
### Тиждень 1
|
**Сценарій:** cuVSLAM Mono-Depth на EuRoC дає ATE > 0.205 м (поточний ORB baseline).
|
||||||
- [ ] Зафіксувати `numpy==1.26.4` в pyproject.toml
|
|
||||||
- [ ] Перевірити FC processor (H743 vs F405)
|
|
||||||
- [ ] Перевірити поточний IMU rate по MAVLink
|
|
||||||
- [ ] Prototype cuVSLAM Mono-Depth з барометром як synthetic depth
|
|
||||||
- [ ] Запустити aero-vloc на наших nadir кадрах
|
|
||||||
|
|
||||||
### Тиждень 2
|
Це **очікувано і не є блокером** — EuRoC indoor ≠ наш production сценарій (outdoor nadir, відома висота). Але потрібне рішення.
|
||||||
- [ ] 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
|
cuVSLAM Mono-Depth ATE на EuRoC
|
||||||
|
│
|
||||||
|
├─ ≤ 0.205 м (краще або рівно ORB)
|
||||||
|
│ → ✅ Merge, продовжуємо
|
||||||
|
│
|
||||||
|
├─ 0.205–0.5 м (гірше ніж ORB але в межах ceiling)
|
||||||
|
│ → ⚠️ Прийнятно для sprint 1 — EuRoC не є target dataset
|
||||||
|
│ → Записати в docs, відкрити тікет для наступного кроку
|
||||||
|
│ → Продовжуємо, але плануємо IMU rate upgrade
|
||||||
|
│
|
||||||
|
└─ > 0.5 м (перевищує ceiling)
|
||||||
|
→ Три варіанти:
|
||||||
|
│
|
||||||
|
├─ A) Тюнінг depth_hint scaling (барометр calibration)
|
||||||
|
│ Тривалість: 1 день
|
||||||
|
│ Спробуй першим — часто проблема в неправильному scale factor
|
||||||
|
│
|
||||||
|
├─ B) Підняти IMU rate → 200 Hz (SR*_RAW_SENS)
|
||||||
|
│ + перейти на ORB-SLAM3 Mono-Inertial (~0.08 м EuRoC)
|
||||||
|
│ Тривалість: 3–5 днів (C++ build + Python binding)
|
||||||
|
│ Потрібно: підтвердити FC має H743, перевірити UART bandwidth
|
||||||
|
│
|
||||||
|
└─ C) Залишити ORB як production VO тимчасово
|
||||||
|
+ зосередитись на GPR (AnyLoc) як основному correction механізмі
|
||||||
|
Тривалість: 0 (нічого не міняємо у VO)
|
||||||
|
Прийнятно якщо GPR hits кожні ≤ 500 м
|
||||||
|
```
|
||||||
|
|
||||||
|
**Важливо:** EuRoC MH_01 — indoor MAV з forward camera. cuVSLAM Mono-Depth оптимізований для outdoor nadir. Поганий ATE на EuRoC ≠ поганий ATE на реальному польоті. Льотні тести є остаточним арбітром.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Аналоги нашої системи
|
## 5. aero-vloc benchmark — що робити з результатами
|
||||||
|
|
||||||
Для розуміння де ми знаходимось відносно SOTA:
|
[aero-vloc](https://github.com/prime-slam/aero-vloc) — benchmark framework для aerial visual localization. Запускається на UAV↔satellite парах.
|
||||||
|
|
||||||
| Система | VO | Fusion | Scale | Статус |
|
### Навіщо
|
||||||
|
|
||||||
|
До того як фіксувати дизайн Faiss index (tile size, descriptor dim, retrieval strategy) — треба знати реальні числа для нашого типу зображень: nadir, fixed-wing altitude, Ukrainian terrain.
|
||||||
|
|
||||||
|
### Що запустити
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/prime-slam/aero-vloc
|
||||||
|
cd aero-vloc
|
||||||
|
|
||||||
|
# 1. Підготувати пари: UAV кадри з наших SRT/відео + відповідні MapTiler тайли
|
||||||
|
# 2. Запустити benchmark з кількома дескрипторами:
|
||||||
|
python benchmark.py --query ./our_nadir_frames/ \
|
||||||
|
--database ./satellite_tiles/ \
|
||||||
|
--descriptors netvlad dinov2_vlad eigenplaces \
|
||||||
|
--top-k 5
|
||||||
|
|
||||||
|
# 3. Записати R@1, R@5, медіанна помилка локалізації в метрах
|
||||||
|
```
|
||||||
|
|
||||||
|
### Що зробити з результатами
|
||||||
|
|
||||||
|
| Результат | Дія |
|
||||||
|
|---|---|
|
||||||
|
| DINOv2-VLAD R@1 ≥ 60% | ✅ Підтверджує AnyLoc як sprint 1 baseline |
|
||||||
|
| DINOv2-VLAD R@1 < 40% | ⚠️ Перевірити domain gap — можливо треба fine-tuning або EigenPlaces |
|
||||||
|
| EigenPlaces > DINOv2-VLAD на ≥10% R@1 | Прискорити перехід на EigenPlaces (з stage 2 → sprint 2) |
|
||||||
|
| Медіанна помилка > 50 м | Проблема з tile resolution або GSD mismatch → перевірити zoom level |
|
||||||
|
| Медіанна помилка ≤ 20 м | ✅ Відповідає `solution.md` цілі `<20 м absolute anchor` |
|
||||||
|
|
||||||
|
**Результати зберегти в:** `_docs/00_research/oss_stack_options/aero_vloc_results.md`
|
||||||
|
**Використати для:** фіналізації Faiss index design (tile size, overlap, descriptor dim) перед реалізацією AnyLocGPR.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. SITL Integration Test Plan
|
||||||
|
|
||||||
|
SITL (Software-In-The-Loop) = ArduPilot запущений як симулятор, приймає GPS_INPUT від нашої системи через MAVLink без реального hardware.
|
||||||
|
|
||||||
|
### Налаштування SITL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Запустити ArduPilot SITL (потрібен окремий binary або Docker)
|
||||||
|
sim_vehicle.py -v ArduPlane --console --map
|
||||||
|
|
||||||
|
# Параметри ArduPilot для GPS_INPUT:
|
||||||
|
# GPS1_TYPE = 14 (MAVLink)
|
||||||
|
# GPS_RATE_MS = 200 (5 Hz мінімум)
|
||||||
|
# EK3_SRC1_POSXY = 1, EK3_SRC1_VELXY = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Декомпозиція тестів
|
||||||
|
|
||||||
|
Тест 1 — **Field encoding** (unit, без SITL):
|
||||||
|
```python
|
||||||
|
# Верифікувати кодування полів за MAVProxy reference:
|
||||||
|
# MAVProxy/modules/mavproxy_GPSInput.py
|
||||||
|
def test_gps_input_field_encoding():
|
||||||
|
msg = build_gps_input(lat=48.123, lon=37.456, alt_m=600.0,
|
||||||
|
vn=10.0, ve=5.0, vd=0.0,
|
||||||
|
h_acc=15.0, v_acc=8.0, fix_type=3)
|
||||||
|
assert msg.lat == int(48.123 * 1e7) # lat ×1e7
|
||||||
|
assert msg.lon == int(37.456 * 1e7) # lon ×1e7
|
||||||
|
assert msg.alt == int(600.0 * 1000) # alt мм
|
||||||
|
assert msg.vn == int(10.0 * 100) # vel см/с
|
||||||
|
assert msg.satellites_visible == 10 # synthetic, prevent failsafe
|
||||||
|
assert msg.fix_type == 3
|
||||||
|
```
|
||||||
|
|
||||||
|
Тест 2 — **Rate delivery** (з реальним pymavlink, mock SITL endpoint):
|
||||||
|
```python
|
||||||
|
# Верифікувати що GPS_INPUT виходить на 5–10 Hz без jitter > ±20 мс
|
||||||
|
def test_gps_input_rate_5hz():
|
||||||
|
timestamps = collect_gps_input_timestamps(duration_s=10)
|
||||||
|
intervals = np.diff(timestamps)
|
||||||
|
assert np.mean(intervals) == pytest.approx(0.2, abs=0.02) # 5 Hz ±10%
|
||||||
|
assert np.max(intervals) < 0.25 # жоден interval не > 250 мс
|
||||||
|
```
|
||||||
|
|
||||||
|
Тест 3 — **Confidence tier transitions** (вже є в `test_sitl_integration.py`, розширити):
|
||||||
|
```python
|
||||||
|
# HIGH → MEDIUM → LOW → FAILED transitions
|
||||||
|
# Верифікувати fix_type і horiz_accuracy змінюються коректно
|
||||||
|
# Вже: test_reloc_request_after_3_failures_with_sitl
|
||||||
|
# Додати: test_fix_type_degrades_without_satellite_match
|
||||||
|
```
|
||||||
|
|
||||||
|
Тест 4 — **ArduPilot EKF acceptance** (повний SITL):
|
||||||
|
```python
|
||||||
|
# Запустити справжній SITL, подати GPS_INPUT, перевірити що EKF приймає
|
||||||
|
# Метрика: GLOBAL_POSITION_INT від SITL відповідає нашому GPS_INPUT з похибкою < 5 м
|
||||||
|
# Це верифікує що ArduPilot не відкидає наші повідомлення (наприклад через fix_type=0)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reference implementation
|
||||||
|
|
||||||
|
Взяти за основу `MAVProxy/modules/mavproxy_GPSInput.py`:
|
||||||
|
- Точне кодування всіх 15+ полів GPS_INPUT (#232)
|
||||||
|
- Обробка GPS time (Unix → GPS epoch, leap seconds)
|
||||||
|
- hdop/vdop synthetic values
|
||||||
|
|
||||||
|
**Зауваження щодо FC процесора:** H743 приймає GPS_INPUT over UART. F405 — мовчки ігнорує. Перевірити до льотних тестів.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Критичні перевірки перед кодом
|
||||||
|
|
||||||
|
### 7.1 numpy pin — негайно
|
||||||
|
```toml
|
||||||
|
# pyproject.toml
|
||||||
|
dependencies = [
|
||||||
|
"numpy>=1.24,<2.0", # NumPy 2.0 ламає GTSAM bindings (issue #2264)
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 Flight Controller processor
|
||||||
|
- **H743** → GPS_INPUT over serial ✅
|
||||||
|
- **F405** → мовчки ігнорує GPS_INPUT ❌
|
||||||
|
- Перевірити: Mission Planner → Help → About, або питати постачальника
|
||||||
|
|
||||||
|
### 7.3 IMU rate по MAVLink
|
||||||
|
- Default ArduPilot: **50 Hz**
|
||||||
|
- Для ORB-SLAM3 Mono-Inertial (майбутнє): **≥100 Hz**
|
||||||
|
- Змінити: `SR2_RAW_SENS = 10` (×10 → 100 Hz) або `= 20` (200 Hz)
|
||||||
|
- Sprint 1 (cuVSLAM Mono-Depth): не критично, але виміряти поточне значення
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Аналоги системи
|
||||||
|
|
||||||
|
| Система | VO | Scale source | Fusion | Satellite anchor |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| **Наша** | cuVSLAM Mono | ESKF | Барометр | Sprint 1 |
|
| **Наша (sprint 1)** | cuVSLAM Mono-Depth | Барометр | ESKF | DINOv2-VLAD+Faiss |
|
||||||
| **VINS-Fusion** | Mono-Inertial | Factor graph | IMU | Open-source, ROS |
|
| **Наша (stage 2)** | cuVSLAM Stereo-Inertial | IMU | ESKF+GTSAM | SP+LG+Faiss |
|
||||||
| **OpenVINS** | MSCKF Mono | EKF | IMU | Open-source, ~0.08м EuRoC |
|
| **VINS-Fusion** | Mono-Inertial | IMU | Factor graph | Немає |
|
||||||
| **PX4 EKF2** | — | UKF | GPS | Вбудований в PX4 |
|
| **OpenVINS** | MSCKF Mono | IMU | EKF | Немає |
|
||||||
| **ArduPilot EKF3** | — | EKF | GPS | Вбудований в ArduPilot |
|
| **ArduPilot EKF3** | — | GPS | EKF | GPS (не satellite matching) |
|
||||||
|
|
||||||
Наша архітектура унікальна тим що **замінює GPS через Place Recognition** (satellite matching) — не просто VIO, а VIO + global anchor. Це правильний підхід для тривалих маршрутів.
|
Унікальність нашої архітектури: **VIO + global satellite anchor** без GPS. Не просто odometry — прив'язка до карти в реальному часі.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Відкриті питання
|
## 9. Відкриті питання
|
||||||
|
|
||||||
1. Якість cuVSLAM Mono-Depth на feature-poor nadir terrain (рівне поле, ліс) — потребує льотних тестів
|
1. Якість cuVSLAM Mono-Depth на feature-poor nadir terrain (рівне поле, ліс) — тільки льотні тести відповідять
|
||||||
2. Частота та надійність GPR match в реальних умовах України
|
2. aero-vloc покаже реальний R@1 для DINOv2-VLAD на нашому типі зображень
|
||||||
3. Чи достатньо барометра для scale recovery при різких змінах висоти (маневри, вітер)
|
3. FC processor: H743 чи F405? — блокер для SITL тестів
|
||||||
4. Перехід на Stereo-Inertial (hardware) — коли і чи потрібен взагалі
|
4. IMU rate: скільки зараз по MAVLink? — вплине на roadmap VO upgrade
|
||||||
|
5. MapTiler MBTiles для України: ліцензія дозволяє offline onboard deployment?
|
||||||
|
|||||||
Reference in New Issue
Block a user