lox_earth/
itrf.rs

1// SPDX-FileCopyrightText: 2025 Helge Eichhorn <git@helgeeichhorn.de>
2//
3// SPDX-License-Identifier: MPL-2.0
4
5use crate::cio::s06::cio_locator;
6use crate::cip::xy06::CipCoords;
7use crate::coordinate_transformations::{
8    PoleCoords, celestial_to_intermediate_frame_of_date_matrix, polar_motion_matrix,
9};
10use crate::eop::{EopProvider, EopProviderError};
11use crate::rotation_angle::earth_rotation_angle_00;
12use crate::tio::tio_locator;
13use glam::{DMat3, DVec3};
14use lox_bodies::{Earth, RotationalElements};
15use lox_core::f64::consts::SECONDS_PER_DAY;
16use lox_frames::dynamic::DynTransformError;
17use lox_frames::transformations::TryTransform;
18use lox_frames::transformations::rotations::Rotation;
19use lox_frames::{Cirf, DynFrame, Icrf, transform_provider};
20use lox_time::Time;
21use lox_time::julian_dates::JulianDate;
22use lox_time::offsets::TryOffset;
23use lox_time::time_scales::{DynTimeScale, Tdb, TimeScale};
24use thiserror::Error;
25
26transform_provider!(EopProvider);
27
28pub fn icrf_to_cirf(centuries: f64) -> Rotation {
29    // TODO: Add IERS corrections
30    let xy = CipCoords::new(centuries);
31    let s = cio_locator(centuries, xy);
32    let m = celestial_to_intermediate_frame_of_date_matrix(xy, s);
33    Rotation::new(m)
34}
35
36impl<T> TryTransform<Icrf, Cirf, T> for EopProvider
37where
38    T: TimeScale + Copy,
39    Self: TryOffset<T, Tdb, Error = EopProviderError>,
40{
41    type Error = EopProviderError;
42
43    fn try_transform(
44        &self,
45        _origin: Icrf,
46        _target: Cirf,
47        time: Time<T>,
48    ) -> Result<Rotation, Self::Error> {
49        let _centuries_tdb = time.try_to_scale(Tdb, self)?.centuries_since_j2000();
50        todo!()
51    }
52}
53
54pub fn cirf_to_tirf(seconds: f64) -> Rotation {
55    let era = earth_rotation_angle_00(seconds / SECONDS_PER_DAY);
56    let rate = Earth.rotation_rate(seconds);
57    let m = DMat3::from_rotation_z(-era.to_radians());
58    let v = DVec3::new(0.0, 0.0, rate);
59    Rotation::new(m).with_angular_velocity(v)
60}
61
62pub fn tirf_to_itrf(centuries: f64) -> Rotation {
63    // TODO: Add IERS corrections
64    let pole_coords = PoleCoords::default();
65    let sp = tio_locator(centuries);
66    let m = polar_motion_matrix(pole_coords, sp);
67    Rotation::new(m)
68}
69
70#[derive(Debug, Error)]
71pub enum DynTransformEopError {
72    #[error(transparent)]
73    DynTransform(#[from] DynTransformError),
74    #[error(transparent)]
75    Eop(#[from] EopProviderError),
76}
77
78impl TryTransform<DynFrame, DynFrame, DynTimeScale> for EopProvider {
79    type Error = DynTransformEopError;
80
81    fn try_transform(
82        &self,
83        _origin: DynFrame,
84        _target: DynFrame,
85        _time: Time<DynTimeScale>,
86    ) -> Result<Rotation, Self::Error> {
87        todo!()
88    }
89}