nyx_space/md/
objective.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 super::StateParameter;
20use crate::{errors::StateError, Spacecraft, State};
21use serde::{Deserialize, Serialize};
22use std::fmt;
23
24/// Defines a state parameter event finder
25#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
26pub struct Objective {
27    /// The state parameter to target
28    pub parameter: StateParameter,
29    /// The desired self.desired_value, must be in the same units as the state parameter
30    pub desired_value: f64,
31    /// The precision on the desired value
32    pub tolerance: f64,
33    /// A multiplicative factor this parameter's error in the targeting (defaults to 1.0)
34    pub multiplicative_factor: f64,
35    /// An additive factor to this parameters's error in the targeting (defaults to 0.0)
36    pub additive_factor: f64,
37}
38
39impl Objective {
40    /// Match a specific value for the parameter.
41    /// By default, the tolerance on the parameter is 0.1 times whatever unit is the default for that parameter.
42    /// For example, a radius event will seek the requested value at the decimeter level, and an angle event will seek it at the tenth of a degree.
43    pub fn new(parameter: StateParameter, desired_value: f64) -> Self {
44        Self::within_tolerance(
45            parameter,
46            desired_value,
47            parameter.default_event_precision(),
48        )
49    }
50
51    /// Match a specific value for the parameter to hit the specified value with the provided tolerance on the value
52    pub fn within_tolerance(parameter: StateParameter, desired_value: f64, tolerance: f64) -> Self {
53        Self {
54            parameter,
55            desired_value,
56            tolerance,
57            multiplicative_factor: 1.0,
58            additive_factor: 0.0,
59        }
60    }
61
62    /// Returns whether this objective has been achieved, and the associated parameter error.
63    pub fn assess(&self, achieved: &Spacecraft) -> Result<(bool, f64), StateError> {
64        Ok(self.assess_value(achieved.value(self.parameter)?))
65    }
66
67    /// Returns whether this objective has been achieved, and the associated parameter error.
68    /// Warning: the parameter `achieved` must be in the same unit as the objective.
69    pub fn assess_value(&self, achieved: f64) -> (bool, f64) {
70        let param_err =
71            self.multiplicative_factor * (self.desired_value - achieved) + self.additive_factor;
72
73        (param_err.abs() <= self.tolerance, param_err)
74    }
75}
76
77impl fmt::Display for Objective {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
79        write!(f, "\t{self:x}")
80    }
81}
82
83impl fmt::LowerHex for Objective {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
85        let max_obj_tol = self.tolerance.log10().abs().ceil() as usize;
86
87        write!(
88            f,
89            "{:?} → {:.prec$} {}",
90            self.parameter,
91            self.desired_value,
92            self.parameter.unit(),
93            prec = max_obj_tol,
94        )?;
95
96        if self.tolerance.abs() < 1e-1 {
97            write!(f, " (± {:.1e})", self.tolerance)
98        } else {
99            write!(f, " (± {:.2})", self.tolerance)
100        }
101    }
102}