# Validation evidence

The project uses a staged ladder so perception and frame conventions are proven
before armed flight. `reports/status.json` is the compact machine-readable
record of the formal reference runs; screenshots and SHA256 checks are under
`reports/assets/`.

| Stage | Purpose | Formal result |
|---|---|---|
| Static perception | 1–3 m, offset and yaw | 5/5 scenes; 100% valid; hamming 0 |
| Compensation bench | level, roll/pitch ±15° | horizontal RMSE `0.000957 m`; p95 `0.001076 m` |
| Unarmed output | 600 attitude setpoints | `50.03 Hz`; attitude-only; never armed |
| Static flight | 60 s relative hold | XY RMS `0.096 m`; p95 `0.227 m`; disarmed |
| Moving target | 0.5 m/s figure-eight, 120 s | visual RMS `0.319 m`; p95 `0.560 m` |
| Independent score | Gazebo truth, read-only | RMS `0.324 m`; p95 `0.574 m` |
| Visible GUI | 0.25 m/s figure-eight, 60 s | visual RMS `0.229 m`; p95 `0.448 m` |
| Manual target | real keyboard events | deadman `0.4 s`; operator quit; disarmed |
| Occlusion | short and persistent loss | recover at `0.352 s`; descend at `9.94 s` |

The truth evaluator subscribes only to Gazebo clock and dynamic pose, publishes
nothing, and is a separate process. The controller's forbidden-input audit lists
GPS, `LOCAL_POSITION_NED`, `GLOBAL_POSITION_INT`, optical flow, LiDAR/SLAM, and
Gazebo truth.

Reference run identifiers remain in `reports/status.json` and image captions so
results can be traced across exported evidence. Raw `runs/` directories are not
committed because they contain transient logs and may grow substantially.

To verify the public evidence contract and image integrity:

```bash
python3 scripts/validate_docs.py
(cd reports/assets && sha256sum -c SHA256SUMS)
./demo.sh --verify
```

To generate a new local run, use `./demo.sh --gate1`, `--gate2`, `--gate3`,
`--gate5`, or `--gate6`. Do not replace the reference numbers with a new run
until its final state is disarmed, cleanup passes, and the controller-input audit
still proves truth isolation.
