use crate::dynamics::DynamicsError;
pub use crate::dynamics::{Dynamics, NyxError};
use crate::io::{ConfigError, InputOutputError};
use crate::linalg::allocator::Allocator;
use crate::linalg::{DefaultAllocator, DimName, OMatrix, OVector};
use crate::md::trajectory::TrajError;
use crate::propagators::PropagationError;
use crate::time::Epoch;
use crate::Orbit;
pub use crate::{State, TimeTagged};
use anise::almanac::planetary::PlanetaryDataError;
use anise::errors::AlmanacError;
use hifitime::Duration;
use snafu::prelude::Snafu;
use std::sync::Arc;
pub mod filter;
pub use filter::Filter;
mod ground_station;
pub use ground_station::GroundStation;
pub mod estimate;
pub mod noise;
pub mod msr;
pub mod simulator;
pub mod process;
use arrow::datatypes::Field;
pub use simulator::TrackingDeviceSim;
pub mod snc;
pub type SpacecraftODProcess<'a> = self::process::ODProcess<
'a,
crate::md::prelude::SpacecraftDynamics,
msr::RangeDoppler,
nalgebra::Const<3>,
crate::Spacecraft,
filter::kalman::KF<crate::Spacecraft, nalgebra::Const<3>, nalgebra::Const<2>>,
>;
#[allow(unused_imports)]
pub mod prelude {
pub use super::estimate::*;
pub use super::filter::kalman::*;
pub use super::ground_station::*;
pub use super::msr::*;
pub use super::noise::{GaussMarkov, StochasticNoise, WhiteNoise};
pub use super::process::*;
pub use super::simulator::TrackingArcSim;
pub use super::simulator::*;
pub use super::snc::*;
pub use super::*;
pub use crate::time::{Duration, Epoch, TimeUnits, Unit};
}
pub trait Measurement: Copy + TimeTagged {
type MeasurementSize: DimName;
fn fields() -> Vec<Field>;
fn from_observation(epoch: Epoch, obs: OVector<f64, Self::MeasurementSize>) -> Self
where
DefaultAllocator: Allocator<Self::MeasurementSize>;
fn observation(&self) -> OVector<f64, Self::MeasurementSize>
where
DefaultAllocator: Allocator<Self::MeasurementSize>;
}
pub trait EstimateFrom<O: State, M: Measurement>
where
Self: State,
DefaultAllocator: Allocator<<O as State>::Size>
+ Allocator<<O as State>::VecLength>
+ Allocator<<O as State>::Size, <O as State>::Size>
+ Allocator<Self::Size>
+ Allocator<Self::VecLength>
+ Allocator<Self::Size, Self::Size>,
{
fn extract(from: O) -> Self;
fn sensitivity(
msr: &M,
receiver: Self,
transmitter: Orbit,
) -> OMatrix<f64, M::MeasurementSize, Self::Size>
where
DefaultAllocator: Allocator<M::MeasurementSize, Self::Size>;
}
impl<O> EstimateFrom<O, O> for O
where
O: State + Measurement,
Self: State,
DefaultAllocator: Allocator<<O as State>::Size>
+ Allocator<<O as State>::VecLength>
+ Allocator<<O as State>::Size, <O as State>::Size>
+ Allocator<Self::Size>
+ Allocator<Self::VecLength>
+ Allocator<Self::Size, Self::Size>,
{
fn extract(from: O) -> Self {
from
}
fn sensitivity(
_full_state_msr: &O,
_receiver: Self,
_transmitter: Orbit,
) -> OMatrix<f64, <O as Measurement>::MeasurementSize, Self::Size>
where
DefaultAllocator: Allocator<<O as Measurement>::MeasurementSize, Self::Size>,
{
OMatrix::<f64, O::MeasurementSize, Self::Size>::identity()
}
}
#[derive(Debug, PartialEq, Snafu)]
#[snafu(visibility(pub(crate)))]
pub enum ODError {
#[snafu(display("during an orbit determination, encountered {source}"))]
ODPropError { source: PropagationError },
#[snafu(display("during an orbit determination, encountered {source}"))]
ODDynamicsError { source: DynamicsError },
#[snafu(display("at least {need} measurements required for {action}"))]
TooFewMeasurements { need: usize, action: &'static str },
#[snafu(display("invalid step size: {step}"))]
StepSizeError { step: Duration },
#[snafu(display("filter iteration did not converge in {loops} iterations"))]
Diverged { loops: usize },
#[snafu(display("STM is singular"))]
SingularStateTransitionMatrix,
#[snafu(display("invalid measurement @ {epoch} = {val}"))]
InvalidMeasurement { epoch: Epoch, val: f64 },
#[snafu(display("sensitivity matrix must be updated before this call"))]
SensitivityNotUpdated,
#[snafu(display("Kalman gain is singular"))]
SingularKalmanGain,
#[snafu(display("Noise matrix is singular"))]
SingularNoiseRk,
#[snafu(display("{kind} noise not configured"))]
NoiseNotConfigured { kind: &'static str },
#[snafu(display("during an OD encountered {source}"))]
ODTrajError { source: TrajError },
#[snafu(display("OD failed because {source}"))]
ODConfigError { source: ConfigError },
#[snafu(display("OD failed because of an I/O error: {source}"))]
ODIOError { source: InputOutputError },
#[snafu(display("OD failed due to Almanac: {action} {source}"))]
ODAlmanac {
#[snafu(source(from(AlmanacError, Box::new)))]
source: Box<AlmanacError>,
action: &'static str,
},
#[snafu(display("OD failed due to planetary data in Almanac: {action} {source}"))]
ODPlanetaryData {
#[snafu(source(from(PlanetaryDataError, Box::new)))]
source: Box<PlanetaryDataError>,
action: &'static str,
},
#[snafu(display("not enough residuals to {action}"))]
ODNoResiduals { action: &'static str },
}