Skip to main content

Tracking-scenario simulator and replay visualizer over a shared JSONL stream contract

Project description

GeoSol Research Logo

TrackSim (Tracking-Scenario Simulation)

Tracking-scenario simulator and replay visualizer over a shared JSONL stream contract. Generate labeled truth, degrade it into observables across fidelity tiers, replay it through a reference estimator, and scrub the result on a timeline. Requires Python 3.12+.

gri-tracksim is two paired tools joined by one file contract: a simulator that emits truth / input / output streams, and a Dash/Plotly replay viewer that reads them. The boundary is the JSONL contract alone, so the viewer renders the output of any contract-conformant tracker, not just this package's.

The viewer is a 2D replay tool. The 3D analyst app ("Crucible") is a separate, closed product and is not part of this repository.

Key Features

  • Scenario simulator: leg-based truth (straight / turn / climb / hold), degraded observables (geo / TDOA / FDOA / AOA / altitude), and a four-tier fidelity ladder (T0..T3) driven from one physical scene.
  • Declarative scenarios: author scenarios in YAML from the shipped vocabulary - no source checkout required.
  • Reference replay: a single-target IMM replay produces the output stream with forward-prediction horizons.
  • Replay viewer: a 2D top-down ENU map plus linked time-series panes, with a play/scrub timeline.
  • Self-contained contract: a language-agnostic JSONL wire format you can emit from your own tracker and render here.

Capability Tiers

gri-tracksim is built around three ways to use it:

  1. Viz-only consumer - you already have a tracker. Emit the JSONL contract and run gri-tracksim-viz to scrub it.
  2. Scenario author - write scenario YAML from the shipped vocabulary (emitters, legs, tiers, collector presets, noise) and generate the truth / input / output triple. Needs the package; no source.
  3. Vocabulary developer - add new leg primitives, collector geometries, fidelity tiers, or parametric sweeps. These live in registries in the source and require a checkout (see AGENTS.md).

Installation

pip install gri-tracksim          # simulator + replay viewer

Quick Start

Generate a scenario (CLI)

gri-tracksim --list                  # list bundled example scenarios
gri-tracksim air_racetrack           # render a bundled scenario
gri-tracksim air_racetrack --tier T3 # same scene, harder tier
gri-tracksim air_racetrack --seed 7  # same scene, new realization
gri-tracksim my_scenario.yaml        # render your own YAML

The scene name (air_racetrack) describes the physical scenario; --tier (T0-T3) and --seed are orthogonal run knobs layered over it. Each defaults to the scene's own value (a --seed-less scene with no seed: draws a random one), and the effective tier and seed are folded into the output directory so sweeps never clobber: streams land in _scratch/<name>_<tier>_s<seed>/. The output root defaults to _scratch/ (a gitignored scratch dir); override it with -o <dir>.

Scrub a run (viewer)

gri-tracksim-viz _scratch/air_racetrack_T2_s3

Author a scenario in Python

from gri_tracksim.sim import load_scenario, write_scenario_streams

scenario = load_scenario("my_scenario.yaml")
n_truth, n_input, n_output = write_scenario_streams(
    scenario, "_scratch/my_scenario", predict_horizons_s=(10.0, 30.0),
)

Read the contract from your own tracker

from gri_tracksim.contract import Header, load_stream, write_jsonl

header, records = load_stream("output.jsonl")   # parsed Header + event records

You only need gri_tracksim.contract to emit or read the streams - it has no dependency on the simulator or the viewer.

Scenario YAML

A scenario is a single declarative file. All keys but name, origin_lla, dt, and emitters are optional:

name: air_racetrack
origin_lla: [38.0, -77.0, 0.0]   # ENU anchor [lat_deg, lon_deg, alt_m]
dt: 2.0                          # grid step (s)
seed: 3                          # default realization (--seed overrides; random if omitted)
tier: T2                         # default tier (--tier overrides): T0 | T1 | T2 | T3
collectors: diverse              # good | weak | diverse | null
motion: air                      # level (cruise) | air (climb-aware IMM)
noise:
  altitude_std_m: 200.0
emitters:
  E1:
    start_enu: [0.0, 0.0, 1000.0]
    azimuth_deg: 90.0
    speed_mps: 120.0
    legs:
      - {type: straight, duration_s: 30.0}
      - {type: climb, duration_s: 20.0, climb_rate_mps: 10.0}
      - {type: turn, delta_azimuth_deg: 180.0, radius_m: 2000.0}

The leg types (straight, turn, climb, hold), fidelity tiers (T0..T3), collector presets (good, weak, diverse), and replay motion banks (level, level_fx, air) are fixed vocabularies; adding to them is the source-only developer path.

Reference Replay Options

