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