Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CONSTRAINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Invariants this project holds itself to. Every entry is either currently true
or is a stated blocker; nothing here is aspirational. Ratchets are measured,
not estimated, and the command to re-measure each one is given.

Last measured: <!-- metric:tests_collected -->1319<!-- /metric --> tests collected, all of which pass except the deliberate
Last measured: <!-- metric:tests_collected -->1322<!-- /metric --> tests collected, all of which pass except the deliberate
xfails and the skips that `pytest -rs` lists, and <!-- metric:coverage_percent -->94.3<!-- /metric -->%
line coverage (<!-- metric:coverage_lines_hit -->10033<!-- /metric -->/<!-- metric:coverage_lines_total -->10638<!-- /metric --> executable lines) on **CPython <!-- metric:coverage_python -->3.13<!-- /metric -->**, measured
with `python scripts/coverage_report.py`. The figures come from `docs/data/metrics.json`, which `scripts/metrics.py` checks in CI. Coverage is quoted from that script alone:
Expand Down Expand Up @@ -83,7 +83,7 @@ These are floors, not goals. Each must not regress; raising one is welcome.

| Ratchet | Floor | Current (CPython 3.13) | Re-measure with |
|---|---:|---:|---|
| Tests collected | 405 | <!-- metric:tests_collected -->1319<!-- /metric --> | `pytest`, `scripts/metrics.py --check` |
| Tests collected | 405 | <!-- metric:tests_collected -->1322<!-- /metric --> | `pytest`, `scripts/metrics.py --check` |
| Tests passing | 300 | all collected, except the deliberate xfails and the listed skips | `pytest -rs` |
| Line coverage | 75% | <!-- metric:coverage_percent -->94.3<!-- /metric -->% | `scripts/coverage_report.py`, `scripts/metrics.py --check-coverage` |
| `io/trajectory.py` coverage | 85% | 95.0% | as above |
Expand Down
8 changes: 7 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ provider fails to authenticate rather than the file failing to load. Rotating
the key is a manual step for the key's owner; ignore rules keep it out of Git but
do not invalidate it anywhere it has already been exposed.

The template was checked against OpenCode 1.19.0 with a local OpenAI-compatible
mock endpoint. `@ai-sdk/openai-compatible` is the supported package for this
kind of provider. To switch a built-in provider off, list it in
`disabled_providers`: a `"disabled": true` key inside a `provider` entry is not
part of the schema and is dropped without a warning, so the provider stays on.

## Before opening a pull request

All of these must pass locally. They are what CI runs.
Expand All @@ -70,7 +76,7 @@ mypy src --ignore-missing-imports
`ruff format src tests scripts` applies formatting; the `--check` form is the
gate.

The suite collects <!-- metric:tests_collected -->1319<!-- /metric --> tests and all of them pass on a fresh clone, except the deliberate
The suite collects <!-- metric:tests_collected -->1322<!-- /metric --> tests and all of them pass on a fresh clone, except the deliberate
xfails and the skips. `pytest -rs` lists the skips: two need TUM VI reference data that is not
vendored (see below), and the doc-table check runs once `python scripts/run_benchmark.py` has
written `results/benchmark.json`. The count and the other numbers the docs quote are in
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,31 @@ table below. It is a synthetic result, the default is unchanged, and visual fusi
> IMU with simulated GNSS and, in one study, real camera frames. No number here is a field
> measurement.

## How it works

<!-- how-it-works-start -->
```mermaid
flowchart TB
IMU["IMU, always on"] --> F
GNSS["GNSS, can be denied"] --> FDIR["Fault detection: screens each measurement"]
CAM["Camera motion, opt-in"] -.-> FDIR
FDIR --> F["Navigation filter: position, and how sure it is"]
F --> ACC["Accuracy: error against the truth"]
F --> HON["Honesty: is the truth inside the claimed area?"]
TRUTH["Known truth: synthetic runs, recorded datasets"] --> ACC
TRUTH --> HON
ACC --> GATE{"Gate B1"}
HON --> GATE
GATE -- "met" --> ON["Camera fusion on"]
GATE -- "not met" --> OFF["Camera fusion off by default (ADR-0003)"]
```

