Skip to main content

ObserverState

Struct ObserverState 

Source
pub struct ObserverState {
    pub time: Dt,
    pub position: Position,
    pub velocity: Velocity,
    pub grav_potential_m2_s2: f64,
    pub characteristic_length_scale: f64,
}
Expand description

A complete relativistic state of an observer (spacecraft, ground station, planet, etc.) at a specific instant.

This is the natural input type for all relativistic light-time calculations in the library. It bundles position, velocity, gravitational potential, and an optional length scale in convenient SI units.

Fields§

§time: Dt

Dt of this state (any [Scale] is accepted).

§position: Position

Position in meters (typically barycentric or heliocentric).

§velocity: Velocity

Velocity in meters per second.

§grav_potential_m2_s2: f64

Local gravitational potential Φ in m² s⁻² (negative for bound orbits). Usually the sum of contributions from the Sun and planets.

§characteristic_length_scale: f64

Characteristic length scale (in meters) over which gravity varies significantly at the observer’s location.
Pass 0.0 (the default) for all solar-system, GNSS, and weak-field cases.

Implementations§

Source§

impl ObserverState

Source

pub const fn new( time: Dt, position: Position, velocity: Velocity, grav_potential_m2_s2: f64, ) -> Self

Creates a new state for typical solar-system or GNSS use.

Source

pub const fn new_strong_field( time: Dt, position: Position, velocity: Velocity, grav_potential_m2_s2: f64, characteristic_length_scale: f64, ) -> Self

Creates a new state when strong-field or gravimeter data is available.

Source

pub const fn proper_time_rate(&self) -> Real

Returns the instantaneous proper-time rate dτ/dt for this observer.

This is the exact rate at which a real clock at the given position, velocity, and gravitational environment would advance compared to coordinate time. It is used internally by the library for proper-time integration, light-time corrections, and Doppler calculations.

Source

pub const fn relativistic_clock_doppler_factor(&self, rx: ObserverState) -> Real

Returns the relativistic clock-rate Doppler factor for a one-way signal sent from this transmitter to the given receiver.

The factor is the ratio of the receiver’s proper-time rate to the transmitter’s proper-time rate. It accounts for the fact that clocks at the two locations run at slightly different speeds due to motion and gravity.

To obtain the full observed frequency shift, multiply this factor by the classical kinematic Doppler term (1 - v_radial / C), where v_radial is the line-of-sight component of the relative velocity (positive when the transmitter and receiver are moving apart).

This value is used for deep-space tracking, GNSS range-rate measurements, and pulsar timing.

§Parameters
  • self – transmitter state (position, velocity, gravitational potential, and length scale at the moment the signal is sent)
  • rx – receiver state (same information, evaluated at the approximate arrival time)
§Example
use deep_time::{ObserverState, Position, Velocity, Dt};
use deep_time::constants::C;


let tx = ObserverState::new(tx_time, tx_pos, tx_vel, phi);
let rx = ObserverState::new(rx_time, rx_pos, rx_vel, phi);

let factor = tx.relativistic_clock_doppler_factor(rx);

// Full observed frequency shift (example only)
let v_radial = 0.0; // m/s, positive if receding
let classical_doppler = 1.0 - v_radial / C;
let total_frequency_shift = 1.0 * factor * classical_doppler;
Source

pub const fn two_way_relativistic_doppler_factor( &self, rx: ObserverState, ) -> Real

Returns the two-way relativistic clock-rate Doppler factor for round-trip ranging (transmit → receive → immediate transponder reply).

This is the product of the one-way factors for the complete round trip and is the value needed by deep-space networks when correcting measured range-rate data.

Source

pub const fn one_way_relativistic_delay_to( &self, rx: ObserverState, context: LightContext, ) -> TSpan

Computes the total relativistic correction that must be added to the Newtonian geometric light time (|r_rx − r_tx| / c) for a one-way signal.

This function accounts for two physical effects:

  • Differential clock-rate drift between transmitter and receiver (special-relativistic velocity + general-relativistic gravitational time dilation) using the library’s unified master-Lagrangian proper-time model.
  • Gravitational (Shapiro) delay caused by spacetime curvature near a central mass.

Use cases include:

  • Deep-space tracking and ranging (DSN, ESA, JPL)
  • GNSS and satellite navigation
  • Pulsar timing arrays
  • Laser communication or ranging to distant spacecraft
  • Future interstellar missions where signals pass near other stars or black holes
§Parameters
  • self – the transmitter’s full relativistic state at the moment the signal is sent
  • rx – the receiver’s relativistic state at the approximate arrival time
  • context – controls the gravitational (Shapiro) contribution. Use LightContext::SOLAR for solar-system work, LightContext::FLAT when you want no central-mass delay, or LightContext::from_grav_param(your_gravitational_parameter) for any other star, planet, or black hole.
§Returns

A TSpan (in seconds) to be added to the Newtonian geometric light time.

§Examples

