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: Real,
    pub characteristic_length_scale: Real,
}
Expand description

A snapshot of an observer’s relativistic state at a specific instant.

ObserverState combines time, position, velocity, and local gravitational information. It is the main input type used by relativistic light-time methods in this library.

Fields§

§time: Dt

The time of this state.

Any [Scale] is accepted. This time is treated as coordinate time for light-time calculations.

§position: Position

Position of the observer in meters.

Typically expressed in a barycentric (solar-system barycenter) or heliocentric frame, depending on the application.

§velocity: Velocity

Velocity of the observer in meters per second.

§grav_potential_m2_s2: Real

Newtonian gravitational potential Φ at the observer’s location (in m² s⁻²).

This value is usually negative for bound orbits. It should normally include contributions from the Sun and all relevant planets.

§characteristic_length_scale: Real

Characteristic length scale (in meters) over which the gravitational field varies significantly at this location.

  • Use 0.0 (the default) for all solar-system, GNSS, and weak-field applications.
  • Provide a non-zero value only when working in strong gravitational fields (e.g. near neutron stars or black holes), where the library’s higher-order curvature terms become relevant.

Implementations§

Source§

impl ObserverState

Source

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

Creates a new ObserverState for typical solar-system, GNSS, or weak-field use.

This is the recommended constructor for most applications. It sets the characteristic_length_scale to 0.0, which disables higher-order curvature terms in the proper-time model.

§Parameters
  • time: The time of the state.
  • position: Position in meters (usually barycentric or heliocentric).
  • velocity: Velocity in m/s.
  • grav_potential_m2_s2: Newtonian gravitational potential Φ at the location (in m²/s²).
Source

pub const fn proper_time_rate(&self) -> Real

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

This value indicates how fast a physical clock located at this state would advance relative to the time used by this ObserverState. A returned value of 1.0 means the clock advances at the same rate as the state’s time coordinate. Values are typically slightly different from 1.0 due to the effects of velocity and gravitational potential.

This rate is computed using the library’s unified proper-time model. It is used internally for light-time corrections and Doppler calculations.

Source

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

Returns the ratio of proper time rates between the receiver and transmitter for a one-way signal.

This method computes:

ratio = rx.proper_time_rate() / self.proper_time_rate()
§Interpretation
  • A value of 1.0 indicates that both clocks run at the same rate.
  • A value less than 1.0 means the receiver’s clock runs slower than the transmitter’s clock. The receiver will observe a lower frequency than was emitted.
  • A value greater than 1.0 means the receiver’s clock runs faster than the transmitter’s clock. The receiver will observe a higher frequency than was emitted.

The ratio captures the combined effect of special-relativistic time dilation (due to velocity) and general-relativistic gravitational time dilation.

§Typical Usage (One-Way)

This ratio is often combined with the classical kinematic Doppler term to estimate the total one-way frequency shift:

approximate_frequency_shift ≈ ratio * (1 - v_radial / C)

where v_radial is the radial velocity (positive when the receiver is receding).

§Two-Way Usage

For round-trip (two-way) measurements, square the one-way ratio:

let one_way_ratio = transmitter.relativistic_clock_rate_ratio(receiver);
let two_way_ratio = one_way_ratio * one_way_ratio;

This pattern is commonly used when correcting two-way Doppler (range-rate) data for relativistic clock effects.

§Limitations
  • This method only accounts for the difference in clock rates between the two ends.
  • It does not include Shapiro delay or higher-order relativistic effects on signal propagation.
  • The combination with classical Doppler shown above is a first-order approximation.
§Parameters
  • self — Transmitter state at the time of transmission.
  • rx — Receiver state at the approximate time of reception.
§Example
let ratio = transmitter.relativistic_clock_rate_ratio(receiver);

let v_radial = ...; // m/s, positive if receding
let classical_doppler = 1.0 - v_radial / C;

let approx_frequency_shift = ratio * classical_doppler;
Source

