Skip to main content

RelativeTranslation

Enum RelativeTranslation 

Source
pub enum RelativeTranslation<Reference: Vehicle> {
    BodyFrame {
        position: Position<BodyFrame<Reference>>,
        velocity: Velocity<BodyFrame<Reference>>,
    },
    Inertial {
        position: Position<RootInertial>,
        velocity: Velocity<RootInertial>,
    },
}
Expand description

Frame-tagged translational state inside a RelativeState.

The compute_relative_state producer chooses the variant based on the runtime presence of the reference’s rotational state — JEOD’s decr_left convention rotates into the reference body frame iff a rotational state is available, and otherwise leaves the difference in the inertial frame. Encoding the choice as a sum-typed variant lets each variant carry a distinct phantom-tagged Position/Velocity pair, so a consumer that mixes a body-frame value with a root-inertial value is a compile error.

§Vehicle phantom

RelativeTranslation carries a single <Reference: Vehicle> parameter naming the reference vehicle in whose body frame the BodyFrame variant’s values are expressed. The Inertial variant is in the root inertial frame and does not depend on a vehicle identity, but the parameter is still threaded through the type so the two variants share a consistent compile-time pair shape with RelativeState’s <Subject, Reference>. Mission code that pins the reference at compile time gets a cross-pair guard: RelativeTranslation<Iss> and RelativeTranslation<Soyuz> are distinct types. The Bevy adapter and standalone runner instantiate <Reference = SelfRef>.

Pattern-match to read:

match rel.trans {
    RelativeTranslation::BodyFrame { position, velocity } => { /* typed body-frame */ }
    RelativeTranslation::Inertial  { position, velocity } => { /* typed root-inertial */ }
}

For consumers that just want the raw DVec3 (e.g. CSV-reference distance metrics in Tier 3 tests where both branches are valid inputs to the same scalar length()), Self::position_raw and Self::velocity_raw return the underlying SI vector without committing to a phantom — they’re the deliberate escape hatch for branch-agnostic numerical consumers.

§Compile-time frame guard

The body-frame variant carries a Position<BodyFrame<Reference>> while the inertial variant carries a Position<RootInertial>. Adding (or otherwise mixing without a deliberate FrameTransform) the two phantoms is a compile error. The doctest below documents the guard and is consumed by cargo test --doc as a compile_fail rustdoc test; if the body-frame and inertial-frame Position types ever became compatible, this test would start passing and fail the doctest.

use astrodyn_quantities::ext::Vec3Ext;
use astrodyn_quantities::frame::{BodyFrame, RootInertial, SelfRef};
use glam::DVec3;

let body_frame_pos = DVec3::ZERO.m_at::<BodyFrame<SelfRef>>();
let inertial_pos   = DVec3::ZERO.m_at::<RootInertial>();
// The two phantoms are kind-distinct — addition requires either
// matching frames or an explicit `FrameTransform`. The compiler
// refuses this expression at the type level:
let _ = body_frame_pos + inertial_pos;

§Compile-time cross-pair guard

The reference-vehicle phantom makes a BodyFrame<Iss> value kind-distinct from a BodyFrame<Soyuz> value. The doctest below shows that a consumer holding a Position<BodyFrame<Iss>> cannot accidentally bind it from a RelativeTranslation<Soyuz>’s body-frame variant — the destructure refuses to typecheck.

use astrodyn_quantities::aliases::Position;
use astrodyn_quantities::define_vehicle;
use astrodyn_quantities::frame::BodyFrame;
use astrodyn::RelativeTranslation;

define_vehicle!(Iss);
define_vehicle!(Soyuz);

fn binder(t: RelativeTranslation<Soyuz>) {
    // Would silently accept Soyuz-frame data into the Iss slot if
    // the phantom didn't propagate through the variant — the
    // compiler refuses this binding:
    let RelativeTranslation::BodyFrame { position, .. } = t else { return; };
    let _bound: Position<BodyFrame<Iss>> = position;
}

