Skip to content

Relativistic Effects

While Newtonian mechanics is sufficient for most satellite orbit calculations, general relativistic effects become measurable with modern precision orbit determination systems. These corrections are particularly important for:

  • Global Navigation Satellite Systems (GPS, Galileo, GLONASS, BeiDou)
  • Fundamental physics experiments in space
  • Ultra-precise orbit determination (cm-level accuracy)
  • Long-term orbit propagation

Physical Basis

General relativity modifies Newton's law of gravitation by accounting for the curvature of spacetime caused by mass. Mntenbruck & Gill (2000) provide the post-Newtonian correction of the acceleration due to Earth's gravity as:

\[ \mathbf{a} = -\frac{GM}{r^2} \left( \left( 4\frac{GM}{c^2r} - \frac{v^2}{c^2} \right)\mathbf{e}_r + 4\frac{v^2}{c^2}\left(\mathbf{e}_r \cdot \mathbf{e}_v\right)\mathbf{e}_v\right) \]

where:

  • \(GM\) is Earth's gravitational parameter (m³/s²)
  • \(c\) is the speed of light (299,792,458 m/s)
  • \(r\) is the satellite position magnitude (m)
  • \(v\) is the satellite velocity magnitude (m/s)
  • \(\mathbf{e}_r = \frac{\mathbf{r}}{r}\) is the radial unit vector
  • \(\mathbf{e}_v = \frac{\mathbf{v}}{v}\) is the velocity unit vector

Usage Examples

Computing Relativistic Acceleration

Calculate the general relativistic correction to a satellite's acceleration.

import brahe as bh
import numpy as np

bh.initialize_eop()

# Define GPS satellite state (MEO orbit where relativity is measurable)
a = bh.R_EARTH + 20180e3  # Semi-major axis (m)
e = 0.01  # Eccentricity
i = np.radians(55.0)  # Inclination (rad)
raan = np.radians(30.0)  # RAAN (rad)
argp = np.radians(45.0)  # Argument of perigee (rad)
nu = np.radians(90.0)  # True anomaly (rad)

# Convert to Cartesian state
oe = np.array([a, e, i, raan, argp, nu])
state = bh.state_koe_to_eci(oe, bh.AngleFormat.RADIANS)

print("GPS Satellite state (ECI):")
print(
    f"  Position: [{state[0] / 1e3:.1f}, {state[1] / 1e3:.1f}, {state[2] / 1e3:.1f}] km"
)
print(
    f"  Velocity: [{state[3] / 1e3:.3f}, {state[4] / 1e3:.3f}, {state[5] / 1e3:.3f}] km/s"
)
r_mag = np.linalg.norm(state[0:3])
v_mag = np.linalg.norm(state[3:6])
print(f"  Altitude: {(r_mag - bh.R_EARTH) / 1e3:.1f} km")
print(f"  Speed: {v_mag / 1e3:.3f} km/s")

# Compute relativistic acceleration
accel_rel = bh.accel_relativity(state)

print("\nRelativistic acceleration (m/s²):")
print(f"  ax = {accel_rel[0]:.15f}")
print(f"  ay = {accel_rel[1]:.15f}")
print(f"  az = {accel_rel[2]:.15f}")
print(f"  Magnitude: {np.linalg.norm(accel_rel):.15e} m/s²")

# Compare to Newtonian point-mass gravity
accel_newton = bh.accel_point_mass_gravity(
    state[0:3], np.array([0.0, 0.0, 0.0]), bh.GM_EARTH
)
accel_newton_mag = np.linalg.norm(accel_newton)

print(f"\nNewtonian gravity magnitude: {accel_newton_mag:.9f} m/s²")
print(
    f"Relativistic/Newtonian ratio: {np.linalg.norm(accel_rel) / accel_newton_mag:.6e}"
)

# Estimate accumulated position error if relativity is ignored
# Using simple approximation: Δr ≈ 0.5 * a * t²
# For 1 day propagation
one_day = 86400.0  # seconds
pos_error_1day = 0.5 * np.linalg.norm(accel_rel) * one_day**2

print("\nApproximate position error if relativity ignored:")
print(f"  After 1 day: {pos_error_1day:.3f} m")
print(f"  After 1 week: {pos_error_1day * 7:.1f} m")

# Compare to other perturbations at this altitude
# J2 magnitude (approximate)
j2 = 1.08263e-3
accel_j2_approx = 1.5 * j2 * bh.GM_EARTH * (bh.R_EARTH / r_mag) ** 2 / r_mag**2

# Third-body (Sun, approximate)
accel_sun_approx = 5e-8  # Typical value for GPS altitude

print("\nRelative magnitude of perturbations at GPS altitude:")
print(f"  J2: ~{accel_j2_approx:.6e} m/s²")
print(f"  Sun: ~{accel_sun_approx:.6e} m/s²")
print(f"  Relativity: {np.linalg.norm(accel_rel):.6e} m/s²")
print(f"  Relativity/J2 ratio: {np.linalg.norm(accel_rel) / accel_j2_approx:.6e}")

# Expected output:
# GPS Satellite state (ECI):
#   Position: [-21864.6, -435.7, 15074.0] km
#   Velocity: [-1.555, -2.730, -2.266] km/s
#   Altitude: 20182.7 km
#   Speed: 3.874 km/s

# Relativistic acceleration (m/s²):
#   ax = -0.000000000234510
#   ay = -0.000000000007302
#   az = 0.000000000158426
#   Magnitude: 2.831022208577214e-10 m/s²

# Newtonian gravity magnitude: 0.565009481 m/s²
# Relativistic/Newtonian ratio: 5.010575e-10

