Documentation
¶
Overview ¶
Package planner implements trajectory prediction (predictor) and stubs for Phase 3 maneuver-library work (hohmann, lambert) that slip past v0.1.
Index ¶
- Variables
- func CaptureBurnDeltaV(vInfinity, muPlanet, rCapture float64) (float64, error)
- func EscapeBurnDeltaV(vInfinity, muPlanet, rPark float64) (float64, error)
- func HohmannTransfer(r1, r2, mu float64) (dv1, dv2, tTransfer float64, err error)
- func LambertSolve(r1, r2 orbital.Vec3, dt, mu float64) (v1, v2 orbital.Vec3, err error)
- func LambertSolveRev(r1, r2 orbital.Vec3, dt, mu float64, nRev int) (v1, v2 orbital.Vec3, err error)
- func PorkchopGrid(muSun float64, depState, arrState EphemerisFn, epoch0 float64, ...) [][]float64
- func PorkchopMinCell(grid [][]float64) (depIdx, tofIdx int, total float64, ok bool)
- func Predict(start physics.StateVector, mu, totalSeconds float64, samples int) []orbital.Vec3
- type EphemerisFn
- type TransferLeg
- type TransferNode
- type TransferPlan
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidOrbit = errors.New("planner: invalid orbit (r1, r2, mu must be > 0)")
ErrInvalidOrbit is returned when HohmannTransfer is asked to solve for a non-physical input (non-positive radius or mu).
var ErrNotImplemented = errors.New("planner: not implemented")
ErrNotImplemented is returned by planner entry points that are still stubbed (e.g. Lambert in v0.2).
Functions ¶
func CaptureBurnDeltaV ¶ added in v0.3.1
CaptureBurnDeltaV mirrors EscapeBurnDeltaV for arrival: Δv to drop from a hyperbolic approach (excess speed vInfinity) into a circular orbit of radius rCapture around the destination primary. By symmetry the magnitude equals EscapeBurnDeltaV; provided as a named helper so the transfer-plan layer reads naturally.
func EscapeBurnDeltaV ¶ added in v0.3.1
EscapeBurnDeltaV returns the prograde Δv that, applied at periapsis of a circular parking orbit of radius rPark around a primary with gravitational parameter muPlanet, yields a hyperbolic escape trajectory whose excess speed at infinity is vInfinity.
Patched-conic identity (vis-viva at hyperbolic periapsis):
v_peri² = v∞² + 2·µ/r_peri Δv = v_peri − v_circ
The result is in m/s (matching the SI used everywhere else in this repo). vInfinity is taken as a magnitude — direction is the caller's concern (typically aligned with the outbound asymptote, which the transfer-plan layer handles via Lambert).
func HohmannTransfer ¶
HohmannTransfer computes the two impulsive burns and transfer time for a circular-to-circular coplanar Hohmann transfer between orbital radii r1 and r2 around a primary with standard gravitational parameter mu. All SI units: r1, r2 in meters, mu in m^3/s^2.
Returned dv1 and dv2 are magnitudes (always ≥ 0). Direction is implicit in r1 vs r2: outbound (r2 > r1) → both burns prograde; inbound → both retrograde. tTransfer is the half-period of the transfer ellipse (time between burn 1 and burn 2).
func LambertSolve ¶
LambertSolve is the single-revolution (N=0) entry point to the Lambert solver. Kept for backward-compat with v0.3.0–v0.3.2 callers; new code should prefer LambertSolveRev with an explicit N.
func LambertSolveRev ¶ added in v0.3.3
func LambertSolveRev(r1, r2 orbital.Vec3, dt, mu float64, nRev int) (v1, v2 orbital.Vec3, err error)
LambertSolveRev solves Lambert's problem for an N-revolution transfer: given two position vectors, a time of flight, and a revolution count, find the velocity vectors that connect them on a Keplerian orbit completing exactly N full revs before reaching r2.
Algorithm: Curtis "Orbital Mechanics for Engineering Students" Algorithm 5.2 — universal-variables formulation, Newton-Raphson on z. For N-rev transfers the lower bound on z shifts to (2πN)² (each rev contributes (2π)² to the universal-variable domain); the bracket sweep starts just past that lower bound.
Single branch only — at N ≥ 1 there are typically two time-of-flight solutions per N (a "long" and "short" transfer separated by the minimum-energy critical z). This solver returns whichever branch the bracket sweep lands in first, which is adequate for the porkchop grid's coarse sampling. Multi-branch selection is a v0.4 polish item if it comes up.
func PorkchopGrid ¶ added in v0.3.3
func PorkchopGrid( muSun float64, depState, arrState EphemerisFn, epoch0 float64, depDays, tofDays []float64, muDep, rPark float64, muArr, rCapture float64, ) [][]float64
PorkchopGrid evaluates a grid of Lambert transfers and returns per- cell total Δv (departure + arrival, m/s). NaN marks cells where the Lambert solver failed to converge — the TUI can render those as "impossible" pixels.
The returned slice is indexed [tofIdx][depIdx] so rendering row-by- row in the TUI naturally walks TOF vertically and departure day horizontally.
- epoch0: sim-time in seconds at which depDays[0] is measured. The ephemeris is sampled at epoch0 + depDays[i]*86400 for departure and epoch0 + (depDays[i]+tofDays[j])*86400 for arrival.
- depState, arrState: body ephemerides (heliocentric r, v).
- muSun: gravitational parameter of the system primary.
- muDep, rPark: destination body μ + parking-orbit radius (for departure Δv via the patched-conic identity).
- muArr, rCapture: arrival body μ + capture-orbit radius.
func PorkchopMinCell ¶ added in v0.3.3
PorkchopMinCell scans a grid and returns the (depIdx, tofIdx, total) of the lowest-Δv non-NaN cell. ok=false if the entire grid is NaN.
func Predict ¶
Predict forward-integrates a shadow StateVector using Verlet, returning a slice of inertial (primary-relative) positions sampled at regular intervals. Used by the maneuver screen for its live preview line.
- start: initial state (post-burn). - mu: gravitational parameter of the primary. - totalSeconds: total sim-time horizon. - samples: number of points to return (inclusive of start).
Types ¶
type EphemerisFn ¶ added in v0.3.3
EphemerisFn returns the heliocentric (system-primary-centered) position and velocity of a body at the given sim-time epoch, in SI units (m, m/s). The planner package doesn't know about bodies/orbital elements — callers (typically sim.World) adapt their Kepler/ calculator machinery into this function type.
type TransferLeg ¶ added in v0.3.1
type TransferLeg int
TransferLeg names which end of a TransferPlan a node belongs to — helpful for HUDs and logging that want to show "departure" vs "arrival" without having to derive it from PrimaryID.
const ( LegDeparture TransferLeg = iota LegArrival )
type TransferNode ¶ added in v0.3.1
type TransferNode struct {
Leg TransferLeg
PrimaryID string // body whose frame the burn was planned in
DV float64 // m/s, magnitude
OffsetTime time.Duration // time after PlanTransfer returns when this fires
IsRetrograde bool // true → retrograde mode; false → prograde
}
TransferNode is a planner-layer description of a single burn that the sim layer will turn into a sim.ManeuverNode. We keep it free of any sim-package dependencies so planner stays a pure math/algorithms surface — sim.PlanTransfer adapts these into sim.ManeuverNodes.
type TransferPlan ¶ added in v0.3.1
type TransferPlan struct {
Departure TransferNode
Arrival TransferNode
TransferDt time.Duration // coast time (Departure → Arrival)
}
TransferPlan is the two-burn output of an auto-plant transfer. Departure fires at a parking-orbit periapsis around the origin primary; Arrival fires at the destination's SOI/circular-capture radius after the transfer ellipse coast.
func PlanHohmannTransfer ¶ added in v0.3.1
func PlanHohmannTransfer( muSun float64, rDeparture, rArrival float64, muDeparture, rPark float64, departureID string, muDestination, rCapture float64, destinationID string, ) (TransferPlan, error)
PlanHohmannTransfer constructs a Hohmann-style transfer plan from a circular parking orbit at radius rPark around a departure planet (helios distance rDeparture, gravitational parameter muDeparture) to a circular capture orbit at radius rCapture around a destination planet (helios distance rArrival, gravitational parameter muDestination), all heliocentric distances in the system primary's frame (mu = muSun).
Result Δv magnitudes are the patched-conic Hohmann values:
departure: v∞_dep = sqrt(µ_sun · (2/r_dep − 1/a_t)) − v_dep_orbit
Δv_dep = EscapeBurnDeltaV(v∞_dep, µ_planet, r_park)
arrival: v∞_arr = v_arr_orbit − sqrt(µ_sun · (2/r_arr − 1/a_t))
Δv_arr = CaptureBurnDeltaV(|v∞_arr|, µ_dest, r_capture)
PrimaryIDs are set so the sim layer can render frame-aware glyphs and the planner UI can label the legs. Phasing is *not* accounted for — both burns assume the destination planet is at the right place at the right time, which the v0.3.1 sandbox doesn't enforce. A porkchop-plot screen (deferred to v0.3.2) is the natural next step.
func PlanLambertTransfer ¶ added in v0.4.1
func PlanLambertTransfer( muSun float64, rDep, vDepBody orbital.Vec3, rArr, vArrBody orbital.Vec3, tof float64, muDeparture, rPark float64, departureID string, muDestination, rCapture float64, destinationID string, depOffset time.Duration, ) (TransferPlan, error)
PlanLambertTransfer builds a two-burn transfer for an arbitrary (departure-time, time-of-flight) pair using a single-rev Lambert solve for the heliocentric coast. Unlike PlanHohmannTransfer which assumes 180° opposition geometry, this supports off-Hohmann launch windows — the same geometry the porkchop grid scores, so Enter-to- plant from the porkchop cursor is a direct call-through.
Inputs: heliocentric state of departure body at t_dep, heliocentric state of arrival body at t_dep + tof, transfer TOF in seconds, plus the parking / capture orbit parameters used for the patched-conic Δv identity (matching PlanHohmannTransfer + PorkchopGrid).
depOffset is the wall-clock delay from "now" (sim-time at planning) until the departure burn; it becomes the Departure node's OffsetTime. The Arrival node's OffsetTime is depOffset + tof.
Retrograde flags follow the same outbound/inbound rule as PlanHohmannTransfer: outbound (|rArr| > |rDep|) gets a prograde departure + retrograde arrival; inbound flips both. Lambert geometry varies more than Hohmann's 180° opposition, but the radius-based sign captures the common case well enough for the porkchop cursor and we can revisit if off-Hohmann arrivals need a sharper rule.