
    hs2                         S /r SSKrSSKJr  SSKJr  SSKJr  SS\R                  " S5      S.r
 " S	 S
\\R                  5      rg)zKallinteris-Andreas    N)utils)	MujocoEnv)Boxg=
ףp}@)        r   g`(\?)trackbodyiddistancelookatc                   x    \ rS rSrSrS/ SQ0rSS0 SS4S	\S
\S\\\	\-  4   S\	S\	4
S jjr
S rS rS rS rSrg)InvertedDoublePendulumEnv   a#  
## Description
This environment originates from control theory and builds on the cartpole environment based on the work of Barto, Sutton, and Anderson in ["Neuronlike adaptive elements that can solve difficult learning control problems"](https://ieeexplore.ieee.org/document/6313077),
powered by the Mujoco physics simulator - allowing for more complex experiments (such as varying the effects of gravity or constraints).
This environment involves a cart that can be moved linearly, with one pole attached to it and a second pole attached to the other end of the first pole (leaving the second pole as the only one with a free end).
The cart can be pushed left or right, and the goal is to balance the second pole on top of the first pole, which is in turn on top of the cart, by applying continuous forces to the cart.


## Action Space
The agent take a 1-element vector for actions.
The action space is a continuous `(action)` in `[-1, 1]`, where `action` represents the
numerical force applied to the cart (with magnitude representing the amount of force and
sign representing the direction)

| Num | Action                    | Control Min | Control Max | Name (in corresponding XML file) | Joint |Type (Unit)|
|-----|---------------------------|-------------|-------------|----------------------------------|-------|-----------|
| 0   | Force applied on the cart | -1          | 1           | slider                           | slide | Force (N) |


## Observation Space
The observation space consists of the following parts (in order):

- *qpos (1 element):* Position values of the robot's cart.
- *sin(qpos) (2 elements):* The sine of the angles of poles.
- *cos(qpos) (2 elements):* The cosine of the angles of poles.
- *qvel (3 elements):* The velocities of these individual body parts (their derivatives).
- *qfrc_constraint (1 element):* Constraint force of the cart.
There is one constraint force for contacts for each degree of freedom (3).
The approach and handling of constraints by MuJoCo is unique to the simulator and is based on their research.
More information can be found  in their [*documentation*](https://mujoco.readthedocs.io/en/latest/computation.html) or in their paper ["Analytically-invertible dynamics with contacts and constraints: Theory and implementation in MuJoCo"](https://homes.cs.washington.edu/~todorov/papers/TodorovICRA14.pdf).

The observation space is a `Box(-Inf, Inf, (9,), float64)` where the elements are as follows:

| Num | Observation                                                       | Min  | Max | Name (in corresponding XML file) | Joint | Type (Unit)              |
| --- | ----------------------------------------------------------------- | ---- | --- | -------------------------------- | ----- | ------------------------ |
| 0   | position of the cart along the linear surface                     | -Inf | Inf | slider                           | slide | position (m)             |
| 1   | sine of the angle between the cart and the first pole             | -Inf | Inf | sin(hinge)                       | hinge | unitless                 |
| 2   | sine of the angle between the two poles                           | -Inf | Inf | sin(hinge2)                      | hinge | unitless                 |
| 3   | cosine of the angle between the cart and the first pole           | -Inf | Inf | cos(hinge)                       | hinge | unitless                 |
| 4   | cosine of the angle between the two poles                         | -Inf | Inf | cos(hinge2)                      | hinge | unitless                 |
| 5   | velocity of the cart                                              | -Inf | Inf | slider                           | slide | velocity (m/s)           |
| 6   | angular velocity of the angle between the cart and the first pole | -Inf | Inf | hinge                            | hinge | angular velocity (rad/s) |
| 7   | angular velocity of the angle between the two poles               | -Inf | Inf | hinge2                           | hinge | angular velocity (rad/s) |
| 8   | constraint force - x                                              | -Inf | Inf | slider                           | slide | Force (N)                |
| excluded | constraint force - y                                         | -Inf | Inf | slider                           | slide | Force (N)                |
| excluded | constraint force - z                                         | -Inf | Inf | slider                           | slide | Force (N)                |


## Rewards
The total reward is: ***reward*** *=* *alive_bonus - distance_penalty - velocity_penalty*.

- *alive_bonus*:
Every timestep that the Inverted Pendulum is healthy (see definition in section "Episode End"),
it gets a reward of fixed value `healthy_reward` (default is $10$).
- *distance_penalty*:
This reward is a measure of how far the *tip* of the second pendulum (the only free end) moves,
and it is calculated as $0.01 x_{pole2-tip}^2 + (y_{pole2-tip}-2)^2$,
where $x_{pole2-tip}, y_{pole2-tip}$ are the xy-coordinatesof the tip of the second pole.
- *velocity_penalty*:
A negative reward to penalize the agent for moving too fast.
$10^{-3} \omega_1 + 5 \times 10^{-3} \omega_2$,
where $\omega_1, \omega_2$ are the angular velocities of the hinges.

`info` contains the individual reward terms.


## Starting State
The initial position state is $\mathcal{U}_{[-reset\_noise\_scale \times I_{3}, reset\_noise\_scale \times I_{3}]}$.
The initial velocity state is $\mathcal{N}(0_{3}, reset\_noise\_scale^2 \times I_{3})$.

where $\mathcal{N}$ is the multivariate normal distribution and $\mathcal{U}$ is the multivariate uniform continuous distribution.


## Episode End
### Termination
The environment terminates when the Inverted Double Pendulum is unhealthy.
The Inverted Double Pendulum is unhealthy if any of the following happens:

1.Termination: The y_coordinate of the tip of the second pole $\leq 1$.

Note: The maximum standing height of the system is 1.2 m when all the parts are perpendicularly vertical on top of each other.

### Truncation
The default duration of an episode is 1000 timesteps.


## Arguments
InvertedDoublePendulum provides a range of parameters to modify the observation space, reward function, initial state, and termination condition.
These parameters can be applied during `gymnasium.make` in the following way:

```python
import gymnasium as gym
env = gym.make('InvertedDoublePendulum-v5', healthy_reward=10, ...)
```

| Parameter               | Type       | Default                        | Description                                                                                   |
|-------------------------|------------|--------------------------------|-----------------------------------------------------------------------------------------------|
| `xml_file`              | **str**    |`"inverted_double_pendulum.xml"`| Path to a MuJoCo model                                                                        |
| `healthy_reward`        | **float**  | `10`                           | Constant reward given if the pendulum is `healthy` (upright) (see `Rewards` section)          |
| `reset_noise_scale`     | **float**  | `0.1`                          | Scale of random perturbations of initial position and velocity (see `Starting State` section) |

## Version History
* v5:
    - Minimum `mujoco` version is now 2.3.3.
    - Added `default_camera_config` argument, a dictionary for setting the `mj_camera` properties, mainly useful for custom environments.
    - Added `frame_skip` argument, used to configure the `dt` (duration of `step()`), default varies by environment check environment documentation pages.
    - Fixed bug: `healthy_reward` was given on every step (even if the Pendulum is unhealthy), now it is only given if the DoublePendulum is healthy (not terminated)(related [GitHub issue](https://github.com/Farama-Foundation/Gymnasium/issues/500)).
    - Excluded the `qfrc_constraint` ("constraint force") of the hinges from the observation space (as it was always 0, thus providing no useful information to the agent, resulting in slightly faster training) (related [GitHub issue](https://github.com/Farama-Foundation/Gymnasium/issues/228)).
    - Added `xml_file` argument.
    - Added `reset_noise_scale` argument to set the range of initial states.
    - Added `healthy_reward` argument to configure the reward function (defaults are effectively the same as in `v4`).
    - Added individual reward terms in `info` (`info["reward_survive"]`, `info["distance_penalty"]`, `info["velocity_penalty"]`).
* v4: All MuJoCo environments now use the MuJoCo bindings in mujoco >= 2.1.3.
* v3: This environment does not have a v3 release. Moved to the [gymnasium-robotics repo](https://github.com/Farama-Foundation/gymnasium-robotics).
* v2: All continuous control environments now use mujoco-py >= 1.50. Moved to the [gymnasium-robotics repo](https://github.com/Farama-Foundation/gymnasium-robotics).
* v1: max_time_steps raised to 1000 for robot based tasks (including inverted pendulum).
* v0: Initial versions release.
render_modeshuman	rgb_arraydepth_array
rgbd_tuplezinverted_double_pendulum.xml   g      $@g?xml_file
frame_skipdefault_camera_confighealthy_rewardreset_noise_scalec                 r   [         R                  R                  " XX%40 UD6  X@l        XPl        [        [        R                  * [        R                  S[        R                  S9n[        R                  " U UU4UUS.UD6  / SQ[        [        R                  " SU R                  -  5      5      S.U l        g )N)	   )lowhighshapedtype)observation_spacer   r   g      ?)r   
render_fps)r   EzPickle__init___healthy_reward_reset_noise_scaler   npinffloat64r   introunddtmetadata)selfr   r   r   r   r   kwargsr   s           k/home/james-whalen/.local/lib/python3.13/site-packages/gymnasium/envs/mujoco/inverted_double_pendulum_v5.pyr"   "InvertedDoublePendulumEnv.__init__   s     	
XQWX-"3RVVG"&&BJJW	
 0"7	
 	
 bhhsTWW}56
    c                 $   U R                  XR                  5        U R                  R                  S   u  p#nU R	                  5       n[        US:*  5      nU R                  X$U5      u  pxUn	U R                  S:X  a  U R                  5         XWUSU	4$ )Nr      r   F)	do_simulationr   data	site_xpos_get_obsbool_get_rewrender_moderender)
r,   actionx_yobservation
terminatedrewardreward_infoinfos
             r.   stepInvertedDoublePendulumEnv.step   s    6??3))%%a(ammo!q&\
"mmA*=w&KKMJt;;r0   c                     U R                   R                  SS u  pESUS-  -  US-
  S-  -   nSUS-  -  SUS-  -  -   nU R                  [        U(       + 5      -  nX-
  U-
  n	UU* U* S.n
X4$ )Nr2      g{Gz?   gMbP?g{Gzt?)reward_survivedistance_penaltyvelocity_penalty)r4   qvelr#   r(   )r,   r<   r>   r@   v1v2dist_penaltyvel_penaltyalive_bonusrA   rB   s              r.   r8   "InvertedDoublePendulumEnv._get_rew   s    !$ad{a!e\1RUlTBE\1**SZ-@@+k9 *!-!,
 ""r0   c                    [         R                  " U R                  R                  S S [         R                  " U R                  R                  SS  5      [         R
                  " U R                  R                  SS  5      [         R                  " U R                  R                  SS5      [         R                  " U R                  R                  SS5      S S /5      R                  5       $ )Nr2   i
   )
r%   concatenater4   qpossincoscliprL   qfrc_constraintravel)r,   s    r.   r6   "InvertedDoublePendulumEnv._get_obs   s    ~~		r"tyy~~ab)*tyy~~ab)*		R0		113;BQ?
 %'	r0   c           	      x   U R                   * nU R                   nU R                  U R                  U R                  R	                  XU R
                  R                  S9-   U R                  U R                  R                  U R
                  R                  5      U R                   -  -   5        U R                  5       $ )N)r   r   size)r$   	set_state	init_qpos	np_randomuniformmodelnq	init_qvelstandard_normalnvr6   )r,   	noise_low
noise_highs      r.   reset_model%InvertedDoublePendulumEnv.reset_model   s    ,,,	,,
NNnn$$TZZ]] %  NNnn,,TZZ]];d>U>UUV	
 }}r0   )r#   r$   r+   N)__name__
__module____qualname____firstlineno____doc__r+   strr(   dictfloatr"   rD   r8   r6   rj   __static_attributes__ r0   r.   r   r      s    up 	 
H 78: $#&!
!
 !
  $C$45	!

 !
 !!
F<# 	r0   r   )__credits__numpyr%   	gymnasiumr   gymnasium.envs.mujocor   gymnasium.spacesr   arrayDEFAULT_CAMERA_CONFIGr!   r   ru   r0   r.   <module>r}      sJ   $%   +   hh67 Z	5>> Zr0   