BB.Math.Quaternion (bb v0.15.0)

View Source

Unit quaternion for 3D rotations, backed by an Nx tensor.

Quaternions are stored in WXYZ order (scalar first): [w, x, y, z]. All math operations use Nx for consistent performance and potential GPU acceleration.

All operations return normalised unit quaternions suitable for representing rotations. The underlying tensor is always {4} shape with :f64 type.

Examples

iex> q = BB.Math.Quaternion.identity()
iex> BB.Math.Quaternion.w(q)
1.0

iex> q1 = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> q2 = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> q3 = BB.Math.Quaternion.multiply(q1, q2)
iex> BB.Math.Quaternion.angular_distance(q3, BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi()))
0.0

Summary

Functions

Computes the angular distance between two quaternions in radians.

Returns the conjugate of a quaternion.

Creates a quaternion from an axis-angle representation.

Creates a quaternion from Euler angles (roll, pitch, yaw).

Creates from a list in WXYZ order.

Creates a quaternion from a 3x3 rotation matrix.

Creates a quaternion from an existing {4} tensor.

Creates a quaternion representing the shortest rotation from one vector to another.

Creates from a list in XYZW order (for ROS/external system compatibility).

Returns the identity quaternion (no rotation).

Returns an identity quaternion as a raw tensor (for batch operations).

Returns the inverse of a quaternion.

Multiplies two quaternions (Hamilton product).

Creates a new quaternion from w, x, y, z components.

Normalises a quaternion to unit length.

Rotates a 3D vector by a quaternion.

Spherical linear interpolation between two quaternions.

Returns the underlying {4} tensor.

Converts a quaternion to axis-angle representation.

Converts a quaternion to Euler angles (roll, pitch, yaw).

Converts to a list in WXYZ order.

Converts a quaternion to a 3x3 rotation matrix.

Converts to a list in XYZW order (for ROS/external system compatibility).

Returns the W (scalar) component.

Returns the X component.

Returns the Y component.

Returns the Z component.

Types

t()

@type t() :: %BB.Math.Quaternion{tensor: Nx.Tensor.t()}

Functions

angular_distance(quaternion1, quaternion2)

@spec angular_distance(t(), t()) :: float()

Computes the angular distance between two quaternions in radians.

Returns a value between 0 and pi.

Examples

iex> q1 = BB.Math.Quaternion.identity()
iex> q2 = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> Float.round(BB.Math.Quaternion.angular_distance(q1, q2), 6)
1.570796

conjugate(quaternion)

@spec conjugate(t()) :: t()

Returns the conjugate of a quaternion.

For unit quaternions, the conjugate equals the inverse.

Examples

iex> q = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> qc = BB.Math.Quaternion.conjugate(q)
iex> Float.round(BB.Math.Quaternion.z(qc), 6)
-0.707107

from_axis_angle(vec3, angle)

@spec from_axis_angle(BB.Math.Vec3.t(), number()) :: t()

Creates a quaternion from an axis-angle representation.

The axis should be a BB.Math.Vec3 unit vector (it will be normalised if not). The angle is in radians.

Examples

iex> q = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> Float.round(BB.Math.Quaternion.w(q), 6)
0.707107

from_euler(roll, pitch, yaw, order \\ :xyz)

@spec from_euler(number(), number(), number(), atom()) :: t()

Creates a quaternion from Euler angles (roll, pitch, yaw).

Angles are in radians. Default order is :xyz (roll around X, pitch around Y, yaw around Z).

Supported orders: :xyz, :zyx

Examples

iex> q = BB.Math.Quaternion.from_euler(0, 0, :math.pi() / 2, :xyz)
iex> Float.round(BB.Math.Quaternion.z(q), 6)
0.707107

from_list(list)

@spec from_list([number()]) :: t()

Creates from a list in WXYZ order.

Examples

