o
    im/                  
   @   s  d dl mZ d dlZd dlZd dlmZ d dlmZm	Z	 dej
dej
dej
deej
 fd	d
Zdej
dej
dej
dej
fddZdej
dej
fddZdd Zdd Zdd Zdd Zdd Z	dEddZ						dFdejdejfd d!Zd"ejdejd#edejd$ejf
d%d&ZdGd'd(Zd)d* Zd+d, Zed-krrejd. d/Zed0d1 e eD Z!e Z"d2Z#ej$d3Z%e&e!Z'e eD ]<Z(e!e( dd3dd3f Z)e!e( dd3d3f Z*e"e) e'e( dd3dd3f< e#e"e*  e% e'e( dd3d3f< d4e'e( d5< qe	e!Z+e	e'Z,ee+e,\Z-Z.Z/e0d6e#d7e/ e0d8e%d7e. e0d9e"d:e- d;Z1ej$e1d3Z2ee2e"e%e#d<d=Z3ee3e-e.e/dd=Z4e5e4e2 Z6e0d>e67  e0d?e68  e67 d@k saJ dAe68 dBk slJ dCe0dD dS dS )H    )ListN)
PosePath3D)affine_inverseaffine_inverse_nprotstransscalesenc_listc                 C   s   d S N )r   r   r   r	   r   r   ?/data/cameron/da3_repo/src/depth_anything_3/utils/pose_align.pybatch_apply_alignment_to_enc   s   r   extc                 C   s8  |j |j}}|jdd  dkr6tjg |jd d ddR |j|d}||dd dd df< d|d< |}t|}| d d d f |dd dd df  }|d d d d f | d d d f |dd ddd f  d	  |d d d f  }	t|}
||
dd dd df< |	|
dd ddf< d|
d< t|
d d d df S )
N      r   )dtypedevice.r         ?.r   r   ).r   )r   r   shapetorchzerosr   
zeros_like)r   r   r   r   r   _padpose_estZpose_new_align_rotZpose_new_align_transZpose_new_alignr   r   r   batch_apply_alignment_to_ext   s   *&J
r   ext_refext_estc                 C   s  | j | j}}| jtjtjfv sJ |jtjtjfv sJ | jdu s$J |jdu s+J g g g }}}t| jd D ];}t| | 	 
 || 	 
 \}}	}
|t|j||d |t|	j||d |tj|
||d q:t|t|t|fS )NFr   )r   r   )r   r   r   float32float64requires_gradranger   align_poses_umeyamacpunumpyappend
from_numpytotensorstack)r   r    r   r   r   r   r   brtsr   r   r   batch_align_poses_umeyama2   s   (r1   c                 C   sJ   | j d dkr#tdd  t| d}| |d d d dd df< |S | S )N   r   r   r   )r   npeyerepeatlen)r   outr   r   r   _to44D   s
   r8   c                 C   s(   t | } t |}t| }t|}||fS r
   )r8   r   )r   r    pose_refr   r   r   r   _poses_from_extL   s
   r:   c                 C   sH   t |  d}t | d}|j|dd\}}}t|j}||||fS )N)	poses_se3T)Zcorrect_scale)r   copyalignr3   r,   r;   )r9   r   Zpath_refZpath_estr.   r/   r0   pose_est_alignedr   r   r   _umeyama_sim3_from_pathsT   s
   r?   c                 C   s   |   }| d d d dd df }| d d d ddf }|| |d d d dd df< |||j  j| |d d d ddf< |S )Nr   )r<   T)Zposesr.   r/   r0   r7   Ritir   r   r   _apply_sim3_to_poses\   s   &rC   c                 C   s~   | d d d ddf }|d d d ddf }g }|D ]}t jj||d d d f  dd}||  q|r=tt |S dS )Nr   r2   axisg        )r3   linalgnormr(   minfloatmedian)r9   r>   ZP_refZP_estdistspddr   r   r   _median_nn_threshe   s    rN   
   c              	   C   s  t j|}| jd }t |}|d u rtd|d d }ntdt||}t| |\}	}
}}|d u r8t| |}| d d d ddf }|	|
|f}d }dt j	f}t
|D ]u}|j||dd}zt| | || \}}}}W n	 tyu   Y qSw t||||}|d d d ddf }t jj|| dd}||k}t| }|dkrt||  nt j	}||d ks||d kr||d k r||f}|||f}|}qS|d ur| dkrt| | || \}}}}n|\}}}|||fS )	Nr   r   r2      F)sizereplacerD   )r3   randomdefault_rngr   arangemaxrH   r?   rN   infr$   choice	ExceptionrC   rF   rG   intsumrI   mean)r9   r   sub_ninlier_thresh	max_itersrandom_staterngNZidx_allr0t0s0Z	pose_est0Z	P_ref_allZ
best_modelZbest_inliersZ
best_scorer   sampler.   r/   r0   Zpose_hZP_hZerrsZinlierskZmean_errr   r   r   _ransac_align_sim3o   sF   




