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}