iex> q = BB.Math.Quaternion.from_list([1.0, 0.0, 0.0, 0.0])
iex> BB.Math.Quaternion.w(q)
1.0

from_rotation_matrix(matrix)

@spec from_rotation_matrix(Nx.Tensor.t()) :: t()

Creates a quaternion from a 3x3 rotation matrix.

Uses the Shepperd method for numerical stability.

Examples

iex> m = Nx.tensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
iex> q = BB.Math.Quaternion.from_rotation_matrix(m)
iex> BB.Math.Quaternion.w(q)
1.0

from_tensor(tensor)

@spec from_tensor(Nx.Tensor.t()) :: t()

Creates a quaternion from an existing {4} tensor.

The tensor should be in WXYZ order. It will be normalised.

from_two_vectors(vec31, vec32)

@spec from_two_vectors(BB.Math.Vec3.t(), BB.Math.Vec3.t()) :: t()

Creates a quaternion representing the shortest rotation from one vector to another.

Both vectors should be unit vectors (they will be normalised if not). Returns the quaternion that rotates from to align with to.

Handles edge cases:

  • Parallel vectors (from ≈ to): returns identity quaternion
  • Anti-parallel vectors (from ≈ -to): returns 180° rotation around a perpendicular axis

Examples

iex> q = BB.Math.Quaternion.from_two_vectors(BB.Math.Vec3.unit_x(), BB.Math.Vec3.unit_y())
iex> rotated = BB.Math.Quaternion.rotate_vector(q, BB.Math.Vec3.unit_x())
iex> {Float.round(BB.Math.Vec3.x(rotated), 6), Float.round(BB.Math.Vec3.y(rotated), 6)}
{0.0, 1.0}

iex> q = BB.Math.Quaternion.from_two_vectors(BB.Math.Vec3.unit_z(), BB.Math.Vec3.unit_z())
iex> BB.Math.Quaternion.w(q)
1.0

from_xyzw_list(list)

@spec from_xyzw_list([number()]) :: t()

Creates from a list in XYZW order (for ROS/external system compatibility).

Examples

iex> q = BB.Math.Quaternion.from_xyzw_list([0.0, 0.0, 0.0, 1.0])
iex> BB.Math.Quaternion.w(q)
1.0

identity()

@spec identity() :: t()

Returns the identity quaternion (no rotation).

Examples

iex> q = BB.Math.Quaternion.identity()
iex> {BB.Math.Quaternion.w(q), BB.Math.Quaternion.x(q), BB.Math.Quaternion.y(q), BB.Math.Quaternion.z(q)}
{1.0, 0.0, 0.0, 0.0}

identity_tensor()

@spec identity_tensor() :: Nx.Tensor.t()

Returns an identity quaternion as a raw tensor (for batch operations).

inverse(q)

@spec inverse(t()) :: t()

Returns the inverse of a quaternion.

For unit quaternions, this equals the conjugate.

Examples

iex> q = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> qi = BB.Math.Quaternion.inverse(q)
iex> qr = BB.Math.Quaternion.multiply(q, qi)
iex> Float.round(BB.Math.Quaternion.w(qr), 6)
1.0

multiply(quaternion1, quaternion2)

@spec multiply(t(), t()) :: t()

Multiplies two quaternions (Hamilton product).

This composes the rotations: multiply(q1, q2) applies q2 first, then q1.

Examples

iex> q1 = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> q2 = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> q3 = BB.Math.Quaternion.multiply(q1, q2)
iex> {_axis, angle} = BB.Math.Quaternion.to_axis_angle(q3)
iex> Float.round(angle, 6)
3.141593

new(w, x, y, z)

@spec new(number(), number(), number(), number()) :: t()

Creates a new quaternion from w, x, y, z components.

The quaternion is automatically normalised.

Examples

iex> q = BB.Math.Quaternion.new(1, 0, 0, 0)
iex> BB.Math.Quaternion.w(q)
1.0

normalise(quaternion)

