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.2.tar.gz (166.9 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.2-py3-none-any.whl (137.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: gri_tracksim-0.3.2.tar.gz
  • Upload date:
  • Size: 166.9 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.2.tar.gz
Algorithm Hash digest
SHA256 8d3cfcc3de8e38b6083db8af0b29c5d85ff061e90eb25c74c91fe1831f5819c4
MD5 57cb3402e6aff8a36d0ef4ab390c2f44
BLAKE2b-256 65f58a6c59eedee7221931e1ca3ef3745c1f3d67e706753b023e8687e3047326

See more details on using hashes here.

File details

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

File metadata

  • Download URL: gri_tracksim-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 137.2 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8ace3802f993453f87c015c484c543b30e3b87b152102e7a4b78f43c84fa98f7
MD5 41312ec2c8012fcf180729e2bd02b5c9
BLAKE2b-256 5013967d9270241eeaa03e9ab9ac56ac6369ea98387f06698e54e63db949e8f0

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