Files
Gymnasium/gym/envs/classic_control/pendulum.py

93 lines
3.1 KiB
Python
Raw Normal View History

Seeding update (#2422) * Ditch most of the seeding.py and replace np_random with the numpy default_rng. Let's see if tests pass * Updated a bunch of RNG calls from the RandomState API to Generator API * black; didn't expect that, did ya? * Undo a typo * blaaack * More typo fixes * Fixed setting/getting state in multidiscrete spaces * Fix typo, fix a test to work with the new sampling * Correctly (?) pass the randomly generated seed if np_random is called with None as seed * Convert the Discrete sample to a python int (as opposed to np.int64) * Remove some redundant imports * First version of the compatibility layer for old-style RNG. Mainly to trigger tests. * Removed redundant f-strings * Style fixes, removing unused imports * Try to make tests pass by removing atari from the dockerfile * Try to make tests pass by removing atari from the setup * Try to make tests pass by removing atari from the setup * Try to make tests pass by removing atari from the setup * First attempt at deprecating `env.seed` and supporting `env.reset(seed=seed)` instead. Tests should hopefully pass but throw up a million warnings. * black; didn't expect that, didya? * Rename the reset parameter in VecEnvs back to `seed` * Updated tests to use the new seeding method * Removed a bunch of old `seed` calls. Fixed a bug in AsyncVectorEnv * Stop Discrete envs from doing part of the setup (and using the randomness) in init (as opposed to reset) * Add explicit seed to wrappers reset * Remove an accidental return * Re-add some legacy functions with a warning. * Use deprecation instead of regular warnings for the newly deprecated methods/functions
2021-12-08 22:14:15 +01:00
from typing import Optional
2016-04-27 08:00:58 -07:00
import gym
from gym import spaces
[WIP] add support for seeding environments (#135) * Make environments seedable * Fix monitor bugs - Set monitor_id before setting the infix. This was a bug that would yield incorrect results with multiple monitors. - Remove extra pid from stats recorder filename. This should be purely cosmetic. * Start uploading seeds in episode_batch * Fix _bigint_from_bytes for python3 * Set seed explicitly in random_agent * Pass through seed argument * Also pass through random state to spaces * Pass random state into the observation/action spaces * Make all _seed methods return the list of used seeds * Switch over to np.random where possible * Start hashing seeds, and also seed doom engine * Fixup seeding determinism in many cases * Seed before loading the ROM * Make seeding more Python3 friendly * Make the MuJoCo skipping a bit more forgiving * Remove debugging PDB calls * Make setInt argument into raw bytes * Validate and upload seeds * Skip box2d * Make seeds smaller, and change representation of seeds in upload * Handle long seeds * Fix RandomAgent example to be deterministic * Handle integer types correctly in Python2 and Python3 * Try caching pip * Try adding swap * Add df and free calls * Bump swap * Bump swap size * Try setting overcommit * Try other sysctls * Try fixing overcommit * Try just setting overcommit_memory=1 * Add explanatory comment * Add what's new section to readme * BUG: Mark ElevatorAction-ram-v0 as non-deterministic for now * Document seed * Move nondetermistic check into spec
2016-05-29 09:07:09 -07:00
from gym.utils import seeding
2016-04-27 08:00:58 -07:00
import numpy as np
from os import path
2020-04-24 23:56:04 +02:00
2016-04-27 08:00:58 -07:00
class PendulumEnv(gym.Env):
2021-07-29 02:26:34 +02:00
metadata = {"render.modes": ["human", "rgb_array"], "video.frames_per_second": 30}
2016-04-27 08:00:58 -07:00
def __init__(self, g=10.0):
2020-04-24 23:56:04 +02:00
self.max_speed = 8
2021-07-29 02:26:34 +02:00
self.max_torque = 2.0
self.dt = 0.05
self.g = g
2021-07-29 02:26:34 +02:00
self.m = 1.0
self.l = 1.0
2016-04-27 08:00:58 -07:00
self.viewer = None
2021-07-29 02:26:34 +02:00
high = np.array([1.0, 1.0, self.max_speed], dtype=np.float32)
2021-07-29 15:39:42 -04:00
self.action_space = spaces.Box(
low=-self.max_torque, high=self.max_torque, shape=(1,), dtype=np.float32
)
2021-07-29 02:26:34 +02:00
self.observation_space = spaces.Box(low=-high, high=high, dtype=np.float32)
2020-02-28 15:55:13 -08:00
def step(self, u):
2020-04-24 23:56:04 +02:00
th, thdot = self.state # th := theta
2016-04-27 08:00:58 -07:00
g = self.g
m = self.m
l = self.l
2016-04-27 08:00:58 -07:00
dt = self.dt
u = np.clip(u, -self.max_torque, self.max_torque)[0]
2020-04-24 23:56:04 +02:00
self.last_u = u # for rendering
2021-07-29 02:26:34 +02:00
costs = angle_normalize(th) ** 2 + 0.1 * thdot ** 2 + 0.001 * (u ** 2)
2016-04-27 08:00:58 -07:00
newthdot = thdot + (3 * g / (2 * l) * np.sin(th) + 3.0 / (m * l ** 2) * u) * dt
2020-04-24 23:56:04 +02:00
newthdot = np.clip(newthdot, -self.max_speed, self.max_speed)
newth = th + newthdot * dt
2016-04-27 08:00:58 -07:00
self.state = np.array([newth, newthdot])
return self._get_obs(), -costs, False, {}
def reset(self, *, seed: Optional[int] = None, options: Optional[dict] = None):
Seeding update (#2422) * Ditch most of the seeding.py and replace np_random with the numpy default_rng. Let's see if tests pass * Updated a bunch of RNG calls from the RandomState API to Generator API * black; didn't expect that, did ya? * Undo a typo * blaaack * More typo fixes * Fixed setting/getting state in multidiscrete spaces * Fix typo, fix a test to work with the new sampling * Correctly (?) pass the randomly generated seed if np_random is called with None as seed * Convert the Discrete sample to a python int (as opposed to np.int64) * Remove some redundant imports * First version of the compatibility layer for old-style RNG. Mainly to trigger tests. * Removed redundant f-strings * Style fixes, removing unused imports * Try to make tests pass by removing atari from the dockerfile * Try to make tests pass by removing atari from the setup * Try to make tests pass by removing atari from the setup * Try to make tests pass by removing atari from the setup * First attempt at deprecating `env.seed` and supporting `env.reset(seed=seed)` instead. Tests should hopefully pass but throw up a million warnings. * black; didn't expect that, didya? * Rename the reset parameter in VecEnvs back to `seed` * Updated tests to use the new seeding method * Removed a bunch of old `seed` calls. Fixed a bug in AsyncVectorEnv * Stop Discrete envs from doing part of the setup (and using the randomness) in init (as opposed to reset) * Add explicit seed to wrappers reset * Remove an accidental return * Re-add some legacy functions with a warning. * Use deprecation instead of regular warnings for the newly deprecated methods/functions
2021-12-08 22:14:15 +01:00
super().reset(seed=seed)
2016-04-27 08:00:58 -07:00
high = np.array([np.pi, 1])
[WIP] add support for seeding environments (#135) * Make environments seedable * Fix monitor bugs - Set monitor_id before setting the infix. This was a bug that would yield incorrect results with multiple monitors. - Remove extra pid from stats recorder filename. This should be purely cosmetic. * Start uploading seeds in episode_batch * Fix _bigint_from_bytes for python3 * Set seed explicitly in random_agent * Pass through seed argument * Also pass through random state to spaces * Pass random state into the observation/action spaces * Make all _seed methods return the list of used seeds * Switch over to np.random where possible * Start hashing seeds, and also seed doom engine * Fixup seeding determinism in many cases * Seed before loading the ROM * Make seeding more Python3 friendly * Make the MuJoCo skipping a bit more forgiving * Remove debugging PDB calls * Make setInt argument into raw bytes * Validate and upload seeds * Skip box2d * Make seeds smaller, and change representation of seeds in upload * Handle long seeds * Fix RandomAgent example to be deterministic * Handle integer types correctly in Python2 and Python3 * Try caching pip * Try adding swap * Add df and free calls * Bump swap * Bump swap size * Try setting overcommit * Try other sysctls * Try fixing overcommit * Try just setting overcommit_memory=1 * Add explanatory comment * Add what's new section to readme * BUG: Mark ElevatorAction-ram-v0 as non-deterministic for now * Document seed * Move nondetermistic check into spec
2016-05-29 09:07:09 -07:00
self.state = self.np_random.uniform(low=-high, high=high)
2016-04-27 08:00:58 -07:00
self.last_u = None
return self._get_obs()
def _get_obs(self):
theta, thetadot = self.state
return np.array([np.cos(theta), np.sin(theta), thetadot], dtype=np.float32)
2016-04-27 08:00:58 -07:00
2021-07-29 02:26:34 +02:00
def render(self, mode="human"):
2016-04-27 08:00:58 -07:00
if self.viewer is None:
from gym.utils import pyglet_rendering
2021-07-29 02:26:34 +02:00
self.viewer = pyglet_rendering.Viewer(500, 500)
2020-04-24 23:56:04 +02:00
self.viewer.set_bounds(-2.2, 2.2, -2.2, 2.2)
rod = pyglet_rendering.make_capsule(1, 0.2)
2021-07-29 02:26:34 +02:00
rod.set_color(0.8, 0.3, 0.3)
self.pole_transform = pyglet_rendering.Transform()
2016-04-27 08:00:58 -07:00
rod.add_attr(self.pole_transform)
self.viewer.add_geom(rod)
axle = pyglet_rendering.make_circle(0.05)
2020-04-24 23:56:04 +02:00
axle.set_color(0, 0, 0)
2016-04-27 08:00:58 -07:00
self.viewer.add_geom(axle)
fname = path.join(path.dirname(__file__), "assets/clockwise.png")
self.img = pyglet_rendering.Image(fname, 1.0, 1.0)
self.imgtrans = pyglet_rendering.Transform()
2016-04-27 08:00:58 -07:00
self.img.add_attr(self.imgtrans)
self.viewer.add_onetime(self.img)
2020-04-24 23:56:04 +02:00
self.pole_transform.set_rotation(self.state[0] + np.pi / 2)
if self.last_u is not None:
2020-04-24 23:56:04 +02:00
self.imgtrans.scale = (-self.last_u / 2, np.abs(self.last_u) / 2)
2016-04-27 08:00:58 -07:00
2021-07-29 02:26:34 +02:00
return self.viewer.render(return_rgb_array=mode == "rgb_array")
2016-04-27 08:00:58 -07:00
def close(self):
if self.viewer:
self.viewer.close()
self.viewer = None
2020-04-24 23:56:04 +02:00
2016-04-27 08:00:58 -07:00
def angle_normalize(x):
2021-07-29 02:26:34 +02:00
return ((x + np.pi) % (2 * np.pi)) - np.pi