use nalgebra::{Matrix2, Matrix3, Vector2, Vector3}; use rustc_hash::FxHashMap; use std::error::Error; extern crate robotics; use robotics::data::utias::UtiasDataset; use robotics::localization::particle_filter::ParticleFilterKnownCorrespondences; use robotics::models::measurement::RangeBearingMeasurementModel; use robotics::models::motion::Velocity; use robotics::utils::plot::plot_landmarks; use robotics::utils::state::GaussianState; fn main() -> Result<(), Box> { let dataset = UtiasDataset::new(0)?; let mut landmarks = FxHashMap::default(); for (id, lm) in &dataset.landmarks { landmarks.insert(*id, Vector3::new(lm.x, lm.y, 0.0)); } let measurement_model = RangeBearingMeasurementModel::new(); let noise = 1.0; let noise_w = 30.0; let noise_g = 10.0; let motion_model = Velocity::new([noise, noise, noise_w, noise_w, noise_g, noise_g]); let q = Matrix2::::from_diagonal(&Vector2::new(0.1, 0.2)); //Observation x,y position covariance let r = Matrix3::::from_diagonal(&Vector3::new(0.2, 0.2, 0.2)); let skip = 0; let gt_state = &dataset.groundtruth[skip]; let state = GaussianState { x: Vector3::new(gt_state.x, gt_state.y, gt_state.orientation), cov: Matrix3::::from_diagonal(&Vector3::new(1e-10, 1e-10, 1e-10)), }; let mut particle_filter = ParticleFilterKnownCorrespondences::new( r, q, landmarks, measurement_model, motion_model, state, 300, ); let mut time_past = gt_state.time; let mut states = Vec::new(); let mut states_measurement = Vec::new(); for (measurements, odometry) in (&dataset).into_iter().skip(skip).take(10000) { let (time_now, measurement_update) = if let Some(m) = &measurements { (m.first().unwrap().time, true) } else if let Some(od) = &odometry { (od.time, false) } else { panic!("NOOOOOOOOO") }; let dt = time_now - time_past; time_past = time_now; let measurements = measurements.map(|ms| { ms.iter() .map(|m| (m.subject_nb, Vector2::new(m.range, m.bearing))) .collect::)>>() }); let odometry = odometry.map(|od| Vector2::new(od.forward_velocity, od.angular_velocity)); particle_filter.estimate(odometry, measurements, dt); states.push(particle_filter.gaussian_estimate()); if measurement_update { states_measurement.push(states.last().unwrap().clone()) } } println!("measurement updates = {}", states_measurement.len()); plot_landmarks( &dataset, &states, &states_measurement, time_past, "./img/pf_landmarks.png", "Particle Filter (Monte Carlo) landmarks", )?; Ok(()) }