o
     ݱi9                  
   @   s  d Z ddlZddlZddlm  mZ dd Zdd Zdd Z	d6d
dZ
dejdejfddZdejdejfddZdejdejfddZdejdejfddZdejdejfddZdejdejfddZdejdejfddZdejdejfd d!Zdejdejfd"d#Zdejd$edejfd%d&Zd'ejd$edejfd(d)Zd*edefd+d,Zd-ed.ed/ed0edejf
d1d2Zd-ed3ejdejfd4d5ZdS )7z,
This file contains some PyTorch utilities.
    Nc                 C      t | }t|}|S zR
    Converts tensor with rot_6d representation to axis-angle representation.
    )rotation_6d_to_matrixmatrix_to_axis_anglerot_6drot_matZrot r	   @/data/cameron/vidgen/unified-world-model/datasets/droid/utils.pyrot_6d_to_axis_angle
      r   c                 C   s4   t | }tjjj| }|d}t	|}|S )M
    Converts tensor with rot_6d representation to euler representation.
    xyz)
r   scipyspatial	transformZRotationZfrom_matrixnumpyZas_eulertorchTensorr   r	   r	   r
   rot_6d_to_euler_angles   s
   

r   c                 C   r   r   )axis_angle_to_matrixmatrix_to_rotation_6d)
axis_angler   r   r	   r	   r
   axis_angle_to_rot_6d   r   r   XYZc                 C   s   t | dd}t|}|S )r   r   )
convention)euler_angles_to_matrixr   )euler_anglesr   r   r   r	   r	   r
   euler_angles_to_rot_6d'   s   r   xreturnc                 C   s(   t | }| dk}t | | ||< |S )z[
    Returns torch.sqrt(torch.max(0, x))
    but with a zero subgradient where x is 0.
    r   )r   
zeros_likesqrt)r   retZpositive_maskr	   r	   r
   _sqrt_positive_part0   s   
r$   quaternionsc                 C   s   t | d\}}}}d| |  d }t d||| ||    ||| ||   ||| ||   ||| ||   d||| ||    ||| ||   ||| ||   ||| ||   d||| ||    f	d}|| jdd d S )z
    Convert rotations given as quaternions to rotation matrices.
    Args:
        quaternions: quaternions with real part first,
            as tensor of shape (..., 4).
    Returns:
        Rotation matrices as tensor of shape (..., 3, 3).
           @   N   r*   )r   unbindsumstackreshapeshape)r%   rijkZtwo_sor	   r	   r
   quaternion_to_matrix;   s    	r5   matrixc              
   C   s  |  ddks|  ddkrtd| j d| jdd }tj| |d dd\	}}}}}}}}	}
ttjd	| | |
 d	| | |
 d	| | |
 d	| | |
 gdd}tjtj|d
 d |	| || || gddtj|	| |d d || || gddtj|| || |d d ||	 gddtj|| || |	| |d d gddgdd}tdj	|j
|jd}|d|d |  }|tj|jdddddkddf |d S )z
    Convert rotations given as rotation matrices to quaternions.
    Args:
        matrix: Rotation matrices as tensor of shape (..., 3, 3).
    Returns:
        quaternions with real part first, as tensor of shape (..., 4).
    r&   r*   Invalid rotation matrix shape .N)	   dim      ?).r      ).r(   ).r>   ).r*   g?)dtypedevicer'   ).N   )num_classes      ?)rA   )size
