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.
AInjectionSpeedist zugleich die Formel hinter dem Oberth-Effekt: tief im Schwerefeld ist der Zuschlag für dasselbev_∞viel kleiner, weil unter der Wurzel der große Term2mu/rsteht.
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 summiertAHohmannDvdie Beträge.
* Fürr2/r1 > 11.94ist 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:
- In der Driftformel steht der Halbparameter
p = a(1−e²), nicht die große Halbachse. Bei einer Kreisbahn ist das dasselbe, bei Molniya mite = 0.74unterscheidet es sich um mehr als das Doppelte. - Sonnensynchron heißt tropisches Jahr (365.2422 Tage), also synchron mit der Sonne und nicht mit den Fixsternen. Die Bahn heißt nach dem, womit sie mitläuft.
- Eine sonnensynchrone Bahn ist zwangsläufig rückläufig. Die verlangte Drift ist positiv, also muss der Kosinus der Neigung negativ sein. Deshalb liegen alle SSO-Neigungen über 90°.
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 |
- Wiederholbahnen (#1993) schließen sich, wenn die Nodalperiode, die Erddrehung und die Knotendrift zusammenpassen.
ASmaFromRepeatCycleliefert für den Landsat-Zyklus 233/16 eine Bahnhöhe von 700.3 km. - Bahnverfall (#1994) verbindet die Luftdichte mit dem ballistischen Koeffizienten aus std.astro.entry. Die Dichte ist ein Parameter, kein Modell — sie kommt vom Aufrufer.
- Frozen Orbits (#1996) brauchen J3 zusätzlich zu J2: J2 dreht das Perigäum, J3 zieht es zurück, und bei genau einer Exzentrizität heben sich beide auf. Für 800 km bei 98.6° sind das 0.0010274.
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).
