o
    ߥi&                     @   s   d dl Zd dlZd dlm  mZ d dlmZ dd Zd(ddZ	d	d
 Z
dejfddZd)ddZdd Zdd Z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*d$ed%edefd&d'ZdS )+    N)Tensorc                 C   sF   |j d }|dd| j d d}| || j d |dddS )a"  
    https://github.com/pytorch/pytorch/issues/14489#issuecomment-607730242
    :param matrix: Sparse or dense matrix, size (m, n).
    :param matrix_batch: Batched dense matrices, size (b, n, k).
    :return: The batched matrix-matrix product,
    size (m, n) x (b, n, k) = (b, m, k).
    r      )shape	transposereshapemm)matrixmatrix_batch
batch_sizevectors r   e/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/models/cv/human3d_animation/transforms.pybatch_mm   s   
r   wxyzTc                 C   s   | j ddd}| }d||dk < | | }tj| jdd d | j| jd}|d	 }|d
krFt|d|d< t	|| |dddf< n|dkrat	|| |dddf< t|d|d< |ru|d dk }||ddf  d9  < |S )a?  
    Convert angle-axis representation to wxyz quaternion
    and to the half plan (w >= 0)
    @param rots: angle-axis rotations, (*, 3)
    @param form: quaternion format, either 'wxyz' or 'xyzw'
    @param unified_orient: Use unified orientation for quaternion
    (quaternion is dual cover of SO3)
    :return:
    r   T)dimkeepdimr   :0yE>N   devicedtype      ?r   .r   .xyzw   .r   r   )
normclonetorchemptyr   r   r   cossqueezesin)rotsformunified_orientanglesr   axisquatsidxr   r   r   aa2quat   s$   
r,   c                 C   sd   | d }| dddf }|j dd}| }d||dk < ||d }t||d }||d S )	z^
    Convert wxyz quaternions to angle-axis representation
    :param quats:
    :return:
    r   .r   Nr   r   gHz>   )r   r   	unsqueezer    atan2)r*   _cosxyz_sinr   r)   angler   r   r   quat2aa>   s   r5   r*   c                 C   s  | d }| d }| d }| d }|| }|| }|| }|| }|| }	|| }
|| }|| }|| }|| }|| }|| }t j| jdd d | j| jd}d	|	|  |d
< || |d< || |d< || |d< d	||  |d< ||
 |d< || |d< ||
 |d< d	||	  |d< |S )z
    Convert (w, x, y, z) quaternions to 3x3 rotation matrix
    :param quats: quaternions of shape (..., 4)
    :return:  rotation matrices of shape (..., 3, 3)
    r   .r   .r.   r   Nr   )r   r   r         ?).r   r   ).r   r   ).r   r.   ).r   r   ).r   r   ).r   r.   ).r.   r   ).r.   r   ).r.   r.   )r    r!   r   r   r   )r*   qwqxqyqzx2y2z2xxyywxxyyzwyxzzzwzmr   r   r   quat2matN   s:   rJ   r2   c                 C   s  | d }| d }| d }| d }t j|jd | j| jd}|dkrqt d|| ||   || ||  ||  ||  |d< t d|| ||   d	d
|d< t d|| ||   || ||  ||  ||  |d< ntd| |r|d t	j
 }|S )za
    Convert (w, x, y, z) quaternions to xyz euler angles.
    This is  used for bvh output.
    r   r6   r7   r   )r   r   r2   r.   r   r   zCannot convert to ordering %s   )r    r!   r   r   r   r0   asinclipNotImplementedErrornppi)qorderdegreesq0q1q2q3esr   r   r   
quat2euleru   s"   &
rY   c                 C   s   t | }t|}|S )zv
    Convert angle-axis representation to rotation matrix
    :param rots: angle-axis representation
    :return:
    )r,   rJ   )r%   quatmatr   r   r   aa2mat   s   r\   c                 C   sR   t | jdd d }d|d< t j| |fdd}t |}|dddddf S )	z<
    Calculate the inverse of any affine transformation
    Nr.   )r   r   r   r   r-   .r   )r    zerosr   catinverse)r[   affinevert_matvert_mat_invr   r   r   
inv_affine   s
   
rc   c                 C   s^   |   }| dddf dd|dddf< t|dddf | d dd |d< |S )z@
    Calculate the inverse of a rigid affine transformation
    .Nr   r   r   )r   r   r    matmulr/   r#   )r[   resr   r   r   inv_rigid_affine   s
   $(rg   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)rh   retpositive_maskr   r   r   _sqrt_positive_part   s   
rn   r	   c              
   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   rd   zInvalid rotation matrix shape .N)	   r-   r8   r   r.   r6   r7   r   g?r   r   g       @).Nr   )num_classesr   r   )size
ValueErrorr   r    unbindr   rn   stacktensortor   r   maxFone_hotargmax)r	   	batch_dimm00m01m02m10m11m12m20m21m22q_absquat_by_rijkflrquat_candidatesr   r   r   matrix_to_quaternion   sZ   
""""


r   quaternionsc                 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   T)pr   r   gư>r   0   )r    r   r0   abs
empty_liker$   )r   normshalf_anglesr(   epssmall_anglessin_half_angles_over_anglesr   r   r   quaternion_to_axis_angle   s   
r   c                 C   s   t t| S )a{  
    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.
    )r   r   )r	   r   r   r   mat2aa
  s   r   r   rot_vecsepsilonc              
   C   s(  t | jdksJ d| j | jd }| j}| j}tj| | dddd}| | }tjt|dd}tjt|dd}tj	|ddd\}	}
}tj
|ddf||d	}tj
|df||d	}tj|| |
|||	 |
 |	|g	dd|ddf}tjd||d	jdd}|||  d| t||  }|S )
a=   Calculates the rotation matrices for a batch of rotation vectors
        Parameters
        ----------
        rot_vecs: torch.tensor Nx3
            array of N axis-angle vectors
        Returns
        -------
        R: torch.tensor Nx3x3
            The rotation matrices for the given axis-angle parameters
    r.   z+Expects an array of size Bx3, but received r   r   T)r   r   r   r-   r   rq   )lenr   r   r   r    r   r/   r"   r$   splitr]   r^   vieweyebmm)r   r   r   r   r   r4   rot_dirr"   r$   rxryrzKr]   identrot_matr   r   r   batch_rodrigues  s&   

$ r   )r   T)r2   T)r   )numpyrO   r    torch.nn.functionalnn
functionalrz   r   r   r,   r5   rJ   rY   r\   rc   rg   rn   r   r   r   floatr   r   r   r   r   <module>   s"   

'2