use nalgebra::{Vector3, matrix};
use crate::constants::AS2RAD;
use crate::math::{SMatrix3, SVector6};
#[allow(non_snake_case)]
pub fn bias_eme2000() -> SMatrix3 {
let dξ = -16.6170e-3 * AS2RAD; let dη = -6.8192e-3 * AS2RAD; let d_alpha = -14.6e-3 * AS2RAD;
matrix![
1.0 - 0.5 * (dξ * dξ + dη * dη), d_alpha, -dξ;
-d_alpha - dξ * dη, 1.0 - 0.5 * (d_alpha * d_alpha + dη * dη), -dη;
dξ + d_alpha * dη, dη + d_alpha * dξ, 1.0 - 0.5 * (dη * dη + dξ * dξ)
]
}
pub fn rotation_gcrf_to_eme2000() -> SMatrix3 {
bias_eme2000()
}
pub fn rotation_eme2000_to_gcrf() -> SMatrix3 {
rotation_gcrf_to_eme2000().transpose()
}
pub fn position_gcrf_to_eme2000(x_gcrf: Vector3<f64>) -> Vector3<f64> {
rotation_gcrf_to_eme2000() * x_gcrf
}
pub fn position_eme2000_to_gcrf(x_eme2000: Vector3<f64>) -> Vector3<f64> {
rotation_eme2000_to_gcrf() * x_eme2000
}
pub fn state_gcrf_to_eme2000(x_gcrf: SVector6) -> SVector6 {
let r = rotation_gcrf_to_eme2000();
let r_gcrf = x_gcrf.fixed_rows::<3>(0);
let v_gcrf = x_gcrf.fixed_rows::<3>(3);
let p: Vector3<f64> = Vector3::from(r * r_gcrf);
let v: Vector3<f64> = Vector3::from(r * v_gcrf);
SVector6::new(p[0], p[1], p[2], v[0], v[1], v[2])
}
pub fn state_eme2000_to_gcrf(x_eme2000: SVector6) -> SVector6 {
let r = rotation_eme2000_to_gcrf();
let r_eme2000 = x_eme2000.fixed_rows::<3>(0);
let v_eme2000 = x_eme2000.fixed_rows::<3>(3);
let p: Vector3<f64> = Vector3::from(r * r_eme2000);
let v: Vector3<f64> = Vector3::from(r * v_eme2000);
SVector6::new(p[0], p[1], p[2], v[0], v[1], v[2])
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use approx::assert_abs_diff_eq;
use nalgebra::Vector3;
use crate::constants::{AS2RAD, DEGREES, R_EARTH};
use crate::coordinates::state_koe_to_eci;
use crate::frames::*;
use crate::math::vector6_from_array;
#[test]
fn test_bias_eme2000() {
let r_eme2000 = bias_eme2000();
let dξ = -16.6170e-3 * AS2RAD; let dη = -6.8192e-3 * AS2RAD; let d_alpha = -14.6e-3 * AS2RAD;
let tol = 1.0e-12;
assert_abs_diff_eq!(
r_eme2000[(0, 0)],
1.0 - 0.5 * (d_alpha.powi(2) + dξ.powi(2)),
epsilon = tol
);
assert_abs_diff_eq!(r_eme2000[(0, 1)], d_alpha, epsilon = tol);
assert_abs_diff_eq!(r_eme2000[(0, 2)], -dξ, epsilon = tol);
assert_abs_diff_eq!(r_eme2000[(1, 0)], -d_alpha - dη * dξ, epsilon = tol);
assert_abs_diff_eq!(
r_eme2000[(1, 1)],
1.0 - 0.5 * (d_alpha.powi(2) + dη.powi(2)),
epsilon = tol
);
assert_abs_diff_eq!(r_eme2000[(1, 2)], -dη, epsilon = tol);
assert_abs_diff_eq!(r_eme2000[(2, 0)], dξ - dη * d_alpha, epsilon = tol);
assert_abs_diff_eq!(r_eme2000[(2, 1)], dη + dξ * d_alpha, epsilon = tol);
assert_abs_diff_eq!(
r_eme2000[(2, 2)],
1.0 - 0.5 * (dη.powi(2) + dξ.powi(2)),
epsilon = tol
);
}
#[test]
fn test_rotation_gcrf_to_eme2000() {
let r_e2g = rotation_gcrf_to_eme2000();
let r_eme2000 = bias_eme2000();
let tol = 1.0e-12;
for i in 0..3 {
for j in 0..3 {
assert_abs_diff_eq!(r_e2g[(i, j)], r_eme2000[(i, j)], epsilon = tol);
}
}
}
#[test]
fn test_rotation_eme2000_to_gcrf() {
let r_g2e = rotation_eme2000_to_gcrf();
let r_e2g = rotation_gcrf_to_eme2000().transpose();
let tol = 1.0e-12;
for i in 0..3 {
for j in 0..3 {
assert_abs_diff_eq!(r_g2e[(i, j)], r_e2g[(i, j)], epsilon = tol);
}
}
}
#[test]
fn test_position_gcrf_to_eme2000() {
let p_gcrf = Vector3::new(R_EARTH + 500e3, 0.0, 0.0);
let p_eme2000 = position_gcrf_to_eme2000(p_gcrf);
let r_e2g = rotation_gcrf_to_eme2000();
let p_eme2000_expected = r_e2g * p_gcrf;
let tol = 1e-10;
assert_abs_diff_eq!(p_eme2000[0], p_eme2000_expected[0], epsilon = tol);
assert_abs_diff_eq!(p_eme2000[1], p_eme2000_expected[1], epsilon = tol);
assert_abs_diff_eq!(p_eme2000[2], p_eme2000_expected[2], epsilon = tol);
}
#[test]
fn test_position_eme2000_to_gcrf() {
let p_eme2000 = Vector3::new(R_EARTH + 500e3, 0.0, 0.0);
let p_gcrf = position_eme2000_to_gcrf(p_eme2000);
let r_g2e = rotation_eme2000_to_gcrf();
let p_gcrf_expected = r_g2e * p_eme2000;
let tol = 1e-10;
assert_abs_diff_eq!(p_gcrf[0], p_gcrf_expected[0], epsilon = tol);
assert_abs_diff_eq!(p_gcrf[1], p_gcrf_expected[1], epsilon = tol);
assert_abs_diff_eq!(p_gcrf[2], p_gcrf_expected[2], epsilon = tol);
}
#[test]
fn test_state_gcrf_to_eme2000() {
let oe = vector6_from_array([R_EARTH + 500e3, 1e-3, 97.8, 75.0, 25.0, 45.0]);
let gcrf = state_koe_to_eci(oe, DEGREES);
let eme2000 = state_gcrf_to_eme2000(gcrf);
let r_e2g = rotation_gcrf_to_eme2000();
let r_gcrf = gcrf.fixed_rows::<3>(0);
let v_gcrf = gcrf.fixed_rows::<3>(3);
let p_expected: Vector3<f64> = Vector3::from(r_e2g * r_gcrf);
let v_expected: Vector3<f64> = Vector3::from(r_e2g * v_gcrf);
let tol = 1e-10;
assert_abs_diff_eq!(eme2000[0], p_expected[0], epsilon = tol);
assert_abs_diff_eq!(eme2000[1], p_expected[1], epsilon = tol);
assert_abs_diff_eq!(eme2000[2], p_expected[2], epsilon = tol);
assert_abs_diff_eq!(eme2000[3], v_expected[0], epsilon = tol);
assert_abs_diff_eq!(eme2000[4], v_expected[1], epsilon = tol);
assert_abs_diff_eq!(eme2000[5], v_expected[2], epsilon = tol);
}
#[test]
fn test_state_eme2000_to_gcrf() {
let oe = vector6_from_array([R_EARTH + 500e3, 1e-3, 97.8, 75.0, 25.0, 45.0]);
let eme2000 = state_koe_to_eci(oe, DEGREES);
let gcrf = state_eme2000_to_gcrf(eme2000);
let r_g2e = rotation_eme2000_to_gcrf();
let r_eme2000 = eme2000.fixed_rows::<3>(0);
let v_eme2000 = eme2000.fixed_rows::<3>(3);
let p_expected: Vector3<f64> = Vector3::from(r_g2e * r_eme2000);
let v_expected: Vector3<f64> = Vector3::from(r_g2e * v_eme2000);
let tol = 1e-10;
assert_abs_diff_eq!(gcrf[0], p_expected[0], epsilon = tol);
assert_abs_diff_eq!(gcrf[1], p_expected[1], epsilon = tol);
assert_abs_diff_eq!(gcrf[2], p_expected[2], epsilon = tol);
assert_abs_diff_eq!(gcrf[3], v_expected[0], epsilon = tol);
assert_abs_diff_eq!(gcrf[4], v_expected[1], epsilon = tol);
assert_abs_diff_eq!(gcrf[5], v_expected[2], epsilon = tol);
}
#[test]
fn test_eme2000_gcrf_roundtrip() {
let oe = vector6_from_array([R_EARTH + 500e3, 1e-3, 97.8, 75.0, 25.0, 45.0]);
let eme2000 = state_koe_to_eci(oe, DEGREES);
let gcrf = state_eme2000_to_gcrf(eme2000);
let eme2000_2 = state_gcrf_to_eme2000(gcrf);
let gcrf_2 = state_eme2000_to_gcrf(eme2000_2);
let tol = 1e-7;
assert_abs_diff_eq!(eme2000_2[0], eme2000[0], epsilon = tol);
assert_abs_diff_eq!(eme2000_2[1], eme2000[1], epsilon = tol);
assert_abs_diff_eq!(eme2000_2[2], eme2000[2], epsilon = tol);
assert_abs_diff_eq!(eme2000_2[3], eme2000[3], epsilon = tol);
assert_abs_diff_eq!(eme2000_2[4], eme2000[4], epsilon = tol);
assert_abs_diff_eq!(eme2000_2[5], eme2000[5], epsilon = tol);
assert_abs_diff_eq!(gcrf_2[0], gcrf[0], epsilon = tol);
assert_abs_diff_eq!(gcrf_2[1], gcrf[1], epsilon = tol);
assert_abs_diff_eq!(gcrf_2[2], gcrf[2], epsilon = tol);
assert_abs_diff_eq!(gcrf_2[3], gcrf[3], epsilon = tol);
assert_abs_diff_eq!(gcrf_2[4], gcrf[4], epsilon = tol);
assert_abs_diff_eq!(gcrf_2[5], gcrf[5], epsilon = tol);
}
}