# External Integrations **Analysis Date:** 2026-04-01 ## APIs & External Services **Satellite Tile Provider:** - Google Maps Slippy Tile API — satellite imagery for navigation reference - URL pattern (actively in code): `https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={zoom}` - Used in: `src/gps_denied/core/satellite.py` (`SatelliteDataManager.fetch_tile`) - Auth: none in current code — the URL is called unauthenticated via the undocumented tile CDN - Config: `TILES_PROVIDER`, `TILES_API_KEY` env vars (key field exists in `TileProviderConfig` but not threaded into URL construction yet) - Note: docs specify Google Maps Tile API with a paid API key; current code hits the public CDN endpoint without a key. This is a mismatch — the key config is wired in `src/gps_denied/config.py` but not used in `satellite.py`. - Alternative providers documented (not implemented): Bing Maps, Mapbox Satellite ## Data Storage **Databases:** - SQLite (async) — primary operational datastore - Default connection: `sqlite+aiosqlite:///./flight_data.db` (relative to CWD) - Configurable via `DB_URL` env var (any SQLAlchemy async-compatible URL) - Client: SQLAlchemy >=2 async ORM (`src/gps_denied/db/engine.py`) - Session factory: `async_sessionmaker` in `src/gps_denied/db/engine.py` - Models: `src/gps_denied/db/models.py` - Migrations: Alembic >=1.14 (migration scripts directory not confirmed in scan) - SQLite pragmas: `PRAGMA foreign_keys=ON` enforced on every connection **File Storage:** - Local filesystem — satellite tile cache via diskcache - Cache directory: `.satellite_cache` (default) or `TILES_CACHE_DIR` env var - Size limit: 10GB default (configurable in `SatelliteDataManager.__init__`) - Key scheme: `{flight_id}_{zoom}_{x}_{y}` (PNG-encoded bytes) - Implementation: `src/gps_denied/core/satellite.py` - Local filesystem — ML model weights - Directory: `weights/` (configurable via `MODEL_WEIGHTS_DIR` env var) **Caching:** - diskcache >=5.6 — disk-based LRU cache for satellite tiles - No in-memory cache layer (Redis/Memcached not used) ## Hardware Interfaces **Camera (UAV):** - Raw image frames ingested via REST API (`POST /flights/{id}/frames`) as multipart file uploads - No direct camera SDK or hardware driver in codebase — hardware abstraction delegated to the flight controller or a separate capture process - Frame format: image files (JPEG/PNG) decoded by OpenCV (`cv2.imdecode`) **IMU:** - IMU data referenced in architecture (`CameraParameters` schema, ESKF fusion design) - No direct IMU hardware driver in current code — IMU input pathway not yet implemented - Planned: multi-rate fusion at ~100Hz IMU vs ~3fps camera, implemented in custom ESKF **GPU / CUDA (Jetson Orin Nano Super):** - CUDA 12.6.10 — JetPack-bundled, accessed via OpenCV CUDA bindings and TensorRT - TensorRT 10.3.0 — planned FP16 inference engine for SuperPoint, LightGlue, LiteSAM/XFeat - Wrapped behind `IModelManager.optimize_to_tensorrt()` interface in `src/gps_denied/core/models.py` - Current implementation uses `MockInferenceEngine` stubs - NVIDIA VPI 3.2 — JetPack-bundled; planned as alternative to OpenCV CUDA for image resize (not yet used in code) ## Authentication & Identity **Auth Provider:** - None — no authentication on the REST API in current code - CORS origins default to `["*"]` (`APIConfig` in `src/gps_denied/config.py`) - Intended for local on-device operation (Jetson Orin Nano Super runs in air-gapped environment) ## Visual Odometry Engine **PyCuVSLAM v15.0.0 (NVIDIA, closed-source):** - Planned primary VO engine — SLAM with mono+IMU mode, loop closure, 116fps at 720p on Orin Nano - Install: local aarch64 wheel from `bin/aarch64/` (not on PyPI) - Abstracted behind `ISequentialVisualOdometry` interface in `src/gps_denied/core/vo.py` - Not yet integrated — current `SequentialVisualOdometry` class uses SuperPoint+LightGlue via `ModelManager` - Fallback if cuVSLAM fails: XFeat frame-to-frame matching (also not yet implemented) ## Factor Graph & Sensor Fusion **GTSAM >=4.3a0:** - Factor graph optimizer for route chunk pose graph optimization - Used in `src/gps_denied/core/graph.py` (`FactorGraphOptimizer`) - Import guarded with try/except — `HAS_GTSAM` flag allows graceful degradation - Custom ESKF (16-state, NumPy/SciPy) is the planned primary fusion engine at 100Hz — not yet a separate file; referenced in docs only ## Streaming Protocol **Server-Sent Events (SSE):** - sse-starlette >=2.0 — `EventSourceResponse` used in `src/gps_denied/api/routers/flights.py` - Streams real-time geolocalization results to a connected client during frame processing - SSE utility helpers in `src/gps_denied/core/sse.py` - No WebSocket or polling fallback ## Output Format **GeoJSON (RFC 7946):** - Primary coordinate output format (WGS84) - `geojson` Python package planned (not yet in `pyproject.toml`) - GPS coordinates returned in API responses via Pydantic schemas (`GPSPoint`, `ObjectGPSResponse`) **CSV:** - Documented as secondary export option; not yet implemented ## Tile Indexing Strategy **Mercator / Slippy Tile Coordinates:** - Web Mercator projection (XYZ tile scheme, same as Google Maps / OSM) - Conversion utilities in `src/gps_denied/utils/mercator.py` (`latlon_to_tile`, `compute_tile_bounds`) - Called from `src/gps_denied/core/satellite.py` **GeoHash Indexing (planned, not yet implemented):** - Docs specify `{geohash}/{zoom}_{x}_{y}.jpg` directory structure for pre-flight tile storage - `pygeohash` package planned but not in `pyproject.toml` - Current implementation uses diskcache flat-key scheme instead ## CI/CD & Deployment **Hosting:** - On-device: NVIDIA Jetson Orin Nano Super (air-gapped during flight) - Development: x86_64 Linux with Docker+CUDA **CI Pipeline:** - Not detected in scanned directories (no `.github/`, `.gitlab-ci.yml`, etc. found) ## Environment Configuration **Required env vars (non-default critical settings):** - `DB_URL` — override default SQLite path for production - `TILES_API_KEY` — Google Maps API key (currently unused in tile fetch code — see mismatch note above) - `MODEL_WEIGHTS_DIR` — path to TensorRT/ONNX model weight files - `AREA_*` — operational area bounding box (defaults to Eastern Ukraine: lat 45-52, lon 22-40) **Secrets location:** - `.env` file in project root (not committed — standard pydantic-settings pattern) ## Webhooks & Callbacks **Incoming:** - None **Outgoing:** - None — system is self-contained on the UAV; results streamed to connected client via SSE --- *Integration audit: 2026-04-01*