tracktor 0.4.0

Multi-target tracking with random finite sets
Documentation

Tracktor

A type-safe Rust library for Multi-Target Tracking (MTT) using Random Finite Set (RFS) based algorithms.

Why Tracktor?

Compile-Time Correctness

Tracktor leverages Rust's type system to catch errors at compile time, not runtime:

// Vector spaces are type-distinct - you can't accidentally mix them
let state: StateVector<f64, 4> = /* ... */;
let measurement: Measurement<f64, 2> = /* ... */;

// This won't compile - type system prevents invalid operations
// let wrong = state + measurement;  // Error!

// Matrices encode their transformations
let H: ObservationMatrix<f64, 2, 4> = /* ... */;  // Maps 4D state → 2D measurement
let measurement = H.observe(&state);               // Correct by construction

State Machine Enforced Filter Phases

The predict-update cycle is enforced at the type level:

// Filter states are typed - can't update before predict
let filter: PhdFilterState<f64, 4, Updated> = /* ... */;

let predicted = filter.predict(&model);  // Returns PhdFilterState<_, _, Predicted>
let updated = predicted.update(&obs, &measurements);  // Returns PhdFilterState<_, _, Updated>

// This won't compile - type system enforces correct ordering
// let wrong = filter.update(&obs, &measurements);  // Error! Can't update an Updated state

Const Generic Dimensions

State and measurement dimensions are compile-time constants:

// 4D state (x, y, vx, vy), 2D measurements (x, y)
type State = StateVector<f64, 4>;
type Meas = Measurement<f64, 2>;

// Dimension mismatches are caught at compile time, not runtime

Embedded-Ready

Full no_std support with optional alloc - deploy on resource-constrained platforms and real-time systems without compromise.

Features

Multi-Target Filters

  • GM-PHD Filter: Gaussian Mixture Probability Hypothesis Density filter based on Vo & Ma (2006)
  • LMB Filter: Labeled Multi-Bernoulli filter with track label preservation
  • LMBM Filter: Labeled Multi-Bernoulli Mixture for multi-hypothesis tracking
  • Multi-Sensor LMB: AA-LMB, GA-LMB, PU-LMB, IC-LMB variants for sensor fusion

Single-Target Filters

  • Kalman Filter: Standard discrete-time linear Kalman filter
  • Extended Kalman Filter (EKF): Nonlinear filter with Jacobian linearization
  • Unscented Kalman Filter (UKF): Sigma-point filter for highly nonlinear systems

Core Capabilities

  • Pluggable Models: Trait-based transition, observation, clutter, and birth models
  • Numerical Stability: Joseph form covariance updates with singular matrix detection
  • Mixture Management: Intelligent pruning and merging to maintain tractable component counts
  • State Extraction: Multiple strategies (threshold, top-N, expected count, local maxima)
  • Assignment Solver: Hungarian algorithm for optimal track-to-measurement association
  • Embedded-Ready: Full no_std support with optional alloc

Quick Start

use tracktor::prelude::*;

fn main() {
    // Define models
    let dt = 1.0;
    let transition = ConstantVelocity2D::new(1.0, 0.95);  // (noise_diff_coeff, p_survival)
    let observation = PositionSensor2D::new(10.0, 0.98);  // (noise_variance, p_detection)
    let clutter = UniformClutter2D::new(10.0, (0.0, 100.0), (0.0, 100.0));
    let birth = FixedBirthModel::<f64, 4>::new();  // Empty birth model

    // Initialize filter with known targets
    let mut mixture = GaussianMixture::new();
    mixture.push(GaussianState::new(
        0.8,
        StateVector::from_array([25.0, 25.0, 1.0, 0.5]),
        StateCovariance::identity().scale(10.0),
    ));

    let filter = PhdFilterState::from_mixture(mixture);

    // Predict-update cycle
    let predicted = filter.predict(&transition, &birth, dt);
    let measurements = [Measurement::from_array([26.1, 25.4])];
    let updated = predicted.update(&measurements, &observation, &clutter);

    // Prune, merge, and extract targets
    let config = PruningConfig::default_config();
    let pruned = prune_and_merge(&updated.mixture, &config);
    let targets = extract_targets(&pruned, &ExtractionConfig::weight_threshold(0.5));

    println!("Expected targets: {:.2}", pruned.total_weight());
    for target in targets {
        println!("Target at ({:.1}, {:.1}) with confidence {:.2}",
            *target.state.index(0), *target.state.index(1), target.confidence);
    }
}

Models

Transition Models

  • ConstantVelocity2D - 4D state [x, y, vx, vy] with white noise acceleration
  • ConstantVelocity3D - 6D state [x, y, z, vx, vy, vz] for 3D tracking
  • CoordinatedTurn2D - 5D state [x, y, vx, vy, omega] with turn rate (nonlinear)

Observation Models

  • PositionSensor2D - Observes [x, y] from 4D position-velocity state
  • PositionSensor2DAsym - Asymmetric noise in x/y directions
  • PositionSensor3D - Observes [x, y, z] from 6D state
  • RangeBearingSensor - Nonlinear range-bearing for 4D state
  • RangeBearingSensor5D - Range-bearing for 5D coordinated turn model

Clutter Models

  • UniformClutter - Uniform Poisson clutter over rectangular surveillance region (generic over dimensions)

Birth Models

  • FixedBirthModel - Predefined birth locations with configurable weights and covariances

State Extraction

Multiple strategies for extracting target estimates from the mixture:

  • Weight Threshold: Extract components exceeding a weight threshold
  • Top-N: Extract N highest-weighted components
  • Expected Count: Extract based on rounded total weight
  • Local Maxima: Extract local maxima with Mahalanobis distance-based suppression
let config = ExtractionConfig::default()
    .with_weight_threshold(0.5)
    .with_max_targets(10);

let targets = config.extract(&mixture);

References

Based on the seminal work:

  • B.-N. Vo and W.-K. Ma, "The Gaussian Mixture Probability Hypothesis Density Filter," IEEE Transactions on Signal Processing, vol. 54, no. 11, pp. 4091-4104, Nov. 2006.

License

Licensed under either of AGPL3.0 or commercial license (contact me)