Math

Reference for the ScalarLike and ComplexLike type aliases, normalize_vec3 and the quaternion helpers.

The math helpers live in witwin.core.math and are exported from witwin.core. All tensor functions keep autograd. Quaternions are scalar-first (w, x, y, z).

from witwin.core import (
    ComplexLike, ScalarLike, normalize_vec3, quat_from_euler, quat_identity,
    quat_multiply, quat_to_rotation_matrix, quat_to_rotation_matrix_np,
)

ScalarLike and ComplexLike#

ScalarLike = float | torch.Tensor
ComplexLike = complex | torch.Tensor

Type aliases. ScalarLike is a real scalar: a Python number or a 0-d floating-point tensor. ComplexLike is a Python complex or a complex (or real) tensor. Core annotates continuous physical quantities with them.

normalize_vec3#

normalize_vec3(values: torch.Tensor, *, eps: float = 1.0e-12) -> torch.Tensor

Scales vectors along the last axis to unit length. The norm is clamped to at least eps, so a zero vector stays zero instead of becoming NaN.

quat_identity#

quat_identity(*, device=None, dtype=torch.float32) -> torch.Tensor

Returns [1, 0, 0, 0].

quat_from_euler#

quat_from_euler(roll: float, pitch: float, yaw: float, *, device=None, dtype=torch.float32) -> torch.Tensor

Converts Euler angles in radians to a quaternion for the rotation Rz(yaw) @ Ry(pitch) @ Rx(roll). The arguments may be numbers or 0-d tensors. Note the argument order, (roll, pitch, yaw): geometry uses this order, antennas use (yaw, pitch, roll).

quat_multiply#

quat_multiply(a: torch.Tensor, b: torch.Tensor) -> torch.Tensor

Hamilton product a * b of two (4,) quaternions. The rotation of the result applies b first, then a.

quat_to_rotation_matrix#

quat_to_rotation_matrix(q: torch.Tensor) -> torch.Tensor

Converts a (4,) quaternion to a (3, 3) rotation matrix. The quaternion is not normalised first; pass a unit quaternion.

quat_to_rotation_matrix_np#

quat_to_rotation_matrix_np(q: torch.Tensor) -> numpy.ndarray

As quat_to_rotation_matrix, detached and copied to a NumPy array on the CPU.

Example#

import math
 
import torch
 
from witwin.core import normalize_vec3, quat_from_euler, quat_multiply, quat_to_rotation_matrix
 
quarter_z = quat_from_euler(0.0, 0.0, math.pi / 2)
half_z = quat_multiply(quarter_z, quarter_z)
print(quarter_z)
print((quat_to_rotation_matrix(half_z) @ torch.tensor([1.0, 0.0, 0.0])).round(decimals=3))
print(normalize_vec3(torch.tensor([[3.0, 0.0, 4.0], [0.0, 0.0, 0.0]])))
tensor([0.7071, 0.0000, 0.0000, 0.7071])
tensor([-1.,  0.,  0.])
tensor([[0.6000, 0.0000, 0.8000],
        [0.0000, 0.0000, 0.0000]])