# 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 **Two separate REST APIs in same repository:** ### Route API (Separate Project) - Route/waypoint/geofence CRUD - Shared by GPS-Denied and Mission Planner - Does NOT call satellite provider ### GPS-Denied API (Main System) - Tri-layer localization (SuperPoint+LightGlue, AnyLoc, LiteSAM) - Calls satellite provider for tiles - Rotation preprocessing (LiteSAM 45° limit) - Per-frame Route API updates - Progressive tile search (1→4→9→16→25) --- ## ROUTE API COMPONENTS (4 components) ### R01_route_rest_api **Interface**: `IRouteRestAPI` **Endpoints**: `POST /routes`, `GET /routes/{routeId}`, `PUT /routes/{routeId}/waypoints`, `DELETE /routes/{routeId}` ### R02_route_data_manager **Interface**: `IRouteDataManager` **API**: `save_route()`, `load_route()`, `update_waypoint()`, `delete_waypoint()`, `get_route_metadata()` ### R03_waypoint_validator **Interface**: `IWaypointValidator` **API**: `validate_waypoint()`, `validate_geofence()`, `check_bounds()`, `validate_route_continuity()` ### R04_route_database_layer **Interface**: `IRouteDatabase` **API**: `insert_route()`, `update_route()`, `query_routes()`, `get_waypoints()` --- ## GPS-DENIED API COMPONENTS (17 components) ### Core REST API Layer **G01_gps_denied_rest_api** **Interface**: `IGPSDeniedRestAPI` **Endpoints**: `POST /gps-denied/flights`, `POST .../images/batch`, `POST .../user-fix`, `GET .../status`, `GET .../stream` **G02_flight_manager** **Interface**: `IFlightManager` **API**: `create_flight()`, `get_flight_state()`, `link_to_route()`, `update_flight_status()` **G03_route_api_client** **Interface**: `IRouteAPIClient` **API**: `update_route_waypoint()`, `get_route_info()`, `batch_update_waypoints()` ### Data Management **G04_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()` **Features**: Progressive retrieval, tile caching, grid calculations **G05_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 **G06_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 **G07_sequential_visual_odometry** **Interface**: `ISequentialVO` **API**: `compute_relative_pose()`, `extract_features()`, `match_features()`, `estimate_motion()` **G08_global_place_recognition** **Interface**: `IGlobalPlaceRecognition` **API**: `retrieve_candidate_tiles()`, `compute_location_descriptor()`, `query_database()`, `rank_candidates()` **G09_metric_refinement** **Interface**: `IMetricRefinement` **API**: `align_to_satellite()`, `compute_homography()`, `extract_gps_from_alignment()`, `compute_match_confidence()` ### State Estimation **G10_factor_graph_optimizer** **Interface**: `IFactorGraphOptimizer` **API**: `add_relative_factor()`, `add_absolute_factor()`, `add_altitude_prior()`, `optimize()`, `get_trajectory()` **G11_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()` **G12_coordinate_transformer** **Interface**: `ICoordinateTransformer` **API**: `pixel_to_gps()`, `gps_to_pixel()`, `image_object_to_gps()`, `compute_gsd()`, `transform_points()` ### Results & Communication **G13_result_manager** **Interface**: `IResultManager` **API**: `update_frame_result()`, `publish_to_route_api()`, `get_flight_results()`, `mark_refined()` **G14_sse_event_streamer** **Interface**: `ISSEEventStreamer` **API**: `create_stream()`, `send_frame_result()`, `send_search_progress()`, `send_user_input_request()`, `send_refinement()` ### Infrastructure **G15_model_manager** **Interface**: `IModelManager` **API**: `load_model()`, `get_inference_engine()`, `optimize_to_tensorrt()`, `fallback_to_onnx()` **G16_configuration_manager** **Interface**: `IConfigurationManager` **API**: `load_config()`, `get_camera_params()`, `validate_config()`, `get_flight_config()` **G17_gps_denied_database_layer** **Interface**: `IGPSDeniedDatabase` **API**: `save_flight_state()`, `load_flight_state()`, `query_processing_history()` --- ## 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` --- ## Comprehensive Component Interaction Matrix ### System Initialization | Source | Target | Method | Purpose | |--------|--------|--------|---------| | G02 | G15 | `load_model()` × 4 | Load SuperPoint, LightGlue, DINOv2, LiteSAM | | G02 | G16 | `load_config()` | Load system configuration | | G04 | G08 | Satellite tiles | G08 generates descriptors for Faiss | | G08 | H04 | `build_index()` | Build satellite descriptor index | | G08 | G15 | `get_inference_engine("DINOv2")` | Get model for descriptor generation | ### Flight Creation | Source | Target | Method | Purpose | |--------|--------|--------|---------| | Client | G01 | `POST /gps-denied/flights` | Create flight | | G01 | G02 | `create_flight()` | Initialize flight state | | G02 | G16 | `get_flight_config()` | Get camera params, altitude | | G02 | G03 | `get_route_info()` | Fetch route metadata | | G03 | Route API | `GET /routes/{routeId}` | HTTP call | | G02 | G04 | `prefetch_route_corridor()` | Prefetch tiles | | G04 | Satellite Provider | `GET /api/satellite/tiles/batch` | HTTP batch download | | G04 | H06 | `compute_tile_bounds()` | Tile coordinate calculations | | G02 | G17 | `save_flight_state()` | Persist flight metadata | | Client | G01 | `GET .../stream` | Open SSE connection | | G01 | G14 | `create_stream()` | Establish SSE channel | ### Image Upload | Source | Target | Method | Purpose | |--------|--------|--------|---------| | Client | G01 | `POST .../images/batch` | Upload 10-50 images | | G01 | G05 | `queue_batch()` | Queue for processing | | G05 | H08 | `validate_batch()` | Validate sequence, format | | G05 | G17 | `store_images()` | Persist images | ### Per-Frame Processing (First Frame / Sharp Turn) | Source | Target | Method | Purpose | |--------|--------|--------|---------| | G05 | G06 | `get_next_image()` | Get image for processing | | G06 | G06 | `requires_rotation_sweep()` | Check if sweep needed | | G06 | H07 | `rotate_image()` × 12 | Rotate in 30° steps | | G06 | G09 | `align_to_satellite()` × 12 | Try LiteSAM each rotation | | G09 | G04 | `get_cached_tile()` | Get expected tile | | G09 | G15 | `get_inference_engine("LiteSAM")` | Get model | | G06 | H07 | `calculate_rotation_from_points()` | Precise angle from homography | | G06 | Internal | `update_heading()` | Store UAV heading | ### Per-Frame Processing (Sequential VO) | Source | Target | Method | Purpose | |--------|--------|--------|---------| | G05 | G07 | `get_next_image()` | Provide image | | G07 | G15 | `get_inference_engine("SuperPoint")` | Get feature extractor | | G07 | G15 | `get_inference_engine("LightGlue")` | Get matcher | | G07 | H05 | `start_timer()`, `end_timer()` | Monitor timing | | G07 | G10 | `add_relative_factor()` | Add pose measurement | ### Tracking Good (Drift Correction) | Source | Target | Method | Purpose | |--------|--------|--------|---------| | G07 | G11 | `check_confidence()` | Check tracking quality | | G11 | G09 | `align_to_satellite()` | Align to 1 tile | | G09 | G04 | `get_tile_grid(1)` | Get single tile | | G09 | G10 | `add_absolute_factor()` | Add GPS measurement | ### Tracking Lost (Progressive Search) | Source | Target | Method | Purpose | |--------|--------|--------|---------| | G07 | G11 | `check_confidence()` → FAIL | Low confidence | | G11 | G06 | `requires_rotation_sweep()` | Trigger rotation sweep | | G11 | G08 | `retrieve_candidate_tiles()` | Coarse localization | | G08 | G15 | `get_inference_engine("DINOv2")` | Get model | | G08 | H04 | `search()` | Query Faiss index | | G08 | G04 | `get_tile_by_gps()` × 5 | Get candidate tiles | | G11 | G04 | `expand_search_grid(4)` | Get 2×2 grid | | G11 | G09 | `align_to_satellite()` | Try LiteSAM on 4 tiles | | G11 (fail) | G04 | `expand_search_grid(9)` | Expand to 3×3 | | G11 (fail) | G04 | `expand_search_grid(16)` | Expand to 4×4 | | G11 (fail) | G04 | `expand_search_grid(25)` | Expand to 5×5 | | G11 (fail) | G14 | `send_user_input_request()` | Request human help | | G11 | G02 | `update_flight_status("BLOCKED")` | Block processing | ### Optimization & Results | Source | Target | Method | Purpose | |--------|--------|--------|---------| | G10 | H03 | `huber_loss()`, `cauchy_loss()` | Apply robust kernels | | G10 | Internal | `optimize()` | Run iSAM2 optimization | | G10 | G12 | `get_trajectory()` | Get optimized poses | | G12 | H01 | `project()`, `unproject()` | Camera operations | | G12 | H02 | `compute_gsd()` | GSD calculations | | G12 | H06 | `tile_to_latlon()` | Coordinate transforms | | G12 | G13 | Frame GPS + object coords | Provide results | | G13 | G03 | `update_route_waypoint()` | Per-frame Route API update | | G03 | Route API | `PUT /routes/.../waypoints/...` | HTTP call | | G13 | G14 | `send_frame_result()` | Publish to client | | G14 | Client | SSE `frame_processed` | Real-time delivery | | G13 | G17 | `save_flight_state()` | Persist state | ### User Input Recovery | Source | Target | Method | Purpose | |--------|--------|--------|---------| | G14 | Client | SSE `user_input_needed` | Notify client | | Client | G01 | `POST .../user-fix` | Provide anchor | | G01 | G11 | `apply_user_anchor()` | Apply fix | | G11 | G10 | `add_absolute_factor()` (high confidence) | Hard constraint | | G10 | Internal | `optimize()` | Re-optimize | | G11 | G02 | `update_flight_status("PROCESSING")` | Resume | ### Asynchronous Refinement | Source | Target | Method | Purpose | |--------|--------|--------|---------| | G10 | Internal (background) | `optimize()` | Back-propagate anchors | | G10 | G13 | `get_trajectory()` | Get refined poses | | G13 | G03 | `batch_update_waypoints()` | Batch update Route API | | G13 | G14 | `send_refinement()` × N | Send updates | | G14 | Client | SSE `frame_refined` × N | Incremental updates | ### Cross-Cutting Concerns | Source | Target | Method | Purpose | |--------|--------|--------|---------| | G16 | ALL | `get_*_config()` | Provide configuration | | H05 | G07, G08, G09, G10, G11 | `start_timer()`, `end_timer()` | Performance monitoring | --- ## Interaction Coverage Verification ✅ **Initialization**: G02→G15, G16, G17; G04→G08→H04 ✅ **Flight creation**: Client→G01→G02→G03,G04,G16,G17,G14 ✅ **Image upload**: Client→G01→G05→H08,G17 ✅ **Rotation sweep**: G06→H07,G09 (12 iterations) ✅ **Sequential VO**: G07→G15,G10,H05 ✅ **Drift correction**: G11→G09→G04(1),G10 ✅ **Tracking loss**: G11→G06,G08,G04(progressive),G09,G14,G02 ✅ **Global PR**: G08→G15,H04,G04 ✅ **Optimization**: G10→H03,G12 ✅ **Coordinate transform**: G12→H01,H02,H06 ✅ **Results**: G12→G13→G03,G14,G17 ✅ **User input**: Client→G01→G11→G10,G02 ✅ **Refinement**: G10→G13→G03,G14 ✅ **Configuration**: G16→ALL ✅ **Performance**: H05→processing components **All major component interactions are covered.** --- ## Deliverables **Component Count**: 29 total - Route API: 4 (R01-R04) - GPS-Denied API: 17 (G01-G17) - Helpers: 8 (H01-H08) **For each component**, create `docs/02_components/[project]_[##]_[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** **Generate draw.io diagram** showing: - Two API projects (Route API, GPS-Denied API) - All 29 components - Route API ↔ GPS-Denied API communication - GPS-Denied → Satellite Provider calls - Rotation preprocessing flow - Progressive search expansion (1→4→9→16→25) - Per-frame Route API update flow - Helper component usage ### To-dos - [x] Create 4 Route API specs with interfaces (REST, data manager, validator, DB) - [x] Create GPS-Denied core API specs with interfaces (REST, flight manager, Route client) - [x] Create data management specs with interfaces (satellite, image pipeline, rotation) - [x] Create visual processing specs with interfaces (VO, place recognition, LiteSAM) - [x] Create coordination specs with interfaces (factor graph, failure recovery, transformer) - [x] Create results/infrastructure specs with interfaces (result manager, SSE, models, config, DB) - [x] Create 8 helper specs with interfaces - [x] Generate draw.io with all components, interactions, flows