# ASTRAL-Next System Component Decomposition Plan ## Design Principle: Interface-Based Architecture **CRITICAL REQUIREMENT**: Each component MUST implement a well-defined interface to ensure interchangeability with different implementations. **Benefits**: - Swap implementations (e.g., replace LiteSAM with TransFG, GTSAM with Ceres) - Enable unit testing with mocks - Support multiple backends (TensorRT vs ONNX, different databases) - Facilitate future enhancements without breaking contracts **Interface Specification**: Each component spec must define: - Interface name (e.g., `ISatelliteDataManager`, `IMetricRefinement`) - All public methods with strict contracts - Input/output data structures - Error conditions and exceptions - Performance guarantees --- ## System Architecture Overview **Single unified Flight API:** - Flight CRUD operations (create, read, update, delete) - Waypoint management within flights - Geofence management - Tri-layer localization (SuperPoint+LightGlue, DINOv2, LiteSAM) - Calls satellite provider for tiles - Rotation preprocessing (LiteSAM 45° limit) - Per-frame waypoint updates - Progressive tile search (1→4→9→16→25) - SSE streaming for real-time results --- ## FLIGHT API COMPONENTS (17 components) ### Core API Layer **F01_flight_api** **Interface**: `IFlightAPI` **Endpoints**: `POST /flights`, `GET /flights/{flightId}`, `DELETE /flights/{flightId}`, `PUT /flights/{flightId}/waypoints/{waypointId}`, `POST .../images/batch`, `POST .../user-fix`, `GET .../status`, `GET .../stream` **F02_flight_processor** **Interface**: `IFlightProcessor` **API**: `create_flight()`, `get_flight()`, `get_flight_state()`, `delete_flight()`, `update_waypoint()`, `batch_update_waypoints()`, `validate_waypoint()`, `validate_geofence()`, `process_frame()`, `run_processing_loop()`, `handle_tracking_loss()`, `initialize_system()` **F03_flight_database** **Interface**: `IFlightDatabase` **API**: `insert_flight()`, `update_flight()`, `query_flights()`, `get_flight_by_id()`, `delete_flight()`, `get_waypoints()`, `insert_waypoint()`, `update_waypoint()`, `batch_update_waypoints()`, `save_flight_state()`, `load_flight_state()`, `save_frame_result()`, `get_frame_results()`, `save_heading()`, `get_heading_history()`, `get_latest_heading()`, `save_image_metadata()`, `get_image_path()`, `get_image_metadata()` ### Data Management **F04_satellite_data_manager** **Interface**: `ISatelliteDataManager` **API**: `fetch_tile()`, `fetch_tile_grid()`, `prefetch_route_corridor()`, `progressive_fetch()`, `cache_tile()`, `get_cached_tile()`, `compute_tile_coords()`, `expand_search_grid()`, `compute_tile_bounds()` **Features**: Progressive retrieval, tile caching, grid calculations **F05_image_input_pipeline** **Interface**: `IImageInputPipeline` **API**: `queue_batch()`, `process_next_batch()`, `validate_batch()`, `store_images()`, `get_next_image()`, `get_image_by_sequence()` **Features**: FIFO queuing, validation, storage **F06_image_rotation_manager** **Interface**: `IImageRotationManager` **API**: `rotate_image_360()`, `try_rotation_steps()`, `calculate_precise_angle()`, `get_current_heading()`, `update_heading()`, `detect_sharp_turn()`, `requires_rotation_sweep()` **Features**: 30° rotation sweeps, heading tracking ### Visual Processing **F07_sequential_visual_odometry** **Interface**: `ISequentialVO` **API**: `compute_relative_pose()`, `extract_features()`, `match_features()`, `estimate_motion()` **F08_global_place_recognition** **Interface**: `IGlobalPlaceRecognition` **API**: `retrieve_candidate_tiles()`, `compute_location_descriptor()`, `query_database()`, `rank_candidates()` **F09_metric_refinement** **Interface**: `IMetricRefinement` **API**: `align_to_satellite(uav_image, satellite_tile, tile_bounds)`, `compute_homography()`, `extract_gps_from_alignment()`, `compute_match_confidence()` ### State Estimation **F10_factor_graph_optimizer** **Interface**: `IFactorGraphOptimizer` **API**: `add_relative_factor()`, `add_absolute_factor()`, `add_altitude_prior()`, `optimize()`, `get_trajectory()`, `get_marginal_covariance()` **F11_failure_recovery_coordinator** **Interface**: `IFailureRecoveryCoordinator` **API**: `check_confidence()`, `detect_tracking_loss()`, `start_search()`, `expand_search_radius()`, `try_current_grid()`, `create_user_input_request()`, `apply_user_anchor()` **F12_route_chunk_manager** **Interface**: `IRouteChunkManager` **API**: `create_chunk()`, `add_frame_to_chunk()`, `get_chunk_frames()`, `get_chunk_images()`, `get_chunk_composite_descriptor()`, `get_chunk_bounds()`, `is_chunk_ready_for_matching()`, `mark_chunk_anchored()`, `get_chunks_for_matching()`, `get_active_chunk()`, `deactivate_chunk()` **Features**: Chunk lifecycle management, chunk state tracking, chunk matching coordination **F13_coordinate_transformer** **Interface**: `ICoordinateTransformer` **API**: `set_enu_origin()`, `get_enu_origin()`, `gps_to_enu()`, `enu_to_gps()`, `pixel_to_gps()`, `gps_to_pixel()`, `image_object_to_gps()`, `transform_points()` **Dependencies**: F10 Factor Graph Optimizer (for frame poses), H02 GSD Calculator (for GSD computation) ### Results & Communication **F14_result_manager** **Interface**: `IResultManager` **API**: `update_frame_result()`, `publish_waypoint_update()`, `get_flight_results()`, `mark_refined()` **F15_sse_event_streamer** **Interface**: `ISSEEventStreamer` **API**: `create_stream()`, `send_frame_result()`, `send_search_progress()`, `send_user_input_request()`, `send_refinement()` ### Infrastructure **F16_model_manager** **Interface**: `IModelManager` **API**: `load_model()`, `get_inference_engine()`, `optimize_to_tensorrt()`, `fallback_to_onnx()` **F17_configuration_manager** **Interface**: `IConfigurationManager` **API**: `load_config()`, `get_camera_params()`, `validate_config()`, `get_flight_config()` --- ## HELPER COMPONENTS (8 components) **H01_camera_model** - `ICameraModel` **H02_gsd_calculator** - `IGSDCalculator` **H03_robust_kernels** - `IRobustKernels` **H04_faiss_index_manager** - `IFaissIndexManager` **H05_performance_monitor** - `IPerformanceMonitor` **H06_web_mercator_utils** - `IWebMercatorUtils` **H07_image_rotation_utils** - `IImageRotationUtils` **H08_batch_validator** - `IBatchValidator` --- ## System Startup Initialization Order **Startup sequence** (blocking, sequential): | Order | Component | Method | Purpose | Dependencies | |-------|-----------|--------|---------|--------------| | 1 | F17 Configuration Manager | `load_config()` | Load system configuration | None | | 2 | F03 Flight Database | Initialize connections | Establish DB connection pool | F17 | | 3 | F16 Model Manager | `load_model("SuperPoint")` | Load SuperPoint feature extractor | F17 | | 4 | F16 Model Manager | `load_model("LightGlue")` | Load LightGlue matcher | F17 | | 5 | F16 Model Manager | `load_model("DINOv2")` | Load DINOv2 for place recognition | F17 | | 6 | F16 Model Manager | `load_model("LiteSAM")` | Load LiteSAM for cross-view matching | F17 | | 7 | F04 Satellite Data Manager | Initialize cache | Initialize tile cache directory | F17 | | 8 | F08 Global Place Recognition | `load_index()` | Load pre-built Faiss index from satellite provider | F04, F16, H04 | | 9 | F12 Route Chunk Manager | Initialize | Initialize chunk state tracking | F10 | | 10 | F02 Flight Processor | Ready | Ready to accept flights | All above | | 11 | F01 Flight API | Start server | Start FastAPI/Uvicorn | F02 | **Estimated total startup time**: ~30 seconds (dominated by model loading) **Shutdown sequence** (reverse order): 1. F01 Flight API - Stop accepting requests 2. F02 Flight Processor - Complete or cancel active flights 3. F11 Failure Recovery Coordinator - Stop background chunk matching 4. F12 Route Chunk Manager - Save chunk state 5. F16 Model Manager - Unload models 6. F03 Flight Database - Close connections 7. F04 Satellite Data Manager - Flush cache --- ## Comprehensive Component Interaction Matrix ### System Initialization | Source | Target | Method | Purpose | |--------|--------|--------|---------| | F02 | F16 | `load_config()` | Load system configuration | | F02 | F16 | `load_model()` × 4 | Load SuperPoint, LightGlue, DINOv2, LiteSAM | | F04 | F08 | Satellite tiles | F08 generates descriptors for Faiss | | F08 | H04 | `build_index()` | Build satellite descriptor index | | F08 | F15 | `get_inference_engine("DINOv2")` | Get model for descriptor generation | ### Flight Creation | Source | Target | Method | Purpose | |--------|--------|--------|---------| | Client | F01 | `POST /flights` | Create flight | | F01 | F02 | `create_flight()` | Initialize flight state | | F02 | F16 | `get_flight_config()` | Get camera params, altitude | | F02 | F12 | `set_enu_origin(start_gps)` | Set ENU coordinate origin | | F02 | F04 | `prefetch_route_corridor()` | Prefetch tiles | | F04 | Satellite Provider | `GET /api/satellite/tiles/batch` | HTTP batch download | | F04 | H06 | `compute_tile_bounds()` | Tile coordinate calculations | | F02 | F03 | `insert_flight()` | Persist flight data | | Client | F01 | `GET .../stream` | Open SSE connection | | F01 | F14 | `create_stream()` | Establish SSE channel | ### Image Upload | Source | Target | Method | Purpose | |--------|--------|--------|---------| | Client | F01 | `POST .../images/batch` | Upload 10-50 images | | F01 | F05 | `queue_batch()` | Queue for processing | | F05 | H08 | `validate_batch()` | Validate sequence, format | | F05 | F03 | `save_image_metadata()` | Persist image metadata | ### Per-Frame Processing (First Frame / Sharp Turn) | Source | Target | Method | Purpose | |--------|--------|--------|---------| | F02 | F05 | `get_next_image()` | Get image for processing | | F02 | F06 | `requires_rotation_sweep()` | Check if sweep needed | | F06 | H07 | `rotate_image()` × 12 | Rotate in 30° steps | | F06 | F09 | `align_to_satellite(img, tile, bounds)` × 12 | Try LiteSAM each rotation | | F06 | F04 | `get_cached_tile()` + `compute_tile_bounds()` | Get expected tile with bounds | | F09 | F15 | `get_inference_engine("LiteSAM")` | Get model | | F06 | H07 | `calculate_rotation_from_points()` | Precise angle from homography | | F06 | F03 | `save_heading()` | Store UAV heading | ### Per-Frame Processing (Sequential VO) | Source | Target | Method | Purpose | |--------|--------|--------|---------| | F02 | F12 | `get_active_chunk()` | Get active chunk for frame | | F02 | F07 | Process frame | Provide image and chunk context | | F07 | F16 | `get_inference_engine("SuperPoint")` | Get feature extractor | | F07 | F16 | `get_inference_engine("LightGlue")` | Get matcher | | F07 | H05 | `start_timer()`, `end_timer()` | Monitor timing | | F07 | F10 | `add_relative_factor_to_chunk()` | Add pose measurement to chunk subgraph | | F02 | F12 | `add_frame_to_chunk()` | Add frame to chunk | ### Tracking Good (Drift Correction) | Source | Target | Method | Purpose | |--------|--------|--------|---------| | F02 | F11 | `check_confidence()` | Check tracking quality | | F02 | F04 | `fetch_tile()` + `compute_tile_bounds()` | Get single tile with bounds | | F02 | F09 | `align_to_satellite(img, tile, bounds)` | Align to 1 tile | | F02 | F10 | `add_absolute_factor()` | Add GPS measurement | ### Tracking Lost (Progressive Search + Chunk Building) | Source | Target | Method | Purpose | |--------|--------|--------|---------| | F02 | F11 | `check_confidence()` → FAIL | Low confidence | | F11 | F12 | `create_chunk_on_tracking_loss()` | **Proactive chunk creation** | | F12 | F10 | `create_new_chunk()` | Create chunk in factor graph | | F12 | F03 | `save_chunk_state()` | Persist chunk state for recovery | | F02 | F12 | `get_active_chunk()` | Get new active chunk | | F11 | F06 | `requires_rotation_sweep()` | Trigger rotation sweep (single-image) | | F11 | F08 | `retrieve_candidate_tiles()` | Coarse localization (single-image) | | F08 | F15 | `get_inference_engine("DINOv2")` | Get model | | F08 | H04 | `search()` | Query Faiss index | | F08 | F04 | `get_tile_by_gps()` × 5 | Get candidate tiles | | F11 | F04 | `expand_search_grid(4)` | Get 2×2 grid | | F11 | F09 | `align_to_satellite(img, tile, bounds)` | Try LiteSAM on tiles | | F11 (fail) | F04 | `expand_search_grid(9)` | Expand to 3×3 | | F11 (fail) | F04 | `expand_search_grid(16)` | Expand to 4×4 | | F11 (fail) | F04 | `expand_search_grid(25)` | Expand to 5×5 | | F11 (fail) | F03 | Continue building chunk | **Chunk building continues** | | F11 (background) | F03 | `get_chunks_for_matching()` | Get unanchored chunks | | F11 (background) | F08 | `retrieve_candidate_tiles_for_chunk()` | **Chunk semantic matching** | | F11 (background) | F06 | `try_chunk_rotation_steps()` | **Chunk rotation sweeps** | | F11 (background) | F09 | `align_chunk_to_satellite()` | **Chunk LiteSAM matching** | | F11 (background) | F10 | `add_chunk_anchor()` + `merge_chunks()` | **Chunk merging** | | F11 (fail) | F14 | `send_user_input_request()` | Request human help (last resort) | | F11 | F02 | `update_flight_status("BLOCKED")` | Block processing | ### Optimization & Results | Source | Target | Method | Purpose | |--------|--------|--------|---------| | F10 | H03 | `huber_loss()`, `cauchy_loss()` | Apply robust kernels | | F10 | Internal | `optimize()` | Run iSAM2 optimization | | F02 | F10 | `get_trajectory()` | Get optimized poses | | F02 | F13 | `enu_to_gps()` | Convert ENU to GPS | | F13 | H01 | `project()`, `unproject()` | Camera operations | | F13 | H02 | `compute_gsd()` | GSD calculations | | F13 | H06 | `tile_to_latlon()` | Coordinate transforms | | F02 | F14 | Frame GPS + object coords | Provide results | | F14 | F02 | `update_waypoint()` | Per-frame waypoint update | | F14 | F15 | `send_frame_result()` | Publish to client | | F15 | Client | SSE `frame_processed` | Real-time delivery | | F14 | F03 | `save_frame_result()` | Persist frame result | ### User Input Recovery | Source | Target | Method | Purpose | |--------|--------|--------|---------| | F15 | Client | SSE `user_input_needed` | Notify client | | Client | F01 | `POST .../user-fix` | Provide anchor | | F01 | F11 | `apply_user_anchor()` | Apply fix | | F11 | F10 | `add_absolute_factor()` (high confidence) | Hard constraint | | F10 | Internal | `optimize()` | Re-optimize | | F11 | Event | Emit `UserFixApplied` | F02 subscribes and resumes | ### Asynchronous Refinement | Source | Target | Method | Purpose | |--------|--------|--------|---------| | F10 | Internal (background) | `optimize()` | Back-propagate anchors | | F10 | F14 | `get_trajectory()` | Get refined poses | | F14 | F02 | `batch_update_waypoints()` | Batch update waypoints | | F14 | F15 | `send_refinement()` × N | Send updates | | F15 | Client | SSE `frame_refined` × N | Incremental updates | ### Chunk Matching (Background) | Source | Target | Method | Purpose | |--------|--------|--------|---------| | F11 (background) | F12 | `get_chunks_for_matching()` | Get unanchored chunks ready for matching | | F11 | F12 | `get_chunk_images()` | Get chunk images | | F11 | F08 | `retrieve_candidate_tiles_for_chunk()` | Chunk semantic matching (aggregate DINOv2) | | F08 | F16 | `get_inference_engine("DINOv2")` | Get model for descriptor computation | | F08 | H04 | `search()` | Query Faiss with chunk descriptor | | F11 | F06 | `try_chunk_rotation_steps()` | Chunk rotation sweeps (12 rotations) | | F06 | F09 | `align_chunk_to_satellite()` × 12 | Try LiteSAM for each rotation | | F11 | F10 | `add_chunk_anchor()` | Anchor chunk with GPS | | F11 | F10 | `merge_chunks()` | Merge chunk to main trajectory (Sim3) | | F10 | Internal | `optimize_global()` | Global optimization after merging | | F11 | F12 | `mark_chunk_anchored()` | Update chunk state | ### Cross-Cutting Concerns | Source | Target | Method | Purpose | |--------|--------|--------|---------| | F16 | ALL | `get_*_config()` | Provide configuration | | H05 | F07, F08, F09, F10, F11 | `start_timer()`, `end_timer()` | Performance monitoring | --- ## Interaction Coverage Verification ✅ **Initialization**: F02→F16, F17; F04→F08→H04 ✅ **Flight creation**: Client→F01→F02→F04,F12,F16,F17,F14 ✅ **Image upload**: Client→F01→F05→H08,F17 ✅ **Rotation sweep**: F06→H07,F09 (12 iterations) ✅ **Sequential VO**: F07→F16,F10(chunk),F12,H05 ✅ **Drift correction**: F02→F04,F09,F10 ✅ **Tracking loss**: F11→F12(proactive chunk),F06,F08,F04(progressive),F09,F15,F02 ✅ **Chunk building**: F02→F12→F10,F07 ✅ **Chunk semantic matching**: F11→F12→F08(chunk descriptor) ✅ **Chunk LiteSAM matching**: F11→F06(chunk rotation)→F09(chunk alignment) ✅ **Chunk merging**: F11→F10(Sim3 transform) ✅ **Global PR**: F08→F16,H04,F04 ✅ **Optimization**: F10→H03(chunk optimization, global optimization) ✅ **Coordinate transform**: F13→H01,H02,H06 ✅ **Results**: F02→F13→F14→F15,F03 ✅ **User input**: Client→F01→F11→F10,F02 ✅ **Refinement**: F10→F14→F02,F15 ✅ **Configuration**: F17→ALL ✅ **Performance**: H05→processing components **All major component interactions are covered.** --- ## Deliverables **Component Count**: 25 total - Flight API: 17 (F01-F17) - Helpers: 8 (H01-H08) **For each component**, create `docs/02_components/[##]_[component_name]/[component_name]_spec.md`: 1. **Interface Definition** (interface name, methods, contracts) 2. **Component Description** (responsibilities, scope) 3. **API Methods** (inputs, outputs, errors, which components call it, test cases) 4. **Integration Tests** 5. **Non-Functional Requirements** (performance, accuracy targets) 6. **Dependencies** (which components it calls) 7. **Data Models** ### Component Specifications Status - [x] F01 Flight API (merged from R01 Route REST API) - [x] F02 Flight Processor (merged from R02, R03, G02) - [x] F04 Satellite Data Manager - [x] F05 Image Input Pipeline - [x] F06 Image Rotation Manager - [x] F07 Sequential Visual Odometry - [x] F08 Global Place Recognition - [x] F09 Metric Refinement - [x] F10 Factor Graph Optimizer - [x] F11 Failure Recovery Coordinator - [x] F12 Route Chunk Manager (Atlas multi-map chunk lifecycle) - [x] F13 Coordinate Transformer (with ENU origin) - [x] F14 Result Manager - [x] F15 SSE Event Streamer - [x] F16 Model Manager - [x] F17 Configuration Manager - [x] F03 Flight Database (merged from R04, G17) - [x] Helper components (H01-H08) --- ## Architecture Notes ### F02 Flight Processor Complexity F02 Flight Processor handles multiple concerns: - Flight lifecycle management - Processing loop orchestration - Event subscription and state updates - Coordination of F07/F08/F09/F10 **Current Status**: Acceptable for MVP. The responsibilities are related (all flight processing) and the component acts as a coordinator rather than implementing logic directly. **Future Consideration**: If complexity grows, consider splitting into: - F02a Flight State Manager (lifecycle, status) - F02b Processing Loop Coordinator (frame processing orchestration) **Decision**: Keep as single component. Clear internal organization with separate methods for state vs processing concerns. Event-based communication with F11 keeps recovery logic separate. ### Error Recovery Strategy **Per-Component Recovery**: - **F02**: Persists flight state via F03 on each significant update. On restart, loads last known state. - **F07**: Stateless - reprocesses frame if VO fails - **F10**: Factor graph state persisted periodically. On restart, rebuilds from F03 checkpoint. - **F11**: Chunk state persisted via F12→F03. Recovery continues from last chunk state. - **F12**: All chunk state persisted to F03. Restores chunk handles on restart. **System-Wide Recovery**: 1. On crash, F02 loads flight state from F03 2. F12 restores chunk state from F03 3. Processing resumes from last successfully processed frame 4. Incomplete chunks continue building/matching **Event Recovery**: - Events are fire-and-forget (no persistence) - Subscribers rebuild state from F03 on restart