
    nij                         S r SSKJrJrJrJrJrJrJr  SSK	r	SSK
r
SSKrSSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SrSr\	R<                   " S S\R>                  5      5       r g)z"The base class for all quadrupeds.    )AnyCallableDictSequenceTupleTextUnionN)bullet_client)sensor)hybrid_motor_model)
robot_base)robot_config)robot_urdf_loader)
data_types)kinematics_utils)r   r   r      )r   r   
   c                   d   \ rS rSrSr\R                  SSS4S\R                  S\	S\
4   S\R                  S	\R                  S
\S\S\\R"                     S\R&                  4S jjr   SHS\\
   S\\
   S\\\\
4   \\
   4   4S jjrS rS rS r\R<                      SIS\\
   S\\
   S\\\\
4   \\
   4   S\4S jj5       r S r!SJS jr" SKS\\\
   \\\
4   4   4S jjr#S r$SLS\S\%4S jjr&SKS\S\
4S  jjr'SKS! jr(S" r)S# r*S$ r+S% r,S& r- SMS' jr.SMS( jr/S)\\0Rb                     4S* jr2S+\%S)\0Rb                  4S, jr3S+\%S-\0Rb                  S)\\%\
4   4S. jr4\5S/ 5       r6\7S0 5       r8\7S1 5       r9\7S2 5       r:\7S3 5       r;\7S4 5       r<\7S5 5       r=\7S6 5       r>\7S7 5       r?\7S8 5       r@\7S9 5       rA\7S: 5       rB\7S; 5       rC\7S< 5       rD\7S)\R                  4S= j5       rE\7S> 5       rF\7S? 5       rG\7S@ 5       rH\7SA 5       rI\7SB 5       rJ\7SC 5       rK\7SD 5       rL\7SE 5       rM\7SF 5       rNSGrOg)NQuadrupedBase   z7The basic quadruped class for both sim and real robots.N pybullet_clientclock.motor_control_modemotor_limitsmotor_model_classaction_filtersensorssafety_configc	                 z   Xl         X l        X0l        XPl        X@l        SU l        SU l        X`l        Xpl        Xl	        SU l
        [        R                  " S5      U l        U R                  5       U l        [        R                  " S5      U l        [        R                  " S5      U l        U R#                  5         g)ab  Initializes the class.

Args:
  pybullet_client: The PyBullet client.
  clock: The sim or real clock. The clock function is typically provided by
    the gym environment.
  motor_control_mode: Specifies in which mode the motor operates.
  motor_limits: The motor limits of the robot. Used by the motor_model_class
    and action space building.
  motor_model_class: The motor model to use. Not needed for real robots.
  action_filter: The filter to smooth and/or regulate the actions.
  sensors: All sensors mounted on the robot.
  safety_config: The safety setting for the robot.
  **kwargs: Additional args.
N   )_pybullet_client_clock_motor_control_mode_motor_model_class_motor_limits_action_space_action_names_action_filter_sensors_safety_config_urdf_loadernpzeros_last_base_velocity_last_observation_time_last_base_acceleration_world%_last_base_acceleration_accelerometerload)
selfr   r   r   r   r   r   r   r   kwargss
             f/home/james-whalen/.local/lib/python3.13/site-packages/pybullet_envs/minitaur/robots/quadruped_base.py__init__QuadrupedBase.__init__   s    8 ,K1/%DD'M'D!xx{D"&++-D)+!D&13!D.IIK    base_positionbase_orientation_quaternionjoint_anglesc           	         U R                  5         U R                  (       d#  [        R                  " U R                  S9U l        U R                  R                  U R                  R                  5      u  U l        U l        U R                  R                  SU R                  S9u  o@l
        U R                  R                  5       U l        U R                  R                  5        Hx  nU R                  R                  U R                  R                  UU R                  R                  SSS9  U R                  R!                  U R                  R                  USSS9  Mz     U R                  R#                  5       U l        U R$                  (       d  ['        S5      eU R$                  R                  5       U l        [+        U R$                  5      U l        U R/                  5         U R0                  (       aS  U R1                  U R,                  U R2                  U R4                  R6                  U R4                  R8                  S9U l        U R                  R=                  U R$                  R?                  5       5      U l         [B        RD                  " [G        U R@                  R                  5       5      5      U l$        U R                  RK                  U R$                  R?                  5       5      U l&        [B        RD                  " [G        U RL                  R                  5       5      5      U l'        U RQ                  5         U RR                   H  nURU                  U 5        M     g	)
a  Loads the URDF with the configured pose.

Args:
  base_position: The base position after URDF loading. Will use the
    configured pose in gin if None.
  base_orientation_quaternion: The base orientation after URDF loading. Will
    use the configured values in gin if not specified.
  joint_angles: The desired joint angles after loading. Will use the
    configured values if None.
)r   r   r   r   positionorientationr   )	bodyIndex
jointIndexcontrolModetargetVelocityforce)linearDampingangularDampingz-Motor id dict cannot be empty for quadrupeds.)
num_motorsr   torque_lower_limitstorque_upper_limitsN)+	_pre_loadr,   r   RobotUrdfLoaderr"   getBasePositionAndOrientationrobot_id_init_urdf_position_init_orientation_quatinvertTransform_init_orientation_inv_quatget_joint_id_dict_joint_id_dictvaluessetJointMotorControl2VELOCITY_CONTROLchangeDynamicsget_motor_id_dict_motor_id_dict
ValueError
_motor_idslen_num_motors_build_action_spacer%   r$   r&   rJ   rK   _motor_modelget_joint_direction_dictkeys_motor_direction_dictr-   arraylist_motor_directionsget_joint_offset_dict_motor_offset_dict_motor_offsets_on_loadr*   	set_robot)r4   r:   r;   r<   unused_positionjoint_idr   s          r6   r3   QuadrupedBase.loadG   s   " 	NN+;;//1d 	;;&&	( :Dd9 	--D,G,G 	. 	I 5O4
 ++==?D''..0
11%%..++<< 2  **



$
$
	 +  1" ++==?DFGG))002DO4../D  11%%!55"00DD"00DD	 2 d "&!2!2!K!K  ""$DXXd4+E+E+L+L+N&OPD"//EE  "$D((4(?(?(F(F(H#IJD 	MMO --t  r9   c                 d   U R                   [        R                  R                  :X  a  [        R
                  R                  U R                  R                  U R                  R                  U R                  4[        R                  S9U l        [        S U R                  R!                  5        5       5      U l        gU R                   [        R                  R$                  :X  a  [        R
                  R                  U R                  R&                  U R                  R(                  U R                  4[        R                  S9U l        [        S U R                  R!                  5        5       5      U l        gU R                   [        R                  R*                  :X  Ga  U R                  R                  U R                  R,                  SSU R                  R&                  /nU R                  R                  U R                  R.                  [        R0                  [        R0                  U R                  R(                  /n[        R2                  " U R                  [        R4                  4U5      R7                  5       n[        R2                  " U R                  [        R4                  4U5      R7                  5       n[        R
                  R                  X4[        R                  S9U l        [        S U R                  R!                  5        5       5      U l        g[9        S5      e)	z<Builds the action space of the robot using the motor limits.)lowhighshapedtypec              3   D   #    U  H  nS R                  U5      v   M     g7f)zPOSITION_{}Nformat.0motors     r6   	<genexpr>4QuadrupedBase._build_action_space.<locals>.<genexpr>   s#      !O3M%-

u
%
%3M    c              3   D   #    U  H  nS R                  U5      v   M     g7f)z	TORQUE_{}Nrv   rx   s     r6   r{   r|      #      !M1K+

U
#
#1Kr}   r   )rq   rr   rt   c              3   D   #    U  H  nS R                  U5      v   M     g7f)z	HYBRID_{}Nrv   rx   s     r6   r{   r|      r   r}   Not yet implemented!N)r$   r   MotorControlModePOSITIONgymspacesBoxr&   angle_lower_limitsangle_upper_limitsr_   r-   float32r'   tupler[   rc   r(   TORQUErJ   rK   HYBRIDvelocity_lower_limitsvelocity_upper_limitsinffullHYBRID_ACTION_DIMENSIONravelNotImplementedError)r4   hybrid_action_limits_lowhybrid_action_limits_high	space_low
space_highs        r6   r`   !QuadrupedBase._build_action_space   s   <#@#@#I#II::>>  33!!44!!#

	 * d
 ! !O373F3F3K3K3M!O Od		!	!\%B%B%I%I	I::>>  44!!55!!#

	 * d
 ! !M151D1D1I1I1K!M Md		!	!\%B%B%I%I	I