Variants§

§

BodyFrame

Reference rotational state was present: position/velocity are rotated into the reference body frame (JEOD S_{ref:subj}). The BodyFrame<Reference> phantom names the reference vehicle’s body frame at the type level — distinct from the subject’s body frame on RelativeState::ang_vel.

Fields

§position: Position<BodyFrame<Reference>>

Position of subject relative to reference, expressed in the reference body frame.

§velocity: Velocity<BodyFrame<Reference>>

Velocity of subject relative to reference, expressed in the reference body frame, with the JEOD Coriolis correction applied (v - ω_ref × r).

§

Inertial

Reference rotational state was absent: position/velocity are the raw inertial-frame difference. The RootInertial phantom is the simulation’s root inertial frame — for body-state inputs read from an integration-frame storage slot the convention rests on the call site (the producer cannot know statically that the inputs are root-inertial vs. some PlanetInertial<P> integration frame). Mission code that holds typed inputs should use the typed sibling API path rather than feeding raw DVec3 here.

Fields

§position: Position<RootInertial>

Position of subject relative to reference, in the inertial frame.

§velocity: Velocity<RootInertial>

Velocity of subject relative to reference, in the inertial frame.

Implementations§

Source§

impl<Reference: Vehicle> RelativeTranslation<Reference>

Source

pub fn position_raw(&self) -> DVec3

Raw position vector in whichever frame the variant carries.

Provided for branch-agnostic numerical consumers (e.g. scalar distance metrics). Frame-aware consumers should pattern-match on the variant to obtain the typed Position<F> and route it through the typed boundary.

Source

pub fn velocity_raw(&self) -> DVec3

Raw velocity vector in whichever frame the variant carries. Companion to Self::position_raw.

Source

pub fn assert_reference<R: Vehicle>(self) -> Self
where (): CompatibleVehicles<Reference, R>,

Type-level witness that this translation carries the caller’s expected reference-vehicle phantom R. Compiles only when Reference == R; on mismatch the astrodyn_quantities::diagnostics::CompatibleVehicles bound fails and surfaces a physics-language diagnostic naming the expected and found vehicles instead of a PhantomData<…> wall.

The method is a no-op (returns self) and has zero runtime cost; it exists so a consumer holding a RelativeTranslation<Iss> can refuse — at compile time, with a physics-language message — a value built for a different reference vehicle.

§Compile-time mismatch
use glam::DVec3;
use astrodyn_quantities::define_vehicle;
use astrodyn::{compute_relative_state, RelativeTranslation, TranslationalState};

define_vehicle!(Iss);
define_vehicle!(Soyuz);

let trans = TranslationalState { position: DVec3::ZERO, velocity: DVec3::ZERO };
let rel = compute_relative_state::<Iss, Iss>(&trans, None, &trans, None);
// Asserting the wrong reference fires the `CompatibleVehicles`
// diagnostic naming `Iss` (found) and `Soyuz` (expected).
let _ = rel.trans.assert_reference::<Soyuz>();

Trait Implementations§

Source§

impl<Reference: Clone + Vehicle> Clone for RelativeTranslation<Reference>

Source§

fn clone(&self) -> RelativeTranslation<Reference>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<Reference: Debug + Vehicle> Debug for RelativeTranslation<Reference>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<Reference> Freeze for RelativeTranslation<Reference>

§

impl<Reference> RefUnwindSafe for RelativeTranslation<Reference>
where Reference: RefUnwindSafe,

§

impl<Reference> Send for RelativeTranslation<Reference>

§

impl<Reference> Sync for RelativeTranslation<Reference>

§

impl<Reference> Unpin for RelativeTranslation<Reference>
where Reference: Unpin,

§

impl<Reference> UnsafeUnpin for RelativeTranslation<Reference>

§

impl<Reference> UnwindSafe for RelativeTranslation<Reference>
where Reference: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.