The replay tracker has three orthogonal knobs (defaults are the validated configuration; legacy values remain available for comparison runs):

  • Motion bank (motion: in the YAML): level (cv / turn / static), air (adds a climb mode so altitude changes read as a mode), level_fx (adds a fixed +/- nominal-rate turn pair -- instant turn discrimination when the platform's maneuver-rate class is known; harmful off-nominal).
  • Segmentation (segmentation=): mode_sequence (default) -- a retrospective MAP decode over the whole track, recomputed each scan, which also emits settled (fixed-lag smoothed) mode probabilities per scan; or locked, the online residual-trigger segmenter.
  • Prediction (prediction=): locked (default) -- predict under the current settled segment's model (settle-gated, speed-guarded); evolved or blend for comparison.

Evaluation Harness

Two console scripts score tracker configurations against truth, corpus-wide:

# render + score scenario x seed runs (metrics.json per run, summary.json per sweep)
gri-tracksim-eval --seeds 10 --tier T2 -o _scratch/eval_new
gri-tracksim-eval --seeds 10 --tier T2 --segmentation locked --prediction blend \
    --model-selection mean_ll -o _scratch/eval_legacy   # the legacy stack

# paired (scenario, seed) comparison: median delta, bootstrap CI, sign test
gri-tracksim-compare _scratch/eval_legacy _scratch/eval_new
gri-tracksim-compare _scratch/eval_legacy _scratch/eval_new --scenario boat_racetrack

Per-run metrics cover segmentation (count, boundary error, label accuracy), characterization (instant and settled mode agreement, lock latency, thrash), smoothing (RMS and straight-leg bow, with a truth-boundary oracle bound), and prediction (per-horizon RMS plus the phantom-curve ratio vs a CV extrapolation).

The Stream Contract

Each stream is JSON Lines: a self-describing header record followed by one record per event.

  • truth - {"t", "emitter_id", "pos_enu", "vel_enu", "leg_mode"}
  • input - {"t", "id", "type", ...} where type is one of geo | tdoa | fdoa | aoa | altitude; the stable id (obs_0000...) is what the output's association references.
  • output - the estimator replay, in two record kinds per scan:
    • per-track records {"t", "track", "pos_enu", "cov_enu", "vel_enu", "existence", "mode_probabilities", "stationary_locked", "resolved", "predicted", ...} - the track estimate (position + velocity in the ENU frame), one predicted entry per requested horizon, each naming the model that produced it. Mode-sequence replays also carry settled_t / settled_mode_probabilities (the fixed-lag smoothed mode mix a few scans behind the playhead).
    • one scene record per scan {"t", "scene", "count_distribution", "association", "events", "worlds"}. The per-observation dispositions live at association.dispositions - one entry per input observation {"obs_id", "verdict", "track", "prob", "cure", "repaired"}, where verdict is assigned | birthed | clutter | cured (the outlier / unused observations are the clutter verdicts). association also holds gates / marginals / hypotheses. worlds carries the MFA's surviving global hypotheses with weights (empty for the committal GNN).
  • smoothed (optional) - one retrospective snapshot per scan: the smoothed trajectory the tracker had settled on by that playhead, plus segments ({model, t_start, t_end}) naming the motion model the smoother used per leg. Segments revise as data accrues, so scrubbing replays the boundary back-dating.

The wire format is plain JSON (no gri types on the wire), so any tracker, in any language, can emit a stream the viewer will render.

Dependencies

A top-tier package in the GRI FOSS ecosystem; a sibling consumer of the same mid-tier libraries as gri-multitrack.

  • gri-geosim (iterative locate), gri-kalman (reference IMM replay), gri-trajectory (legs), gri-obs, gri-pos, gri-ell, gri-utils
  • gri-plot, dash, plotly (the replay viewer)
  • numpy, scipy, pyyaml

Other Projects

Current list of other GRI FOSS Projects we are building and maintaining.

License

MIT License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gri_tracksim-0.3.1.tar.gz (165.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gri_tracksim-0.3.1-py3-none-any.whl (136.1 kB view details)

Uploaded Python 3

File details

Details for the file gri_tracksim-0.3.1.tar.gz.

File metadata

  • Download URL: gri_tracksim-0.3.1.tar.gz
  • Upload date:
  • Size: 165.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for gri_tracksim-0.3.1.tar.gz
Algorithm Hash digest
SHA256 96cc8e8e3cac916db894c30f729e9e4e971ce7267571284f7fcff71434f03ba4
MD5 b4d353c82c299376e4364abde0e2747f
BLAKE2b-256 a0f485036687369b279ce9789cbfea9ace04bf7a8c83dd4dcdacaea6730f7596

See more details on using hashes here.

File details

Details for the file gri_tracksim-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: gri_tracksim-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 136.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for gri_tracksim-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a5fc51b2b2402ae32916bc9e2238d52df4da7a6e23a18f31afa4f4c24838d19b
MD5 faf61933682059ab4d1667f5d551ac4d
BLAKE2b-256 aed892498a7327a2a2315cf1b8ecfae27babc4eaefabfa047e4c9fd591dea2d7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page