$


ri   Fc                 C   sp   t | |\}}	|st||	\}
}}}nt||	||||d\}
}}t|	|
||}|r3t|}|
|||fS |
||fS )a  
    Align estimated trajectory to reference using Umeyama Sim(3).
    Default no RANSAC; if ransac=True, use RANSAC (max iterations default 10).
    - sub_n defaults to half the number of frames (rounded up, at least 3)
    - inlier_thresh defaults to median of "distance from each estimated pose to
      nearest reference pose after pre-alignment"
    Returns rotation (3x3), translation (3,), scale; optionally returns aligned extrinsics (4x4).
    )r^   r_   r`   ra   )r:   r?   ri   rC   r   )r   r    return_alignedransacr^   r_   Zransac_max_itersra   r9   r   r.   r/   r0   r>   Zext_est_alignedr   r   r   r%      s    
r%   rotscalereturnc                 C   s   |j dd dkr.tjg |j dd ddR |jd}||dddddf< d|d	< |}t|}|dddddf }|ddddf }td
| |}|td| | | }	t|}
||
dddddf< |	|
ddddf< d|
d	< t|
S )z
    Apply Sim(3) (R, t, s) to a batch of world-to-camera extrinsics ext_est.
    Returns the aligned extrinsics, with the same shape as input.
    r   Nr   r   )r   .r   r   r   zij,...jk->...ikzij,...j->...i)r   r3   r   r   r   einsumr   )rl   r   rm   r    r   r   ZR_eZt_eZR_at_aZpose_ar   r   r   apply_umeyama_alignment_to_ext   s   (
rq   c                 C   s&   |s|| |j   | S | | | | S )z
    Sim(3) transform point cloud
    points: (N, 3)
    rot: (3, 3)
    trans: (3,) or (1, 3)
    scale: float
    inverse: Whether to do inverse transform (ref->est)
    Returns: (N, 3)
    )r@   )pointsrl   r   rm   inverser   r   r   transform_points_sim3  s   
rt   c                  C   sf  t jd\} }}t t d|  t dt jj |  t d|  t dt jj |  t | t dt jj |  t | t dt jj |  g}|\}}}}t dd|| ||    d|| ||   d|| ||   gd|| ||   dd|| ||    d|| ||   gd|| ||   d|| ||   dd|| ||    ggS )Nr   r2   rP   )	r3   rT   randarraysqrtsinmathpicos)u1u2u3qwxyzr   r   r   	_rand_rot  s   ""<<<r   c                  C   sF   t  tjd} }td}| |d dd df< ||d ddf< |S )Nr   r   )r   r3   rT   randnr4   )Rr/   Pr   r   r   
_rand_pose.  s
   
r   __main__*      c                 C   s   g | ]}t  qS r   )r   ).0r   r   r   r   
<listcomp>:  s    r   gffffff@r   r   )r   r   z	GT scale:z
Estimated:z	GT trans:zGT rot:
z
Estimated:
d   T)rs   z,Point cloud sim3 transform error (mean abs):z+Point cloud sim3 transform error (max abs):gư>z$Mean sim3 transform error too large!gh㈵>z#Max sim3 transform error too large!z5Sim(3) point cloud transform & alignment test passed!)NNrO   N)FFNNrO   N)F)9typingr   r'   r3   r   Zevo.core.trajectoryr   depth_anything_3.utils.geometryr   r   Tensorr   r   r1   r8   r:   r?   rC   rN   ri   ndarrayr%   rI   rq   rt   r   r   __name__rT   seedrc   r,   r$   r9   Zrot_gtZscale_gtr   Ztrans_gtr   r   ir   r/   r   r    Zr_estZt_estZs_estprintZ
num_pointsZ
points_refZ
points_estZpoints_ref_recoveredabserrr]   rW   r   r   r   r   <module>   s   

	
2
E

%

 