o
    *j&                     @   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)matrixZmatrix_batch
batch_sizeZvectors r   r/var/www/html/Deteccion_Ine/venv/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   .Zxyzw   .r   r   )
normclonetorchemptyr   r   r   cossqueezesin)rotsformZ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   r1   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&   ZqwZqxZqyZqzZx2y2Zz2xxyyZwxZxyZyzZwyxzzzZwzmr   r   r   quat2matN   s:   r;   r.   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   r2   r3   r   )r   r   r.   r*   r   r   zCannot convert to ordering %s   )r   r   r   r   r   r,   asinZclipNotImplementedErrornppi)qorderdegreesq0q1q2Zq3esr   r   r   
quat2euleru   s"   &
rH   c                 C   s   t | }t|}|S )zv
    Convert angle-axis representation to rotation matrix
    :param rots: angle-axis representation
    :return:
    )r(   r;   )r"   Zquatmatr   r   r   aa2mat   s   rJ   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   catZinverse)rI   ZaffineZvert_matZvert_mat_invr   r   r   
inv_affine   s
   
rM   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    )rI   resr   r   r   inv_rigid_affine   s
   $(rQ   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   Z
zeros_likesqrt)rR   retZpositive_maskr   r   r   _sqrt_positive_part   s   
rV   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   rN   zInvalid rotation matrix shape .N)	   r)   r4   r   r*   r2   r3   r   g?r   r   g       @).Nr   )Znum_classesr   r   )size
ValueErrorr   r   Zunbindr   rV   stackZtensortor   r   maxFZone_hotZargmax)r	   Z	batch_dimZm00Zm01Zm02Zm10Zm11Zm12Zm20Zm21Zm22Zq_absZquat_by_rijkZflrZ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   r,   absZ
empty_liker!   )ra   ZnormsZhalf_anglesr$   epsZsmall_anglesZsin_half_angles_over_anglesr   r   r   quaternion_to_axis_angle   s   
rf   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.
    )rf   r`   )r	   r   r   r   mat2aa
  s   rg   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   rb   r)   r   rY   )lenr   r   r   r   r   r+   r   r!   splitrK   rL   vieweyeZbmm)rh   ri   r
   r   r   r0   Zrot_dirr   r!   rxZryZrzKrK   identZrot_matr   r   r   batch_rodrigues  s&   

$ rq   )r   T)r.   T)r   )numpyr?   r   Ztorch.nn.functionalnnZ
functionalr_   r   r   r(   r1   r;   rH   rJ   rM   rQ   rV   r`   rf   rg   floatrq   r   r   r   r   <module>   s"   

'2