a
    lɀjT                     @   s|   d Z ddlZddlZddlZddlmZmZmZ ddl	m
Z
 daG dd dZG dd dZG d	d
 d
ZG dd dZdS )aY  RobotEnv: turns a spec into a learnable task.

Two rules kept strictly:
  1. The policy only ever sees what the spec's sensors publish, at their real
     rate, with noise, bias and latency. No cheating on privileged state.
  2. The reward may use ground truth, because the reward only exists at
     training time and never ships to the robot.
    N)	load_specspec_to_mjcf
find_joint)	make_taskc                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )
SensorBankzBZero-order-hold + noise + per-episode bias over MuJoCo sensordata.c           
      C   s  || _ || _g | _|d D ]}|dds,qt|tjj|d }|dk r^td|d d|j	| }|j
| }dt|d	d
 }	| j|d t||| t||	t|ddt|ddt|ddt|t|dd
 qtdd | jD | _d S )Nsensorsin_obsFnamer   zsensor z missing from compiled model      ?Zrate_hz    eAnoise        biasscale)
r	   slicedimperiodr   bias_magr   r   heldnext_tc                 s   s   | ]}|d  V  qdS )r   N ).0er   r   '/home/ghrups/robot-bench/trainer/env.py	<genexpr>3       z&SensorBank.__init__.<locals>.<genexpr>)rng
control_dtentriesgetmujoco
mj_name2idmjtObjmjOBJ_SENSORKeyError
sensor_adr
sensor_dimfloatappendr   intnpzerossumr   )
selfmodelspecr   r   ssidadrr   r   r   r   r   __init__   s2    


zSensorBank.__init__c                 C   sN   | j D ]B}| jj|d  |d |d d|d< t|d |d< d|d< qd S )Nr   r   sizer   r   r   r   )r   r   uniformr*   r+   )r-   r   r   r   r   reset5   s    
$zSensorBank.resetc                 C   s   t | j}d}| jD ]}||d krt j||d  td}|d r^| jjd|d |d dnd}||d	  | |d
< ||d  |d< |d
 |d  ||||d  < ||d 7 }q|S )Nr   r   r   dtyper   r   r   r4   r   r   r   r   )r*   emptyr   r   asarrayr'   r   normal)r-   
sensordatatoutir   rawr   r   r   r   read;   s    
& zSensorBank.readc                 C   sZ   | j D ](}|d |kr|d |d p&d   S q||}|rPtj|| tdS tdS )zThe corrupted reading for a named sensor, matching what the policy
        sees, so the estimator never gets a cleaner signal than the network.r	   r   r   r
   r8      )r   r   r*   r;   r'   r+   )r-   r	   r=   rA   r   slr   r   r   noisyH   s
    

zSensorBank.noisyc                    sR   g }| j D ]B  d dkr*| d  q
| fdddd  d  D 7 }q
|S )Nr      r	   c                    s   g | ]} d   d| qS )r	   .r   )r   cr   r   r   
<listcomp>W   r   z%SensorBank.labels.<locals>.<listcomp>Zxyzw)r   r(   )r-   r?   r   rI   r   labelsQ   s    
$zSensorBank.labelsN)	__name__
__module____qualname____doc__r3   r7   rB   rE   rK   r   r   r   r   r      s   	r   c                   @   s2   e Zd ZdZdddZdd Zd	d
 Zdd ZdS )AttitudeEstimatora  Complementary filter over the robot's own noisy gyro and accelerometer.

    A single accelerometer sample cannot tell you which way is up while the
    robot is moving: it measures gravity minus the body's own acceleration, and
    a balancing machine is always accelerating. Measured on this robot, tilt
    inferred from one sample is out by 25 degrees at the median, on a machine
    that falls at 55.

    The gyro has the opposite problem: excellent short term, drifts long term.
    Blending them is what every real balancing robot does on its MCU, so doing
    it here is modelling the hardware rather than cheating. The estimator sees
    only the same noisy, biased signals the policy does.
    \(\?{Gz?ףp=
?c                 C   s,   || _ || _|| _tg d| _d| _d S Nr   r   r
   r   )alphaheading_alphadtr*   arrayupheading)r-   rV   rX   rW   r   r   r   r3   j   s
    zAttitudeEstimator.__init__c                 C   s   t g d| _d| _d S rT   )r*   rY   rZ   r[   r-   r   r   r   r7   q   s    zAttitudeEstimator.resetc           
      C   s   | j t|| j | j  }tj|}|dkr6|| n| j }tj|}|dkrt|| }tddt|d d  }d| j	 | }d| | ||  }	tj|	}|dkr|	| n|| _ n|| _ | j S )N&.>ư>r   r
   gQ#@)
