use tracktor::filters::phd::GmPhdFilter;
use tracktor::prelude::*;
use tracktor::utils::{ExtractionConfig, PruningConfig, extract_targets, prune_and_merge};
fn main() {
println!("Tracktor: Multi-Target Tracking Library");
println!("======================================\n");
let transition = ConstantVelocity2D::new(
1.0, 0.99, );
let observation = PositionSensor2D::new(
5.0, 0.9, );
let clutter = UniformClutter2D::new(
5.0, (0.0, 200.0), (0.0, 200.0), );
let mut birth = FixedBirthModel::<f64, 4>::new();
birth.add_birth_location(
0.05, StateVector::from_array([10.0, 10.0, 0.0, 0.0]),
StateCovariance::from_matrix(nalgebra::matrix![
100.0, 0.0, 0.0, 0.0;
0.0, 100.0, 0.0, 0.0;
0.0, 0.0, 25.0, 0.0;
0.0, 0.0, 0.0, 25.0
]),
);
birth.add_birth_location(
0.05,
StateVector::from_array([190.0, 190.0, 0.0, 0.0]),
StateCovariance::from_matrix(nalgebra::matrix![
100.0, 0.0, 0.0, 0.0;
0.0, 100.0, 0.0, 0.0;
0.0, 0.0, 25.0, 0.0;
0.0, 0.0, 0.0, 25.0
]),
);
let filter = GmPhdFilter::new(transition, observation, clutter, birth);
let initial_components = vec![
GaussianState::new(
1.0,
StateVector::from_array([50.0, 50.0, 2.0, 1.0]),
StateCovariance::from_matrix(nalgebra::matrix![
10.0, 0.0, 0.0, 0.0;
0.0, 10.0, 0.0, 0.0;
0.0, 0.0, 5.0, 0.0;
0.0, 0.0, 0.0, 5.0
]),
),
GaussianState::new(
1.0,
StateVector::from_array([100.0, 100.0, -1.0, 2.0]),
StateCovariance::from_matrix(nalgebra::matrix![
10.0, 0.0, 0.0, 0.0;
0.0, 10.0, 0.0, 0.0;
0.0, 0.0, 5.0, 0.0;
0.0, 0.0, 0.0, 5.0
]),
),
];
let mut state = filter.initial_state_from(initial_components);
println!(
"Initial state: {} components, {:.2} expected targets\n",
state.mixture.len(),
state.expected_target_count()
);
let measurements_per_step = [
vec![[52.0, 51.0], [99.0, 102.0], [150.0, 30.0]],
vec![[54.0, 52.0], [45.0, 180.0]],
vec![[56.0, 53.0], [97.0, 106.0]],
vec![[58.0, 54.0], [95.0, 110.0], [20.0, 20.0], [180.0, 50.0]],
vec![[60.0, 55.0], [93.0, 114.0]],
];
let dt = 1.0;
let pruning_config = PruningConfig::new(1e-4, 4.0, 50);
let extraction_config = ExtractionConfig::weight_threshold(0.5);
for (t, meas_data) in measurements_per_step.iter().enumerate() {
let measurements: Vec<Measurement<f64, 2>> = meas_data
.iter()
.map(|m| Measurement::from_array(*m))
.collect();
println!("Time step {}: {} measurements", t, measurements.len());
let predicted = state.predict(&filter.transition, &filter.birth, dt);
println!(
" After predict: {} components, {:.2} expected targets",
predicted.mixture.len(),
predicted.expected_target_count()
);
let updated = predicted.update(&measurements, &filter.observation, &filter.clutter);
println!(
" After update: {} components, {:.2} expected targets",
updated.mixture.len(),
updated.expected_target_count()
);
let pruned = prune_and_merge(&updated.mixture, &pruning_config);
state = tracktor::filters::phd::PhdFilterState::from_mixture(pruned);
println!(
" After prune: {} components, {:.2} expected targets",
state.mixture.len(),
state.expected_target_count()
);
let targets = extract_targets(&state.mixture, &extraction_config);
println!(" Extracted targets:");
for (i, target) in targets.iter().enumerate() {
println!(
" Target {}: pos=({:.1}, {:.1}), vel=({:.1}, {:.1}), conf={:.2}",
i,
target.state.index(0),
target.state.index(1),
target.state.index(2),
target.state.index(3),
target.confidence
);
}
println!();
}
println!("Tracking complete!");
}