74 KiB
ASTRAL-Next System Flows
See also: System Flow Diagrams (Mermaid) 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.1 | Flight Lifecycle Manager | IFlightLifecycleManager |
Flight CRUD, init, API delegation |
| F02.2 | Flight Processing Engine | IFlightProcessingEngine |
Processing loop, recovery orchestration |
| 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.1 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.1 │ Flight Lifecycle Manager
└────┬────┘
┌────────────────────────┬─┴─┬────────────────────────┐
│ │ │ │
▼ │ ▼ ▼
┌───────────────┐ │ ┌───────────────┐ ┌───────────────┐
│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.2 Flight Processing Engine │
│ │
│ ┌─────────────┐ │
│ │ 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() │ ││
│ │ ├─ 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(flight_id,│ │ Skip absolute anchor │ ││
│ │ frame_id, gps, covariance, │ │ (VO-only frame) │ ││
│ │ is_user_anchor=False) │ └─────────────────────────┘ ││
│ │F06 update_heading() │ ││
│ └────────────┬─────────────────────┘ ││
│ │ ││
│ └─────────────────────┬───────────────────────────────────┘│
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ F10 optimize_chunk(flight_id, chunk_id, iterations) │ │
│ └──────────────────────────────┬──────────────────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 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.2 updates 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_chunk_subgraph(flight_id, chunk_id, │ │
│ │ │ start_frame_id) ← Factor graph subgraph │ │
│ │ ├─ Initialize chunk state (unanchored, active) │ │
│ │ └─ F03 save_chunk_state() │ │
│ └──────────────────────────────┬──────────────────────────────┘ │
│ │ │
│ ┌───────────────────────┴────────────────────────────┐ │
│ │ For each frame in chunk: │ │
│ │ │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ F07 compute_relative_pose() │ │ │
│ │ └───────────────────┬─────────────────┘ │ │
│ │ ▼ │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ F12 add_frame_to_chunk() │ │ │
│ │ │ └─ F10 add_relative_factor_to_chunk│ │ │
│ │ │ (flight_id, chunk_id, frame_i, │ │ │
│ │ │ frame_j, relative_pose, cov) │ │ │
│ │ └───────────────────┬──────────────────┘ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ F10 optimize_chunk(flight_id, │ │ │
│ │ │ chunk_id, iterations) (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(flight_id, chunk_id, frame_id, │ │
│ │ gps, covariance) │ │
│ └──────────────────────────────┬──────────────────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 3. Determine target chunk (predecessor or "main") │ │
│ │ └─ Returns target_chunk_id (predecessor or "main") │ │
│ └──────────────────────────────┬──────────────────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 4. Merge: F12 merge_chunks(target_chunk_id, chunk_id, Sim3) │ │
│ │ ├─ F10 merge_chunk_subgraphs(flight_id, chunk_id, │ │
│ │ │ target_chunk_id, transform) ← Apply Sim(3) │ │
│ │ ├─ F12 deactivate_chunk(chunk_id) │ │
│ │ └─ F03 save_chunk_state() │ │
│ └──────────────────────────────┬──────────────────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 5. Optimize global: F10 optimize_global(flight_id, │ │
│ │ iterations) │ │
│ └──────────────────────────────┬──────────────────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 6. EMIT ChunkMerged event (flight_id,chunk_id,merged_frames)│ │
│ │ └─ F14 subscribes → update_results_after_chunk_merge() │ │
│ │ ├─ F10 get_trajectory(flight_id) → 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.2 updates 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.2 updates 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(flight_id) → 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.1 Flight Lifecycle Manager │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. All frames processed (Signal from F02.2) │ │
│ │ 2. Wait for pending chunk merges (if any) │ │
│ │ 3. F10 optimize_global(flight_id, 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.1 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.1 Flight Lifecycle Manager │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ (Spawns/Manages) │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ F02.2 Flight Processing Engine │ │
│ │ (Processing loop, State machine, Recovery orchestration) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
├─────────────────────────────────────────────────────────────┐
▼ ▼
┌─────────────────────────────────────────────┐ ┌────────────────────────────┐
│ DATA MANAGEMENT LAYER │ │ RECOVERY LAYER │
│ ┌─────────────┐ ┌─────────────┐ │ │ ┌───────────────────────┐ │
│ │ F04 │ │ F05 │ │ │ │ F11 │ │
│ │ Satellite │ │ Image │ │ │ │ Failure Recovery │ │
│ │ Data │ │ Input │ │ │ │ (Logic & Strategies) │ │
│ └─────────────┘ └─────────────┘ │ │ └───────────────────────┘ │
│ │ │ │ │
│ ┌─────────────┐ ┌─────────────┐ │ │ ▼ │
│ │ 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) ││
│ └───────────────┘ └───────────────┘ └────────────────────────────────────┘│
└──────────────────────────────────────────────────────────────────────────────┘
Status-Based Recovery Communication
F11 Failure Recovery Coordinator uses Direct Call Returns to communicate with F02.2 Flight Processing Engine. Events have been removed to eliminate circular dependencies and clarify control flow.
| Action | Caller | Called | Return/Outcome |
|---|---|---|---|
start_search |
F02.2 | F11 | SearchSession object |
try_current_grid |
F02.2 | F11 | AlignmentResult (or None) |
create_user_input_request |
F02.2 | F11 | UserInputRequest object |
apply_user_anchor |
F02.2 | F11 | Success boolean |
F02.2 is responsible for updating the flight status (e.g., "recovering", "blocked", "processing") based on these return values.
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) |