kornia.geometry.quaternion#
Module state#
Quaternion data given as a plain tensor is a persistent buffer under _data; an nn.Parameter stays a
parameter under the same key. So3 saves its rotation as _q._data and Se3 as _rotation._q._data,
prefixed by the enclosing module’s attribute names when nested. load_state_dict(strict=True) raises on a state
dict that lacks these keys; with strict=False they are reported as missing and the target keeps its own rotation.
- class kornia.geometry.quaternion.Quaternion(data)[source]#
Base class to represent a Quaternion.
A quaternion is a four dimensional vector representation of a rotation transformation in 3d. See more: https://en.wikipedia.org/wiki/Quaternion
The general definition of a quaternion is given by:
\[Q = a + b \cdot \mathbf{i} + c \cdot \mathbf{j} + d \cdot \mathbf{k}\]Thus, we represent a rotation quaternion as a contiguous torch.Tensor structure to perform rigid bodies transformations:
\[Q = \begin{bmatrix} q_w & q_x & q_y & q_z \end{bmatrix}\]- Convention:
datais(w, x, y, z), real part first, with shape \((*, 4)\); only the last axis is checked. Other libraries’ orders, such as scipy’s default(x, y, z, w), are mapped on Rotations and rigid motions.*between quaternions is the Hamilton product, so(q1 * q2).matrix()isq1.matrix() @ q2.matrix(),q1 / q2isq1 * q2.inv(), andqand-qare the same rotation. A float or tensor operand of+,-,*or/is the real quaternion[s, 0, 0, 0], and a tensor of the shape ofq.wholds one such scalar per quaternion of the batch.Nothing normalises the stored data or the results of
*,**andinv().matrix(),to_axis_angle(),to_euler(),polar_angleandslerpread only the direction ofq: rescalingqby a positive factor changes their result by roundoff only, as long as its squared components stay within the range of the dtype and its norm stays above1e-12.At construction, plain tensor data is registered as a persistent buffer; an explicit
nn.Parameterremains a parameter. Both are saved and restored bystate_dict()andload_state_dict()and follow an enclosing module’s device and dtype conversions. Construction preserves the input tensor and its autograd history.Quaternion.to()returns a new quaternion; enclosing module conversions update the existing module’s state.Known defects: below a norm of
1e-12,matrix()andslerpgive wrong results, and the zero quaternion’smatrix()is the identity (#3952).
Example
>>> q = Quaternion.identity(batch_size=4) >>> q.data tensor([[1., 0., 0., 0.], [1., 0., 0., 0.], [1., 0., 0., 0.], [1., 0., 0., 0.]]) >>> q.real tensor([1., 1., 1., 1.]) >>> q.vec tensor([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])
- __add__(right)[source]#
Add a given quaternion, scalar, or torch.Tensor.
- Parameters:
right (
Union[Quaternion,Tensor,float]) – the quaternion, scalar, or torch.Tensor to add.- Return type:
Example
>>> q1 = Quaternion.identity() >>> q2 = Quaternion(torch.tensor([2., 0., 1., 1.])) >>> q3 = q1 + q2 >>> q3.data tensor([3., 0., 1., 1.])
- __init__(data)[source]#
Construct a quaternion from torch.Tensor or parameter data.
- Parameters:
data (
Union[Tensor,Parameter]) – torch.Tensor or parameter containing the quaternion data with the shape of \((*, 4)\). Stored without copying as a persistent buffer, or as a parameter if already annn.Parameter.
Example
>>> # Create with torch.tensor(no gradients tracked by default) >>> data = torch.tensor([1., 0., 0., 0.]) >>> q1 = Quaternion(data) >>> # Create with parameter (gradients tracked) >>> param_data = torch.nn.Parameter(torch.tensor([1., 0., 0., 0.])) >>> q2 = Quaternion(param_data)
- __neg__()[source]#
Inverts the sign of the quaternion data.
- Return type:
Example
>>> q = Quaternion.identity() >>> (-q).data tensor([-1., -0., -0., -0.])
- __pow__(t)[source]#
Return the power of a quaternion raised to exponent t.
For \(q = \|q\| (\cos\theta + n \sin\theta)\) this is \(q^t = \|q\|^t (\cos t\theta + n \sin t\theta)\), so
q**2 == q * qandq**-1 == q.inv().On the negative real axis (
w < 0and a zero vector part) \(\theta = \pi\) and the axis \(n\) is undefined: for a non-integertevery unit vector gives a valid power. This method takes \(n = e_x\) there, soq**thas norm \(\|q\|^t\) and angle \(t\pi\),(q**0.5)**2 == q, and the result is the limit from the+xside of the axis. An integertkeeps a zero vector part.- Parameters:
t (
Union[float,Tensor]) – raised exponent, a float or a tensor that broadcasts against(..., 1).- Return type:
Example
>>> q = Quaternion(torch.tensor([1., .5, 0., 0.])) >>> q_pow = q**2
- __radd__(left)[source]#
Right addition (left + self) where left is a scalar or torch.Tensor.
- Return type:
- __rdiv__(left)[source]#
Right division (left / self) where left is a scalar or torch.Tensor.
- Return type:
- __rmul__(left)[source]#
Right multiplication (left * self) where left is a scalar or torch.Tensor.
- Return type:
- __rsub__(left)[source]#
Right subtraction (left - self) where left is a scalar or torch.Tensor.
- Return type:
- __rtruediv__(left)[source]#
Right division (left / self) where left is a scalar or torch.Tensor.
- Return type:
- __sub__(right)[source]#
Subtract a given quaternion, scalar, or torch.Tensor.
- Parameters:
right (
Union[Quaternion,Tensor,float]) – the quaternion, scalar, or torch.Tensor to subtract.- Return type:
Example
>>> q1 = Quaternion(torch.tensor([2., 0., 1., 1.])) >>> q2 = Quaternion.identity() >>> q3 = q1 - q2 >>> q3.data tensor([1., 0., 1., 1.])
- property coeffs: Tuple[Tensor, Tensor, Tensor, Tensor]#
Return a tuple with the underlying coefficients in WXYZ order.
- conj()[source]#
Compute the conjugate of the quaternion.
- Return type:
- Returns:
The conjugate quaternion, with the vector part negated.
Example
>>> q = Quaternion(torch.tensor([1., 2., 3., 4.])) >>> q_conj = q.conj()
- classmethod from_axis_angle(axis_angle)[source]#
Create a quaternion from axis-angle representation.
- Parameters:
axis_angle (
Tensor) – rotation vector of shape \((B, 3)\).- Return type:
Example
>>> axis_angle = torch.tensor([[1., 0., 0.]]) >>> q = Quaternion.from_axis_angle(axis_angle) >>> q.data tensor([[0.8776, 0.4794, 0.0000, 0.0000]])
- classmethod from_coeffs(w, x, y, z)[source]#
Create a quaternion from the data coefficients.
- Parameters:
- Return type:
Example
>>> q = Quaternion.from_coeffs(1., 0., 0., 0.) >>> q.data tensor([1., 0., 0., 0.])
- classmethod from_euler(roll, pitch, yaw)[source]#
Create a quaternion from Euler angles.
- Parameters:
- Return type:
Example
>>> roll, pitch, yaw = torch.tensor(0), torch.tensor(1), torch.tensor(0) >>> q = Quaternion.from_euler(roll, pitch, yaw) >>> q.data tensor([0.8776, 0.0000, 0.4794, 0.0000])
- classmethod from_matrix(matrix, check_rotation=False)[source]#
Create a quaternion from a rotation matrix.
- Parameters:
matrix (
Tensor) – the rotation matrix to convert of shape \((B, 3, 3)\).check_rotation (
bool, optional) – ifTrue, raiseValueErrorunless every input is a rotation matrix. The defaultFalsekeeps the unchecked behaviour, under which a reflection such asdiag(-1, 1, 1)returns a non-unit quaternion rather than being reported as invalid. Default:False
- Return type:
Example
>>> m = torch.eye(3)[None] >>> q = Quaternion.from_matrix(m) >>> q.data tensor([[1., 0., 0., 0.]])
- classmethod identity(batch_size=None, device=None, dtype=None)[source]#
Create a quaternion representing an identity rotation.
- Parameters:
- Return type:
Example
>>> q = Quaternion.identity() >>> q.data tensor([1., 0., 0., 0.])
- inv()[source]#
Compute the inverse of the quaternion.
- Return type:
- Returns:
The inverse quaternion.
Example
>>> q = Quaternion.identity() >>> q_inv = q.inv()
- matrix()[source]#
Convert the quaternion to a rotation matrix of shape \((B, 3, 3)\).
- Return type:
Example
>>> q = Quaternion.identity() >>> m = q.matrix() >>> m tensor([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
- norm(keepdim=False)[source]#
Compute the norm (magnitude) of the quaternion.
- Parameters:
keepdim (
bool, optional) – whether to retain the last dimension. Default:False- Return type:
- Returns:
The norm of the quaternion(s) as a torch.Tensor.
Example
>>> q = Quaternion.identity() >>> q.norm() tensor(1.)
- normalize()[source]#
Return a normalized (unit) quaternion.
- Return type:
- Returns:
The normalized quaternion.
Example
>>> q = Quaternion(torch.tensor([2., 1., 0., 0.])) >>> q_norm = q.normalize()
- property polar_angle: Tensor#
Return the polar angle \(\arccos(w / |q|)\) in \([0, \pi]\), with shape \((B,)\).
qrotates by twice this angle about the axisvec.Example
>>> q = Quaternion.identity() >>> q.polar_angle tensor(0.)
- classmethod random(batch_size=None, device=None, dtype=None)[source]#
Create a random unit quaternion of shape \((B, 4)\).
Uniformly distributed across the rotation space as per: http://planning.cs.uiuc.edu/node198.html
- Parameters:
- Return type:
Example
>>> q = Quaternion.random() >>> q = Quaternion.random(batch_size=2)
- slerp(q1, t)[source]#
Return a unit quaternion spherically interpolated between quaternions self.q and q1.
The interpolation follows the shorter arc between the two rotations, whatever the signs of the stored quaternions:
q1and-q1give the same result, and att = 1the output isq1or-q1. The exception is a half turn whose relative quaternionself.inv() * q1has a real part of exactly zero: both arcs are then equally short and the path is not unique. The arc taken follows the sign of the vector part ofself.inv() * q1, soq1and-q1take opposite arcs, and the result is not continuous inq1there.See more: https://en.wikipedia.org/wiki/Slerp
- Parameters:
q1 (
Quaternion) – second quaternion to be interpolated between.t (
Union[float,Tensor]) – interpolation ratio,0atselfand1atq1. It is not validated: values outside[0, 1]extrapolate along the same arc. A per-batch ratio has shape \((B,)\), likeself.w, or \((B, 1)\).
- Return type:
Example
>>> q0 = Quaternion.identity() >>> q1 = Quaternion(torch.tensor([1., .5, 0., 0.])) >>> q2 = q0.slerp(q1, .3)
- squared_norm()[source]#
Compute the squared norm (magnitude) of the quaternion.
- Return type:
- Returns:
The squared norm of the quaternion(s) as a torch.Tensor.
Example
>>> q = Quaternion.identity() >>> q.squared_norm() tensor(1.)
- to(*args, **kwargs)[source]#
Move and/or cast the quaternion data.
- Parameters:
- Return type:
- Returns:
A new Quaternion with converted data.
- to_axis_angle()[source]#
Convert the quaternion to an axis-angle representation.
- Return type:
Example
>>> q = Quaternion.identity() >>> axis_angle = q.to_axis_angle() >>> axis_angle tensor([0., 0., 0.])
- kornia.geometry.quaternion.average_quaternions(Q, w=None)[source]#
Compute (weighted) average of multiple quaternions.
- Convention:
The chordal mean of scipy’s
Rotation.mean: the eigenvector of \(\sum_i w_i q_i q_i^\top / \sum_i w_i\) with the largest eigenvalue.q_iand-q_icount the same, and the sign of the result is arbitrary.wneed not sum to one: scaling it by a positive factor does not change the result. A negative weight, or weights that are all zero, raiseValueError.The members are normalised first, so only their directions count: a member stored as
3 * qweighs the same asq.
- Parameters:
Q (Quaternion) – quaternion object containing data of shape (M, 4).
w (torch.Tensor, optional) – Weights of shape (M,). If None, uniform weights are used. Default:
None
- Returns:
averaged quaternion of shape (1, 4), wrapped back in the Quaternion class.
- Return type: