kornia.geometry.liegroup#
A Lie group combines the concepts of a group and a smooth manifold in a single object.
A group is a non-empty set with an operation that satisfies the following constraints: the operation is associative, has an identity element, and every element of the set has an inverse element.
See more: Group
A Lie group \(G\) is a smooth manifold whose elements satisfy the group axioms. You can visualize a manifold as a curved, smooth (hyper-)surface, with no edges or spikes, embedded in a space of higher dimension.
See more: Manifold
In robotics, we say that our state vector evolves on this surface; that is, the manifold describes, or is defined by, the constraints imposed on the state.
Lie algebra#
If \(M\) is the manifold that represents a Lie group, the tangent space at the identity is called the Lie algebra of \(M\). The Lie algebra \(m\) is a vector space. As such, its elements can be identified with vectors in \(R^d\), whose dimension \(d\) is the number of degrees of freedom of \(M\). For example, \(d = 3\) for the Lie group \(SO(3)\).
Lie group and Lie algebra#
Every Lie group has an associated Lie algebra. We relate the Lie group to its Lie algebra through the following facts:
The Lie algebra \(m\) is a vector space. As such, its elements can be identified with vectors in \(R^d\), whose dimension \(d\) is the number of degrees of freedom of \(M\).
The exponential map, \(\exp : m \rightarrow M\), exactly converts elements of the Lie algebra into elements of the group. The \(\log\) map is the inverse operation.
Reference: A micro Lie theory for state estimation in robotics
Classes#
- class kornia.geometry.liegroup.So3(q)[source]#
Base class to represent the So3 group.
The SO(3) is the group of all rotations about the origin of three-dimensional Euclidean space \(R^3\) under the operation of composition. See more: https://en.wikipedia.org/wiki/3D_rotation_group
We internally represent the rotation by a
Quaternion.- Convention:
The tangent vector is the rotation vector, the axis times the angle in radians, and
hat(v)is its cross-product matrix:hat(v) @ pequalstorch.linalg.cross(v, p).log()isq.to_axis_angle(): it reads only the direction ofq, within the range limits stated onQuaternion, and returns the principal vector, of norm at most \(\pi\), the same forqand-qbelow a half turn.a * bcomposes likea.matrix() @ b.matrix(), sobacts first;s * protates pointspof shape \((B, 3)\), a tensor or aVector3, as \(R p\); andadjoint()is \(R\) itself. Rotations and rigid motions compares these with scipy, Sophus and Eigen.A non-unit quaternion stands for the rotation of its direction \(q / |q|\), as for
matrix():matrix()ands * pnormalise it where they use it, somatrix()is always a rotation ands * pkeeps the norm ofp.qreturns the quaternion as stored, which keeps annn.Parameterregistered and following optimiser steps.For a small \(\delta\), \(\exp(\omega + \delta) \approx \exp(\omega) \exp(J_r \delta) = \exp(J_l \delta) \exp(\omega)\), with \(J_r\) =
right_jacobian(omega)and \(J_l\) =left_jacobian(omega)=right_jacobian(-omega).from_matrixdoes not check its input by default: a reflection (det \(-1\)) is accepted without error and returns anSo3whosematrix()is not the input.check_rotation=TrueraisesValueErrorinstead.The quaternion is registered as module state following
Quaternion’s buffer/parameter convention, including rotations produced byexp,identity,random,from_matrixand group operations.matrix(),adjoint(),a * bands * pcompute in float32 for float16/bfloat16 inputs and return the input dtype, rounding once; float32 and float64 are evaluated in their own dtype.
Example
>>> q = Quaternion.identity() >>> s = So3(q) >>> s.q tensor([1., 0., 0., 0.])
- __init__(q)[source]#
Construct the base class.
- Parameters:
q (
Quaternion) – Quaternion with the shape of \((B, 4)\).
Example
>>> data = torch.tensor([[1., 0., 0., 0.], [0., 1., 0., 0.]]) >>> q = Quaternion(data) >>> So3(q) tensor([[1., 0., 0., 0.], [0., 1., 0., 0.]])
- __mul__(right)[source]#
Compose two So3 transformations, or rotate points.
Both compute in float32 for float16/bfloat16 inputs and return the input dtype.
- adjoint()[source]#
Return the adjoint matrix of shape \((B, 3, 3)\).
- Return type:
Example
>>> s = So3.identity() >>> s.adjoint() tensor([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
- static exp(v)[source]#
Convert elements of lie algebra to elements of lie group.
See more: https://vision.in.tum.de/_media/members/demmeln/nurlanov2021so3log.pdf
Example
>>> v = torch.zeros((2, 3)) >>> s = So3.exp(v) >>> s tensor([[1., 0., 0., 0.], [1., 0., 0., 0.]])
- classmethod from_matrix(matrix, check_rotation=False)[source]#
Create So3 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)is silently turned into the identity. Note thatSo2.from_matrixrejects the 2D reflectiondiag(1, -1)regardless. Default:False
- Return type:
Example
>>> m = torch.eye(3) >>> s = So3.from_matrix(m) >>> s tensor([1., 0., 0., 0.])
- classmethod from_wxyz(wxyz)[source]#
Create So3 from a torch.Tensor representing a quaternion.
Example
>>> q = torch.tensor([1., 0., 0., 0.]) >>> s = So3.from_wxyz(q) >>> s tensor([1., 0., 0., 0.])
- static hat(v)[source]#
Convert elements from vector space to lie algebra. Returns matrix of shape \((B,3,3)\).
Example
>>> v = torch.ones((1,3)) >>> m = So3.hat(v) >>> m tensor([[[ 0., -1., 1.], [ 1., 0., -1.], [-1., 1., 0.]]])
- classmethod identity(batch_size=None, device=None, dtype=None)[source]#
Create a So3 group representing an identity rotation.
- Parameters:
- Return type:
Example
>>> s = So3.identity() >>> s tensor([1., 0., 0., 0.])
>>> s = So3.identity(batch_size=2) >>> s tensor([[1., 0., 0., 0.], [1., 0., 0., 0.]])
- inverse()[source]#
Return the inverse transformation.
- Return type:
Example
>>> s = So3.identity() >>> s.inverse() tensor([1., -0., -0., -0.])
- static left_jacobian(vec)[source]#
Compute the left Jacobian of So3.
Example
>>> vec = torch.tensor([1., 2., 3.]) >>> So3.left_jacobian(vec) tensor([[-0.0687, -0.2267, 0.5074], [ 0.5556, 0.1779, 0.3629], [-0.0141, 0.6236, 0.5890]])
- log()[source]#
Convert elements of lie group to elements of lie algebra.
- Return type:
Example
>>> So3.identity(batch_size=2).log() tensor([[0., 0., 0.], [0., 0., 0.]])
- matrix()[source]#
Convert the quaternion to a rotation matrix of shape \((B,3,3)\).
The matrix is of the form:
\[\begin{split}\begin{bmatrix} 1-2y^2-2z^2 & 2xy-2zw & 2xz+2yw \\ 2xy+2zw & 1-2x^2-2z^2 & 2yz-2xw \\ 2xz-2yw & 2yz+2xw & 1-2x^2-2y^2\end{bmatrix}\end{split}\]It computes in float32 for float16/bfloat16 inputs and returns the input dtype.
Example
>>> s = So3.identity() >>> m = s.matrix() >>> m tensor([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
- Return type:
- property q: Quaternion#
Return the underlying data with shape \((B,4)\).
- classmethod random(batch_size=None, device=None, dtype=None)[source]#
Create a So3 group representing a random rotation.
- Parameters:
- Return type:
Example
>>> s = So3.random() >>> s = So3.random(batch_size=3)
- static right_jacobian(vec)[source]#
Compute the right Jacobian of So3.
Example
>>> vec = torch.tensor([1., 2., 3.]) >>> So3.right_jacobian(vec) tensor([[-0.0687, 0.5556, -0.0141], [-0.2267, 0.1779, 0.6236], [ 0.5074, 0.3629, 0.5890]])
- static vee(omega)[source]#
Convert elements from lie algebra to vector space. Returns vector of shape \((B,3)\).
\[\begin{split}omega = \begin{bmatrix} 0 & -c & b \\ c & 0 & -a \\ -b & a & 0\end{bmatrix}\end{split}\]Example
>>> v = torch.ones((1,3)) >>> omega = So3.hat(v) >>> So3.vee(omega) tensor([[1., 1., 1.]])
- class kornia.geometry.liegroup.Se3(rotation, translation)[source]#
Base class to represent the Se3 group.
The SE(3) is the group of rigid body transformations about the origin of three-dimensional Euclidean space \(R^3\) under the operation of composition. See more: https://ingmec.ual.es/~jlblanco/papers/jlblanco2010geometry3D_techrep.pdf
- Convention:
The tangent vector is \([\upsilon, \omega]\), translation first (Rotations and rigid motions maps it onto Sophus and GTSAM):
exprotates bySo3.exp(omega)and translates by \(V(\omega) \upsilon\),hatis \([[\hat\omega, \upsilon], [0, 0]]\), andlogis principal, with \(|\omega| \le \pi\).matrix()is the 4x4 \([[R, t], [0, 1]]\).a * bisa.matrix() @ b.matrix(), sobacts first, andg * pis \(R p + t\).adjoint()is \([[R, \hat t R], [0, R]]\).The rotation is an
So3, whose storage and point-shape conventions apply: a non-unit quaternion stands for the rotation of its direction.from_matrixignores the bottom row.tis always a tensor registered as module state, whichever constructor built the pose; aVector3passed to the constructor is unwrapped.g * preturns aVector3only whenpis one.state_dict(),load_state_dict()and module device/dtype conversions include both the rotation and translation. Rotation state followsQuaternion’s buffer/parameter convention.a * bandg * pcompute in float32 for float16/bfloat16 inputs and return the input dtype, rounding \(R p + t\) once;matrix()andinverse()take the rotation fromSo3, which does the same.
Example
>>> q = Quaternion.identity() >>> s = Se3(q, torch.ones(3)) >>> s.r tensor([1., 0., 0., 0.]) >>> s.t Parameter containing: tensor([1., 1., 1.], requires_grad=True)
- __init__(rotation, translation)[source]#
Construct the base class.
Internally represented by an So3 rotation and a translation 3-vector.
- Parameters:
rotation (
Quaternion|So3) – So3 group encompassing a rotation, or a Quaternion to wrap in one; it is stored as given, and a non-unit quaternion stands for the rotation of its direction.translation (
Vector3|Tensor) – translation torch.Tensor with the shape of \((B, 3)\), or a Vector3 wrapping one; the tensor is what gets stored. It must have the rotation’s dtype and device.
- Raises:
TypeCheckError – if the translation is an integer, bool or complex tensor (an
nn.Parametertoo), or its dtype differs from the rotation’s (inverse,adjointand the other methods cannot combine them).DeviceError – if the translation is on another device than the rotation.
Example
>>> from kornia.geometry.quaternion import Quaternion >>> q = Quaternion.identity(batch_size=1) >>> s = Se3(q, torch.ones((1, 3))) >>> s.r tensor([[1., 0., 0., 0.]]) >>> s.t Parameter containing: tensor([[1., 1., 1.]], requires_grad=True)
- __mul__(right)[source]#
Compose two Se3 transformations, or transform points.
Both compute in float32 for float16/bfloat16 inputs and return the input dtype.
- adjoint()[source]#
Return the adjoint matrix of shape \((B, 6, 6)\).
- Return type:
Example
>>> s = Se3.identity() >>> s.adjoint() tensor([[1., 0., 0., 0., 0., 0.], [0., 1., 0., 0., 0., 0.], [0., 0., 1., 0., 0., 0.], [0., 0., 0., 1., 0., 0.], [0., 0., 0., 0., 1., 0.], [0., 0., 0., 0., 0., 1.]], grad_fn=<CatBackward0>)
- static exp(v)[source]#
Convert elements of lie algebra to elements of lie group.
Example
>>> v = torch.zeros((1, 6)) >>> s = Se3.exp(v) >>> s.r tensor([[1., 0., 0., 0.]]) >>> s.t Parameter containing: tensor([[0., 0., 0.]], requires_grad=True)
- classmethod from_matrix(matrix, check_rotation=False)[source]#
Create a Se3 group from a matrix.
- Parameters:
matrix (
Tensor) – torch.Tensor of shape \((B, 4, 4)\).check_rotation (
bool, optional) – ifTrue, raiseValueErrorunless the rotation block of every input is a rotation matrix. The defaultFalsekeeps the unchecked behaviour, under which a reflection block such asdiag(-1, 1, 1)yields a non-unit quaternion. Default:False
- Return type:
Example
>>> s = Se3.from_matrix(torch.eye(4)) >>> s.r tensor([1., 0., 0., 0.]) >>> s.t Parameter containing: tensor([0., 0., 0.], requires_grad=True)
- classmethod from_qxyz(qxyz)[source]#
Create a Se3 group from a quaternion and a translation vector.
- Parameters:
qxyz (
Tensor) – torch.Tensor of shape \((B, 7)\) laid out as[qw, qx, qy, qz, x, y, z], scalar first; the quaternion is stored as given, and a non-unit one stands for the rotation of its direction.- Return type:
Example
>>> qxyz = torch.tensor([0., 0., 0., 1., 0., 0., 1.]) >>> s = Se3.from_qxyz(qxyz) >>> s.r tensor([0., 0., 0., 1.]) >>> s.t Parameter containing: tensor([0., 0., 1.], requires_grad=True)
- static hat(v)[source]#
Convert elements from vector space to lie algebra.
- Parameters:
v (
Tensor) – vector of shape \((B, 6)\).- Return type:
- Returns:
matrix of shape \((B, 4, 4)\).
Example
>>> v = torch.ones((1, 6)) >>> m = Se3.hat(v) >>> m tensor([[[ 0., -1., 1., 1.], [ 1., 0., -1., 1.], [-1., 1., 0., 1.], [ 0., 0., 0., 0.]]])
- classmethod identity(batch_size=None, device=None, dtype=None)[source]#
Create a Se3 group representing an identity rotation and zero translation.
- Parameters:
- Return type:
Example
>>> s = Se3.identity() >>> s.r tensor([1., 0., 0., 0.]) >>> s.t Parameter containing: tensor([0., 0., 0.], requires_grad=True)
- inverse()[source]#
Return the inverse transformation.
- Return type:
Example
>>> s = Se3(So3.identity(), torch.ones(3)) >>> s_inv = s.inverse() >>> s_inv.r tensor([1., -0., -0., -0.]) >>> s_inv.t tensor([-1., -1., -1.], grad_fn=<SliceBackward0>)
- log()[source]#
Convert elements of lie group to elements of lie algebra.
- Return type:
Example
>>> from kornia.geometry.quaternion import Quaternion >>> q = Quaternion.identity() >>> Se3(q, torch.zeros(3)).log() tensor([0., 0., 0., 0., 0., 0.], grad_fn=<CatBackward0>)
- matrix()[source]#
Return the matrix representation of shape \((B, 4, 4)\).
- Return type:
Example
>>> s = Se3(So3.identity(), torch.ones(3)) >>> s.matrix() tensor([[1., 0., 0., 1.], [0., 1., 0., 1.], [0., 0., 1., 1.], [0., 0., 0., 1.]], grad_fn=<CopySlices>)
- property quaternion: Quaternion#
Return the underlying rotation(Quaternion).
- classmethod random(batch_size=None, device=None, dtype=None)[source]#
Create a Se3 group representing a random transformation.
- Parameters:
- Return type:
Example
>>> s = Se3.random() >>> s = Se3.random(batch_size=3)
- static vee(omega)[source]#
Convert elements from lie algebra to vector space.
- Parameters:
omega (
Tensor) – 4x4-matrix representing lie algebra of shape \((B,4,4)\).- Return type:
- Returns:
vector of shape \((B,6)\).
Example
>>> v = torch.ones((1, 6)) >>> omega_hat = Se3.hat(v) >>> Se3.vee(omega_hat) tensor([[1., 1., 1., 1., 1., 1.]])
- class kornia.geometry.liegroup.So2(z)[source]#
Base class to represent the So2 group.
The SO(2) is the group of all rotations about the origin of two-dimensional Euclidean space \(R^2\) under the operation of composition. See more: https://en.wikipedia.org/wiki/Orthogonal_group#Special_orthogonal_group
- Convention:
Represents the rotation as a complex number
zof shape \(()\) or \((B,)\); a \((B, 1)\)zor angle is accepted and read as \((B,)\). For unit \(z = \cos\theta + i \sin\theta\),matrix()is \([[\cos\theta, -\sin\theta], [\sin\theta, \cos\theta]]\). Non-unitz = a + i bis accepted and produces \([[a, -b], [b, a]]\), which rotates and scales by \(|z|\). The complex storage has no bfloat16 counterpart in PyTorch, soexp,identity,randomandfrom_matrixraiseTypeCheckErrorfor bfloat16 values.A positive angle rotates the x axis toward the y axis: counter-clockwise in a y-up frame, clockwise as displayed on y-down image axes. For a unit rotation,
matrix()is the transpose ofangle_to_rotation_matrix(), which takes degrees.logreturns the angle in \([-\pi, \pi]\), andadjoint()is the 2x2 identity.hatreturns the so(2) generator \([[0, -\theta], [\theta, 0]]\) andveereads its[1, 0]entry, somatrix_exp(hat(theta))equalsexp(theta).matrix().Module dtype conversions act on the real and imaginary components together:
.float()and.to(torch.float32)use complex64 state, while.double()and.to(torch.float64)use complex128. Device-only conversions preserve the complex precision, and explicit complex dtypes are also accepted. The complex checkpoint key_zand its shape are unchanged..half()uses PyTorch’s experimental complex32 dtype. Since PyTorch has no complex bfloat16 dtype,.bfloat16()and.to(torch.bfloat16)keep the rotation’s existing complex precision while following any requested device move.
Example
>>> real = torch.tensor([0.6]) >>> imag = torch.tensor([0.8]) >>> So2(torch.complex(real, imag)) Parameter containing: tensor([0.6000+0.8000j], requires_grad=True)
- __init__(z)[source]#
Construct the base class.
Internally represented by torch.complex number z.
- Parameters:
z (
Tensor) – Complex number with the shape of \((B,)\) or \(()\); \((B, 1)\) is read as \((B,)\).- Raises:
TypeCheckError – if
zis not a complex tensor (an integer, bool or real floating-point tensor).
Example
>>> real = torch.tensor(0.6) >>> imag = torch.tensor(0.8) >>> So2(torch.complex(real, imag)).z Parameter containing: tensor(0.6000+0.8000j, requires_grad=True)
- __mul__(right)[source]#
Perform a left-multiplication either rotation concatenation or point-transform.
- adjoint()[source]#
Return the adjoint matrix of shape \((B, 2, 2)\).
- Return type:
Example
>>> s = So2.identity() >>> s.adjoint() tensor([[1., -0.], [0., 1.]], grad_fn=<StackBackward0>)
- static exp(theta)[source]#
Convert elements of lie algebra to elements of lie group.
- Parameters:
theta (
Tensor) – angle in radians of shape \((B,)\) or \(()\); \((B, 1)\) is squeezed to \((B,)\).- Raises:
TypeCheckError – if
thetais bfloat16, which has no complex dtype in PyTorch.- Return type:
Example
>>> v = torch.tensor([3.1415/2]) >>> s = So2.exp(v) >>> s Parameter containing: tensor([4.6329e-05+1.j], requires_grad=True)
- classmethod from_matrix(matrix)[source]#
Create So2 from a rotation matrix.
- Parameters:
matrix (
Tensor) – the rotation matrix to convert of shape \((B, 2, 2)\).- Raises:
TypeCheckError – if
matrixis bfloat16, which has no complex dtype in PyTorch.- Return type:
Example
>>> m = torch.eye(2) >>> s = So2.from_matrix(m) >>> s.z Parameter containing: tensor(1.+0.j, requires_grad=True)
- static hat(theta)[source]#
Convert an angle to the so(2) generator \([[0, -\theta], [\theta, 0]]\), which
vee()inverts.The output has shape \((2, 2)\) or \((B, 2, 2)\); a \((B, 1)\) angle is squeezed to \((B,)\). Its matrix exponential is the rotation
exp()returns.- Parameters:
theta (
Tensor) – angle in radians of shape \((B,)\) or \(()\); \((B, 1)\) is squeezed to \((B,)\).- Return type:
Example
>>> theta = torch.tensor(3.1415/2) >>> So2.hat(theta) tensor([[ 0.0000, -1.5707], [ 1.5707, 0.0000]])
- classmethod identity(batch_size=None, device=None, dtype=None)[source]#
Create a So2 group representing an identity rotation.
- Parameters:
- Raises:
TypeCheckError – if
dtypeis bfloat16, which has no complex dtype in PyTorch.- Return type:
Example
>>> s = So2.identity(batch_size=2) >>> s Parameter containing: tensor([1.+0.j, 1.+0.j], requires_grad=True)
- inverse()[source]#
Return the inverse transformation.
Complex-half state is inverted in complex64 and returned in its original dtype.
- Return type:
Example
>>> s = So2.identity() >>> s.inverse().z tensor(1.+0.j, grad_fn=<MulBackward0>)
- log()[source]#
Convert elements of lie group to elements of lie algebra.
- Return type:
Example
>>> real = torch.tensor([0.6]) >>> imag = torch.tensor([0.8]) >>> So2(torch.complex(real, imag)).log() tensor([0.9273], grad_fn=<Atan2Backward0>)
- matrix()[source]#
Return a matrix of shape
z.shape + (2, 2)for each stored complex number.- Return type:
Example
>>> s = So2.identity() >>> m = s.matrix() >>> m tensor([[1., -0.], [0., 1.]], grad_fn=<StackBackward0>)
- classmethod random(batch_size=None, device=None, dtype=None)[source]#
Create a So2 group with a unit rotation whose angle is drawn from \(U[-\pi, \pi)\).
- Parameters:
- Raises:
TypeCheckError – if
dtypeis bfloat16, which has no complex dtype in PyTorch.- Return type:
Example
>>> s = So2.random() >>> s = So2.random(batch_size=3)
- static vee(omega)[source]#
Read the angle back from a
hat()matrix of shape \((2, 2)\) or \((B, 2, 2)\).Returns a scalar or a \((B,)\) vector, respectively.
It reads the
[1, 0]entry, \(\theta\) in the so(2) generator \([[0, -\theta], [\theta, 0]]\).Example
>>> v = torch.ones(3) >>> omega = So2.hat(v) >>> So2.vee(omega) tensor([1., 1., 1.])
- class kornia.geometry.liegroup.Se2(rotation, translation)[source]#
Base class to represent the Se2 group.
The SE(2) is the group of rigid body transformations about the origin of two-dimensional Euclidean space \(R^2\) under the operation of composition.
- Convention:
matrix()is the 3x3 \([[R, t], [0, 1]]\).a * bisa.matrix() @ b.matrix()andg * pis \(R p + t\), as inSe3, but an unbatched pose also transforms \((N, 2)\) points and a batched one a single \((2,)\) point. The rotation is anSo2, whose storage and direction conventions apply.The tangent vector is \((v_x, v_y, \theta)\), angle last:
exprotates by \(\theta\) and translates by \(V(\theta) (v_x, v_y)\), andlogreturns \(\theta\) in \([-\pi, \pi]\).adjoint()is \([[R, (t_y, -t_x)^\top], [0, 1]]\).from_matrixignores the bottom row. In eager execution, it checks approximately that the rotation block has the form \([[a, -b], [b, a]]\), a rotation scaled by \(\sqrt{a^2 + b^2}\), and keeps the scale as a non-unitzthatlogdrops; it rejects a reflection. Graph export omits the value check and interprets the block asz = m00 + i m10.tis always a tensor registered as module state, whichever constructor built the pose; aVector2passed to the constructor is unwrapped.g * preturns aVector2only whenpis one.hatreturns the se(2) generator \([[0, -\theta, v_x], [\theta, 0, v_y], [0, 0, 0]]\) andveereads it back, somatrix_exp(hat(v))equalsexp(v).matrix().Module conversions follow
So2’s dtype policy for the rotation and PyTorch’s native policy for the translation. A bfloat16 cast changes the translation precision while keeping the rotation’s existing complex precision; both follow any requested device move. Building a pose from bfloat16 values (exp,identity,random,from_matrixortrans*) raisesTypeCheckError, as forSo2.
Example
>>> so2 = So2.identity(1) >>> t = torch.ones((1, 2)) >>> se2 = Se2(so2, t) >>> se2 rotation: Parameter containing: tensor([1.+0.j], requires_grad=True) translation: Parameter containing: tensor([[1., 1.]], requires_grad=True)
- __init__(rotation, translation)[source]#
Construct the base class.
Internally represented by a torch.complex number z and a translation 2-vector.
- Parameters:
rotation (
So2) – So2 group encompassing a rotation.translation (
Vector2|Tensor) – translation torch.Tensor with the shape of \((B, 2)\), or a Vector2 wrapping one; the tensor is what gets stored. It must have the rotation’s dtype (z’s real dtype) and device; a bfloat16 translation is also accepted beside a complex32, complex64 or complex128 rotation, which is what.bfloat16()leaves (PyTorch has no complex bfloat16). Every method then reads the translation at the rotation’s precision, andinverseandg * greturn a translation of the rotation’s real dtype.
- Raises:
TypeCheckError – if the translation is an integer, bool or complex tensor (an
nn.Parametertoo), or its dtype differs from the rotation’s (logand the other methods cannot combine them).DeviceError – if the translation is on another device than the rotation.
Example
>>> so2 = So2.identity(1) >>> t = torch.ones((1, 2)) >>> se2 = Se2(so2, t) >>> se2 rotation: Parameter containing: tensor([1.+0.j], requires_grad=True) translation: Parameter containing: tensor([[1., 1.]], requires_grad=True)
- adjoint()[source]#
Return the adjoint matrix of shape \((B, 3, 3)\).
- Return type:
Example
>>> s = Se2.identity() >>> s.adjoint() tensor([[1., -0., 0.], [0., 1., -0.], [0., 0., 1.]], grad_fn=<CopySlices>)
- static exp(v)[source]#
Convert elements of lie algebra to elements of lie group.
Example
>>> v = torch.ones((1, 3)) >>> s = Se2.exp(v) >>> s.r Parameter containing: tensor([0.5403+0.8415j], requires_grad=True) >>> s.t Parameter containing: tensor([[0.3818, 1.3012]], requires_grad=True)
- classmethod from_matrix(matrix)[source]#
Create an Se2 group from a matrix.
Example
>>> s = Se2.from_matrix(torch.eye(3).repeat(2, 1, 1)) >>> s.r Parameter containing: tensor([1.+0.j, 1.+0.j], requires_grad=True) >>> s.t Parameter containing: tensor([[0., 0.], [0., 0.]], requires_grad=True)
- static hat(v)[source]#
Convert a tangent vector to the se(2) generator. Returns
v.shape[:-1] + (3, 3).For \(v = (v_x, v_y, \theta)\) the matrix is \([[0, -\theta, v_x], [\theta, 0, v_y], [0, 0, 0]]\).
vee()inverts it, and its matrix exponential is the poseexp()returns.Example
>>> v = torch.tensor([1.0, 2.0, 0.5]) >>> Se2.hat(v) tensor([[ 0.0000, -0.5000, 1.0000], [ 0.5000, 0.0000, 2.0000], [ 0.0000, 0.0000, 0.0000]])
- classmethod identity(batch_size=None, device=None, dtype=None)[source]#
Create a Se2 group representing an identity rotation and zero translation.
- Parameters:
- Return type:
Example
>>> s = Se2.identity(1) >>> s.r Parameter containing: tensor([1.+0.j], requires_grad=True) >>> s.t Parameter containing: tensor([[0., 0.]], requires_grad=True)
- inverse()[source]#
Return the inverse transformation.
- Return type:
Example
>>> s = Se2(So2.identity(1), torch.ones(1,2)) >>> s_inv = s.inverse() >>> s_inv.r tensor([1.+0.j], grad_fn=<MulBackward0>) >>> s_inv.t tensor([[-1., -1.]], grad_fn=<StackBackward0>)
- log()[source]#
Convert elements of lie group to elements of lie algebra.
- Return type:
Example
>>> v = torch.ones((1, 3)) >>> s = Se2.exp(v).log() >>> s.shape torch.Size([1, 3]) >>> torch.allclose(s, v) True >>> s.requires_grad True
- matrix()[source]#
Return the matrix representation of shape \((B, 3, 3)\).
- Return type:
Example
>>> s = Se2(So2.identity(1), torch.ones(1, 2)) >>> s.matrix() tensor([[[1., -0., 1.], [0., 1., 1.], [0., 0., 1.]]], grad_fn=<CopySlices>)
- classmethod random(batch_size=None, device=None, dtype=None)[source]#
Create a Se2 group from
So2.randomand a translation drawn from \(U[0, 1)\).- Parameters:
- Return type:
Example
>>> s = Se2.random() >>> s = Se2.random(batch_size=3)
- static vee(omega)[source]#
Read the tangent vector back from a
hat()matrix.It reads the translation from the last column and the angle from the
[1, 0]entry.- Parameters:
omega (
Tensor) – 3x3-matrix built byhat(), of shape \((B, 3, 3)\) or \((3, 3)\).- Return type:
- Returns:
vector of shape \((B, 3)\) or \((3,)\).
Example
>>> v = torch.ones(3) >>> omega_hat = Se2.hat(v) >>> Se2.vee(omega_hat) tensor([1., 1., 1.])