rZ   r*   crossrX   linalgnormr;   maxabsrV   )
r-   gyroaccelprednameastrustkZblendedr   r   r   updateu   s    zAttitudeEstimator.updatec                 C   sD  |  j tt|| j| j 7  _ |du r0| j S tj|td}tj|}|dk rX| j S || }|| jt|| j  }tj|}|dk r| j S || }t	| jt
g d}tj|}|dk r| j S || }t	|| j}	ttt||tt||	}
|
| j  tj dtj  tj }|  j d| j | 7  _ | j S )a5  Yaw from the magnetometer, tilt-compensated, blended with the gyro.

        Gravity fixes roll and pitch but says nothing about yaw, so without a
        magnetometer heading drifts forever. The magnetometer is the only
        absolute yaw reference - and the least trustworthy sensor on the robot.
        Nr8   r]   r^   )r
   r   r      r
   )r[   r'   r*   dotrZ   rX   r;   r`   ra   r_   rY   mathatan2pirW   )r-   rd   magmrg   ZhorizZhnZeastenZnorthri   errr   r   r   update_heading   s.    "$ z AttitudeEstimator.update_headingN)rQ   rR   rS   )rL   rM   rN   rO   r3   r7   rl   rv   r   r   r   r   rP   [   s
   
rP   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	FusedIMUa  A BNO055/BNO085-class chip: fusion runs on the sensor, attitude comes out.

    Modelling the chip's OUTPUT rather than re-deriving it from raw gyro and
    accelerometer, because that is what the hardware actually provides. Honesty
    lives in the error model instead: white noise, a slow wander the chip cannot
    remove, a heading axis that is always worse than tilt, and extra heading
    error from six BLDC motors sitting near the sensor.
    c              	   C   s   t j}|| _|| _|t|dd| _|t|dd| _|t|dd| _|t|dd| _	|t|d	d
| _
tdttt|ddd | | _|   d S )NZtilt_noise_deg皙?Ztilt_drift_degr
   Zheading_noise_degg      ?Zheading_drift_deg      @Zmotor_coupling_deg      @r   Z
latency_ms
   g     @@)ro   radiansrX   r   r'   r   
tilt_noise
tilt_drift
head_noise
head_driftmotor_couplingrb   r)   roundlatencyr7   )r-   cfgrX   r   dr   r   r   r3      s    (zFusedIMU.__init__c                 C   sB   | j d| jd| _| j d| j| _td| _d| _	g | _
d S )Nr   rC   r   )r   r<   r~   	tilt_biasr   	head_biasr*   r+   walk	head_walkqueuer\   r   r   r   r7      s
    zFusedIMU.resetc                 C   s   d| j  | jd| jd d | _ d| j | jd| jd  | _tj|td}|| j	 | j  | jd| j
d }tj|}|dkr|| ntg d}|| j | j | jd| j | j|  }| j||f t| j| jkr| jdS | jd S )Ng+?r   {Gz?rC   r8   r]   rU   )r   r   r<   r~   r   r   r*   r;   r'   r   r}   r`   ra   rY   r   r   r   r   r(   lenr   pop)r-   Zup_trueZheading_truedriverZ   rg   headr   r   r   rl      s    " "zFusedIMU.updateN)rL   rM   rN   rO   r3   r7   rl   r   r   r   r   rw      s   	rw   c                   @   sv   e Zd ZdddZdd Zd	d
 Zdd Zdd Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd ZdS ) RobotEnvr   Nr
   unionc           &   	      s  t |_tj|_|p2jdi p,i d}tj|||d_|_	jj
_tjdrnj ng _tjjd_tjj_tj_jjrbtjjd }	tjjd }
tdd|
}tdd|	}t||\}}d	td
tj d| d   td
tj d| d   dtd
tj d| d|     dtd
tj d| d|  d    }||   t!dt"|! |    }|
d
 |	d
  }}t!d|
