o
    oig5                     @  s   d dl mZ d dlmZ d dlZd dlmZmZmZm	Z	m
Z
mZmZmZmZmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ G d
d deZdS )    )annotations)OptionalN)
DeviceDtypeModuleTensorconcatenateeyestackwherezeros
zeros_like)KORNIA_CHECK_TYPE)vector_to_skew_symmetric_matrix)batched_dot_product
Quaternion)Vector3c                      sB  e Zd ZdZdI fddZdJd	d
ZdKddZdLddZedMddZ	e
dNddZdOddZe
dPddZe
dQddZdOd d!ZedRd#d$ZedSd&d'Ze	(dTdUd/d0ZdVd1d2Ze	(dTdUd3d4ZedWd6d7ZedXd9d:ZedYd<d=ZdOd>d?Ze
dZdAdBZe
dZdCdDZe
dZdEdFZe
dZdGdHZ  ZS )[So3a  Base class to represent the So3 group.

    The SO(3) is the group of all rotations about the origin of three-dimensional Euclidean space
    :math:`R^3` under the operation of composition.
    See more: https://en.wikipedia.org/wiki/3D_rotation_group

    We internally represent the rotation by a unit quaternion.

    Example:
        >>> q = Quaternion.identity()
        >>> s = So3(q)
        >>> s.q
        tensor([1., 0., 0., 0.])

    qr   returnNonec                   s   t    t|t || _dS )am  Construct the base class.

        Internally represented by a unit quaternion `q`.

        Args:
            q: Quaternion with the shape of :math:`(B, 4)`.

        Example:
            >>> data = torch.ones((2, 4))
            >>> q = Quaternion(data)
            >>> So3(q)
            tensor([[1., 1., 1., 1.],
                    [1., 1., 1., 1.]])

        N)super__init__r   r   _q)selfr   	__class__ P/home/ubuntu/.local/lib/python3.10/site-packages/kornia/geometry/liegroup/so3.pyr   3   s   


zSo3.__init__strc                 C  s   | j  S N)r   r   r   r   r   __repr__G   s   zSo3.__repr__idxint | slicec                 C  s   t | j| S r!   )r   r   )r   r$   r   r   r   __getitem__J   s   zSo3.__getitem__rightc                 C  s   t |trt| j|j S t |ttfrOtg |jdd dR |j|jd}t	t
||jfd}| j| | j  j}t |trD|S t |trMt|S dS tdt| )zCompose two So3 transformations.

        Args:
            right: the other So3 transformation.

        Return:
            The resulting So3 transformation.

        N   devicedtypezNot So3 or Tensor type. Got: )
isinstancer   r   r   r   r   shaper+   r,   r   r   dataconjvec	TypeErrortype)r   r'   wquatoutr   r   r   __mul__M   s   
(

zSo3.__mul__c                 C  s   | j S )z4Return the underlying data with shape :math:`(B,4)`.)r   r"   r   r   r   r   f   s   zSo3.qvr   c                 C  s   | j ddd}d| }t|}t| jjd }||k}t|| }d|| d  }t|||}||  }	tj||	fdd}
t	t
|
S )a  Convert elements of lie algebra to elements of lie group.

        See more: https://vision.in.tum.de/_media/members/demmeln/nurlanov2021so3log.pdf

        Args:
            v: vector of shape :math:`(B,3)`.

        Example:
            >>> v = torch.zeros((2, 3))
            >>> s = So3.exp(v)
            >>> s
            tensor([[1., 0., 0., 0.],
                    [1., 0., 0., 0.]])

        r(   Tdimkeepdimg      ?g     @@g      H@)r:   )normtorchcosfinfor,   epssinr   catr   r   )r8   theta
theta_halfr4   r@   
small_maskb_largeb_smallbxyzr   r   r   r   expk   s   
zSo3.expc                 C  sb   t | jj| jj }t|d dkd| jjd   | jj |d  d| jj | jjd  }|S )a  Convert elements of lie group  to elements of lie algebra.

        Example:
            >>> data = torch.ones((2, 4))
            >>> q = Quaternion(data)
            >>> So3(q).log()
            tensor([[0., 0., 0.],
                    [0., 0., 0.]])

        .Nr      )r   r   r1   sqrtr   realacos)r   rC   omegar   r   r   log   s   
