From f5f7c11a198598a0769988bd5e1f37da660d8631 Mon Sep 17 00:00:00 2001 From: Christopher Rabotin Date: Sat, 13 Jul 2024 16:04:19 -0600 Subject: [PATCH] Impl sim/proc tracker diff in other tests --- src/od/noise/gauss_markov.rs | 5 +- tests/orbit_determination/multi_body.rs | 94 ++++++++++++++++--------- tests/orbit_determination/spacecraft.rs | 86 +++++++++++++++------- 3 files changed, 123 insertions(+), 62 deletions(-) diff --git a/src/od/noise/gauss_markov.rs b/src/od/noise/gauss_markov.rs index bd4c2545..17b79950 100644 --- a/src/od/noise/gauss_markov.rs +++ b/src/od/noise/gauss_markov.rs @@ -150,10 +150,7 @@ impl Stochastics for GaussMarkov { let steady_noise = 0.5 * self.process_noise * self.tau.to_seconds() * anti_decay; let ss_sample = rng.sample(Normal::new(0.0, steady_noise).unwrap()); - let bias = self.init_sample.unwrap() * decay + ss_sample; - - // Return the new bias - bias + self.init_sample.unwrap() * decay + ss_sample } } diff --git a/tests/orbit_determination/multi_body.rs b/tests/orbit_determination/multi_body.rs index c772ad46..5d7b109d 100644 --- a/tests/orbit_determination/multi_body.rs +++ b/tests/orbit_determination/multi_body.rs @@ -25,14 +25,36 @@ fn almanac() -> Arc { test_almanac_arcd() } -#[allow(clippy::identity_op)] -#[rstest] -fn od_val_multi_body_ckf_perfect_stations(almanac: Arc) { - let _ = pretty_env_logger::try_init(); - +#[fixture] +fn sim_devices(almanac: Arc) -> Vec { let iau_earth = almanac.frame_from_uid(IAU_EARTH_FRAME).unwrap(); + let elevation_mask = 0.0; + let dss65_madrid = GroundStation::dss65_madrid( + elevation_mask, + StochasticNoise::ZERO, + StochasticNoise::ZERO, + iau_earth, + ); + let dss34_canberra = GroundStation::dss34_canberra( + elevation_mask, + StochasticNoise::ZERO, + StochasticNoise::ZERO, + iau_earth, + ); + let dss13_goldstone = GroundStation::dss13_goldstone( + elevation_mask, + StochasticNoise::ZERO, + StochasticNoise::ZERO, + iau_earth, + ); - // Define the ground stations. + vec![dss65_madrid, dss34_canberra, dss13_goldstone] +} + +/// Devices for processing the measurement, noise may not be zero. +#[fixture] +fn proc_devices(almanac: Arc) -> Vec { + let iau_earth = almanac.frame_from_uid(IAU_EARTH_FRAME).unwrap(); let elevation_mask = 0.0; let dss65_madrid = GroundStation::dss65_madrid( elevation_mask, @@ -53,22 +75,28 @@ fn od_val_multi_body_ckf_perfect_stations(almanac: Arc) { iau_earth, ); + vec![dss65_madrid, dss34_canberra, dss13_goldstone] +} + +#[allow(clippy::identity_op)] +#[rstest] +fn od_val_multi_body_ckf_perfect_stations( + almanac: Arc, + sim_devices: Vec, + proc_devices: Vec, +) { + let _ = pretty_env_logger::try_init(); + // Define the tracking configurations let mut configs = BTreeMap::new(); - configs.insert( - dss65_madrid.name.clone(), - TrkConfig::from_sample_rate(10.seconds()), - ); - configs.insert( - dss34_canberra.name.clone(), - TrkConfig::from_sample_rate(10.seconds()), - ); - configs.insert( - dss13_goldstone.name.clone(), - TrkConfig::from_sample_rate(10.seconds()), - ); + for device in &sim_devices { + configs.insert( + device.name.clone(), + TrkConfig::from_sample_rate(10.seconds()), + ); + } - let all_stations = vec![dss65_madrid, dss34_canberra, dss13_goldstone]; + let all_stations = sim_devices; // Define the propagator information. let prop_time = 1 * Unit::Day; @@ -88,10 +116,11 @@ fn od_val_multi_body_ckf_perfect_stations(almanac: Arc) { let (final_truth, traj) = prop.for_duration_with_traj(prop_time).unwrap(); // Simulate tracking data - let mut arc_sim = TrackingArcSim::with_seed(all_stations, traj, configs, 0).unwrap(); + let mut arc_sim = TrackingArcSim::with_seed(all_stations, traj, configs.clone(), 0).unwrap(); arc_sim.build_schedule(almanac.clone()).unwrap(); - let arc = arc_sim.generate_measurements(almanac.clone()).unwrap(); + let mut arc = arc_sim.generate_measurements(almanac.clone()).unwrap(); + arc.set_devices(proc_devices, configs).unwrap(); // Now that we have the truth data, let's start an OD with no noise at all and compute the estimates. // We expect the estimated orbit to be perfect since we're using strictly the same dynamics, no noise on @@ -169,19 +198,16 @@ fn od_val_multi_body_ckf_perfect_stations(almanac: Arc) { #[allow(clippy::identity_op)] #[rstest] -fn multi_body_ckf_covar_map(almanac: Arc) { +fn multi_body_ckf_covar_map( + almanac: Arc, + sim_devices: Vec, + proc_devices: Vec, +) { // For this test, we're only enabling one station so we can check that the covariance inflates between visibility passes. let _ = pretty_env_logger::try_init(); - let iau_earth = almanac.frame_from_uid(IAU_EARTH_FRAME).unwrap(); - // Define the ground stations. - let elevation_mask = 0.0; - let dss13_goldstone = GroundStation::dss13_goldstone( - elevation_mask, - StochasticNoise::MIN, - StochasticNoise::MIN, - iau_earth, - ); + let dss13_goldstone = sim_devices[2].clone(); + // Define the tracking configurations let mut configs = BTreeMap::new(); configs.insert( @@ -213,10 +239,12 @@ fn multi_body_ckf_covar_map(almanac: Arc) { let (_, traj) = prop.for_duration_with_traj(prop_time).unwrap(); // Simulate tracking data - let mut arc_sim = TrackingArcSim::with_seed(all_stations, traj, configs, 0).unwrap(); + let mut arc_sim = TrackingArcSim::with_seed(all_stations, traj, configs.clone(), 0).unwrap(); arc_sim.build_schedule(almanac.clone()).unwrap(); - let arc = arc_sim.generate_measurements(almanac.clone()).unwrap(); + let mut arc = arc_sim.generate_measurements(almanac.clone()).unwrap(); + arc.set_devices(vec![proc_devices[2].clone()], configs) + .unwrap(); // Now that we have the truth data, let's start an OD with no noise at all and compute the estimates. // We expect the estimated orbit to be perfect since we're using strictly the same dynamics, no noise on diff --git a/tests/orbit_determination/spacecraft.rs b/tests/orbit_determination/spacecraft.rs index 3cafdf8c..f2121a06 100644 --- a/tests/orbit_determination/spacecraft.rs +++ b/tests/orbit_determination/spacecraft.rs @@ -25,27 +25,36 @@ fn almanac() -> Arc { test_almanac_arcd() } -#[allow(clippy::identity_op)] -#[rstest] -fn od_val_sc_mb_srp_reals_duals_models(almanac: Arc) { - /* - * This tests that the state transition matrix computation is correct when multiple celestial gravities and solar radiation pressure - * are added to the model. - * - * Specifically, the same dynamics are used for both the measurement generation and for the estimation. - * However, only the estimation generation propagates the STM. When STM propagation is enabled, the code will compute - * the dynamics using a hyperdual representation in 9 dimensions: 1 for the reals, 3 for the position partials, - * 3 for the velocity partials, 1 for the Cr partials and 1 for the Cd partials. - * - * Hence, if the filter state estimation is any different from the truth data, then it means that the equations of - * motion computed in hyperdual space differ from the ones computes in the reals. - * - * Thereby, this serves as a validation of the spacecraft dynamics and SRP duals implementation. - **/ - let _ = pretty_env_logger::try_init(); +#[fixture] +fn sim_devices(almanac: Arc) -> Vec { + let iau_earth = almanac.frame_from_uid(IAU_EARTH_FRAME).unwrap(); + let elevation_mask = 0.0; + let dss65_madrid = GroundStation::dss65_madrid( + elevation_mask, + StochasticNoise::ZERO, + StochasticNoise::ZERO, + iau_earth, + ); + let dss34_canberra = GroundStation::dss34_canberra( + elevation_mask, + StochasticNoise::ZERO, + StochasticNoise::ZERO, + iau_earth, + ); + let dss13_goldstone = GroundStation::dss13_goldstone( + elevation_mask, + StochasticNoise::ZERO, + StochasticNoise::ZERO, + iau_earth, + ); + vec![dss65_madrid, dss34_canberra, dss13_goldstone] +} + +/// Devices for processing the measurement, noise may not be zero. +#[fixture] +fn proc_devices(almanac: Arc) -> Vec { let iau_earth = almanac.frame_from_uid(IAU_EARTH_FRAME).unwrap(); - // Define the ground stations. let elevation_mask = 0.0; let dss65_madrid = GroundStation::dss65_madrid( elevation_mask, @@ -66,6 +75,32 @@ fn od_val_sc_mb_srp_reals_duals_models(almanac: Arc) { iau_earth, ); + vec![dss65_madrid, dss34_canberra, dss13_goldstone] +} + +#[allow(clippy::identity_op)] +#[rstest] +fn od_val_sc_mb_srp_reals_duals_models( + almanac: Arc, + sim_devices: Vec, + proc_devices: Vec, +) { + /* + * This tests that the state transition matrix computation is correct when multiple celestial gravities and solar radiation pressure + * are added to the model. + * + * Specifically, the same dynamics are used for both the measurement generation and for the estimation. + * However, only the estimation generation propagates the STM. When STM propagation is enabled, the code will compute + * the dynamics using a hyperdual representation in 9 dimensions: 1 for the reals, 3 for the position partials, + * 3 for the velocity partials, 1 for the Cr partials and 1 for the Cd partials. + * + * Hence, if the filter state estimation is any different from the truth data, then it means that the equations of + * motion computed in hyperdual space differ from the ones computes in the reals. + * + * Thereby, this serves as a validation of the spacecraft dynamics and SRP duals implementation. + **/ + let _ = pretty_env_logger::try_init(); + let epoch = Epoch::from_gregorian_tai_at_midnight(2020, 1, 1); let prop_time = 1 * Unit::Day; @@ -78,11 +113,11 @@ fn od_val_sc_mb_srp_reals_duals_models(almanac: Arc) { }]) .build(); - configs.insert(dss65_madrid.name.clone(), cfg.clone()); - configs.insert(dss34_canberra.name.clone(), cfg.clone()); - configs.insert(dss13_goldstone.name.clone(), cfg); + for device in &sim_devices { + configs.insert(device.name.clone(), cfg.clone()); + } - let all_stations = vec![dss65_madrid, dss34_canberra, dss13_goldstone]; + let all_stations = sim_devices; // Define the propagator information. let step_size = 10.0 * Unit::Second; @@ -142,10 +177,11 @@ fn od_val_sc_mb_srp_reals_duals_models(almanac: Arc) { .unwrap(); // Simulate tracking data - let mut arc_sim = TrackingArcSim::with_seed(all_stations, traj, configs, 0).unwrap(); + let mut arc_sim = TrackingArcSim::with_seed(all_stations, traj, configs.clone(), 0).unwrap(); arc_sim.build_schedule(almanac.clone()).unwrap(); - let arc = arc_sim.generate_measurements(almanac.clone()).unwrap(); + let mut arc = arc_sim.generate_measurements(almanac.clone()).unwrap(); + arc.set_devices(proc_devices, configs).unwrap(); arc.to_parquet_simple(path.with_file_name("sc_msr_arc.parquet")) .unwrap();