pub const fn one_way_relativistic_delay( &self, rx: ObserverState, bodies: &[(Dt, Position)], ) -> Dt

Computes the combined one-way relativistic correction for a signal traveling from this observer (the transmitter) to a receiver.

This value is the total extra time you should add to the Newtonian geometric light travel time (distance / speed of light). It includes two separate relativistic effects:

  1. The gravitational propagation delay (Shapiro delay) caused by the Sun and other bodies slowing the signal.
  2. The differential clock-rate correction caused by the transmitter and receiver having slightly different proper-time rates (due to their velocities and gravitational potentials).

In other words, this method gives you propagation delay + clock-rate correction in one convenient call.

Important: This is a convenience method. It is provided so you can get the full one-way relativistic correction quickly. If you need strict separation of the two effects (for example, to apply them at different stages of your calculation), call Self::shapiro_delay and Self::compute_differential_clock_correction individually and add the results yourself.

§When to use this method

Use this when you need the complete relativistic correction for one-way light time in a single step — for example when:

  • Computing high-precision one-way range or Doppler observables
  • Building simplified navigation or orbit determination models
  • You want the total effect without manually combining the pieces
§The bodies parameter – which masses to include

Pass a slice of (shapiro_coefficient, body_position) pairs:

  • shapiro_coefficient: How strong the delay from this body should be. It equals 2GM / c³. Use Dt::SHAPIRO_SOLAR for the Sun, or [Dt::shapiro_from_grav_param(gm)] for any other body.
  • body_position: Where the center of that body is located at the relevant time.

Important: All positions must be measured the same way

The transmitter position (self.position), the receiver position (rx.position), and every body_position you provide must all be measured from the same point in space, and they must all use the same directions for their X, Y, and Z axes.

For example, if your transmitter position is measured from the center of the solar system, then the receiver and body positions must also be measured from the center of the solar system using the same pointing directions for the coordinate axes.

In most solar-system work, people use positions from JPL ephemerides (which are measured from the center of the solar system).

Pass an empty slice (&[]) to turn off the Shapiro (gravitational) part of the correction.

§Parameters
  • rx — Receiver state at the approximate time the signal arrives.
  • bodies — List of bodies that should contribute to the gravitational propagation delay.
§Returns

The total one-way relativistic correction (Shapiro propagation delay plus differential clock-rate correction), expressed as a Dt in the same time scale as self.time.

This value should normally be added to the Newtonian geometric light time.

Source

pub fn iterative_one_way_light_time_to<F>( &self, rx_provider: &mut F, bodies: &[(Dt, Position)], tolerance: Dt, max_iter: usize, ) -> (Dt, Dt, ObserverState)
where F: FnMut(Dt) -> ObserverState,

Iteratively solves the one-way light-time equation in coordinate time, including relativistic propagation corrections, until convergence.

This solver computes the receive epoch t_rx such that:

t_rx = t_tx + |r_rx(t_rx) − r_tx(t_tx)| / c + Δt_shapiro(t_tx, t_rx)

It performs fixed-point iteration using the propagation delay returned by Self::shapiro_delay. Clock-rate and proper-time effects are not included in the iteration; they should be applied separately when converting between coordinate time and proper time or when forming observables.

The solver is suitable for high-precision one-way light-time calculations and works with any ephemeris source via the provided closure.

§Parameters
  • rx_provider — Closure returning the full ObserverState of the receiver at a given coordinate time.
  • bodies — Slice of (shapiro_coefficient, body_position) pairs controlling the Shapiro contribution. Use &[(Dt::SHAPIRO_SOLAR, sun_pos)] for solar-system work; include additional bodies for higher precision. Pass &[] to disable Shapiro.
  • tolerance — Maximum allowed change in receive time per iteration before declaring convergence (e.g. Dt::from_ns(1, Scale::TAI)).
  • max_iter — Maximum number of iterations. Typical values are 12–20 for solar-system geometries.
§Returns