Every run is scored twice: how far the estimate is from the truth, and whether the truth falls
inside the area the filter claims. A feature that improves the first and breaks the second stays
off. A short captioned explainer is on the [project page](https://telschow.github.io/contested-nav/);
the module-level design is in [docs/architecture.md](docs/architecture.md).
<!-- how-it-works-end -->

## Quickstart

Python 3.11 to 3.13. From a fresh clone this took **18.7 s** (clone, environment, install and a
Expand Down
2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Sequenced by dependency, not by ambition. Each item names its exit test.
Status markers: `[x]` done, `[~]` in progress, `[ ]` not started, `[!]`
blocked.

Measured baseline: <!-- metric:tests_collected -->1319<!-- /metric --> tests collected and <!-- metric:coverage_percent -->94.3<!-- /metric -->% line coverage on CPython
Measured baseline: <!-- metric:tests_collected -->1322<!-- /metric --> tests collected and <!-- metric:coverage_percent -->94.3<!-- /metric -->% line coverage on CPython
<!-- metric:coverage_python -->3.13<!-- /metric --> (`docs/data/metrics.json`, from `scripts/metrics.py` and `scripts/coverage_report.py`). Every
number below re-measures against that, not against a remembered value.

Expand Down
Binary file added docs/assets/video/contested-nav-explainer.mp4
Binary file not shown.
Binary file added docs/assets/video/explainer-poster.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/data/metrics.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"coverage_lines_total": 10638,
"coverage_percent": 94.31,
"coverage_python": "3.13",
"tests_collected": 1319
"tests_collected": 1322
}
15 changes: 15 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

**Is the filter right about how wrong it is?**

<video controls preload="metadata" poster="assets/video/explainer-poster.jpg" style="width:100%">
<source src="assets/video/contested-nav-explainer.mp4" type="video/mp4">
</video>

*A captioned explainer built from one benchmark run: the same GNSS outage with the camera off and
on, the measured accuracy and calibration, and the decision that follows.*

![Position error against the uncertainty the filter claims, through a GNSS outage, without and with vision](figures/hero.png)

`contested-nav` is a 21-state error-state Kalman filter and an evaluation harness for GNSS-denied
Expand All @@ -21,6 +28,14 @@ did not (see [Results](results.md)).
The table above comes from a deterministic known-answer fixture. The recorded-data pages use a
real IMU with GNSS simulated from the ground truth. No number here is a field measurement.

## How it works

{%
include-markdown "../README.md"
start="<!-- how-it-works-start -->"
end="<!-- how-it-works-end -->"
%}

## Where to start

- [Getting started](getting-started.md): install, run the headline case in 19 seconds, reproduce every number.
Expand Down
9 changes: 3 additions & 6 deletions opencode.example.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"$schema": "https://opencode.ai/config.json",
"model": "freellmapi/auto",
"disabled_providers": [
"ollama"
],
"provider": {
"freellmapi": {
"npm": "@ai-sdk/openai-compatible",
Expand All @@ -20,12 +23,6 @@
"name": "Auto Router (Fastest / Low Latency)"
}
}
},
"local": {
"disabled": true
},
"ollama": {
"disabled": true
}
}
}
32 changes: 32 additions & 0 deletions tests/test_opencode_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""The committed OpenCode template: shape checks that do not need OpenCode installed.

OpenCode 1.19.0 drops unknown keys inside a ``provider`` entry without a warning, so a
``"disabled": true`` there leaves the provider switched on. ``disabled_providers`` is the
supported switch.
"""

from __future__ import annotations

import json
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
CONFIG = json.loads((ROOT / "opencode.example.json").read_text(encoding="utf-8"))


def test_default_model_names_a_declared_provider_and_model() -> None:
provider, _, model = CONFIG["model"].partition("/")
assert model in CONFIG["provider"][provider]["models"]


def test_providers_are_disabled_with_the_supported_key() -> None:
for name, entry in CONFIG["provider"].items():
assert "disabled" not in entry, f"{name}: use disabled_providers instead"
assert isinstance(CONFIG.get("disabled_providers", []), list)


def test_api_key_comes_from_the_environment() -> None:
for name, entry in CONFIG["provider"].items():
key = entry.get("options", {}).get("apiKey")
if key is not None:
assert key.startswith("{env:") and key.endswith("}"), name
Loading