std.geodesy.frames — geodätisch, ECEF, ENU, NED

import std.geodesy.frames;

Die Umrechnung zwischen den vier Bezugsrahmen: geodätische Koordinaten (Breite, Länge, Höhe), erdfestes ECEF und die beiden örtlichen Rahmen ENU und NED.

→ std.geodesy Übersicht · std.geodesy.ellipsoid · Guide: Kurs und Lage im 3D-Raum


1. Geodätische Koordinaten

pub type Geodetic = struct { latRad: f64; lonRad: f64; hEll: f64; }

Signatur Zweck
GeodNew(latRad, lonRad, hEll): Geodetic aus Bogenmaß
GeodFromDeg(latDeg, lonDeg, hEll): Geodetic aus Grad — der übliche Einstieg
GeodLatDeg(g: Geodetic): f64 · GeodLonDeg(g: Geodetic): f64 zurück in Grad

hEll ist die Höhe über dem Ellipsoid, nicht über dem Meeresspiegel. Der Unterschied (Geoidundulation) beträgt in Mitteleuropa rund 45 m — wer eine GPS-Höhe unbesehen als Höhe über NN nimmt, liegt genau um diesen Betrag daneben. Ein Geoidmodell bringt diese Unit nicht mit.


2. Geodätisch ↔ ECEF

Signatur Zweck
GeodToEcef(e: Ellipsoid, g: Geodetic): V3 nach erdfest-kartesisch
EcefToGeod(e: Ellipsoid, p: V3): Geodetic zurück

Die Rückrechnung ist der schwierigere Weg — die Breite steht in einer Gleichung, die sich nicht geschlossen auflösen lässt. Die Umrechnung hin und zurück trifft im Test wieder denselben Wert (53.630400 → 53.630400).

Drei Proben, die man nachrechnen kann

45N/45O:   3194419.145 | 3194419.145 | 4487348.409
Aequator:  6378137.000 |       0.000 |       0.000
Nordpol:          0.000 |       0.000 | 6356752.314

  • 45° N / 45° O stimmt bis auf drei Nachkommastellen mit dem Literaturwert überein — die übliche Kontrollstelle, weil dort x und y gleich groß sein müssen.
  • Am Äquator ist x genau die große Halbachse (EllWgs84().a = 6378137.000), y und z sind null.
  • Am Pol ist z genau die kleine Halbachse (EllB(e) = 6356752.314).

Diese drei Fälle sind die schnellste Probe, ob ein Ellipsoid richtig eingesetzt und die Breite nicht versehentlich in Grad statt Bogenmaß übergeben wurde: schon ein vertauschtes Winkelmaß verschiebt den Äquatorpunkt um Tausende Kilometer.

ECEF ist die Drehscheibe dieser Unit: alles andere führt über diesen Rahmen.


3. Örtliche Rahmen

Signatur Zweck
EcefToEnu(e: Ellipsoid, origin: Geodetic, p: V3): V3 ECEF → Ost, Nord, Oben
EnuToEcef(e: Ellipsoid, origin: Geodetic, enu: V3): V3 zurück
EcefToNed(e: Ellipsoid, origin: Geodetic, p: V3): V3 ECEF → Nord, Ost, Unten
NedToEcef(e: Ellipsoid, origin: Geodetic, ned: V3): V3 zurück
EnuToNed(enu: V3): V3 · NedToEnu(ned: V3): V3 direkt umtauschen
 
ENU und NED unterscheiden sich in zwei Dingen: die ersten beiden Achsen sind vertauscht, und die dritte hat das umgekehrte Vorzeichen. EnuToNed rechnet (e, n, u) → (n, e, −u).

Das Vorzeichen ist die Falle: wer ENU-Werte als NED liest, bekommt eine Höhe, die unter der Erde liegt — und in einer Regelschleife eine Steuergröße mit falschem Vorzeichen. Luftfahrt und Regelungstechnik rechnen in NED, Vermessung und Antennentechnik in ENU.


4. Sichtlinie

Signatur Zweck
EnuAzimuth(enu: V3): f64 Azimut in Bogenmaß, von Nord über Ost
EnuElevation(enu: V3): f64 Erhebungswinkel über der Horizontebene
EnuSlantRange(enu: V3): f64 Schrägentfernung — die Luftlinie, nicht die Grundstrecke

5. Beispiel

unit main;
import std.coordinates.vec3;
import std.coordinates.transform;
import std.geodesy.ellipsoid;
import std.geodesy.frames;
import std.io;
import std.string;

fn main(): int64 {
    var e:  Ellipsoid := EllWgs84();
    var hh: Geodetic  := GeodFromDeg(53.6304, 9.9882, 0.0);
    var zz: Geodetic  := GeodFromDeg(53.5511, 9.9937, 0.0);

    var enu: V3 := EcefToEnu(e, hh, GeodToEcef(e, zz));

    PrintLn(StrConcat("Ost (m):      ", FloatToStr(enu.x, 1)));
    PrintLn(StrConcat("Nord (m):     ", FloatToStr(enu.y, 1)));
    PrintLn(StrConcat("Azimut (Grad):", FloatToStr(RadToDeg(EnuAzimuth(enu)), 2)));
    PrintLn(StrConcat("Entfernung:   ", FloatToStr(EnuSlantRange(enu), 1)));
    return 0;
}

Ost (m):      363.4
Nord (m):     -8825.9
Azimut (Grad):177.63
Entfernung:   8833.4

Nord ist negativ, weil das Ziel südlich liegt — und der Azimut 177,6° sagt dasselbe noch einmal. Beides zusammen ist die Probe, ob der Rahmen richtig herum steht.


Letzte Aktualisierung: 2026-09-07 — Abschnitt „Drei Proben„ ergänzt: 45°N/45°O gegen den Literaturwert, Äquator gegen die große und Pol gegen die kleine Halbachse; nachgemessen mit lyxc 1.2.2D.

Vorherige letzte Aktualisierung: 2026-09-06 — Seite neu angelegt; erhoben aus std/geodesy/frames.lyx, Beispiel gegen lyxc 1.2.2D übersetzt und ausgeführt.