Basic usage for a solar-system one-way light-time correction (e.g. Earth to Mars):

use deep_time::{
    ObserverState, Position, Velocity, Dt, TSpan, LightContext,
    // Assume you have ephemeris functions or constants available
};


let transmitter = ObserverState::new(
    tx_time,
    tx_pos,
    tx_vel,
    tx_potential,
);

let receiver_approx = ObserverState::new(
    rx_approx_time,
    rx_pos,
    rx_vel,
    rx_potential,
);

// Use SOLAR for Sun-centered calculations
let correction: TSpan = transmitter
    .one_way_relativistic_delay_to(receiver_approx, LightContext::SOLAR);

// The result should be added to the Newtonian geometric delay `r_sep / C`

For a custom body (e.g. Jupiter):

let jupiter_context = LightContext::from_grav_param(jupiter_gm);  // GM in m³/s²
let correction = tx.one_way_relativistic_delay_to(rx, jupiter_context);
§Multi-body and exotic environments

This function models the Shapiro delay from only a single central mass via the supplied LightContext. For signals that pass near multiple massive bodies (e.g. two stars, a star and a planet, or a binary black-hole system) or in highly dynamic/strong-field regimes, the single-body approximation may not be sufficient.

In those cases consider using [one_way_relativistic_delay_integrated] instead, which lets you supply your own full spacetime model along the entire path. Alternatively, you can compute individual Shapiro contributions from each body (using the helper shapiro_one_way_for_body if you add it) and manually combine them with the result of this function.

Source

pub fn iterative_one_way_relativistic_delay_to<F>( &self, rx_provider: F, context: LightContext, tolerance: TSpan, max_iter: usize, ) -> (TSpan, Dt)
where F: FnMut(Dt) -> ObserverState,

Iteratively solves for the true receive time and the corresponding relativistic correction for a one-way signal.

Because the exact arrival time depends on the relativistic correction itself, an iterative approach is required. The function typically converges in 3–5 iterations to sub-nanosecond accuracy, even for outer-solar-system distances.

§Parameters
  • self – the transmitter’s relativistic state (fixed)
  • rx_provider – a closure that, given a guessed receive Dt, returns the full ObserverState of the receiver at that time. You usually create this closure by calling your ephemeris/orbit propagator.
  • context – gravitational context (LightContext::SOLAR, LightContext::FLAT, or a custom value). See [one_way_relativistic_delay_to] for details.
  • tolerance – maximum allowed change in receive time between iterations (recommended TSpan::from_ns(1) or tighter)
  • max_iter – safety limit on the number of iterations (recommended 8–12)
§Returns

A tuple (correction, final_rx_time) where:

  • correction is the relativistic delay (same as returned by [one_way_relativistic_delay_to])
  • final_rx_time is the converged receive Dt
§Examples
use deep_time::{ObserverState, Dt, TSpan, LightContext, Position, Velocity};


let transmitter = ObserverState::new(
    tx_time,
    tx_pos,
    tx_vel,
    tx_potential,
);

let (correction, final_rx_time) = transmitter.iterative_one_way_relativistic_delay_to(
    |guessed_rx_time| {
        // Call your ephemeris / orbit propagator here
        let (pos, vel, potential) = get_receiver_state_at(guessed_rx_time);
        ObserverState::new(guessed_rx_time, pos, vel, potential)
    },
    LightContext::SOLAR,
    TSpan::from_ns(1),   // 1 nanosecond tolerance (recommended)
    12,                  // safety limit (recommended)
);

// `correction` is the total relativistic delay (clock drift + Shapiro)
// to add to the Newtonian geometric light time.
// `final_rx_time` is the accurately converged signal arrival time.

Using a custom central body (e.g. near Jupiter) and a tighter tolerance:

let jupiter_gm = 1.26686534e17_f64; // m³/s²
let context = LightContext::from_grav_param(jupiter_gm);

let (correction, rx_time) = tx.iterative_one_way_relativistic_delay_to(
    rx_provider, context, TSpan::from_ns(0.1), 10
);
Source

pub const fn one_way_relativistic_delay_integrated( &self, rx: ObserverState, context: LightContext, samples: &[LocalSpacetime], ) -> TSpan

Computes the relativistic correction using numerical quadrature (Simpson’s rule) of the relative clock-rate offset along the entire straight-line light path.

This is the most accurate method when the clock-rate offset varies continuously along the path (long baselines, interstellar distances, or strong-field regions).

§Parameters
  • self – the transmitter’s relativistic state
  • rx – the receiver’s relativistic state
  • context – gravitational context for the Shapiro delay (see [one_way_relativistic_delay_to])
  • samples – a slice of LocalSpacetime snapshots uniformly spaced along the path (λ ∈ [0, 1]). You build this slice by evaluating your spacetime model at several points between transmitter and receiver. Even 9–21 samples give excellent accuracy.
§Returns

A TSpan containing the integrated clock-drift correction plus the Shapiro delay from the supplied context.

