tinysim 0.0.4__tar.gz → 0.0.5__tar.gz

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 (138) hide show
  1. {tinysim-0.0.4 → tinysim-0.0.5}/PKG-INFO +5 -6
  2. {tinysim-0.0.4 → tinysim-0.0.5}/README.md +4 -5
  3. {tinysim-0.0.4 → tinysim-0.0.5}/pyproject.toml +1 -1
  4. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/__init__.py +7 -2
  5. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/_tk_base.py +20 -2
  6. tinysim-0.0.5/tinysim/_widget_base.py +41 -0
  7. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/flappy/__init__.py +5 -3
  8. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/flappy/tk.py +10 -34
  9. tinysim-0.0.5/tinysim/flappy/widget.py +24 -0
  10. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/frogger/__init__.py +21 -4
  11. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/frogger/tk.py +12 -28
  12. tinysim-0.0.5/tinysim/frogger/widget.py +31 -0
  13. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/mountain_car/__init__.py +17 -12
  14. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/mountain_car/tk.py +9 -27
  15. tinysim-0.0.5/tinysim/mountain_car/widget.py +27 -0
  16. tinysim-0.0.5/tinysim/tinyspace.py +68 -0
  17. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/topdown_driving/__init__.py +16 -18
  18. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/topdown_driving/tk.py +13 -38
  19. tinysim-0.0.5/tinysim/topdown_driving/track_0.json +1 -0
  20. tinysim-0.0.5/tinysim/topdown_driving/widget.py +25 -0
  21. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim.egg-info/PKG-INFO +5 -6
  22. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim.egg-info/SOURCES.txt +5 -5
  23. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/gl_viewer.py +36 -11
  24. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/__init__.py +19 -5
  25. tinysim-0.0.5/tinysim_mujoco/manipulation/push_env.py +268 -0
  26. tinysim-0.0.5/tinysim_mujoco/manipulation/push_env_cam.py +274 -0
  27. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/panda.xml +59 -16
  28. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/scene.xml +0 -3
  29. tinysim-0.0.5/tinysim_mujoco/manipulation/xmls/table.xml +41 -0
  30. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/notebook_viewer.py +3 -6
  31. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/__init__.py +7 -10
  32. tinysim-0.0.5/tinysim_warp/__init__.py +108 -0
  33. tinysim-0.0.5/tinysim_warp/cart_pole/__init__.py +103 -0
  34. tinysim-0.0.5/tinysim_warp/quadruped/__init__.py +66 -0
  35. tinysim-0.0.5/tinysim_warp/simple_quadruped/__init__.py +97 -0
  36. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_warp/simple_quadruped/simple_quadruped.urdf +0 -9
  37. tinysim-0.0.4/tinysim/flappy/widget.py +0 -53
  38. tinysim-0.0.4/tinysim/frogger/widget.py +0 -60
  39. tinysim-0.0.4/tinysim/mountain_car/widget.py +0 -56
  40. tinysim-0.0.4/tinysim/simple_amr/example_maps.py +0 -121
  41. tinysim-0.0.4/tinysim/simple_amr/sim.js +0 -430
  42. tinysim-0.0.4/tinysim/simple_amr/styles.css +0 -54
  43. tinysim-0.0.4/tinysim/simple_amr/widget.py +0 -73
  44. tinysim-0.0.4/tinysim/topdown_driving/track_0.json +0 -753
  45. tinysim-0.0.4/tinysim/topdown_driving/widget.py +0 -59
  46. tinysim-0.0.4/tinysim_mujoco/__init__.py +0 -0
  47. tinysim-0.0.4/tinysim_mujoco/manipulation/xmls/table.xml +0 -37
  48. tinysim-0.0.4/tinysim_warp/cart_pole/__init__.py +0 -259
  49. tinysim-0.0.4/tinysim_warp/quadruped/__init__.py +0 -203
  50. tinysim-0.0.4/tinysim_warp/simple_quadruped/__init__.py +0 -168
  51. {tinysim-0.0.4 → tinysim-0.0.5}/setup.cfg +0 -0
  52. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/flappy/sim.js +0 -0
  53. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/frogger/sim.js +0 -0
  54. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/mountain_car/sim.js +0 -0
  55. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/mountain_car/styles.css +0 -0
  56. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim/topdown_driving/sim.js +0 -0
  57. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim.egg-info/dependency_links.txt +0 -0
  58. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim.egg-info/requires.txt +0 -0
  59. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim.egg-info/top_level.txt +0 -0
  60. {tinysim-0.0.4/tinysim/simple_amr → tinysim-0.0.5/tinysim_mujoco}/__init__.py +0 -0
  61. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/d405.stl +0 -0
  62. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/finger_0.obj +0 -0
  63. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/finger_1.obj +0 -0
  64. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/hand.stl +0 -0
  65. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/hand_0.obj +0 -0
  66. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/hand_1.obj +0 -0
  67. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/hand_2.obj +0 -0
  68. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/hand_3.obj +0 -0
  69. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/hand_4.obj +0 -0
  70. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0.stl +0 -0
  71. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_0.obj +0 -0
  72. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_1.obj +0 -0
  73. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_10.obj +0 -0
  74. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_11.obj +0 -0
  75. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_2.obj +0 -0
  76. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_3.obj +0 -0
  77. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_4.obj +0 -0
  78. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_5.obj +0 -0
  79. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_7.obj +0 -0
  80. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_8.obj +0 -0
  81. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link0_9.obj +0 -0
  82. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link1.obj +0 -0
  83. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link1.stl +0 -0
  84. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link2.obj +0 -0
  85. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link2.stl +0 -0
  86. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link3.stl +0 -0
  87. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link3_0.obj +0 -0
  88. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link3_1.obj +0 -0
  89. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link3_2.obj +0 -0
  90. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link3_3.obj +0 -0
  91. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link4.stl +0 -0
  92. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link4_0.obj +0 -0
  93. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link4_1.obj +0 -0
  94. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link4_2.obj +0 -0
  95. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link4_3.obj +0 -0
  96. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link5_0.obj +0 -0
  97. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link5_1.obj +0 -0
  98. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link5_2.obj +0 -0
  99. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link5_collision_0.obj +0 -0
  100. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link5_collision_1.obj +0 -0
  101. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link5_collision_2.obj +0 -0
  102. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6.stl +0 -0
  103. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_0.obj +0 -0
  104. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_1.obj +0 -0
  105. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_10.obj +0 -0
  106. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_11.obj +0 -0
  107. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_12.obj +0 -0
  108. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_13.obj +0 -0
  109. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_14.obj +0 -0
  110. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_15.obj +0 -0
  111. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_16.obj +0 -0
  112. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_2.obj +0 -0
  113. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_3.obj +0 -0
  114. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_4.obj +0 -0
  115. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_5.obj +0 -0
  116. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_6.obj +0 -0
  117. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_7.obj +0 -0
  118. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_8.obj +0 -0
  119. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link6_9.obj +0 -0
  120. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link7.stl +0 -0
  121. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link7_0.obj +0 -0
  122. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link7_1.obj +0 -0
  123. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link7_2.obj +0 -0
  124. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link7_3.obj +0 -0
  125. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link7_4.obj +0 -0
  126. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link7_5.obj +0 -0
  127. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link7_6.obj +0 -0
  128. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/manipulation/xmls/assets/link7_7.obj +0 -0
  129. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/unitree_a1/CHANGELOG.md +0 -0
  130. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/unitree_a1/LICENSE +0 -0
  131. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/unitree_a1/README.md +0 -0
  132. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/unitree_a1/a1.xml +0 -0
  133. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/unitree_a1/assets/calf.obj +0 -0
  134. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/unitree_a1/assets/hip.obj +0 -0
  135. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/unitree_a1/assets/thigh.obj +0 -0
  136. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/unitree_a1/assets/thigh_mirror.obj +0 -0
  137. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/unitree_a1/assets/trunk.obj +0 -0
  138. {tinysim-0.0.4 → tinysim-0.0.5}/tinysim_mujoco/unitree_a1/unitree_a1/scene.xml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tinysim
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: small modular simulation environments
5
5
  Author-email: Matthew Taylor <matthew.taylor.andre@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/MatthewAndreTaylor/TinySim
