Inhaltsverzeichnis

std.astro.orbit — Bahnmechanik

import std.astro.orbit;

Vis-Viva und alles, was daraus folgt: Geschwindigkeiten, Energie, Bahnelemente aus einem Zustand, Hohmann-Transfer, Fluchtbahnen und Ebenenänderungen. Alle Winkel in Radiant, alle Längen in Metern.

std.astro (Übersicht) · std.astro.state · std.astro.insertion


1. Zentralkörper

Die Werte stehen als Funktionen, nicht als Konstanten — so sind sie in Ausdrücken überall verwendbar.

Funktion Wert Einheit
AMuEarth() 3.986004418e14 m³/s²
AMuSun() 1.32712440018e20 m³/s²
AMuMoon() 4.902800118e12 m³/s²
AMuMars() 4.2828372e13 m³/s²
ARadiusEarth() 6378137.0 m (Äquator)
ARadiusMoon() 1737400.0 m
ARadiusMars() 3396200.0 m
AGravConstant() 6.6743e−11 m³/(kg·s²)
Funktion Rückgabe Bedeutung
AMuFromMass(m) f64 G · m für einen Körper, der oben nicht steht
ASurfaceGravity(mu, R) f64 [m/s²] mu/R² — für die Erde 9.7983 (am Äquator, ohne Fliehkraft)

2. Geschwindigkeiten

Funktion Rückgabe Bedeutung NaN wenn
AVisViva(mu, r, a) f64 [m/s] v² = mu·(2/r − 1/a) — die Gleichung, aus der fast alles folgt mu≤0, r≤0, a=0 oder Radikand < 0 (Ort liegt gar nicht auf der Bahn)
ACircularSpeed(mu, r) f64 Kreisbahn, der Sonderfall a = r mu≤0 oder r≤0
AEscapeSpeed(mu, r) f64 Bahnenergie wird 0; immer √2 mal Kreisbahntempo dito

3. Flucht und Hyperbelbahn

Funktion Rückgabe Bedeutung
AHyperbolicExcess(mu, r, v) f64 [m/s] v_∞ — was vom Tempo unendlich weit draußen übrig bleibt. NaN, wenn v unter der Fluchtgeschwindigkeit liegt
AC3(mu, r, v) f64 [m²/s²] charakteristische Energie = v_∞² = 2E; anders als v_∞ auch für gebundene Bahnen definiert und dann negativ
AInjectionSpeed(mu, r, vInf) f64 welches Tempo am Ort r ein gewünschtes v_∞ ergibt: √(v_∞² + 2mu/r)
AEscapeDv(mu, r, vInf) f64 Schub aus der Kreisbahn auf dieses v_∞; vInf = 0 ergibt (√2−1)·v_kreis
ATurnAngle(e) f64 [rad] Ablenkung einer Vorbeiflugbahn: sin(δ/2) = 1/e. NaN für e ≤ 1
AImpactParameter(a, e) f64 [m] b = |a|·√(e²−1) — Abstand, in dem der Körper ohne Schwerkraft vorbeigeflogen wäre
AFlybyPeriapsis(mu, vInf, b) f64 [m] nächster Abstand eines Vorbeiflugs. Ob er unter dem Körperradius liegt (Einschlag), prüft der Aufrufer
 
Drei Verwechslungen, die die Unit im Quelltext ausdrücklich benennt: Die Fluchtgeschwindigkeit ist ein Betrag ohne Richtung; sie gilt für diesen Zentralkörper (wer die Erde mit 11.2 km/s verlässt, steht danach in einer Sonnenbahn); und sie gilt für den Stoß — ein Antrieb mit kleinem Schub über Stunden braucht mehr.

AInjectionSpeed ist zugleich die Formel hinter dem Oberth-Effekt: tief im Schwerefeld ist der Zuschlag für dasselbe v_∞ viel kleiner, weil unter der Wurzel der große Term 2mu/r steht.

4. Energie, Halbachse, Umlaufzeit