/
/



2
2





0
0" 


/
/



2
2BFFBFF



0
0#
 ''\AA
B
"$$)EG  77\AA
B
#%%*UW  ::>>

 * <d  !M151D1D1I1I1K!M Md   677r9   c                     g)z]Robot specific pre load routine.

For example, this allows configuration of the URDF loader.
Nr   r4   s    r6   rL   QuadrupedBase._pre_load   s    
 	r9   c                     g)zRobot specific post load routine.

For example, we need to add add additional hinge constraints to the leg
components of Minitaur after loading.

Nr   r   s    r6   rk   QuadrupedBase._on_load   s     	r9   save_base_posec                    U R                   R                  5         [        R                  " S5      U l        U R                  5       U l        [        R                  " S5      U l        [        R                  " S5      U l        [        R                  " U R                  5      U l
        U R                  5         U R                  X5        U R                  U5        U(       ag  U R                  R                  U R                   R"                  5      u  U l        U l        U R                  R)                  SU R&                  S9u  o`l        U R                  5         U R                  5       U l        g)a  Resets the robot base and joint pose without reloading the URDF.

Base pose resetting only works for simulated robots or visualization of real
robots. This routine also updates the initial observation dict.

Args:
  base_position: The desired base position. Will use the configured pose in
    gin if None. Does not affect the position of the real robots in general.
  base_orientation_quaternion: The base orientation after resetting. Will
    use the configured values in gin if not specified.
  joint_angles: The desired joint angles after resetting. Will use the
    configured values if None.
  save_base_pose: Save the base position and orientation as the default pose
    after resetting.
  **kwargs: Other args for backward compatibility. TODO(b/151975607): Remove
    after migration.
r!   r>   r?   N)ra   resetr-   r.   r/   r#   r0   r1   r2   r_   _motor_torquesreceive_observation_reset_base_pose_reset_joint_anglesr"   rN   r,   rO   rP   rQ   rR   rS   _time_at_reset)r4   r:   r;   r<   r   r5   rm   s          r6   r   QuadrupedBase.reset   s   6 	  "xx{D"&++-D)+!D&13!D. ((4#3#34D 	-E\*
 


=
=((* <d ; 


/
/ d.I.I 0 K 7o6
 	++-Dr9   c                 <    U R                  5       U R                  -
  $ N)r#   r   r   s    r6   GetTimeSinceResetQuadrupedBase.GetTimeSinceReset  s    ;;=4....r9   c                 :    U R                   R                  X5        g)a;  Resets the pose of the robot's base.

Base pose resetting only works for simulated robots or visualization of real
robots.

Args:
  position: The desired base position. Will use the configured pose in gin
    if None.
  orientation_quat: The desired base rotation. Will use the configured
    default pose in None.
N)r,   reset_base_pose)r4   r@   orientation_quats      r6   r   QuadrupedBase._reset_base_pose  s     	%%hAr9   c                 :    U R                   R                  U5        g)aO  Resets the joint pose.

