Surface Target Mode
Issue: #758
Summary
Add a surface_retrograde attitude mode that orients the ship’s engine against its surface-relative velocity vector. This accounts for body rotation, unlike orbital retrograde. A landing HUD overlay shows descent rate, horizontal speed, and time to impact when close to a body’s surface.
Attitude Mode: Surface Retrograde
Keybinding
- Shift+M key: engage surface retrograde attitude hold
- H key: disengage (existing behavior)
Physics
Surface-relative velocity subtracts the body’s rotational velocity at the ship’s position:
omega_body = (2*pi / rotation_period) * spin_axis_icrf
v_rotation = cross(omega_body, r_ship_relative)
v_surface = v_ship_relative - v_rotation
target_direction = -normalize(v_surface)
Where spin_axis_icrf is the body’s north pole direction in ICRF, computed from axial tilt:
spin_axis_icrf = [0, sin(axial_tilt), cos(axial_tilt)]
The attitude controller aligns ship +Z (forward) with this direction, using the existing PD controller. Below 0.1 m/s surface-relative speed, holds the last valid direction.
Difference from Orbital Retrograde
At Luna’s surface, rotational velocity is ~4.6 m/s (27.3-day period). This is negligible at orbital speeds (~1.68 km/s) but significant during final descent when ship speed approaches zero. Surface retrograde properly zeroes ground-relative motion for a soft landing.
Landing HUD
When the ship is within 50 km AGL of any body, a landing HUD overlay appears automatically (independent of attitude mode):
| Indicator | Label | Source |
|---|---|---|
| Descent rate | VSPD | Radial velocity component toward surface (positive = descending) |
| Horizontal speed | HSPD | Tangential velocity relative to body center |
| Time to impact | TTI | AGL / descent_rate (linear estimate, shown when descending) |
| Altitude AGL | AGL | Already exists in orbit diagram |
Display format:
- VSPD:
↓ X.X m/s(descending) or↑ X.X m/s(ascending) - HSPD:
X.X m/s - TTI:
Xm XsorXswhen < 60s,--when ascending
The landing HUD is a lightweight HTML overlay, not added to the orbit diagram SVG.
Implementation
Proto
Add ATTITUDE_SURFACE_RETROGRADE = 15 to AttitudeMode enum in physics.proto (all copies).
Physics Service
models.py: AddSURFACE_RETROGRADEtoAttitudeModeandTRACKING_MODESattitude.py: Add_compute_body_spin_vector(ref_body)helper andSURFACE_RETROGRADEcase incompute_attitude_target_direction()grpc_server.py: Add proto ↔ model mappings
API Gateway
websocket.py: Addattitude_surface_retrogrademessage handler
Web Client
network.js: AddsendAttitudeSurfaceRetrograde()controlInput.js: Add M key → surface_retrograde mappingcockpitView.js: Wire into_attitudeSenders, init landing HUDcockpitLandingHud.js: New module —computeLandingData()(pure logic, tested),updateLandingHud()(DOM display)cockpitOrbitDiagram.js: CallsupdateLandingHud()alongside AGL computationindex.html: Landing HUD element (#landing-hud) with CSS styles
Bodies
Works for all bodies. Uses terrain elevation when available (Luna), mean radius as fallback.