use crate::constants::{J2, TWO_PI, X2O3, XKE};
use crate::propagation::gstime::gstime;
use crate::DpperOpsMode;
pub struct InitOptions {
pub ecco: f64,
pub epoch: f64,
pub inclo: f64,
pub opsmode: DpperOpsMode,
pub no: f64,
}
#[derive(PartialEq, Debug)]
#[allow(dead_code)]
pub enum InitlMethod {
N,
D,
}
#[allow(dead_code)]
pub struct InitlResult {
pub no: f64,
pub method: InitlMethod,
pub ainv: f64,
pub ao: f64,
pub con41: f64,
pub con42: f64,
pub cosio: f64,
pub cosio2: f64,
pub eccsq: f64,
pub omeosq: f64,
pub posq: f64,
pub rp: f64,
pub rteosq: f64,
pub sinio: f64,
pub gsto: f64,
}
pub fn initl(options: InitOptions) -> InitlResult {
let ecco = options.ecco;
let epoch = options.epoch;
let inclo = options.inclo;
let opsmode = options.opsmode;
let mut no = options.no;
let eccsq = ecco * ecco;
let omeosq = 1.0 - eccsq;
let rteosq = (omeosq).sqrt();
let cosio = (inclo).cos();
let cosio2 = cosio * cosio;
let ak = (XKE / no).powf(X2O3);
let d1 = (0.75 * J2 * ((3.0 * cosio2) - 1.0)) / (rteosq * omeosq);
let mut del_prime = d1 / (ak * ak);
let adel = ak
* (1.0
- (del_prime * del_prime)
- (del_prime * ((1.0 / 3.0) + ((134.0 * del_prime * del_prime) / 81.0))));
del_prime = d1 / (adel * adel);
no /= 1.0 + del_prime;
let ao = (XKE / no).powf(X2O3);
let sinio = (inclo).sin();
let po = ao * omeosq;
let con42 = 1.0 - (5.0 * cosio2);
let con41 = -con42 - cosio2 - cosio2;
let ainv = 1.0 / ao;
let posq = po * po;
let rp = ao * (1.0 - ecco);
let method = InitlMethod::N;
let mut gsto;
if opsmode == DpperOpsMode::A {
let ts70 = epoch - 7305.0;
let ds70 = (ts70 + 1.0e-8).floor();
let tfrac = ts70 - ds70;
let c1 = 1.72027916940703639e-2;
let thgr70 = 1.7321343856509374;
let fk5r = 5.07551419432269442e-15;
let c1p2p = c1 + TWO_PI;
gsto = (thgr70 + (c1 * ds70) + (c1p2p * tfrac) + (ts70 * ts70 * fk5r)) % TWO_PI;
if gsto < 0.0 {
gsto += TWO_PI;
}
} else {
gsto = gstime(epoch + 2433281.5);
}
InitlResult {
no,
method,
ainv,
ao,
con41,
con42,
cosio,
cosio2,
eccsq,
omeosq,
posq,
rp,
rteosq,
sinio,
gsto,
}
}
#[cfg(test)]
mod test{
use super::{
initl,
InitOptions,
DpperOpsMode,
InitlMethod
};
fn is_close(actual: f64, ed: f64, epsilon: f64) -> bool {
(actual - ed).abs() < epsilon
}
#[test]
pub fn legacy_sidereal_time_calculations() {
const OPTIONS: InitOptions = InitOptions {
ecco: 0.1846988,
epoch: 25938.538312919904,
inclo: 0.0,
no: 0.0037028783237264057,
opsmode: DpperOpsMode::A,
};
let results = initl(OPTIONS);
let epsilon = 1e-3;
assert!(is_close(results.ainv, 0.1353414893496189, epsilon));
assert!(is_close(results.ao, 7.3887172721793, epsilon));
assert_eq!(results.con41, 2.0);
assert_eq!(results.con42, -4.0);
assert_eq!(results.cosio, 1.0);
assert_eq!(results.cosio2, 1.0);
assert!(is_close(results.eccsq, 0.034113646721439995, epsilon));
assert!(is_close(results.gsto, 5.220883431398299, epsilon));
assert_eq!(results.method, InitlMethod::N);
assert!(is_close(results.no, 0.003702762286531528, epsilon));
assert!(is_close(results.omeosq, 0.96588635327856, epsilon));
assert!(is_close(results.posq, 50.931932818552305, epsilon));
assert!(is_close(results.rp, 6.02403005846851, epsilon));
assert!(is_close(results.rteosq, 0.9827951736137902, epsilon));
assert_eq!(results.sinio, 0.0);
}
}