No description
  • Python 67.1%
  • JavaScript 21.7%
  • CSS 5.9%
  • HTML 5.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-26 00:03:30 +03:00
src/tofdr Initial 2026-09-25 23:55:58 +03:00
tests Initial 2026-09-25 23:55:58 +03:00
.gitignore Initial 2026-09-25 23:55:58 +03:00
pyproject.toml Initial 2026-09-25 23:55:58 +03:00
README.md requirements.txt 2026-09-26 00:03:30 +03:00
requirements.txt requirements.txt 2026-09-26 00:03:30 +03:00

tofdr

Beacon ranging simulation with a web UI. A client moves at a set speed and bearing while fixed beacons measure their distance to it with uniform noise. The client periodically multilaterates its position from the latest range estimates (least-squares Gauss-Newton, minimum 4 beacons) and reports a 1-sigma position uncertainty. The web app shows the real and estimated client, track histories, and an uncertainty bubble on a top-down map.

Setup

Requires Python 3.10+.

source .venv/bin/activate
pip install -e ".[dev]"

Running the web app

python -m tofdr.webapp

Then open http://localhost:8000 (served on 127.0.0.1 only). The simulation runs server-side; the browser steps it at ~10 Hz and redraws the map.

Using the UI

Simulation panel (each change restarts the world):

Control Meaning Default
beacon estimate rate how often each beacon produces a range estimate (Hz, fractional) 2
client report rate how often the client computes a position fix (Hz; may exceed the beacon rate) 5
client speed real client speed (m/s) 1.5
client direction bearing in degrees clockwise from north 90
ranging noise uniform noise added to each beacon's distance (± m) 5

Beacons panel:

  • Number of beacons (1-32); new beacons are placed on a ring of radius 200 m around the start point. Position estimation needs at least 4 beacons — otherwise a warning is shown and no estimate is drawn.
  • Each beacon's x (east), y (north), and altitude (meters above ground) can be edited in the table, or the beacon can be dragged directly on the map. Altitude spread matters: a couple of high beacons give the solver vertical information.

Map and readout:

  • Green dot: real client; gray line: true track.
  • Orange dot: estimated client; dashed orange line: estimate track; filled bubble: 2-sigma horizontal uncertainty, outline: 1-sigma.
  • Blue squares: beacons (labeled b1, b2, ...).
  • Readout above the map shows the current horizontal error, sigma horizontal, sigma vertical, and the rate configuration.
  • The view auto-fits and only expands; it recenters on the next config change.
  • Pause/Resume freezes the simulation; Reset restarts with the current settings.

HTTP API

The UI is a static page over a small JSON API:

  • GET /api/state — current world state (beacons, true/estimated position, tracks, error, config).
  • POST /api/config — replace the world. Body: {"beacons": [{"x", "y", "alt"}, ...], "beacon_rate", "report_rate", "speed", "bearing", "noise"}; omitting beacons uses n_beacons on the default ring. Invalid values fall back to defaults.
  • POST /api/step — advance the world by {"dt": seconds} (capped at 5 s) and return the new state.

Tests

pytest