mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-23 03:36:37 +00:00
component decomposition is done
This commit is contained in:
@@ -0,0 +1,331 @@
|
||||
# Route API Client
|
||||
|
||||
## Interface Definition
|
||||
|
||||
**Interface Name**: `IRouteAPIClient`
|
||||
|
||||
### Interface Methods
|
||||
|
||||
```python
|
||||
class IRouteAPIClient(ABC):
|
||||
@abstractmethod
|
||||
def update_route_waypoint(self, route_id: str, waypoint_id: str, waypoint: Waypoint) -> bool:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_route_info(self, route_id: str) -> Optional[RouteInfo]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def batch_update_waypoints(self, route_id: str, waypoints: List[Waypoint]) -> BatchUpdateResult:
|
||||
pass
|
||||
```
|
||||
|
||||
## Component Description
|
||||
|
||||
### Responsibilities
|
||||
- HTTP client for communicating with Route API
|
||||
- Send per-frame GPS refinements to Route API
|
||||
- Retrieve route metadata and waypoints
|
||||
- Handle batch waypoint updates for trajectory refinements
|
||||
- Manage connection pooling and retry logic
|
||||
- Handle HTTP errors and timeouts
|
||||
|
||||
### Scope
|
||||
- Synchronous HTTP client (requests library)
|
||||
- Waypoint update operations
|
||||
- Route metadata retrieval
|
||||
- Error handling and retries
|
||||
- Rate limiting and backpressure management
|
||||
|
||||
## API Methods
|
||||
|
||||
### `update_route_waypoint(route_id: str, waypoint_id: str, waypoint: Waypoint) -> bool`
|
||||
|
||||
**Description**: Updates a single waypoint in Route API. Called per-frame after GPS calculation.
|
||||
|
||||
**Called By**:
|
||||
- G13 Result Manager (per-frame update)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
route_id: str
|
||||
waypoint_id: str # Frame sequence number
|
||||
waypoint: Waypoint:
|
||||
lat: float
|
||||
lon: float
|
||||
altitude: Optional[float]
|
||||
confidence: float
|
||||
timestamp: datetime
|
||||
refined: bool # Always True for GPS-Denied updates
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
bool: True if updated successfully, False on failure
|
||||
```
|
||||
|
||||
**HTTP Request**:
|
||||
```
|
||||
PUT /routes/{route_id}/waypoints/{waypoint_id}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"lat": 48.123456,
|
||||
"lon": 37.654321,
|
||||
"altitude": 800.0,
|
||||
"confidence": 0.95,
|
||||
"timestamp": "2025-11-24T10:30:00Z",
|
||||
"refined": true
|
||||
}
|
||||
```
|
||||
|
||||
**Error Handling**:
|
||||
- **Retry**: 3 attempts with exponential backoff (1s, 2s, 4s)
|
||||
- **Timeout**: 5 seconds per request
|
||||
- **404 Not Found**: Log warning, return False
|
||||
- **429 Too Many Requests**: Backoff and retry
|
||||
- **500 Server Error**: Retry with backoff
|
||||
|
||||
**Error Conditions**:
|
||||
- Returns `False`: Update failed after retries
|
||||
- Logs errors but doesn't raise exceptions (non-critical path)
|
||||
|
||||
**Test Cases**:
|
||||
1. **Successful update**: Returns True
|
||||
2. **Route API unavailable**: Retries 3 times, returns False
|
||||
3. **Waypoint not found**: Returns False
|
||||
4. **Network timeout**: Retries, returns False if all fail
|
||||
5. **High-frequency updates**: 100 updates/sec sustained
|
||||
|
||||
---
|
||||
|
||||
### `get_route_info(route_id: str) -> Optional[RouteInfo]`
|
||||
|
||||
**Description**: Retrieves route metadata including rough waypoints and geofences.
|
||||
|
||||
**Called By**:
|
||||
- G02 Flight Manager (during flight creation)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
route_id: str
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
RouteInfo:
|
||||
route_id: str
|
||||
name: str
|
||||
description: str
|
||||
points: List[GPSPoint] # Rough waypoints
|
||||
geofences: Geofences
|
||||
waypoint_count: int
|
||||
created_at: datetime
|
||||
```
|
||||
|
||||
**HTTP Request**:
|
||||
```
|
||||
GET /routes/{route_id}
|
||||
```
|
||||
|
||||
**Error Handling**:
|
||||
- **Retry**: 3 attempts for transient errors
|
||||
- **Timeout**: 10 seconds
|
||||
- **404 Not Found**: Return None
|
||||
- **500 Server Error**: Retry with backoff
|
||||
|
||||
**Error Conditions**:
|
||||
- Returns `None`: Route not found or error after retries
|
||||
- `RouteAPIError`: Critical error retrieving route
|
||||
|
||||
**Test Cases**:
|
||||
1. **Existing route**: Returns complete RouteInfo
|
||||
2. **Non-existent route**: Returns None
|
||||
3. **Large route**: 2000+ waypoints → returns successfully
|
||||
4. **Concurrent requests**: 10 simultaneous requests → all succeed
|
||||
|
||||
---
|
||||
|
||||
### `batch_update_waypoints(route_id: str, waypoints: List[Waypoint]) -> BatchUpdateResult`
|
||||
|
||||
**Description**: Updates multiple waypoints in a single request. Used for trajectory refinements.
|
||||
|
||||
**Called By**:
|
||||
- G13 Result Manager (asynchronous refinement updates)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
route_id: str
|
||||
waypoints: List[Waypoint] # Refined waypoints
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
BatchUpdateResult:
|
||||
success: bool
|
||||
updated_count: int
|
||||
failed_ids: List[str]
|
||||
```
|
||||
|
||||
**HTTP Request**:
|
||||
```
|
||||
PUT /routes/{route_id}/waypoints/batch
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"waypoints": [
|
||||
{
|
||||
"id": "AD000237",
|
||||
"lat": 48.123,
|
||||
"lon": 37.654,
|
||||
"altitude": 800.0,
|
||||
"confidence": 0.97,
|
||||
"timestamp": "2025-11-24T10:30:00Z",
|
||||
"refined": true
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Error Handling**:
|
||||
- **Partial success**: Some waypoints update, some fail
|
||||
- **Retry**: 3 attempts for complete batch
|
||||
- **Timeout**: 30 seconds (larger batches)
|
||||
- Returns updated_count and failed_ids
|
||||
|
||||
**Error Conditions**:
|
||||
- Returns `success=False` with failed_ids list
|
||||
|
||||
**Test Cases**:
|
||||
1. **Batch update 100 waypoints**: All succeed
|
||||
2. **Partial failure**: 5 waypoints fail → returns failed_ids
|
||||
3. **Empty batch**: Returns success=True, updated_count=0
|
||||
4. **Large batch**: 500 waypoints → splits into sub-batches
|
||||
|
||||
## Integration Tests
|
||||
|
||||
### Test 1: Per-Frame Update Flow
|
||||
1. Create flight and process 100 frames
|
||||
2. update_route_waypoint() × 100 sequentially
|
||||
3. Verify all updates successful via get_route_info()
|
||||
4. Verify waypoints marked as refined=True
|
||||
|
||||
### Test 2: Refinement Batch Update
|
||||
1. Process route, track 200 frames needing refinement
|
||||
2. batch_update_waypoints() with 200 waypoints
|
||||
3. Verify all updates applied
|
||||
4. Handle partial failures gracefully
|
||||
|
||||
### Test 3: Error Recovery
|
||||
1. Simulate Route API downtime
|
||||
2. Attempt update_route_waypoint() → retries 3 times
|
||||
3. Route API comes back online
|
||||
4. Next update succeeds
|
||||
|
||||
### Test 4: High-Frequency Updates
|
||||
1. Send 200 waypoint updates sequentially
|
||||
2. Measure throughput and success rate
|
||||
3. Verify no rate limiting issues
|
||||
4. Verify all updates persisted
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
### Performance
|
||||
- **update_route_waypoint**: < 100ms average latency (critical path)
|
||||
- **get_route_info**: < 200ms
|
||||
- **batch_update_waypoints**: < 2 seconds for 100 waypoints
|
||||
- **Throughput**: Support 100 waypoint updates per second
|
||||
|
||||
### Scalability
|
||||
- Connection pool: 20-50 connections
|
||||
- Handle 1000+ waypoint updates per flight (2000+ frame flight)
|
||||
- Support concurrent updates from multiple flights
|
||||
|
||||
### Reliability
|
||||
- **Retry strategy**: 3 attempts with exponential backoff
|
||||
- **Circuit breaker**: Temporarily stop requests after 5 consecutive failures
|
||||
- **Timeout management**: Progressive timeouts (5s, 10s, 30s)
|
||||
- **Graceful degradation**: Continue processing even if Route API unavailable
|
||||
|
||||
### Monitoring
|
||||
- Track success/failure rates
|
||||
- Monitor latency percentiles (p50, p95, p99)
|
||||
- Alert on high failure rates
|
||||
- Log all HTTP errors
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Internal Components
|
||||
- None (external HTTP client)
|
||||
|
||||
### External Dependencies
|
||||
- **Route API**: External REST API service
|
||||
- **requests** or **httpx**: HTTP client library
|
||||
- **tenacity**: Retry library
|
||||
- **urllib3**: Connection pooling
|
||||
|
||||
## Data Models
|
||||
|
||||
### RouteInfo
|
||||
```python
|
||||
class GPSPoint(BaseModel):
|
||||
lat: float
|
||||
lon: float
|
||||
|
||||
class Geofences(BaseModel):
|
||||
polygons: List[Polygon]
|
||||
|
||||
class RouteInfo(BaseModel):
|
||||
route_id: str
|
||||
name: str
|
||||
description: str
|
||||
points: List[GPSPoint]
|
||||
geofences: Geofences
|
||||
waypoint_count: int
|
||||
created_at: datetime
|
||||
```
|
||||
|
||||
### Waypoint
|
||||
```python
|
||||
class Waypoint(BaseModel):
|
||||
id: str
|
||||
lat: float
|
||||
lon: float
|
||||
altitude: Optional[float]
|
||||
confidence: float
|
||||
timestamp: datetime
|
||||
refined: bool
|
||||
```
|
||||
|
||||
### BatchUpdateResult
|
||||
```python
|
||||
class BatchUpdateResult(BaseModel):
|
||||
success: bool
|
||||
updated_count: int
|
||||
failed_ids: List[str]
|
||||
errors: Optional[Dict[str, str]] # waypoint_id -> error_message
|
||||
```
|
||||
|
||||
### HTTPConfig
|
||||
```python
|
||||
class HTTPConfig(BaseModel):
|
||||
route_api_base_url: str # e.g., "http://localhost:8000"
|
||||
timeout: int = 5 # seconds
|
||||
max_retries: int = 3
|
||||
retry_backoff: float = 1.0 # seconds
|
||||
connection_pool_size: int = 50
|
||||
max_batch_size: int = 500
|
||||
```
|
||||
|
||||
### Retry Strategy
|
||||
```python
|
||||
retry_strategy = {
|
||||
"stop": "stop_after_attempt(3)",
|
||||
"wait": "wait_exponential(multiplier=1, min=1, max=10)",
|
||||
"retry": "retry_if_exception_type((ConnectionError, Timeout, HTTPError))",
|
||||
"reraise": True
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user