====== std.astro.groundtrack — Bodenspur ====== Diese Unit schließt ein einzelnes Glied: die Drehung vom Inertialsystem auf die drehende Erde. Vorne liegt [[lyx_-_programmiersprache:units:astro:state|std.astro.state]] mit dem Ortsvektor im **ECI**, hinten [[lyx_-_programmiersprache:units:geodesy:frames|std.geodesy.frames]] mit ''EcefToGeod''. Dazwischen fehlte die Drehung um den **Greenwich-Stundenwinkel** — und die ist der ganze Unterschied zwischen beiden Rahmen ([[https://github.com/SEOLizer/LyX-Compiler/issues/1995|#1995]]). → [[lyx_-_programmiersprache:units:astro|std.astro (Übersicht)]] · [[lyx_-_programmiersprache:units:astro:orbit|std.astro.orbit]] · [[lyx_-_programmiersprache:units:astro:state|std.astro.state]] · [[lyx_-_programmiersprache:units:geodesy:frames|std.geodesy.frames]] · [[lyx_-_programmiersprache:units:astro:bahntypen|Bahntypen]] ---- ===== 1. Warum eine eigene Unit ===== Der Grund ist die **Zeitachse**. Alles in ''std.astro.orbit'' rechnet zeitlos: eine Bahn hat eine Umlaufzeit, aber keinen Zeitpunkt. Sobald ein Datum ins Spiel kommt — und ohne Datum gibt es keinen Stundenwinkel —, ist das eine andere Art von Rechnung. Die Abhängigkeit zeigt außerdem bewusst **nicht** auf ''std.geodesy''. Die Unit liefert den Unterpunkt geozentrisch, also auf der Kugel, und den ECEF-Vektor. Wer die geodätische Breite auf dem Ellipsoid braucht, verkettet selbst mit ''EcefToGeod''. Der Unterschied ist nicht klein — bis zu 0.19 Grad in mittleren Breiten —, aber die Wahl gehört dem Aufrufer. ===== 2. Die Funktionen ===== ^ Funktion ^ Rückgabe ^ Bedeutung ^ | ''AJ2000()'' | ''f64'' | julianisches Datum der Epoche J2000.0 = 2 451 545.0 | | ''AJulianCenturies(jd)'' | ''f64'' | julianische Jahrhunderte seit J2000.0 | | ''AGmst(jd)'' | ''f64'' | Greenwich-Sternzeit als Winkel in **Radiant** | | ''AEciToEcef(v, gmst)'' | ''AVec3'' | Drehung ins erdfeste System | | ''AEcefToEci(v, gmst)'' | ''AVec3'' | die Gegenrichtung | | ''ASubPointLatitude(v)'' | ''f64'' | geozentrische Breite des Unterpunkts (aus dem ECI-Vektor) | | ''ASubPointLongitude(v, gmst)'' | ''f64'' | Länge des Unterpunkts | | ''ASubPointAltitude(v, rBody)'' | ''f64'' | Höhe über der Kugel | Die Breite braucht **keinen** Stundenwinkel: die Drehung geht um die z-Achse und lässt die Breite unberührt. Nur die Länge hängt an der Zeit. ===== 3. Die Bodenspur eines Umlaufs ===== Ein Satellit auf einer 400-km-Kreisbahn, Startpunkt auf der x-Achse des ECI, Epoche JD 2 460 000.5: ^ Zeit ^ GMST ^ Länge des Unterpunkts ^ | 0.0 min | 154.602° | −154.602° | | 23.1 min | 160.403° | −70.403° | | 46.3 min | 166.204° | 13.796° | | 69.4 min | 172.005° | 97.995° | | 92.6 min | 177.805° | −177.805° | Die letzte Zeile ist der ganze Punkt: nach einem vollen Umlauf steht der Satellit wieder über demselben //Inertialpunkt//, aber die Länge ist von −154.602° auf −177.805° gewandert. **23.2 Grad Westdrift je Umlauf** — die Erde hat sich in den 92.56 Minuten weitergedreht. Genau diese Drift muss eine [[lyx_-_programmiersprache:units:astro:bahntypen|Wiederholbahn]] so treffen, dass sie sich nach ganzen Tagen schließt. Zwei Proben stehen daneben: * Ein Vektor über dem Nordpol liefert **90.0°** Breite, unabhängig vom Stundenwinkel. * ''AEcefToEci(AEciToEcef(v, gmst), gmst)'' gibt denselben Vektor zurück — 6 778 137.0 m, auf den Meter. ===== 4. Das Programm ===== unit main; import std.astro.groundtrack; import std.astro.orbit; import std.astro.state; import std.math; import std.io; import std.string; fn f(v: f64, d: int64): pchar { return FloatToStr(v, d); } fn G(r: f64): f64 { return r * 180.0 / Pi(); } fn main(): int64 { // ISS-artige Bahn, 400 km, der Einfachheit halber in der Aequatorebene var r: f64 := ARadiusEarth() + 400000.0; var T: f64 := APeriod(AMuEarth(), r); var jd0: f64 := 2460000.5; PrintLn(StrConcat("Umlaufzeit: ", StrConcat(f(T / 60.0, 2), " min"))); PrintLn(""); PrintLn("Minute | GMST Grad | Laenge Grad"); var i: int64 := 0; while i <= 4 { var dt: f64 := (i as f64) * T / 4.0; var jd: f64 := jd0 + dt / 86400.0; var gmst: f64 := AGmst(jd); // Position auf der Kreisbahn nach dt Sekunden var w: f64 := SqrtF64(AMuEarth() / (r * r * r)); var eci: AVec3 := AVec(r * CosF64(w * dt), r * SinF64(w * dt), 0.0); Print(f(dt / 60.0, 1)); Print(" | "); Print(f(G(gmst), 3)); Print(" | "); PrintLn(f(G(ASubPointLongitude(eci, gmst)), 3)); i := i + 1; } PrintLn(""); PrintLn(StrConcat("J2000 als julianisches Datum: ", f(AJ2000(), 1))); PrintLn(StrConcat("Jahrhunderte seit J2000: ", f(AJulianCenturies(jd0), 6))); var eci2: AVec3 := AVec(0.0, 0.0, r); PrintLn(StrConcat("Ueber dem Nordpol, Breite: ", StrConcat(f(G(ASubPointLatitude(eci2)), 1), " Grad"))); PrintLn(StrConcat("Hin und zurueck (ECI->ECEF->ECI) x: ", f(AEcefToEci(AEciToEcef(eci2, AGmst(jd0)), AGmst(jd0)).z, 1))); return 0; } Ausgabe: Umlaufzeit: 92.56 min Minute | GMST Grad | Laenge Grad 0.0 | 154.602 | -154.602 23.1 | 160.403 | -70.403 46.3 | 166.204 | 13.796 69.4 | 172.005 | 97.995 92.6 | 177.805 | -177.805 J2000 als julianisches Datum: 2451545.0 Jahrhunderte seit J2000: 0.231499 Ueber dem Nordpol, Breite: 90.0 Grad Hin und zurueck (ECI->ECEF->ECI) x: 6778137.0 > **Die Zeit ist hier die Fehlerquelle, nicht die Geometrie.** ''AGmst'' erwartet ein julianisches Datum, und ein Tag Abweichung dreht die Länge um knapp ein Grad daneben — der Sterntag ist vier Minuten kürzer als der Sonnentag. Wer eine Bodenspur über Wochen rechnet, muss die Epoche sauber führen.