A tuple (prop_correction, rx_time, final_state) where:

  • prop_correction is the converged Shapiro propagation delay,
  • rx_time is the converged receive time (same scale as self.time),
  • final_state is the receiver state at rx_time.
Source

pub fn round_trip_light_time_correction<RxF, TxF>( &self, rx_provider: RxF, tx_provider: TxF, bodies: &[(Dt, Position)], tolerance: Dt, max_iter: usize, ) -> Dt
where RxF: FnMut(Dt) -> ObserverState, TxF: FnMut(Dt) -> ObserverState,

Computes the total Shapiro (gravitational propagation) delay for a complete round-trip (two-way) signal.

This method solves the uplink and downlink legs separately and independently using the iterative light-time solver. This approach is more accurate than older combined round-trip formulas when the two ends have significantly different velocities or are in different gravitational environments.

The returned value is the sum of the uplink and downlink Shapiro delays only. It does not include clock-rate or proper-time corrections.

§When to use this method

Use this when you need the total gravitational propagation correction for two-way (round-trip) measurements, for example:

  • Two-way range or range-rate (Doppler) data
  • Transponded signals from spacecraft
  • Any high-precision two-way light-time calculation

For one-way signals, use Self::shapiro_delay or Self::one_way_relativistic_delay instead.

§How the calculation works
  1. Solves the uplink leg (from self to the remote receiver) using the rx_provider closure.
  2. Obtains the accurate receiver state at the uplink arrival time.
  3. Solves the downlink leg (from the receiver back to the local transmitter) using the tx_provider closure.
§The bodies parameter – which masses to include

Pass a slice of (shapiro_coefficient, body_position) pairs (the same slice is used for both legs). See Self::shapiro_delay for details on how to build this slice.

Important: All states returned by the providers must be consistent with the same reference frame (same origin and same coordinate axes).

§Parameters
  • rx_provider — Closure that returns the full ObserverState of the remote receiver (planet, spacecraft, etc.) at any given coordinate time.
  • tx_provider — Closure that returns the full ObserverState of the local transmitter at any given coordinate time (used only for the downlink leg).
  • bodies — Slice of (shapiro_coefficient, body_position) pairs describing the gravitating bodies.
  • tolerance — Convergence tolerance for each leg’s iterative solver (e.g. Dt::from_ns(1, Scale::TAI)).
  • max_iter — Maximum number of iterations allowed per leg (typical values are 12–20).
§Returns

The total round-trip Shapiro propagation delay (uplink + downlink) as a Dt, in the same time scale as self.time.

This value should normally be added to the Newtonian geometric round-trip light time. Clock-rate corrections must still be applied separately (e.g. by squaring the one-way clock-rate ratio).

Source

pub const fn shapiro_delay( &self, rx: ObserverState, bodies: &[(Dt, Position)], ) -> Dt

Computes the one-way gravitational propagation delay (Shapiro delay) caused by massive bodies between this observer (the transmitter) and a receiver.

This value is the extra time a radio signal takes to travel because gravity from the Sun and planets slightly slows it down. You normally add this delay to the ordinary geometric light travel time (distance / speed of light) to get a more accurate total one-way signal travel time.

Important: This method returns only the gravitational propagation delay. It does not include clock-rate differences between the transmitter and receiver caused by velocity or gravity. Those effects are available separately through Self::compute_differential_clock_correction, Self::proper_time_rate, and Self::relativistic_clock_rate_ratio.

§When to use this method

Use this when you need the gravitational (Shapiro) contribution to one-way light time — for example when building high-precision range, Doppler, or orbit determination models.

§The bodies parameter – which masses to include

Pass a slice of (shapiro_coefficient, body_position) pairs:

  • shapiro_coefficient: How strong the delay from this body should be. It equals 2GM / c³. Use Dt::SHAPIRO_SOLAR for the Sun, or [Dt::shapiro_from_grav_param(gm)] for any other body.
  • body_position: Where the center of that body is located at the relevant time.

Important: All positions must be measured the same way

