1use crate::dynamics::DynamicsError;
20pub use crate::dynamics::{Dynamics, NyxError};
21use crate::errors::StateError;
22use crate::io::{ConfigError, InputOutputError};
23use crate::linalg::OVector;
24use crate::md::prelude::SpacecraftDynamics;
25use crate::md::trajectory::TrajError;
26use crate::propagators::PropagationError;
27use crate::time::Epoch;
28pub use crate::{State, TimeTagged};
29use anise::almanac::planetary::PlanetaryDataError;
30use anise::errors::AlmanacError;
31use hifitime::Duration;
32use snafu::prelude::Snafu;
33use std::sync::Arc;
34
35pub mod kalman;
36
37mod ground_station;
39pub use ground_station::GroundStation;
40
41pub mod estimate;
43
44pub mod noise;
46
47pub mod msr;
49
50pub mod simulator;
52
53pub mod process;
55
56pub use simulator::TrackingDevice;
57
58pub mod snc;
60
61pub mod blse;
63
64#[cfg(feature = "premium")]
66pub mod interlink;
67
68#[cfg(feature = "premium")]
70pub mod groundpnt;
71
72#[cfg(feature = "premium")]
74pub mod position;
75
76pub type SpacecraftKalmanOD = self::process::KalmanODProcess<
78 SpacecraftDynamics,
79 nalgebra::Const<2>,
80 nalgebra::Const<3>,
81 GroundStation,
82>;
83
84pub type SpacecraftKalmanScalarOD = self::process::KalmanODProcess<
86 SpacecraftDynamics,
87 nalgebra::Const<1>,
88 nalgebra::Const<3>,
89 GroundStation,
90>;
91
92#[cfg(feature = "premium")]
94pub type InterlinkKalmanOD = self::process::KalmanODProcess<
95 SpacecraftDynamics,
96 nalgebra::Const<2>,
97 nalgebra::Const<3>,
98 interlink::InterlinkTxSpacecraft,
99>;
100
101#[allow(unused_imports)]
102pub mod prelude {
103 pub use super::estimate::*;
104 pub use super::ground_station::*;
105 pub use super::kalman::KalmanVariant;
106 pub use super::kalman::*;
107 pub use super::msr::*;
108 pub use super::noise::{GaussMarkov, StochasticNoise, WhiteNoise};
109 pub use super::process::*;
110 pub use super::simulator::TrackingArcSim;
111 pub use super::simulator::*;
112 pub use super::snc::*;
113 pub use super::*;
114 pub use crate::od::process::NormalizedConsistency;
115
116 pub use crate::time::{Duration, Epoch, TimeUnits, Unit};
117}
118
119#[derive(Debug, PartialEq, Snafu)]
120#[snafu(visibility(pub(crate)))]
121pub enum ODError {
122 #[snafu(display("during an orbit determination, encountered {source}"))]
123 ODPropError {
124 #[snafu(source(from(PropagationError, Box::new)))]
125 source: Box<PropagationError>,
126 },
127 #[snafu(display("during an orbit determination, encountered {source}"))]
128 ODDynamicsError {
129 #[snafu(source(from(DynamicsError, Box::new)))]
130 source: Box<DynamicsError>,
131 },
132 #[snafu(display("at least {need} measurements required for {action}"))]
133 TooFewMeasurements { need: usize, action: &'static str },
134 #[snafu(display("invalid step size: {step}"))]
135 StepSizeError { step: Duration },
136 #[snafu(display("filter iteration did not converge in {loops} iterations"))]
137 Diverged { loops: usize },
138 #[snafu(display("STM is singular"))]
139 SingularStateTransitionMatrix,
140 #[snafu(display("invalid measurement @ {epoch} = {val}"))]
141 InvalidMeasurement { epoch: Epoch, val: f64 },
142 #[snafu(display("Kalman gain is singular"))]
143 SingularKalmanGain,
144 #[snafu(display("Information matrix is singular"))]
145 SingularInformationMatrix,
146 #[snafu(display("noise matrix is singular"))]
147 SingularNoiseRk,
148 #[snafu(display("{kind} noise not configured"))]
149 NoiseNotConfigured { kind: String },
150 #[snafu(display("measurement sim error: {details}"))]
151 MeasurementSimError { details: String },
152 #[snafu(display("during an OD encountered {source}: {details}"))]
153 ODTrajError { source: TrajError, details: String },
154 #[snafu(display("OD failed because {source}"))]
155 ODConfigError { source: ConfigError },
156 #[snafu(display("OD failed because of an I/O error: {source}"))]
157 ODIOError { source: InputOutputError },
158 #[snafu(display("OD failed due to Almanac: {action} {source}"))]
159 ODAlmanac {
160 #[snafu(source(from(AlmanacError, Box::new)))]
161 source: Box<AlmanacError>,
162 action: &'static str,
163 },
164 #[snafu(display("OD failed due to planetary data in Almanac: {action} {source}"))]
165 ODPlanetaryData {
166 #[snafu(source(from(PlanetaryDataError, Box::new)))]
167 source: Box<PlanetaryDataError>,
168 action: &'static str,
169 },
170 #[snafu(display("not enough residuals to {action}"))]
171 ODNoResiduals { action: &'static str },
172 #[snafu(display("could not {action} OD results: {source}"))]
173 ODStateError {
174 #[snafu(source(from(StateError, Box::new)))]
175 source: Box<StateError>,
176 action: &'static str,
177 },
178 #[snafu(display("Maximum iterations ({max_iter}) reached without convergence"))]
179 ODMaxIterations { max_iter: usize },
180 #[snafu(display("Nyx orbit determination limitation: {action}"))]
181 ODLimitation { action: &'static str },
182}