nyx_space/cosmic/
mod.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 anise::errors::{AlmanacError, PhysicsError};
20pub use anise::prelude::*;
21
22pub use crate::cosmic::{DragData, GuidanceMode, Mass, SRPData, Spacecraft};
23use crate::dynamics::DynamicsError;
24pub use crate::errors::NyxError;
25use crate::errors::StateError;
26use crate::linalg::allocator::Allocator;
27use crate::linalg::{DefaultAllocator, DimName, OMatrix, OVector};
28use crate::md::StateParameter;
29use snafu::Snafu;
30use std::fmt;
31
32/// A trait allowing for something to have an epoch
33pub trait TimeTagged {
34    /// Retrieve the Epoch
35    fn epoch(&self) -> Epoch;
36    /// Set the Epoch
37    fn set_epoch(&mut self, epoch: Epoch);
38}
39
40/// A trait for generate propagation and estimation state.
41/// The first parameter is the size of the state, the second is the size of the propagated state including STM and extra items.
42pub trait State: Default + Copy + PartialEq + fmt::Display + fmt::LowerExp + Send + Sync
43where
44    Self: Sized,
45    DefaultAllocator:
46        Allocator<Self::Size> + Allocator<Self::Size, Self::Size> + Allocator<Self::VecLength>,
47{
48    /// Size of the state and its STM
49    type Size: DimName;
50    type VecLength: DimName;
51
52    /// Initialize an empty state
53    /// By default, this is not implemented. This function must be implemented when filtering on this state.
54    fn zeros() -> Self {
55        unimplemented!()
56    }
57
58    /// Return this state as a vector for the propagation/estimation
59    fn to_vector(&self) -> OVector<f64, Self::VecLength>;
60
61    /// Return this state as a vector for the propagation/estimation
62    /// By default, this is not implemented. This function must be implemented when filtering on this state.
63    fn stm(&self) -> Result<OMatrix<f64, Self::Size, Self::Size>, DynamicsError> {
64        Err(DynamicsError::StateTransitionMatrixUnset)
65    }
66
67    /// Return this state as a vector for the propagation/estimation
68    /// By default, this is not implemented. This function must be implemented when filtering on this state.
69    fn reset_stm(&mut self) {
70        unimplemented!()
71    }
72
73    /// Unsets the STM for this state
74    fn unset_stm(&mut self);
75
76    /// Set this state
77    fn set(&mut self, epoch: Epoch, vector: &OVector<f64, Self::VecLength>);
78
79    /// Reconstruct a new State from the provided delta time in seconds compared to the current state
80    /// and with the provided vector.
81    fn set_with_delta_seconds(
82        mut self,
83        delta_t_s: f64,
84        vector: &OVector<f64, Self::VecLength>,
85    ) -> Self
86    where
87        DefaultAllocator: Allocator<Self::VecLength>,
88    {
89        self.set(self.epoch() + delta_t_s, vector);
90        self
91    }
92
93    /// Retrieve the Epoch
94    fn epoch(&self) -> Epoch;
95    /// Set the Epoch
96    fn set_epoch(&mut self, epoch: Epoch);
97
98    /// By default, this is not implemented. This function must be implemented when filtering on this state.
99    fn add(self, _other: OVector<f64, Self::Size>) -> Self {
100        unimplemented!()
101    }
102
103    /// Return the value of the parameter, returns an error by default
104    fn value(&self, param: StateParameter) -> Result<f64, StateError> {
105        Err(StateError::Unavailable { param })
106    }
107
108    /// Allows setting the value of the given parameter.
109    /// NOTE: Most parameters where the `value` is available CANNOT be also set for that parameter (it's a much harder problem!)
110    fn set_value(&mut self, param: StateParameter, _val: f64) -> Result<(), StateError> {
111        Err(StateError::Unavailable { param })
112    }
113
114    /// Returns a copy of the orbit
115    fn orbit(&self) -> Orbit;
116
117    /// Modifies this state's orbit
118    fn set_orbit(&mut self, _orbit: Orbit) {}
119}
120
121pub fn assert_orbit_eq_or_abs(left: &Orbit, right: &Orbit, epsilon: f64, msg: &str) {
122    if !left.eq_within(right, epsilon, epsilon) {
123        panic!(
124            r#"assertion failed: {}
125  left: `{:?}`,
126 right: `{:?}`"#,
127            msg, left, right
128        )
129    }
130}
131
132#[derive(Debug, PartialEq, Snafu)]
133#[snafu(visibility(pub(crate)))]
134pub enum AstroError {
135    #[snafu(display("B Plane jacobian invariant must be either VX, VY or VZ"))]
136    BPlaneInvariant,
137    #[snafu(display("operation requires a local frame"))]
138    NotLocalFrame,
139    #[snafu(display("partial derivatives not defined for this parameter"))]
140    PartialsUndefined,
141    #[snafu(display("Orbit is not hyperbolic so there is no hyperbolic anomaly."))]
142    NotHyperbolic,
143    #[snafu(display("physics error occured during astro computation: {source}"))]
144    AstroPhysics { source: PhysicsError },
145    #[snafu(display("ANISE Almanac error occured during astro computation: {source}"))]
146    AstroAlmanac {
147        #[snafu(source(from(AlmanacError, Box::new)))]
148        source: Box<AlmanacError>,
149    },
150}
151
152// Re-Export OrbitDual
153mod orbitdual;
154pub use self::orbitdual::*;
155
156// Re-Export B Plane
157mod bplane;
158pub use self::bplane::*;
159
160// Re-Export spacecraft
161mod spacecraft;
162pub use self::spacecraft::*;
163
164/// The eclipse module allows finding eclipses and (conversely) visibility between a state and another one (e.g. a planet or the Sun).
165pub mod eclipse;
166
167/// Speed of light in meters per second
168pub const SPEED_OF_LIGHT_M_S: f64 = SPEED_OF_LIGHT_KM_S * 1e3;
169pub use anise::constants::SPEED_OF_LIGHT_KM_S;
170
171/// Astronomical unit, in kilometers, according to the [IAU](https://www.iau.org/public/themes/measuring/).
172pub const AU: f64 = 149_597_870.700;
173
174/// From NIST special publication 330, 2008 edition, in meters per second squared
175pub const STD_GRAVITY: f64 = 9.80665;