The transmitter position (self.position), the receiver position (rx.position), and every body_position you provide must all be measured from the same point in space, and they must all use the same directions for their X, Y, and Z axes.

For example, if the transmitter position is measured from the center of the solar system, then the receiver and body positions must also be measured from the center of the solar system, using the same pointing directions for the coordinate axes.

If the positions come from different measurement systems, the calculated delay will be wrong.

In most solar-system work, people use positions from JPL ephemerides (which are measured from the center of the solar system).

Pass an empty slice (&[]) to turn off Shapiro delay entirely.

§Parameters
  • rx — Receiver state at the approximate time the signal arrives.
  • bodies — List of bodies that should contribute to the delay.
§Returns

The total one-way Shapiro gravitational propagation delay, in the same time scale as self.time. This value should normally be added to the Newtonian geometric light time.

Source

pub const fn compute_differential_clock_correction( &self, rx: ObserverState, ) -> Dt

Computes the differential proper-time correction between self (transmitter) and rx (receiver) over the interval between their time tags.

This returns the difference in proper time advance between the two observers. It does not include Shapiro propagation delay.

The result can be added to the output of Self::shapiro_delay or Self::iterative_one_way_light_time_to when a combined relativistic correction (propagation + clock rate) is required.

§Parameters
  • rx — Receiver state at the approximate time of reception.
§Returns

The differential clock-rate correction (rx_proper_advance − tx_proper_advance).

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<'de> Deserialize<'de> for ObserverState

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. 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 Serialize for ObserverState

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Tsify for ObserverState

Source§

const DECL: &'static str = "/**\n * A snapshot of an observer\u{2019}s relativistic state at a specific instant.\n *\n * `ObserverState` combines time, position, velocity, and local gravitational\n * information. It is the main input type used by relativistic light-time\n * methods in this library.\n */\nexport interface ObserverState {\n /**\n * The time of this state.\n *\n * Any [`Scale`] is accepted. This time is treated as coordinate time\n * for light-time calculations.\n */\n time: Dt;\n /**\n * Position of the observer in meters.\n *\n * Typically expressed in a barycentric (solar-system barycenter) or\n * heliocentric frame, depending on the application.\n */\n position: Position;\n /**\n * Velocity of the observer in meters per second.\n */\n velocity: Velocity;\n /**\n * Newtonian gravitational potential \u{3a6} at the observer\u{2019}s location\n * (in m\u{b2} s\u{207b}\u{b2}).\n *\n * This value is usually negative for bound orbits. It should normally\n * include contributions from the Sun and all relevant planets.\n */\n grav_potential_m2_s2: Real;\n /**\n * Characteristic length scale (in meters) over which the gravitational\n * field varies significantly at this location.\n *\n * - Use `0.0` (the default) for all solar-system, GNSS, and weak-field\n * applications.\n * - Provide a non-zero value only when working in strong gravitational\n * fields (e.g. near neutron stars or black holes), where the library\u{2019}s\n * higher-order curvature terms become relevant.\n */\n characteristic_length_scale: Real;\n}"

Source§

const SERIALIZATION_CONFIG: SerializationConfig

Source§

type JsType = JsType

Source§

fn into_js(&self) -> Result<Self::JsType, Error>
where Self: Serialize,

Source§

fn from_js<T>(js: T) -> Result<Self, Error>
where T: Into<JsValue>, Self: DeserializeOwned,

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> 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.
Source§

impl<S, T> Upcast<T> for S
where T: UpcastFrom<S> + ?Sized, S: ?Sized,

Source§

fn upcast(&self) -> &T
where Self: ErasableGeneric, T: ErasableGeneric<Repr = Self::Repr>,

Perform a zero-cost type-safe upcast to a wider ref type within the Wasm bindgen generics type system. Read more
Source§

fn upcast_into(self) -> T
where Self: Sized + ErasableGeneric, T: ErasableGeneric<Repr = Self::Repr>,

Perform a zero-cost type-safe upcast to a wider type within the Wasm bindgen generics type system. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,