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
|
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-10-30 21:42:01 +05:30
|
|
|
|
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
|
|
|
|
2019-06-22 05:00:04 +05:30
|
|
|
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
|
2019-06-22 05:00:04 +05:30
|
|
|
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
|
2016-05-30 18:07:59 -07:00
|
|
|
|
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)
|
2016-05-30 18:07:59 -07:00
|
|
|
|
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
|
|
|
|
2019-06-22 05:00:04 +05:30
|
|
|
g = self.g
|
2019-10-25 17:22:10 -04:00
|
|
|
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
|
|
|
|
2021-09-25 20:00:28 +02: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)
|
2021-09-25 20:00:28 +02:00
|
|
|
newth = th + newthdot * dt
|
2016-04-27 08:00:58 -07:00
|
|
|
|
|
|
|
self.state = np.array([newth, newthdot])
|
|
|
|
return self._get_obs(), -costs, False, {}
|
|
|
|
|
2022-01-19 23:28:59 +01:00
|
|
|
def reset(self, *, seed: Optional[int] = None, options: Optional[dict] = None):
|
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])
|
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
|
2021-08-22 00:11:19 +02:00
|
|
|
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:
|
2022-01-06 19:01:29 +01:00
|
|
|
from gym.utils import pyglet_rendering
|
2021-07-29 02:26:34 +02:00
|
|
|
|
2022-01-06 19:01:29 +01: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)
|
2022-01-06 19:01:29 +01:00
|
|
|
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)
|
2022-01-06 19:01:29 +01:00
|
|
|
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)
|
2022-01-06 19:01:29 +01:00
|
|
|
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")
|
2022-01-06 19:01:29 +01:00
|
|
|
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)
|
2021-08-20 22:22:47 -04:00
|
|
|
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
|
|
|
|
Cleanup, removal of unmaintained code (#836)
* add dtype to Box
* remove board_game, debugging, safety, parameter_tuning environments
* massive set of breaking changes
- remove python logging module
- _step, _reset, _seed, _close => non underscored method
- remove benchmark and scoring folder
* Improve render("human"), now resizable, closable window.
* get rid of default step and reset in wrappers, so it doesn’t silently fail for people with underscore methods
* CubeCrash unit test environment
* followup fixes
* MemorizeDigits unit test envrionment
* refactored spaces a bit
fixed indentation
disabled test_env_semantics
* fix unit tests
* fixes
* CubeCrash, MemorizeDigits tested
* gym backwards compatibility patch
* gym backwards compatibility, followup fixes
* changelist, add spaces to main namespaces
* undo_logger_setup for backwards compat
* remove configuration.py
2018-01-25 18:20:14 -08:00
|
|
|
def close(self):
|
2018-09-14 13:36:57 -07:00
|
|
|
if self.viewer:
|
|
|
|
self.viewer.close()
|
|
|
|
self.viewer = None
|
Cleanup, removal of unmaintained code (#836)
* add dtype to Box
* remove board_game, debugging, safety, parameter_tuning environments
* massive set of breaking changes
- remove python logging module
- _step, _reset, _seed, _close => non underscored method
- remove benchmark and scoring folder
* Improve render("human"), now resizable, closable window.
* get rid of default step and reset in wrappers, so it doesn’t silently fail for people with underscore methods
* CubeCrash unit test environment
* followup fixes
* MemorizeDigits unit test envrionment
* refactored spaces a bit
fixed indentation
disabled test_env_semantics
* fix unit tests
* fixes
* CubeCrash, MemorizeDigits tested
* gym backwards compatibility patch
* gym backwards compatibility, followup fixes
* changelist, add spaces to main namespaces
* undo_logger_setup for backwards compat
* remove configuration.py
2018-01-25 18:20:14 -08:00
|
|
|
|
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
|