lox_frames/transformations/
iau.rs1use crate::transformations::rotations::Rotation;
10use glam::{DMat3, DVec3};
11use lox_bodies::RotationalElements;
12use lox_bodies::{TryRotationalElements, UndefinedOriginPropertyError};
13use lox_time::Time;
14use lox_time::time_scales::Tdb;
15use lox_time::time_scales::TryToScale;
16use lox_time::{julian_dates::JulianDate, time_scales::TimeScale};
17use std::f64::consts::{FRAC_PI_2, TAU};
18use thiserror::Error;
19
20use crate::frames::{Iau, Icrf};
21use crate::traits::TryRotateTo;
22
23#[derive(Debug, Error)]
24pub enum IauFrameTransformationError {
25 #[error(transparent)]
26 UndefinedRotationalElements(#[from] UndefinedOriginPropertyError),
27 #[error("TDB transformation error: {0}")]
28 Tdb(String),
29}
30
31pub fn icrf_to_iau<T, O, P>(
32 time: Time<T>,
33 body: O,
34 provider: Option<&P>,
35) -> Result<Rotation, IauFrameTransformationError>
36where
37 T: TimeScale + TryToScale<Tdb, P>,
38 O: TryRotationalElements,
39{
40 let seconds = time
41 .try_to_scale(Tdb, provider)
42 .map_err(|err| IauFrameTransformationError::Tdb(err.to_string()))?
43 .seconds_since_j2000();
44 let (right_ascension, declination, rotation_angle) = body.try_rotational_elements(seconds)?;
45 let (right_ascension_rate, declination_rate, rotation_rate) =
46 body.try_rotational_element_rates(seconds)?;
47
48 let m1 = DMat3::from_rotation_z(-(right_ascension + FRAC_PI_2));
49 let m2 = DMat3::from_rotation_x(-(FRAC_PI_2 - declination));
50 let m3 = DMat3::from_rotation_z(-(rotation_angle % TAU));
51 let m = m3 * m2 * m1;
52 let v = DVec3::new(right_ascension_rate, -declination_rate, rotation_rate);
53 Ok(Rotation::new(m).with_angular_velocity(v))
54}
55
56impl<T, O, P> TryRotateTo<T, Iau<O>, P> for Icrf
57where
58 T: TimeScale + TryToScale<Tdb, P>,
59 O: RotationalElements,
60{
61 type Error = IauFrameTransformationError;
62
63 fn try_rotation(
64 &self,
65 frame: Iau<O>,
66 time: Time<T>,
67 provider: Option<&P>,
68 ) -> Result<Rotation, Self::Error> {
69 icrf_to_iau(time, frame.0, provider)
70 }
71}
72
73impl<T, O, P> TryRotateTo<T, Icrf, P> for Iau<O>
74where
75 T: TimeScale + TryToScale<Tdb, P>,
76 O: RotationalElements + Clone,
77{
78 type Error = IauFrameTransformationError;
79
80 fn try_rotation(
81 &self,
82 _frame: Icrf,
83 time: Time<T>,
84 provider: Option<&P>,
85 ) -> Result<Rotation, Self::Error> {
86 Ok(icrf_to_iau(time, self.0.clone(), provider)?.transpose())
87 }
88}