"zSo3.logVector3 | Tensorc                 C  s   t | tr| d | d | d }}}n| j| j| j}}}t|}t|| |fd}t||| fd}t| ||fd}t|||fdS )a  Convert elements from vector space to lie algebra. Returns matrix of shape :math:`(B,3,3)`.

        Args:
            v: Vector3 or tensor of shape :math:`(B,3)`.

        Example:
            >>> v = torch.ones((1,3))
            >>> m = So3.hat(v)
            >>> m
            tensor([[[ 0., -1.,  1.],
                     [ 1.,  0., -1.],
                     [-1.,  1.,  0.]]])

        ).r   ).r)   ).rL   r(   )r-   r   xyzr   r
   )r8   arH   crV   row0row1row2r   r   r   hat   s   
zSo3.hatrP   c                 C  s,   | d | d | d }}}t |||fdS )a  Convert elements from lie algebra to vector space. Returns vector of shape :math:`(B,3)`.

        .. math::
            omega = \begin{bmatrix} 0 & -c & b \\
            c & 0 & -a \\
            -b & a & 0\end{bmatrix}

        Args:
            omega: 3x3-matrix representing lie algebra.

        Example:
            >>> v = torch.ones((1,3))
            >>> omega = So3.hat(v)
            >>> So3.vee(omega)
            tensor([[1., 1., 1.]])

        ).rL   r)   ).r   rL   ).r)   r   r(   )r
   )rP   rW   rH   rX   r   r   r   vee   s   zSo3.veec                 C  sX  | j jd }| j jd | j jd | j jd }}}dd|d   d|d   }d| | d| |  }d| | d| |  }t|||fd}d| | d| |  }dd|d   d|d   }d| | d| |  }t|||fd}	d| | d| |  }d| | d| |  }dd|d   d|d   }t|||fd}
t||	|
fdS )a  Convert the quaternion to a rotation matrix of shape :math:`(B,3,3)`.

        The matrix is of the form:

        .. math::
            \begin{bmatrix} 1-2y^2-2z^2 & 2xy-2zw & 2xy+2yw \\
            2xy+2zw & 1-2x^2-2z^2 & 2yz-2xw \\
            2xz-2yw & 2yz+2xw & 1-2x^2-2y^2\end{bmatrix}

        Example:
            >>> s = So3.identity()
            >>> m = s.matrix()
            >>> m
            tensor([[1., 0., 0.],
                    [0., 1., 0.],
                    [0., 0., 1.]])

        rK   r)   rL   r(   rS   )r   r4   rT   rU   rV   r   r
   )r   r4   rT   rU   rV   q0q1q2rY   rZ   r[   r   r   r   matrix   s   (z
So3.matrixra   c                 C  s   | t |S )a  Create So3 from a rotation matrix.

        Args:
            matrix: the rotation matrix to convert of shape :math:`(B,3,3)`.

        Example:
            >>> m = torch.eye(3)
            >>> s = So3.from_matrix(m)
            >>> s
            tensor([1., 0., 0., 0.])

        )r   from_matrix)clsra   r   r   r   rb      s   zSo3.from_matrixwxyzc                 C  s   | t |S )a1  Create So3 from a tensor representing a quaternion.

        Args:
            wxyz: the quaternion to convert of shape :math:`(B,4)`.

        Example:
            >>> q = torch.tensor([1., 0., 0., 0.])
            >>> s = So3.from_wxyz(q)
            >>> s
            tensor([1., 0., 0., 0.])

        r   )rc   rd   r   r   r   	from_wxyz  s   zSo3.from_wxyzN