d }t#|	D ]|}t#|
D ]l}t$%|| || | }|dk rddt$t$j|   }|||f | |||f d|   |||f< qܐq|& jj'd d < jd }dt"|dd _(t!dtt)j(jj*j+ _,jdjdi }t"|dd_-t"|di dd_.t$t$/t"|di d d!_0tt)jj1j( _2|_3|j_4t5jd"i }|d urZt6||d#< |_7jj8d d df 9 _:jj8d d df 9 _;t<jj=d d df 9 _>dj>j>dk < jj?_@g g  _A_Bt5jd$i d%i }tCjd&d r|DjjE |_F|G D ]B\}}tHjtjIjJ|}jAKjjL|  jBKt"| q"tjMjAtd'_AtMjB_BtjMfd(d)|D td'_Ndj:j;  _Odj;j:  _PtMd*d) jd+g D _QtRjd+g D ]^\}}|d,d-krq||d. } | d u r2qt"|d/d0}!| jO|< |!jP|< qS  d1d) jd+g D  tCjd+d }"|"r fd2d)|"D ntTt#j@_UtVjU_@W  tXjjj(j_Yjd3d4d5d6}#t6|#d#d4_Z|#dd7_[j[d8kr0t\|#j(j_]n(t^t"|#d9d5j(t"|#d:d;_]t_d<d= jd>g D _`tad?d= jd>g D d_bjZrd@nd_ci _ddAD ]P}$tHjtjIje|$}%|%dkrtfjjg|% jjg|% jjh|%  jd|$< qjYjijc jjj j@ _kj@_lj@_ljjm9 _njjo9 _pjjq9 _rjjs9 _tjju9 _vjjw9 _xjj=9 _yi _zdBD ]F}$tHjtjIje|$}%tfjjg|% jjg|% jjh|%  jz|$< qd S )CNtasktype)layoutbuild_props)propsr   r   r
   g?rm   g @rx   g333333?g333333?g333333?g@g?g      ?g333333@r]   ry   g      $@      ?simZ
control_hzd   rF   limitsZtarget_height	terminateZ
min_heightZmax_tilt_deg7   Zdomain_randomisationenabledinitqposposer8   c                    s(   g | ] } j jt j tjj| qS r   )r.   
jnt_dofadrr    r!   r"   mjOBJ_JOINTr   rg   r\   r   r   rJ   7  s   z%RobotEnv.__init__.<locals>.<listcomp>c                 S   s   g | ]}| d rdndqS )reversed      r
   r   r   rh   r   r   r   rJ   C  s   	actuatorsmodepositionjointZaction_scale333333?c                 S   s   g | ]}|d  qS )r	   r   r   r   r   r   rJ   V  r   c                    s   g | ]}  |qS r   )indexr   )namesr   r   rJ   X  r   	estimatorTrQ   )r   rV   ZcomplementaryfusedrV   rW   rS   c                 s   s&   | ]}| d dko| dV  qdS )r	   rr   r   Nr   r   xr   r   r   r   j  s   z$RobotEnv.__init__.<locals>.<genexpr>r   c                 s   s,   | ]$}| d dkrt| ddV  qdS )r	   rr   r   r   N)r   r'   r   r   r   r   r   l  s      rd   re   rr   gt_quatgt_posgt_upgt_velgt_gyro){r   r/   r*   randomdefault_rngr   r   r   task_objr   r	   	task_namehasattrr   r   r   xmlr    MjModelfrom_xml_stringr.   MjDatadatanhfieldr)   hfield_nrowhfield_ncollinspacemeshgridsinrq   cosminrb   r'   rangero   hypotravelhfield_datar   r   opttimestepn_subh_targetmin_hr|   min_up	episode_s	max_steps	cmd_scale
curriculumdictbooldractuator_ctrlrangecopyctrl_loctrl_hirc   actuator_forcerange	tau_limitnun_actleg_joint_ids	q_nominalgetattrrl   r   init_qitemsr!   r"   r   r(   jnt_qposadrrY   Zleg_dof_ids
act_centeract_spanact_sign	enumerate_settle_heightlistact_idxr   _resolve_motorsr   r   est_onest_moderw   r   rP   anyhas_magnextmag_couplingZest_dim_rawr#   r   r%   r&   r   	obs_extraZobs_dimact_dim	body_mass
_base_massbody_inertia_base_inertia	body_ipos
_base_iposgeom_friction_base_frictionactuator_gainprm
_base_gainactuator_biasprm
_base_bias_base_forcerange_gt)&r-   	spec_pathseed	randomiser   r   task_cfgr   r   nrZncZxsZysXYhZcxcyRrrH   ddwr   r   r   r   r	   valjidr@   rh   nominalspanwantZest_cfgnmr1   r   )r   r-   r   r3      s   



"&&
4
 
 
	





zRobotEnv.__init__c           
      C   sH  t | j}| jd d |jdd< t| di  D ]6\}}t | jt jj	|}|dkr4||j| jj
| < q4t | j| d\}}t| jjD ]d}| jj| t jjkrqt| jj| d }|dk rqt|j| d	 }	|du s|	|k r|	| }}q|du rt| jd d d	 | _nt|jd	 ||  | _| j| _| jd
 | _dS )zWhere does the robot stand in THIS task's pose?

        Solved kinematically, not by simulating: an unsupported robot topples
        during any settle long enough to converge, and you end up measuring the
        height of a fallen robot.
        rootposNrC   r   r   )Nr   gQ?rm   r   )r    r   r.   r/   r   r   r   r!   r"   r   r   
mj_forwardr   ngeom	geom_typemjtGeommjGEOM_CYLINDERr'   	geom_size	geom_xposspawn_zr   r   )
r-   r   r	   r  r  Zlowestradiusgir  zr   r   r   r     s,    
zRobotEnv._settle_heightc                 C   s   ddl }g i i   | _| _| _t| jdg D ]p\}}t| j	tj
j|d }| j	j| | j|< |ddkr0|| j|}| j| |r|d nd| j|< q0dS )	a  Which actuators are torque-mode, and where their dof lives.

        This has to be re-resolved whenever the model changes. Swapping the
        root joint for a tether rig renumbers every dof - the free-floating
        robot has 14, hung from a hook it has 12 - so a cached dof index from
        the old model reads the wrong joint at best and runs off the end of
        qvel at worst. The torque-speed curve in step() dereferences these
        every tick, which is how a stale index crashed the whole live sim.
        r   Nr   r   r   torqueZno_load_rad_sg     @)mjcf
torque_idxact_dofno_loadr   r/   r   r    r!   r.   r"   r   r   Zmotor_limitsr(   )r-   _mjcfr@   rh   r  Zlimr   r   r   r     s    
zRobotEnv._resolve_motorsc                    s   j jdddf   _ j jdddf   _t j jdddf   _d j jdk < tj	 fdd j
D td _   t j  j j j _i  _d	D ]D}t j tjj|}t j j|  j j|  j j|   j|< qi  _d
D ]L}t j tjj|}|dkrt j j|  j j|  j j|   j|< q j j  _ j j  _ j j   _! j j"  _# j j$  _% j j&  _' j j  _(t) fddt* j j+D   _,dS )a  Re-resolve everything that points into the model.

        Swapping the root joint (to build a tethered test rig) changes every
        index, so the sensor addresses and joint ids have to be looked up again
        or the readings silently belong to the wrong quantities.
        Nr   rF   r
   r]   c                    s(   g | ] } j jt j tjj| qS r   )r.   r   r    r!   r"   r   r   r\   r   r   rJ     s   
z$RobotEnv._rebind.<locals>.<listcomp>r8   r   r   c                 3   s"   | ]} j j| tjjkV  qd S )N)r.   jnt_typer    mjtJoint
mjJNT_FREE)r   jr\   r   r   r     s   z#RobotEnv._rebind.<locals>.<genexpr>)-r.   r   r   r   r   r*   rc   r   r   rY   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  r  r  r  r	  r   r   njnttethered)r-   r  r1   r   r\   r   _rebind  sD     
zRobotEnv._rebindc                 C   sn  | j }| j|jd d < | j|jd d < | j|jd d < | j|jd d < | j	|j
d d < | j|jd d < | j|jd d < d| _| jddsd S | jdddg\}}| jj|||jd}| j| |jd d < | j|d d d f  |jd d < t| jdd}|rBt|tjj| jd	 d
 }| j| | j| |d |j|< | jdddg\}}| jd d df | j|| |jd d df< | jdddg\}}| jj|||jd}| j	d d df | |j
d d df< | jd d df | |jd d df< | jd d df | |jd d df< | j|d d d f  |jd d < | jdddg\}}t| j||d | _d S )Nr   r   FZ
mass_scalerF   r4   Z
com_offsetr   r  r	   rC   Zfriction_scaleZactuator_gain_scalerm   Zlatency_steps)r.   r   r   r   r   r  r  r  r  r  r  r  r  r	  r   r   r   r   r   r6   nbodyr'   r    r!   r"   
mjOBJ_BODYr/   r   r)   Zintegers)r-   rs   lohir   comZroot_bidgr   r   r   	_apply_dr  s:     ".$$$ zRobotEnv._apply_drc                    s      t j j t jdi di }t j	dd rN|
 j	j  jd }t ddrd jjd d < t jjD ]<} jj| tjjkr jj| }g d jj||d	 < q j D ]0\}}t jtjj|}| jj jj| < qt j j  j   j  tg d
 _d _d _ d _!dddddddd _"d  _#t$ j% _& fddtdD  _'d _( )   j	  j* d _+ , S |d  jjdd<  j- j*.d|dd  jjd< |dd}t j*.d|d| j*.d|d| j*.d|d|g}	t$d	}
