# 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*