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}