t/|
|	d |
 jjdd< |dd}t0 j1 j2D ]$\}}| j*.d|  jj|< q| j*.d|ddd jj3d d< t j j  j   j  tg d
 _d _ j*j.dd}|tj45|d   _6dddddddd _"d  _#d _ d _!t$ j% _& fd dt j(d D  _' )   j7 j	_8 j	  j* t9 j:d!i d"d _+ , S )#Nr   r   
init_noiser  r6  Fr   )r
   r   r   r      rU   r   )up_pkfa_ifa_pkside_iside_pkjerk_irate_pkc                    s   g | ]}t  jqS r   r*   r+   r   r   _r\   r   r   rJ   :  r   z"RobotEnv.reset.<locals>.<listcomp>rF   r   r  rC   base_zrm   base_rpy	base_roll
base_pitchbase_yawZxyz   r   base_vel   r4   r]   c                    s   g | ]}t  jqS r   rH  rI  r\   r   r   rJ   b  r   pushevery_s);r>  r    mj_resetDatar.   r   r   r/   r   r   r   rl   r?  r   r   r5  r1  r2  
mjJNT_BALLr   r   r   r!   r"   r   r   r   r7   r   r*   rY   est_upest_headingstep_ir>   feel_feel_prev_ar+   r   prev_actionaction_queuer   _cache_truthr   
_next_push_obsr'  r<   mju_euler2Quatzipr   r   qvelr`   ra   	_mag_axisr   r   r'   r   )r-   r   r  r4  rh   r	   r  r  rL  Zrpyquatjnr2   vr   r\   r   r7     s    
$
$


zRobotEnv.resetc                 C   s   | j j}tj|| jd  td| _tj|| jd  td| _tj|| jd  td| _tj|| jd  td| _	t|| jd  d | _
t| jd | _dS )	zpGround truth, refreshed once per step. Reward and scenery logic may
        read these; the observation may not.r   r8   r   r   r   r   rm   N)r   r=   r*   r;   r
  r'   base_pos	base_quat	vel_local	gyro_trueup_zheight)r-   sdr   r   r   r^  i  s    zRobotEnv._cache_truthc           	   	   C   st  | j stdS | jdkr| j}td|d |d  |d |d    dd|d |d  |d |d     }ttt	| j
jd }| jtj| j
j| jd  td||\}}|| | _| _|S | jd	| j
j| j}| jd
| j
j| j}| j|| | jrl| jd| j
j| j }| jr^ttt	| j
j}|| j| j | d  }| j|| | jjS )z7Produce the attitude the flight computer would receive.r   r   rm   rC   rF   rz   r   r8   rd   re   rr   r   )r   r*   r+   r   ri  ro   rp   r'   meanrc   r   actuator_forcer   rl   r;   r=   r
  rW  rX  r   rE   r   r   r   r   rd  rv   rZ   )	r-   qyawr   rZ   r   r=  rh   rs   r   r   r   _est_updatet  s0    

&&zRobotEnv._est_updatec              
   C   s8  | j d| jj| j}| j d| jj| j}t| dtg d}t	t
|d  tdt
|d }d}t
|d t
|d	 t
|d   }}}|t| |t|  | d
 }	|t| |t|  | }
|| }| j}tdurTtd}|durFtddt|
|d   t||d	   dt|	|d    td< |
||	ftd< t|d |	|d< |d  t|
| j 7  < t|d t|
|d< |d  t|| j 7  < t|d t||d< | j}|dur|d  t
tt|| d 7  < tj|t
d | _t|d t
tt||d< dS )a  THE FEELINGS: the vestibular sense, metered every tick.

        A kid learns to stand by feeling its balance - these are the
        numbers that feeling is made of, taken from the same noisy IMU
        the real robot will carry (never ground truth). Every episode
        of every stage accumulates them in env.feel; a stage prices
        them into its score via FEEL_WEIGHTS when its exam wants the
        skill smooth, not just successful.

          up_pk    peak vertical thrust (g, above gravity)
          fa_i/pk  fore-aft g: integral and peak (the lurch)
          side_i/pk lateral g: integral and peak (the wobble)
          jerk_i   integral of accel change (the roughness)
          rate_pk  peak body rotation rate (rad/s)
        re   rd   rW  rU   r   r^   rm   gfffffX@rF   r
   NZ_prevZroughr   r   rA  rB  rC  rD  rE  rF  r8   rG  )r   rE   r   r=   r   r   r*   rY   ro   rp   r'   rb   r   r   rZ  
