mirror of
https://github.com/azaion/gps-denied-desktop.git
synced 2026-04-23 02:06:36 +00:00
add features
This commit is contained in:
+123
@@ -0,0 +1,123 @@
|
||||
# Feature: Chunk Lifecycle Management
|
||||
|
||||
## Name
|
||||
Chunk Lifecycle Management
|
||||
|
||||
## Description
|
||||
Core operations for creating, growing, and managing the lifecycle of route chunks. Chunks are first-class entities in the Atlas multi-map architecture, created proactively on tracking loss to continue processing without failure. This feature handles the fundamental CRUD-like operations for chunk management and maintains internal state tracking.
|
||||
|
||||
## Component APIs Implemented
|
||||
|
||||
### `create_chunk(flight_id: str, start_frame_id: int) -> ChunkHandle`
|
||||
Creates a new route chunk when tracking is lost or proactively by F11.
|
||||
- Generates unique chunk_id
|
||||
- Calls F10.create_new_chunk() to initialize subgraph
|
||||
- Initializes chunk state (unanchored, active)
|
||||
- Stores ChunkHandle in internal dictionary
|
||||
|
||||
### `add_frame_to_chunk(chunk_id: str, frame_id: int, vo_result: RelativePose) -> bool`
|
||||
Adds a frame to an active chunk during frame processing.
|
||||
- Verifies chunk exists and is active
|
||||
- Appends frame_id to chunk's frames list
|
||||
- Calls F10.add_relative_factor_to_chunk()
|
||||
- Updates end_frame_id
|
||||
|
||||
### `get_active_chunk(flight_id: str) -> Optional[ChunkHandle]`
|
||||
Retrieves the currently active chunk for a flight.
|
||||
- Queries internal state dictionary
|
||||
- Returns ChunkHandle with is_active=True or None
|
||||
|
||||
### `deactivate_chunk(chunk_id: str) -> bool`
|
||||
Deactivates a chunk after merging or completion.
|
||||
- Sets is_active=False on ChunkHandle
|
||||
- Does not delete chunk data
|
||||
|
||||
## External Tools and Services
|
||||
- **F10 Factor Graph Optimizer**: `create_new_chunk()`, `add_relative_factor_to_chunk()`
|
||||
|
||||
## Internal Methods
|
||||
|
||||
### `_generate_chunk_id() -> str`
|
||||
Generates unique chunk identifier (UUID or sequential).
|
||||
|
||||
### `_validate_chunk_active(chunk_id: str) -> bool`
|
||||
Checks if chunk exists and is_active=True.
|
||||
|
||||
### `_get_chunk_by_id(chunk_id: str) -> Optional[ChunkHandle]`
|
||||
Internal lookup in _chunks dictionary.
|
||||
|
||||
### `_update_chunk_end_frame(chunk_id: str, frame_id: int)`
|
||||
Updates end_frame_id after adding frame.
|
||||
|
||||
## Unit Tests
|
||||
|
||||
### Test: create_chunk_returns_active_handle
|
||||
- Call create_chunk(flight_id, start_frame_id)
|
||||
- Assert returned ChunkHandle has is_active=True
|
||||
- Assert chunk_id is non-empty string
|
||||
- Assert start_frame_id matches input
|
||||
|
||||
### Test: create_chunk_calls_f10
|
||||
- Call create_chunk()
|
||||
- Assert F10.create_new_chunk() was called with correct parameters
|
||||
|
||||
### Test: create_multiple_chunks_same_flight
|
||||
- Create chunk_1 and chunk_2 for same flight
|
||||
- Assert both chunks exist with different chunk_ids
|
||||
|
||||
### Test: add_frame_to_active_chunk
|
||||
- Create chunk
|
||||
- Call add_frame_to_chunk() with valid frame
|
||||
- Assert returns True
|
||||
- Assert frame_id in chunk.frames
|
||||
|
||||
### Test: add_frame_updates_end_frame_id
|
||||
- Create chunk with start_frame_id=10
|
||||
- Add frames 11, 12, 13
|
||||
- Assert end_frame_id=13
|
||||
|
||||
### Test: add_frame_to_inactive_chunk_fails
|
||||
- Create chunk, then deactivate_chunk()
|
||||
- Call add_frame_to_chunk()
|
||||
- Assert returns False
|
||||
|
||||
### Test: add_frame_to_nonexistent_chunk_fails
|
||||
- Call add_frame_to_chunk("invalid_id", ...)
|
||||
- Assert returns False
|
||||
|
||||
### Test: get_active_chunk_returns_correct_chunk
|
||||
- Create chunk for flight_1
|
||||
- Assert get_active_chunk(flight_1) returns chunk
|
||||
- Assert get_active_chunk(flight_2) returns None
|
||||
|
||||
### Test: get_active_chunk_none_when_deactivated
|
||||
- Create chunk, then deactivate
|
||||
- Assert get_active_chunk() returns None
|
||||
|
||||
### Test: deactivate_chunk_success
|
||||
- Create chunk
|
||||
- Call deactivate_chunk()
|
||||
- Assert returns True
|
||||
- Assert chunk.is_active=False
|
||||
|
||||
### Test: deactivate_nonexistent_chunk_fails
|
||||
- Call deactivate_chunk("invalid_id")
|
||||
- Assert returns False
|
||||
|
||||
## Integration Tests
|
||||
|
||||
### Test: chunk_lifecycle_flow
|
||||
1. create_chunk() → verify ChunkHandle
|
||||
2. add_frame_to_chunk() × 10 → verify frames list grows
|
||||
3. get_active_chunk() → returns the chunk
|
||||
4. deactivate_chunk() → chunk deactivated
|
||||
5. get_active_chunk() → returns None
|
||||
|
||||
### Test: multiple_chunks_isolation
|
||||
1. Create chunk_1 (flight_A)
|
||||
2. Create chunk_2 (flight_A)
|
||||
3. Add frames to chunk_1
|
||||
4. Add frames to chunk_2
|
||||
5. Verify frames lists are independent
|
||||
6. Verify only one can be active at a time per flight
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
# Feature: Chunk Data Retrieval
|
||||
|
||||
## Name
|
||||
Chunk Data Retrieval
|
||||
|
||||
## Description
|
||||
Query operations for retrieving chunk data including frame lists, images, estimated bounds, and composite descriptors. These methods provide data to other components (F08, F09, F11) for matching and recovery operations. The feature handles data aggregation and transformation without modifying chunk state.
|
||||
|
||||
## Component APIs Implemented
|
||||
|
||||
### `get_chunk_frames(chunk_id: str) -> List[int]`
|
||||
Retrieves ordered list of frame IDs in a chunk.
|
||||
- Returns frames list from ChunkHandle
|
||||
- Ordered by sequence (insertion order)
|
||||
|
||||
### `get_chunk_images(chunk_id: str) -> List[np.ndarray]`
|
||||
Retrieves images for all frames in a chunk.
|
||||
- Calls F05.get_image_by_sequence() for each frame
|
||||
- Returns images in frame order
|
||||
|
||||
### `get_chunk_bounds(chunk_id: str) -> ChunkBounds`
|
||||
Estimates GPS bounds of a chunk based on VO trajectory.
|
||||
- Computes estimated center from relative poses
|
||||
- Calculates radius from trajectory extent
|
||||
- Returns confidence based on anchor status
|
||||
|
||||
### `get_chunk_composite_descriptor(chunk_id: str) -> np.ndarray`
|
||||
Computes aggregate DINOv2 descriptor for semantic matching.
|
||||
- Retrieves chunk images
|
||||
- Calls F08.compute_chunk_descriptor() with aggregation strategy
|
||||
- Returns 4096-dim or 8192-dim vector
|
||||
|
||||
## External Tools and Services
|
||||
- **F05 Image Input Pipeline**: `get_image_by_sequence()`
|
||||
- **F08 Global Place Recognition**: `compute_chunk_descriptor()`
|
||||
|
||||
## Internal Methods
|
||||
|
||||
### `_compute_trajectory_extent(chunk_id: str) -> Tuple[float, float]`
|
||||
Calculates trajectory spread from VO poses for bounds estimation.
|
||||
|
||||
### `_estimate_center_from_poses(chunk_id: str) -> GPSPoint`
|
||||
Estimates center GPS from accumulated relative poses and last known anchor.
|
||||
|
||||
### `_calculate_bounds_confidence(chunk_id: str) -> float`
|
||||
Returns confidence (0.0-1.0) based on anchor status and trajectory length.
|
||||
|
||||
## Unit Tests
|
||||
|
||||
### Test: get_chunk_frames_returns_ordered_list
|
||||
- Create chunk, add frames 10, 11, 12
|
||||
- Assert get_chunk_frames() returns [10, 11, 12]
|
||||
|
||||
### Test: get_chunk_frames_empty_chunk
|
||||
- Create chunk without adding frames
|
||||
- Assert get_chunk_frames() returns [start_frame_id] only
|
||||
|
||||
### Test: get_chunk_frames_nonexistent_chunk
|
||||
- Call get_chunk_frames("invalid_id")
|
||||
- Assert returns empty list or raises exception
|
||||
|
||||
### Test: get_chunk_images_returns_correct_count
|
||||
- Create chunk with 5 frames
|
||||
- Mock F05.get_image_by_sequence()
|
||||
- Assert get_chunk_images() returns 5 images
|
||||
|
||||
### Test: get_chunk_images_preserves_order
|
||||
- Create chunk with frames [10, 11, 12]
|
||||
- Assert images returned in same order as frames
|
||||
|
||||
### Test: get_chunk_bounds_unanchored
|
||||
- Create unanchored chunk with 10 frames
|
||||
- Assert get_chunk_bounds().confidence < 0.5
|
||||
- Assert estimated_radius > 0
|
||||
|
||||
### Test: get_chunk_bounds_anchored
|
||||
- Create chunk, mark as anchored
|
||||
- Assert get_chunk_bounds().confidence > 0.7
|
||||
|
||||
### Test: get_chunk_composite_descriptor_shape
|
||||
- Create chunk with 10 frames
|
||||
- Mock F08.compute_chunk_descriptor()
|
||||
- Assert descriptor has expected dimensions (4096 or 8192)
|
||||
|
||||
### Test: get_chunk_composite_descriptor_calls_f08
|
||||
- Create chunk
|
||||
- Call get_chunk_composite_descriptor()
|
||||
- Assert F08.compute_chunk_descriptor() called with chunk images
|
||||
|
||||
## Integration Tests
|
||||
|
||||
### Test: chunk_descriptor_computation
|
||||
1. Create chunk with 10 frames
|
||||
2. get_chunk_images() → 10 images
|
||||
3. get_chunk_composite_descriptor() → aggregated descriptor
|
||||
4. Verify descriptor shape and non-zero values
|
||||
|
||||
### Test: chunk_bounds_accuracy
|
||||
1. Create chunk with known anchor
|
||||
2. Add 10 frames with VO results
|
||||
3. get_chunk_bounds() → verify center near anchor
|
||||
4. Verify radius reasonable for trajectory length
|
||||
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
# Feature: Chunk Matching Coordination
|
||||
|
||||
## Name
|
||||
Chunk Matching Coordination
|
||||
|
||||
## Description
|
||||
Operations related to the chunk matching workflow including readiness checks, matching status tracking, anchoring, and merging. This feature implements transactional integrity with F10 Factor Graph Optimizer using "Check-Act" pattern: F10 is called first, and only on success is internal state updated. Critical for the Atlas multi-map architecture where chunks are matched and merged into the global trajectory.
|
||||
|
||||
## Component APIs Implemented
|
||||
|
||||
### `is_chunk_ready_for_matching(chunk_id: str) -> bool`
|
||||
Checks if chunk meets criteria for satellite matching attempt.
|
||||
- Min frames: >= 5 (configurable)
|
||||
- Max frames: <= 20 (configurable)
|
||||
- Not already matched (status != "anchored" or "merged")
|
||||
|
||||
### `get_chunks_for_matching(flight_id: str) -> List[ChunkHandle]`
|
||||
Retrieves all unanchored chunks ready for matching.
|
||||
- Filters by flight_id
|
||||
- Returns chunks with matching_status="unanchored" and is_ready_for_matching=True
|
||||
|
||||
### `mark_chunk_matching(chunk_id: str) -> bool`
|
||||
Marks chunk as currently being matched.
|
||||
- Updates matching_status to "matching"
|
||||
- Prevents duplicate matching attempts
|
||||
|
||||
### `mark_chunk_anchored(chunk_id: str, frame_id: int, gps: GPSPoint) -> bool`
|
||||
Anchors chunk to GPS coordinate after successful satellite matching.
|
||||
- **Transactional**: Calls F10.add_chunk_anchor() first
|
||||
- On success: Updates has_anchor, anchor_frame_id, anchor_gps, matching_status="anchored"
|
||||
- On failure: Returns False, no state change
|
||||
|
||||
### `merge_chunks(main_chunk_id: str, new_chunk_id: str, transform: Sim3Transform) -> bool`
|
||||
Merges new_chunk INTO main_chunk using Sim(3) transformation.
|
||||
- Resolves flight_id from internal ChunkHandle for main_chunk_id
|
||||
- **Transactional**: Calls F10.merge_chunk_subgraphs() first
|
||||
- On success: new_chunk marked "merged" and deactivated, main_chunk extended
|
||||
- On failure: Returns False, no state change
|
||||
|
||||
## External Tools and Services
|
||||
- **F10 Factor Graph Optimizer**: `add_chunk_anchor()`, `merge_chunk_subgraphs()`
|
||||
- **F03 Flight Database**: `save_chunk_state()` (after merge)
|
||||
|
||||
## Internal Methods
|
||||
|
||||
### `_check_matching_criteria(chunk_id: str) -> bool`
|
||||
Validates chunk meets all matching readiness criteria.
|
||||
|
||||
### `_get_matching_status(chunk_id: str) -> str`
|
||||
Returns current matching_status from ChunkHandle.
|
||||
|
||||
### `_update_anchor_state(chunk_id: str, frame_id: int, gps: GPSPoint)`
|
||||
Updates ChunkHandle with anchor information after successful F10 call.
|
||||
|
||||
### `_mark_chunk_merged(chunk_id: str)`
|
||||
Updates new_chunk state after successful merge operation.
|
||||
|
||||
## Unit Tests
|
||||
|
||||
### Test: is_chunk_ready_min_frames
|
||||
- Create chunk with 3 frames
|
||||
- Assert is_chunk_ready_for_matching() returns False
|
||||
- Add 2 more frames (total 5)
|
||||
- Assert is_chunk_ready_for_matching() returns True
|
||||
|
||||
### Test: is_chunk_ready_max_frames
|
||||
- Create chunk with 21 frames
|
||||
- Assert is_chunk_ready_for_matching() returns False
|
||||
|
||||
### Test: is_chunk_ready_already_anchored
|
||||
- Create chunk, mark as anchored
|
||||
- Assert is_chunk_ready_for_matching() returns False
|
||||
|
||||
### Test: get_chunks_for_matching_filters_correctly
|
||||
- Create 3 chunks: unanchored+ready, anchored, unanchored+not_ready
|
||||
- Assert get_chunks_for_matching() returns only first chunk
|
||||
|
||||
### Test: get_chunks_for_matching_filters_by_flight
|
||||
- Create chunks for flight_A and flight_B
|
||||
- Assert get_chunks_for_matching(flight_A) returns only flight_A chunks
|
||||
|
||||
### Test: mark_chunk_matching_updates_status
|
||||
- Create chunk
|
||||
- Call mark_chunk_matching()
|
||||
- Assert matching_status="matching"
|
||||
|
||||
### Test: mark_chunk_anchored_transactional_success
|
||||
- Create chunk
|
||||
- Mock F10.add_chunk_anchor() returns success
|
||||
- Call mark_chunk_anchored()
|
||||
- Assert returns True
|
||||
- Assert has_anchor=True, anchor_gps set, matching_status="anchored"
|
||||
|
||||
### Test: mark_chunk_anchored_transactional_failure
|
||||
- Create chunk
|
||||
- Mock F10.add_chunk_anchor() returns failure
|
||||
- Call mark_chunk_anchored()
|
||||
- Assert returns False
|
||||
- Assert has_anchor=False (no state change)
|
||||
|
||||
### Test: merge_chunks_transactional_success
|
||||
- Create main_chunk and new_chunk
|
||||
- Mock F10.merge_chunk_subgraphs() returns success
|
||||
- Call merge_chunks()
|
||||
- Assert returns True
|
||||
- Assert new_chunk.is_active=False
|
||||
- Assert new_chunk.matching_status="merged"
|
||||
|
||||
### Test: merge_chunks_transactional_failure
|
||||
- Create main_chunk and new_chunk
|
||||
- Mock F10.merge_chunk_subgraphs() returns failure
|
||||
- Call merge_chunks()
|
||||
- Assert returns False
|
||||
- Assert new_chunk state unchanged
|
||||
|
||||
### Test: merge_chunks_resolves_flight_id
|
||||
- Create main_chunk for flight_A
|
||||
- Verify merge_chunks() calls F10 with correct flight_id from ChunkHandle
|
||||
|
||||
## Integration Tests
|
||||
|
||||
### Test: chunk_matching_workflow
|
||||
1. create_chunk() with 10 frames
|
||||
2. is_chunk_ready_for_matching() → True
|
||||
3. mark_chunk_matching() → status="matching"
|
||||
4. mark_chunk_anchored() → status="anchored"
|
||||
5. is_chunk_ready_for_matching() → False
|
||||
|
||||
### Test: chunk_merge_workflow
|
||||
1. Create main_chunk (frames 1-10), new_chunk (frames 20-30)
|
||||
2. Anchor new_chunk via mark_chunk_anchored()
|
||||
3. merge_chunks(main_chunk, new_chunk, transform)
|
||||
4. Verify new_chunk deactivated and marked "merged"
|
||||
5. Verify main_chunk still active
|
||||
|
||||
### Test: transactional_integrity_anchor
|
||||
1. Create chunk
|
||||
2. Configure F10.add_chunk_anchor() to fail
|
||||
3. Call mark_chunk_anchored()
|
||||
4. Verify chunk state unchanged
|
||||
5. Configure F10.add_chunk_anchor() to succeed
|
||||
6. Call mark_chunk_anchored()
|
||||
7. Verify chunk state updated
|
||||
|
||||
### Test: transactional_integrity_merge
|
||||
1. Create main_chunk and new_chunk
|
||||
2. Configure F10.merge_chunk_subgraphs() to fail
|
||||
3. Call merge_chunks()
|
||||
4. Verify both chunks' state unchanged
|
||||
5. Configure F10.merge_chunk_subgraphs() to succeed
|
||||
6. Call merge_chunks()
|
||||
7. Verify new_chunk state updated
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
# Feature: Chunk State Persistence
|
||||
|
||||
## Name
|
||||
Chunk State Persistence
|
||||
|
||||
## Description
|
||||
Persistence operations for saving and loading chunk state via F03 Flight Database. Enables system recovery after restarts and maintains chunk state across processing sessions. Serializes internal _chunks dictionary to persistent storage.
|
||||
|
||||
## Component APIs Implemented
|
||||
|
||||
### `save_chunk_state(flight_id: str) -> bool`
|
||||
Persists all chunk state for a flight.
|
||||
- Serializes ChunkHandles for specified flight
|
||||
- Calls F03.save_chunk_state()
|
||||
- Returns success status
|
||||
|
||||
### `load_chunk_state(flight_id: str) -> bool`
|
||||
Loads chunk state for a flight from persistent storage.
|
||||
- Calls F03.load_chunk_states()
|
||||
- Deserializes and populates internal _chunks dictionary
|
||||
- Returns success status
|
||||
|
||||
## External Tools and Services
|
||||
- **F03 Flight Database**: `save_chunk_state()`, `load_chunk_states()`
|
||||
|
||||
## Internal Methods
|
||||
|
||||
### `_serialize_chunks(flight_id: str) -> Dict`
|
||||
Converts ChunkHandles to serializable dictionary format.
|
||||
|
||||
### `_deserialize_chunks(data: Dict) -> Dict[str, ChunkHandle]`
|
||||
Reconstructs ChunkHandles from serialized data.
|
||||
|
||||
### `_filter_chunks_by_flight(flight_id: str) -> List[ChunkHandle]`
|
||||
Filters internal _chunks dictionary by flight_id.
|
||||
|
||||
### `_merge_loaded_chunks(chunks: Dict[str, ChunkHandle])`
|
||||
Merges loaded chunks into internal state without overwriting existing.
|
||||
|
||||
## Unit Tests
|
||||
|
||||
### Test: save_chunk_state_calls_f03
|
||||
- Create chunks for flight_A
|
||||
- Call save_chunk_state(flight_A)
|
||||
- Assert F03.save_chunk_state() called with serialized data
|
||||
|
||||
### Test: save_chunk_state_filters_by_flight
|
||||
- Create chunks for flight_A and flight_B
|
||||
- Call save_chunk_state(flight_A)
|
||||
- Assert only flight_A chunks serialized
|
||||
|
||||
### Test: save_chunk_state_success
|
||||
- Create chunks
|
||||
- Mock F03.save_chunk_state() returns success
|
||||
- Assert save_chunk_state() returns True
|
||||
|
||||
### Test: save_chunk_state_failure
|
||||
- Create chunks
|
||||
- Mock F03.save_chunk_state() returns failure
|
||||
- Assert save_chunk_state() returns False
|
||||
|
||||
### Test: load_chunk_state_populates_internal_dict
|
||||
- Mock F03.load_chunk_states() returns chunk data
|
||||
- Call load_chunk_state(flight_A)
|
||||
- Assert internal _chunks dictionary populated
|
||||
|
||||
### Test: load_chunk_state_success
|
||||
- Mock F03.load_chunk_states() returns success
|
||||
- Assert load_chunk_state() returns True
|
||||
|
||||
### Test: load_chunk_state_failure
|
||||
- Mock F03.load_chunk_states() returns failure
|
||||
- Assert load_chunk_state() returns False
|
||||
|
||||
### Test: load_chunk_state_empty_flight
|
||||
- Mock F03.load_chunk_states() returns empty
|
||||
- Call load_chunk_state(flight_A)
|
||||
- Assert returns True (no error)
|
||||
- Assert no chunks loaded
|
||||
|
||||
### Test: serialize_preserves_all_fields
|
||||
- Create chunk with all fields populated (anchor, frames, status)
|
||||
- Serialize and deserialize
|
||||
- Assert all fields match original
|
||||
|
||||
### Test: deserialize_handles_missing_optional_fields
|
||||
- Create serialized data with optional fields missing
|
||||
- Deserialize
|
||||
- Assert ChunkHandle created with default values
|
||||
|
||||
## Integration Tests
|
||||
|
||||
### Test: save_load_roundtrip
|
||||
1. Create chunks with various states (active, anchored, merged)
|
||||
2. save_chunk_state()
|
||||
3. Clear internal state
|
||||
4. load_chunk_state()
|
||||
5. Verify all chunks restored with correct state
|
||||
|
||||
### Test: persistence_across_restart
|
||||
1. Create flight with chunks
|
||||
2. Process frames, anchor some chunks
|
||||
3. save_chunk_state()
|
||||
4. Simulate restart (new instance)
|
||||
5. load_chunk_state()
|
||||
6. Verify can continue processing
|
||||
|
||||
### Test: partial_state_recovery
|
||||
1. Create chunks for multiple flights
|
||||
2. save_chunk_state(flight_A)
|
||||
3. Clear internal state
|
||||
4. load_chunk_state(flight_A)
|
||||
5. Verify only flight_A chunks loaded
|
||||
|
||||
Reference in New Issue
Block a user