nyx_space/od/simulator/trackdata.rs
1/*
2 Nyx, blazing fast astrodynamics
3 Copyright (C) 2018-onwards Christopher Rabotin <christopher.rabotin@gmail.com>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17*/
18
19use std::sync::Arc;
20
21use anise::almanac::Almanac;
22use anise::errors::AlmanacResult;
23use hifitime::Epoch;
24use indexmap::IndexSet;
25use nalgebra::{DimName, OMatrix, OVector};
26use rand_pcg::Pcg64Mcg;
27
28use crate::io::ConfigRepr;
29use crate::linalg::allocator::Allocator;
30use crate::linalg::DefaultAllocator;
31use crate::md::prelude::{Frame, Traj};
32use crate::md::trajectory::Interpolatable;
33use crate::od::msr::measurement::Measurement as NewMeasurement;
34use crate::od::msr::MeasurementType;
35use crate::od::ODError;
36use crate::Orbit;
37
38/// Tracking device simulator.
39pub trait TrackingDevice<MsrIn>: ConfigRepr
40where
41 MsrIn: Interpolatable,
42 DefaultAllocator:
43 Allocator<MsrIn::Size> + Allocator<MsrIn::Size, MsrIn::Size> + Allocator<MsrIn::VecLength>,
44{
45 /// Returns the name of this tracking data simulator
46 fn name(&self) -> String;
47
48 /// Returns the _enabled_ measurement types for thie device.
49 fn measurement_types(&self) -> &IndexSet<MeasurementType>;
50
51 /// Performs a measurement of the input trajectory at the provided epoch (with integration times if relevant), and returns a measurement from itself to the input state. Returns None of the object is not visible.
52 /// This trait function takes in a trajectory and epoch so it can properly simulate integration times for the measurements.
53 /// If the random number generator is provided, it shall be used to add noise to the measurement.
54 ///
55 /// # Choice of the random number generator
56 /// The Pcg64Mcg is chosen because it is fast, space efficient, and has a good statistical distribution.
57 ///
58 /// # Errors
59 /// + A specific measurement is requested but the noise on that measurement type is not configured.
60 ///
61 fn measure(
62 &mut self,
63 epoch: Epoch,
64 traj: &Traj<MsrIn>,
65 rng: Option<&mut Pcg64Mcg>,
66 almanac: Arc<Almanac>,
67 ) -> Result<Option<NewMeasurement>, ODError>;
68
69 /// Returns the device location at the given epoch and in the given frame.
70 fn location(&self, epoch: Epoch, frame: Frame, almanac: Arc<Almanac>) -> AlmanacResult<Orbit>;
71
72 // Perform an instantaneous measurement (without integration times, i.e. one-way). Returns None if the object is not visible, else returns the measurement.
73 fn measure_instantaneous(
74 &mut self,
75 rx: MsrIn,
76 rng: Option<&mut Pcg64Mcg>,
77 almanac: Arc<Almanac>,
78 ) -> Result<Option<NewMeasurement>, ODError>;
79
80 // Return the noise statistics of this tracking device for the provided measurement type at the requested epoch.
81 fn measurement_covar(&self, msr_type: MeasurementType, epoch: Epoch) -> Result<f64, ODError>;
82
83 // Return the measurement bias for the provided measurement type at the requested epoch.
84 fn measurement_bias(&self, msr_type: MeasurementType, epoch: Epoch) -> Result<f64, ODError>;
85
86 fn measurement_covar_matrix<M: DimName>(
87 &self,
88 msr_types: &IndexSet<MeasurementType>,
89 epoch: Epoch,
90 ) -> Result<OMatrix<f64, M, M>, ODError>
91 where
92 DefaultAllocator: Allocator<M, M>,
93 {
94 // Rebuild the R matrix of the measurement noise.
95 let mut r_mat = OMatrix::<f64, M, M>::zeros();
96
97 for (i, msr_type) in msr_types.iter().enumerate() {
98 if self.measurement_types().contains(msr_type) {
99 r_mat[(i, i)] = self.measurement_covar(*msr_type, epoch)?;
100 }
101 }
102
103 Ok(r_mat)
104 }
105
106 fn measurement_bias_vector<M: DimName>(
107 &self,
108 msr_types: &IndexSet<MeasurementType>,
109 epoch: Epoch,
110 ) -> Result<OVector<f64, M>, ODError>
111 where
112 DefaultAllocator: Allocator<M>,
113 {
114 // Rebuild the R matrix of the measurement noise.
115 let mut b_vec = OVector::<f64, M>::zeros();
116
117 for (i, msr_type) in msr_types.iter().enumerate() {
118 if self.measurement_types().contains(msr_type) {
119 b_vec[i] = self.measurement_bias(*msr_type, epoch)?;
120 }
121 }
122
123 Ok(b_vec)
124 }
125}