Documentation
¶
Overview ¶
Package physics implements the spacecraft propagation layer: state vectors, integrators (Verlet + RK4), and patched-conic SOI handling.
Index ¶
- func Accel(r orbital.Vec3, mu float64) orbital.Vec3
- func GravityOnly(mu float64) func(r, v orbital.Vec3, t float64) orbital.Vec3
- func SOIRadius(body, primary bodies.CelestialBody) float64
- func SemimajorAxis(s StateVector, mu float64) float64
- func SpecificEnergy(s StateVector, mu float64) float64
- func SurfaceGravity(b bodies.CelestialBody) float64
- type Primary
- type StateVector
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Accel ¶
Accel returns the two-body gravitational acceleration on the spacecraft due to the primary with gravitational parameter mu. Direction is toward the primary (origin in the relative frame).
func GravityOnly ¶
GravityOnly wraps Accel as an RK4-compatible accelFn closure.
func SOIRadius ¶
func SOIRadius(body, primary bodies.CelestialBody) float64
SOIRadius returns the sphere-of-influence radius of `body` orbiting `primary`, in meters. SOI = a_body * (m_body / m_primary)^(2/5). Returns 0 for bodies without orbital data (e.g. the system primary itself).
func SemimajorAxis ¶
func SemimajorAxis(s StateVector, mu float64) float64
SemimajorAxis returns the orbit's semimajor axis a = -μ/(2ε) for bound orbits; NaN for parabolic (ε≈0) and negative for hyperbolic trajectories.
func SpecificEnergy ¶
func SpecificEnergy(s StateVector, mu float64) float64
SpecificEnergy returns the two-body orbital specific energy ε = v²/2 − μ/r (J/kg). Used as an invariant by energy-conservation tests.
func SurfaceGravity ¶
func SurfaceGravity(b bodies.CelestialBody) float64
SurfaceGravity returns the magnitude of gravitational acceleration at the body's mean radius (m/s²). Diagnostic helper for tests.
Types ¶
type Primary ¶
type Primary struct {
Body bodies.CelestialBody
Inertial orbital.Vec3
}
Primary captures which body the spacecraft is currently bound to and its inertial position at the relevant sim-time. Physics operates relative to the primary; world code looks this up every few ticks.
func FindPrimary ¶
func FindPrimary( system bodies.System, rInertial orbital.Vec3, positions map[string]orbital.Vec3, ) Primary
FindPrimary picks the best primary for a spacecraft at inertial position rInertial. Rule: smallest SOI that contains the spacecraft wins; default to the system primary if none contain it.
Each body's SOI is computed against its actual parent (v0.5.0+): planets against the system primary, moons against their planet (per CelestialBody.ParentID). Pre-v0.5.0 every body's SOI was computed against the system primary, which silently treated moons as planets — a Luna at 384k km from Earth had its SOI sized as if it orbited the Sun at 384k km, an absurd value. Fixing this is what enables the Earth-and-Luna nested-SOI walk.
type StateVector ¶
type StateVector struct {
R orbital.Vec3 // position relative to primary
V orbital.Vec3 // velocity relative to primary
M float64 // current total mass (wet)
}
StateVector is the spacecraft's kinematic state relative to the current primary body (see patched-conic model in plan §Phase 1). All SI: position in m, velocity in m/s, mass in kg.
func KeplerStep ¶ added in v0.4.3
func KeplerStep(s StateVector, mu, dt float64) (StateVector, bool)
KeplerStep advances a state vector by dt using analytic Kepler propagation. Snapshots orbital elements, advances mean anomaly by n·dt, and reconstructs (r, v) from the new true anomaly. Exact (modulo Newton iteration tolerance in SolveKepler) — no numerical drift, regardless of dt size relative to orbital period.
Returns ok=false for hyperbolic / parabolic orbits (e ≥ 1) and degenerate inputs; the caller falls back to numerical integration (Verlet). Used for the v0.4.3 "warp lock": when warp > 1× and no active burn, integrateSpacecraft takes one KeplerStep per tick instead of looping Verlet sub-steps that drift eccentricity over many orbits.
SOI handling is the caller's responsibility: KeplerStep does not detect or rebase across primary boundaries. integrateSpacecraft guards against SOI crossings by checking apo < primary's SOI before taking the analytic path.
func Rebase ¶
func Rebase( s StateVector, oldPrimaryInertial, newPrimaryInertial orbital.Vec3, dvInertial orbital.Vec3, ) StateVector
Rebase converts a state vector expressed relative to oldPrimary into one expressed relative to newPrimary. Both primaries' inertial positions are required. Velocity transforms by vector subtraction only if the primaries have non-zero relative velocity; in v0.1 planets are on fixed Keplerian tracks with velocities computed on demand, so we accept a relative-velocity parameter (dvInertial = v_oldPrimary - v_newPrimary).
func StepRK4 ¶
func StepRK4( s StateVector, dt float64, accelFn func(r, v orbital.Vec3, t float64) orbital.Vec3, t float64, ) StateVector
StepRK4 advances a StateVector by dt using classical 4th-order Runge-Kutta. Not symplectic — energy drifts over long horizons — but handles non- conservative forces (thrust during a finite burn, drag) cleanly, which Verlet does not. Parked for Phase 2 burns per plan §Phase 1 rationale; until then, Verlet is the default integrator.
accelFn(r, v, t) lets callers inject an applied thrust on top of two-body gravity. For pure gravity, pass a closure that computes Accel(r, μ).
func StepVerlet ¶
func StepVerlet(s StateVector, mu, dt float64) StateVector
StepVerlet advances a StateVector by dt using the symplectic velocity- Verlet integrator. Single force evaluation per step (cheap under warp), conserves specific orbital energy over long horizons — see plan §Phase 1 rationale. Returns the new state; input is untouched.
The algorithm (for a = a(r) only, true for pure two-body gravity):
r' = r + v·dt + ½·a·dt² a' = Accel(r') v' = v + ½·(a + a')·dt