batch_sizeOptional[int]r+   Optional[Device]r,   Optional[Dtype]c                 C     | t |||S )a  Create a So3 group representing an identity rotation.

        Args:
            batch_size: the batch size of the underlying data.
            device: device to place the result on.
            dtype: dtype of the result.

        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.]])

        )r   identityrc   rf   r+   r,   r   r   r   rk     s   zSo3.identityc                 C  s   t | j S )zReturn the inverse transformation.

        Example:
            >>> s = So3.identity()
            >>> s.inverse()
            tensor([1., -0., -0., -0.])

        )r   r   r0   r"   r   r   r   inverse,  s   	zSo3.inversec                 C  rj   )aE  Create a So3 group representing a random rotation.

        Args:
            batch_size: the batch size of the underlying data.
            device: device to place the result on.
            dtype: dtype of the result.

        Example:
            >>> s = So3.random()
            >>> s = So3.random(batch_size=3)

        )r   randomrl   r   r   r   rn   7  s   z
So3.randomrT   c                 C  s   t |}| t|||fdS )z_Construct a x-axis rotation.

        Args:
            x: the x-axis rotation angle.

        r(   r   rJ   r
   )rc   rT   zsr   r   r   rot_xI     z	So3.rot_xrU   c                 C  s   t |}| t|||fdS )z_Construct a z-axis rotation.

        Args:
            y: the y-axis rotation angle.

        r(   ro   )rc   rU   rp   r   r   r   rot_yT  rr   z	So3.rot_yrV   c                 C  s   t |}| t|||fdS )z_Construct a z-axis rotation.

        Args:
            z: the z-axis rotation angle.

        r(   ro   )rc   rV   rp   r   r   r   rot_z_  rr   z	So3.rot_zc                 C  s   |   S )zReturn the adjoint matrix of shape :math:`(B, 3, 3)`.

        Example:
            >>> s = So3.identity()
            >>> s.adjoint()
            tensor([[1., 0., 0.],
                    [0., 1., 0.],
                    [0., 0., 1.]])

        )ra   r"   r   r   r   adjointj  s   zSo3.adjointr1   c                 C  sh   t | }| jdddd }td| j| jd}|d|  |d  |  ||  |d  ||   }|S )	at  Compute the right Jacobian of So3.

        Args:
            vec: the input point of shape :math:`(B, 3)`.

        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]])

        r(   Tr9   rK      r*   r)   rL   r   r<   r	   r+   r,   r>   rA   )r1   R_skewrC   IJrr   r   r   right_jacobianw  
   8zSo3.right_jacobianc                 C  
   t | S )zlAlias for right jacobian.

        Args:
            vec: the input point of shape :math:`(B, 3)`.

        )r   r{   r1   r   r   r   rz        
zSo3.Jrc                 C  sh   t | }| jdddd }td| j| jd}|d|  |d  |  ||  |d  ||   }|S )	ar  Compute the left Jacobian of So3.

        Args:
            vec: the input point of shape :math:`(B, 3)`.

        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]])

        r(   Tr9   rK   rv   r*   r)   rL   rw   )r1   rx   rC   ry   Jlr   r   r   left_jacobian  r|   zSo3.left_jacobianc                 C  r}   )zkAlias for left jacobian.

        Args:
            vec: the input point of shape :math:`(B, 3)`.

        )r   r   r~   r   r   r   r     r   zSo3.Jl)r   r   r   r   )r   r    )r$   r%   r   r   )r'   r   r   r   )r   r   )r8   r   r   r   )r   r   )r8   rR   r   r   )rP   r   r   r   )ra   r   r   r   )rd   r   r   r   )NNN)rf   rg   r+   rh   r,   ri   r   r   )r   r   )rT   r   r   r   )rU   r   r   r   )rV   r   r   r   )r1   r   r   r   )__name__
__module____qualname____doc__r   r#   r&   r7   propertyr   staticmethodrJ   rQ   r\   r]   ra   classmethodrb   re   rk   rm   rn   rq   rs   rt   ru   r{   rz   r   r   __classcell__r   r   r   r   r   "   sT    




#




	r   )
__future__r   typingr   r=   kornia.corer   r   r   r   r   r	   r
   r   r   r   kornia.core.checkr   kornia.geometry.conversionsr   kornia.geometry.linalgr   kornia.geometry.quaternionr   kornia.geometry.vectorr   r   r   r   r   r   <module>   s   0