use log::{debug, error};
use nalgebra::{Rotation3, Vector3};
use crate::prelude::{Duration, Ephemeris, Epoch, Frame, Orbit};
impl Ephemeris {
pub fn is_valid(&self, now: Epoch, max_dtoe: Duration) -> bool {
(now - self.toe).abs() < max_dtoe
}
pub fn weekly_toe_seconds(&self) -> f64 {
(self.toe.to_time_of_week().1 as f64) / 1.0E9
}
pub fn weekly_toc_seconds(&self) -> f64 {
(self.toc.to_time_of_week().1 as f64) / 1.0E9
}
pub fn resolve_state(&self, epoch: Epoch, frame: Frame) -> Option<Orbit> {
const GM_M3_S2: f64 = 3.986004418E14;
const OMEGA_EARTH: f64 = 7.2921151467E-5;
let e = self.eccentricity;
let e_2 = e.powi(2);
let a = self.semi_major_axis_m;
let a_3 = a.powi(3);
let (cus, cuc) = self.cus_cuc_rad;
let (cis, cic) = self.cis_cic_rad;
let (crs, crc) = self.crs_crc_m;
let (i0, idot) = (self.i0_rad, self.idot_rad_s);
let (omega0, omega, omega_dot) = (self.omega0_rad, self.omega_rad, self.omega_dot_rad_s);
let timescale = self.sv.constellation.timescale()?;
let epoch = epoch.to_time_scale(timescale);
let t_k = (epoch - self.toe).to_seconds();
let n0 = (GM_M3_S2 / a_3).sqrt();
let n = n0 + self.dn_rad;
let m = self.m0_rad + n * t_k;
let mut e_k;
let mut i = 0;
let e_k_lst = 0.0_f64;
loop {
e_k = m + e * e_k_lst.sin();
if (e_k - e_k_lst).abs() < 1E-10 {
break;
}
i += 1;
if i == 10 {
error!("{}({}) - kepler solver in failure", epoch, self.sv);
return None;
}
}
let (sin_e_k, cos_e_k) = e_k.sin_cos();
let v_k = ((1.0 - e_2).sqrt() * sin_e_k).atan2(cos_e_k - e);
let phi = v_k + omega;
let (sin_2phi, cos_2phi) = (2.0 * phi).sin_cos();
let u_k = phi + cuc * cos_2phi + cus * sin_2phi;
let r_k = a * (1.0 - e * cos_e_k) + crc * cos_2phi + crs * sin_2phi;
let i_k = i0 + idot * t_k + cic * cos_2phi + cis * sin_2phi;
let omega_k =
omega0 + (omega_dot - OMEGA_EARTH) * t_k - OMEGA_EARTH * self.weekly_toe_seconds();
let (x, y, z) = (r_k * u_k.cos(), r_k * u_k.sin(), 0.0);
let rot_x3 = Rotation3::from_axis_angle(&Vector3::x_axis(), i_k);
let rot_z3 = Rotation3::from_axis_angle(&Vector3::z_axis(), omega_k);
let rot3 = rot_z3 * rot_x3;
let xyz_vec3 = Vector3::new(x, y, z);
let xyz_ecef = rot3 * xyz_vec3;
let (x_km, y_km, z_km) = (
xyz_ecef[0] / 1000.0,
xyz_ecef[1] / 1000.0,
xyz_ecef[2] / 1000.0,
);
debug!(
"{}({}) - kepler solving x_km={}, y_km={} z_km={} t_k={}",
epoch, self.sv, x_km, y_km, z_km, t_k
);
Some(Orbit::from_position(x_km, y_km, z_km, epoch, frame))
}
}