Added full cartesian support with (the beginning of) frames
This commit is contained in:
1 parent
412d96dde0
commit
b089b206f5
11 files changed
+731
-167
No files matched your search
+136
@@ -0,0 +1,136 @@
|
||||
//! Reference frames: where a state's origin is and how its axes are oriented.
|
||||
//!
|
||||
//! This module carries the frame *type*. Transformations between orientations —
|
||||
//! J2000 to ITRF, topocentric, geodetic site coordinates — are a separate piece of
|
||||
//! work and will land here on top of ANISE.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::body::Body;
|
||||
|
||||
/// How a frame's axes are oriented.
|
||||
///
|
||||
/// Provisional and deliberately coarse. The distinctions that matter for
|
||||
/// sub-arcsecond work — ICRF against EME2000, ITRF against a body-fixed IAU frame
|
||||
/// — arrive with the transformations, which is the point at which getting them
|
||||
/// wrong would show up. Marked `#[non_exhaustive]` so refining it is not a
|
||||
/// breaking change.
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Orientation {
|
||||
/// Inertial, aligned with the J2000 mean equator and equinox.
|
||||
J2000,
|
||||
/// Rotating with the central body.
|
||||
BodyFixed,
|
||||
}
|
||||
|
||||
/// A reference frame: a central body and an orientation.
|
||||
///
|
||||
/// Held by every [`Cartesian`](crate::cartesian::Cartesian) and every element set,
|
||||
/// which is what lets conversions read `mu` from the state rather than take it as
|
||||
/// an argument.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Frame {
|
||||
/// The body at the origin.
|
||||
pub center: Body,
|
||||
/// How the axes are oriented.
|
||||
pub orientation: Orientation,
|
||||
}
|
||||
|
||||
impl Frame {
|
||||
/// Earth-centered, J2000-oriented. The frame the study's scenarios work in.
|
||||
pub const EARTH_J2000: Self = Self {
|
||||
center: Body::EARTH,
|
||||
orientation: Orientation::J2000,
|
||||
};
|
||||
|
||||
/// Earth-centered, rotating with the Earth.
|
||||
pub const EARTH_FIXED: Self = Self {
|
||||
center: Body::EARTH,
|
||||
orientation: Orientation::BodyFixed,
|
||||
};
|
||||
|
||||
/// Moon-centered, J2000-oriented.
|
||||
pub const MOON_J2000: Self = Self {
|
||||
center: Body::MOON,
|
||||
orientation: Orientation::J2000,
|
||||
};
|
||||
|
||||
/// A J2000-oriented frame centered on `center`.
|
||||
pub const fn inertial(center: Body) -> Self {
|
||||
Self {
|
||||
center,
|
||||
orientation: Orientation::J2000,
|
||||
}
|
||||
}
|
||||
|
||||
/// A frame rotating with `center`.
|
||||
pub const fn body_fixed(center: Body) -> Self {
|
||||
Self {
|
||||
center,
|
||||
orientation: Orientation::BodyFixed,
|
||||
}
|
||||
}
|
||||
|
||||
/// The central body's gravitational parameter, m^3/s^2.
|
||||
pub fn mu(&self) -> f64 {
|
||||
self.center.mu
|
||||
}
|
||||
|
||||
/// Whether orbital motion in this frame is unaccelerated by the frame itself.
|
||||
///
|
||||
/// Element conversions and the two-body relations are only meaningful in an
|
||||
/// inertial frame; in a rotating one the velocity is not the inertial velocity.
|
||||
pub fn is_inertial(&self) -> bool {
|
||||
matches!(self.orientation, Orientation::J2000)
|
||||
}
|
||||
|
||||
/// The same frame with a different orientation.
|
||||
pub fn with_orientation(&self, orientation: Orientation) -> Self {
|
||||
Self {
|
||||
orientation,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Frame {
|
||||
fn default() -> Self {
|
||||
Self::EARTH_J2000
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_frame_carries_the_central_bodys_mu() {
|
||||
assert_eq!(Frame::EARTH_J2000.mu(), Body::EARTH.mu);
|
||||
assert_eq!(Frame::MOON_J2000.mu(), Body::MOON.mu);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_only_inertial_frames_report_inertial() {
|
||||
assert!(Frame::EARTH_J2000.is_inertial());
|
||||
assert!(!Frame::EARTH_FIXED.is_inertial());
|
||||
assert!(Frame::inertial(Body::SUN).is_inertial());
|
||||
assert!(!Frame::body_fixed(Body::SUN).is_inertial());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_orientation_can_be_swapped_keeping_the_center() {
|
||||
let fixed = Frame::EARTH_J2000.with_orientation(Orientation::BodyFixed);
|
||||
assert_eq!(fixed, Frame::EARTH_FIXED);
|
||||
assert_eq!(fixed.center, Body::EARTH);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_frame_round_trips_through_json() {
|
||||
let json = serde_json::to_string(&Frame::MOON_J2000).unwrap();
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Frame>(&json).unwrap(),
|
||||
Frame::MOON_J2000
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user