use super::State;
use crate::Spacecraft;
use crate::cosmic::Orbit;
use crate::linalg::allocator::Allocator;
use crate::linalg::{DefaultAllocator, OMatrix, OVector};
use hifitime::Epoch;
use std::cmp::PartialEq;
use std::fmt;
pub mod residual;
pub use residual::Residual;
pub mod kfestimate;
pub use kfestimate::KfEstimate;
mod sc_uncertainty;
pub use sc_uncertainty::SpacecraftUncertainty;
pub trait Estimate<T: State>
where
Self: Clone + PartialEq + Sized + fmt::Display,
DefaultAllocator: Allocator<<T as State>::Size>
+ Allocator<<T as State>::Size, <T as State>::Size>
+ Allocator<<T as State>::VecLength>,
{
fn zeros(state: T) -> Self;
fn epoch(&self) -> Epoch {
self.state().epoch()
}
fn set_epoch(&mut self, dt: Epoch) {
self.state().set_epoch(dt);
}
fn state(&self) -> T {
self.nominal_state().add(self.state_deviation())
}
fn state_deviation(&self) -> OVector<f64, <T as State>::Size>;
fn nominal_state(&self) -> T;
fn covar(&self) -> OMatrix<f64, <T as State>::Size, <T as State>::Size>;
fn predicted_covar(&self) -> OMatrix<f64, <T as State>::Size, <T as State>::Size>;
fn set_state_deviation(&mut self, new_state: OVector<f64, <T as State>::Size>);
fn set_covar(&mut self, new_covar: OMatrix<f64, <T as State>::Size, <T as State>::Size>);
fn predicted(&self) -> bool;
fn stm(&self) -> &OMatrix<f64, <T as State>::Size, <T as State>::Size>;
fn within_sigma(&self, sigma: f64) -> bool {
let state = self.state_deviation();
let covar = self.covar();
for i in 0..state.len() {
let bound = covar[(i, i)].sqrt() * sigma;
if state[i] > bound || state[i] < -bound {
return false;
}
}
true
}
fn within_3sigma(&self) -> bool {
self.within_sigma(3.0)
}
}
pub trait NavSolution<T>: Estimate<Spacecraft>
where
T: State,
DefaultAllocator: Allocator<<T as State>::Size>
+ Allocator<<T as State>::Size, <T as State>::Size>
+ Allocator<<T as State>::VecLength>,
{
fn orbital_state(&self) -> Orbit;
fn expected_state(&self) -> Orbit;
}
impl NavSolution<Spacecraft> for KfEstimate<Spacecraft> {
fn orbital_state(&self) -> Orbit {
self.state().orbit
}
fn expected_state(&self) -> Orbit {
self.nominal_state().orbit
}
}