pub mod nbody;
pub mod planet_gm;
use nalgebra::Vector3;
use crate::{
constants::ROT_ECLMJ2000_TO_EQUMJ2000, jpl_ephem::naif::naif_ids::NaifIds, EquinoctialElements,
JPLEphem, OutfitError,
};
#[derive(Debug, Clone, Default)]
pub enum PropagatorKind {
#[default]
TwoBody,
NBody(NBodyConfig),
}
impl PropagatorKind {
pub(crate) fn propagate_to_epoch(
&self,
elements: &EquinoctialElements,
obs_time_mjd: f64,
jpl: &JPLEphem,
) -> Result<(Vector3<f64>, Vector3<f64>), OutfitError> {
match self {
PropagatorKind::TwoBody => propagate_twobody(elements, obs_time_mjd),
PropagatorKind::NBody(nbody_config) => {
propagate_nbody(elements, obs_time_mjd, jpl, nbody_config)
}
}
}
}
fn propagate_twobody(
elements: &EquinoctialElements,
obs_time_mjd: f64,
) -> Result<(Vector3<f64>, Vector3<f64>), OutfitError> {
let dt = obs_time_mjd - elements.reference_epoch;
let (pos_ecl, vel_ecl, _) = elements.propagate_twobody(0.0, dt, false)?;
Ok(ecl_state_to_equ(pos_ecl, vel_ecl))
}
fn propagate_nbody(
elements: &EquinoctialElements,
obs_time_mjd: f64,
jpl: &JPLEphem,
config: &NBodyConfig,
) -> Result<(Vector3<f64>, Vector3<f64>), OutfitError> {
let result = elements.propagate_nbody(obs_time_mjd, jpl, config)?;
Ok(ecl_state_to_equ(result.position, result.velocity))
}
#[inline]
fn ecl_state_to_equ(pos_ecl: Vector3<f64>, vel_ecl: Vector3<f64>) -> (Vector3<f64>, Vector3<f64>) {
(
ROT_ECLMJ2000_TO_EQUMJ2000 * pos_ecl,
ROT_ECLMJ2000_TO_EQUMJ2000 * vel_ecl,
)
}
#[derive(Debug, Clone)]
pub struct NBodyConfig {
pub perturbing_bodies: Vec<NaifIds>,
pub abs_tol: f64,
pub rel_tol: f64,
}
impl Default for NBodyConfig {
fn default() -> Self {
use crate::jpl_ephem::naif::naif_ids::solar_system_bary::SolarSystemBary;
Self {
perturbing_bodies: vec![NaifIds::SSB(SolarSystemBary::Sun)],
abs_tol: 1e-12,
rel_tol: 1e-12,
}
}
}