add chunking

This commit is contained in:
Oleksandr Bezdieniezhnykh
2025-11-27 03:43:19 +02:00
parent 4f8c18a066
commit 2037870f67
43 changed files with 7041 additions and 4135 deletions
+9 -5
View File
@@ -3,7 +3,7 @@
## Overview
Comprehensive test specifications for the GPS-denied navigation system following the QA testing pyramid approach.
**Total Test Specifications**: 54
**Total Test Specifications**: 56
## Test Organization
@@ -23,8 +23,8 @@ Tests individual system components in isolation with their dependencies.
- 08: Image Rotation Manager
**Service Infrastructure (09-12)**:
- 09: REST API
- 10: SSE Event Streamer
- 09: REST API (FastAPI endpoints for flight management, image uploads, user fixes)
- 10: SSE Event Streamer (Server-Sent Events for real-time result streaming)
- 11: Flight Manager
- 12: Result Manager
@@ -71,6 +71,10 @@ Tests mapped to 10 acceptance criteria.
- 42: Degraded satellite data
- 43: Complete system validation
**Chunk-Based Recovery (55-56)**:
- 55: Chunk rotation recovery (rotation sweeps for chunks)
- 56: Multi-chunk simultaneous processing (Atlas architecture)
### GPS-Analyzed Scenario Tests (51-54): Real Data
Tests using GPS-analyzed test datasets.
@@ -108,8 +112,8 @@ Tests using GPS-analyzed test datasets.
| AC-1 | 80% < 50m error | 31, 43, 51, 54 | ✓ Covered |
| AC-2 | 60% < 20m error | 32, 43, 51, 54 | ✓ Covered |
| AC-3 | 350m outlier robust | 33, 43, 52, 54 | ✓ Covered |
| AC-4 | Sharp turn <5% overlap | 34, 43, 53, 54 | ✓ Covered |
| AC-5 | Multi-fragment connection | 35, 43 | ✓ Covered |
| AC-4 | Sharp turn <5% overlap | 34, 43, 53, 54, 55 | ✓ Covered |
| AC-5 | Multi-fragment connection | 35, 39, 43, 56 | ✓ Covered |
| AC-6 | User input after 3 failures | 36, 43 | ✓ Covered |
| AC-7 | <5s per image | 37, 43, 51, 54 | ✓ Covered |
| AC-8 | Real-time + refinement | 38, 43 | ✓ Covered |
+16 -15
View File
@@ -31,7 +31,7 @@ The API is the primary interface for external clients to interact with the GPS-d
## Input Data
### Test Case 1: Create Flight
- **Endpoint**: POST /api/v1/flights
- **Endpoint**: POST /flights
- **Payload**:
```json
{
@@ -48,60 +48,61 @@ The API is the primary interface for external clients to interact with the GPS-d
- **Expected**: 201 Created, returns flight_id
### Test Case 2: Upload Single Image
- **Endpoint**: POST /api/v1/flights/{flight_id}/images
- **Endpoint**: POST /flights/{flightId}/images
- **Payload**: Multipart form-data with AD000001.jpg
- **Headers**: Content-Type: multipart/form-data
- **Expected**: 202 Accepted, processing started
### Test Case 3: Upload Multiple Images
- **Endpoint**: POST /api/v1/flights/{flight_id}/images/batch
- **Endpoint**: POST /flights/{flightId}/images/batch
- **Payload**: AD000001-AD000010 (10 images)
- **Expected**: 202 Accepted, all images queued
### Test Case 4: Get Flight Status
- **Endpoint**: GET /api/v1/flights/{flight_id}/status
- **Endpoint**: GET /flights/{flightId}
- **Expected**: 200 OK, returns processing status and statistics
### Test Case 5: Get Results
- **Endpoint**: GET /api/v1/flights/{flight_id}/results
- **Endpoint**: GET /flights/{flightId}/results
- **Query Params**: ?format=json&include_refined=true
- **Expected**: 200 OK, returns GPS coordinates for all processed images
### Test Case 6: Get Specific Image Result
- **Endpoint**: GET /api/v1/flights/{flight_id}/images/{image_id}/result
- **Endpoint**: GET /flights/{flightId}/results?image_id={imageId}
- **Expected**: 200 OK, returns detailed result for one image
### Test Case 7: Submit User Fix (AC-6)
- **Endpoint**: POST /api/v1/flights/{flight_id}/images/{image_id}/user_fix
- **Endpoint**: POST /flights/{flightId}/user-fix
- **Payload**:
```json
{
"gps": {"lat": 48.270334, "lon": 37.374442},
"confidence": "high"
"frame_id": 15,
"uav_pixel": [3126, 2084],
"satellite_gps": {"lat": 48.270334, "lon": 37.374442}
}
```
- **Expected**: 200 OK, system incorporates user fix
- **Expected**: 200 OK, system incorporates user fix, processing resumes
### Test Case 8: List Flights
- **Endpoint**: GET /api/v1/flights
- **Endpoint**: GET /flights
- **Query Params**: ?status=active&limit=10
- **Expected**: 200 OK, returns list of flights
### Test Case 9: Delete Flight
- **Endpoint**: DELETE /api/v1/flights/{flight_id}
- **Endpoint**: DELETE /flights/{flightId}
- **Expected**: 204 No Content, flight and associated data deleted
### Test Case 10: Error Handling - Invalid Input
- **Endpoint**: POST /api/v1/flights
- **Endpoint**: POST /flights
- **Payload**: Invalid JSON or missing required fields
- **Expected**: 400 Bad Request with error details
### Test Case 11: Error Handling - Not Found
- **Endpoint**: GET /api/v1/flights/nonexistent_id
- **Endpoint**: GET /flights/nonexistent_id
- **Expected**: 404 Not Found
### Test Case 12: SSE Connection
- **Endpoint**: GET /api/v1/flights/{flight_id}/stream
- **Endpoint**: GET /flights/{flightId}/stream
- **Headers**: Accept: text/event-stream
- **Expected**: 200 OK, establishes SSE stream for real-time updates
@@ -213,7 +213,7 @@ For each test case, verify:
c. Prepare SSE test clients
2. **Test Case 1 - Single Client**:
a. Open SSE connection to /api/v1/flights/{flight_id}/stream
a. Open SSE connection to GET /flights/{flightId}/stream
b. Upload 10 images to flight
c. Collect all events
d. Verify event count and content
@@ -33,27 +33,27 @@ This is a comprehensive end-to-end test simulating real operational usage. Tests
- Prepare satellite tiles
2. **Create Flight (< 1s)**:
- POST /api/v1/flights
- POST /flights
- Payload: start_gps, altitude=400m, camera_params
- Verify: flight_id returned, state="created"
3. **Upload Images (< 30s)**:
- POST /api/v1/flights/{id}/images/batch
- POST /flights/{flightId}/images/batch
- Upload AD000001-AD000030
- Verify: All 30 queued, processing starts
4. **Monitor Processing via SSE (< 150s)**:
- Connect to /api/v1/flights/{id}/stream
- Connect to GET /flights/{flightId}/stream
- Receive "image_processed" events as each image completes
- Verify: Events received in < 1s of processing
5. **Await Completion (< 150s total)**:
- Monitor flight status
- Monitor flight status via GET /flights/{flightId}
- Wait for state="completed"
- Verify: No failures, all 30 images processed
6. **Retrieve Results (< 2s)**:
- GET /api/v1/flights/{id}/results?format=json
- GET /flights/{flightId}/results?format=json
- Download GPS coordinates for all images
- Compare with ground truth
@@ -64,7 +64,7 @@ This is a comprehensive end-to-end test simulating real operational usage. Tests
- Check: Mean error < 30m
8. **Export Results (< 5s)**:
- GET /api/v1/flights/{id}/results?format=csv
- GET /flights/{flightId}/results?format=csv
- Verify CSV matches coordinates.csv format
## Expected Results
@@ -38,7 +38,7 @@ Process baseline flight of 30 images with normal spacing (~120m between images).
- Registration rate > 95%
### Step 5: Retrieve Results
- **Action**: GET /api/v1/flights/{id}/results
- **Action**: GET /flights/{flightId}/results
- **Expected Result**: Results for all 30 images returned
### Step 6: Calculate Errors
@@ -38,7 +38,7 @@ Process same baseline flight as AC-1 test, but now validate the more stringent c
- Factor graph well-constrained
### Step 5: Retrieve Final Results
- **Action**: GET /api/v1/flights/{id}/results with latest versions
- **Action**: GET /flights/{flightId}/results?include_refined=true
- **Expected Result**: Refined GPS coordinates (post-optimization)
### Step 6: Calculate Errors
+27 -15
View File
@@ -7,10 +7,13 @@ Validate Acceptance Criterion 5 (partial): "System should try to operate when UA
**AC-5**: Connect multiple disconnected route fragments
## Preconditions
1. System with "Atlas" multi-map capability (factor graph)
2. L2 global place recognition functional
3. Geodetic map-merging logic implemented
4. Test dataset: Simulate 3 disconnected route fragments
1. System with "Atlas" multi-map capability (factor graph with native chunk support)
2. F12 Route Chunk Manager functional
3. F10 Factor Graph Optimizer with multi-chunk support
4. L2 global place recognition functional (chunk semantic matching)
5. L3 metric refinement functional (chunk LiteSAM matching)
6. Geodetic map-merging logic implemented (Sim(3) transform)
7. Test dataset: Simulate 3 disconnected route fragments
## Test Description
Test system's ability to handle completely disconnected route segments (no overlap between segments) and eventually connect them into a coherent trajectory using global GPS anchors.
@@ -36,15 +39,19 @@ Test system's ability to handle completely disconnected route segments (no overl
- **Action**: Process AD000025 after AD000010
- **Expected Result**:
- L1 fails (no overlap, large displacement ~2km)
- System detects new fragment
- Initializes Map_Fragment_2
- System **proactively creates new chunk** (Map_Fragment_2)
- Processing continues immediately in new chunk
- Chunk matching attempted asynchronously
### Step 4: Process Fragment 2 Independently
- **Action**: Process AD000025-030
- **Expected Result**:
- New sequential tracking starts
- L2 provides global localization for AD000025
- Map_Fragment_2 created with local consistency
- New sequential tracking starts in chunk_2
- Frames processed within chunk_2 context
- Relative factors added to chunk_2's subgraph
- Chunk_2 optimized independently for local consistency
- Chunk semantic matching attempted when ready (5-20 frames)
- Chunk LiteSAM matching with rotation sweeps attempted
### Step 5: Process Fragment 3
- **Action**: Process AD000050-055 after AD000030
@@ -56,9 +63,11 @@ Test system's ability to handle completely disconnected route segments (no overl
### Step 6: Global Map Merging
- **Action**: Factor graph attempts geodetic map-merging
- **Expected Result**:
- All 3 fragments have GPS anchors from L3
- All 3 chunks have GPS anchors from chunk LiteSAM matching
- Chunks merged via Sim(3) transform (translation, rotation, scale)
- Fragments aligned in global coordinate frame
- Single consistent trajectory created
- Global optimization performed
### Step 7: Validate Fragment Connections
- **Action**: Verify all 18 images have global GPS coordinates
@@ -138,15 +147,18 @@ Processing Mode: Multi-Map Atlas
- Geodetic merging aligns all maps
**Recovery Mechanisms**:
- L2 (AnyLoc) finds location for first image of new fragment
- L3 (LiteSAM) refines GPS anchor
- Factor graph creates new map fragment
- Global alignment via GPS coordinates
- **Proactive chunk creation** on tracking loss (immediate, not reactive)
- Chunk semantic matching (aggregate DINOv2) finds location for chunk
- Chunk LiteSAM matching (with rotation sweeps) refines GPS anchor
- Factor graph creates new chunk subgraph
- Sim(3) transform merges chunks into global trajectory
**Fragment Detection**:
- Large displacement (> 500m) from last image
- Low/zero overlap
- L1 failure triggers new fragment initialization
- L1 failure triggers **proactive** new chunk creation
- Chunks processed independently with local optimization
- Multiple chunks can exist simultaneously
## Notes
- AC-5 describes realistic operational scenario (multiple turns, disconnected segments)
+3 -2
View File
@@ -17,8 +17,9 @@ Validate Acceptance Criterion 6: "In case of being absolutely incapable of deter
- **Expected Result**: Event includes image needing fix (AD000005), top-3 satellite tiles for reference
### Step 3: User Provides GPS Fix
- **Action**: User submits GPS for AD000005: POST /api/v1/flights/{id}/images/AD000005/user_fix
- **Expected Result**: Fix accepted, confidence=1.0, processing resumes
- **Action**: User submits GPS for AD000005: POST /flights/{flightId}/user-fix
- **Payload**: `{"frame_id": 5, "uav_pixel": [3126, 2084], "satellite_gps": {"lat": 48.273997, "lon": 37.379828}}`
- **Expected Result**: Fix accepted, processing resumes, SSE event "user_fix_applied" sent
### Step 4: System Incorporates Fix
- **Action**: Factor graph adds user fix as high-confidence GPS anchor
@@ -0,0 +1,136 @@
# Acceptance Test: Chunk Rotation Recovery
## Summary
Validate chunk LiteSAM matching with rotation sweeps for chunks with unknown orientation (sharp turns).
## Linked Acceptance Criteria
**AC-4**: Robust to sharp turns (<5% overlap)
**AC-5**: Connect route chunks
## Preconditions
1. F12 Route Chunk Manager functional
2. F06 Image Rotation Manager with chunk rotation support
3. F09 Metric Refinement with chunk LiteSAM matching
4. F10 Factor Graph Optimizer with chunk merging
5. Test dataset: Chunk with unknown orientation (simulated sharp turn)
## Test Description
Test system's ability to match chunks with unknown orientation using rotation sweeps. When a chunk is created after a sharp turn, its orientation relative to the satellite map is unknown. The system must rotate the entire chunk to all possible angles and attempt LiteSAM matching.
## Test Steps
### Step 1: Create Chunk with Unknown Orientation
- **Action**: Simulate sharp turn scenario
- Process frames 1-10 (normal flight, heading 0°)
- Sharp turn at frame 11 (heading changes to 120°)
- Tracking lost, chunk_2 created proactively
- Process frames 11-20 in chunk_2
- **Expected Result**:
- Chunk_2 created with frames 11-20
- Chunk orientation unknown (previous heading not relevant)
- Chunk ready for matching (10 frames)
### Step 2: Chunk Semantic Matching
- **Action**: Attempt chunk semantic matching
- **Expected Result**:
- F08.compute_chunk_descriptor() → aggregate DINOv2 descriptor
- F08.retrieve_candidate_tiles_for_chunk() → returns top-5 candidate tiles
- Correct tile in top-5 candidates
### Step 3: Chunk Rotation Sweeps
- **Action**: Attempt chunk LiteSAM matching with rotation sweeps
- **Expected Result**:
- F06.try_chunk_rotation_steps() called
- For each rotation angle (0°, 30°, 60°, ..., 330°):
- F06.rotate_chunk_360() rotates all 10 images
- F09.align_chunk_to_satellite() attempts matching
- Match found at 120° rotation (correct orientation)
- Returns ChunkAlignmentResult with:
- rotation_angle: 120°
- chunk_center_gps: correct GPS
- confidence > 0.7
- Sim(3) transform computed
### Step 4: Chunk Merging
- **Action**: Merge chunk_2 to main trajectory
- **Expected Result**:
- F10.add_chunk_anchor() anchors chunk_2
- F10.merge_chunks() merges chunk_2 into chunk_1
- Sim(3) transform applied correctly
- Global trajectory consistent
### Step 5: Verify Final Trajectory
- **Action**: Verify all frames have GPS coordinates
- **Expected Result**:
- All 20 frames have GPS coordinates
- Frames 1-10: Original trajectory
- Frames 11-20: Merged chunk trajectory
- Global consistency maintained
- Accuracy: 18/20 < 50m (90%)
## Success Criteria
**Primary Criterion**:
- Chunk rotation sweeps find correct orientation (120°)
- Chunk LiteSAM matching succeeds with rotation
- Chunk merged correctly to main trajectory
**Supporting Criteria**:
- All 12 rotation angles tried
- Match found at correct angle
- Sim(3) transform computed correctly
- Final trajectory globally consistent
## Expected Results
```
Chunk Rotation Recovery:
- Chunk_2 created: frames 11-20
- Unknown orientation: previous heading (0°) not relevant
- Chunk semantic matching: correct tile in top-5
- Rotation sweeps: 12 rotations tried (0°, 30°, ..., 330°)
- Match found: 120° rotation
- Chunk center GPS: Accurate (within 20m)
- Chunk merged: Sim(3) transform applied
- Final trajectory: Globally consistent
- Accuracy: 18/20 < 50m (90%)
```
## Pass/Fail Criteria
**TEST PASSES IF**:
- Chunk rotation sweeps find match at correct angle (120°)
- Chunk LiteSAM matching succeeds
- Chunk merged correctly
- Final trajectory globally consistent
- Accuracy acceptable (≥ 80% < 50m)
**TEST FAILS IF**:
- Rotation sweeps don't find correct angle
- Chunk LiteSAM matching fails
- Chunk merging produces inconsistent trajectory
- Final accuracy below threshold
## Architecture Elements
**Chunk Rotation**:
- F06 rotates all images in chunk by same angle
- 12 rotation steps: 0°, 30°, 60°, ..., 330°
- F09 attempts LiteSAM matching for each rotation
**Chunk LiteSAM Matching**:
- Aggregate correspondences from multiple images
- More robust than single-image matching
- Handles featureless terrain better
**Chunk Merging**:
- Sim(3) transform (translation, rotation, scale)
- Critical for monocular VO scale ambiguity
- Preserves internal consistency
## Notes
- Rotation sweeps are critical for chunks from sharp turns
- Previous heading may not be relevant after sharp turn
- Chunk matching more robust than single-image matching
- Sim(3) transform accounts for scale differences
@@ -0,0 +1,170 @@
# Acceptance Test: Multi-Chunk Simultaneous Processing
## Summary
Validate system's ability to process multiple chunks simultaneously, matching and merging them asynchronously.
## Linked Acceptance Criteria
**AC-4**: Robust to sharp turns (<5% overlap)
**AC-5**: Connect route chunks (multiple chunks)
## Preconditions
1. F10 Factor Graph Optimizer with native multi-chunk support
2. F12 Route Chunk Manager functional
3. F11 Failure Recovery Coordinator with chunk orchestration
4. Test dataset: Flight with 3 disconnected segments
## Test Description
Test system's ability to handle multiple disconnected route segments simultaneously. The system should create chunks proactively, process them independently, and match/merge them asynchronously without blocking frame processing.
## Test Steps
### Step 1: Create Multi-Segment Flight
- **Action**: Create flight with 3 disconnected segments:
- Segment 1: AD000001-010 (10 frames, sequential)
- Segment 2: AD000025-030 (6 frames, no overlap with Segment 1)
- Segment 3: AD000050-055 (6 frames, no overlap with Segments 1 or 2)
- **Expected Result**: Flight created with all 22 images
### Step 2: Process Segment 1
- **Action**: Process AD000001-010
- **Expected Result**:
- Chunk_1 created (frames 1-10)
- Sequential VO provides relative factors
- Factors added to chunk_1's subgraph
- Chunk_1 optimized independently
- GPS anchors from LiteSAM matching
- Chunk_1 anchored and merged to main trajectory
### Step 3: Detect Discontinuity (Segment 1 → 2)
- **Action**: Process AD000025 after AD000010
- **Expected Result**:
- Tracking lost detected (large displacement ~2km)
- **Chunk_2 created proactively** (immediate, not reactive)
- Processing continues immediately in chunk_2
- Chunk_1 remains in factor graph (not deleted)
### Step 4: Process Segment 2 Independently
- **Action**: Process AD000025-030
- **Expected Result**:
- Frames processed in chunk_2 context
- Relative factors added to chunk_2's subgraph
- Chunk_2 optimized independently
- Chunk_1 and chunk_2 exist simultaneously
- Chunk_2 matching attempted asynchronously (background)
### Step 5: Detect Discontinuity (Segment 2 → 3)
- **Action**: Process AD000050 after AD000030
- **Expected Result**:
- Tracking lost detected again
- **Chunk_3 created proactively**
- Processing continues in chunk_3
- Chunk_1, chunk_2, chunk_3 all exist simultaneously
### Step 6: Process Segment 3 Independently
- **Action**: Process AD000050-055
- **Expected Result**:
- Frames processed in chunk_3 context
- Chunk_3 optimized independently
- All 3 chunks exist simultaneously
- Each chunk processed independently
### Step 7: Asynchronous Chunk Matching
- **Action**: Background task attempts matching for unanchored chunks
- **Expected Result**:
- Chunk_2 semantic matching attempted
- Chunk_2 LiteSAM matching attempted
- Chunk_2 anchored when match found
- Chunk_3 semantic matching attempted
- Chunk_3 LiteSAM matching attempted
- Chunk_3 anchored when match found
- Matching happens asynchronously (doesn't block frame processing)
### Step 8: Chunk Merging
- **Action**: Merge chunks as they become anchored
- **Expected Result**:
- Chunk_2 merged to chunk_1 when anchored
- Chunk_3 merged to merged trajectory when anchored
- Sim(3) transforms applied correctly
- Global optimization performed
- All chunks merged into single trajectory
### Step 9: Verify Final Trajectory
- **Action**: Verify all 22 frames have GPS coordinates
- **Expected Result**:
- All frames have GPS coordinates
- Trajectory globally consistent
- No systematic bias between segments
- Accuracy: 20/22 < 50m (90.9%)
## Success Criteria
**Primary Criterion**:
- Multiple chunks created simultaneously
- Chunks processed independently
- Chunks matched and merged asynchronously
- Final trajectory globally consistent
**Supporting Criteria**:
- Chunk creation is proactive (immediate)
- Frame processing continues during chunk matching
- Chunk matching doesn't block processing
- Sim(3) transforms computed correctly
## Expected Results
```
Multi-Chunk Simultaneous Processing:
- Chunk_1: frames 1-10, anchored, merged
- Chunk_2: frames 25-30, anchored asynchronously, merged
- Chunk_3: frames 50-55, anchored asynchronously, merged
- Simultaneous existence: All 3 chunks exist at same time
- Independent processing: Each chunk optimized independently
- Asynchronous matching: Matching doesn't block frame processing
- Final trajectory: Globally consistent
- Accuracy: 20/22 < 50m (90.9%)
```
## Pass/Fail Criteria
**TEST PASSES IF**:
- Multiple chunks created simultaneously
- Chunks processed independently
- Chunks matched and merged asynchronously
- Final trajectory globally consistent
- Accuracy acceptable (≥ 80% < 50m)
**TEST FAILS IF**:
- Chunks not created simultaneously
- Chunk processing blocks frame processing
- Chunk matching blocks processing
- Merging produces inconsistent trajectory
- Final accuracy below threshold
## Architecture Elements
**Multi-Chunk Support**:
- F10 Factor Graph Optimizer supports multiple chunks simultaneously
- Each chunk has own subgraph
- Chunks optimized independently
**Proactive Chunk Creation**:
- Chunks created immediately on tracking loss
- Not reactive (doesn't wait for matching to fail)
- Processing continues in new chunk
**Asynchronous Matching**:
- Background task processes unanchored chunks
- Matching doesn't block frame processing
- Chunks matched and merged asynchronously
**Chunk Merging**:
- Sim(3) transform for merging
- Accounts for translation, rotation, scale
- Global optimization after merging
## Notes
- Multiple chunks can exist simultaneously
- Chunk processing is independent and non-blocking
- Asynchronous matching reduces user input requests
- Sim(3) transform critical for scale ambiguity resolution