1use anise::analysis::AnalysisError;
20use anise::errors::{AlmanacError, PhysicsError};
21pub use anise::prelude::*;
22
23pub use crate::cosmic::{DragData, GuidanceMode, Mass, SRPData, Spacecraft};
24use crate::dynamics::DynamicsError;
25pub use crate::errors::NyxError;
26use crate::errors::StateError;
27use crate::linalg::allocator::Allocator;
28use crate::linalg::{DefaultAllocator, DimName, OMatrix, OVector};
29use crate::md::StateParameter;
30use snafu::Snafu;
31use std::fmt;
32
33#[cfg(feature = "python")]
34mod nyx_python;
35
36pub trait TimeTagged {
38 fn epoch(&self) -> Epoch;
40 fn set_epoch(&mut self, epoch: Epoch);
42}
43
44pub trait State: Default + Copy + PartialEq + fmt::Display + fmt::LowerExp + Send + Sync
47where
48 Self: Sized,
49 DefaultAllocator:
50 Allocator<Self::Size> + Allocator<Self::Size, Self::Size> + Allocator<Self::VecLength>,
51{
52 type Size: DimName;
54 type VecLength: DimName;
55
56 fn zeros() -> Self {
59 unimplemented!()
60 }
61
62 fn to_vector(&self) -> OVector<f64, Self::VecLength>;
64
65 fn to_state_vector(&self) -> OVector<f64, Self::Size> {
67 OVector::<f64, Self::Size>::from_iterator(
68 self.to_vector().iter().copied().take(Self::Size::DIM),
69 )
70 }
71
72 fn stm(&self) -> Result<OMatrix<f64, Self::Size, Self::Size>, DynamicsError> {
75 Err(DynamicsError::StateTransitionMatrixUnset)
76 }
77
78 fn with_stm(self) -> Self;
80
81 fn reset_stm(&mut self) {
83 unimplemented!()
84 }
85
86 fn unset_stm(&mut self);
88
89 fn set(&mut self, epoch: Epoch, vector: &OVector<f64, Self::VecLength>);
91
92 fn set_with_delta_seconds(
95 mut self,
96 delta_t_s: f64,
97 vector: &OVector<f64, Self::VecLength>,
98 ) -> Self
99 where
100 DefaultAllocator: Allocator<Self::VecLength>,
101 {
102 self.set(self.epoch() + delta_t_s, vector);
103 self
104 }
105
106 fn epoch(&self) -> Epoch;
108
109 fn set_epoch(&mut self, epoch: Epoch);
111
112 fn add(self, _other: OVector<f64, Self::Size>) -> Self {
114 unimplemented!()
115 }
116
117 fn value(&self, param: StateParameter) -> Result<f64, StateError> {
119 Err(StateError::Unavailable { param })
120 }
121
122 fn set_value(&mut self, param: StateParameter, _val: f64) -> Result<(), StateError> {
125 Err(StateError::Unavailable { param })
126 }
127
128 fn orbit(&self) -> Orbit;
130
131 fn set_orbit(&mut self, _orbit: Orbit) {}
133}
134
135pub fn assert_orbit_eq_or_abs(left: &Orbit, right: &Orbit, epsilon: f64, msg: &str) {
136 if !left.eq_within(right, epsilon, epsilon) {
137 panic!(
138 r#"assertion failed: {msg}
139 left: `{left:?}`,
140 right: `{right:?}`"#
141 )
142 }
143}
144
145#[derive(Debug, PartialEq, Snafu)]
146#[snafu(visibility(pub(crate)))]
147pub enum AstroError {
148 #[snafu(display("B Plane jacobian invariant must be either VX, VY or VZ"))]
149 BPlaneInvariant,
150 #[snafu(display("operation requires a local frame"))]
151 NotLocalFrame,
152 #[snafu(display("partial derivatives not defined for this parameter"))]
153 PartialsUndefined,
154 #[snafu(display("Orbit is not hyperbolic so there is no hyperbolic anomaly."))]
155 NotHyperbolic,
156 #[snafu(display("physics error occured during astro computation: {source}"))]
157 AstroPhysics { source: PhysicsError },
158 #[snafu(display("analysis error occured during astro computation: {source}"))]
159 AstroAnalysis { source: AnalysisError },
160 #[snafu(display("ANISE Almanac error occured during astro computation: {source}"))]
161 AstroAlmanac {
162 #[snafu(source(from(AlmanacError, Box::new)))]
163 source: Box<AlmanacError>,
164 },
165}
166
167mod bplane;
169pub use self::bplane::*;
170
171mod spacecraft;
173pub use self::spacecraft::*;
174
175pub mod eclipse;
177
178pub const SPEED_OF_LIGHT_M_S: f64 = SPEED_OF_LIGHT_KM_S * 1e3;
180pub use anise::constants::SPEED_OF_LIGHT_KM_S;
181
182pub const AU: f64 = 149_597_870.700;
184
185pub const STD_GRAVITY: f64 = 9.80665;