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.TensorType 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.TensorScales 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.TensorReturns [1, 0, 0, 0].
quat_from_euler#
quat_from_euler(roll: float, pitch: float, yaw: float, *, device=None, dtype=torch.float32) -> torch.TensorConverts 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.TensorHamilton 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.TensorConverts 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.ndarrayAs 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]])