FEEL_ACCUMr   rc   r   r[  r,   r;   r   )r-   rh   r=  rZ   pZ_GaxZayazZup_gZfa_gZside_gfZ_pprevr   r   r   _feel_update  s>    $($ 




(zRobotEnv._feel_updatec                 C   s   | j | jj| j}| jr\t| dtg d}t| dd}t	|t
|t
|gg}n
td}t	||| j| | jgtjS )NrW  rU   rX  r   r   )r   rB   r   r=   r>   r   r   r*   rY   concatenatero   r   r   r+   r   obsr\  astypefloat64)r-   r0   rZ   r   Zestr   r   r   r`    s     
zRobotEnv._obsc                 C   s  t t j|tddd}| j| | jd}t t| j	}||| j
< || j }t | j	|| j  | j| j}| jD ]\}tt| jj| j|  }| j| tdd|| j|    }tt || | |||< qx|| jjd t|< | jdi }| jdr| j| jkr| jj|dddg }	| jdd	tj }
| jjd  |	t|
 7  < | jjd
  |	t |
 7  < | j|dd | _t!| j"D ]}t#$| j%| j q|  j| j&7  _|  j'd
7  _'| (  | )  | *  | j+,| | j | j+-| |\}}| j.| j/k pF| j0| j1k pFt 2| jj34  pF| j+5| }| j'| j6k}|| _7|t8|| j0| j.t8| j+9| d}| : t|t8|t8||fS )Nr8   r   r
   r   r   rS  r   impulserm   rF   rT  r   )termsfellrm  rl  success);r*   clipr;   r'   r]  r(   r   r+   r   r   r   r   r   r   r   r-  rc   r   rc  r.  rb   r/  ctrlr   r   r>   r_  r   r6   ro   rq   r   r   r   r   r    mj_stepr.   r   rY  r^  rs  rz  r   on_steprewardrl  r   rm  r   isfiniter   all
terminatedr   r\  r   r  r`  )r-   actionZappliedfullr  r@   r  ZavailrS  impangrJ  r  r  r  Z	truncatedinfor   r   r   step  sR    


"
zRobotEnv.stepc                    s    fddt d jjD S )Nc                    s    g | ]}t  jt jj|qS r   )r    
mj_id2namer.   r"   r9  r   r@   r\   r   r   rJ     s   z'RobotEnv.body_names.<locals>.<listcomp>rF   )r   r.   r8  r\   r   r\   r   
body_names  s    
zRobotEnv.body_namesc                    sn   t  jd fddtd jjD  fddtd jjD d} j }|durjdd |D |d	< |S )
zCBody world poses for the three.js bench, so the viewer needs no FK.r@  c                    s"   g | ]}d d  j j| D qS )c                 S   s   g | ]}t t|d qS r   r   r'   r   rg  r   r   r   rJ     r   -RobotEnv.frame.<locals>.<listcomp>.<listcomp>)r   xposr  r\   r   r   rJ     s   z"RobotEnv.frame.<locals>.<listcomp>rF   c                    s"   g | ]}d d  j j| D qS )c                 S   s   g | ]}t t|d qS r  r  r  r   r   r   rJ     r   r  )r   xquatr  r\   r   r   rJ     s   )r>   r  re  Nc                 S   s   g | ]}t |d qS )r@  )r   r  r   r   r   rJ     r   goal)r   r>   r   r.   r8  r   goal_marker)r-   rx  r  r   r\   r   frame	  s    


zRobotEnv.frame)r   Nr
   NNr   )rL   rM   rN   r3   r   r   r7  r>  r7   r^  rs  rz  r`  r  r  r  r   r   r   r   r      s      
 -"/.J55r   )rO   ro   numpyr*   r    r,  r   r   r   tasksr   rt  r   rP   rw   r   r   r   r   r   <module>   s   	DR2