std.quat — Quaternionen

Drehungen im Raum in Hamilton-Konvention: Produkt, Slerp, Achse und Winkel, Euler-Winkel, Rotationsmatrix.

Mathematik-Units · std.vector · std.mathx · std.linalg

import std.quat;

Schicht 2, hängt an std.mathx. 38 Funktionen. Alle Beispiele mit lyxc 1.0.21A übersetzt und ausgeführt.


 
Die Struct-Rückgabe legt keinen Speicher mehr an (#1580 behoben). Vorher kostete jeder Aufruf zwei mmap ohne munmap — die Kopie bei der Rückgabe und, größer noch, die Deklaration var p: Pair; mit 4096 Byte. Nachgemessen mit 1.1.2E über 200 000 Rückgaben:

Laufzeit 0,05 s, Spitzenspeicher 6272 kB
mmap-Aufrufe insgesamt: 9   (Programmstart, nicht die Schleife)


Der frühere Rat, in Schleifen adressbasiert zu arbeiten, ist damit hinfällig.

Aufbau

Quat ist ein struct mit den Feldern w, x, y, z — Skalarteil zuerst, in Hamilton-Konvention. Auf die Felder wird direkt zugegriffen:

var q: Quat := QuatFromAxisAngle(0.0, 0.0, 1.0, PI / 2.0);
var v: Quat := QuatRotateVec3(q, 1.0, 0.0, 0.0);
// v.x, v.y, v.z sind die gedrehten Koordinaten

Ein Vektor wird ebenfalls als Quat geführt (mit w = 0) — QuatFromVec3 baut ihn.


Eine Drehung

unit main;
import std.io;
import std.string;
import std.math;
import std.math.constants;
import std.quat;

fn ZF(t: pchar, v: f64): void { Print(t); PrintF64(v); }

fn main(): int64 {
    var q: Quat := QuatFromAxisAngle(0.0, 0.0, 1.0, PI / 2.0);
    ZF("Norm             : ", QuatNorm(q));
    ZF("Angle (soll pi/2): ", QuatAngle(q));

    var v: Quat := QuatRotateVec3(q, 1.0, 0.0, 0.0);
    ZF("rot(1,0,0).x     : ", v.x);
    ZF("rot(1,0,0).y     : ", v.y);
    return 0;
}

Norm             : 0.999999
Angle (soll pi/2): 1.570796
rot(1,0,0).x     : 0.000000
rot(1,0,0).y     : 0.999999

Eine Vierteldrehung um die z-Achse führt (1, 0, 0) auf (0, 1, 0) — genau das steht da. Die Norm bleibt 1, wie es für eine Drehung sein muss.


Warum Quaternionen und nicht Euler-Winkel

 
Euler-Winkel haben eine Singularität. Steht die Nick-Achse senkrecht (pitch = ±90°), fallen Roll- und Gierachse zusammen — ein Freiheitsgrad geht verloren, und die Zuordnung wird mehrdeutig. In der Luftfahrt heißt das Gimbal Lock, und es tritt genau dann auf, wenn es am wenigsten gebraucht werden kann.

Quaternionen haben das Problem nicht. Der Preis ist, dass sie sich nicht ablesen lassen — deshalb gibt es QuatFromEuler, QuatRoll, QuatPitch und QuatYaw für die Ein- und Ausgabe an der Schnittstelle zum Menschen, während intern durchgehend mit Quaternionen gerechnet wird.
 
q und −q beschreiben dieselbe Drehung. Die Abbildung ist zweideutig: jede Orientierung hat zwei Quaternionen. Ein Vergleich mit QuatApproxEq meldet die beiden deshalb als verschieden, obwohl sie dasselbe bedeuten. Wer Orientierungen vergleicht, nimmt QuatSameRotation — das berücksichtigt beide Vorzeichen.

Interpolation

Der eigentliche Grund, warum Quaternionen sich in Animation und Robotik durchgesetzt haben: zwischen zwei Orientierungen lässt sich gleichmäßig interpolieren. Slerp läuft auf der Kugeloberfläche mit konstanter Winkelgeschwindigkeit — eine lineare Interpolation der Euler-Winkel dagegen erzeugt ruckelnde, gekrümmte Bewegungen.


Funktionsübersicht

Gruppe Funktionen
Erzeugen QuatNew · QuatIdentity · QuatZero · QuatCopy · QuatFromVec3
Rechnen QuatAdd · QuatSub · QuatNeg · QuatScale · QuatMul · QuatDiv · QuatDot
Betrag und Kehrwert QuatNorm · QuatNormSq · QuatNormalize · QuatConj · QuatInverse
Prüfen QuatIsZero · QuatIsUnit · QuatApproxEq · QuatSameRotation
Drehung setzen QuatFromAxisAngle · QuatFromEuler · QuatFromTo
Drehung ablesen QuatAngle · QuatAxis · QuatRoll · QuatPitch · QuatYaw
Anwenden QuatRotate · QuatRotateVec3
 
QuatMul ist nicht kommutativ. QuatMul(a, b) dreht erst mit b, dann mit a — wie bei Matrizen. Die vertauschte Reihenfolge ergibt eine andere Orientierung, und der Fehler fällt bei kleinen Winkeln kaum auf, bei großen sofort.

Nur Einheitsquaternionen beschreiben Drehungen. Nach vielen Multiplikationen weicht die Norm durch Rundung ab; QuatNormalize gehört regelmäßig dazwischen. QuatIsUnit(q, eps) prüft mit Toleranz.

QuatFromTo(ax, ay, az, bx, by, bz) liefert die Drehung, die einen Vektor auf einen anderen abbildet — die übliche Aufgabe beim Ausrichten eines Objekts an einer Richtung.


Offener Punkt

 
QuatExp und die Winkelfunktionen greifen teilweise noch auf ExpF64/SinF64 aus std.math zurück statt auf die genaueren Fassungen in std.mathx. Damit hängt das Ergebnis davon ab, welche Fassung der Standardbibliothek eingebunden ist (→ #1578). Eine Umstellung ist vorgeschlagen, aber nicht entschieden.

Letzte Aktualisierung: 2026-08-16 · alle Beispiele mit lyxc 1.0.21A übersetzt und ausgeführt; die Drehung Koordinate für Koordinate geprüft, #1580 selbst nachgemessen.