use kshana::naif_kernel::{naif_et_from_utc, PckKernel, SpkKernel};
const DIR: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/fixtures/lunar_vlbi_anise_oracle/kernels/"
);
fn kernels() -> (SpkKernel, PckKernel, PckKernel) {
let p = |f: &str| std::path::PathBuf::from(format!("{DIR}{f}"));
(
SpkKernel::open(&p("de440s_2024-01-01.bsp")).expect("spk"),
PckKernel::open(&p("earth_itrf93_2024-01-01.bpc")).expect("earth pck"),
PckKernel::open(&p("moon_pa_de440_2024-01-01.bpc")).expect("moon pck"),
)
}
fn spice_rows() -> Vec<Vec<f64>> {
std::fs::read_to_string(format!("{DIR}spice_reader_check.csv"))
.expect("spice_reader_check.csv")
.lines()
.filter(|l| !l.starts_with('#') && !l.trim().is_empty())
.map(|l| l.split(',').map(|x| x.parse().expect("number")).collect())
.collect()
}
#[test]
fn reader_matches_spice_on_the_cut_kernels() {
let (spk, earth, moon) = kernels();
let rows = spice_rows();
assert_eq!(rows.len(), 25);
let (mut d_pos, mut d_vel, mut d_rot, mut d_et) = (0.0f64, 0.0f64, 0.0f64, 0.0f64);
for r in &rows {
let hour = r[0];
let (hi, lo) = naif_et_from_utc(2_460_310.5, hour * 3_600.0);
d_et = d_et.max(((hi - r[1]) + lo).abs());
let (eh, el) = (r[1].round(), r[1] - r[1].round());
let m = spk.state(301, 399, eh, el).unwrap();
let e = spk.state(399, 0, eh, el).unwrap();
for k in 0..3 {
d_pos = d_pos.max((m[0][k] - r[2 + k] * 1e3).abs());
d_vel = d_vel.max((m[1][k] - r[5 + k] * 1e3).abs());
d_pos = d_pos.max((e[0][k] - r[8 + k] * 1e3).abs());
d_vel = d_vel.max((e[1][k] - r[11 + k] * 1e3).abs());
}
let (ri, _) = earth.rotation_from_j2000(3000, eh, el).unwrap();
let (rp, _) = moon.rotation_from_j2000(31008, eh, el).unwrap();
for i in 0..3 {
for j in 0..3 {
d_rot = d_rot.max((ri[i][j] - r[14 + 3 * i + j]).abs());
d_rot = d_rot.max((rp[i][j] - r[23 + 3 * i + j]).abs());
}
}
}
eprintln!(
"reader vs SPICE: position {d_pos:.3e} m, velocity {d_vel:.3e} m/s, rotation element \
{d_rot:.3e}, ET {d_et:.3e} s"
);
assert!(d_pos < 1e-4, "position {d_pos}");
assert!(d_vel < 1e-9, "velocity {d_vel}");
assert!(d_rot < 1e-11, "rotation {d_rot}");
assert!(d_et < 1e-7, "ET {d_et}");
}