use kfilter::{
measurement::{LinearMeasurement, Measurement},
system::LinearNoInputSystem,
KalmanLinearNoInput, KalmanPredict, KalmanUpdate,
};
use nalgebra::{Matrix1, Matrix1x2, SMatrix, Vector2};
use rand_distr::Distribution;
#[allow(non_snake_case)]
fn main() {
let dt = 0.1;
let F = SMatrix::<f64, 2, 2>::new(1.0, dt, 0.0, 1.0);
let Q = SMatrix::<f64, 2, 2>::identity() * 0.1;
let x_initial = Vector2::new(0.0, 0.0);
let sys = LinearNoInputSystem::new(F, Q, x_initial);
let mut kf = KalmanLinearNoInput::new_custom(sys, SMatrix::zeros());
let mut gps = LinearMeasurement::new(
Matrix1x2::new(1.0, 0.0),
Matrix1::new(0.5),
Matrix1::new(0.0),
);
let mut vel = LinearMeasurement::new(
Matrix1x2::new(0.0, 1.0),
Matrix1::new(0.5),
Matrix1::new(0.0),
);
let mut x_real = x_initial;
let acc = 1.0; let vel_noise = rand_distr::Normal::new(0.0, 0.2).unwrap();
let vel_bias = 0.2;
let gps_noise = rand_distr::Normal::new(0.0, 0.2).unwrap();
let mut rng = rand::thread_rng();
let mut state = Vec::new();
let mut measured = Vec::new();
let mut predicted = Vec::new();
let mut updated = Vec::new();
let n_samples = 100;
for t in 0..n_samples {
x_real.y += (acc - 0.2 * x_real.y) * dt;
x_real.x += x_real.y * dt;
state.push(x_real);
let kf_pred = kf.predict().unwrap();
predicted.push(*kf_pred);
let vel_meas = x_real.y + vel_noise.sample(&mut rng) + vel_bias;
vel.set_measurement(Matrix1::new(vel_meas));
let kf_update = kf.update(&vel).unwrap();
if t % 10 == 0 {
let gps_meas = x_real.x + gps_noise.sample(&mut rng);
gps.set_measurement(Matrix1::new(gps_meas));
let kf_update = kf.update(&gps).unwrap();
updated.push(*kf_update);
measured.push(Vector2::new(gps_meas, vel_meas));
} else {
updated.push(*kf_update);
measured.push(Vector2::new(0.0, vel_meas));
}
}
for i in 0..state.len() {
println!(
"{:.2}, {:.2}, {:.2}, {:.2}, {:.2}, {:.2}, {:.2}, {:.2}",
state[i].x,
state[i].y,
measured[i].x,
measured[i].y,
predicted[i].x,
predicted[i].y,
updated[i].x,
updated[i].y
);
}
}