mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-22 21:46:36 +00:00
component decomposition is done
This commit is contained in:
@@ -0,0 +1,289 @@
|
||||
# Route REST API
|
||||
|
||||
## Interface Definition
|
||||
|
||||
**Interface Name**: `IRouteRestAPI`
|
||||
|
||||
### Interface Methods
|
||||
|
||||
```python
|
||||
class IRouteRestAPI(ABC):
|
||||
@abstractmethod
|
||||
def create_route(self, route_data: RouteCreateRequest) -> RouteResponse:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_route(self, route_id: str) -> RouteResponse:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def update_waypoints(self, route_id: str, waypoints: List[Waypoint]) -> UpdateResponse:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_route(self, route_id: str) -> DeleteResponse:
|
||||
pass
|
||||
```
|
||||
|
||||
## Component Description
|
||||
|
||||
### Responsibilities
|
||||
- Expose REST API endpoints for route lifecycle management
|
||||
- Handle HTTP request validation and routing
|
||||
- Coordinate with Route Data Manager for persistence operations
|
||||
- Validate incoming requests through Waypoint Validator
|
||||
- Return appropriate HTTP responses with proper status codes
|
||||
|
||||
### Scope
|
||||
- CRUD operations for routes
|
||||
- Waypoint management within routes
|
||||
- Geofence management
|
||||
- Route metadata retrieval
|
||||
- Used by both GPS-Denied system and Mission Planner
|
||||
|
||||
## API Methods
|
||||
|
||||
### `create_route(route_data: RouteCreateRequest) -> RouteResponse`
|
||||
|
||||
**Description**: Creates a new route with initial waypoints and geofences.
|
||||
|
||||
**Called By**:
|
||||
- Client applications (GPS-Denied UI, Mission Planner UI)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
RouteCreateRequest:
|
||||
id: Optional[str] # UUID, generated if not provided
|
||||
name: str
|
||||
description: str
|
||||
points: List[GPSPoint] # Initial rough waypoints
|
||||
geofences: Geofences
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
RouteResponse:
|
||||
route_id: str
|
||||
created: bool
|
||||
timestamp: datetime
|
||||
```
|
||||
|
||||
**Error Conditions**:
|
||||
- `400 Bad Request`: Invalid input data (missing required fields, invalid GPS coordinates)
|
||||
- `409 Conflict`: Route with same ID already exists
|
||||
- `500 Internal Server Error`: Database or internal error
|
||||
|
||||
**Test Cases**:
|
||||
1. **Valid route creation**: Provide valid route data → returns 201 with routeId
|
||||
2. **Missing required field**: Omit name → returns 400 with error message
|
||||
3. **Invalid GPS coordinates**: Provide lat > 90 → returns 400
|
||||
4. **Duplicate route ID**: Create route with existing ID → returns 409
|
||||
|
||||
---
|
||||
|
||||
### `get_route(route_id: str) -> RouteResponse`
|
||||
|
||||
**Description**: Retrieves complete route information including all waypoints and geofences.
|
||||
|
||||
**Called By**:
|
||||
- Client applications
|
||||
- G03 Route API Client (from GPS-Denied system)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
route_id: str # UUID
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
RouteResponse:
|
||||
route_id: str
|
||||
name: str
|
||||
description: str
|
||||
points: List[Waypoint] # All waypoints with metadata
|
||||
geofences: Geofences
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
```
|
||||
|
||||
**Error Conditions**:
|
||||
- `404 Not Found`: Route ID does not exist
|
||||
- `500 Internal Server Error`: Database error
|
||||
|
||||
**Test Cases**:
|
||||
1. **Existing route**: Valid routeId → returns 200 with complete route data
|
||||
2. **Non-existent route**: Invalid routeId → returns 404
|
||||
3. **Route with many waypoints**: Route with 2000+ waypoints → returns 200 with all data
|
||||
|
||||
---
|
||||
|
||||
### `update_waypoints(route_id: str, waypoint_id: str, waypoint_data: Waypoint) -> UpdateResponse`
|
||||
|
||||
**Description**: Updates a specific waypoint within a route. Used for per-frame GPS refinement from GPS-Denied system.
|
||||
|
||||
**Called By**:
|
||||
- G03 Route API Client (per-frame updates)
|
||||
- Client applications (manual corrections)
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
route_id: str
|
||||
waypoint_id: str # Frame sequence number or waypoint ID
|
||||
waypoint_data: Waypoint:
|
||||
lat: float
|
||||
lon: float
|
||||
altitude: Optional[float]
|
||||
confidence: float
|
||||
timestamp: datetime
|
||||
refined: bool # True if updated by GPS-Denied refinement
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
UpdateResponse:
|
||||
updated: bool
|
||||
waypoint_id: str
|
||||
```
|
||||
|
||||
**Error Conditions**:
|
||||
- `404 Not Found`: Route or waypoint not found
|
||||
- `400 Bad Request`: Invalid waypoint data
|
||||
- `500 Internal Server Error`: Database error
|
||||
|
||||
**Test Cases**:
|
||||
1. **Update existing waypoint**: Valid data → returns 200
|
||||
2. **Refinement update**: GPS-Denied sends refined coordinates → updates successfully
|
||||
3. **Invalid coordinates**: lat > 90 → returns 400
|
||||
4. **Non-existent waypoint**: Invalid waypoint_id → returns 404
|
||||
|
||||
---
|
||||
|
||||
### `delete_route(route_id: str) -> DeleteResponse`
|
||||
|
||||
**Description**: Deletes a route and all associated waypoints.
|
||||
|
||||
**Called By**:
|
||||
- Client applications
|
||||
|
||||
**Input**:
|
||||
```python
|
||||
route_id: str
|
||||
```
|
||||
|
||||
**Output**:
|
||||
```python
|
||||
DeleteResponse:
|
||||
deleted: bool
|
||||
route_id: str
|
||||
```
|
||||
|
||||
**Error Conditions**:
|
||||
- `404 Not Found`: Route does not exist
|
||||
- `500 Internal Server Error`: Database error
|
||||
|
||||
**Test Cases**:
|
||||
1. **Delete existing route**: Valid routeId → returns 200
|
||||
2. **Delete non-existent route**: Invalid routeId → returns 404
|
||||
3. **Delete route with active flight**: Route linked to processing flight → returns 200 (cascade handling in DB)
|
||||
|
||||
## Integration Tests
|
||||
|
||||
### Test 1: Route Creation and Retrieval Flow
|
||||
1. POST `/routes` with valid data
|
||||
2. Verify 201 response with routeId
|
||||
3. GET `/routes/{routeId}`
|
||||
4. Verify returned data matches created data
|
||||
|
||||
### Test 2: GPS-Denied Integration Flow
|
||||
1. Create route via POST
|
||||
2. Simulate GPS-Denied per-frame updates via PUT `/routes/{routeId}/waypoints/{waypointId}` × 100
|
||||
3. GET route and verify all waypoints updated
|
||||
4. Verify `refined: true` flag set
|
||||
|
||||
### Test 3: Concurrent Waypoint Updates
|
||||
1. Create route
|
||||
2. Send 50 concurrent PUT requests to different waypoints
|
||||
3. Verify all updates succeed
|
||||
4. Verify data consistency
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
### Performance
|
||||
- **Create route**: < 500ms response time
|
||||
- **Get route**: < 200ms for routes with < 2000 waypoints
|
||||
- **Update waypoint**: < 100ms (critical for GPS-Denied real-time updates)
|
||||
- **Delete route**: < 300ms
|
||||
- **Throughput**: Handle 100 concurrent waypoint updates per second
|
||||
|
||||
### Scalability
|
||||
- Support 1000+ concurrent route processing sessions
|
||||
- Handle routes with up to 3000 waypoints
|
||||
|
||||
### Availability
|
||||
- 99.9% uptime SLA
|
||||
- Graceful degradation under load
|
||||
|
||||
### Security
|
||||
- Input validation on all endpoints
|
||||
- SQL injection prevention
|
||||
- Rate limiting: 1000 requests/minute per client
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Internal Components
|
||||
- **R02 Route Data Manager**: For all data persistence operations
|
||||
- **R03 Waypoint Validator**: For input validation
|
||||
- **R04 Route Database Layer**: Indirectly through Data Manager
|
||||
|
||||
### External Dependencies
|
||||
- **FastAPI/Flask**: Web framework
|
||||
- **Pydantic**: Request/response validation
|
||||
- **Uvicorn**: ASGI server
|
||||
|
||||
## Data Models
|
||||
|
||||
### RouteCreateRequest
|
||||
```python
|
||||
class GPSPoint(BaseModel):
|
||||
lat: float # Latitude -90 to 90
|
||||
lon: float # Longitude -180 to 180
|
||||
|
||||
class Polygon(BaseModel):
|
||||
north_west: GPSPoint
|
||||
south_east: GPSPoint
|
||||
|
||||
class Geofences(BaseModel):
|
||||
polygons: List[Polygon]
|
||||
|
||||
class RouteCreateRequest(BaseModel):
|
||||
id: Optional[str] = None # UUID
|
||||
name: str
|
||||
description: str
|
||||
points: List[GPSPoint] # Initial rough waypoints
|
||||
geofences: Geofences
|
||||
```
|
||||
|
||||
### Waypoint
|
||||
```python
|
||||
class Waypoint(BaseModel):
|
||||
id: str # Sequence number or UUID
|
||||
lat: float
|
||||
lon: float
|
||||
altitude: Optional[float] = None
|
||||
confidence: float # 0.0 to 1.0
|
||||
timestamp: datetime
|
||||
refined: bool = False
|
||||
```
|
||||
|
||||
### RouteResponse
|
||||
```python
|
||||
class RouteResponse(BaseModel):
|
||||
route_id: str
|
||||
name: str
|
||||
description: str
|
||||
points: List[Waypoint]
|
||||
geofences: Geofences
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user