o
    ÁB	jÇ<  ã                   @   sˆ  d Z ddlZddlZddlZddlmZ ddlm  mZ ej	 
dd¡Zej	 
dd¡ZdZdZd	Zd
ZdZdZdZdd„ Zdd„ ZG dd„ dejƒZedkrÂe ej ¡ rWdnd¡Zeddd e¡Zedd„ e ¡ D ƒƒZ edd„ e ¡ D ƒƒZ!e"de d›de!d›ƒ d\Z#Z$e %e#e$d dd¡ e¡Z&e 'e#e$d!¡ e¡d Z(e )¡  ee&e(ƒZ*W d  ƒ n1 sµw   Y  e"d"e*j+ƒ dS dS )#uÚ  Autoregressive transformer policy with high-res patches + relative-to-EEF positional embeddings.

Architecture (per Cameron's spec, 2026-05-16):
  Per-frame patches (frozen DINOv3 ViT-S/16, 28x28 = 784 patches, D=384)
  + 1 learnable EEF token per timestep
  History context H frames (default 8)
  Three summed positional embeddings on every token:
    (1) temporal PE â€” which timestep (0..H-1)
    (2) absolute 2D PE â€” patch position (or EEF position) in [0,1]^2
    (3) relative-to-EEF PE â€” (xy - EEF(t-1).xy), the anchor inductive bias for free-space motion
  Causal mask along time; within a frame all tokens are bidirectional.
  Readout: take the EEF_query token at t = H-1, MLP -> logits over a 56x56 spatial grid
  Loss: cross-entropy on grid cell containing next-EEF GT.

First-pass scope:
  xy-only output (no height / rotation / gripper â€” bolt on later as parallel readout queries).
  Teacher-force past EEF coords from data; predict next-step (single step) EEF cell.
é    NÚDINO_REPO_DIRz;/Users/cameronsmith/Projects/robotics_testing/random/dinov3ÚDINO_WEIGHTS_PATHzt/Users/cameronsmith/Projects/robotics_testing/random/dinov3/weights/dinov3_vits16plus_pretrain_lvd1689m-4057cbaa.pthé   é   é8   i€  é   é   iÀ  c                 C   sV   |d }t  t j|||dt d¡|   ¡}|  d¡| }t j| ¡ | ¡ gddS )zKpositions: (...,) float in any range. dim must be even. returns (..., dim).é   ©ÚdeviceÚdtypeg     ˆÃ@éÿÿÿÿ©Údim)	ÚtorchÚexpÚarangeÚmathÚlogÚ	unsqueezeÚcatÚsinÚcos)Ú	positionsr   r   r   ÚhalfZfreqsÚangles© r   ú1/data/cameron/para/libero/model_autoregressive.pyÚ_sincos_pe_1d'   s   &r   c                 C   s>   |d }t | d |||ƒ}t | d |||ƒ}tj||gddS )z=xy: (..., 2). dim must be divisible by 4. returns (..., dim).r	   ).r   ).é   r   r   )r   r   r   )Úxyr   r   r   r   ÚpxÚpyr   r   r   Ú_sincos_pe_2d/   s   r#   c                       sL   e Zd Zeeeeeedf‡ fdd„	Z	dd„ Z
dd„ Zdd	„ Zd
d„ Z‡  ZS )ÚARTransformerPolicyTc              
      sè  t ƒ  ¡  || _|| _|| _|| _t| _|| j | _| jd | _	t
d |¡ƒ tjjtddtd| _|rD| j ¡ D ]}d|_q9| j ¡  | jj| _| j|ksZJ d|› d| j› d	ƒ‚|| _t t |¡d
 ¡| _t t |¡d
 ¡| _t t |¡d
 ¡| _t t d|¡t ¡ t ||¡¡| _ tj!||d| ddddd}	tj"|	|d| _#t t $|¡t ||¡t ¡ t ||| ¡¡| _%t &| j¡d | j }
