mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-22 22:46:36 +00:00
component assesment and fixes done
This commit is contained in:
@@ -38,6 +38,12 @@ class IRouteChunkManager(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def mark_chunk_anchored(self, chunk_id: str, frame_id: int, gps: GPSPoint) -> bool:
|
||||
"""
|
||||
Transactional update:
|
||||
1. Calls F10.add_chunk_anchor().
|
||||
2. IF success: Updates internal state to 'anchored'.
|
||||
3. Returns success status.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
@@ -54,7 +60,12 @@ class IRouteChunkManager(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def merge_chunks(self, target_chunk_id: str, source_chunk_id: str, transform: Sim3Transform) -> bool:
|
||||
"""Merges source_chunk INTO target_chunk. Result is stored in target_chunk."""
|
||||
"""
|
||||
Transactional update:
|
||||
1. Calls F10.merge_chunk_subgraphs().
|
||||
2. IF success: Updates internal state (source merged/deactivated).
|
||||
3. Returns success status.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
@@ -63,40 +74,23 @@ class IRouteChunkManager(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def save_chunk_state(self, flight_id: str) -> bool:
|
||||
"""Persist all chunk state to F03 for crash recovery."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def load_chunk_state(self, flight_id: str) -> bool:
|
||||
"""Load chunk state from F03 on restart."""
|
||||
pass
|
||||
```
|
||||
|
||||
## Component Description
|
||||
|
||||
### Responsibilities
|
||||
- **Source of truth for chunk state** (active, anchored, merged status)
|
||||
- Manage chunk lifecycle (creation, activation, deactivation, merging)
|
||||
- Track chunk state (frames, anchors, matching status)
|
||||
- Provide chunk representations for matching (composite images, descriptors)
|
||||
- Determine chunk readiness for matching (min frames, consistency)
|
||||
- Persist chunk state via F03 Flight Database
|
||||
- **Source of Truth**: Manages chunk states (Active, Matching, Anchored, Merged).
|
||||
- **Transactional Integrity**: Ensures internal state updates are atomic with respect to Factor Graph (F10) operations.
|
||||
- **Implementation**: Uses "Check-Act" pattern. Calls F10 first; if F10 fails, F12 does not update state and returns error.
|
||||
|
||||
### Chunk Responsibility Clarification
|
||||
|
||||
**F12 is the high-level chunk manager**:
|
||||
- Owns chunk state (ChunkHandle with matching_status, is_active, has_anchor)
|
||||
- Provides high-level queries: `get_active_chunk()`, `get_chunks_for_matching()`
|
||||
- Coordinates with F10 for factor graph operations
|
||||
- Persists chunk state for crash recovery
|
||||
|
||||
**F10 provides low-level factor graph operations** (see F10 spec):
|
||||
- Subgraph creation and factor management
|
||||
- Does NOT own chunk state - only factor graph data
|
||||
|
||||
**F11 coordinates recovery** (see F11 spec):
|
||||
- Calls F12 for chunk operations
|
||||
- F11 NEVER directly calls F10 chunk methods
|
||||
### Interaction
|
||||
- Called by **F02.2 Flight Processing Engine** and **F11 Failure Recovery Coordinator** (via F02.2 or direct delegation).
|
||||
- Calls **F10 Factor Graph Optimizer**.
|
||||
|
||||
### Scope
|
||||
- Chunk lifecycle management
|
||||
@@ -108,10 +102,10 @@ class IRouteChunkManager(ABC):
|
||||
|
||||
### `create_chunk(flight_id: str, start_frame_id: int) -> ChunkHandle`
|
||||
|
||||
**Description**: Creates a new route chunk and initializes it in the factor graph.
|
||||
**Description**: Initializes a new route chunk.
|
||||
|
||||
**Called By**:
|
||||
- F02 Flight Processor (when tracking lost)
|
||||
- F02.2 Flight Processing Engine (when tracking lost)
|
||||
- F11 Failure Recovery Coordinator (proactive chunk creation)
|
||||
|
||||
**Input**:
|
||||
@@ -151,10 +145,10 @@ ChunkHandle:
|
||||
|
||||
### `add_frame_to_chunk(chunk_id: str, frame_id: int, vo_result: RelativePose) -> bool`
|
||||
|
||||
**Description**: Adds a frame to an existing chunk with its VO result.
|
||||
**Description**: Adds a frame to an active chunk.
|
||||
|
||||
**Called By**:
|
||||
- F02 Flight Processor (during frame processing)
|
||||
- F02.2 Flight Processing Engine (during frame processing)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
@@ -192,20 +186,9 @@ bool: True if frame added successfully
|
||||
- F09 Metric Refinement (for chunk LiteSAM matching)
|
||||
- F11 Failure Recovery Coordinator (chunk state queries)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
chunk_id: str
|
||||
```
|
||||
**Input**: `chunk_id: str`
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
List[int] # Frame IDs in chunk, ordered by sequence
|
||||
```
|
||||
|
||||
**Test Cases**:
|
||||
1. **Get frames**: Returns all frames in chunk
|
||||
2. **Empty chunk**: Returns empty list
|
||||
3. **Ordered frames**: Frames returned in sequence order
|
||||
**Output**: `List[int]` # Frame IDs in chunk, ordered by sequence
|
||||
|
||||
---
|
||||
|
||||
@@ -218,25 +201,7 @@ List[int] # Frame IDs in chunk, ordered by sequence
|
||||
- F09 Metric Refinement (chunk LiteSAM matching)
|
||||
- F06 Image Rotation Manager (chunk rotation)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
chunk_id: str
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
List[np.ndarray] # Images for each frame in chunk
|
||||
```
|
||||
|
||||
**Processing Flow**:
|
||||
1. Get chunk frames via get_chunk_frames()
|
||||
2. Load images from F05 Image Input Pipeline
|
||||
3. Return list of images
|
||||
|
||||
**Test Cases**:
|
||||
1. **Get images**: Returns all images in chunk
|
||||
2. **Image loading**: Images loaded correctly from pipeline
|
||||
3. **Order consistency**: Images match frame order
|
||||
**Output**: `List[np.ndarray]` # Images for each frame in chunk
|
||||
|
||||
---
|
||||
|
||||
@@ -247,30 +212,7 @@ List[np.ndarray] # Images for each frame in chunk
|
||||
**Called By**:
|
||||
- F08 Global Place Recognition (chunk semantic matching)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
chunk_id: str
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
np.ndarray: Aggregated descriptor vector (4096-dim or 8192-dim)
|
||||
```
|
||||
|
||||
**Processing Flow**:
|
||||
1. Get chunk images via get_chunk_images()
|
||||
2. Call F08.compute_chunk_descriptor(chunk_images) → aggregate descriptor
|
||||
3. Return composite descriptor
|
||||
|
||||
**Delegation**:
|
||||
- Delegates to F08.compute_chunk_descriptor() for descriptor computation
|
||||
- F08 handles aggregation logic (mean, VLAD, or max)
|
||||
- Single source of truth for chunk descriptor computation
|
||||
|
||||
**Test Cases**:
|
||||
1. **Compute descriptor**: Returns aggregated descriptor
|
||||
2. **Multiple images**: Descriptor aggregates correctly
|
||||
3. **Descriptor quality**: More robust than single-image descriptor
|
||||
**Output**: `np.ndarray`: Aggregated descriptor vector (4096-dim or 8192-dim)
|
||||
|
||||
---
|
||||
|
||||
@@ -282,11 +224,6 @@ np.ndarray: Aggregated descriptor vector (4096-dim or 8192-dim)
|
||||
- F11 Failure Recovery Coordinator (for tile search area)
|
||||
- F04 Satellite Data Manager (for tile prefetching)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
chunk_id: str
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
ChunkBounds:
|
||||
@@ -295,58 +232,23 @@ ChunkBounds:
|
||||
confidence: float
|
||||
```
|
||||
|
||||
**Processing Flow**:
|
||||
1. Get chunk trajectory from F10.get_chunk_trajectory()
|
||||
2. If chunk has anchor:
|
||||
- Use anchor GPS as center
|
||||
- Compute radius from trajectory extent
|
||||
3. If chunk unanchored:
|
||||
- Estimate center from VO trajectory (relative to start)
|
||||
- Use dead-reckoning estimate
|
||||
- Lower confidence
|
||||
4. Return ChunkBounds
|
||||
|
||||
**Test Cases**:
|
||||
1. **Anchored chunk**: Returns accurate bounds with high confidence
|
||||
2. **Unanchored chunk**: Returns estimated bounds with lower confidence
|
||||
3. **Bounds calculation**: Radius computed from trajectory extent
|
||||
|
||||
---
|
||||
|
||||
### `is_chunk_ready_for_matching(chunk_id: str) -> bool`
|
||||
|
||||
**Description**: Determines if chunk has enough frames and consistency for matching.
|
||||
|
||||
**Called By**:
|
||||
- F11 Failure Recovery Coordinator (before attempting matching)
|
||||
- Background matching task
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
chunk_id: str
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
bool: True if chunk ready for matching
|
||||
```
|
||||
**Description**: Checks if a chunk has enough data (frames, spread) to attempt satellite matching.
|
||||
|
||||
**Criteria**:
|
||||
- **Min frames**: >= 5 frames (configurable)
|
||||
- **Max frames**: <= 20 frames (configurable, prevents oversized chunks)
|
||||
- **Internal consistency**: VO factors have reasonable inlier counts
|
||||
- **Not already matched**: matching_status != "anchored" or "merged"
|
||||
|
||||
**Test Cases**:
|
||||
1. **Ready chunk**: 10 frames, good consistency → True
|
||||
2. **Too few frames**: 3 frames → False
|
||||
3. **Already anchored**: has_anchor=True → False
|
||||
- Min frames: >= 5 frames (configurable)
|
||||
- Max frames: <= 20 frames (configurable, prevents oversized chunks)
|
||||
- Internal consistency: VO factors have reasonable inlier counts
|
||||
- Not already matched: matching_status != "anchored" or "merged"
|
||||
|
||||
---
|
||||
|
||||
### `mark_chunk_anchored(chunk_id: str, frame_id: int, gps: GPSPoint) -> bool`
|
||||
|
||||
**Description**: Marks chunk as anchored with GPS coordinate.
|
||||
**Description**: Anchors a chunk to a specific GPS coordinate (e.g., from successful satellite matching).
|
||||
|
||||
**Called By**:
|
||||
- F11 Failure Recovery Coordinator (after successful chunk matching)
|
||||
@@ -358,17 +260,15 @@ frame_id: int # Frame within chunk that was anchored
|
||||
gps: GPSPoint
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
bool: True if marked successfully
|
||||
```
|
||||
**Output**: `bool` - True if marked successfully
|
||||
|
||||
**Processing Flow**:
|
||||
1. Verify chunk exists
|
||||
2. Call F10.add_chunk_anchor()
|
||||
3. Update chunk state (has_anchor=True, anchor_frame_id, anchor_gps)
|
||||
4. Update matching_status to "anchored"
|
||||
5. Trigger chunk optimization
|
||||
3. If successful:
|
||||
- Update chunk state (has_anchor=True, anchor_frame_id, anchor_gps)
|
||||
- Update matching_status to "anchored"
|
||||
- Trigger chunk optimization
|
||||
|
||||
**Test Cases**:
|
||||
1. **Mark anchored**: Chunk state updated correctly
|
||||
@@ -383,30 +283,8 @@ bool: True if marked successfully
|
||||
|
||||
**Called By**:
|
||||
- F11 Failure Recovery Coordinator (background matching task)
|
||||
- Background processing task
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
flight_id: str
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
List[ChunkHandle] # Unanchored chunks ready for matching
|
||||
```
|
||||
|
||||
**Processing Flow**:
|
||||
1. Get all chunks for flight_id
|
||||
2. Filter chunks where:
|
||||
- has_anchor == False
|
||||
- is_chunk_ready_for_matching() == True
|
||||
- matching_status == "unanchored" or "matching"
|
||||
3. Return filtered list
|
||||
|
||||
**Test Cases**:
|
||||
1. **Get unanchored chunks**: Returns ready chunks
|
||||
2. **Filter criteria**: Only returns chunks meeting criteria
|
||||
3. **Empty result**: Returns empty list if no ready chunks
|
||||
**Output**: `List[ChunkHandle]` # Unanchored chunks ready for matching
|
||||
|
||||
---
|
||||
|
||||
@@ -415,22 +293,9 @@ List[ChunkHandle] # Unanchored chunks ready for matching
|
||||
**Description**: Gets the currently active chunk for a flight.
|
||||
|
||||
**Called By**:
|
||||
- F02 Flight Processor (before processing frame)
|
||||
- F02.2 Flight Processing Engine (before processing frame)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
flight_id: str
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
Optional[ChunkHandle] # Active chunk or None
|
||||
```
|
||||
|
||||
**Test Cases**:
|
||||
1. **Get active chunk**: Returns active chunk
|
||||
2. **No active chunk**: Returns None
|
||||
3. **Multiple chunks**: Returns only active chunk
|
||||
**Output**: `Optional[ChunkHandle]` # Active chunk or None
|
||||
|
||||
---
|
||||
|
||||
@@ -440,27 +305,9 @@ Optional[ChunkHandle] # Active chunk or None
|
||||
|
||||
**Called By**:
|
||||
- F11 Failure Recovery Coordinator (after chunk merged)
|
||||
- F02 Flight Processor (chunk lifecycle)
|
||||
- F02.2 Flight Processing Engine (chunk lifecycle)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
chunk_id: str
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
bool: True if deactivated successfully
|
||||
```
|
||||
|
||||
**Processing Flow**:
|
||||
1. Verify chunk exists
|
||||
2. Update chunk state (is_active=False)
|
||||
3. Update matching_status to "merged" if merged
|
||||
4. Return True
|
||||
|
||||
**Test Cases**:
|
||||
1. **Deactivate chunk**: Chunk marked inactive
|
||||
2. **After merge**: Matching status updated to "merged"
|
||||
**Output**: `bool` - True if deactivated successfully
|
||||
|
||||
---
|
||||
|
||||
@@ -481,35 +328,18 @@ transform: Sim3Transform:
|
||||
scale: float
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
bool: True if merge successful
|
||||
```
|
||||
**Output**: `bool` - True if merge successful
|
||||
|
||||
**Processing Flow**:
|
||||
1. Verify both chunks exist
|
||||
2. Verify source_chunk_id is anchored (has_anchor=True)
|
||||
3. Validate chunks can be merged (not already merged, not same chunk)
|
||||
4. Call F10.merge_chunk_subgraphs(flight_id, source_chunk_id, target_chunk_id, transform)
|
||||
5. Update source_chunk_id state:
|
||||
- Set is_active=False
|
||||
- Set matching_status="merged"
|
||||
- Call deactivate_chunk(source_chunk_id)
|
||||
6. target_chunk remains active (now contains merged frames)
|
||||
7. Persist chunk state via F03 Flight Database.save_chunk_state()
|
||||
8. Return True
|
||||
|
||||
**Merge Convention**:
|
||||
- `merge_chunks(target, source)` → source is merged INTO target
|
||||
- Result is stored in target_chunk
|
||||
- source_chunk is deactivated after merge
|
||||
- Example: `merge_chunks("main", "chunk_3")` merges chunk_3 into main trajectory
|
||||
|
||||
**Validation**:
|
||||
- Both chunks must exist
|
||||
- source_chunk must be anchored
|
||||
- source_chunk must not already be merged
|
||||
- target_chunk and source_chunk must be different
|
||||
1. Call F10.merge_chunk_subgraphs(flight_id, source_chunk_id, target_chunk_id, transform)
|
||||
2. If successful:
|
||||
- Update source_chunk_id state:
|
||||
- Set is_active=False
|
||||
- Set matching_status="merged"
|
||||
- Call deactivate_chunk(source_chunk_id)
|
||||
- target_chunk remains active (now contains merged frames)
|
||||
- Persist chunk state via F03 Flight Database.save_chunk_state()
|
||||
3. Return True
|
||||
|
||||
**Test Cases**:
|
||||
1. **Merge anchored chunk**: source_chunk merged into target_chunk
|
||||
@@ -525,29 +355,7 @@ bool: True if merge successful
|
||||
**Called By**:
|
||||
- F11 Failure Recovery Coordinator (when chunk matching starts)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
chunk_id: str
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
bool: True if marked successfully
|
||||
```
|
||||
|
||||
**Processing Flow**:
|
||||
1. Verify chunk exists
|
||||
2. Verify chunk is unanchored (has_anchor=False)
|
||||
3. Update matching_status to "matching"
|
||||
4. Return True
|
||||
|
||||
**State Transition**:
|
||||
- `unanchored` → `matching` (explicit transition)
|
||||
|
||||
**Test Cases**:
|
||||
1. **Mark unanchored chunk**: Status updated to "matching"
|
||||
2. **Mark already anchored chunk**: Returns False (invalid state)
|
||||
3. **Mark non-existent chunk**: Returns False
|
||||
**Output**: `bool` - True if marked successfully
|
||||
|
||||
## Integration Tests
|
||||
|
||||
@@ -600,14 +408,10 @@ bool: True if marked successfully
|
||||
## Dependencies
|
||||
|
||||
### Internal Components
|
||||
- **F10 Factor Graph Optimizer**: Chunk creation and factor management
|
||||
- **F05 Image Input Pipeline**: Image retrieval
|
||||
- **F08 Global Place Recognition**: Descriptor computation
|
||||
- **F07 Sequential VO**: VO results for chunk building
|
||||
- **F03 Flight Database**: Chunk state persistence
|
||||
|
||||
### External Dependencies
|
||||
- **numpy**: Array operations
|
||||
- **F10 Factor Graph Optimizer**: Critical dependency for subgraph operations (`create_chunk_subgraph`, `add_relative_factor_to_chunk`, `merge_chunk_subgraphs`).
|
||||
- **F03 Flight Database**: Persistence via `save_chunk_state()`, `load_chunk_states()`.
|
||||
- **F05 Image Input Pipeline**: Image retrieval via `get_image_by_sequence()` for `get_chunk_images()`.
|
||||
- **F08 Global Place Recognition**: Descriptor computation via `compute_chunk_descriptor()` for `get_chunk_composite_descriptor()`.
|
||||
|
||||
## Data Models
|
||||
|
||||
@@ -649,4 +453,3 @@ class Sim3Transform(BaseModel):
|
||||
rotation: np.ndarray # (3, 3) rotation matrix or (4,) quaternion
|
||||
scale: float # Scale factor
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user