# Approximate position error if relativity ignored:
#   After 1 day: 1.057 m
#   After 1 week: 7.4 m

# Relative magnitude of perturbations at GPS altitude:
#   J2: ~5.290937e-05 m/s²
#   Sun: ~5.000000e-08 m/s²
#   Relativity: 2.831022e-10 m/s²
#   Relativity/J2 ratio: 5.350701e-06
//! nalgebra = "0.33"
//! ```

//! Compute general relativistic correction to satellite acceleration

#[allow(unused_imports)]
use brahe as bh;
use nalgebra as na;

fn main() {
    bh::initialize_eop().unwrap();

    // Define GPS satellite state (MEO orbit where relativity is measurable)
    let a = bh::constants::R_EARTH + 20180e3; // Semi-major axis (m)
    let e = 0.01;                             // Eccentricity
    let i = 55.0_f64.to_radians();            // Inclination (rad)
    let raan = 30.0_f64.to_radians();         // RAAN (rad)
    let argp = 45.0_f64.to_radians();         // Argument of perigee (rad)
    let nu = 90.0_f64.to_radians();           // True anomaly (rad)

    // Convert to Cartesian state
    let oe = na::SVector::<f64, 6>::new(a, e, i, raan, argp, nu);
    let state = bh::state_koe_to_eci(oe, bh::AngleFormat::Radians);

    println!("GPS Satellite state (ECI):");
    println!("  Position: [{:.1}, {:.1}, {:.1}] km",
             state[0] / 1e3, state[1] / 1e3, state[2] / 1e3);
    println!("  Velocity: [{:.3}, {:.3}, {:.3}] km/s",
             state[3] / 1e3, state[4] / 1e3, state[5] / 1e3);

    let r = na::Vector3::new(state[0], state[1], state[2]);
    let v = na::Vector3::new(state[3], state[4], state[5]);
    let r_mag = r.norm();
    let v_mag = v.norm();

    println!("  Altitude: {:.1} km", (r_mag - bh::constants::R_EARTH) / 1e3);
    println!("  Speed: {:.3} km/s", v_mag / 1e3);

    // Compute relativistic acceleration
    let accel_rel = bh::orbit_dynamics::accel_relativity(state);

    println!("\nRelativistic acceleration (m/s²):");
    println!("  ax = {:.15}", accel_rel[0]);
    println!("  ay = {:.15}", accel_rel[1]);
    println!("  az = {:.15}", accel_rel[2]);
    println!("  Magnitude: {:.15e} m/s²", accel_rel.norm());

    // Compare to Newtonian point-mass gravity
    let accel_newton = bh::orbit_dynamics::accel_point_mass_gravity(
        r, na::Vector3::<f64>::zeros(), bh::constants::GM_EARTH
    );
    let accel_newton_mag = accel_newton.norm();

    println!("\nNewtonian gravity magnitude: {:.9} m/s²", accel_newton_mag);
    println!("Relativistic/Newtonian ratio: {:.6e}", accel_rel.norm() / accel_newton_mag);

    // Estimate accumulated position error if relativity is ignored
    // Using simple approximation: Δr ≈ 0.5 * a * t²
    // For 1 day propagation
    let one_day = 86400.0; // seconds
    let pos_error_1day = 0.5 * accel_rel.norm() * one_day * one_day;

    println!("\nApproximate position error if relativity ignored:");
    println!("  After 1 day: {:.3} m", pos_error_1day);
    println!("  After 1 week: {:.1} m", pos_error_1day * 7.0);

    // Compare to other perturbations at this altitude
    // J2 magnitude (approximate)
    let j2 = 1.08263e-3;
    let accel_j2_approx = 1.5 * j2 * bh::constants::GM_EARTH *
                          (bh::constants::R_EARTH / r_mag).powi(2) / (r_mag * r_mag);

    // Third-body (Sun, approximate)
    let accel_sun_approx = 5e-8; // Typical value for GPS altitude

    println!("\nRelative magnitude of perturbations at GPS altitude:");
    println!("  J2: ~{:.6e} m/s²", accel_j2_approx);
    println!("  Sun: ~{:.6e} m/s²", accel_sun_approx);
    println!("  Relativity: {:.6e} m/s²", accel_rel.norm());
    println!("  Relativity/J2 ratio: {:.6e}", accel_rel.norm() / accel_j2_approx);

    // Expected output:
    // GPS Satellite state (ECI):
    //   Position: [-21864.6, -435.7, 15074.0] km
    //   Velocity: [-1.555, -2.730, -2.266] km/s
    //   Altitude: 20182.7 km
    //   Speed: 3.874 km/s

    // Relativistic acceleration (m/s²):
    //   ax = -0.000000000234510
    //   ay = -0.000000000007302
    //   az = 0.000000000158426
    //   Magnitude: 2.831022208577214e-10 m/s²

    // Newtonian gravity magnitude: 0.565009481 m/s²
    // Relativistic/Newtonian ratio: 5.010575e-10

    // Approximate position error if relativity ignored:
    //   After 1 day: 1.057 m
    //   After 1 week: 7.4 m

    // Relative magnitude of perturbations at GPS altitude:
    //   J2: ~5.290937e-05 m/s²
    //   Sun: ~5.000000e-08 m/s²
    //   Relativity: 2.831022e-10 m/s²
    //   Relativity/J2 ratio: 5.350701e-06
}

See Also

References

Montenbruck, O., & Gill, E. (2000). Satellite Orbits: Models, Methods, and Applications. Springer. Section 3.7: Relativistic Effects.