Conversions¶
The astrojax.attitude_representations.conversions module contains
pure conversion functions that operate on raw JAX arrays. These
kernels avoid circular imports between the class modules and serve
as the computational backbone for the to_* / from_* methods on
the representation classes.
Module Design¶
The conversion functions accept and return plain jax.Array values
rather than class instances. This separation keeps the conversion
math independent of the class hierarchy and allows direct use in
JIT-compiled pipelines without class overhead.
Convention:
- Quaternion layout: scalar-first
[w, x, y, z], shape(4,) - Rotation matrix layout: row-major, shape
(3, 3) - Euler axis:
(axis(3,), angle_scalar)
Quaternion ↔ Rotation Matrix¶
quaternion_to_rotation_matrix¶
Converts a unit quaternion to a 3x3 rotation matrix using the bilinear product form:
import jax.numpy as jnp
from astrojax.attitude_representations.conversions import quaternion_to_rotation_matrix
q = jnp.array([1.0, 0.0, 0.0, 0.0]) # identity
R = quaternion_to_rotation_matrix(q) # shape (3, 3)
rotation_matrix_to_quaternion¶
Converts a 3x3 rotation matrix to a unit quaternion using
Shepperd's method. Uses jax.lax.switch on argmax for
numerical stability and JIT compatibility:
from astrojax.attitude_representations.conversions import rotation_matrix_to_quaternion
R = jnp.eye(3)
q = rotation_matrix_to_quaternion(R) # shape (4,)
Shepperd's method
Shepperd's method computes four candidate trace values and
selects the branch with the largest trace to avoid numerical
instability from small denominators. The jax.lax.switch
dispatch makes this fully JIT-compatible.
Euler Axis ↔ Quaternion¶
euler_axis_to_quaternion¶
Converts an axis-angle pair to a quaternion using half-angle trigonometry:
from astrojax.attitude_representations.conversions import euler_axis_to_quaternion
axis = jnp.array([0.0, 0.0, 1.0])
angle = jnp.float32(0.7854) # ~45 degrees
q = euler_axis_to_quaternion(axis, angle)
quaternion_to_euler_axis¶
Extracts the axis and angle from a quaternion. Returns a default
axis of [1, 0, 0] when the rotation angle is zero:
from astrojax.attitude_representations.conversions import quaternion_to_euler_axis
q = jnp.array([1.0, 0.0, 0.0, 0.0])
axis, angle = quaternion_to_euler_axis(q)
Euler Angle → Quaternion¶
euler_angle_to_quaternion¶
Converts Euler angles to a quaternion. Dispatches to one of 12
branch functions (one per EulerAngleOrder) using
jax.lax.switch:
from astrojax.attitude_representations.conversions import euler_angle_to_quaternion
order_idx = jnp.int32(1) # XYZ
phi = jnp.float32(0.5236)
theta = jnp.float32(0.7854)
psi = jnp.float32(1.0472)
q = euler_angle_to_quaternion(order_idx, phi, theta, psi)
The 12 internal branch functions correspond to:
| Index | Order | Index | Order |
|---|---|---|---|
| 0 | XYX | 6 | YZX |
| 1 | XYZ | 7 | YZY |
| 2 | XZX | 8 | ZXY |
| 3 | XZY | 9 | ZXZ |
| 4 | YXY | 10 | ZYX |
| 5 | YXZ | 11 | ZYZ |
Rotation Matrix → Euler Angle¶
rotation_matrix_to_euler_angle¶
Extracts Euler angles from a rotation matrix. Dispatches to one of 12 branch functions matching the order index:
from astrojax.attitude_representations.conversions import rotation_matrix_to_euler_angle
R = jnp.eye(3)
order_idx = jnp.int32(10) # ZYX
angles = rotation_matrix_to_euler_angle(order_idx, R) # [phi, theta, psi]
Quaternion Operations¶
quaternion_multiply¶
Hamilton product of two quaternions. The result is normalized:
from astrojax.attitude_representations.conversions import quaternion_multiply
q1 = jnp.array([1.0, 0.0, 0.0, 0.0])
q2 = jnp.array([0.5, 0.5, 0.5, 0.5])
q3 = quaternion_multiply(q1, q2)
quaternion_slerp¶
Spherical linear interpolation between two quaternions. Falls back to linear interpolation when the quaternions are nearly parallel (dot product > 0.9995):
from astrojax.attitude_representations.conversions import quaternion_slerp
q_mid = quaternion_slerp(q1, q2, 0.5) # halfway interpolation
The SLERP implementation:
- Computes the dot product between the two quaternions
- Flips the sign of
q2if needed for shortest-path interpolation - Uses
jax.lax.condto branch between linear and spherical interpolation