t &| j¡d | j }tj'|
|dd\}}| j(dtj)||gdd *| j	d¡dd d S )Nr	   z&Loading DINOv3 backbone (frozen={})...Zdinov3_vits16plusÚlocal)ÚsourceÚweightsFz	d_model (z) must equal DINO embed_dim (u?   ) â€” otherwise add a linear projection before the transformer.g{®Gáz”?r   g        ÚgeluT)Úd_modelÚnheadÚdim_feedforwardÚdropoutÚ
activationÚbatch_firstÚ
norm_first)Ú
num_layersg      à?Úij)ÚindexingÚpatch_xy_01r   r   )Ú
persistent)+ÚsuperÚ__init__Útarget_sizeÚhistory_lenÚ	grid_sizer)   ÚDINO_PATCH_SIZEZ
patch_sizeZpatches_per_sideÚ	n_patchesÚprintÚformatr   ÚhubÚloadr   r   ÚdinoÚ
parametersÚrequires_gradÚevalÚ	embed_dimÚfreeze_backboneÚnnÚ	ParameterÚrandnÚ	eef_tokenÚtype_embed_patchÚtype_embed_eefÚ
SequentialÚLinearÚGELUÚ
rel_pe_mlpÚTransformerEncoderLayerÚTransformerEncoderÚtransformerÚ	LayerNormÚreadoutr   ÚmeshgridÚregister_bufferÚstackÚreshape)Úselfr7   r8   r9   r)   Zn_headsZn_layersrE   ÚpÚlayerÚysÚxsÚgrid_yÚgrid_x©Ú	__class__r   r   r6   8   s`   

ü

ÿÿ
þý
ýzARTransformerPolicy.__init__c           
      C   sä  | j rˆt ¡ u | j |¡\}\}}| jjD ]}| jjr$| jj||dnd}|||ƒ}q| jjr^| j |dd…d| jj	d …f ¡}| j 
|dd…| jj	d d…f ¡}tj||gdd}n| j 
|¡}|dd…| jj	d d…f }	W d  ƒ |	 ¡ S 1 sw   Y  |	 ¡ S | j |¡\}\}}| jjD ]}| jjr¤| jj||dnd}|||ƒ}q–| jjrÞ| j |dd…d| jj	d …f ¡}| j 
|dd…| jj	d d…f ¡}tj||gdd}n| j 
|¡}|dd…| jj	d d…f S )z8x: (N, 3, H, W). returns patch tokens (N, n_patches, D).)ÚHÚWNr   r   )rE   r   Úno_gradr@   Zprepare_tokens_with_masksÚblocksZ
rope_embedZuntie_cls_and_patch_normsZcls_normZn_storage_tokensÚnormr   Údetach)
rY   ÚxÚtokensZH_pZW_pZblkZrope_sincosZcls_nZpat_nÚpatchesr   r   r   Ú_dino_patches…   s4   
$$
õô$$z!ARTransformerPolicy._dino_patchesc                 C   sD  |j }|j}| j}| j}tj|||d}t||||ƒ}	t| j 	|¡|||ƒ}
|dd…ddd…f }| j 	|¡ 
d¡ ||d¡}|| 
d¡ d }|  |¡}t||||ƒ}|| 
d¡ d }|  |¡}|
 
d¡| }g }t|ƒD ]+}||	|  }|dd…|f |dd…|f  |	|   
d¡}| tj||gdd¡ qotj|ddS )	uš  Build the summed positional embedding for every token in the sequence.

        Sequence layout per batch element:
          for t = 0..H-1:
            patch tokens (Np)        â€” at frame t
            EEF token (1)            â€” at frame t (query when t == H-1)
        Total tokens per frame: Np + 1; total length: H * (Np + 1).

        history_eef_xy_01: (B, H, 2) in [0,1] image coords. The EEF token at the LAST
        frame is the prediction query; we pass the previous frame's EEF as that token's
        positional anchor (since the current EEF is unknown at prediction time, by spec
        "Relative-to-current-EEF uses EEF(t-1) as anchor").
        r
   Nr   r   r	   r   g       @r   )r   r   r)   r;   r   r   r   r#   r3   Útor   ÚexpandrO   ÚrangeÚappendr   )rY   ÚBrb   Zhistory_eef_xy_01r   r   ÚDÚNpZtime_idxZtime_peZpatch_abs_peZanchor_xy_01Zpatch_xyZpatch_rel_xyZpatch_rel_peZ
eef_abs_peZ
eef_rel_xyZ
eef_rel_peZpatch_pe_per_frameÚfullÚtZp_peZe_per   r   r   Ú_positional_embeddings¤   s*   

.z*ARTransformerPolicy._positional_embeddingsc              	   C   sl   | j }|d }|| }tj|||d}| tjtj|||tjdddtdƒ¡ |j|ddj|dd}|S )a   Causal across time: token in frame t may NOT attend to tokens in frame > t.
        Within a frame, all tokens (patches + eef) attend bidirectionally.

        Returns additive mask (T, T) with 0 / -inf entries, suitable for nn.TransformerEncoder.
        r   )r   r
   )Údiagonalz-infr   r   )	r;   r   ÚzerosÚmasked_fill_ÚtriuÚonesÚboolÚfloatÚrepeat_interleave)rY   rb   r   rr   Z	per_frameÚTÚblockÚmaskr   r   r   Ú_build_causal_time_maskã   s   *z+ARTransformerPolicy._build_causal_time_maskc              	   C   sž  |j \}}}}}|| jksJ d| j› d|› ƒ‚|| jkr"|| jks4J d| j› d| j› d|› d|› ƒ‚| || |||¡}|  |¡}	|	 ||| j| j¡}	|	| j }	| j| j	 }
|
 dd| j¡ 
||| j¡}g }t|ƒD ] }tj|	dd…|f |dd…||d …f gdd}| |¡ qltj|dd}|t| jƒ }|  |||¡}|| }|  ||j¡}| j||d}|| jd  d }|dd…|dd…f }|  |¡}|S )	uð  
        Args:
            history_imgs:   (B, H, 3, 448, 448) â€” past H frames (most recent at index H-1).
            history_eef_xy: (B, H, 2) â€” past H EEF pixel coords in image-pixel space
                                         (the last entry is the current frame's EEF; teacher-forced).

        Returns:
            logits: (B, grid_size*grid_size) â€” categorical over 56x56 spatial grid
                                                 for the predicted next-step EEF cell.
        zExpected H=z, got z	Expected rh   r   Nr   )r€   )Úshaper8   r7   Úviewrk   r;   r)   rJ   rI   rK   rm   rn   r   r   ro   r|   ru   r   r   rR   rT   )rY   Zhistory_imgsZhistory_eef_xyrp   rb   ÚCZHiZWirh   rj   Z	eef_protoZ
eef_tokensZframe_blocksrt   r   ÚseqZhistory_eef_01Úper€   ÚoutZ	query_idxZ
query_featÚlogitsr   r   r   Úforwardõ   s2    ÿ

2
zARTransformerPolicy.forward)Ú__name__Ú
__module__Ú__qualname__Ú
IMAGE_SIZEÚHISTORY_LENÚ	GRID_SIZEÚTRANSFORMER_DÚTRANSFORMER_HÚTRANSFORMER_Lr6   rk   ru   r   r‰   Ú__classcell__r   r   r`   r   r$   7   s    øM?r$   Ú__main__ÚcudaÚcpuT)r8   rE   c                 c   s    | ]
}|j r| ¡ V  qd S ©N)rB   Únumel©Ú.0rZ   r   r   r   Ú	<genexpr>+  s   € r›   c                 c   s    | ]}|  ¡ V  qd S r—   )r˜   r™   r   r   r   r›   ,  s   € zTrainable params: ú,z / )r	   r   é   r	   rˆ   ),Ú__doc__Úosr   r   Útorch.nnrF   Ztorch.nn.functionalÚ
functionalÚFÚenvironÚgetr   r   r:   rŽ   r   r   r‘   r’   r   r   r#   ÚModuler$   rŠ   r   r•   Úis_availablerl   ÚmodelÚsumrA   Ún_trainÚn_totalr<   rp   rb   rH   ÚimgsÚrandÚeefrd   rˆ   r‚   r   r   r   r   Ú<module>   sB     r
ÿô