std.astro.guidance — Annäherung, Abweichung, Proportional Navigation
import std.astro.guidance;
Alles, was aus Relativvektoren folgt: Abstand, Annäherungsrate, dichteste Annäherung, Restflugzeit, Sichtlinienrate und die Sollbeschleunigung der Proportional Navigation.
Alle Funktionen nehmen rRel und vRel — Ort und Geschwindigkeit des Ziels relativ zum eigenen Fahrzeug, im selben Rahmen. Wer absolute Zustände hat, bildet vorher die Differenz.
→ std.astro (Übersicht) · std.astro.attitude · std.astro.state
1. Abstand und Annäherung
| Funktion | Rückgabe | Bedeutung |
|---|---|---|
ARange(rRel) | f64 [m] | Abstand |
AClosingSpeed(rRel, vRel) | f64 [m/s] | Annäherungsrate; positiv beim Näherkommen |
ATimeToCPA(rRel, vRel) | f64 [s] | Zeit bis zur dichtesten Annäherung; negativ heißt: der Punkt liegt hinter uns |
ADistanceAtCPA(rRel, vRel) | f64 [m] | Abstand in diesem Punkt |
ARelPositionAt(rRel, vRel, t) | AVec3 | geradlinig fortgeschriebene Relativposition |
ATimeToGo(rRel, vRel) | f64 [s] | Restflugzeit; NaN, wenn sich das Ziel entfernt |
AGuidanceThreshold() | f64 | 1e−12 |
ATimeToGomeldet lieber NaN als eine große Zahl. Entfernt sich das Ziel, gibt es keine Restflugzeit — ein großer positiver Wert wäre dort besonders gefährlich, weil er aussieht wie „noch viel Zeit„.
2. Abweichung von der Bahn
| Funktion | Rückgabe | Bedeutung |
|---|---|---|
ACrossTrack(rRel, vRel) | f64 [m] | Querabweichung — senkrecht auf die Geschwindigkeitsrichtung |
AAlongTrack(rRel, vRel) | f64 [m] | Abstand entlang der Bahngeraden, positiv wenn das Ziel voraus liegt |
Gemessen wird senkrecht auf die Bewegungsrichtung, nicht auf die Verbindungslinie. Der Unterschied ist keine Kleinigkeit: bei 50 km Abstand und 50 Grad zwischen beiden liegen 12 km dazwischen. Der Fehler fällt nur auf, wenn ein Test einen schiefen Fall rechnet — ein rechtwinkliger gibt beidesmal dasselbe.
3. Sichtlinie und Proportional Navigation
| Funktion | Rückgabe | Bedeutung |
|---|---|---|
ALosRate(rRel, vRel) | AVec3 [rad/s] | Drehvektor der Sichtlinie: (r × v)/|r|² — Betrag = Rate, Richtung = Drehachse |
ALosRateMagnitude(rRel, vRel) | f64 [rad/s] | nur der Betrag |
ALosUnit(rRel) | AVec3 | Einheitsvektor der Sichtlinie |
AProNavAccel(rRel, vRel, n) | AVec3 [m/s²] | Sollbeschleunigung N·V_c·(ω × r̂) |
AOnCollisionCourse(rRel, vRel, rateSchranke) | bool | Sichtlinienrate unter der Schranke und Ziel kommt näher |
Der Navigationsbeiwert n liegt üblich bei 3 bis 5.
Die Kernaussage der Proportional Navigation steht in einer Zahl: bei konstanter Sichtlinienrichtung ist ω null und damit die Sollbeschleunigung null — das ist Kollisionskurs. Die Beschleunigung steht senkrecht auf der Sichtlinie: sie stellt die Sichtlinie still, sie bremst nicht. Wer sie entlang der Sichtlinie ansetzt, fliegt eine Verfolgungskurve und keine Proportional Navigation.
AOnCollisionCourseprüft deshalb zwei Bedingungen. Eine ruhende Sichtlinie bei wachsendem Abstand ist gerade kein Kollisionskurs, sondern ein sich entfernendes Ziel auf derselben Geraden.
4. Beispiel
import std.astro.state;
import std.astro.guidance;
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 {
// Ziel 1000 m voraus, 50 m seitlich versetzt, kommt mit 10 m/s entgegen
var r: AVec3 := AVec(1000.0, 50.0, 0.0);
var v: AVec3 := AVec(0.0 - 10.0, 0.0, 0.0);
zeig("Abstand m : ", ARange(r), 1);
zeig("Annaeherungsrate : ", AClosingSpeed(r, v), 2);
zeig("Zeit bis CPA s : ", ATimeToCPA(r, v), 1);
zeig("Abstand bei CPA m : ", ADistanceAtCPA(r, v), 1);
zeig("Restflugzeit s : ", ATimeToGo(r, v), 1);
zeig("Querabweichung m : ", ACrossTrack(r, v), 1);
zeig("Laengsabweichung m : ", AAlongTrack(r, v), 1);
zeig("Sichtlinienrate : ", ALosRateMagnitude(r, v), 6);
var p: AVec3 := ARelPositionAt(r, v, 50.0);
Print("Ort nach 50 s : ("); Print(FloatToStr(p.x, 1));
Print(", "); Print(FloatToStr(p.y, 1)); PrintLn(")");
var a: AVec3 := AProNavAccel(r, v, 4.0);
zeig("ProNav |a| m/s2 : ", AMagnitude(a), 4);
Print("Kollisionskurs? : "); PrintLn(IntToStr(BI(AOnCollisionCourse(r, v, 0.0001))));
// Echter Kollisionskurs: genau aufeinander zu
var rk: AVec3 := AVec(1000.0, 0.0, 0.0);
var vk: AVec3 := AVec(0.0 - 10.0, 0.0, 0.0);
zeig("gerade: Sichtrate : ", ALosRateMagnitude(rk, vk), 6);
zeig("gerade: ProNav |a| : ", AMagnitude(AProNavAccel(rk, vk, 4.0)), 6);
Print("gerade: Kollision? : "); PrintLn(IntToStr(BI(AOnCollisionCourse(rk, vk, 0.0001))));
// Ziel entfernt sich: keine Restflugzeit, kein Kollisionskurs
var vw: AVec3 := AVec(10.0, 0.0, 0.0);
Print("entfernt: t_go NaN : "); PrintLn(IntToStr(BI(AIsError(ATimeToGo(rk, vw)))));
Print("entfernt: Kollis.? : "); PrintLn(IntToStr(BI(AOnCollisionCourse(rk, vw, 0.0001))));
return 0;
}
Abstand m : 1001.2
Annaeherungsrate : 9.99
Zeit bis CPA s : 100.0
Abstand bei CPA m : 50.0
Restflugzeit s : 100.3
Querabweichung m : 50.0
Laengsabweichung m : -1000.0
Sichtlinienrate : 0.000499
Ort nach 50 s : (500.0, 50.0)
ProNav |a| m/s2 : 0.0199
Kollisionskurs? : 0
gerade: Sichtrate : 0.000000
gerade: ProNav |a| : 0.000000
gerade: Kollision? : 1
entfernt: t_go NaN : 1
entfernt: Kollis.? : 0
Der mittlere Block ist die eigentliche Aussage: auf genauem Kollisionskurs sind Sichtlinienrate und Sollbeschleunigung exakt null. Die Regelung tut nichts — weil nichts zu tun ist. Im schiefen Fall darüber ergibt dieselbe Rechnung 0.0199 m/s², und die Querabweichung von 50 m bleibt bis zur dichtesten Annäherung erhalten.
Der letzte Block zeigt die Gegenprobe: dasselbe Ziel, nur wegfliegend — die Restflugzeit ist NaN, und AOnCollisionCourse meldet trotz ruhender Sichtlinie korrekt „nein“.
Letzte Aktualisierung: 2026-09-01 — Seite neu angelegt aus std/astro/guidance.lyx (Commit 32353cc, #1900, 83 Prüfungen); Beispiel mit lyxc 1.1.16A gebaut und ausgeführt.