ValueErrorr/   r   r+   r.   r$   r-   tensortor?   r@   maxFone_hotargmax)r6   	batch_dimZm00Zm01Zm02Zm10Zm11Zm12Zm20Zm21Zm22Zq_absZquat_by_rijkZflrZquat_candidatesr	   r	   r
   matrix_to_quaternionY   s>   (((( 
rM   r   c                 C      t t| S )a}  
    Convert rotations given as axis/angle to rotation matrices.
    Args:
        axis_angle: Rotations given as a vector in axis angle form,
            as a tensor of shape (..., 3), where the magnitude is
            the angle turned anticlockwise in radians around the
            vector's direction.
    Returns:
        Rotation matrices as tensor of shape (..., 3, 3).
    )r5   axis_angle_to_quaternion)r   r	   r	   r
   r         r   c                 C   rN   )ay  
    Convert rotations given as rotation matrices to axis/angle.
    Args:
        matrix: Rotation matrices as tensor of shape (..., 3, 3).
    Returns:
        Rotations given as a vector in axis angle form, as a tensor
            of shape (..., 3), where the magnitude is the angle
            turned anticlockwise in radians around the vector's
            direction.
    )quaternion_to_axis_anglerM   )r6   r	   r	   r
   r      rP   r   c                 C   s   t j| dddd}|d }d}| |k }t |}t ||  ||   || < d|| ||  d  ||< t jt || | gdd}|S )	a  
    Convert rotations given as axis/angle to quaternions.
    Args:
        axis_angle: Rotations given as a vector in axis angle form,
            as a tensor of shape (..., 3), where the magnitude is
            the angle turned anticlockwise in radians around the
            vector's direction.
    Returns:
        quaternions with real part first, as tensor of shape (..., 4).
    r>   r&   Tpr<   keepdimrC   ư>0   r;   )r   normabs
empty_likesincatcos)r   angleshalf_anglesepssmall_anglessin_half_angles_over_anglesr%   r	   r	   r
   rO      s   
