diff --git a/crates/physics/apsis-frames/src/earth_rotation.rs b/crates/physics/apsis-frames/src/earth_rotation.rs index 262c11e..31eec1b 100644 --- a/crates/physics/apsis-frames/src/earth_rotation.rs +++ b/crates/physics/apsis-frames/src/earth_rotation.rs @@ -1,7 +1,6 @@ //! The Earth Rotation Angle and the rotation it defines between the //! inertial and Earth-fixed frames. -use crate::frame::{Ecef, Eci}; use apsis_math::Mat3; use core::f64::consts::PI; @@ -125,19 +124,3 @@ pub fn rotation_eci_to_ecef(angle: EarthRotationAngle) -> Mat3 { pub fn rotation_ecef_to_eci(angle: EarthRotationAngle) -> Mat3 { rotation_eci_to_ecef(angle).transpose() } - -impl Eci { - /// Converts this inertial vector to the Earth-fixed frame at the given - /// Earth Rotation Angle. - pub fn to_ecef(self, angle: EarthRotationAngle) -> Ecef { - Ecef::new(rotation_eci_to_ecef(angle) * self.0) - } -} - -impl Ecef { - /// Converts this Earth-fixed vector to the inertial frame at the given - /// Earth Rotation Angle. - pub fn to_eci(self, angle: EarthRotationAngle) -> Eci { - Eci::new(rotation_ecef_to_eci(angle) * self.0) - } -} diff --git a/crates/physics/apsis-frames/src/frame.rs b/crates/physics/apsis-frames/src/frame.rs deleted file mode 100644 index cccda08..0000000 --- a/crates/physics/apsis-frames/src/frame.rs +++ /dev/null @@ -1,41 +0,0 @@ -//! Frame marker types. - -use apsis_math::Vec3; - -/// A position or vector expressed in the Earth-centered inertial frame. -/// -/// The frame is aligned with the mean equator and equinox of J2000.0. It is -/// treated as inertial here, so it does not rotate with the Earth. -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct Eci(pub Vec3); - -/// A position or vector expressed in the Earth-centered Earth-fixed frame. -/// -/// The frame rotates with the Earth, so a point fixed to the ground has -/// constant coordinates in it. -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct Ecef(pub Vec3); - -impl Eci { - /// Creates an inertial frame vector from its components. - pub const fn new(vector: Vec3) -> Self { - Self(vector) - } - - /// Returns the underlying vector. - pub const fn vector(self) -> Vec3 { - self.0 - } -} - -impl Ecef { - /// Creates an Earth-fixed frame vector from its components. - pub const fn new(vector: Vec3) -> Self { - Self(vector) - } - - /// Returns the underlying vector. - pub const fn vector(self) -> Vec3 { - self.0 - } -} diff --git a/crates/physics/apsis-frames/src/lib.rs b/crates/physics/apsis-frames/src/lib.rs index 8f92d15..b90b91f 100644 --- a/crates/physics/apsis-frames/src/lib.rs +++ b/crates/physics/apsis-frames/src/lib.rs @@ -1,8 +1,11 @@ -//! Reference frame definitions and the transformations between them. +//! Reference frame definitions and the rotation between the inertial and +//! Earth-fixed frames. //! //! A reference frame fixes the orientation and origin that a vector is -//! expressed relative to. This crate defines the two frames used for -//! near-Earth work and the rotation between them. +//! expressed relative to. This crate names the two frames used for +//! near-Earth work and computes the rotation between them. Concrete +//! position types that carry a frame are defined in `apsis-coord`; this +//! crate works with the rotation matrix and the angle that defines it. //! //! The inertial frame is the Earth-centered inertial (ECI) frame aligned //! with the mean equator and equinox of J2000.0. Its axes are fixed in @@ -11,16 +14,16 @@ //! //! The rotating frame is the Earth-centered Earth-fixed (ECEF) frame. Its //! third axis is the Earth's rotation axis and its first axis follows the -//! prime meridian, so a point fixed to the ground has constant -//! coordinates in it. +//! prime meridian, so a point fixed to the ground has constant coordinates +//! in it. //! //! The two are related by a rotation of [`EarthRotationAngle`] about the -//! common third axis. This crate models the Earth's rotation with the -//! Earth Rotation Angle, which is a function of UT1 only. It does not -//! apply precession or nutation, because an angle accurate to a few -//! hundredths of a degree is sufficient for pointing and coverage work and -//! the full model needs the orientation of the celestial pole, which is a -//! separate computation. +//! common third axis. This crate models the Earth's rotation with the Earth +//! Rotation Angle, which is a function of UT1 only. It does not apply +//! precession or nutation, because an angle accurate to a few hundredths of +//! a degree is sufficient for pointing and coverage work and the full model +//! needs the orientation of the celestial pole, which is a separate +//! computation. //! //! Source: the Earth Rotation Angle expression is from the International //! Astronomical Union, as given in the *IERS Conventions (2010)*, equation @@ -43,10 +46,8 @@ #![deny(missing_docs)] mod earth_rotation; -mod frame; pub use earth_rotation::{ ERA_J2000_TURNS, ERA_RATE_TURNS_PER_DAY, EarthRotationAngle, rotation_ecef_to_eci, rotation_eci_to_ecef, ut1_days_from_j2000, }; -pub use frame::{Ecef, Eci}; diff --git a/crates/physics/apsis-frames/tests/earth_rotation.rs b/crates/physics/apsis-frames/tests/earth_rotation.rs index 492f774..75296d3 100644 --- a/crates/physics/apsis-frames/tests/earth_rotation.rs +++ b/crates/physics/apsis-frames/tests/earth_rotation.rs @@ -1,8 +1,8 @@ //! Tests for the Earth Rotation Angle and the frame rotations. use apsis_frames::{ - ERA_RATE_TURNS_PER_DAY, EarthRotationAngle, Ecef, Eci, rotation_ecef_to_eci, - rotation_eci_to_ecef, ut1_days_from_j2000, + ERA_RATE_TURNS_PER_DAY, EarthRotationAngle, rotation_ecef_to_eci, rotation_eci_to_ecef, + ut1_days_from_j2000, }; use apsis_math::Vec3; use core::f64::consts::PI; @@ -125,38 +125,6 @@ fn rotation_carries_the_second_axis_toward_the_first() { assert!((rotated.norm() - 1.0).abs() < EPS); } -#[test] -fn frame_conversions_round_trip() { - let angle = EarthRotationAngle::from_ut1_days(9.25); - let original = Eci::new(Vec3::new(7_000.0, -1_500.0, 3_200.0)); - let ecef = original.to_ecef(angle); - let back = ecef.to_eci(angle); - assert!((back.vector() - original.vector()).norm() < 1e-9); -} - -#[test] -fn frame_conversion_preserves_length() { - let angle = EarthRotationAngle::from_ut1_days(-3.5); - let vector = Vec3::new(6_878_137.0, 0.0, 0.0); - let converted = Eci::new(vector).to_ecef(angle); - assert!((converted.vector().norm() - vector.norm()).abs() < 1e-6); -} - -#[test] -fn rotating_background_returns_a_ground_point_to_the_same_longitude() { - // A point on the equator at zero longitude in the Earth-fixed frame is - // rotated by minus the Earth Rotation Angle in the inertial frame. - let angle = EarthRotationAngle::from_ut1_days(1.5); - let ground = Ecef::new(Vec3::new(6_378_137.0, 0.0, 0.0)); - let inertial = ground.to_eci(angle); - let expected = Vec3::new( - 6_378_137.0 * angle.radians_positive().cos(), - 6_378_137.0 * angle.radians_positive().sin(), - 0.0, - ); - assert!((inertial.vector() - expected).norm() < 1e-6); -} - #[test] fn a_full_turn_returns_to_the_same_rotation() { // The rotation depends on the angle modulo one turn, so angles that diff --git a/crates/physics/apsis-frames/tests/frame.rs b/crates/physics/apsis-frames/tests/frame.rs deleted file mode 100644 index 7e61136..0000000 --- a/crates/physics/apsis-frames/tests/frame.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Tests for the frame marker types. - -use apsis_frames::{Ecef, Eci}; -use apsis_math::Vec3; - -#[test] -fn wrappers_preserve_the_vector() { - let vector = Vec3::new(1.0, 2.0, 3.0); - assert_eq!(Eci::new(vector).vector(), vector); - assert_eq!(Ecef::new(vector).vector(), vector); -} - -#[test] -fn wrappers_compare_by_value() { - let vector = Vec3::new(-4.0, 5.5, 0.0); - assert_eq!(Eci::new(vector), Eci(vector)); - assert_eq!(Ecef::new(vector), Ecef(vector)); - assert_ne!(Eci::new(vector), Eci::new(Vec3::ZERO)); -}