physics: keep frames limited to rotations
This commit is contained in:
parent
efb69c77bf
commit
bdbaa20a5a
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
Loading…
Reference in New Issue