mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-22 22:46:36 +00:00
4f8c18a066
gen_tests updated solution.md updated
365 lines
14 KiB
Markdown
365 lines
14 KiB
Markdown
<!-- 31098ee5-58fb-474a-815e-fd9cbd17c063 9f609f9e-c80d-4c88-b618-3135b96a8333 -->
|
||
# 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
|
||
|