Funktion Rückgabe Bedeutung
AEnergy(mu, r, v) f64 [J/kg] v²/2 − mu/r. Negativ = gebunden, 0 = Parabel, positiv = Hyperbel
ASemiMajorAxis(mu, r, v) f64 [m] −mu/(2E); NaN bei E = 0 — die Parabel hat keine endliche Halbachse
APeriod(mu, a) f64 [s] 2π√(a³/mu), drittes Keplersches Gesetz; NaN für a ≤ 0
ASemiMajorFromPeriod(mu, T) f64 [m] Umkehrung — für sonnensynchrone und geostationäre Auslegung

5. Bahnelemente aus einem Zustand

Funktion Rückgabe Bedeutung
AEccentricityVec(mu, s) AVec3 Laplace-Runge-Lenz-Vektor; zeigt zum Perizentrum
AEccentricity(mu, s) f64 dessen Betrag
AInclination(s) f64 [rad] 0…π; über π/2 heißt rückläufig. NaN bei gerader Bahn
ARaan(s) f64 [rad] Rektaszension des aufsteigenden Knotens, 0…2π. NaN bei äquatorialer Bahn — dort gibt es keinen Knoten, und 0 wäre ein gültiger Winkel
ACircularThreshold() f64 1e−12
AIsCircular(mu, s) bool Exzentrizität unter der Schwelle
ATrueAnomaly(mu, s) f64 [rad] Winkel vom Perizentrum zum Ort, 0…2π; das Vorzeichen entscheidet die Radialgeschwindigkeit. NaN auf der Kreisbahn
APeriapsis(a, e) · AApoapsis(a, e) f64 [m] a(1∓e); NaN für e ≥ 1
 
Warum es eine Kreisbahn-Schwelle gibt. Eine rechnerisch exakte Kreisbahn existiert nicht: der Exzentrizitätsvektor einer aus dem Kreistempo gebauten Bahn hat den Betrag ~1.2e−16 — Rundungsrauschen, aber nicht 0, und seine Richtung ist dabei völlig beliebig. Wer daraus eine wahre Anomalie rechnet, bekommt eine Zahl ohne Bedeutung. 1e−12 trennt sauber: Rundung liegt vier Größenordnungen darunter, die kleinste praktisch gemeinte Exzentrizität darüber.

6. Hohmann-Transfer

Funktion Rückgabe Bedeutung
AHohmannDv1(mu, r1, r2) f64 erster Schub (im Ausgangsorbit), vorzeichenbehaftet
AHohmannDv2(mu, r1, r2) f64 zweiter Schub (im Zielorbit), vorzeichenbehaftet
AHohmannDv(mu, r1, r2) f64 Summe der Beträge
AHohmannTime(mu, r1, r2) f64 [s] halbe Umlaufzeit der Transferellipse
AHohmannPhaseAngle(mu, r1, r2) f64 [rad] Voraushaltewinkel: wie weit das Ziel beim Start vorausstehen muss
 
Zwei Grenzen, die die Unit selbst benennt:

* Beim Absenken sind beide Einzelwerte negativ. Wer sie vorzeichenbehaftet addiert, bekommt den Treibstoffbedarf mit falschem Vorzeichen — deshalb summiert AHohmannDv die Beträge.
* Für r2/r1 > 11.94 ist der bielliptische Transfer günstiger. Diese Unit rechnet ihn nicht; sie liefert dann einen richtigen, aber nicht den besten Wert.

7. Ebenenänderung

Funktion Rückgabe Bedeutung
APlaneChangeDv(v, dInc) f64 2v·sin(Δi/2) — reine Inklinationsänderung
ACombinedDv(v1, v2, dInc) f64 Tempo und Ebene in einem Schub (Kosinussatz); nie teurer als beide nacheinander

Bei 7.7 km/s kostet ein Grad rund 135 m/s. Deshalb wird die Ebene im Apozentrum gedreht, wo das Tempo am kleinsten ist.

