Files
gps-denied-desktop/docs/02_components/system_flows.md
T
2025-11-30 16:09:31 +02:00

74 KiB
Raw Blame History

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


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)