tinysim 0.0.4__py3-none-any.whl → 0.0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tinysim/__init__.py +7 -2
- tinysim/_tk_base.py +20 -2
- tinysim/_widget_base.py +41 -0
- tinysim/flappy/__init__.py +5 -3
- tinysim/flappy/tk.py +10 -34
- tinysim/flappy/widget.py +9 -38
- tinysim/frogger/__init__.py +21 -4
- tinysim/frogger/tk.py +12 -28
- tinysim/frogger/widget.py +8 -37
- tinysim/mountain_car/__init__.py +17 -12
- tinysim/mountain_car/tk.py +9 -27
- tinysim/mountain_car/widget.py +8 -37
- tinysim/tinyspace.py +68 -0
- tinysim/topdown_driving/__init__.py +16 -18
- tinysim/topdown_driving/tk.py +13 -38
- tinysim/topdown_driving/track_0.json +1 -753
- tinysim/topdown_driving/widget.py +8 -42
- {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/METADATA +5 -6
- {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/RECORD +35 -35
- {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/WHEEL +1 -1
- tinysim_mujoco/gl_viewer.py +36 -11
- tinysim_mujoco/manipulation/__init__.py +19 -5
- tinysim_mujoco/manipulation/push_env.py +268 -0
- tinysim_mujoco/manipulation/push_env_cam.py +274 -0
- tinysim_mujoco/manipulation/xmls/panda.xml +59 -16
- tinysim_mujoco/manipulation/xmls/scene.xml +0 -3
- tinysim_mujoco/manipulation/xmls/table.xml +17 -13
- tinysim_mujoco/notebook_viewer.py +3 -6
- tinysim_mujoco/unitree_a1/__init__.py +7 -10
- tinysim_warp/__init__.py +108 -0
- tinysim_warp/cart_pole/__init__.py +44 -200
- tinysim_warp/quadruped/__init__.py +23 -160
- tinysim_warp/simple_quadruped/__init__.py +20 -91
- tinysim_warp/simple_quadruped/simple_quadruped.urdf +0 -9
- tinysim/simple_amr/__init__.py +0 -0
- tinysim/simple_amr/example_maps.py +0 -121
- tinysim/simple_amr/sim.js +0 -430
- tinysim/simple_amr/styles.css +0 -54
- tinysim/simple_amr/widget.py +0 -73
- {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/top_level.txt +0 -0
tinysim/__init__.py
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
|
|
3
|
+
from .tinyspace import Space
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
class SimEnvironment(ABC):
|
|
7
|
+
|
|
8
|
+
action_space: Space
|
|
9
|
+
|
|
5
10
|
@abstractmethod
|
|
6
|
-
def step(self,
|
|
11
|
+
def step(self, *args, **kwargs):
|
|
7
12
|
pass
|
|
8
13
|
|
|
9
14
|
@abstractmethod
|
|
10
|
-
def reset(self
|
|
15
|
+
def reset(self, *args, **kwargs):
|
|
11
16
|
pass
|
tinysim/_tk_base.py
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import tkinter as tk
|
|
2
1
|
import threading
|
|
2
|
+
import tkinter as tk
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
4
|
|
|
5
|
+
from . import SimEnvironment
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
class TkBaseFrontend(ABC):
|
|
7
9
|
|
|
8
|
-
def __init__(self):
|
|
10
|
+
def __init__(self, sim_env: SimEnvironment):
|
|
11
|
+
self.sim_env = sim_env
|
|
9
12
|
self._root = None
|
|
10
13
|
self._canvas = None
|
|
11
14
|
self._thread = None
|
|
@@ -16,6 +19,21 @@ class TkBaseFrontend(ABC):
|
|
|
16
19
|
self._thread = threading.Thread(target=self._window_hook, daemon=True)
|
|
17
20
|
self._thread.start()
|
|
18
21
|
|
|
22
|
+
def step(self, *args, **kwargs):
|
|
23
|
+
state = self.sim_env.step(*args, **kwargs)
|
|
24
|
+
if self._root:
|
|
25
|
+
self._root.after(0, lambda: self._draw_state(state))
|
|
26
|
+
return state
|
|
27
|
+
|
|
28
|
+
def reset(self, *args, **kwargs):
|
|
29
|
+
state = self.sim_env.reset()
|
|
30
|
+
if self._canvas:
|
|
31
|
+
self._draw_state(state)
|
|
32
|
+
return state
|
|
33
|
+
|
|
34
|
+
def _draw_state(self, state):
|
|
35
|
+
raise NotImplementedError
|
|
36
|
+
|
|
19
37
|
def _window_hook(self):
|
|
20
38
|
root = tk.Tk()
|
|
21
39
|
root.protocol("WM_DELETE_WINDOW", self._on_close)
|
tinysim/_widget_base.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import anywidget
|
|
2
|
+
import traitlets
|
|
3
|
+
from IPython.display import display
|
|
4
|
+
from jupyter_ui_poll import ui_events
|
|
5
|
+
|
|
6
|
+
from . import SimEnvironment
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BaseWidget(anywidget.AnyWidget):
|
|
10
|
+
|
|
11
|
+
sim_env: SimEnvironment
|
|
12
|
+
_view_ready = traitlets.Bool(default_value=False).tag(sync=True)
|
|
13
|
+
|
|
14
|
+
def __init__(self, sim_env: SimEnvironment):
|
|
15
|
+
super().__init__()
|
|
16
|
+
self.sim_env = sim_env
|
|
17
|
+
self.sim_state = self.sim_env.reset()
|
|
18
|
+
self._update_props(self.sim_state)
|
|
19
|
+
|
|
20
|
+
def render(self):
|
|
21
|
+
display(self)
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
with ui_events() as ui_poll:
|
|
25
|
+
while not self._view_ready:
|
|
26
|
+
ui_poll(100)
|
|
27
|
+
except Exception:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
def _update_props(self, sim_state):
|
|
31
|
+
self.sim_state = sim_state
|
|
32
|
+
|
|
33
|
+
def step(self, *args, **kwargs):
|
|
34
|
+
sim_state = self.sim_env.step(*args, **kwargs)
|
|
35
|
+
self._update_props(sim_state)
|
|
36
|
+
return sim_state
|
|
37
|
+
|
|
38
|
+
def reset(self, *args, **kwargs):
|
|
39
|
+
sim_state = self.sim_env.reset(*args, **kwargs)
|
|
40
|
+
self._update_props(sim_state)
|
|
41
|
+
return sim_state
|
tinysim/flappy/__init__.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
+
|
|
2
3
|
from .. import SimEnvironment
|
|
4
|
+
from ..tinyspace import Discrete
|
|
3
5
|
|
|
4
6
|
WIDTH, HEIGHT = 800, 600
|
|
5
7
|
GRAVITY = 900.0
|
|
@@ -16,6 +18,7 @@ BIRD_SIZE = 35
|
|
|
16
18
|
class FlappyEnv(SimEnvironment):
|
|
17
19
|
def __init__(self, num_envs: int = 1):
|
|
18
20
|
self.num_envs = num_envs
|
|
21
|
+
self.action_space = Discrete(2) # 0: no flap, 1: flap
|
|
19
22
|
self.reset()
|
|
20
23
|
|
|
21
24
|
def reset(self):
|
|
@@ -54,16 +57,15 @@ class FlappyEnv(SimEnvironment):
|
|
|
54
57
|
self.pipes_x = self.pipes_x[keep]
|
|
55
58
|
self.pipes_y = self.pipes_y[keep]
|
|
56
59
|
|
|
57
|
-
def _check_collisions(self):
|
|
60
|
+
def _check_collisions(self):
|
|
58
61
|
hit_bounds = (self.bird_y < 0) | (self.bird_y + BIRD_SIZE > HEIGHT)
|
|
59
|
-
bx = BIRD_X
|
|
60
62
|
by = self.bird_y[:, None]
|
|
61
63
|
px = self.pipes_x[None, :]
|
|
62
64
|
upper_y = np.zeros_like(self.pipes_y)[None, :]
|
|
63
65
|
upper_h = self.pipes_y[None, :]
|
|
64
66
|
lower_y = (self.pipes_y + PIPE_GAP)[None, :]
|
|
65
67
|
lower_h = (HEIGHT - (self.pipes_y + PIPE_GAP))[None, :]
|
|
66
|
-
x_overlap = (
|
|
68
|
+
x_overlap = (BIRD_X < px + PIPE_WIDTH) & (BIRD_X + BIRD_SIZE > px)
|
|
67
69
|
upper_hit = x_overlap & (by < upper_y + upper_h) & (by + BIRD_SIZE > upper_y)
|
|
68
70
|
lower_hit = x_overlap & (by < lower_y + lower_h) & (by + BIRD_SIZE > lower_y)
|
|
69
71
|
hit_pipe = (upper_hit | lower_hit).any(axis=1)
|
tinysim/flappy/tk.py
CHANGED
|
@@ -1,45 +1,22 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
|
|
3
1
|
try:
|
|
4
2
|
import tkinter as tk
|
|
5
|
-
|
|
3
|
+
|
|
4
|
+
from .._tk_base import TkBaseFrontend
|
|
6
5
|
except ImportError:
|
|
7
6
|
raise ImportError("tkinter is required for FlappyTkFrontend")
|
|
8
7
|
|
|
9
|
-
from . import
|
|
10
|
-
FlappyEnv,
|
|
11
|
-
WIDTH,
|
|
12
|
-
HEIGHT,
|
|
13
|
-
PIPE_WIDTH,
|
|
14
|
-
BIRD_SIZE,
|
|
15
|
-
BIRD_X,
|
|
16
|
-
PIPE_GAP,
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class FlappyTkFrontend(_tk_base.TkBaseFrontend):
|
|
8
|
+
from . import BIRD_SIZE, BIRD_X, HEIGHT, PIPE_GAP, PIPE_WIDTH, WIDTH, FlappyEnv
|
|
21
9
|
|
|
22
|
-
def __init__(self, viewport_size=(800, 600), sim_env=None):
|
|
23
|
-
super().__init__()
|
|
24
|
-
if sim_env is None:
|
|
25
|
-
sim_env = FlappyEnv()
|
|
26
10
|
|
|
27
|
-
|
|
11
|
+
class FlappyTkFrontend(TkBaseFrontend):
|
|
12
|
+
def __init__(self, viewport_size=(800, 600), sim_env=FlappyEnv()):
|
|
13
|
+
super().__init__(sim_env)
|
|
28
14
|
self._viewport_size = viewport_size
|
|
29
15
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
await asyncio.sleep(dt)
|
|
36
|
-
return state
|
|
37
|
-
|
|
38
|
-
async def reset(self):
|
|
39
|
-
state = self.sim_env.reset()
|
|
40
|
-
if self._root:
|
|
41
|
-
self._draw_state(state)
|
|
42
|
-
return state
|
|
16
|
+
if sim_env.num_envs != 1:
|
|
17
|
+
raise ValueError(
|
|
18
|
+
"FlappyTkFrontend currently only supports single environment."
|
|
19
|
+
)
|
|
43
20
|
|
|
44
21
|
def _create_window(self, root):
|
|
45
22
|
w, h = self._viewport_size
|
|
@@ -66,7 +43,6 @@ class FlappyTkFrontend(_tk_base.TkBaseFrontend):
|
|
|
66
43
|
|
|
67
44
|
# bird
|
|
68
45
|
by = state["bird_y"]
|
|
69
|
-
|
|
70
46
|
if not state.get("done", False):
|
|
71
47
|
canvas.create_oval(
|
|
72
48
|
BIRD_X,
|
tinysim/flappy/widget.py
CHANGED
|
@@ -1,53 +1,24 @@
|
|
|
1
1
|
import pathlib
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import traitlets
|
|
4
|
-
import asyncio
|
|
5
|
-
from IPython.display import display
|
|
6
|
-
from jupyter_ui_poll import ui_events
|
|
7
4
|
|
|
5
|
+
from .._widget_base import BaseWidget
|
|
8
6
|
from . import FlappyEnv
|
|
9
7
|
|
|
10
8
|
|
|
11
|
-
class FlappySim(
|
|
9
|
+
class FlappySim(BaseWidget):
|
|
12
10
|
_esm = pathlib.Path(__file__).parent / "sim.js"
|
|
13
11
|
|
|
14
12
|
sim_state = traitlets.Dict(default_value={}).tag(sync=True)
|
|
15
|
-
_viewport_size = traitlets.Tuple(
|
|
16
|
-
traitlets.Int(), traitlets.Int(), default_value=(800, 600)
|
|
17
|
-
).tag(sync=True)
|
|
13
|
+
_viewport_size = traitlets.Tuple(default_value=(800, 600)).tag(sync=True)
|
|
18
14
|
_manual_control = traitlets.Bool(default_value=False).tag(sync=True)
|
|
19
|
-
_view_ready = traitlets.Bool(default_value=False).tag(sync=True)
|
|
20
15
|
|
|
21
|
-
def __init__(
|
|
22
|
-
|
|
16
|
+
def __init__(
|
|
17
|
+
self, viewport_size=(800, 600), manual_control=False, sim_env=FlappyEnv()
|
|
18
|
+
):
|
|
19
|
+
super().__init__(sim_env)
|
|
23
20
|
self._viewport_size = viewport_size
|
|
24
21
|
self._manual_control = manual_control
|
|
25
|
-
|
|
26
|
-
sim_env = FlappyEnv()
|
|
22
|
+
|
|
27
23
|
if sim_env.num_envs != 1:
|
|
28
24
|
raise ValueError("FlappySim currently only supports single environment.")
|
|
29
|
-
|
|
30
|
-
self.sim_env = sim_env
|
|
31
|
-
self.sim_state = self.sim_env.reset()
|
|
32
|
-
|
|
33
|
-
def render(self):
|
|
34
|
-
display(self)
|
|
35
|
-
|
|
36
|
-
try:
|
|
37
|
-
with ui_events() as ui_poll:
|
|
38
|
-
while not self._view_ready:
|
|
39
|
-
ui_poll(100)
|
|
40
|
-
except Exception:
|
|
41
|
-
pass
|
|
42
|
-
|
|
43
|
-
async def step(self, action, dt=0.02):
|
|
44
|
-
state = self.sim_env.step(action, dt=dt)
|
|
45
|
-
self.sim_state = state
|
|
46
|
-
await asyncio.sleep(dt)
|
|
47
|
-
return state
|
|
48
|
-
|
|
49
|
-
async def reset(self):
|
|
50
|
-
state = self.sim_env.reset()
|
|
51
|
-
self.sim_state = state
|
|
52
|
-
await asyncio.sleep(0)
|
|
53
|
-
return state
|
tinysim/frogger/__init__.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
+
|
|
2
3
|
from .. import SimEnvironment
|
|
4
|
+
from ..tinyspace import Discrete
|
|
3
5
|
|
|
4
6
|
WIDTH, HEIGHT = 800, 600
|
|
5
7
|
CELL = 40
|
|
@@ -14,6 +16,9 @@ class FroggerEnv(SimEnvironment):
|
|
|
14
16
|
self.car_width = CELL * 2
|
|
15
17
|
self.traffic_rows = np.array([4, 5, 6, 8, 9])
|
|
16
18
|
self.speeds = np.array([120, -150, 200, -180, 140], dtype=np.float32)
|
|
19
|
+
self.done = np.zeros(self.num_envs, dtype=bool)
|
|
20
|
+
|
|
21
|
+
self.action_space = Discrete(5) # 0: stay, 1: left, 2: right, 3: up, 4: down
|
|
17
22
|
self.reset()
|
|
18
23
|
|
|
19
24
|
def reset(self):
|
|
@@ -62,9 +67,17 @@ class FroggerEnv(SimEnvironment):
|
|
|
62
67
|
dx = np.array([action_map[a][0] for a in action])
|
|
63
68
|
dy = np.array([action_map[a][1] for a in action])
|
|
64
69
|
|
|
65
|
-
# Move frogs
|
|
66
|
-
self.frog_pos[:, 0] = np.
|
|
67
|
-
|
|
70
|
+
# Move frogs only move frog if not done
|
|
71
|
+
self.frog_pos[:, 0] = np.where(
|
|
72
|
+
~self.done,
|
|
73
|
+
np.clip(self.frog_pos[:, 0] + dx, 0, COLS - 1),
|
|
74
|
+
self.frog_pos[:, 0],
|
|
75
|
+
)
|
|
76
|
+
self.frog_pos[:, 1] = np.where(
|
|
77
|
+
~self.done,
|
|
78
|
+
np.clip(self.frog_pos[:, 1] + dy, 0, ROWS - 1),
|
|
79
|
+
self.frog_pos[:, 1],
|
|
80
|
+
)
|
|
68
81
|
|
|
69
82
|
# Update car positions
|
|
70
83
|
self.car_x += self.speeds[:, None] * dt
|
|
@@ -127,6 +140,10 @@ class FroggerEnv(SimEnvironment):
|
|
|
127
140
|
current_height = self.total_height - self.frog_pos[:, 1]
|
|
128
141
|
self.score = self.crossings + current_height / self.total_height
|
|
129
142
|
|
|
143
|
+
# Added to persist done state
|
|
144
|
+
self.done = done | self.done
|
|
145
|
+
done = self.done
|
|
146
|
+
|
|
130
147
|
frog_pos = self.frog_pos.tolist()
|
|
131
148
|
grid = self._build_car_grid().tolist()
|
|
132
149
|
scores = self.score.tolist()
|
|
@@ -140,6 +157,6 @@ class FroggerEnv(SimEnvironment):
|
|
|
140
157
|
return {
|
|
141
158
|
"frog_pos": frog_pos,
|
|
142
159
|
"grid": grid,
|
|
143
|
-
"done": done,
|
|
144
160
|
"score": scores,
|
|
161
|
+
"done": done,
|
|
145
162
|
}
|
tinysim/frogger/tk.py
CHANGED
|
@@ -1,41 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
from . import FroggerEnv, WIDTH, HEIGHT, CELL, ROWS, COLS
|
|
1
|
+
from . import CELL, COLS, HEIGHT, ROWS, WIDTH, FroggerEnv
|
|
3
2
|
|
|
4
3
|
try:
|
|
5
4
|
import tkinter as tk
|
|
6
|
-
|
|
5
|
+
|
|
6
|
+
from .._tk_base import TkBaseFrontend
|
|
7
7
|
except ImportError:
|
|
8
8
|
raise ImportError("tkinter is required for FroggerTkFrontend")
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class FroggerTkFrontend(
|
|
11
|
+
class FroggerTkFrontend(TkBaseFrontend):
|
|
12
|
+
|
|
13
|
+
def __init__(self, viewport_size=(800, 600), sim_env=FroggerEnv()):
|
|
14
|
+
super().__init__(sim_env)
|
|
15
|
+
self._viewport_size = viewport_size
|
|
16
|
+
self.keys = set()
|
|
12
17
|
|
|
13
|
-
def __init__(self, viewport_size=(800, 600), sim_env=None):
|
|
14
|
-
super().__init__()
|
|
15
|
-
if sim_env is None:
|
|
16
|
-
sim_env = FroggerEnv()
|
|
17
18
|
if sim_env.num_envs != 1:
|
|
18
19
|
raise ValueError(
|
|
19
20
|
"FroggerTkFrontend currently only supports single environment."
|
|
20
21
|
)
|
|
21
|
-
self.sim_env = sim_env
|
|
22
|
-
self._viewport_size = viewport_size
|
|
23
|
-
|
|
24
|
-
self.keys = set()
|
|
25
|
-
|
|
26
|
-
async def step(self, action, dt=0.01):
|
|
27
|
-
state = self.sim_env.step(action, dt=dt)
|
|
28
|
-
if self._root:
|
|
29
|
-
self._root.after(0, lambda: self._draw_state(self.sim_env))
|
|
30
|
-
|
|
31
|
-
await asyncio.sleep(dt)
|
|
32
|
-
return state
|
|
33
|
-
|
|
34
|
-
async def reset(self):
|
|
35
|
-
state = self.sim_env.reset()
|
|
36
|
-
if self._canvas:
|
|
37
|
-
self._draw_state(self.sim_env)
|
|
38
|
-
return state
|
|
39
22
|
|
|
40
23
|
def _create_window(self, root):
|
|
41
24
|
w, h = self._viewport_size
|
|
@@ -49,11 +32,12 @@ class FroggerTkFrontend(_tk_base.TkBaseFrontend):
|
|
|
49
32
|
root.bind("<KeyRelease>", lambda e: self.keys.discard(e.keysym))
|
|
50
33
|
|
|
51
34
|
self.bring_to_front(root)
|
|
52
|
-
self._draw_state(
|
|
35
|
+
self._draw_state()
|
|
53
36
|
self._pump()
|
|
54
37
|
root.mainloop()
|
|
55
38
|
|
|
56
|
-
def _draw_state(self,
|
|
39
|
+
def _draw_state(self, state=None):
|
|
40
|
+
sim_env = self.sim_env
|
|
57
41
|
if not self._canvas:
|
|
58
42
|
return
|
|
59
43
|
|
tinysim/frogger/widget.py
CHANGED
|
@@ -1,60 +1,31 @@
|
|
|
1
1
|
import pathlib
|
|
2
|
-
|
|
3
|
-
import traitlets
|
|
4
|
-
import asyncio
|
|
2
|
+
|
|
5
3
|
import numpy as np
|
|
6
|
-
|
|
7
|
-
from jupyter_ui_poll import ui_events
|
|
4
|
+
import traitlets
|
|
8
5
|
|
|
6
|
+
from .._widget_base import BaseWidget
|
|
9
7
|
from . import FroggerEnv
|
|
10
8
|
|
|
11
9
|
|
|
12
|
-
class FroggerWidget(
|
|
10
|
+
class FroggerWidget(BaseWidget):
|
|
13
11
|
_esm = pathlib.Path(__file__).parent / "sim.js"
|
|
14
12
|
|
|
15
13
|
sim_state = traitlets.Dict(default_value={}).tag(sync=True)
|
|
16
14
|
car_positions = traitlets.List(default_value=[]).tag(sync=True)
|
|
17
|
-
_viewport_size = traitlets.Tuple(
|
|
18
|
-
traitlets.Int(), traitlets.Int(), default_value=(800, 600)
|
|
19
|
-
).tag(sync=True)
|
|
20
|
-
_view_ready = traitlets.Bool(default_value=False).tag(sync=True)
|
|
15
|
+
_viewport_size = traitlets.Tuple(default_value=(800, 600)).tag(sync=True)
|
|
21
16
|
|
|
22
17
|
def get_car_positions(self):
|
|
23
18
|
return np.vstack(self.sim_env.car_rects).flatten().tolist()
|
|
24
19
|
|
|
25
|
-
def __init__(self, viewport_size=(800, 600), sim_env=
|
|
20
|
+
def __init__(self, viewport_size=(800, 600), sim_env=FroggerEnv()):
|
|
21
|
+
super().__init__(sim_env)
|
|
26
22
|
self._viewport_size = viewport_size
|
|
27
|
-
super().__init__()
|
|
28
|
-
if sim_env is None:
|
|
29
|
-
sim_env = FroggerEnv()
|
|
30
23
|
|
|
31
24
|
if sim_env.num_envs != 1:
|
|
32
25
|
raise ValueError(
|
|
33
26
|
"FroggerWidget currently only supports single environment."
|
|
34
27
|
)
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
self.sim_state = self.sim_env.reset()
|
|
38
|
-
self.car_positions = self.get_car_positions()
|
|
39
|
-
|
|
40
|
-
def render(self):
|
|
41
|
-
display(self)
|
|
42
|
-
|
|
43
|
-
try:
|
|
44
|
-
with ui_events() as ui_poll:
|
|
45
|
-
while not self._view_ready:
|
|
46
|
-
ui_poll(100)
|
|
47
|
-
except Exception:
|
|
48
|
-
pass
|
|
49
|
-
|
|
50
|
-
async def step(self, action: int, dt: float = 0.01) -> dict:
|
|
51
|
-
sim_state = self.sim_env.step(action)
|
|
29
|
+
def _update_props(self, sim_state):
|
|
52
30
|
self.sim_state = sim_state
|
|
53
31
|
self.car_positions = self.get_car_positions()
|
|
54
|
-
await asyncio.sleep(dt)
|
|
55
|
-
return sim_state
|
|
56
|
-
|
|
57
|
-
async def reset(self) -> dict:
|
|
58
|
-
sim_state = self.sim_env.reset()
|
|
59
|
-
self.sim_state = sim_state
|
|
60
|
-
return sim_state
|
tinysim/mountain_car/__init__.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
+
|
|
2
3
|
from .. import SimEnvironment
|
|
4
|
+
from ..tinyspace import Discrete
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
class MountainCarEnv(SimEnvironment):
|
|
@@ -12,12 +14,12 @@ class MountainCarEnv(SimEnvironment):
|
|
|
12
14
|
self.force = 0.001
|
|
13
15
|
self.gravity = 0.0025
|
|
14
16
|
self.goal_position = 0.5
|
|
17
|
+
self.reset()
|
|
15
18
|
|
|
16
|
-
#
|
|
17
|
-
self.
|
|
18
|
-
self.velocity = np.zeros(num_envs, dtype=np.float32)
|
|
19
|
+
# actions: 0 (left), 1 (no push), 2 (right)
|
|
20
|
+
self.action_space = Discrete(3)
|
|
19
21
|
|
|
20
|
-
def step(self, action)
|
|
22
|
+
def step(self, action):
|
|
21
23
|
if np.isscalar(action):
|
|
22
24
|
action = np.full(self.num_envs, action, dtype=np.float32)
|
|
23
25
|
else:
|
|
@@ -46,11 +48,14 @@ class MountainCarEnv(SimEnvironment):
|
|
|
46
48
|
|
|
47
49
|
return {"position": self.position, "velocity": self.velocity, "done": done}
|
|
48
50
|
|
|
49
|
-
def reset(self) -> dict:
|
|
50
|
-
self.position = -0.5
|
|
51
|
-
self.velocity =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
def reset(self, **kwargs) -> dict:
|
|
52
|
+
self.position = np.full(self.num_envs, -0.5, dtype=np.float32)
|
|
53
|
+
self.velocity = np.zeros(self.num_envs, dtype=np.float32)
|
|
54
|
+
done = self.position >= self.goal_position
|
|
55
|
+
|
|
56
|
+
if self.num_envs == 1:
|
|
57
|
+
self.position = float(self.position[0])
|
|
58
|
+
self.velocity = float(self.velocity[0])
|
|
59
|
+
done = bool(done[0])
|
|
60
|
+
|
|
61
|
+
return {"position": self.position, "velocity": self.velocity, "done": done}
|
tinysim/mountain_car/tk.py
CHANGED
|
@@ -1,39 +1,23 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import math
|
|
2
|
+
|
|
3
3
|
import numpy as np
|
|
4
|
+
|
|
4
5
|
from . import MountainCarEnv
|
|
5
6
|
|
|
6
7
|
try:
|
|
7
8
|
import tkinter as tk
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
from .._tk_base import TkBaseFrontend
|
|
9
11
|
except ImportError:
|
|
10
12
|
raise ImportError("tkinter is required for MountainCarTkFrontend")
|
|
11
13
|
|
|
12
14
|
|
|
13
|
-
class MountainCarTkFrontend(
|
|
15
|
+
class MountainCarTkFrontend(TkBaseFrontend):
|
|
14
16
|
|
|
15
|
-
def __init__(self, viewport_size=(600, 400), sim_env=
|
|
16
|
-
super().__init__()
|
|
17
|
-
if sim_env is None:
|
|
18
|
-
sim_env = MountainCarEnv()
|
|
19
|
-
self.sim_env = sim_env
|
|
17
|
+
def __init__(self, viewport_size=(600, 400), sim_env=MountainCarEnv()):
|
|
18
|
+
super().__init__(sim_env)
|
|
20
19
|
self._viewport_size = viewport_size
|
|
21
20
|
|
|
22
|
-
async def step(self, action, dt=0.01):
|
|
23
|
-
state = self.sim_env.step(action)
|
|
24
|
-
|
|
25
|
-
if self._root:
|
|
26
|
-
self._root.after(0, lambda s=state: self._draw_state(s))
|
|
27
|
-
|
|
28
|
-
await asyncio.sleep(dt)
|
|
29
|
-
return state
|
|
30
|
-
|
|
31
|
-
async def reset(self):
|
|
32
|
-
state = self.sim_env.reset()
|
|
33
|
-
if self._canvas:
|
|
34
|
-
self._draw_state(state)
|
|
35
|
-
return state
|
|
36
|
-
|
|
37
21
|
def _create_window(self, root):
|
|
38
22
|
w, h = self._viewport_size
|
|
39
23
|
root.title("Mountain Car")
|
|
@@ -46,7 +30,7 @@ class MountainCarTkFrontend(_tk_base.TkBaseFrontend):
|
|
|
46
30
|
self._pump()
|
|
47
31
|
root.mainloop()
|
|
48
32
|
|
|
49
|
-
def _draw_state(self, state
|
|
33
|
+
def _draw_state(self, state=None):
|
|
50
34
|
if not self._canvas:
|
|
51
35
|
return
|
|
52
36
|
|
|
@@ -54,12 +38,10 @@ class MountainCarTkFrontend(_tk_base.TkBaseFrontend):
|
|
|
54
38
|
w = int(c.winfo_width() or self._viewport_size[0])
|
|
55
39
|
h = int(c.winfo_height() or self._viewport_size[1])
|
|
56
40
|
c.delete("all")
|
|
57
|
-
|
|
58
41
|
min_x = self.sim_env.min_position
|
|
59
42
|
max_x = self.sim_env.max_position
|
|
60
43
|
world_width = max_x - min_x
|
|
61
44
|
scale = w / world_width
|
|
62
|
-
clearance = 10
|
|
63
45
|
|
|
64
46
|
def heightFn(x):
|
|
65
47
|
return np.sin(3 * x) * 0.45 + 0.55
|
|
@@ -105,7 +87,7 @@ class MountainCarTkFrontend(_tk_base.TkBaseFrontend):
|
|
|
105
87
|
for i, x_world in enumerate(positions):
|
|
106
88
|
y_world = heightFn(x_world)
|
|
107
89
|
x_screen = (x_world - min_x) * scale
|
|
108
|
-
y_screen = h - y_world * scale
|
|
90
|
+
y_screen = h - y_world * scale
|
|
109
91
|
|
|
110
92
|
slope = math.cos(3 * x_world)
|
|
111
93
|
angle = -math.atan(slope)
|
tinysim/mountain_car/widget.py
CHANGED
|
@@ -1,56 +1,27 @@
|
|
|
1
1
|
import pathlib
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import traitlets
|
|
4
|
-
import asyncio
|
|
5
|
-
from IPython.display import display
|
|
6
|
-
from jupyter_ui_poll import ui_events
|
|
7
4
|
|
|
5
|
+
from .._widget_base import BaseWidget
|
|
8
6
|
from . import MountainCarEnv
|
|
9
7
|
|
|
10
8
|
|
|
11
|
-
class MountainCarWidget(
|
|
9
|
+
class MountainCarWidget(BaseWidget):
|
|
12
10
|
_esm = pathlib.Path(__file__).parent / "sim.js"
|
|
13
11
|
_css = pathlib.Path(__file__).parent / "styles.css"
|
|
14
12
|
|
|
15
13
|
sim_state = traitlets.Dict(default_value={}).tag(sync=True)
|
|
16
|
-
_viewport_size = traitlets.Tuple(
|
|
17
|
-
traitlets.Int(), traitlets.Int(), default_value=(600, 400)
|
|
18
|
-
).tag(sync=True)
|
|
19
|
-
_view_ready = traitlets.Bool(default_value=False).tag(sync=True)
|
|
14
|
+
_viewport_size = traitlets.Tuple(default_value=(600, 400)).tag(sync=True)
|
|
20
15
|
_manual_control = traitlets.Bool(default_value=False).tag(sync=True)
|
|
21
16
|
|
|
22
|
-
def __init__(
|
|
17
|
+
def __init__(
|
|
18
|
+
self, manual_control=False, viewport_size=(600, 400), sim_env=MountainCarEnv()
|
|
19
|
+
):
|
|
20
|
+
super().__init__(sim_env)
|
|
23
21
|
self._manual_control = manual_control
|
|
24
22
|
self._viewport_size = viewport_size
|
|
25
|
-
super().__init__()
|
|
26
|
-
if sim_env is None:
|
|
27
|
-
sim_env = MountainCarEnv()
|
|
28
23
|
|
|
29
24
|
if sim_env.num_envs != 1:
|
|
30
25
|
raise ValueError(
|
|
31
26
|
"MountainCarWidget currently only supports single environment."
|
|
32
27
|
)
|
|
33
|
-
|
|
34
|
-
self.sim_env = sim_env
|
|
35
|
-
self.sim_state = self.sim_env.reset()
|
|
36
|
-
|
|
37
|
-
def render(self):
|
|
38
|
-
display(self)
|
|
39
|
-
|
|
40
|
-
try:
|
|
41
|
-
with ui_events() as ui_poll:
|
|
42
|
-
while not self._view_ready:
|
|
43
|
-
ui_poll(100)
|
|
44
|
-
except Exception:
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
async def step(self, action: int, dt: float = 0.01) -> dict:
|
|
48
|
-
sim_state = self.sim_env.step(action)
|
|
49
|
-
self.sim_state = sim_state
|
|
50
|
-
await asyncio.sleep(dt)
|
|
51
|
-
return sim_state
|
|
52
|
-
|
|
53
|
-
async def reset(self) -> dict:
|
|
54
|
-
sim_state = self.sim_env.reset()
|
|
55
|
-
self.sim_state = sim_state
|
|
56
|
-
return sim_state
|