jaxtransform3d.rotations.compose_quaternions#

jaxtransform3d.rotations.compose_quaternions(q1: Array | ndarray | bool_ | number | bool | int | float | complex, q2: Array | ndarray | bool_ | number | bool | int | float | complex) Array[source]#

Compose two quaternions.

We concatenate two quaternions by quaternion multiplication \(\boldsymbol{q}_1\boldsymbol{q}_2\).

We use Hamilton’s quaternion multiplication.

If the two quaternions are divided up into scalar part and vector part each, i.e., \(\boldsymbol{q} = (w, \boldsymbol{v}) \in \mathbb{H}, w \in \mathbb{R}, \boldsymbol{v} \in \mathbb{R}^3\), then the quaternion product is

\[\boldsymbol{q}_{12} = (w_1 w_2 - \boldsymbol{v}_1^T \cdot \boldsymbol{v}_2, w_1 \boldsymbol{v}_2 + w_2 \boldsymbol{v}_1 + \boldsymbol{v}_1 \times \boldsymbol{v}_2)\]

with the dot product \(\cdot\) and the cross product \(\times\).

Parameters:
q1array-like, shape (…, 4)

First quaternion, scalar first.

q2array-like, shape (…, 4)

Second quaternion, scalar first.

Returns:
q12array, shape (…, 4)

Quaternion that represents the concatenated rotation \(\boldsymbol{q}_1\boldsymbol{q}_2\) as defined above.

See also

compose_matrices

Compose two rotation matrices.

Examples

>>> import jax.numpy as jnp
>>> from jaxtransform3d.rotations import compose_quaternions
>>> compose_quaternions(jnp.array([1., 0., 0., 0.]),
...                     jnp.array([0., 1., 0., 0.]))
Array([0., 1., 0., 0.], dtype=...)
>>> compose_quaternions(jnp.array([0., 1., 0., 0.]),
...                     jnp.array([0., 0., 1., 0.]))
Array([0., 0., 0., 1.], dtype=...)
>>> compose_quaternions(jnp.array([0., 0., 1., 0.]),
...                     jnp.array([0., 0., 0., 1.]))
Array([0., 1., 0., 0.], dtype=...)
>>> compose_quaternions(jnp.array([0., 0., 0., 1.]),
...                     jnp.array([0., 0., 0., 1.]))
Array([-1., 0., 0., 0.], dtype=...)