use nalgebra::{DMatrix, DVector, SMatrix, Vector6};
use crate::constants::AngleFormat;
use crate::orbits::state_koe_osc_to_mean;
use crate::time::Epoch;
use crate::utils::errors::BraheError;
use crate::utils::identifiable::Identifiable;
pub trait SStateProvider {
fn state(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn states(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs.iter().map(|&epoch| self.state(epoch)).collect()
}
}
pub trait DStateProvider {
fn state(&self, epoch: Epoch) -> Result<DVector<f64>, BraheError>;
fn state_dim(&self) -> usize;
fn states(&self, epochs: &[Epoch]) -> Result<Vec<DVector<f64>>, BraheError> {
epochs.iter().map(|&epoch| self.state(epoch)).collect()
}
}
pub trait SCovarianceProvider {
fn covariance(&self, epoch: Epoch) -> Result<SMatrix<f64, 6, 6>, BraheError>;
}
pub trait DCovarianceProvider {
fn covariance(&self, epoch: Epoch) -> Result<DMatrix<f64>, BraheError>;
fn covariance_dim(&self) -> usize;
}
pub trait SOrbitStateProvider: SStateProvider {
fn state_eci(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn state_ecef(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn state_gcrf(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn state_itrf(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn state_eme2000(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn state_koe_osc(
&self,
epoch: Epoch,
angle_format: AngleFormat,
) -> Result<Vector6<f64>, BraheError>;
fn state_koe_mean(
&self,
epoch: Epoch,
angle_format: AngleFormat,
) -> Result<Vector6<f64>, BraheError> {
let osc = self.state_koe_osc(epoch, angle_format)?;
Ok(state_koe_osc_to_mean(&osc, angle_format))
}
fn states_eci(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs.iter().map(|&epoch| self.state_eci(epoch)).collect()
}
fn states_ecef(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs.iter().map(|&epoch| self.state_ecef(epoch)).collect()
}
fn states_gcrf(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs.iter().map(|&epoch| self.state_gcrf(epoch)).collect()
}
fn states_itrf(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs.iter().map(|&epoch| self.state_itrf(epoch)).collect()
}
fn states_eme2000(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs
.iter()
.map(|&epoch| self.state_eme2000(epoch))
.collect()
}
fn states_koe_osc(
&self,
epochs: &[Epoch],
angle_format: AngleFormat,
) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs
.iter()
.map(|&epoch| self.state_koe_osc(epoch, angle_format))
.collect()
}
fn states_koe_mean(
&self,
epochs: &[Epoch],
angle_format: AngleFormat,
) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs
.iter()
.map(|&epoch| self.state_koe_mean(epoch, angle_format))
.collect()
}
}
pub trait DOrbitStateProvider: DStateProvider {
fn state_eci(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn state_ecef(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn state_gcrf(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn state_itrf(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn state_eme2000(&self, epoch: Epoch) -> Result<Vector6<f64>, BraheError>;
fn state_koe_osc(
&self,
epoch: Epoch,
angle_format: AngleFormat,
) -> Result<Vector6<f64>, BraheError>;
fn state_koe_mean(
&self,
epoch: Epoch,
angle_format: AngleFormat,
) -> Result<Vector6<f64>, BraheError> {
let osc = self.state_koe_osc(epoch, angle_format)?;
Ok(state_koe_osc_to_mean(&osc, angle_format))
}
fn states_eci(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs.iter().map(|&epoch| self.state_eci(epoch)).collect()
}
fn states_ecef(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs.iter().map(|&epoch| self.state_ecef(epoch)).collect()
}
fn states_gcrf(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs.iter().map(|&epoch| self.state_gcrf(epoch)).collect()
}
fn states_itrf(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs.iter().map(|&epoch| self.state_itrf(epoch)).collect()
}
fn states_eme2000(&self, epochs: &[Epoch]) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs
.iter()
.map(|&epoch| self.state_eme2000(epoch))
.collect()
}
fn states_koe_osc(
&self,
epochs: &[Epoch],
angle_format: AngleFormat,
) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs
.iter()
.map(|&epoch| self.state_koe_osc(epoch, angle_format))
.collect()
}
fn states_koe_mean(
&self,
epochs: &[Epoch],
angle_format: AngleFormat,
) -> Result<Vec<Vector6<f64>>, BraheError> {
epochs
.iter()
.map(|&epoch| self.state_koe_mean(epoch, angle_format))
.collect()
}
}
pub trait SOrbitCovarianceProvider: SCovarianceProvider {
fn covariance_eci(&self, epoch: Epoch) -> Result<SMatrix<f64, 6, 6>, BraheError>;
fn covariance_gcrf(&self, epoch: Epoch) -> Result<SMatrix<f64, 6, 6>, BraheError>;
fn covariance_rtn(&self, epoch: Epoch) -> Result<SMatrix<f64, 6, 6>, BraheError>;
}
pub trait DOrbitCovarianceProvider: DCovarianceProvider {
fn covariance_eci(&self, epoch: Epoch) -> Result<DMatrix<f64>, BraheError>;
fn covariance_gcrf(&self, epoch: Epoch) -> Result<DMatrix<f64>, BraheError>;
fn covariance_rtn(&self, epoch: Epoch) -> Result<DMatrix<f64>, BraheError>;
}
pub trait SIdentifiableStateProvider: SOrbitStateProvider + Identifiable {}
impl<T: SOrbitStateProvider + Identifiable> SIdentifiableStateProvider for T {}
pub trait DIdentifiableStateProvider: DOrbitStateProvider + Identifiable {}
impl<T: DOrbitStateProvider + Identifiable> DIdentifiableStateProvider for T {}
pub trait ToPropagatorRefs<P: DIdentifiableStateProvider> {
fn to_refs(&self) -> Vec<&P>;
}
impl<P: DIdentifiableStateProvider> ToPropagatorRefs<P> for P {
fn to_refs(&self) -> Vec<&P> {
vec![self]
}
}
impl<P: DIdentifiableStateProvider> ToPropagatorRefs<P> for [P] {
fn to_refs(&self) -> Vec<&P> {
self.iter().collect()
}
}
impl<P: DIdentifiableStateProvider> ToPropagatorRefs<P> for Vec<P> {
fn to_refs(&self) -> Vec<&P> {
self.iter().collect()
}
}
impl<P: DIdentifiableStateProvider> ToPropagatorRefs<P> for [&P] {
fn to_refs(&self) -> Vec<&P> {
self.to_vec()
}
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use super::*;
use crate::constants::DEGREES;
use crate::propagators::KeplerianPropagator;
use crate::propagators::traits::SStatePropagator;
use crate::time::{Epoch, TimeSystem};
use crate::traits::{OrbitFrame, OrbitRepresentation};
use nalgebra::Vector6;
const TEST_EPOCH_JD: f64 = 2451545.0;
fn create_test_propagator() -> KeplerianPropagator {
let epoch = Epoch::from_jd(TEST_EPOCH_JD, TimeSystem::UTC);
let elements = Vector6::new(7000e3, 0.01, 45.0, 0.0, 0.0, 0.0);
KeplerianPropagator::new(
epoch,
elements,
OrbitFrame::ECI,
OrbitRepresentation::Keplerian,
Some(DEGREES),
60.0,
)
}
#[test]
fn test_to_propagator_refs_single_propagator() {
let prop = create_test_propagator();
let refs = prop.to_refs();
assert_eq!(refs.len(), 1);
assert_eq!(refs[0].initial_epoch(), prop.initial_epoch());
}
#[test]
fn test_to_propagator_refs_slice_of_propagators() {
let props = [
create_test_propagator(),
create_test_propagator(),
create_test_propagator(),
];
let slice: &[KeplerianPropagator] = &props;
let refs = slice.to_refs();
assert_eq!(refs.len(), 3);
for (i, prop_ref) in refs.iter().enumerate() {
assert_eq!(prop_ref.initial_epoch(), props[i].initial_epoch());
}
}
#[test]
fn test_to_propagator_refs_vec_of_propagators() {
let props = vec![create_test_propagator(), create_test_propagator()];
let refs = props.to_refs();
assert_eq!(refs.len(), 2);
for (i, prop_ref) in refs.iter().enumerate() {
assert_eq!(prop_ref.initial_epoch(), props[i].initial_epoch());
}
}
#[test]
fn test_to_propagator_refs_slice_of_refs() {
let props = [
create_test_propagator(),
create_test_propagator(),
create_test_propagator(),
create_test_propagator(),
];
let prop_refs: Vec<&KeplerianPropagator> = props.iter().collect();
let slice_of_refs: &[&KeplerianPropagator] = &prop_refs;
let refs = slice_of_refs.to_refs();
assert_eq!(refs.len(), 4);
for (i, prop_ref) in refs.iter().enumerate() {
assert_eq!(prop_ref.initial_epoch(), props[i].initial_epoch());
}
}
#[test]
fn test_to_propagator_refs_empty_vec() {
let props: Vec<KeplerianPropagator> = vec![];
let refs = props.to_refs();
assert_eq!(refs.len(), 0);
}
#[test]
fn test_to_propagator_refs_empty_slice() {
let props: Vec<KeplerianPropagator> = vec![];
let slice: &[KeplerianPropagator] = &props;
let refs = slice.to_refs();
assert_eq!(refs.len(), 0);
}
}