mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-22 21:46:36 +00:00
884 lines
72 KiB
Markdown
884 lines
72 KiB
Markdown
# ASTRAL-Next System Flows
|
||
|
||
> **See also**: [System Flow Diagrams (Mermaid)](./system_flows_diagrams.md) for interactive visual diagrams.
|
||
|
||
## System Overview
|
||
|
||
ASTRAL-Next is a GPS-denied UAV visual localization system using tri-layer matching (SuperPoint+LightGlue for VO, DINOv2 for place recognition, LiteSAM for cross-view matching) with an Atlas-style multi-map chunk architecture for robust tracking and recovery.
|
||
|
||
## Components Summary
|
||
|
||
| ID | Component | Interface | Purpose |
|
||
|----|-----------|-----------|---------|
|
||
| F01 | Flight API | `IFlightAPI` | REST endpoints, SSE streaming |
|
||
| F02 | Flight Processor | `IFlightProcessor` | Central coordinator, processing loop |
|
||
| F03 | Flight Database | `IFlightDatabase` | Persistence layer |
|
||
| F04 | Satellite Data Manager | `ISatelliteDataManager` | Tile fetching, caching, progressive search |
|
||
| F05 | Image Input Pipeline | `IImageInputPipeline` | Image ingestion, validation, storage |
|
||
| F06 | Image Rotation Manager | `IImageRotationManager` | Rotation sweeps, heading tracking |
|
||
| F07 | Sequential Visual Odometry | `ISequentialVisualOdometry` | Frame-to-frame VO (SuperPoint+LightGlue) |
|
||
| F08 | Global Place Recognition | `IGlobalPlaceRecognition` | Coarse localization (DINOv2+VLAD) |
|
||
| F09 | Metric Refinement | `IMetricRefinement` | Precise alignment (LiteSAM) |
|
||
| F10 | Factor Graph Optimizer | `IFactorGraphOptimizer` | GTSAM-based trajectory optimization |
|
||
| F11 | Failure Recovery Coordinator | `IFailureRecoveryCoordinator` | Recovery orchestration, chunk matching |
|
||
| F12 | Route Chunk Manager | `IRouteChunkManager` | Chunk lifecycle management |
|
||
| F13 | Coordinate Transformer | `ICoordinateTransformer` | Coordinate conversions (GPS↔ENU↔Pixel) |
|
||
| F14 | Result Manager | `IResultManager` | Result tracking and publishing |
|
||
| F15 | SSE Event Streamer | `ISSEEventStreamer` | Real-time event streaming |
|
||
| F16 | Model Manager | `IModelManager` | ML model loading (TensorRT/ONNX) |
|
||
| F17 | Configuration Manager | `IConfigurationManager` | System configuration |
|
||
|
||
### Helper Components
|
||
|
||
| ID | Helper | Interface | Purpose |
|
||
|----|--------|-----------|---------|
|
||
| H01 | Camera Model | `ICameraModel` | Projection/unprojection |
|
||
| H02 | GSD Calculator | `IGSDCalculator` | Ground sampling distance |
|
||
| H03 | Robust Kernels | `IRobustKernels` | Huber/Cauchy loss functions |
|
||
| H04 | Faiss Index Manager | `IFaissIndexManager` | Similarity search |
|
||
| H05 | Performance Monitor | `IPerformanceMonitor` | Timing measurements |
|
||
| H06 | Web Mercator Utils | `IWebMercatorUtils` | Tile coordinate calculations |
|
||
| H07 | Image Rotation Utils | `IImageRotationUtils` | Image rotation operations |
|
||
| H08 | Batch Validator | `IBatchValidator` | Image batch validation |
|
||
|
||
---
|
||
|
||
## Flow 1: System Initialization
|
||
|
||
**Purpose**: Initialize all system components on startup.
|
||
|
||
**Sequence**:
|
||
```
|
||
┌─────────────────┐
|
||
│ System Start │
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F17 load_config │ ← Load system configuration
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F03 Initialize │ ← Establish DB connection pool
|
||
│ connections │
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────────────────────────────┐
|
||
│ F16 load_model() × 4 │
|
||
│ ├─ SuperPoint (feature extraction) │
|
||
│ ├─ LightGlue (feature matching) │
|
||
│ ├─ DINOv2 (place recognition) │
|
||
│ └─ LiteSAM (cross-view matching) │
|
||
└────────┬────────────────────────────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│F04 Initialize │ ← Initialize tile cache
|
||
│ cache │
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────────────────────────────┐
|
||
│ F08 load_index() │
|
||
│ ← Load pre-built Faiss index from │
|
||
│ satellite provider │
|
||
└────────┬────────────────────────────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F12 Initialize │ ← Initialize chunk state tracking
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F02 Ready │ ← Ready to accept flights
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F01 Start │ ← Start FastAPI/Uvicorn
|
||
│ server │
|
||
└─────────────────┘
|
||
```
|
||
|
||
**Duration**: ~30 seconds (dominated by model loading)
|
||
|
||
---
|
||
|
||
## Flow 2: Flight Creation
|
||
|
||
**Purpose**: Create a new flight with initial configuration and prefetch satellite data.
|
||
|
||
**Trigger**: `POST /flights`
|
||
|
||
**Sequence**:
|
||
```
|
||
┌──────────┐ POST /flights ┌─────┐
|
||
│ Client │ ───────────────────► │ F01 │
|
||
└──────────┘ └──┬──┘
|
||
│ create_flight()
|
||
▼
|
||
┌─────────┐
|
||
│ F02 │ Flight Processor
|
||
└────┬────┘
|
||
┌────────────────────────┬─┴─┬────────────────────────┐
|
||
│ │ │ │
|
||
▼ │ ▼ ▼
|
||
┌───────────────┐ │ ┌───────────────┐ ┌───────────────┐
|
||
│F17 get_flight │ │ │F13 set_enu │ │F04 prefetch │
|
||
│ _config() │ │ │ _origin() │ │ _route │
|
||
└───────────────┘ │ └───────────────┘ │ _corridor() │
|
||
│ └───────┬───────┘
|
||
│ │
|
||
▼ ▼
|
||
┌─────────────┐ ┌─────────────────┐
|
||
│F03 insert │ │ Satellite │
|
||
│ _flight() │ │ Provider API │
|
||
└─────────────┘ │ GET tiles/batch │
|
||
└─────────────────┘
|
||
│
|
||
┌──────┴──────┐
|
||
│ F14 │
|
||
│create_stream│
|
||
└─────────────┘
|
||
│
|
||
┌──────┴──────┐
|
||
SSE Connection │ Client │
|
||
◄─────────────────────────────│ GET stream │
|
||
└─────────────┘
|
||
```
|
||
|
||
**Output**: `flight_id`, SSE stream established
|
||
|
||
---
|
||
|
||
## Flow 3: Image Upload
|
||
|
||
**Purpose**: Upload batch of UAV images for processing.
|
||
|
||
**Trigger**: `POST /flights/{flightId}/images/batch`
|
||
|
||
**Sequence**:
|
||
```
|
||
┌──────────┐ POST images/batch ┌─────┐
|
||
│ Client │ ──────────────────► │ F01 │
|
||
│ │ (10-50 images) └──┬──┘
|
||
└──────────┘ │ queue_batch()
|
||
▼
|
||
┌─────────────┐
|
||
│ F05 │ Image Input Pipeline
|
||
└──────┬──────┘
|
||
┌───────────────┼───────────────┐
|
||
▼ ▼ ▼
|
||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||
│H08 validate │ │ Store to │ │F03 save │
|
||
│ _batch() │ │ disk │ │ _image │
|
||
└─────────────┘ └─────────────┘ │ _metadata()│
|
||
└─────────────┘
|
||
```
|
||
|
||
**Validation Rules**:
|
||
- Batch size: 10-50 images
|
||
- Naming convention: ADxxxxxx.jpg
|
||
- Sequential numbering
|
||
- Image dimensions: 640×480 to 6252×4168
|
||
|
||
---
|
||
|
||
## Flow 4: Normal Frame Processing (Tracking Good)
|
||
|
||
**Purpose**: Process a single frame when tracking quality is good.
|
||
|
||
**Sequence**:
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────────────┐
|
||
│ F02 Flight Processor │
|
||
│ │
|
||
│ ┌─────────────┐ │
|
||
│ │ get_next │◄───────────────────────────────────────────────────────┐│
|
||
│ │ _image() │ ││
|
||
│ └──────┬──────┘ ││
|
||
│ │ F05 ││
|
||
│ ▼ ││
|
||
│ ┌─────────────────────────────────────────────────────────────┐ ││
|
||
│ │ get_active_chunk() via F12 │ ││
|
||
│ └──────────────────────────────┬──────────────────────────────┘ ││
|
||
│ ▼ ││
|
||
│ ┌─────────────────────────────────────────────────────────────┐ ││
|
||
│ │ requires_rotation_sweep()? via F06 │ ││
|
||
│ │ ├─ YES → Flow 5 (First Frame/Sharp Turn) │ ││
|
||
│ │ └─ NO → Pre-rotate to current heading │ ││
|
||
│ └──────────────────────────────┬──────────────────────────────┘ ││
|
||
│ ▼ ││
|
||
│ ┌─────────────────────────────────────────────────────────────┐ ││
|
||
│ │ F07 compute_relative_pose_in_chunk() │ ││
|
||
│ │ ├─ SuperPoint extract (prev + curr) via F16 │ ││
|
||
│ │ └─ LightGlue match via F16 │ ││
|
||
│ └──────────────────────────────┬──────────────────────────────┘ ││
|
||
│ │ ││
|
||
│ ┌─────────────────┼─────────────────┐ ││
|
||
│ │ Tracking Good? │ Tracking Lost? │ ││
|
||
│ ▼ ▼ ▼ ││
|
||
│ ┌─────────────────┐ ┌─────────────────────────────────┐ ││
|
||
│ │F12 add_frame │ │ →Flow 6 (Tracking Loss/Recovery)│ ││
|
||
│ │ _to_chunk() │ └─────────────────────────────────┘ ││
|
||
│ └────────┬────────┘ ││
|
||
│ ▼ ││
|
||
│ ┌─────────────────────────────────────────────────────────────┐ ││
|
||
│ │ F04 fetch_tile() + compute_tile_bounds() │ ││
|
||
│ └──────────────────────────────┬──────────────────────────────┘ ││
|
||
│ ▼ ││
|
||
│ ┌─────────────────────────────────────────────────────────────┐ ││
|
||
│ │ F09 align_to_satellite(image, tile, tile_bounds) │ ││
|
||
│ │ └─ LiteSAM matching via F16 │ ││
|
||
│ └──────────────────────────────┬──────────────────────────────┘ ││
|
||
│ │ ││
|
||
│ ┌─────────────────┴─────────────────┐ ││
|
||
│ │ Match Found? │ ││
|
||
│ ▼ ▼ ││
|
||
│ ┌─────────────────────────┐ ┌─────────────────────────┐ ││
|
||
│ │F10 add_absolute_factor()│ │ Skip absolute anchor │ ││
|
||
│ │F06 update_heading() │ │ (VO-only frame) │ ││
|
||
│ └────────────┬────────────┘ └─────────────────────────┘ ││
|
||
│ │ ││
|
||
│ └─────────────────────┬───────────────────────────────────┘│
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ F10 optimize_chunk() │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ F13 enu_to_gps() → Convert ENU pose to GPS │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ F14 update_frame_result() + publish_waypoint_update() │ │
|
||
│ │ └─ F15 send_frame_result() → SSE "frame_processed" │ │
|
||
│ │ └─ F03 save_frame_result() │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└──────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Performance**: < 5 seconds per frame
|
||
|
||
---
|
||
|
||
## Flow 5: First Frame / Sharp Turn (Rotation Sweep)
|
||
|
||
**Purpose**: Establish UAV heading when unknown or after sharp turn.
|
||
|
||
**Trigger**: `requires_rotation_sweep()` returns True
|
||
|
||
**Sequence**:
|
||
```
|
||
┌───────────────────────────────────────────────────────────────────────────┐
|
||
│ F06 Image Rotation Manager │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ try_rotation_steps(image, satellite_tile, tile_bounds) │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌───────────────────────┴────────────────────────────┐ │
|
||
│ │ For angle in [0°, 30°, 60°, ... 330°]: │ │
|
||
│ │ │ │
|
||
│ │ ┌─────────────────────────────────────┐ │ │
|
||
│ │ │ H07 rotate_image(image, angle) │ │ │
|
||
│ │ └───────────────────┬─────────────────┘ │ │
|
||
│ │ ▼ │ │
|
||
│ │ ┌─────────────────────────────────────┐ │ │
|
||
│ │ │ F09 align_to_satellite(rotated, │ │ │
|
||
│ │ │ satellite_tile, tile_bounds) │ │ │
|
||
│ │ └───────────────────┬─────────────────┘ │ │
|
||
│ │ │ │ │
|
||
│ │ ┌──────────────┴──────────────┐ │ │
|
||
│ │ │ Match Found? │ │ │
|
||
│ │ ▼ ▼ │ │
|
||
│ │ ┌───────────────┐ ┌───────────────┐ │ │
|
||
│ │ │ Calculate │ │ Try next │ │ │
|
||
│ │ │ precise angle │ │ rotation │ │ │
|
||
│ │ └───────┬───────┘ └───────────────┘ │ │
|
||
│ │ │ │ │
|
||
│ │ ▼ │ │
|
||
│ │ ┌─────────────────────────────────────┐ │ │
|
||
│ │ │ F03 save_heading() via F06 │ │ │
|
||
│ │ │ update_heading() │ │ │
|
||
│ │ └─────────────────────────────────────┘ │ │
|
||
│ │ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────────┴────────────┐ │
|
||
│ │ Return RotationResult │ │
|
||
│ │ or None │ │
|
||
│ └─────────────────────────┘ │
|
||
└───────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Output**: RotationResult with precise heading angle
|
||
|
||
---
|
||
|
||
## Flow 6: Tracking Loss / Recovery (Progressive Search)
|
||
|
||
**Purpose**: Recover localization after tracking loss.
|
||
|
||
**Trigger**: VO inlier count < 20 or LiteSAM match fails
|
||
|
||
**Sequence**:
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────────────┐
|
||
│ F11 Failure Recovery Coordinator │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 1. EMIT RecoveryStarted event │ │
|
||
│ │ └─ F02 subscribes → Update status to "recovering" │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 2. create_chunk_on_tracking_loss() via F12 │ │
|
||
│ │ └─ Proactive chunk creation (processing continues) │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 3. Single-image recovery attempt: │ │
|
||
│ │ ├─ F06 requires_rotation_sweep() → trigger sweep │ │
|
||
│ │ ├─ F08 retrieve_candidate_tiles() (DINOv2) │ │
|
||
│ │ └─ Progressive tile search (1→4→9→16→25): │ │
|
||
│ │ │ │
|
||
│ │ ┌───────────────────────────────────────────────────┐ │ │
|
||
│ │ │ For grid_size in [1, 4, 9, 16, 25]: │ │ │
|
||
│ │ │ ├─ F04 expand_search_grid() │ │ │
|
||
│ │ │ ├─ For each tile: │ │ │
|
||
│ │ │ │ ├─ F04 compute_tile_bounds() │ │ │
|
||
│ │ │ │ └─ F09 align_to_satellite(img, tile, bounds)│ │ │
|
||
│ │ │ │ │ │ │
|
||
│ │ │ └─ If match found: BREAK │ │ │
|
||
│ │ └───────────────────────────────────────────────────┘ │ │
|
||
│ │ │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────────────────┴────────────────────┐ │
|
||
│ │ Single-image match found? │ │
|
||
│ ▼ ▼ │
|
||
│ ┌─────────────────────┐ ┌────────────────────────────┐ │
|
||
│ │ EMIT RecoverySucceeded│ │ Continue chunk building │ │
|
||
│ │ Resume normal flow │ │ → Flow 7 (Chunk Building) │ │
|
||
│ └─────────────────────┘ │ → Flow 8 (Chunk Matching) │ │
|
||
│ │ (Background) │ │
|
||
│ └────────────────────────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────┐ │
|
||
│ │ If all strategies exhausted: │ │
|
||
│ │ → Flow 10 (User Input Recovery) │ │
|
||
│ └─────────────────────────────────────┘ │
|
||
└──────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Flow 7: Chunk Building
|
||
|
||
**Purpose**: Build route chunks when tracking is lost, continuing VO within chunk.
|
||
|
||
**Sequence**:
|
||
```
|
||
┌───────────────────────────────────────────────────────────────────────────┐
|
||
│ F12 Route Chunk Manager │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ create_chunk(flight_id, start_frame_id) │ │
|
||
│ │ ├─ F10 create_new_chunk() ← Factor graph subgraph │ │
|
||
│ │ ├─ Initialize chunk state (unanchored, active) │ │
|
||
│ │ └─ F03 save_chunk_state() │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ │ │
|
||
│ ┌───────────────────────┴────────────────────────────┐ │
|
||
│ │ For each frame in chunk: │ │
|
||
│ │ │ │
|
||
│ │ ┌─────────────────────────────────────┐ │ │
|
||
│ │ │ F07 compute_relative_pose_in_chunk()│ │ │
|
||
│ │ └───────────────────┬─────────────────┘ │ │
|
||
│ │ ▼ │ │
|
||
│ │ ┌──────────────────────────────────────┐ │ │
|
||
│ │ │ F12 add_frame_to_chunk() │ │ │
|
||
│ │ │ └─ F10 add_relative_factor_to_chunk│ │ │
|
||
│ │ └───────────────────┬──────────────────┘ │ │
|
||
│ │ ▼ │ │
|
||
│ │ ┌─────────────────────────────────────┐ │ │
|
||
│ │ │ F10 optimize_chunk() (local) │ │ │
|
||
│ │ └─────────────────────────────────────┘ │ │
|
||
│ │ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ is_chunk_ready_for_matching()? │ │
|
||
│ │ ├─ Min 5 frames │ │
|
||
│ │ ├─ Max 20 frames │ │
|
||
│ │ └─ Internal consistency (good VO inlier counts) │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└───────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Flow 8: Background Chunk Matching
|
||
|
||
**Purpose**: Asynchronously match unanchored chunks to satellite data.
|
||
|
||
**Trigger**: Background task (every 5 seconds)
|
||
|
||
**Sequence**:
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────────────┐
|
||
│ F11 process_unanchored_chunks() (Background Task) │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ while flight_active: │ │
|
||
│ │ ├─ unanchored = F12 get_chunks_for_matching() │ │
|
||
│ │ │ │ │
|
||
│ │ └─ for chunk in unanchored: │ │
|
||
│ │ │ │ │
|
||
│ │ ▼ │ │
|
||
│ │ ┌─────────────────────────────────────────────────────┐ │ │
|
||
│ │ │ if F12 is_chunk_ready_for_matching(chunk_id): │ │ │
|
||
│ │ │ ├─ F12 mark_chunk_matching(chunk_id) │ │ │
|
||
│ │ │ │ │ │ │
|
||
│ │ │ ├─ STEP 1: Chunk Semantic Matching │ │ │
|
||
│ │ │ │ ├─ F12 get_chunk_images() │ │ │
|
||
│ │ │ │ └─ F08 retrieve_candidate_tiles_for_chunk() │ │ │
|
||
│ │ │ │ └─ F08 compute_chunk_descriptor() │ │ │
|
||
│ │ │ │ └─ H04 Faiss search() │ │ │
|
||
│ │ │ │ │ │ │
|
||
│ │ │ ├─ STEP 2: Chunk LiteSAM Matching (with rotation) │ │ │
|
||
│ │ │ │ ├─ For each candidate tile: │ │ │
|
||
│ │ │ │ │ ├─ F04 get_tile + compute_tile_bounds() │ │ │
|
||
│ │ │ │ │ ├─ F06 try_chunk_rotation_steps() │ │ │
|
||
│ │ │ │ │ │ └─ F09 align_chunk_to_satellite() │ │ │
|
||
│ │ │ │ │ └─ If match: BREAK │ │ │
|
||
│ │ │ │ │ │ │
|
||
│ │ │ └─ If match found: │ │ │
|
||
│ │ │ └─ → Flow 9 (Chunk Merging) │ │ │
|
||
│ │ │ │ │ │
|
||
│ │ └─────────────────────────────────────────────────────┘ │ │
|
||
│ │ │ │
|
||
│ │ sleep(5 seconds) │ │
|
||
│ │ │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└──────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Flow 9: Chunk Merging
|
||
|
||
**Purpose**: Merge anchored chunk into main trajectory.
|
||
|
||
**Trigger**: Successful chunk matching
|
||
|
||
**Sequence**:
|
||
```
|
||
┌───────────────────────────────────────────────────────────────────────-──┐
|
||
│ F11 merge_chunk_to_trajectory() │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 1. Get chunk frames: F12 get_chunk_frames(chunk_id) │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 2. Anchor chunk: F12 mark_chunk_anchored(chunk_id, gps) │ │
|
||
│ │ └─ F10 add_chunk_anchor() │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 3. Determine target chunk (predecessor or "main") │ │
|
||
│ │ └─ Returns target_chunk_id (predecessor or "main") │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 4. Merge: F12 merge_chunks(chunk_id, target_chunk_id, Sim3) │ │
|
||
│ │ ├─ F10 merge_chunks() ← Apply Sim(3) transform │ │
|
||
│ │ ├─ F12 deactivate_chunk(chunk_id) │ │
|
||
│ │ └─ F03 save_chunk_state() │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 5. Optimize global: F10 optimize_global() │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 6. EMIT ChunkMerged event (flight_id,chunk_id,merged_frames)│ │
|
||
│ │ └─ F14 subscribes → update_results_after_chunk_merge() │ │
|
||
│ │ ├─ F10 get_trajectory() → ENU poses │ │
|
||
│ │ ├─ F13 enu_to_gps() for each frame │ │
|
||
│ │ ├─ F03 save_frame_result() + update_waypoint() │ │
|
||
│ │ └─ F15 send_refinement() → SSE "frame_refined" × N │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└──────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Sim(3) Transform**: Translation + Rotation + Scale alignment between chunks
|
||
|
||
---
|
||
|
||
## Flow 10: User Input Recovery
|
||
|
||
**Purpose**: Request human assistance when all automatic recovery fails.
|
||
|
||
**Trigger**: Progressive search exhausted (25 tiles), chunk matching failed
|
||
|
||
**Sequence**:
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────────────┐
|
||
│ F11 create_user_input_request() │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 1. Get UAV image for frame_id │ │
|
||
│ │ 2. Get top-5 candidates from F08 │ │
|
||
│ │ 3. Create UserInputRequest │ │
|
||
│ │ 4. F15 send_user_input_request() → SSE "user_input_needed" │ │
|
||
│ │ 5. EMIT UserInputNeeded event │ │
|
||
│ │ └─ F02 subscribes → Update status to "BLOCKED" │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└──────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼ Client receives SSE event
|
||
┌───────────────────────────────────────────────────────────────────────────┐
|
||
│ Client UI │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ Display UAV image + candidate satellite tiles │ │
|
||
│ │ User clicks corresponding point on satellite tile │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ POST /flights/{flightId}/user-fix │ │
|
||
│ │ body: { frame_id, uav_pixel, satellite_gps } │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└───────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ F11 apply_user_anchor() │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 1. Validate anchor data │ │
|
||
│ │ 2. F10 add_absolute_factor(is_user_anchor=True) ← σ=5m │ │
|
||
│ │ 3. F10 optimize() │ │
|
||
│ │ 4. EMIT UserFixApplied event │ │
|
||
│ │ └─ F02 subscribes → Update status to "PROCESSING" │ │
|
||
│ │ 5. Resume processing loop │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└──────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Flow 11: Asynchronous Refinement
|
||
|
||
**Purpose**: Back-propagate optimization improvements to previous frames.
|
||
|
||
**Trigger**: New absolute GPS factor added, chunk merged
|
||
|
||
**Sequence**:
|
||
```
|
||
┌─────────────────────────────────────────────────────────────-────────────┐
|
||
│ F10 Background Optimization │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 1. New absolute factor triggers batch optimization │ │
|
||
│ │ 2. F10 optimize(iterations=50-100) │ │
|
||
│ │ └─ Levenberg-Marquardt with robust kernels │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 3. Identify refined frames │ │
|
||
│ │ 4. F14 mark_refined(frame_ids) │ │
|
||
│ │ ├─ For each frame: │ │
|
||
│ │ │ ├─ F10 get_trajectory() → ENU pose │ │
|
||
│ │ │ ├─ F13 enu_to_gps(flight_id, enu_pose) │ │
|
||
│ │ │ ├─ F03 save_frame_result(refined=True) │ │
|
||
│ │ │ └─ F03 update_waypoint() │ │
|
||
│ │ │ │ │
|
||
│ │ └─ F15 send_refinement() × N → SSE "frame_refined" × N │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└──────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Flow 12: Object to GPS Conversion
|
||
|
||
**Purpose**: Convert detected object pixel coordinates to GPS (external integration).
|
||
|
||
**Trigger**: `POST /flights/{flightId}/frames/{frameId}/object-to-gps`
|
||
|
||
**Sequence**:
|
||
```
|
||
┌──────────────────┐ POST object-to-gps ┌─────┐
|
||
│ External System │ ────────────────────►│ F01 │
|
||
│ (Azaion.Inference│ {pixel_x, pixel_y} └──┬──┘
|
||
└──────────────────┘ │
|
||
▼
|
||
┌─────────────┐
|
||
│ F13 │ Coordinate Transformer
|
||
└──────┬──────┘
|
||
┌───────────────────┼───────────────────┐
|
||
▼ ▼ ▼
|
||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||
│F10 get_pose │ │F17 camera │ │ H01 Camera │
|
||
│ (frame_id) │ │ _params │ │ Model │
|
||
└─────────────┘ └─────────────┘ └─────────────┘
|
||
│ │ │
|
||
└───────────────────┼───────────────────┘
|
||
▼
|
||
┌─────────────┐
|
||
│ pixel_to_gps│
|
||
│ calculation │
|
||
└──────┬──────┘
|
||
│
|
||
▼
|
||
┌───────────────────────────┐
|
||
│ Return ObjectGPSResponse │
|
||
│ { gps, accuracy_meters }│
|
||
└───────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Flow 13: Flight Completion
|
||
|
||
**Purpose**: Complete flight processing and clean up resources.
|
||
|
||
**Trigger**: All images processed successfully
|
||
|
||
**Sequence**:
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────────────┐
|
||
│ F02 Flight Processor │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 1. All frames processed │ │
|
||
│ │ 2. Wait for pending chunk merges (if any) │ │
|
||
│ │ 3. F10 optimize_global(iterations=100) ← Final optimization │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 4. F14 mark_refined(all_frames) │ │
|
||
│ │ └─ Final refinement updates │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 5. F03 save_flight_state(status="completed") │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 6. F15 send event → SSE "flight_completed" │ │
|
||
│ └──────────────────────────────┬──────────────────────────────┘ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 7. Cleanup: │ │
|
||
│ │ ├─ Stop background chunk matching task │ │
|
||
│ │ ├─ F04 clear_flight_cache(flight_id) (optional) │ │
|
||
│ │ └─ Release flight resources │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└──────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Flow 14: System Shutdown
|
||
|
||
**Purpose**: Gracefully shutdown all components.
|
||
|
||
**Sequence**:
|
||
```
|
||
┌─────────────────┐
|
||
│ Shutdown Signal │
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F01 Stop │ ← Stop accepting requests
|
||
│ accepting │
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F02 Complete/ │ ← Complete or cancel active flights
|
||
│ Cancel │
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F11 Stop │ ← Stop background chunk matching
|
||
│ background │
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F12 Save chunk │ ← Save chunk state for recovery
|
||
│ state │
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F16 Unload │ ← Unload ML models, free GPU memory
|
||
│ models │
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F03 Close │ ← Close database connections
|
||
│ connections │
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ F04 Flush cache │ ← Flush satellite tile cache
|
||
└────────┬────────┘
|
||
▼
|
||
┌─────────────────┐
|
||
│ Shutdown │
|
||
│ Complete │
|
||
└─────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Component Interaction Summary
|
||
|
||
### Data Flow Direction
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ EXTERNAL │
|
||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||
│ │ Client │ │ Satellite │ │ External │ │
|
||
│ │ (UI) │ │ Provider │ │ Detector │ │
|
||
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
||
└─────────┼───────────────────┼───────────────────┼───────────────────────────┘
|
||
│ REST/SSE │ HTTP │ REST
|
||
▼ ▼ ▼
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ API LAYER │
|
||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||
│ │ F01 Flight API │ │
|
||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ ORCHESTRATION LAYER │
|
||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||
│ │ F02 Flight Processor │ │
|
||
│ │ (Central coordinator, event subscriber, background task manager) │ │
|
||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
├─────────────────────────────────────────────────────────────┐
|
||
▼ ▼
|
||
┌─────────────────────────────────────────────┐ ┌────────────────────────────┐
|
||
│ DATA MANAGEMENT LAYER │ │ RECOVERY LAYER │
|
||
│ ┌─────────────┐ ┌─────────────┐ │ │ ┌───────────────────────┐ │
|
||
│ │ F04 │ │ F05 │ │ │ │ F11 │ │
|
||
│ │ Satellite │ │ Image │ │ │ │ Failure Recovery │ │
|
||
│ │ Data │ │ Input │ │ │ │ (Event emitter) │ │
|
||
│ └─────────────┘ └─────────────┘ │ │ └───────────────────────┘ │
|
||
│ │ │ │ │
|
||
│ ┌─────────────┐ ┌─────────────┐ │ │ ▼ │
|
||
│ │ F12 │ │ F03 │ │ │ ┌───────────────────────┐ │
|
||
│ │Route Chunk │ │ Flight │ │ │ │ F12 │ │
|
||
│ │ Manager │ │ Database │ │ │ │ (Chunk state source) │ │
|
||
│ └─────────────┘ └─────────────┘ │ │ └───────────────────────┘ │
|
||
└─────────────────────────────────────────────┘ └────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ VISUAL PROCESSING LAYER │
|
||
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ┌──────────────┐ │
|
||
│ │ F06 │ │ F07 │ │ F08 │ │ F09 │ │
|
||
│ │ Rotation │ │ Sequential VO │ │ Global │ │ Metric │ │
|
||
│ │ Manager │ │(SuperPoint+ │ │ Place │ │ Refinement │ │
|
||
│ │ (30° sweeps) │ │ LightGlue) │ │ Recognition │ │ (LiteSAM) │ │
|
||
│ │ │ │ │ │ (DINOv2) │ │ │ │
|
||
│ └───────────────┘ └───────────────┘ └───────────────┘ └──────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ STATE ESTIMATION LAYER │
|
||
│ ┌──────────────────────────────────────────────────────────────────k──┐ │
|
||
│ │ F10 Factor Graph Optimizer │ │
|
||
│ │ (GTSAM, iSAM2, Robust kernels, Chunk subgraphs, Sim(3) merging) │ │
|
||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ OUTPUT LAYER │
|
||
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
|
||
│ │ F13 │ │ F14 │ │ F15 │ │
|
||
│ │ Coordinate │ │ Result │ │ SSE │ │
|
||
│ │ Transformer │ │ Manager │ │ Streamer │ │
|
||
│ │ (ENU↔GPS↔Px) │ │ │ │ │ │
|
||
│ └───────────────┘ └───────────────┘ └───────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────────-┐
|
||
│ INFRASTRUCTURE LAYER │
|
||
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────────────────────────-┐│
|
||
│ │ F16 │ │ F17 │ │ HELPERS ││
|
||
│ │ Model │ │Configuration │ │ H01-H08 (Camera, GSD, Kernels, ││
|
||
│ │ Manager │ │ Manager │ │ Faiss, Monitor, Mercator, etc) ││
|
||
│ └───────────────┘ └───────────────┘ └────────────────────────────────────┘│
|
||
└──────────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Event-Based Communication
|
||
|
||
F11 Failure Recovery Coordinator emits events instead of directly calling F02:
|
||
|
||
| Event | Publisher | Subscribers | Action |
|
||
|-------|-----------|-------------|--------|
|
||
| `RecoveryStarted` | F11 | F02 | Update status to "recovering" |
|
||
| `RecoverySucceeded` | F11 | F02 | Update status to "processing", resume |
|
||
| `RecoveryFailed` | F11 | F02 | Update status to "blocked" |
|
||
| `UserInputNeeded` | F11 | F02 | Update status to "blocked", await fix |
|
||
| `UserFixApplied` | F11 | F02 | Update status to "processing", resume |
|
||
| `ChunkCreated` | F11 | F02 | Log chunk creation |
|
||
| `ChunkAnchored` | F11 | F02 | Log chunk anchor |
|
||
| `ChunkMerged` | F11 | F02, F14 | F14 updates results for merged frames |
|
||
|
||
---
|
||
|
||
## SSE Events to Client
|
||
|
||
| Event | Trigger | Data |
|
||
|-------|---------|------|
|
||
| `frame_processed` | Frame completed | frame_id, gps, altitude, heading, confidence |
|
||
| `frame_refined` | Trajectory refined | frame_id, updated gps, refined=true |
|
||
| `search_expanded` | Progressive search | frame_id, grid_size, status |
|
||
| `user_input_needed` | Recovery exhausted | request_id, frame_id, candidate_tiles |
|
||
| `processing_blocked` | Status change | reason, frame_id |
|
||
| `flight_completed` | Flight done | statistics |
|
||
|
||
---
|
||
|
||
## Performance Targets
|
||
|
||
| Flow | Target |
|
||
|------|--------|
|
||
| System Initialization | < 30 seconds |
|
||
| Flight Creation | < 500ms response |
|
||
| Image Batch Upload | < 2 seconds (50 images) |
|
||
| Per-Frame Processing | < 5 seconds |
|
||
| Rotation Sweep (12 rotations) | < 1.2 seconds |
|
||
| Progressive Search (25 tiles) | < 1.5 seconds |
|
||
| Chunk Matching | < 3 seconds (background) |
|
||
| SSE Event Latency | < 500ms |
|
||
|
||
---
|
||
|
||
## Accuracy Targets
|
||
|
||
| Metric | Target |
|
||
|--------|--------|
|
||
| GPS Accuracy | 60% < 20m, 80% < 50m |
|
||
| Mean Reprojection Error | < 1.0 pixels |
|
||
| Place Recognition Recall@5 | > 85% |
|
||
| LiteSAM Success Rate | > 95% (when rotation correct) |
|
||
|