@spec normalise(t()) :: t()

Normalises a quaternion to unit length.

Examples

iex> q = %BB.Math.Quaternion{tensor: Nx.tensor([2.0, 0.0, 0.0, 0.0])}
iex> qn = BB.Math.Quaternion.normalise(q)
iex> BB.Math.Quaternion.w(qn)
1.0

rotate_vector(quaternion, vec3)

@spec rotate_vector(t(), BB.Math.Vec3.t()) :: BB.Math.Vec3.t()

Rotates a 3D vector by a quaternion.

Examples

iex> q = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> v = BB.Math.Vec3.unit_x()
iex> rotated = BB.Math.Quaternion.rotate_vector(q, v)
iex> {Float.round(BB.Math.Vec3.x(rotated), 6), Float.round(BB.Math.Vec3.y(rotated), 6)}
{0.0, 1.0}

slerp(quaternion1, quaternion2, t)

@spec slerp(t(), t(), number()) :: t()

Spherical linear interpolation between two quaternions.

t should be between 0.0 and 1.0.

Examples

iex> q1 = BB.Math.Quaternion.identity()
iex> q2 = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi())
iex> q_mid = BB.Math.Quaternion.slerp(q1, q2, 0.5)
iex> {_axis, angle} = BB.Math.Quaternion.to_axis_angle(q_mid)
iex> Float.round(angle, 6)
1.570796

tensor(quaternion)

@spec tensor(t()) :: Nx.Tensor.t()

Returns the underlying {4} tensor.

to_axis_angle(quaternion)

@spec to_axis_angle(t()) :: {BB.Math.Vec3.t(), float()}

Converts a quaternion to axis-angle representation.

Returns {axis, angle} where axis is a BB.Math.Vec3 unit vector and angle is in radians (0 to pi).

Examples

iex> q = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> {axis, angle} = BB.Math.Quaternion.to_axis_angle(q)
iex> Float.round(angle, 6)
1.570796
iex> Float.round(BB.Math.Vec3.z(axis), 1)
1.0

to_euler(q, order \\ :xyz)

@spec to_euler(t(), atom()) :: {float(), float(), float()}

Converts a quaternion to Euler angles (roll, pitch, yaw).

Returns {roll, pitch, yaw} in radians. Default order is :xyz.

Note: Euler angles can have gimbal lock issues near pitch = ±90°.

Examples

iex> q = BB.Math.Quaternion.from_euler(0.1, 0.2, 0.3, :xyz)
iex> {roll, pitch, yaw} = BB.Math.Quaternion.to_euler(q, :xyz)
iex> Float.round(roll, 6)
0.1

to_list(quaternion)

@spec to_list(t()) :: [float()]

Converts to a list in WXYZ order.

Examples

iex> q = BB.Math.Quaternion.identity()
iex> BB.Math.Quaternion.to_list(q)
[1.0, 0.0, 0.0, 0.0]

to_rotation_matrix(quaternion)

@spec to_rotation_matrix(t()) :: Nx.Tensor.t()

Converts a quaternion to a 3x3 rotation matrix.

Examples

iex> q = BB.Math.Quaternion.identity()
iex> m = BB.Math.Quaternion.to_rotation_matrix(q)
iex> Nx.to_number(m[0][0])
1.0

to_xyzw_list(quaternion)

@spec to_xyzw_list(t()) :: [float()]

Converts to a list in XYZW order (for ROS/external system compatibility).

Examples

iex> q = BB.Math.Quaternion.identity()
iex> BB.Math.Quaternion.to_xyzw_list(q)
[0.0, 0.0, 0.0, 1.0]

w(quaternion)

@spec w(t()) :: float()

Returns the W (scalar) component.

x(quaternion)

@spec x(t()) :: float()

Returns the X component.

y(quaternion)

@spec y(t()) :: float()

Returns the Y component.

z(quaternion)

@spec z(t()) :: float()

Returns the Z component.