# 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:
```rust
// 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:
```rust
// 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:
```rust
// 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
```rust
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
```rust
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)