pub struct Quaternion<T> {
pub w: T,
pub x: T,
pub y: T,
pub z: T,
}Expand description
Unit quaternion for 3D rotations.
Scalar-first Hamilton convention: q = w + xi + yj + zk stored as
[w, x, y, z]. Hamilton product satisfies ij = k.
§Rotation convention
q * v computes the rotated vector q v q⁻¹. When used for attitude
representation, q is the source-to-body (e.g. inertial-to-body)
quaternion: v_body = q * v_inertial.
Composition follows right-to-left order: q_total = q2 * q1 applies
q1 first, then q2.
§Example
use numeris::{Quaternion, Vector3};
// Create a 90° rotation about the Z axis
let q = Quaternion::from_axis_angle(
Vector3::from_array([0.0, 0.0, 1.0]),
std::f64::consts::FRAC_PI_2,
);
// Rotate the X unit vector → should become Y
let v = Vector3::from_array([1.0, 0.0, 0.0]);
let rotated = q * v;
assert!((rotated[0]).abs() < 1e-12);
assert!((rotated[1] - 1.0).abs() < 1e-12);Fields§
§w: T§x: T§y: T§z: TImplementations§
Source§impl<T: FloatScalar> Quaternion<T>
impl<T: FloatScalar> Quaternion<T>
Sourcepub fn from_axis_angle(axis: Vector3<T>, angle: T) -> Self
pub fn from_axis_angle(axis: Vector3<T>, angle: T) -> Self
Create from an axis (must be unit length) and angle in radians.
use numeris::{Quaternion, Vector3};
let q = Quaternion::from_axis_angle(
Vector3::from_array([0.0_f64, 1.0, 0.0]),
1.0,
);
assert!((q.norm() - 1.0).abs() < 1e-12);Sourcepub fn from_rotation_matrix(m: &Matrix<T, 3, 3>) -> Self
pub fn from_rotation_matrix(m: &Matrix<T, 3, 3>) -> Self
Create from a 3×3 rotation matrix using Shepperd’s method.
Numerically stable for all rotation angles.
Sourcepub fn from_euler(roll: T, pitch: T, yaw: T) -> Self
pub fn from_euler(roll: T, pitch: T, yaw: T) -> Self
Create from Euler angles (ZYX intrinsic convention).
Arguments: roll (X), pitch (Y), yaw (Z), all in radians.
Source§impl<T: FloatScalar> Quaternion<T>
impl<T: FloatScalar> Quaternion<T>
Sourcepub fn norm_squared(&self) -> T
pub fn norm_squared(&self) -> T
Squared norm: w² + x² + y² + z².
Source§impl<T: FloatScalar> Quaternion<T>
impl<T: FloatScalar> Quaternion<T>
Sourcepub fn to_rotation_matrix(&self) -> Matrix<T, 3, 3>
pub fn to_rotation_matrix(&self) -> Matrix<T, 3, 3>
Convert to a 3×3 rotation matrix.
use numeris::{Quaternion, Matrix, Vector3};
let q = Quaternion::from_axis_angle(
Vector3::from_array([0.0_f64, 1.0, 0.0]),
0.8,
);
let m = q.to_rotation_matrix();
// Rotation via quaternion and matrix should match
let v = Vector3::from_array([1.0, 0.0, 0.0]);
let r_q = q * v;
let r_m = m.vecmul(&v);
assert!((r_q[0] - r_m[0]).abs() < 1e-12);Sourcepub fn to_axis_angle(&self) -> (Vector3<T>, T)
pub fn to_axis_angle(&self) -> (Vector3<T>, T)
Convert to axis-angle representation.
Returns (axis, angle) where axis is a unit vector and angle is in radians.
For identity rotation, returns ([1,0,0], 0).
Source§impl<T: FloatScalar> Quaternion<T>
impl<T: FloatScalar> Quaternion<T>
Sourcepub fn slerp(&self, other: &Self, t: T) -> Self
pub fn slerp(&self, other: &Self, t: T) -> Self
Spherical linear interpolation between self and other.
t = 0 returns self, t = 1 returns other.
Automatically takes the short path on the 4-sphere.
use numeris::{Quaternion, Vector3};
use std::f64::consts::FRAC_PI_2;
let a = Quaternion::<f64>::identity();
let b = Quaternion::from_axis_angle(
Vector3::from_array([0.0, 0.0, 1.0]),
FRAC_PI_2,
);
let mid = a.slerp(&b, 0.5);
assert!((mid.norm() - 1.0).abs() < 1e-12);Source§impl<T: FloatScalar> Quaternion<T>
impl<T: FloatScalar> Quaternion<T>
Sourcepub fn from_angular_velocity(omega: &Vector3<T>, dt: T) -> Self
pub fn from_angular_velocity(omega: &Vector3<T>, dt: T) -> Self
Create a rotation quaternion from angular velocity and time step.
Computes the exact finite rotation δq = exp(½ ω dt) using the
axis-angle formula: angle = |ω| · dt, axis = ω / |ω|.
The returned quaternion represents the rotation that the body undergoes
over dt at constant angular velocity omega. To apply it to an
existing attitude quaternion, right-multiply: q_new = q ⊗ δq
(see propagate).
Sourcepub fn derivative(&self, omega: &Vector3<T>) -> Self
pub fn derivative(&self, omega: &Vector3<T>) -> Self
Quaternion time derivative for body-frame angular velocity.
Returns q̇ = ½ q ⊗ ω̃ where ω̃ = (0, ωx, ωy, ωz) is the angular
velocity as a pure quaternion.
§Convention
selfis the source-to-body quaternion (e.g. inertial-to-body). It transforms vectors from the source frame into the body frame:v_body = q * v_source.omegais the angular velocity of the body relative to the source frame, expressed in the body frame — this is what a body-mounted gyroscope measures.- The right-multiply (
q ⊗ ω̃) follows from body-frame rates. If you have rates in the source (inertial) frame instead, useq̇ = ½ ω̃_source ⊗ q(left-multiply).
§Usage
Feed this into an ODE integrator (e.g. RK4, RKTS54). The result is a
general quaternion (not unit), so normalize periodically to prevent
drift. For constant-rate propagation, use propagate
instead.
§Example
use numeris::{Quaternion, Vector3};
// Constant rotation about Z at 1 rad/s
let q = Quaternion::<f64>::identity();
let omega = Vector3::from_array([0.0, 0.0, 1.0]);
let q_dot = q.derivative(&omega);
// q̇ = ½ (1,0,0,0) ⊗ (0,0,0,1) = (0, 0, 0, 0.5)
assert!((q_dot.w).abs() < 1e-12);
assert!((q_dot.z - 0.5).abs() < 1e-12);Sourcepub fn propagate(&self, omega: &Vector3<T>, dt: T) -> Self
pub fn propagate(&self, omega: &Vector3<T>, dt: T) -> Self
Propagate quaternion by body-frame angular velocity over a time step using the exponential map (exact for constant rate).
Computes q_new = q ⊗ δq where δq = exp(½ ω dt) is the exact
finite rotation. This is geometrically exact for constant angular
velocity over dt and preserves unit norm (up to floating-point
rounding). Equivalent to from_angular_velocity
composed with the current quaternion.
§Convention
Same as derivative:
selfis the source-to-body quaternion (e.g. inertial-to-body).omegais the angular velocity of the body relative to the source frame, expressed in the body frame.- The delta rotation is right-multiplied (
q ⊗ δq) because the rates are in the body frame.
§When to use
Use this for constant-rate steps or as a first-order integrator.
For time-varying rates (e.g. from Euler’s equations with applied
torques), use derivative with a higher-order
ODE integrator instead.
§Example
use numeris::{Quaternion, Vector3};
// Rotate 90° about Z at 1 rad/s
let q = Quaternion::<f64>::identity();
let omega = Vector3::from_array([0.0, 0.0, 1.0]);
let q_new = q.propagate(&omega, std::f64::consts::FRAC_PI_2);
// Should match a 90° rotation about Z
let v = Vector3::from_array([1.0, 0.0, 0.0]);
let rotated = q_new * v;
assert!((rotated[0]).abs() < 1e-12);
assert!((rotated[1] - 1.0).abs() < 1e-12);Trait Implementations§
Source§impl<T: Clone> Clone for Quaternion<T>
impl<T: Clone> Clone for Quaternion<T>
Source§fn clone(&self) -> Quaternion<T>
fn clone(&self) -> Quaternion<T>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<T: Debug> Debug for Quaternion<T>
impl<T: Debug> Debug for Quaternion<T>
Source§impl<T: Display> Display for Quaternion<T>
impl<T: Display> Display for Quaternion<T>
Source§impl<T: FloatScalar> Mul<&Matrix<T, 1, 3>> for &Quaternion<T>
impl<T: FloatScalar> Mul<&Matrix<T, 1, 3>> for &Quaternion<T>
Source§impl<T: FloatScalar> Mul<&Matrix<T, 1, 3>> for Quaternion<T>
impl<T: FloatScalar> Mul<&Matrix<T, 1, 3>> for Quaternion<T>
Source§impl<T: FloatScalar> Mul<&Quaternion<T>> for &Quaternion<T>
impl<T: FloatScalar> Mul<&Quaternion<T>> for &Quaternion<T>
Source§type Output = Quaternion<T>
type Output = Quaternion<T>
* operator.Source§fn mul(self, rhs: &Quaternion<T>) -> Quaternion<T>
fn mul(self, rhs: &Quaternion<T>) -> Quaternion<T>
* operation. Read moreSource§impl<T: FloatScalar> Mul<&Quaternion<T>> for Quaternion<T>
impl<T: FloatScalar> Mul<&Quaternion<T>> for Quaternion<T>
Source§type Output = Quaternion<T>
type Output = Quaternion<T>
* operator.Source§fn mul(self, rhs: &Quaternion<T>) -> Quaternion<T>
fn mul(self, rhs: &Quaternion<T>) -> Quaternion<T>
* operation. Read moreSource§impl<T: FloatScalar> Mul<Matrix<T, 1, 3>> for &Quaternion<T>
impl<T: FloatScalar> Mul<Matrix<T, 1, 3>> for &Quaternion<T>
Source§impl<T: FloatScalar> Mul<Matrix<T, 1, 3>> for Quaternion<T>
impl<T: FloatScalar> Mul<Matrix<T, 1, 3>> for Quaternion<T>
Source§impl<T: FloatScalar> Mul<Quaternion<T>> for &Quaternion<T>
impl<T: FloatScalar> Mul<Quaternion<T>> for &Quaternion<T>
Source§type Output = Quaternion<T>
type Output = Quaternion<T>
* operator.Source§fn mul(self, rhs: Quaternion<T>) -> Quaternion<T>
fn mul(self, rhs: Quaternion<T>) -> Quaternion<T>
* operation. Read moreSource§impl<T: FloatScalar> Mul for Quaternion<T>
impl<T: FloatScalar> Mul for Quaternion<T>
Source§impl<T: FloatScalar> Neg for &Quaternion<T>
impl<T: FloatScalar> Neg for &Quaternion<T>
Source§type Output = Quaternion<T>
type Output = Quaternion<T>
- operator.Source§fn neg(self) -> Quaternion<T>
fn neg(self) -> Quaternion<T>
- operation. Read more