Real robots need to specify their routine to send joint angles. Simulated
Minitaur robots also needs to use dynamics to drive the motor joints, due to
the additional hinge joints not present in the URDF.

Args:
  joint_angles: The joint pose if provided. Will use the robot default pose
    from configuration.
N)r,   reset_joint_angles)r4   r<   s     r6   r   !QuadrupedBase._reset_joint_angles)  s     	((6r9   c                     g)zIThe safe exit routine for the robot.

Only implemented for real robots.

Nr   r   s    r6   	terminateQuadrupedBase.terminate9  s     	r9   actionnum_sub_stepsc                     U R                  U5      n[        U5       H>  nU R                  U5        U R                  R	                  5         U R                  5         M@     U R                  5         g)aU  Steps the simulation.

This is maintained for backward compatibility with the old robot class.

Args:
  action: The control command to be executed by the robot.
  num_sub_steps: Each action can be applied (possibly with interpolation)
    multiple timesteps, to simulate the elapsed time between two consecutive
    commands on real robots.
N)pre_control_steprangeapply_actionr"   stepSimulationr   post_control_step)r4   r   r   _s       r6   stepQuadrupedBase.stepA  s]     ""6*F=!

**,
  " 	r9   control_timestepc                 ^    U R                   (       a  U R                   R                  U5      nU$ )a  Processes the action and updates per control step quantities.