§Example of building samples
let samples: Vec<LocalSpacetime> = (0..=15)
    .map(|i| {
        let lambda = i as f64 / 15.0;
        let point = tx.position.lerp(rx.position, lambda);
        let phi_over_c2 = compute_total_potential_at(point); // your model
        LocalSpacetime::from_potential_velocity_and_scale(
            phi_over_c2,
            Velocity::ZERO,
            0.0, // weak-field
        )
    })
    .collect();
§Examples

Full usage example for high-accuracy one-way light-time correction (e.g. interstellar distances or strong gravitational fields):

use deep_time::{
    ObserverState, LocalSpacetime, Position, Velocity, Dt,
    TSpan, LightContext,
};


let transmitter = ObserverState::new(
    tx_time, tx_pos, tx_vel, tx_potential,
);

let receiver = ObserverState::new(
    rx_time, rx_pos, rx_vel, rx_potential,
);

// Build uniformly spaced samples along the straight-line path.
// 9–21 points are usually sufficient; use more for interstellar/strong-field cases.
let samples: Vec<LocalSpacetime> = (0..=21)
    .map(|i| {
        let lambda = i as f64 / 21.0;
        let point = transmitter.position.lerp(receiver.position, lambda);
        let phi_over_c2 = compute_total_potential_at(point);

        LocalSpacetime::from_potential_velocity_and_scale(
            phi_over_c2,
            Velocity::ZERO,   // light itself carries no rest-mass velocity
            0.0,              // weak-field approximation
        )
    })
    .collect();

let total_correction: TSpan = transmitter.one_way_relativistic_delay_integrated(
    receiver,
    LightContext::SOLAR,
    &samples,
);

// `total_correction` is the integrated clock-drift + Shapiro delay
// to be added to the Newtonian geometric light time.

Using a custom central body (e.g. near another star or planet):

let custom_context = LightContext::from_grav_param(star_gm); // GM in m³/s²
let correction = tx.one_way_relativistic_delay_integrated(
    rx, custom_context, &samples
);
§Multi-body and exotic environments

This function is the recommended choice when a signal passes near multiple massive bodies (two or more stars, a star and a planet, binary black holes, etc.) or when operating in strong gravitational fields or highly dynamic spacetimes. Because you supply your own LocalSpacetime snapshots, each sample can incorporate the combined gravitational potential, velocity, and curvature from every relevant body in your model.

In contrast, the faster [one_way_relativistic_delay_to] function only supports a single central mass via LightContext. For complex geometries or high-fidelity simulations, this integrated method provides greater accuracy and flexibility.

Source

pub const fn round_trip_relativistic_correction( &self, round_trip_measured: TSpan, rx: ObserverState, context: LightContext, ) -> TSpan

Computes the relativistic correction for a two-way round-trip ranging measurement (transmit → receive → immediate transponder reply).

Deep-space networks measure distance by timing a round-trip signal. This function returns the tiny relativistic adjustment that must be subtracted from the raw measured round-trip time to recover the true geometric distance.

§Parameters
  • self – the transmitter’s relativistic state at send time
  • round_trip_measured – the raw measured round-trip duration (in seconds)
  • rx – the receiver’s relativistic state (its time field is ignored)
  • context – gravitational context for the Shapiro delay (see [one_way_relativistic_delay_to])
§Returns

A TSpan (in seconds) that must be subtracted from the measured round-trip time.

§Examples

Typical usage for deep-space two-way ranging (e.g. Earth to spacecraft or planet via DSN):

use deep_time::{
    ObserverState, Position, Velocity, Dt, TSpan, LightContext,
};


let transmitter = ObserverState::new(
    tx_time,
    tx_pos,
    tx_vel,
    tx_potential,
);

// Receiver state at approximate arrival time (its `.time` field is ignored)
let receiver_approx = ObserverState::new(
    Dt::default(), // dummy time - will be ignored
    rx_pos,
    rx_vel,
    rx_potential,
);

let relativistic_correction = transmitter.round_trip_relativistic_correction(
    measured_round_trip,
    receiver_approx,
    LightContext::SOLAR,
);

// Correct the measured round-trip time:
let corrected_round_trip = measured_round_trip.sub(relativistic_correction);

// Then the true geometric one-way light time and distance can be computed from
// `corrected_round_trip / 2`.

Using a custom gravitational context (e.g. ranging to a probe near Jupiter):

let jupiter_context = LightContext::from_grav_param(jupiter_gm); // GM in m³/s²
let correction = tx.round_trip_relativistic_correction(
    measured, rx_approx, jupiter_context
);

Trait Implementations§

Source§

impl Clone for ObserverState

Source§

fn clone(&self) -> ObserverState

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 Debug for ObserverState

Source§

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

Formats the value using the given formatter. Read more
Source§

impl PartialEq for ObserverState

Source§

fn eq(&self, other: &ObserverState) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for ObserverState

Source§

impl StructuralPartialEq for ObserverState

Auto Trait Implementations§

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, 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.