@@ -30,7 +30,7 @@ Requires-Dist: mujoco; extra == "mujoco"
30
30
  # TinySim
31
31
 
32
32
  [![PyPI](https://img.shields.io/pypi/v/tinysim.svg)](https://pypi.org/project/tinysim)
33
- [![Jupyterlite](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://matthewandretaylor.github.io/TinySim/lab?path=example.ipynb)
33
+ [![Jupyterlite](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://matthewandretaylor.github.io/TinySim)
34
34
 
35
35
  The goal of this project is to create more minimal simulation environments for robotics and machine learning.
36
36
 
@@ -73,8 +73,7 @@ To use the [mujoco](https://github.com/google-deepmind/mujoco) simulation enviro
73
73
  ```bash
74
74
  pip install tinysim[mujoco]
75
75
  ```
76
- | [UnitreeA1WalkEnv](https://github.com/MatthewAndreTaylor/TinySim/tree/main/tinysim_mujoco/unitree_a1) |
77
- |:-------------------------:|
78
- | <img width="312" alt="mujoco_sim" src="https://github.com/user-attachments/assets/1109488e-0563-4694-8926-682edd0c8278" /> |
79
-
76
+ | [UnitreeA1WalkEnv](https://github.com/MatthewAndreTaylor/TinySim/tree/main/tinysim_mujoco/unitree_a1) | [ManipulationEnvV0](https://github.com/MatthewAndreTaylor/TinySim/tree/main/tinysim_mujoco/manipulation) |
77
+ |:-------------------------:|:-------------------------:|
78
+ | <img width="312" alt="mujoco_sim" src="https://github.com/user-attachments/assets/1109488e-0563-4694-8926-682edd0c8278" /> | <img width="312" alt="mujoco_sim" src="https://github.com/user-attachments/assets/07b406b5-15fc-4cfd-83c4-cf6b855d773a" /> |
80
79
 
@@ -2,7 +2,7 @@
2
2
  # TinySim
3
3
 
4
4
  [![PyPI](https://img.shields.io/pypi/v/tinysim.svg)](https://pypi.org/project/tinysim)
5
- [![Jupyterlite](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://matthewandretaylor.github.io/TinySim/lab?path=example.ipynb)
5
+ [![Jupyterlite](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://matthewandretaylor.github.io/TinySim)
6
6
 
7
7
  The goal of this project is to create more minimal simulation environments for robotics and machine learning.
8
8
 
@@ -45,8 +45,7 @@ To use the [mujoco](https://github.com/google-deepmind/mujoco) simulation enviro
45
45
  ```bash
46
46
  pip install tinysim[mujoco]
47
47
  ```
48
- | [UnitreeA1WalkEnv](https://github.com/MatthewAndreTaylor/TinySim/tree/main/tinysim_mujoco/unitree_a1) |
49
- |:-------------------------:|
50
- | <img width="312" alt="mujoco_sim" src="https://github.com/user-attachments/assets/1109488e-0563-4694-8926-682edd0c8278" /> |
51
-
48
+ | [UnitreeA1WalkEnv](https://github.com/MatthewAndreTaylor/TinySim/tree/main/tinysim_mujoco/unitree_a1) | [ManipulationEnvV0](https://github.com/MatthewAndreTaylor/TinySim/tree/main/tinysim_mujoco/manipulation) |
49
+ |:-------------------------:|:-------------------------:|
50
+ | <img width="312" alt="mujoco_sim" src="https://github.com/user-attachments/assets/1109488e-0563-4694-8926-682edd0c8278" /> | <img width="312" alt="mujoco_sim" src="https://github.com/user-attachments/assets/07b406b5-15fc-4cfd-83c4-cf6b855d773a" /> |
52
51
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tinysim"
3
- version = "0.0.4"
3
+ version = "0.0.5"
4
4
  description = "small modular simulation environments"
5
5
  authors = [
6
6
  {name = "Matthew Taylor", email = "matthew.taylor.andre@gmail.com"},
@@ -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, action) -> dict:
11
+ def step(self, *args, **kwargs):
7
12
  pass
8
13
 
9
14
  @abstractmethod
10
- def reset(self) -> dict:
15
+ def reset(self, *args, **kwargs):
11
16
  pass
@@ -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)
@@ -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
@@ -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): # world bounds
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 = (bx < px + PIPE_WIDTH) & (bx + BIRD_SIZE > px)
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)
@@ -1,45 +1,22 @@
1
- import asyncio
2
-
3
1
  try:
4
2
  import tkinter as tk
5
- from .. import _tk_base
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
- self.sim_env = sim_env
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
- async def step(self, action, dt=0.02):
31
- state = self.sim_env.step(action, dt=dt)
32
- if self._root:
33
- self._root.after(0, lambda: self._draw_state(state))
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,
@@ -0,0 +1,24 @@
1
+ import pathlib
2
+
3
+ import traitlets
4
+
5
+ from .._widget_base import BaseWidget
6
+ from . import FlappyEnv
7
+
8
+
9
+ class FlappySim(BaseWidget):
10
+ _esm = pathlib.Path(__file__).parent / "sim.js"
11
+
12
+ sim_state = traitlets.Dict(default_value={}).tag(sync=True)
13
+ _viewport_size = traitlets.Tuple(default_value=(800, 600)).tag(sync=True)
14
+ _manual_control = traitlets.Bool(default_value=False).tag(sync=True)
15
+
16
+ def __init__(
17
+ self, viewport_size=(800, 600), manual_control=False, sim_env=FlappyEnv()
18
+ ):
19
+ super().__init__(sim_env)
20
+ self._viewport_size = viewport_size
21
+ self._manual_control = manual_control
22
+
23
+ if sim_env.num_envs != 1:
24
+ raise ValueError("FlappySim currently only supports single environment.")
@@ -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.clip(self.frog_pos[:, 0] + dx, 0, COLS - 1)
67
- self.frog_pos[:, 1] = np.clip(self.frog_pos[:, 1] + dy, 0, ROWS - 1)
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
  }
@@ -1,41 +1,24 @@
1
- import asyncio
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
- from .. import _tk_base
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(_tk_base.TkBaseFrontend):
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(self.sim_env)
35
+ self._draw_state()
53
36
  self._pump()
54
37
  root.mainloop()
55
38
 
56
- def _draw_state(self, sim_env: FroggerEnv):
39
+ def _draw_state(self, state=None):
40
+ sim_env = self.sim_env
57
41
  if not self._canvas:
58
42
  return
59
43
 
@@ -0,0 +1,31 @@
1
+ import pathlib
2
+
3
+ import numpy as np
4
+ import traitlets
5
+
6
+ from .._widget_base import BaseWidget
7
+ from . import FroggerEnv
8
+
9
+
10
+ class FroggerWidget(BaseWidget):
11
+ _esm = pathlib.Path(__file__).parent / "sim.js"
12
+
13
+ sim_state = traitlets.Dict(default_value={}).tag(sync=True)
14
+ car_positions = traitlets.List(default_value=[]).tag(sync=True)
15
+ _viewport_size = traitlets.Tuple(default_value=(800, 600)).tag(sync=True)
16
+
17
+ def get_car_positions(self):
18
+ return np.vstack(self.sim_env.car_rects).flatten().tolist()
19
+
20
+ def __init__(self, viewport_size=(800, 600), sim_env=FroggerEnv()):
21
+ super().__init__(sim_env)
22
+ self._viewport_size = viewport_size
23
+
24
+ if sim_env.num_envs != 1:
25
+ raise ValueError(
26
+ "FroggerWidget currently only supports single environment."
27
+ )
28
+
29
+ def _update_props(self, sim_state):
30
+ self.sim_state = sim_state
31
+ self.car_positions = self.get_car_positions()
@@ -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
- # initial state
17
- self.position = np.full(num_envs, -0.5, dtype=np.float32)
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) -> dict:
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 = 0.0
52
- return {
53
- "position": self.position,
54
- "velocity": self.velocity,
55
- "done": self.position >= self.goal_position,
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}
@@ -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
- from .. import _tk_base
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(_tk_base.TkBaseFrontend):
15
+ class MountainCarTkFrontend(TkBaseFrontend):
14
16
 
15
- def __init__(self, viewport_size=(600, 400), sim_env=None):
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: dict):
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 - clearance
90
+ y_screen = h - y_world * scale
109
91
 
110
92
  slope = math.cos(3 * x_world)
111
93
  angle = -math.atan(slope)
@@ -0,0 +1,27 @@
1
+ import pathlib
2
+
3
+ import traitlets
4
+
5
+ from .._widget_base import BaseWidget
6
+ from . import MountainCarEnv
7
+
8
+
9
+ class MountainCarWidget(BaseWidget):
10
+ _esm = pathlib.Path(__file__).parent / "sim.js"
11
+ _css = pathlib.Path(__file__).parent / "styles.css"
12
+
13
+ sim_state = traitlets.Dict(default_value={}).tag(sync=True)
14
+ _viewport_size = traitlets.Tuple(default_value=(600, 400)).tag(sync=True)
15
+ _manual_control = traitlets.Bool(default_value=False).tag(sync=True)
16
+
17
+ def __init__(
18
+ self, manual_control=False, viewport_size=(600, 400), sim_env=MountainCarEnv()
19
+ ):
20
+ super().__init__(sim_env)
21
+ self._manual_control = manual_control
22
+ self._viewport_size = viewport_size
23
+
24
+ if sim_env.num_envs != 1:
25
+ raise ValueError(
26
+ "MountainCarWidget currently only supports single environment."
27
+ )
@@ -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