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.
Files changed (40) hide show
  1. tinysim/__init__.py +7 -2
  2. tinysim/_tk_base.py +20 -2
  3. tinysim/_widget_base.py +41 -0
  4. tinysim/flappy/__init__.py +5 -3
  5. tinysim/flappy/tk.py +10 -34
  6. tinysim/flappy/widget.py +9 -38
  7. tinysim/frogger/__init__.py +21 -4
  8. tinysim/frogger/tk.py +12 -28
  9. tinysim/frogger/widget.py +8 -37
  10. tinysim/mountain_car/__init__.py +17 -12
  11. tinysim/mountain_car/tk.py +9 -27
  12. tinysim/mountain_car/widget.py +8 -37
  13. tinysim/tinyspace.py +68 -0
  14. tinysim/topdown_driving/__init__.py +16 -18
  15. tinysim/topdown_driving/tk.py +13 -38
  16. tinysim/topdown_driving/track_0.json +1 -753
  17. tinysim/topdown_driving/widget.py +8 -42
  18. {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/METADATA +5 -6
  19. {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/RECORD +35 -35
  20. {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/WHEEL +1 -1
  21. tinysim_mujoco/gl_viewer.py +36 -11
  22. tinysim_mujoco/manipulation/__init__.py +19 -5
  23. tinysim_mujoco/manipulation/push_env.py +268 -0
  24. tinysim_mujoco/manipulation/push_env_cam.py +274 -0
  25. tinysim_mujoco/manipulation/xmls/panda.xml +59 -16
  26. tinysim_mujoco/manipulation/xmls/scene.xml +0 -3
  27. tinysim_mujoco/manipulation/xmls/table.xml +17 -13
  28. tinysim_mujoco/notebook_viewer.py +3 -6
  29. tinysim_mujoco/unitree_a1/__init__.py +7 -10
  30. tinysim_warp/__init__.py +108 -0
  31. tinysim_warp/cart_pole/__init__.py +44 -200
  32. tinysim_warp/quadruped/__init__.py +23 -160
  33. tinysim_warp/simple_quadruped/__init__.py +20 -91
  34. tinysim_warp/simple_quadruped/simple_quadruped.urdf +0 -9
  35. tinysim/simple_amr/__init__.py +0 -0
  36. tinysim/simple_amr/example_maps.py +0 -121
  37. tinysim/simple_amr/sim.js +0 -430
  38. tinysim/simple_amr/styles.css +0 -54
  39. tinysim/simple_amr/widget.py +0 -73
  40. {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/top_level.txt +0 -0
tinysim/tinyspace.py ADDED
@@ -0,0 +1,68 @@
1
+ from typing import Any
2
+
3
+ import numpy as np
4
+
5
+ # It is encouraged to implement your own Space classes or use existing ones from external libraries.
6
+
7
+
8
+ class Space:
9
+ """A minimal implementation of the Space class for TinySim."""
10
+
11
+ def sample(self) -> Any:
12
+ """Randomly sample an element from this space."""
13
+ raise NotImplementedError
14
+
15
+ def contains(self, x: Any) -> bool:
16
+ """Return boolean specifying if x is a valid member of this space."""
17
+ raise NotImplementedError
18
+
19
+ def __contains__(self, x: Any) -> bool:
20
+ return self.contains(x)
21
+
22
+
23
+ class Discrete(Space):
24
+ """A discrete space in TinySim."""
25
+
26
+ def __init__(self, n: int):
27
+ assert n >= 0, "n (number of elements) must be non-negative"
28
+ self.n = n
29
+
30
+ def sample(self) -> int:
31
+ return np.random.randint(0, self.n)
32
+
33
+ def contains(self, x: Any) -> bool:
34
+ return isinstance(x, int) and 0 <= x < self.n
35
+
36
+
37
+ class Box(Space):
38
+ """A box space in TinySim."""
39
+
40
+ def __init__(self, low: float, high: float, shape: tuple, dtype=np.float32):
41
+ self.low = np.full(shape, low, dtype=dtype)
42
+ self.high = np.full(shape, high, dtype=dtype)
43
+ self.shape = shape
44
+ self.dtype = dtype
45
+
46
+ def sample(self) -> Any:
47
+ return np.random.uniform(self.low, self.high, self.shape)
48
+
49
+ def contains(self, x: Any) -> bool:
50
+ x = np.array(x)
51
+ return (
52
+ x.shape == self.shape and np.all(x >= self.low) and np.all(x <= self.high)
53
+ )
54
+
55
+
56
+ class Dict(Space):
57
+ """A dictionary space in TinySim."""
58
+
59
+ def __init__(self, spaces: dict):
60
+ self.spaces = spaces
61
+
62
+ def sample(self) -> dict:
63
+ return {key: space.sample() for key, space in self.spaces.items()}
64
+
65
+ def contains(self, x: Any) -> bool:
66
+ if isinstance(x, dict) and x.keys() == self.spaces.keys():
67
+ return all(x[key] in self.spaces[key] for key in self.spaces.keys())
68
+ return False
@@ -1,9 +1,11 @@
1
1
  import json
2
2
  import math
3
- import numpy as np
4
3
  from pathlib import Path
5
- from .. import SimEnvironment
6
4
 
5
+ import numpy as np
6
+
7
+ from .. import SimEnvironment
8
+ from ..tinyspace import Box
7
9
 
8
10
  try:
9
11
  with open(Path(__file__).parent / "track_0.json", "r") as f:
@@ -104,6 +106,9 @@ def collides(cx, cy):
104
106
  class TopDownDrivingEnv(SimEnvironment):
105
107
  def __init__(self, num_envs: int = 1):
106
108
  self.num_envs = num_envs
109
+
110
+ # throttle, steer
111
+ self.action_space = Box(low=-1.0, high=1.0, shape=(num_envs, 2))
107
112
  self.reset()
108
113
 
109
114
  def reset(self):
@@ -125,24 +130,18 @@ class TopDownDrivingEnv(SimEnvironment):
125
130
  }
126
131
 
127
132
  def step(self, action, dt=0.02):
128
- throttle = action.get("throttle", 0.0)
129
- steer = action.get("steer", 0.0)
130
-
131
- if np.isscalar(throttle) and np.isscalar(steer):
132
- throttle = np.full(self.num_envs, throttle, dtype=np.float32)
133
- steer = np.full(self.num_envs, steer, dtype=np.float32)
134
- elif isinstance(throttle, np.ndarray) and isinstance(steer, np.ndarray):
135
- throttle = np.asarray(throttle, dtype=np.float32)
136
- steer = np.asarray(steer, dtype=np.float32)
137
- if throttle.shape[0] != self.num_envs or steer.shape[0] != self.num_envs:
138
- raise ValueError(
139
- f"Expected actions of shape ({self.num_envs},), got {throttle.shape} and {steer.shape}"
140
- )
141
- else:
133
+ if not isinstance(action, np.ndarray):
142
134
  raise ValueError(
143
135
  "Inputs throttle and steer must both be either scalars or numpy arrays."
144
136
  )
145
137
 
138
+ throttle = action[:, 0].astype(np.float32)
139
+ steer = action[:, 1].astype(np.float32)
140
+ if throttle.shape[0] != self.num_envs or steer.shape[0] != self.num_envs:
141
+ raise ValueError(
142
+ f"Expected actions of shape ({self.num_envs},), got {throttle.shape} and {steer.shape}"
143
+ )
144
+
146
145
  self.velocity += throttle * ACCELERATION * dt
147
146
  self.velocity = np.clip(self.velocity, 0.0, MAX_VEL)
148
147
  self.angle -= steer * TURN_SPEED * dt
@@ -171,8 +170,7 @@ class TopDownDrivingEnv(SimEnvironment):
171
170
  reward = self.prev_dist - dist
172
171
  reached = dist <= CHECKPOINT_RADIUS
173
172
 
174
- bonus = 1.0
175
- reward += np.where(reached, bonus, 0.0)
173
+ reward += np.where(reached, 1.0, 0.0)
176
174
  self.checkpoint_idx = np.where(
177
175
  reached, self.checkpoint_idx + 1, self.checkpoint_idx
178
176
  )
@@ -1,25 +1,26 @@
1
- import asyncio
2
1
  import math
2
+
3
3
  from . import (
4
- TopDownDrivingEnv,
5
4
  CAR_LENGTH,
6
5
  CAR_WIDTH,
7
- LOCAL_WALLS,
8
6
  CHECKPOINTS,
7
+ LOCAL_WALLS,
9
8
  RAY_COUNT,
10
9
  RAY_SPREAD,
10
+ TopDownDrivingEnv,
11
11
  )
12
12
 
13
13
  try:
14
14
  import tkinter as tk
15
- from .. import _tk_base
15
+
16
+ from .._tk_base import TkBaseFrontend
16
17
  except ImportError:
17
18
  raise ImportError("tkinter is required for MountainCarTkFrontend")
18
19
 
19
20
 
20
21
  CHECKPOINT_RADIUS = 0.85
21
22
  COLOR_MAP = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]
22
-
23
+ CANVAS_W, CANVAS_H = 800, 600
23
24
  xs, ys = [], []
24
25
 
25
26
  for x, y, w, h, rot in LOCAL_WALLS:
@@ -30,8 +31,6 @@ for x, y, w, h, rot in LOCAL_WALLS:
30
31
 
31
32
  min_x, max_x = min(xs), max(xs)
32
33
  min_y, max_y = min(ys), max(ys)
33
-
34
- CANVAS_W, CANVAS_H = 800, 600
35
34
  scale = min((CANVAS_W - 2) / (max_x - min_x), (CANVAS_H - 2) / (max_y - min_y))
36
35
  offset_x = -min_x * scale
37
36
  offset_y = max_y * scale
@@ -53,33 +52,14 @@ def world_to_screen(x, y):
53
52
  return x * scale + offset_x, -y * scale + offset_y
54
53
 
55
54
 
56
- class TopDownDrivingTkFrontend(_tk_base.TkBaseFrontend):
55
+ class TopDownDrivingTkFrontend(TkBaseFrontend):
57
56
 
58
- def __init__(self, viewport_size=(800, 600), sim_env=None):
59
- super().__init__()
60
- if sim_env is None:
61
- sim_env = TopDownDrivingEnv()
62
- self.sim_env = sim_env
57
+ def __init__(self, viewport_size=(800, 600), sim_env=TopDownDrivingEnv()):
58
+ super().__init__(sim_env)
63
59
  self._viewport_size = viewport_size
64
60
  self.show_rays = False
65
-
66
61
  self.keys = set()
67
62
 
68
- async def step(self, action, dt=0.02):
69
- state = self.sim_env.step(action)
70
-
71
- if self._root:
72
- self._root.after(0, lambda s=state: self._draw_state(self.sim_env))
73
-
74
- await asyncio.sleep(dt)
75
- return state
76
-
77
- async def reset(self):
78
- state = self.sim_env.reset()
79
- if self._canvas:
80
- self._draw_state(self.sim_env)
81
- return state
82
-
83
63
  def _create_window(self, root):
84
64
  w, h = self._viewport_size
85
65
  root.title("Top Down Driving")
@@ -94,7 +74,6 @@ class TopDownDrivingTkFrontend(_tk_base.TkBaseFrontend):
94
74
  r = CHECKPOINT_RADIUS * scale
95
75
  for i, (x, y) in enumerate(CHECKPOINTS):
96
76
  sx, sy = world_to_screen(x, y)
97
-
98
77
  canvas.create_oval(
99
78
  sx - r,
100
79
  sy - r,
@@ -115,26 +94,24 @@ class TopDownDrivingTkFrontend(_tk_base.TkBaseFrontend):
115
94
  self.bring_to_front(root)
116
95
  self._root = root
117
96
  self._canvas = canvas
118
- self._draw_state(self.sim_env)
97
+ self._draw_state()
119
98
  self._pump()
120
99
  root.mainloop()
121
100
 
122
- def _draw_state(self, sim_env):
101
+ def _draw_state(self, state=None):
102
+ sim_env = self.sim_env
123
103
  if not self._canvas:
124
104
  return
125
105
 
126
106
  c = self._canvas
127
107
  c.delete("car")
128
108
  c.delete("ray")
129
-
130
- xs = sim_env.x
131
- ys = sim_env.y
109
+ xs, ys = sim_env.x, sim_env.y
132
110
  angles = sim_env.angle
133
111
  n = len(xs)
134
112
 
135
113
  for i in range(n):
136
114
  cx, cy = world_to_screen(xs[i], ys[i])
137
-
138
115
  pts = rotated_rect(
139
116
  cx,
140
117
  cy,
@@ -160,7 +137,6 @@ class TopDownDrivingTkFrontend(_tk_base.TkBaseFrontend):
160
137
  for i in range(n):
161
138
  ox, oy = xs[i], ys[i]
162
139
  base = angles[i]
163
-
164
140
  sx1, sy1 = world_to_screen(ox, oy)
165
141
 
166
142
  for r_idx, dist in enumerate(sim_env.rays[i]):
@@ -168,7 +144,6 @@ class TopDownDrivingTkFrontend(_tk_base.TkBaseFrontend):
168
144
  x2 = ox + math.cos(a) * dist
169
145
  y2 = oy + math.sin(a) * dist
170
146
  sx2, sy2 = world_to_screen(x2, y2)
171
-
172
147
  c.create_line(
173
148
  sx1,
174
149
  sy1,