mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-22 22:46:36 +00:00
2dd60a0e37
7 structured documents covering stack, integrations, architecture, structure, conventions, testing, and concerns. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
249 lines
12 KiB
Markdown
249 lines
12 KiB
Markdown
# Codebase Structure
|
|
|
|
**Analysis Date:** 2026-04-01
|
|
|
|
## Directory Layout
|
|
|
|
```
|
|
gps-denied-onboard/
|
|
├── src/
|
|
│ └── gps_denied/ # Main package
|
|
│ ├── __init__.py # Package version
|
|
│ ├── __main__.py # Entry point (uvicorn runner)
|
|
│ ├── app.py # FastAPI app factory + lifespan
|
|
│ ├── config.py # Pydantic-settings configuration classes
|
|
│ ├── api/
|
|
│ │ ├── __init__.py
|
|
│ │ ├── deps.py # FastAPI dependency providers (singletons)
|
|
│ │ └── routers/
|
|
│ │ ├── __init__.py
|
|
│ │ └── flights.py # All /flights/* endpoints
|
|
│ ├── core/
|
|
│ │ ├── processor.py # FlightProcessor — main orchestrator
|
|
│ │ ├── pipeline.py # ImageInputPipeline — image ingestion/queuing
|
|
│ │ ├── vo.py # SequentialVisualOdometry (SuperPoint+LightGlue)
|
|
│ │ ├── satellite.py # SatelliteDataManager (tile fetch/cache)
|
|
│ │ ├── gpr.py # GlobalPlaceRecognition (AnyLoc/DINOv2)
|
|
│ │ ├── metric.py # MetricRefinement (LiteSAM homography alignment)
|
|
│ │ ├── graph.py # FactorGraphOptimizer (GTSAM/mock pose graph)
|
|
│ │ ├── chunk_manager.py # RouteChunkManager (disconnected segments)
|
|
│ │ ├── recovery.py # FailureRecoveryCoordinator (tracking loss handling)
|
|
│ │ ├── rotation.py # ImageRotationManager (360° sweep, heading tracking)
|
|
│ │ ├── coordinates.py # CoordinateTransformer (ENU↔GPS, pixel→GPS)
|
|
│ │ ├── models.py # ModelManager + MockInferenceEngine
|
|
│ │ ├── results.py # ResultManager (DB + SSE publish)
|
|
│ │ └── sse.py # SSEEventStreamer (per-flight async queues)
|
|
│ ├── db/
|
|
│ │ ├── __init__.py
|
|
│ │ ├── engine.py # Async SQLAlchemy engine + session factory
|
|
│ │ ├── models.py # ORM table definitions (8 tables)
|
|
│ │ └── repository.py # FlightRepository DAO (all SQL operations)
|
|
│ ├── schemas/
|
|
│ │ ├── __init__.py # GPSPoint, CameraParameters, Polygon, Geofences
|
|
│ │ ├── flight.py # Flight CRUD request/response schemas
|
|
│ │ ├── image.py # ImageBatch, ImageData, ProcessedBatch schemas
|
|
│ │ ├── vo.py # Features, Matches, Motion, RelativePose
|
|
│ │ ├── gpr.py # TileCandidate, DatabaseMatch
|
|
│ │ ├── metric.py # AlignmentResult, ChunkAlignmentResult, Sim3Transform
|
|
│ │ ├── satellite.py # TileCoords, TileBounds
|
|
│ │ ├── graph.py # Pose, OptimizationResult, FactorGraphConfig
|
|
│ │ ├── chunk.py # ChunkHandle, ChunkStatus enum
|
|
│ │ ├── rotation.py # RotationResult, HeadingHistory
|
|
│ │ ├── model.py # InferenceEngine base schema
|
|
│ │ └── events.py # SSEMessage, SSEEventType, FrameProcessedEvent, etc.
|
|
│ └── utils/
|
|
│ └── mercator.py # Slippy map tile math (lat/lon↔tile x/y/bounds)
|
|
├── _docs/
|
|
│ ├── _autopilot_state.md # GSD planning state tracker
|
|
│ ├── 01_solution/
|
|
│ │ └── solution.md # Master architecture document (finalized draft 06)
|
|
│ └── 02_document/
|
|
│ └── tests/ # Test scenario specifications (43 scenarios)
|
|
├── .planning/
|
|
│ └── codebase/ # GSD mapping documents (this directory)
|
|
├── .venv/ # Python virtual environment (committed or local)
|
|
├── pyproject.toml # Project metadata and dependencies
|
|
└── flight_data.db # SQLite DB (runtime artifact, not committed)
|
|
```
|
|
|
|
## Directory Purposes
|
|
|
|
**`src/gps_denied/`:**
|
|
- Purpose: Top-level Python package; everything importable from here
|
|
- Key files: `app.py` (create_app factory), `config.py` (all settings), `__main__.py` (entrypoint)
|
|
|
|
**`src/gps_denied/api/`:**
|
|
- Purpose: HTTP API surface only — routing, request/response handling, dependency injection
|
|
- Contains: One router (`flights.py`) with 9 endpoints, `deps.py` with 3 singleton providers
|
|
- Key files: `routers/flights.py` (all endpoints), `deps.py` (ProcessorDep, SessionDep, RepoDep)
|
|
|
|
**`src/gps_denied/core/`:**
|
|
- Purpose: All processing logic — state machines, algorithms, pipeline components
|
|
- Module count: 14 files
|
|
- Key files: `processor.py` (orchestrator), `models.py` (inference abstraction), `graph.py` (pose graph)
|
|
- Note: Each component has a matching `I*` ABC interface defined in the same file
|
|
|
|
**`src/gps_denied/db/`:**
|
|
- Purpose: Database access only — no business logic
|
|
- Contains: Engine setup, ORM models, one repository class
|
|
- Key files: `models.py` (8 ORM tables), `repository.py` (all DB operations)
|
|
|
|
**`src/gps_denied/schemas/`:**
|
|
- Purpose: Pydantic data contracts; shared across API, core, and DB layers
|
|
- Contains: 12 schema files covering every domain concept
|
|
- Key files: `__init__.py` (GPSPoint, CameraParameters — imported everywhere), `flight.py` (largest — all REST schemas)
|
|
|
|
**`src/gps_denied/utils/`:**
|
|
- Purpose: Pure utility functions with no side effects
|
|
- Contains: `mercator.py` — Mercator projection math for tile coordinate conversion
|
|
- Used by: `satellite.py` exclusively
|
|
|
|
**`_docs/`:**
|
|
- Purpose: Architecture documentation and planning artifacts — not source code
|
|
- Key files: `01_solution/solution.md` (the authoritative design doc), `_autopilot_state.md` (GSD planning tracker)
|
|
|
|
## Key File Locations
|
|
|
|
**Entry Points:**
|
|
- `src/gps_denied/__main__.py`: Invoked by `python -m gps_denied`; starts uvicorn
|
|
- `src/gps_denied/app.py`: `create_app()` factory; `app` module-level instance used by uvicorn
|
|
|
|
**Configuration:**
|
|
- `src/gps_denied/config.py`: All settings via `pydantic-settings`; reads from `.env` and env vars
|
|
- `DB_URL` → SQLAlchemy connection string (default: SQLite)
|
|
- `TILES_ZOOM_LEVEL`, `TILES_CACHE_DIR`, `TILES_API_KEY` → satellite tile provider
|
|
- `MODEL_WEIGHTS_DIR`, `MODEL_SUPERPOINT_PATH`, etc. → model file paths
|
|
- `RECOVERY_*`, `ROTATION_*` → algorithm thresholds
|
|
|
|
**Core Orchestration:**
|
|
- `src/gps_denied/core/processor.py`: `FlightProcessor` — only class that calls other pipeline components
|
|
|
|
**Dependency Wiring:**
|
|
- `src/gps_denied/api/deps.py`: Single location where singletons (`FlightProcessor`, `SSEEventStreamer`) are created and wired; `ProcessorDep` type alias used in all routers
|
|
|
|
**Database Schema:**
|
|
- `src/gps_denied/db/models.py`: All 8 ORM tables with cascade deletes; ground truth for DB schema
|
|
|
|
**Pydantic Contracts:**
|
|
- `src/gps_denied/schemas/__init__.py`: `GPSPoint` and `CameraParameters` — imported by nearly every module
|
|
|
|
## Naming Conventions
|
|
|
|
**Files:**
|
|
- `snake_case.py` throughout
|
|
- Core components named after their function: `vo.py`, `gpr.py`, `metric.py`, `graph.py`
|
|
- Interfaces co-located with implementation in the same file (`ISequentialVisualOdometry` and `SequentialVisualOdometry` both in `vo.py`)
|
|
|
|
**Classes:**
|
|
- Implementation classes: `PascalCase` noun phrases (`FlightProcessor`, `RouteChunkManager`)
|
|
- Interfaces: `I` prefix + implementation name (`IRouteChunkManager`)
|
|
- ORM models: suffixed with `Row` (`FlightRow`, `WaypointRow`)
|
|
- Pydantic models: suffixed with `Request`/`Response` for API schemas; bare names for internal data
|
|
|
|
**Functions:**
|
|
- `snake_case`
|
|
- Async functions throughout API and DB layers; sync in core (except `process_frame` which is async)
|
|
|
|
**Constants/Enums:**
|
|
- `TrackingState`: `str, Enum` with lowercase values (`"normal"`, `"lost"`, `"recovery"`)
|
|
- `SSEEventType`: `str, Enum` with snake_case values
|
|
- `ChunkStatus`: `str, Enum`
|
|
|
|
## Where to Add New Code
|
|
|
|
**New API endpoint:**
|
|
- Add route function to `src/gps_denied/api/routers/flights.py`
|
|
- Add request/response Pydantic models to `src/gps_denied/schemas/flight.py`
|
|
- Add business logic method to `src/gps_denied/core/processor.py`
|
|
- If new router prefix needed: create `src/gps_denied/api/routers/{name}.py` and register in `app.py`
|
|
|
|
**New pipeline component:**
|
|
- Create `src/gps_denied/core/{component_name}.py`
|
|
- Define `I{ComponentName}(ABC)` interface and `{ComponentName}` implementation in same file
|
|
- Add schemas to `src/gps_denied/schemas/{component_name}.py`
|
|
- Add component instantiation to `app.py` lifespan block
|
|
- Inject via `FlightProcessor.attach_components()` and call from `process_frame()`
|
|
|
|
**New database table:**
|
|
- Add `{Name}Row(Base)` to `src/gps_denied/db/models.py`
|
|
- Add CRUD methods to `src/gps_denied/db/repository.py`
|
|
- Add foreign key + relationship to `FlightRow` if flight-scoped
|
|
|
|
**New configuration setting:**
|
|
- Add field to the appropriate `BaseSettings` subclass in `src/gps_denied/config.py`
|
|
- Use `ENV_PREFIX__FIELD_NAME` env var pattern
|
|
|
|
**New schema type:**
|
|
- Add to `src/gps_denied/schemas/{relevant_file}.py` or create new file
|
|
- If broadly shared (like `GPSPoint`), add to `src/gps_denied/schemas/__init__.py`
|
|
|
|
**Utility functions:**
|
|
- Add to `src/gps_denied/utils/mercator.py` if geospatial math
|
|
- Create `src/gps_denied/utils/{name}.py` for other pure utilities
|
|
|
|
## Special Directories
|
|
|
|
**`.venv/`:**
|
|
- Purpose: Python virtual environment
|
|
- Generated: Yes (via `python -m venv` or uv)
|
|
- Committed: Present in tree (check `.gitignore`)
|
|
|
|
**`_docs/`:**
|
|
- Purpose: Architecture docs, test specs, GSD planning artifacts
|
|
- Generated: No (hand-authored)
|
|
- Committed: Yes
|
|
|
|
**`.planning/`:**
|
|
- Purpose: GSD (Get Stuff Done) planning system — phase plans, codebase maps
|
|
- Generated: By GSD commands
|
|
- Committed: Yes (used by CI/planning tools)
|
|
|
|
**`.image_storage/` (runtime):**
|
|
- Purpose: Disk storage for uploaded UAV images per flight
|
|
- Created by: `ImageInputPipeline.store_images()`
|
|
- Path: Relative to process CWD; configurable via `ImageInputPipeline(storage_dir=...)`
|
|
|
|
**`.satellite_cache/` (runtime):**
|
|
- Purpose: diskcache directory for satellite tiles
|
|
- Created by: `SatelliteDataManager.__init__()`
|
|
- Size limit: 10GB default
|
|
|
|
## Module Dependency Graph (simplified)
|
|
|
|
```
|
|
api/routers/flights.py
|
|
→ api/deps.py
|
|
→ core/processor.py
|
|
→ core/pipeline.py (image ingestion)
|
|
→ core/results.py (DB + SSE publish)
|
|
→ core/sse.py (event streaming)
|
|
→ [via attach_components]
|
|
→ core/vo.py → core/models.py
|
|
→ core/gpr.py → core/models.py
|
|
→ core/metric.py → core/models.py
|
|
→ core/graph.py (optional: gtsam)
|
|
→ core/chunk_manager.py → core/graph.py
|
|
→ core/recovery.py → core/chunk_manager.py
|
|
→ core/gpr.py
|
|
→ core/metric.py
|
|
→ core/rotation.py
|
|
→ db/repository.py
|
|
→ db/models.py
|
|
→ core/sse.py
|
|
→ db/engine.py
|
|
|
|
core/satellite.py (standalone — not wired into processor yet)
|
|
core/coordinates.py (standalone — not wired into processor yet)
|
|
utils/mercator.py → only used by core/satellite.py
|
|
schemas/* → imported by all layers (no internal imports)
|
|
config.py → imported by db/engine.py, and anywhere settings needed
|
|
```
|
|
|
|
**Notably standalone (not connected to processor):**
|
|
- `src/gps_denied/core/satellite.py`: `SatelliteDataManager` — instantiated nowhere in `app.py` or `processor.py`; satellite tiles fetched inline with mock in `processor.py`
|
|
- `src/gps_denied/core/coordinates.py`: `CoordinateTransformer` — not instantiated in the pipeline; `convert_object_to_gps` in processor returns a hardcoded stub (`GPSPoint(lat=48.0, lon=37.0)`)
|
|
|
|
---
|
|
|
|
*Structure analysis: 2026-04-01*
|