Gravity Gradient Tether with Tidal Pumping (#961)

Problem

Stations in orbits around moons experience tidal energy drift from the parent planet’s gravity gradient. At Io (orbiting Jupiter at 17.3 km/s), this drift is ~0.03-0.05%/orbit, eventually causing orbit decay and surface impact. The Encke integration (#960) reduces numerical drift but cannot eliminate the physical tidal perturbation.

Solution

A gravity gradient tether provides two functions:

  1. Attitude stabilization — the tidal torque on an extended mass aligns the station radially (gravity gradient stabilization)
  2. Orbital correction — oscillating the tether length in phase with the orbital period exchanges energy with the tidal field (tidal pumping), counteracting secular drift

Physics

Gravity gradient attitude

A tether of length L with tip mass m_tip in a gravity field creates a restoring torque that aligns the tether along the local vertical (radial direction from the parent body). The station’s attitude quaternion is set kinematically each tick — no angular velocity dynamics needed.

Tidal pumping

The station records its target semi-major axis a₀ at spawn. Each tick, the controller:

  1. Computes current specific orbital energy: E = ½v² - μ/r (relative to parent body)

  2. Computes target energy: E₀ = -μ/(2a₀)

  3. Computes energy error: δE = E - E₀

  4. Applies a radial velocity correction: δv = clamp(-K × δE, ±δv_max)

    where K is a proportional gain and δv_max is the tether’s physical capability per tick.

Tether capability

The maximum correction per tick comes from the tidal force differential across the tether:

F_tidal = m_tip × (2μ/r³) × (L/2)

δv_max = F_tidal / m_station × dt

where 2μ/r³ is the tidal gradient from the parent body at the station’s orbital radius r.

Auto-sizing

At spawn, tether parameters are computed from the local environment:

  • Length: L = clamp(0.01 × r_orbit, 100m, 10km)
  • Tip mass: m_tip = 0.05 × m_station (per tip)
  • Target SMA: a₀ = r_orbit (circular orbit at spawn)

Design

Scope

  • Stations only (not jump gates or ships)
  • Orbital force correction only (no attitude dynamics — kinematic radial alignment each tick)
  • Telemetry visible in station info panel

Station model fields

  • tether_length (float, meters, set at spawn)
  • tether_tip_mass (float, kg, set at spawn)
  • target_sma (float, meters, set at spawn)
  • tether_energy_error (float, J/kg, updated each tick)
  • tether_correction_dv (float, m/s, updated each tick)

Integration

In update_station(), after leapfrog integration:

  1. Find parent body from station.parent_body
  2. Apply tidal pumping correction (proportional controller)
  3. Orient attitude to local vertical

Rendering

  • Station mesh oriented along radial (gravity gradient alignment)
  • Tether rendered as a billboarded mesh ribbon (16 segments × 2 vertices each = triangle strip) with transverse standing-wave oscillation perpendicular to the tether axis, simulating real tether dynamics. THREE.Line was replaced because it renders as 1px on Chrome’s ANGLE backend — invisible on HiDPI displays (#1007).
    • Ribbon half-width: 3m (6m total physical width)
    • Ribbon orientation: perpendicular to camera each frame via cross(tetherAxis, viewDirection)
    • Two superimposed sine modes at different frequencies for organic, non-repeating motion
    • Amplitude = 1.5% of tether half-length
    • DoubleSide rendering, frustumCulled: false
  • Tension color: base orange (0xff8844) shifts toward cyan (0x44ddff) proportional to |tether_energy_error|, showing when tidal pumping is actively correcting. Lerp factor = clamp(|error| / 100, 0, 1).
  • Structure mesh loader retries failed GLB loads every 5 seconds (up to 3 attempts). Without retry, a transient mesh-service failure leaves the station as a permanent placeholder with no tether (#1007).
  • Docking tether also rendered as catenary (16 segments) with sag toward the parent body (scene origin); sag magnitude = 8% of tether distance
  • Telemetry in station info panel: tether length, energy error, correction delta-v

Config

  • tether_pumping_gain: 1e-6 (m/s)/(J/kg)
  • tether_max_correction_per_tick: 0.001 m/s

Files

  • models.py — tether fields on Station
  • nbody.py — apply_tether_tidal_pumping(), attitude in update_station()
  • spawning.py — auto-size tether, compute target SMA
  • redis_state.py — serialize tether fields
  • config.py — tether constants
  • grpc_server.py, physics.proto — new proto fields
  • ws_state_broadcast.py — include tether in broadcast
  • cockpitExtrapolation.js — tether line rendering

Back to top

Galaxy — Kubernetes-based multiplayer space game

This site uses Just the Docs, a documentation theme for Jekyll.