# Technology Stack

**Analysis Date:** 2026-04-01

## Languages

**Primary:**
- Python 3.11+ — entire application (enforced in `pyproject.toml` via `requires-python = ">=3.11"`)

## Runtime

**Environment:**
- Target hardware: NVIDIA Jetson Orin Nano Super 8GB (ARM64/aarch64)
- Target OS: JetPack 6.2.2 (L4T / Ubuntu 22.04)
- CUDA 12.6.10, TensorRT 10.3.0, cuDNN 9.3 (all JetPack-bundled, not in pyproject.toml)
- Development/CI: x86_64 Linux with Docker+CUDA (cuVSLAM and TensorRT mocked)

**Package Manager:**
- pip / setuptools >=75
- Lockfile: not present (no `requirements.txt`, no lock file)

## Frameworks

**Core:**
- FastAPI (unpinned, >=0.115 per docs) — REST API framework with auto-generated OpenAPI docs
- Uvicorn (`uvicorn[standard]`, unpinned) — ASGI server
- sse-starlette >=2.0 — Server-Sent Events streaming (`EventSourceResponse` actively used in `src/gps_denied/api/routers/flights.py`)

**Data Validation / Settings:**
- Pydantic >=2 — schema definitions across all `src/gps_denied/schemas/*.py`
- pydantic-settings >=2 — env/YAML configuration in `src/gps_denied/config.py`

**Database:**
- SQLAlchemy >=2 (async) — ORM and query layer (`src/gps_denied/db/engine.py`, `src/gps_denied/db/models.py`)
- Alembic >=1.14 — database migrations
- aiosqlite >=0.20 — async SQLite driver (default DB URL: `sqlite+aiosqlite:///./flight_data.db`)

**Testing:**
- pytest >=8.0 — test runner (config in `pyproject.toml`, `testpaths = ["tests"]`)
- pytest-asyncio >=0.24 — async test support (`asyncio_mode = "auto"`)
- httpx >=0.28 (dev) — HTTP client for integration tests

**Linting / Formatting:**
- ruff >=0.9 — linting and formatting (`target-version = "py311"`, `line-length = 100`)

## Key Dependencies

**HTTP Client:**
- httpx >=0.27 — async HTTP client used in `src/gps_denied/core/satellite.py` for tile fetching

**Computer Vision:**
- opencv-python-headless >=4.9 — image decode/encode, feature detection/matching, resize
  - Actively imported in `src/gps_denied/core/satellite.py` and `src/gps_denied/core/vo.py`
  - Note: docs specify a CUDA-enabled build must be compiled from source (`CUDA_ARCH_BIN=8.7`) on Jetson; pyproject.toml installs the headless CPU build as default
- numpy >=1.26 — array operations, ESKF math, image buffer handling (used throughout core modules)

**Tile Caching:**
- diskcache >=5.6 — disk-based tile cache with size limit in `src/gps_denied/core/satellite.py`

**Factor Graph Optimization:**
- gtsam >=4.3a0 — factor graph optimizer (`src/gps_denied/core/graph.py`)
  - Import is wrapped in a try/except (`HAS_GTSAM` flag); the module degrades gracefully if not installed

**Multipart Upload:**
- python-multipart >=0.0.9 — required for FastAPI `UploadFile` in flight frame ingestion

## Dependencies Planned-but-Not-in-pyproject.toml

These appear in `_docs/01_solution/tech_stack.md` but are NOT listed in `pyproject.toml` or `requires.txt`:

| Package | Planned Purpose | Status |
|---------|----------------|--------|
| PyCuVSLAM v15.0.0 (aarch64 wheel) | Primary visual odometry engine | Planned — local wheel install from `bin/aarch64/` |
| scipy | Rotation matrices, ESKF spatial transforms | Planned — not yet in deps |
| torch (JetPack-compatible aarch64) | LiteSAM / XFeat model loading | Conditional — depends on day-1 benchmark |
| tensorrt 10.3.0 | TensorRT FP16 inference engine | JetPack-bundled, not pip-installed |
| pycuda | CUDA stream management | Planned, not yet added |
| geojson | GeoJSON output formatting | Planned, not yet added |
| pygeohash | GeoHash tile indexing | Planned, not yet added |
| filterpy v1.4.5 | ESKF reference/fallback | Planned, not yet added |

The VO interface in `src/gps_denied/core/vo.py` is written against an abstract `ISequentialVisualOdometry` — PyCuVSLAM implementation is a planned concrete subclass. Current `ModelManager` in `src/gps_denied/core/models.py` uses `MockInferenceEngine` stubs (SuperPoint/LightGlue mock returning random keypoints).

## ML Models (Planned)

| Model | Format | Purpose |
|-------|--------|---------|
| SuperPoint | TensorRT FP16 / ONNX | Frame keypoint extraction (VO) |
| LightGlue | TensorRT FP16 / ONNX | Keypoint matching (VO) |
| LiteSAM (opt) OR XFeat semi-dense | TensorRT FP16 | Satellite image matching — selection via day-1 benchmark at 480px |

Weights expected at paths configured in `ModelPaths` settings (`src/gps_denied/config.py`): `weights/superpoint.pt`, `weights/lightglue.pt`, `weights/litesam.pt`.

## Configuration

**Environment:**
- Loaded from `.env` file (root) via pydantic-settings `AppSettings` in `src/gps_denied/config.py`
- Nested delimiter: `__` (e.g., `DB__URL=...`)
- Key env prefix groups: `DB_`, `API_`, `TILES_`, `MODEL_`, `AREA_`, `RECOVERY_`, `ROTATION_`

**Build:**
- `pyproject.toml` — project metadata, dependencies, ruff and pytest config
- No Dockerfile present in scanned directories

## Platform Requirements

**Development:**
- Python 3.11+, pip
- x86_64 Linux with GPU (Docker+CUDA) for model export and unit tests
- cuVSLAM and TensorRT mocked in unit tests (per documented strategy)

**Production:**
- NVIDIA Jetson Orin Nano Super 8GB, JetPack 6.2.2
- No internet connectivity during flight (all tiles pre-fetched)
- OpenCV must be compiled from source with `CUDA_ARCH_BIN=8.7` for GPU preprocessing

---

*Stack analysis: 2026-04-01*
