Skip to main content

gri-kalman

Per-target Kalman tracking for geolocation: interacting multiple model (IMM) filters with a motion-model bank, maneuver segmentation, RTS smoothing, and EKF/UKF measurement updates from either Ell position fixes or raw observables.

This package was factored out of gri-convolve so the per-target estimators can be reused without the ellipsoid-convolution stack. It depends only on gri-ell, gri-obs, gri-pos, gri-utils (plus numpy/scipy).

Documentation

The wheel ships its documentation inside the package, in gri_kalman/docs/, so it is available wherever the package is installed:

  • overview.md -- the trackers, the result surface, motion models, gating and its limits, segmentation, and observables
  • api_summary.md -- every public class, function, and signature (generated)

Print the directory with python -c "import gri_kalman, pathlib; print(pathlib.Path(gri_kalman.__file__).parent / 'docs')". Every example in those files is run by the test suite.

Install

uv add gri-kalman

Trackers

All implement the Tracker protocol (update / update_observable / predict / coast / smoothed_track / result / is_initialized):

Tracker Description
IMM Interacting multiple model filter over a motion-model bank
SmartIMM IMM with outlier rejection on the measurement stream
SegmentedIMM Maneuver-segmenting IMM (per-segment filters)
SmartSegmentedIMM Segmenting + outlier-rejecting (the recommended default)

Motion models: ConstantVelocity, ConstantAcceleration, NearlyConstantSpeed, CoordinatedTurn, Singer, AscendDescend, Static (plus the LinearMotionModel / NonlinearMotionModel / MotionModel base protocols).

Local-level (ENU) awareness

The state is ECEF, but a maneuver's "horizontal" and "vertical" are defined relative to local up, not the ECEF axes. Models whose dynamics or noise are anisotropic in that sense take a level_rotation provider (an ECEF position -> 3x3 ECEF->ENU rotation):

  • CoordinatedTurn turns in the local horizontal plane about local up (not the ECEF polar axis).
  • AscendDescend puts its large maneuvering noise along local up.
  • ConstantVelocity can split process noise / velocity prior into horizontal and a small vertical component, to model a level mover (boat, car, cruising aircraft).

Pass a constant rotation for a fixed local-level frame (rigorous over a bounded area) or the position-dependent wgs84_level_rotation to follow Earth curvature with no re-origining.

Gauss-Markov reverting components

Several models hold a state that should revert toward zero absent evidence, all via the same first-order Gauss-Markov (Ornstein-Uhlenbeck) mechanism — a (tau, sigma) pair (time constant + steady-state spread), gauss_markov_step:

  • Static reverts its (nuisance) velocity toward zero.
  • CoordinatedTurn reverts its turn rate toward zero (straight), so a turn rate picked up from noise on a straight leg relaxes instead of persisting.
  • Singer reverts its acceleration toward zero (the canonical named case).

The pull is gentle (long tau) — real maneuver evidence overrides it within a scan or two, so it costs no responsiveness.

Smoothing: rts_smooth, rts_smooth_segments, track_to_ells. Result container: KalmanResult.

EKF vs UKF for observable updates

update() consumes an Ell (3D position + covariance) and is always an exact linear update. update_observable() consumes a nonlinear observable (TDOA, FDOA, AOA, Range, ...); choose the linearization with update_method:

  • "ekf" (default): linearizes at the predicted mean via the observable's jacobian(). Cheap and accurate when the prior is tight relative to the geometry's nonlinearity.
  • "ukf": propagates sigma points through predicted() (no Jacobian). More robust (better-calibrated covariance) when the prior is broad and the observable is strongly nonlinear -- e.g. track initiation, long coast gaps, AOA, or satellite TDOA. Tune the spread with ukf_alpha.

The UKF's advantage is consistency, not necessarily smaller point error; switch to it for robustness when the prior is broad, not expecting lower position error in mildly nonlinear cases.

Output: the unified tracking surface

tracker.result returns a KalmanResult that satisfies the TrackingOutput protocol — the same surface the multi-target gri-multitrack engine reports, so a consumer reads tracks, per-observation dispositions, and (on request) smoothed trajectories the same way regardless of which tracker produced them. A single-target tracker is the degenerate one-track case.

  • result.tracks — a list of TrackEstimate (one element here; use result.track for it). Each carries state as an EllVel (position + velocity + full 6x6 covariance; an EllAcc when a constant-acceleration model contributes), mode_probabilities, existence, confirmed, hits, and a bound predict.

  • result.dispositions — one Disposition per observation, in arrival order, indexed in the whole stream handed to the tracker (for the segmented trackers too; a gate failure still awaiting a changepoint decision is provisional). Each has index, used, verdict (assigned / rejected), track, confidence. The outlier / unused bucket is simply:

    outliers = [d for d in result.dispositions if not d.used]
    

    Only the gating trackers (SmartIMM, SmartSegmentedIMM) reject; a plain IMM has no gate, so everything is assigned.

  • Prediction is a bound closure: result.track.predict(dt_s) returns a PredictedState (an EllVel at time + dt_s), propagated through the motion model. Ask for any horizon on demand — there is no fixed prediction list.

  • Smoothing is optional and on request (it refines the past trajectory, not the present estimate, so it is never part of the live output):

    smoothed = result.smoothed()          # {label: [(t, Ell), ...]}
    

    The live tracks are the filtered ("best given data so far") estimate; smoothed() returns the retrospective ("best given all data") trajectory.

out = tracker.result
fix = out.track.state                  # EllVel: .ell (position), .vel_xyz, .vel_cov
v = out.track.state.vel_xyz            # current velocity
outliers = [d for d in out.dispositions if not d.used]
future = out.track.predict(30.0).state # extrapolate 30 s ahead
past = out.smoothed()                  # retrospective trajectory (opt-in)

Notes

  • State is ECEF; positions/covariances interchange with gri-ell Ell objects.
  • Downstream consumers: the multi-target engine gri-multitrack orchestrates these trackers via the Tracker protocol; gri-convolve no longer ships them.

License

MIT -- see LICENSE.

Metadata

Release files for gri-kalman 0.3.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gri-kalman 0.3.6
File Size Uploaded
gri_kalman-0.3.6.tar.gz 114.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gri-kalman 0.3.6
File Interpreter ABI Platform
gri_kalman-0.3.6-py3-none-any.whl Python 3 none any Details

Total release size: 206.4 kB

Release files / gri_kalman-0.3.6.tar.gz

Download URL gri_kalman-0.3.6.tar.gz
Size 114.4 kB
Tags Source
SHA-256 checksum
How to use checksums
5e76ddb37b632566c6ec81cd682d16dc5a552a1b0cf85bddb91f8558bcb0a2c4
BLAKE2b-256 checksum
How to use checksums
110a99af88578ae2be87386b3b6a33448d704705e29f71aac08f97e7004eb8b1
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release files / gri_kalman-0.3.6-py3-none-any.whl

Download URL gri_kalman-0.3.6-py3-none-any.whl
Size 92.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
83eea2996fc20bdb6d99b4fe966f0e34527f7168b75d5fc7991d0ec0c7a7d114
BLAKE2b-256 checksum
How to use checksums
ed9f1f7261a94f50e24d485461f7d301119bce985302f1c9dd0f43c80c2f7176
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release history Release notifications | RSS feed

This release

0.3.6 This release

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page