Args:
  action: The input control command.
  control_timestep: The control time step in the environment.
    TODO(b/153835005), we can remove this once we pass env to the robot.

Returns:
  The filtered action.
)r)   filter)r4   r   r   s      r6   r   QuadrupedBase.pre_control_stepW  s(     ""))&1fMr9   c                 R   [         R                  " U5      nU R                  R                  X5      u  p4X@l        [         R
                  " X@R                  5      nU R                  R                  U R                  R                  U R                  U R                  R                  US9  g )N)rB   jointIndicesrD   forces)r-   asarrayra   get_motor_torquesr   multiplyrg   r"   setJointMotorControlArrayr,   rO   r]   TORQUE_CONTROL)r4   motor_commandsr   unused_observed_torquesactual_torquesapplied_motor_torquess         r6   r   QuadrupedBase.apply_actiong  s     ZZ/N 	++NO ,( KK8N8NO33##,,__))88$	 4 &r9   c                     U R                   R                  U R                  R                  5      u  p[        R
                  " U R                   U R                  R                  UU R                  5      $ r   )r"   getBaseVelocityr,   rO   r   rotate_to_base_frameurdf_loaderrS   )r4   r   angular_velocitys      r6   _get_base_roll_pitch_yaw_rate+QuadrupedBase._get_base_roll_pitch_yaw_rate{  s`    //??""$A00t//88:J'') )r9   c                 h    U R                   R                  U R                  R                  5      u  pU$ r   )r"   r   r,   rO   )r4   base_velocityr   s      r6   _get_base_velocity QuadrupedBase._get_base_velocity  s0    ,,<<""$Mr9   c                 >   U R                   U R                  :  Ga  [        R                  " U R                  5      U R
                  -
  U R                  U R                   -
  -  U l        U R                  R                  [        R                  " S5      [        R                  " U R                  5      5      u  pU R                  R                  [        R                  " S5      UU R                  [        -   [        5      S   n[        R                  " U5      U l        gg)z5Update the base acceleration using finite difference.r!   r   N)r0   	timestampr-   re   _base_velocityr/   r1   r   rR   r.   r;   multiplyTransforms_GRAVITY_ACCELERATION_OFFSET_UNIT_QUATERNIONr2   )r4   r   inv_base_orientationbase_acceleration_accelerometers       r6   _update_base_acceleration'QuadrupedBase._update_base_acceleration  s    ""T^^3
((4&&
'$*B*B
Bnnt:::,<d( !% 4 4 D D
((1+rxx @ @A!Ca
 )-(<(<(O(O
((1++

,
,/K
K
) )% 4688
)4+d0 4r9   c                    U R                   R                  U R                  R                  5      u  U l        nU R                   R                  SU R                  SUS9u  o l        U R                  5       U l	        U R                   R                  U R                  5      U l        U R                  5       U l        U R                   R                  U R                  R                  U R                  5      U l        ["        R$                  " U R                    Vs/ s H  o3S   PM	     sn5      U l        U R&                  U R(                  -
  U R*                  -  U l        ["        R$                  " U R                    Vs/ s H  o3S   PM	     sn5      U l        U R,                  U R*                  -  U l        U R.                  (       a?  U R.                  R1                  U R3                  5       U R&                  U R,                  5        U R5                  5         ["        R$                  " U R                  5      U l        U R8                  U l        gs  snf s  snf )z*Receives the observations for all sensors.r>   )	positionAorientationA	positionBorientationBr   r   N)r"   rN   r,   rO   _base_positionr   rS   _base_orientation_quatr   r   getEulerFromQuaternion_base_roll_pitch_yawr   _base_roll_pitch_yaw_rategetJointStatesr]   _joint_statesr-   re   _motor_anglesrj   rg   _motor_velocitiesra   updater#   r   r/   r   r0   )r4   base_orientation_quatr   joint_states       r6   r   !QuadrupedBase.receive_observation  s   
 	;;&&	( /D. &*%:%:%M%M44*	 &N &,"A"
 113D $ 5 5 L L##!%D &*%G%G%ID"..==""DOO5D+/+=+=>+=KQ+=>@D,,--.151G1GHD  XX+/+=+=>+=KQ+=>@D!33d6L6LLD 
t{{}d.@.@#557 	""$!xx(;(;<D"&..D# 	?
 	?s   I9Ic                     g)zCCalled at the end of a control step outside the action repeat loop.Nr   r   s    r6   r   QuadrupedBase.post_control_step  s    r9   c           	         [         R                  " U R                  5      n[        U R                  R                  5       R                  5       5      n[        R                  " U R                  U R                  UUUUS9n[         R                  " [         R                  " U5      [         R                  " U R                  5      -
  U R                  5      nX54$ )a  Use IK to compute the motor angles, given the feet links' positions.

Args:
  foot_positions: The foot links' positions in frame specified by the next
    parameter. The input is a numpy array of size (4, 3).
  position_in_world_frame: Whether the foot_positions are specified in the
    world frame.

Returns:
  A tuple. The position indices and the angles for all joints along the
  leg. The position indices is consistent with the joint orders as returned
  by GetMotorAngles API.
)r   urdf_idlink_positionslink_idsjoint_dof_idspositions_are_in_world_frame)r-   arangerI   r   r,   get_end_effector_id_dictrV   r    joint_angles_from_link_positionsr   rO   r   r   rj   rg   )r4   foot_positionsposition_in_world_framejoint_position_idxsfoot_link_idsr<   s         r6    motor_angles_from_foot_positions.QuadrupedBase.motor_angles_from_foot_positions  s      ))DOO4$++DDFMMOPM#DD,,%)%<>L ;;


< 2::d.A.A#BB L ,,r9   c           	         / n[        U R                  R                  5       R                  5       5      nU H~  nU(       d;  UR	                  [
        R                  " U R                  U R                  US95        ME  UR	                  [
        R                  " U R                  U R                  US95        M     [        R                  " U5      $ )z;Returns the robot's foot positions in the base/world frame.)r   r   link_id)r   r,   r  rV   appendr   link_position_in_base_framer   rO   link_position_in_world_framer-   re   )r4   r  r  r  foot_ids        r6   r  QuadrupedBase.foot_positions  s    N$++DDFMMOPM $88 $ 4 4	 	99 $ 4 4	 ! 88N##r9   returnc                 2   [        U R                  R                  5       R                  5       5      n[	        [        U5      5       Vs/ s H  n[        R                  " S5      PM     nnU R                  R                  U R                  R                  S9nU H  nUu  pgpn
ppnnnnnX:X  a  M  X;   a  [        R                  " U5      U-  n[        R                  " U5      U-  [        R                  " U5      U-  -   nUU-   n[        R                  " U R                  U R                  R                  UU R                  5      n[        R                   R#                  U5      nUR%                  U	5      nUS:  a  UU==   U-  ss'   M  M  M     U$ s  snf )a  Gets the contact forces on all feet.

Reals robot may use a robot specific implementation. For example, the
Laikago will measure each contact force in the corresponding foot's local
frame, and this force will not be the total contact force due to the sensor
limitation.

For simulated robots, we wll always report the force in the base frame.

Returns:
  A list of foot contact forces.
r!   )bodyAr   )r   r,   r  rV   r   r^   r-   r.   r"   getContactPointsrO   re   r   r   r   rS   linalgnormindex)r4   r  r   contact_forcesall_contactscontactunused_flag	body_a_id	body_b_id	link_a_idunused_link_b_idunused_pos_on_aunused_pos_on_bcontact_normal_b_to_aunused_distancenormal_force
friction_1friction_direction_1
friction_2friction_direction_2friction_forcerF   local_forcelocal_force_normtoe_link_orders                            r6   feet_contact_forces!QuadrupedBase.feet_contact_forces  s    $++DDFMMOPM+0]1C+DE+Dabhhqk+DNE((99(( : *L    '{y5E)>Z!5z 
			#xx 56E"67*Drxx H"$.H/ /~-&;;!!4#3#3#<#<e++- 99>>+6&,,Y7a

(K
7
(   	/  0 ; Fs    Fleg_idc           
         U R                   R                  n[        U R                   R                  5       R	                  5       5      n[
        R                  " U R                  U R                  X1   U R                   Vs/ s H  oDS   PM	     snS9[        R                  " [        R                  " U5      U R                  /5      -  $ s  snf )a  Compute the Jacobian for a given leg.

Args:
  leg_id: Index of the leg for which the jacobian is computed.

Returns:
  The 3 x N transposed Jacobian matrix. where N is the total DoFs of the
  robot. For a quadruped, the first 6 columns of the matrix corresponds to
  the CoM translation and rotation. The columns corresponds to a leg can be
  extracted with indices [6 + leg_id * 3: 6 + leg_id * 3 + 3]. Note that
  the jacobian is calculated for motors, which takes motor directions into
  consideration.
r   )r   r   r
  all_joint_positions)r,   com_dofr   r  rV   r   compute_jacobianr   rO   r   r-   concatenateonesrg   )r4   r.  r1  r  states        r6   compute_jacobian_for_one_leg*QuadrupedBase.compute_jacobian_for_one_leg'  s     ''G$++DDFMMOPM,,,,%"&"4"4
"4!H"4
	 ^^RWWW-t/E/EFGH H
s   ?C	contact_forcec                 ^   [        U R                  R                  5       R                  5       5      nU R	                  U5      n[
        R                  " X$5      n0 nU R                  [        U5      -  nU R                  R                  n[        X-  US-   U-  5       H  n	XXU	-      Xi'   M     U$ )zMaps the foot contact force to the leg joint torques.

Args:
  leg_id: Index of the leg for which the jacobian is computed.
  contact_force: Desired contact force experted by the leg.

Returns:
  A dict containing the torques for each motor on the leg.
r   )r   r,   r  rV   r6  r-   matmulrI   r^   r1  r   )
r4   r.  r8  r  jvall_motor_torquesmotor_torquesmotors_per_legr1  rn   s
             r6   "map_contact_force_to_joint_torques0QuadrupedBase.map_contact_force_to_joint_torques?  s     $++DDFMMOPM		*	*6	2B		-4M__M(::N''G&1!A:79 1H2D Em9 r9   c                     [        S5      e)Nr   )r   )clss    r6   get_constantsQuadrupedBase.get_constantsV  s    
4
55r9   c                 "    U R                  5       $ r   )r#   r   s    r6   r   QuadrupedBase.timestampZ  s    ;;=r9   c                     U R                   $ r   )r'   r   s    r6   action_spaceQuadrupedBase.action_space^      r9   c                     U R                   $ r   )r(   r   s    r6   action_namesQuadrupedBase.action_namesb  rJ  r9   c                     U R                   $ )a  Gets the base orientation as a quaternion.

The base orientation is always relative to the init_orientation, which
can be updated by Reset function. This is necessary as many URDF can have an
internal frame that is not z-up, so if we don't provide an init_orientation
(through Reset), the loaded robot can have its belly facing the horizontal
direction.

Returns:
  The base orientation in quaternion.
)r   r   s    r6   r;   )QuadrupedBase.base_orientation_quaternionf  s     &&&r9   c                 h    U R                   R                  U R                  R                  5      u  pU$ )aH  Gets the base orientation in the robot's default frame.

This is the base orientation in whatever frame the robot specifies. For
simulated robot this is the URDF's internal frame. For real robot this can
be based on the rpy reading determined by the IMU.

Returns:
  The base orientation in quaternion in a robot default frame.
)r"   rN   r,   rO   )r4   r   r   s      r6   )base_orientation_quaternion_default_frame7QuadrupedBase.base_orientation_quaternion_default_frameu  s6     	;;&&	( A ! r9   c                     U R                   $ r   )r*   r   s    r6   r   QuadrupedBase.sensors  s    ==r9   c                     U R                   $ r   )r   r   s    r6   base_roll_pitch_yaw!QuadrupedBase.base_roll_pitch_yaw  s    $$$r9   c                     U R                   $ r   )r   r   s    r6   base_roll_pitch_yaw_rate&QuadrupedBase.base_roll_pitch_yaw_rate  s    )))r9   c                     U R                   $ r   )r   r   s    r6   r:   QuadrupedBase.base_position      r9   c                     U R                   $ r   )r   r   s    r6   r   QuadrupedBase.base_velocity  r]  r9   c                     g)NTr   r   s    r6   is_safeQuadrupedBase.is_safe  s    r9   c                     U R                   $ r   )r_   r   s    r6   rI   QuadrupedBase.num_motors  s    r9   c                     U R                   $ r   )ra   r   s    r6   motor_modelQuadrupedBase.motor_model      r9   c                     U R                   $ r   )r&   r   s    r6   r   QuadrupedBase.motor_limits  rJ  r9   c                     U R                   $ r   )r   r   s    r6   motor_anglesQuadrupedBase.motor_angles  rJ  r9   c                     U R                   $ r   )r   r   s    r6   motor_velocitiesQuadrupedBase.motor_velocities  s    !!!r9   c                     U R                   $ r   )r   r   s    r6   r=  QuadrupedBase.motor_torques  r]  r9   c                     U R                   $ r   )r"   r   s    r6   r   QuadrupedBase.pybullet_client  s       r9   c                     U R                   $ r   )r,   r   s    r6   r   QuadrupedBase.urdf_loader  rh  r9   c                 .    U R                   R                  $ r   )r,   rO   r   s    r6   rO   QuadrupedBase.robot_id  s    %%%r9   c                     U R                   $ r   )rS   r   s    r6   'initital_orientation_inverse_quaternion5QuadrupedBase.initital_orientation_inverse_quaternion  s    ***r9   c                 B    [         R                  " U R                  5      $ )aN  Get the base acceleration measured by an accelerometer.

The acceleration is measured in the local frame of a free-falling robot,
which is consistent with the robot's IMU measurements. Here the
gravitational acceleration is first added to the acceleration in the world
frame, which is then converted to the local frame of the robot.

)r-   re   r2   r   s    r6   r   -QuadrupedBase.base_acceleration_accelerometer  s     88D>>??r9   c                 B    [         R                  " U R                  5      $ )z-Get the base acceleration in the world frame.)r-   re   r1   r   s    r6   base_accelerationQuadrupedBase.base_acceleration  s     88D6677r9   )%r)   r(   r'   r   r   r   r   r   r#   rS   rQ   rP   rU   r   r2   r1   r/   r0   r   r$   rd   rg   r[   r]   r&   ra   r%   ri   rj   r   r   r_   r"   r+   r*   r   r,   )NNN)NNNF)NNr   )r   )F)P__name__
__module____qualname____firstlineno____doc__r   HybridMotorModelr
   BulletClientr   floatr   r   MotorLimitsr   r   
sensor_libSensorsafety_data_typesSafetyConfigr7   r   r	   r   r   r3   r`   rL   rk   ginconfigurableboolr   r   r   r   r   intr   r   r   r   r   r   r   r   r  r  r-   ndarrayr,  r6  r?  classmethodrC  propertyr   rH  rL  r;   rQ  r   rV  rY  r:   r   ra  rI   rf  r   rl  ro  r=  r   r   rO   rz  r   r  __static_attributes__r   r9   r6   r   r      sH   ?  2BB-/6:,$11, c5j!, '77	,
 !,,, , , 
))*, '33,` %)26=A	U5\U $)<U $tU{+U5\9:	Un+8Z		  %)26=A":(5\:( $)<:( $tU{+U5\9:	:(
 :( :(x/B  DH7(-eEl.24;.?/@ )A7 	 S ,S E  &()
+$&1P	 @E->$*+8BJJ#7 +ZH H H0(*

7;CJ7G. 6 6       ' ' ! !   % % * *           L44     " "   ! !   & & + + 	@ 	@ 8 8r9   r   )!r  typingr   r   r   r   r   r   r	   r  r   numpyr-   pybullet_utilsr
   &pybullet_envs.minitaur.envs_v2.sensorsr   r  pybullet_envs.minitaur.robotsr   r   r   r   $pybullet_envs.minitaur.robots.safetyr   r  'pybullet_envs.minitaur.robots.utilitiesr   r   r   r  	RobotBaser   r   r9   r6   <module>r     sh    ( D D D 
 
  ( G < 4 6 ; P D )  ~
8J(( ~
8 ~
8r9   