#![forbid(unsafe_code)]
use assert_float_eq::*;
use minikalman::prelude::*;
use minikalman::regular::builder::*;
pub struct TestFilter {
pub filter: KalmanFilterType<3, f32>,
pub control: KalmanFilterControlType<3, 1, f32>,
pub measurement: KalmanFilterObservationType<3, 2, f32>,
}
pub fn create_test_filter(delta_t: f32) -> TestFilter {
let builder = KalmanFilterBuilder::<3, f32>::default();
let mut filter = builder.build();
let controls = builder.controls();
let mut control = controls.build::<1>();
let measurements = builder.observations();
let mut measurement = measurements.build::<2>();
filter.state_transition_mut().apply(|mat| {
mat.set_at(0, 0, 1.0);
mat.set_at(0, 1, delta_t);
mat.set_at(0, 2, 0.5 * delta_t * delta_t);
mat.set_at(1, 0, 0.0);
mat.set_at(1, 1, 1.0);
mat.set_at(1, 2, delta_t);
mat.set_at(2, 0, 0.0);
mat.set_at(2, 1, 0.0);
mat.set_at(2, 2, 1.0);
});
filter.state_vector_mut().set_zero();
filter.estimate_covariance_mut().make_scalar(0.1);
control.control_matrix_mut().apply(|mat| {
mat.set_at(0, 0, 0.5 * delta_t * delta_t);
mat.set_at(1, 0, delta_t);
mat.set_at(2, 0, 1.0);
});
control.control_vector_mut().set_zero();
control
.process_noise_covariance_mut()
.make_comatrix(1.0, 0.1);
measurement.observation_matrix_mut().set_all(1.0 / 3.0);
measurement.observation_matrix_mut().apply(|mat| {
mat.set_at(0, 0, 1.0); mat.set_at(0, 1, 0.0);
mat.set_at(0, 2, 0.0);
});
measurement
.measurement_noise_covariance_mut()
.make_identity();
TestFilter {
filter,
control,
measurement,
}
}
#[test]
fn simple_filter() {
let mut example = create_test_filter(1.0);
assert!(example
.filter
.estimate_covariance()
.inspect(|mat| (0..3).into_iter().all(|i| { mat.get_at(i, i) == 0.1 })));
for _ in 0..10 {
example.filter.predict();
}
assert!(example
.filter
.state_vector()
.as_ref()
.iter()
.all(|&x| x == 0.0));
example.filter.estimate_covariance().inspect(|mat| {
assert_f32_near!(mat.get_at(0, 0), 260.1);
assert_f32_near!(mat.get_at(1, 1), 10.1);
assert_f32_near!(mat.get_at(2, 2), 0.1);
});
example
.measurement
.measurement_vector_mut()
.set_at(0, 0, 0.0);
example.filter.correct(&mut example.measurement);
assert!(example
.filter
.state_vector()
.as_ref()
.iter()
.all(|&x| x == 0.0));
example.filter.estimate_covariance().inspect(|mat| {
assert!(mat.get_at(0, 0) < 1.0);
assert!(mat.get_at(1, 1) < 0.2);
assert!(mat.get_at(2, 2) < 0.01);
});
example.control.control_vector_mut().set_at(0, 0, 1.0);
example.filter.predict();
example.filter.control(&mut example.control);
example.filter.state_vector().inspect(|vec| {
assert_eq!(
vec.get_at(0, 0),
0.5,
"incorrect position after control input"
);
assert_eq!(
vec.get_at(1, 0),
1.0,
"incorrect velocity after control input"
);
assert_eq!(
vec.get_at(2, 0),
1.0,
"incorrect acceleration after control input"
);
});
example.filter.predict();
example.filter.state_vector().inspect(|vec| {
assert_eq!(vec.get_at(0, 0), 2.0, "incorrect position");
assert_eq!(vec.get_at(1, 0), 2.0, "incorrect velocity");
assert_eq!(vec.get_at(2, 0), 1.0, "incorrect acceleration");
});
example.filter.estimate_covariance().inspect(|mat| {
assert!(mat.get_at(0, 0) > 6.2);
assert!(mat.get_at(1, 1) > 4.2);
assert!(mat.get_at(2, 2) > 1.0);
});
example.measurement.measurement_vector_mut().apply(|vec| {
vec.set_at(0, 0, 2.0);
vec.set_at(1, 0, (2.0 + 2.0 + 1.0) / 3.0);
});
example.filter.correct(&mut example.measurement);
example.filter.estimate_covariance().inspect(|mat| {
assert!(mat.get_at(0, 0) < 1.0);
assert!(mat.get_at(1, 1) < 1.0);
assert!(mat.get_at(2, 2) < 0.4);
});
}