Skip to content

Quaternions

Quaternions are a mathematical concept that extends the idea of complex numbers to four dimensions. They are used in many fields, including computer graphics, robotics, and physics. In the context of this toolkit, they represent rotations in 3D space and are operationally equivalent to rotation matrices.

They have several advantages over rotation matrices, including:

  • They are more compact, requiring only four numbers to represent a rotation instead of nine.
  • They are more numerically stable, avoiding the gimbal lock problem.
  • They are easier to interpolate between, making them useful for animations.

Warning

Quaternions in this module perform a right-handed rotation of the vector. You will occasionally see (especially in attitude control texts) a quaternion convention that does a right-handed rotation of the coordinate system, which is a left-handed rotation of the vector.

For an excellent description of quaternions, see here; the conventions follow Markley & Crassidis (2014), and spherical linear interpolation (slerp) is the construction of Shoemake (1985).

quaternion

Quaternion representing rotation of 3D Cartesian axes

Quaternions perform right-handed rotation of a vector, e.g. rotation of +xhat 90 degrees by +zhat give +yhat

This is different than the convention used in Vallado, but it is the way it is commonly used in mathematics and it is the way it should be done.

For the uninitiated: quaternions are a more-compact and computationally efficient way of representing 3D rotations. They can also be multiplied together and easily renormalized to avoid problems with floating-point precision eventually causing changes in the rotated vecdtor norm.

For details, see:

https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

Notes
  • Under the hood, this is using the "UnitQuaternion" object in the rust "nalgebra" crate.

norm property

Quaternion norm (Euclidean length of the 4 components; 1 for a unit rotation quaternion)

angle property

Return the angle in radians of the rotation

Returns:

Type Description
float

Angle in radians of the rotation

axis property

Return the axis of rotation as a unit vector

Returns:

Type Description
NDArray[float64]

3-element array representing the axis of rotation as a unit vector

x property

X component of the quaternion

Returns:

Type Description
float

X component of the quaternion

y property

Y component of the quaternion

Returns:

Type Description
float

Y component of the quaternion

z property

Z component of the quaternion

Returns:

Type Description
float

Z component of the quaternion

w property

Scalar component of the quaternion

Returns:

Type Description
float

Scalar component of the quaternion

from_axis_angle(axis, angle) staticmethod

Quaternion representing right-handed rotation of vector by "angle" radians about the given axis

Parameters:

Name Type Description Default
axis ArrayLike[float64]

3-element array representing axis of rotation (unitless direction; need not be normalized)

required
angle float

angle of rotation in radians

required

Returns:

Type Description
quaternion

Quaternion representing rotation by "angle" radians about the given axis

from_rotation_matrix(dcm) staticmethod

Return quaternion representing identical rotation to input 3x3 rotation matrix

Parameters:

Name Type Description Default
mat ArrayLike[float64]

3x3 rotation matrix

required

Returns:

Type Description
quaternion

Quaternion representing identical rotation to input 3x3 rotation matrix

rotx(theta_rad) staticmethod

Quaternion representing right-handed rotation of vector by "theta" radians about the xhat unit vector

Parameters:

Name Type Description Default
theta float

angle of rotation in radians

required

Returns:

Type Description
quaternion

Quaternion representing right-handed rotation of vector by "theta" radians about the xhat unit vector

Notes

Equivalent rotation matrix: | 1 0 0| | 0 cos(theta) -sin(theta)| | 0 sin(theta) cos(theta)|

roty(theta_rad) staticmethod

Quaternion representing right-handed rotation of vector by "theta" radians about the yhat unit vector

Parameters:

Name Type Description Default
theta float

angle of rotation in radians

required

Returns:

Type Description
quaternion

Quaternion representing right-handed rotation of vector by "theta" radians about the yhat unit vector

Notes

Equivalent rotation matrix: | cos(theta) 0 sin(theta)| | 0 1 0| | -sin(theta) 0 cos(theta)|

rotz(theta_rad) staticmethod

Quaternion representing right-handed rotation of vector by "theta" radians about the zhat unit vector

Parameters:

Name Type Description Default
theta float

angle of rotation in radians

required

Returns:

Type Description
quaternion

Quaternion representing right-handed rotation of vector by "theta" radians about the zhat unit vector

Notes

Equivalent rotation matrix: | cos(theta) -sin(theta) 0| | sin(theta) cos(theta) 0| | 0 0 1|

rotation_between(v1, v2) staticmethod

Quaternion representation rotation between two input vectors

Parameters:

Name Type Description Default
v1 ArrayLike

