# Radio Coverage Map — drone link baseline (v0.1)

Pin the pilot, pick a device and altitude, get a coverage map of the
controller-to-drone link. This is the **geometric physics baseline** of the
research plan: it is the prior the fast ML model will correct and the yardstick
it must beat on real flight logs.

## Run

```bash
docker compose up --build        # then open http://localhost:8000
```

Colima works: `colima start --cpu 4 --memory 6` first. The first click in a new
area downloads terrain tiles and building footprints (~30–60 s); after that it
comes from `./data`.

Without Docker: `pip install -r requirements.txt && uvicorn app.main:app`.
Tests: `pytest -q` (FSPL, knife-edge J(ν), single-wall diffraction against the
analytic formula, terrain collision, link-budget consistency).

## Model

`PL = FSPL(slant distance) + J(ν_Bullington)` per pilot→drone path.

| Piece | Choice | Source / note |
|---|---|---|
| Terrain | AWS Terrain Tiles (Terrarium) z14, ~8 m | US: mostly USGS 3DEP bare earth. Clamped at sea level (the dataset includes bathymetry) |
| Buildings | Overture Maps footprints + `height` | Nearly every LA building has a height. Missing → floors×3 m → 6 m |
| Diffraction | Bullington equivalent knife edge, ITU-R P.526 J(ν) | Earth curvature with k = 4/3. No "delta-Bullington" smooth-earth term |
| Geometry | radial rays from the pilot, numba-parallel | 2 km radius at 5 m ≈ 0.6–1.5 s per altitude on a laptop |
| Link budget | `L_max = FSPL(rated range for the interference level)` | DJI publishes no receiver sensitivity; the rated ranges are the only honest anchor. The mid-points of DJI's ranges are an **assumption** |
| Altitude | above take-off (DJI convention) or above ground | Take-off mode flags cells where the drone would sit inside terrain or buildings |

Maps: **Link margin** (best of 2.4 / 5.8 GHz), **Line of sight** (≥60% first
Fresnel zone clear / LOS but obstructed / no LOS), **Min altitude** (lowest of
10…120 m that keeps the required margin).

## Known limitations (intentional in the baseline)

- No vegetation loss. Wrong wherever the path crosses trees at 2.4/5.8 GHz.
- No reflections or multipath, so it is **pessimistic in urban canyons**. A
  pilot standing next to 10–15 m buildings gets ~20–30 dB of near-field
  diffraction loss in every direction. Reality is better thanks to reflections.
  This gap is the most interesting thing to measure.
- No interference modelling beyond DJI's rated-range levels.
- No antenna patterns, and no blocking by the pilot's body or controller orientation.

## Layout

```
rcm/grid.py          local metric grid around the pilot
rcm/terrain.py       Terrarium tiles → elevation grid (cached)
rcm/buildings.py     Overture buildings → height grid (cached)
rcm/propagation.py   FSPL + Bullington, radial numba kernel
rcm/devices.py       device catalogue + rated-range link budget
rcm/service.py       scene cache, coverage, min-altitude, PNG rendering
app/                 FastAPI + Leaflet UI
tests/               analytic checks
logs/                DJI flight records (git/docker-ignored)
```

## Next

1. Decrypt the flight logs (DJI Open API key) → per-sample signal quality with
   3D position.
2. Replay each flight through this baseline and compare predicted margin against
   the logged uplink/downlink quality.
3. Add a vegetation layer (Meta 1 m canopy height) and re-compare.
4. Sionna RT data generation → fast surrogate model.