8. Abplattung: Knotendrift, Apsidendrift, sonnensynchrone Bahnen

Die Unit rechnet sonst mit einem kugelsymmetrischen Zentralkörper. Dieser Abschnitt ist die einzige Ausnahme: er berücksichtigt die Abplattung über den Koeffizienten J2 — den Term, ohne den sich sonnensynchrone Bahnen, Molniya und Tundra nicht erklären lassen (#1988).

Funktion Rückgabe Bedeutung
AJ2Earth(), AJ2Mars(), AJ2Moon() f64 zweiter zonaler Koeffizient; Erde 1.08263·10⁻³
ANodalDrift(mu, j2, rBody, a, e, inc) f64 Knotendrift in rad/s; negativ bei prograden Bahnen (Knoten wandert nach Westen)
AApsidalDrift(mu, j2, rBody, a, e, inc) f64 Drehung der Apsidenlinie in rad/s
ACriticalInclination() f64 63.4349° in Radiant — dort verschwindet der Apsidendrift
ACriticalInclinationRetro() f64 die zweite Lösung, 116.5651°
ASunSyncDrift() f64 Solldrift einer sonnensynchronen Bahn: 360° je tropischem Jahr
ASunSyncInclination(mu, j2, rBody, a, e) f64 Neigung, die diese Drift erzeugt; Fehlerwert, wenn es bei dieser Höhe keine gibt

Drei Punkte, an denen die Formeln anders sind, als man sie im Kopf hat:

Ein Zahlenbeispiel steht auf der Seite Bahntypen: 700 km Bahnhöhe verlangen 98.188°, und die ISS-Bahnebene wandert 5.0023 Grad pro Tag nach Westen.

Auf demselben Term bauen drei weitere Funktionsgruppen auf:

Funktion Rückgabe Bedeutung
ANodalPeriod(mu, j2, rBody, a, e, inc) f64 Umlaufzeit von Knoten zu Knoten — nicht dasselbe wie APeriod
ARepeatCycleFromSma(mu, j2, rBody, omegaBody, a, e, inc) f64 Umläufe pro Tag einer gegebenen Bahn
ASmaFromRepeatCycle(mu, j2, rBody, omegaBody, k, m, e, inc) f64 Halbachse für k Umläufe in m Tagen
ADecayPerRev(rho, ballisticCoeff, a) f64 Höhenverlust je Umlauf durch Luftwiderstand
ADecayRate(mu, rho, ballisticCoeff, a) f64 derselbe Verlust als Rate
AJ3Earth() f64 dritter zonaler Koeffizient, −2.532·10⁻⁶
AFrozenArgPerigee() f64 90° — die einzige Lage, in der ein Perigäum stehenbleibt
AFrozenEccentricity(j2, j3, rBody, a, inc) f64 Exzentrizität, bei der J2 und J3 sich aufheben
AIsFrozen(j2, j3, rBody, a, e, inc, argP, toleranz) bool Prüfung einer gegebenen Bahn

Zeitabhängige Rechnungen stehen bewusst nicht hier, sondern in std.astro.groundtrack: alles in dieser Unit ist zeitlos, eine Bahn hat eine Periode, aber keinen Zeitpunkt.

9. Die Parameter im Einzelnen

Name Bedeutung Einheit Zu beachten
mu Gravitationsparameter G·M des Zentralkörpers m³/s² AMuEarth() & Co.; für einen anderen Körper AMuFromMass(m). Muss > 0 sein
r Abstand vom Mittelpunkt, nicht Höhe über der Oberfläche m ARadiusEarth() + hoehe. Muss > 0 sein
a große Halbachse; bei der Kreisbahn a = r, bei der Hyperbel negativ m a = 0 ist ungültig (Parabel)
e numerische Exzentrizität: 0 Kreis, <1 Ellipse, 1 Parabel, >1 Hyperbel dimensionslos APeriapsis/AApoapsis verlangen e < 1, ATurnAngle/AImpactParameter verlangen e > 1
v Bahngeschwindigkeit am Ort r m/s
vInf hyperbolische Überschussgeschwindigkeit „im Unendlichen„ m/s 0 ist gültig (Parabel)
r1, r2 Radien der Ausgangs- und der Zielkreisbahn beim Hohmann-Transfer m r2 < r1 ist erlaubt: das Absenken
dInc Änderung der Bahnneigung Radiant Grad × Pi()/180.0
T Umlaufzeit bei ASemiMajorFromPeriod s für geostationär die siderische 86164 s, nicht 86400
b Stoßparameter eines Vorbeiflugs m
s Zustand aus std.astro.state muss AStateValid bestehen
 
Drei Verwechslungen, die Zahlen liefern statt Fehler:

* Höhe statt Radius. ACircularSpeed(mu, 400000.0) rechnet eine Bahn 400 km vom Erdmittelpunkt — tief im Inneren. Das Ergebnis (31.6 km/s) sieht aus wie eine Geschwindigkeit.
* Grad statt Radiant. APlaneChangeDv(7725.8, 30.0) liest 30 als Radiant, also knapp fünf volle Umdrehungen. Alle Winkel dieser Unit sind Radiant.
* 86400 statt 86164 s. Der geostationäre Radius folgt aus dem Sterntag; mit dem Sonnentag kommen rund 42 240 km statt 42 164 km heraus — 76 km daneben.

10. Beispiel: Kreisbahn und Transfer

import std.astro.state;
import std.astro.orbit;
import std.io;

fn zeig(n: pchar, v: f64, d: int64): void { Print(n); PrintLn(FloatToStr(v, d)); }
fn BI(b: bool): int64 { if (b) { return 1; } return 0; }

fn main(): int64 {
    var mu:  f64 := AMuEarth();
    var leo: f64 := 6678000.0;      // 300 km Hoehe
    var geo: f64 := 42164000.0;

    zeig("g0 Oberflaeche     : ", ASurfaceGravity(mu, ARadiusEarth()), 4);
    zeig("v_kreis LEO        : ", ACircularSpeed(mu, leo), 2);
    zeig("v_flucht LEO       : ", AEscapeSpeed(mu, leo), 2);
    zeig("Energie LEO        : ", AEnergy(mu, leo, ACircularSpeed(mu, leo)), 1);
    zeig("Umlaufzeit min     : ", APeriod(mu, leo) / 60.0, 2);
    zeig("a aus T (siderisch): ", ASemiMajorFromPeriod(mu, 86164.0), 1);
    zeig("Hohmann dv1        : ", AHohmannDv1(mu, leo, geo), 1);
    zeig("Hohmann dv2        : ", AHohmannDv2(mu, leo, geo), 1);
    zeig("Hohmann dv gesamt  : ", AHohmannDv(mu, leo, geo), 1);
    zeig("Hohmann t Stunden  : ", AHohmannTime(mu, leo, geo) / 3600.0, 2);
    zeig("Ebenenaend. 1 Grad : ", APlaneChangeDv(7725.8, 0.017453292519943295), 1);
    zeig("v_inf bei 11 km/s  : ", AHyperbolicExcess(mu, leo, 11000.0), 1);

    Print("v_inf zu langsam   : ");
    PrintLn(IntToStr(BI(AIsError(AHyperbolicExcess(mu, leo, 7000.0)))));
    return 0;
}

g0 Oberflaeche     : 9.7983
v_kreis LEO        : 7725.84
v_flucht LEO       : 10925.99
Energie LEO        : -29844297.8
Umlaufzeit min     : 90.52
a aus T (siderisch): 42164138.8
Hohmann dv1        : 2425.8
Hohmann dv2        : 1466.8
Hohmann dv gesamt  : 3892.6
Hohmann t Stunden  : 5.28
Ebenenaend. 1 Grad : 134.8
v_inf bei 11 km/s  : 1273.9
v_inf zu langsam   : 1

Die letzte Zeile ist der wichtigste Teil des Beispiels: 7 km/s reichen in 300 km Höhe nicht zur Flucht, und die Funktion sagt das mit NaN — statt 0 zurückzugeben, was wie eine gerade noch erreichte Flucht aussähe.

11. Beispiel: Bahnelemente einer Ellipse

Aus einem einzigen Zustand im Perigäum lässt sich die ganze Bahn ablesen — hier eine Molniya-artige Bahn (Perigäum 600 km, Apogäum 39 900 km, 63.4 Grad Neigung):

import std.astro.state;
import std.astro.orbit;
import std.math;
import std.io;

fn zeig(n: pchar, v: f64, d: int64): void { Print(n); PrintLn(FloatToStr(v, d)); }

fn main(): int64 {
    var mu:  f64 := AMuEarth();
    var rad: f64 := Pi() / 180.0;

    var rp: f64 := ARadiusEarth() +   600000.0;
    var ra: f64 := ARadiusEarth() + 39900000.0;
    var a:  f64 := (rp + ra) / 2.0;
    var vp: f64 := AVisViva(mu, rp, a);        // Tempo im Perigaeum
    var inc: f64 := 63.4 * rad;

    // Im Perigaeum steht die Geschwindigkeit senkrecht auf dem Ort
    var s: AState := AMakeState(rp, 0.0, 0.0,  0.0, vp * CosF64(inc), vp * SinF64(inc));

    zeig("Tempo Perigaeum    : ", ASpeed(s), 1);
    zeig("Halbachse km       : ", ASemiMajorAxis(mu, ARadius(s), ASpeed(s)) / 1000.0, 1);
    zeig("Exzentrizitaet     : ", AEccentricity(mu, s), 5);
    zeig("Inklination Grad   : ", AInclination(s) / rad, 2);
    zeig("Umlaufzeit h       : ", APeriod(mu, a) / 3600.0, 3);
    zeig("Perigaeum km       : ", APeriapsis(a, AEccentricity(mu, s)) / 1000.0, 1);
    zeig("Apogaeum km        : ", AApoapsis(a, AEccentricity(mu, s)) / 1000.0, 1);
    zeig("wahre Anomalie Grad: ", ATrueAnomaly(mu, s) / rad, 2);
    zeig("Tempo Apogaeum     : ", AVisViva(mu, ra, a), 1);
    return 0;
}

Tempo Perigaeum    : 9963.6
Halbachse km       : 26628.1
Exzentrizitaet     : 0.73794
Inklination Grad   : 63.40
Umlaufzeit h       : 12.012
Perigaeum km       : 6978.1
Apogaeum km        : 46278.1
wahre Anomalie Grad: 0.00
Tempo Apogaeum     : 1502.4

Zwei Proben, die zeigen, dass die Rechnung geschlossen ist: die zurückgerechneten Peri- und Apozentrumsabstände treffen die Eingabe wieder (6978 km = 6378 + 600, 46278 km = 6378 + 39900), und die wahre Anomalie ist 0 — der Zustand steht ja im Perigäum.

Die Umlaufzeit von 12.012 h ist der Grund für diese Bahnfamilie: zwei Umläufe je Sterntag, mit langem Verweilen über der Nordhalbkugel. Das Tempo unterscheidet sich dabei um den Faktor 6.6 zwischen Perigäum (9964 m/s) und Apogäum (1502 m/s) — deshalb sind Manöver im Apogäum billig.


Letzte Aktualisierung: 2026-08-31 — Parametertabelle mit den drei häufigen Verwechslungen (Höhe/Radius, Grad/Radiant, Sonnentag/Sterntag) und ein zweites Beispiel zu den Bahnelementen ergänzt; beide Beispiele mit lyxc 1.1.15B gebaut und ausgeführt.

Zuvor 2026-08-31 — Seite neu angelegt aus std/astro/orbit.lyx (PR #1890).