3-element vector rotating from (any real numeric array-like)

required
v2 ArrayLike

3-element vector rotating to (any real numeric array-like)

required

Returns:

Type Description
quaternion

Quaternion that rotates from v1 to v2

Example
import numpy as np
v1 = np.array([1, 0, 0])
v2 = np.array([0, 1, 0])
q = satkit.quaternion.rotation_between(v1, v2)
print(q * v1)
# [0, 1, 0]

to_rotation_matrix()

Return 3x3 rotation matrix representing equivalent rotation

Returns:

Type Description
NDArray[float64]

3x3 rotation matrix representing equivalent rotation

as_rotation_matrix()

Deprecated since 0.23, removed in 0.25. Use :meth:quaternion.to_rotation_matrix.

to_euler()

Return equivalent rotation as intrinsic ZYX Euler angles (yaw, pitch, roll).

The decomposition follows the aerospace convention (Tait-Bryan angles): the rotation is equivalent to first rotating by yaw about Z, then pitch about the new Y, then roll about the new X.

Returns:

Type Description
tuple[float, float, float]

tuple[float, float, float]: (roll, pitch, yaw) in radians

Example
q = satkit.quaternion.rotz(0.1) * satkit.quaternion.roty(0.2)
roll, pitch, yaw = q.to_euler()

as_euler()

Deprecated since 0.23, removed in 0.25. Use :meth:quaternion.to_euler.

from_euler(roll, pitch, yaw) staticmethod

Create quaternion from roll, pitch, yaw Euler angles in radians (inverse of to_euler)

Parameters:

Name Type Description Default
roll float

Roll angle in radians

required
pitch float

Pitch angle in radians

required
yaw float

Yaw angle in radians

required

Returns:

Name Type Description
quaternion quaternion

Quaternion representing the input euler-angle rotation

identity() staticmethod

The identity (no-rotation) quaternion (w=1, x=y=z=0)

normalize()

Return this quaternion normalized to unit length

inverse()

Quaternion inverse. Equals the conjugate for a unit (rotation) quaternion.

dot(other)

Dot product of the 4 quaternion components with another quaternion

conj()

Quaternion conjugate, which for a unit (rotation) quaternion is the inverse rotation. Same as conjugate() and inverse().

Returns:

Type Description
quaternion

Conjugate or inverse of the rotation

conjugate()

Quaternion conjugate, which for a unit (rotation) quaternion is the inverse rotation. Same as conj() and inverse().

Returns:

Type Description
quaternion

Conjugate or inverse of the rotation

slerp(other, frac)

Spherical linear interpolation between self and other

Parameters:

Name Type Description Default
other quaternion

Quaternion to perform interpolation to

required
frac float

fractional amount of interpolation, in range [0,1]

required

Returns:

Type Description
quaternion

Quaternion representing interpolation between self and other

Example
import math
q1 = satkit.quaternion.rotz(math.radians(0))
q2 = satkit.quaternion.rotz(math.radians(90))
q_mid = q1.slerp(q2, 0.5)
print(f"Mid-rotation angle: {math.degrees(q_mid.angle):.1f} deg")
# Mid-rotation angle: 45.0 deg

__init__(w, x, y, z)

__init__() -> None
__init__(w: float, x: float, y: float, z: float) -> None

Return quaternion with input (w,x,y,z) values

With no arguments, return the identity quaternion. Otherwise pass all four components positionally (keywords are not accepted).

Parameters:

Name Type Description Default
w float

Scalar component of the quaternion

required
x float

X component of the quaternion

required
y float

Y component of the quaternion

required
z float

Z component of the quaternion

required
Example
# Identity quaternion (no rotation)
q = satkit.quaternion()

# 90 degree rotation about z-axis
import math
q = satkit.quaternion.rotz(math.radians(90))

__mul__(other)

__mul__(other: quaternion) -> quaternion
__mul__(other: npt.NDArray[Any] | Sequence[float] | Sequence[Sequence[float]]) -> npt.NDArray[np.float64]

Multiply by a vector to rotate the vector

Parameters:

Name Type Description Default
other NDArray | Sequence[float] | Sequence[Sequence[float]]

3-element vector to rotate, or Nx3 array of vectors to rotate (any real numeric array, list or tuple; integers are converted to float64). A scalar is not a vector: q * 2.0 raises TypeError

required

Returns:

Type Description
NDArray[float64]

3-element array representing rotated vector or Nx3 array of rotated vectors

Example
xhat = np.array([1,0,0])
q = satkit.quaternion.rotz(np.pi/2)
print(q * xhat)
# [0, 1, 0]