nyx_space/od/process/
conf.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 crate::time::{Duration, Epoch};
20use crate::NyxError;
21use std::convert::TryFrom;
22use std::default::Default;
23use std::fmt;
24use typed_builder::TypedBuilder;
25
26/// Defines the stopping condition for the smoother
27#[derive(Clone, Copy, Debug)]
28pub enum SmoothingArc {
29    /// Stop smoothing when the gap between estimate is the provided floating point number in seconds
30    TimeGap(Duration),
31    /// Stop smoothing at the provided Epoch.
32    Epoch(Epoch),
33    /// Stop smoothing at the first prediction
34    Prediction,
35    /// Only stop once all estimates have been processed
36    All,
37}
38
39impl fmt::Display for SmoothingArc {
40    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41        match *self {
42            SmoothingArc::All => write!(f, "all estimates"),
43            SmoothingArc::Epoch(e) => write!(f, "{e}"),
44            SmoothingArc::TimeGap(g) => write!(f, "time gap of {g}"),
45            SmoothingArc::Prediction => write!(f, "first prediction"),
46        }
47    }
48}
49
50impl Default for SmoothingArc {
51    fn default() -> Self {
52        Self::All
53    }
54}
55
56/// Defines a filter iteration configuration. Allows iterating on an OD solution until convergence criteria is met.
57/// The root mean squared of the prefit residuals ratios is used to assess convergence between iterations.
58#[derive(Clone, Copy, Debug, TypedBuilder)]
59
60pub struct IterationConf {
61    /// The number of measurements to account for in the iteration
62    #[builder(default)]
63    pub smoother: SmoothingArc,
64    /// The absolute tolerance of the RMS prefit residual ratios
65    #[builder(default = 1e-1)]
66    pub absolute_tol: f64,
67    /// The relative tolerance between the latest RMS prefit residual ratios and the best RMS prefit residual ratios so far
68    #[builder(default = 1e-2)]
69    pub relative_tol: f64,
70    /// The maximum number of iterations to allow (will raise an error if the filter has not converged after this many iterations)
71    #[builder(default = 15)]
72    pub max_iterations: usize,
73    /// The maximum number of subsequent divergences in RMS.
74    #[builder(default = 3)]
75    pub max_divergences: usize,
76    /// Set to true to force an ODP failure when the convergence criteria is not met
77    #[builder(default = false)]
78    pub force_failure: bool,
79}
80
81impl IterationConf {
82    /// Iterate and smooth only once
83    pub fn once() -> Self {
84        Self {
85            max_iterations: 1,
86            ..Default::default()
87        }
88    }
89}
90
91impl Default for IterationConf {
92    /// The default absolute tolerance is 1e-2 (calibrated on an EKF with error).
93    fn default() -> Self {
94        Self {
95            smoother: SmoothingArc::All,
96            absolute_tol: 1e-1,
97            relative_tol: 1e-2,
98            max_iterations: 15,
99            max_divergences: 3,
100            force_failure: false,
101        }
102    }
103}
104
105impl fmt::Display for IterationConf {
106    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107        write!(f, "Iterate until abs = {:.2e}, or rel = {:.2e}, or {} iterations, or {} subsequent divergences with smoothing condition of {}",
108            self.absolute_tol,
109            self.relative_tol,
110            self.max_iterations,
111            self.max_divergences,
112            self.smoother)
113    }
114}
115
116impl TryFrom<SmoothingArc> for IterationConf {
117    type Error = NyxError;
118
119    /// Converts a smoother into an interation configuration to iterate just once without failing
120    fn try_from(smoother: SmoothingArc) -> Result<Self, Self::Error> {
121        Ok(Self {
122            smoother,
123            force_failure: false,
124            ..Default::default()
125        })
126    }
127}