rO   c                 C   s   t j| dddf dddd}t || dddf }d| }d}| |k }t |}t ||  ||   || < d	|| ||  d
  ||< | dddf | S )a  
    Convert rotations given as quaternions to axis/angle.
    Args:
        quaternions: quaternions with real part first,
            as tensor of shape (..., 4).
    Returns:
        Rotations given as a vector in axis angle form, as a tensor
            of shape (..., 3), where the magnitude is the angle
            turned anticlockwise in radians around the vector's
            direction.
    .r(   Nr>   r&   TrR   rU   rC   rV   )r   rW   atan2rX   rY   rZ   )r%   normsr^   r]   r_   r`   ra   r	   r	   r
   rQ      s   
rQ   d6c                 C   s|   | dddf | dddf }}t j|dd}||| jddd|  }t j|dd}tj||dd}tj|||fddS )	a  
    Converts 6D rotation representation by Zhou et al. [1] to rotation matrix
    using Gram--Schmidt orthogonalization per Section B of [1].
    Args:
        d6: 6D rotation representation, of size (*, 6)
    Returns:
        batch of rotation matrices of size (*, 3, 3)
    [1] Zhou, Y., Barnes, C., Lu, J., Yang, J., & Li, H.
    On the Continuity of Rotation Representations in Neural Networks.
    IEEE Conference on Computer Vision and Pattern Recognition, 2019.
    Retrieved from http://arxiv.org/abs/1812.07035
    .Nr*   r&   r;   T)rT   r7   )rI   	normalizer,   r   crossr-   )rd   a1a2b1b2b3r	   r	   r
   r      s   "r   c                 C   s4   |   dd }| dddddf  |d S )a  
    Converts rotation matrices to 6D rotation representation by Zhou et al. [1]
    by dropping the last row. Note that 6D representation is not unique.
    Args:
        matrix: batch of rotation matrices of size (*, 3, 3)
    Returns:
        6D rotation representation, of size (*, 6)
    [1] Zhou, Y., Barnes, C., Lu, J., Yang, J., & Li, H.
    On the Continuity of Rotation Representations in Neural Networks.
    IEEE Conference on Computer Vision and Pattern Recognition, 2019.
    Retrieved from http://arxiv.org/abs/1812.07035
    Nr7   .r>   )   )rD   cloner.   )r6   rL   r	   r	   r
   r     s   $r   r   c              
   C   sB  t |dkr
td|d |d |d fv rtd| d|D ]}|dvr.td	| d
q | ddks=| ddkrFtd| j dt|d }t|d }||k}|rmt| d||f || dv rhdnd }n
t| d||f }t|d |d | d|f d||t|d |d | d|ddf d|f}t	|dS )a,  
    Convert rotations given as rotation matrices to Euler angles in radians.

    Args:
        matrix: Rotation matrices as tensor of shape (..., 3, 3).
        convention: Convention string of three uppercase letters.

    Returns:
        Euler angles in radians as tensor of shape (..., 3).
    r*   Convention must have 3 letters.r(   r   r>   Invalid convention r9   XYZInvalid letter  in convention string.r&   r7   r8   .)r&   r>   g      r=   FNT)
lenrE   rD   r/   _index_from_letterr   asinacos_angle_from_tanr-   )r6   r   letteri0i2
tait_bryanZcentral_angler4   r	   r	   r
   matrix_to_euler_angles  s6     	r   r   c                 C   s   |   dks| jd dkrtdt|dkrtd|d |d |d fv r/td| d	|D ]}|d
vr?td| dq1dd t|t| dD }tt|d |d |d S )aW  
    Convert rotations given as Euler angles in radians to rotation matrices.

    Args:
        euler_angles: Euler angles in radians as tensor of shape (..., 3).
        convention: Convention string of three uppercase letters from
            {"X", "Y", and "Z"}.

    Returns:
        Rotation matrices as tensor of shape (..., 3, 3).
    r   r&   r*   zInvalid input euler angles.rn   r(   r>   ro   r9   rp   rt   ru   c                 S   s   g | ]	\}}t ||qS r	   )_axis_angle_rotation).0cer	   r	   r
   
<listcomp>R  s    z*euler_angles_to_matrix.<locals>.<listcomp>)r<   r/   rE   rv   zipr   r+   matmul)r   r   r{   matricesr	   r	   r
   r   =  s    r   r{   c                 C   s,   | dkrdS | dkrdS | dkrdS t d)Nrq   r   rr   r(   rs   r>    letter must be either X, Y or Z.)rE   )r{   r	   r	   r
   rw   Z  s   rw   axis
other_axis
horizontalr~   c                 C   s   dddd|  \}}|r||}}| | dv }||kr)t |d|f |d|f S |r:t |d|f  |d|f S t |d|f |d|f  S )a  
    Extract the first or third Euler angle from the two members of
    the matrix which are positive constant times its sine and cosine.

    Args:
        axis: Axis label "X" or "Y or "Z" for the angle we are finding.
        other_axis: Axis label "X" or "Y or "Z" for the middle axis in the
            convention.
        data: Rotation matrices as tensor of shape (..., 3, 3).
        horizontal: Whether we are looking for the angle for the third axis,
            which means the relevant entries are in the same row of the
            rotation matrix. If not, they are in the same column.
        tait_bryan: Whether the first and third axes in the convention differ.

    Returns:
        Euler Angles in radians for each matrix in data as a tensor
        of shape (...).
    )r>   r(   )r   r>   )r(   r   rp   )ZXYZYZZZX.)r   rb   )r   r   datar   r~   i1r}   evenr	   r	   r
   rz   d  s   
rz   anglec              	   C   s   t |}t |}t |}t |}| dkr%|||||| |||f	}n&| dkr6||||||| ||f	}n| dkrG|| |||||||f	}ntdt |d|jd S )aM  
    Return the rotation matrices for one of the rotations about an axis
    of which Euler angles describe, for each value of the angle given.

    Args:
        axis: Axis label "X" or "Y or "Z".
        angle: any shape tensor of Euler angles in radians

    Returns:
        Rotation matrices as tensor of shape (..., 3, 3).
    rq   rr   rs   r   r&   r)   )	r   r\   rZ   	ones_liker!   rE   r-   r.   r/   )r   r   r\   rZ   onezeroZR_flatr	   r	   r
   r     s   



r   )r   )__doc__r   r   Ztorch.nn.functionalnn
functionalrI   r   r   r   r   r   r$   r5   rM   r   r   rO   rQ   r   r   strr   r   intrw   boolrz   r   r	   r	   r	   r
   <module>   s@    	
		<*

!