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
@@ -0,0 +1,108 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ import numpy as np
4
+
5
+ try:
6
+ import warp as wp
7
+ import warp.sim.render
8
+ except ImportError:
9
+ raise ImportError(
10
+ "Warp is not installed. Install using `pip install tinysim[warp]`"
11
+ )
12
+
13
+
14
+ class WarpBaseEnv(ABC):
15
+ def __init__(self, use_cuda_graph=False, headless=False, num_envs=1, fps=60):
16
+ self.try_use_cuda_graph = use_cuda_graph
17
+ self.headless = headless
18
+ self.num_envs = num_envs
19
+
20
+ self.fps = fps
21
+ self.sim_time = 0.0
22
+ self.frame_dt = 1.0 / fps
23
+ self.sim_substeps = 10 # todo: make configurable
24
+ self.sim_dt = self.frame_dt / self.sim_substeps
25
+ self.num_envs = num_envs
26
+ self.env_offsets = self.comp_env_offsets()
27
+ self.model = self.build_model()
28
+ self.integrator = self.solver()
29
+
30
+ self.renderer = wp.sim.render.SimRendererOpenGL(
31
+ self.model, "viewer", headless=headless
32
+ )
33
+ self.state_0 = self.model.state()
34
+ self.state_1 = self.model.state()
35
+ wp.sim.eval_fk(
36
+ self.model, self.state_0.joint_q, self.state_0.joint_qd, None, self.state_0
37
+ )
38
+ self.capture_graph()
39
+
40
+ @abstractmethod
41
+ def build_model(self):
42
+ raise NotImplementedError("build_model() must be implemented in subclass.")
43
+
44
+ @abstractmethod
45
+ def solver(self):
46
+ raise NotImplementedError("solver() must be implemented in subclass.")
47
+
48
+ @abstractmethod
49
+ def apply_actions(self, actions):
50
+ raise NotImplementedError("apply_actions() must be implemented in subclass.")
51
+
52
+ @abstractmethod
53
+ def get_obs(self):
54
+ raise NotImplementedError("get_obs() must be implemented in subclass.")
55
+
56
+ def comp_env_offsets(self, offset=(5.0, 0.0, 0.0)):
57
+ offset = np.array(offset, dtype=float)
58
+ axis = np.nonzero(offset)[0]
59
+ axis = axis[0] if len(axis) else 0
60
+ t = np.arange(self.num_envs) * offset[axis]
61
+ offsets = np.zeros((self.num_envs, 3))
62
+ offsets[:, axis] = t - t.mean()
63
+ return offsets
64
+
65
+ def capture_graph(self):
66
+ # CUDA graph
67
+ self.use_cuda_graph = (
68
+ self.try_use_cuda_graph
69
+ and wp.get_device().is_cuda
70
+ and wp.is_mempool_enabled(wp.get_device())
71
+ )
72
+ if self.try_use_cuda_graph and not self.use_cuda_graph:
73
+ raise Warning("""Unable to enable CUDA graph capture.
74
+ Please verify that Warp is using CUDA and that the memory pool is enabled.
75
+ """)
76
+
77
+ if self.use_cuda_graph:
78
+ with wp.ScopedCapture() as capture:
79
+ self.simulate()
80
+ self.graph = capture.graph
81
+
82
+ def simulate(self):
83
+ for _ in range(self.sim_substeps):
84
+ self.state_0.clear_forces()
85
+ wp.sim.collide(self.model, self.state_0)
86
+ self.integrator.simulate(
87
+ self.model, self.state_0, self.state_1, self.sim_dt
88
+ )
89
+ self.state_0, self.state_1 = self.state_1, self.state_0
90
+
91
+ def step(self, actions):
92
+ self.apply_actions(actions)
93
+
94
+ if self.use_cuda_graph:
95
+ wp.capture_launch(self.graph)
96
+ else:
97
+ self.simulate()
98
+
99
+ self.sim_time += self.frame_dt
100
+ return self.get_obs()
101
+
102
+ def render(self):
103
+ self.renderer.begin_frame(self.sim_time)
104
+ self.renderer.render(self.state_0)
105
+ self.renderer.end_frame()
106
+
107
+ def reset(self, **kwargs):
108
+ raise NotImplementedError("reset() must be implemented in subclass.")
@@ -1,94 +1,67 @@
1
- # written by: Matthew Taylor
2
- # source: https://github.com/MatthewAndreTaylor/WarpSimBalance
3
-
4
- try:
5
- import warp as wp
6
- import warp.sim.render
7
- except ImportError:
8
- raise ImportError(
9
- "Warp is not installed. Install using `pip install tinysim[warp]`"
10
- )
11
-
12
1
  import numpy as np
2
+ import warp as wp
13
3
 
4
+ from tinysim_warp import WarpBaseEnv
14
5
 
15
- def compute_env_offsets(num_envs, env_offset=(5.0, 0.0, 0.0)):
16
- env_offset = np.array(env_offset, dtype=float)
17
- axis = np.nonzero(env_offset)[0]
18
- axis = axis[0] if len(axis) else 0
19
- env_offsets = np.zeros((num_envs, 3))
20
- env_offsets[:, axis] = np.arange(num_envs) * env_offset[axis]
21
- env_offsets -= env_offsets.mean(axis=0)
22
- env_offsets[:, 1] = 0.0
23
- return env_offsets
24
-
6
+ quat_id = wp.quat_identity()
25
7
 
26
- class CartPoleBaseEnv:
27
- def __init__(self, use_cuda_graph=False, headless=False, num_envs=3):
28
- self.actions = np.array([0.0, 0.5, -0.5])
29
- self.num_envs = num_envs
30
8
 
31
- fps = 60
32
- self.frame_dt = 1.0 / fps
33
- self.sim_substeps = 10
34
- self.sim_dt = self.frame_dt / self.sim_substeps
9
+ class CartPoleBaseEnv(WarpBaseEnv):
35
10
 
36
- self.initialize()
11
+ actions = np.array([0.0, 0.5, -0.5])
37
12
 
38
- self.integrator = wp.sim.SemiImplicitIntegrator()
39
- self.renderer = wp.sim.render.SimRendererOpenGL(
40
- self.model, "example", headless=headless
41
- )
13
+ def build_model(self):
14
+ builder = wp.sim.ModelBuilder()
15
+ for i in range(self.num_envs):
16
+ builder.add_builder(
17
+ self.create_cartpole(),
18
+ xform=wp.transform(self.env_offsets[i], quat_id),
19
+ )
42
20
 
43
- # CUDA graph
44
- self.use_cuda_graph = (
45
- use_cuda_graph
46
- and wp.get_device().is_cuda
47
- and wp.is_mempool_enabled(wp.get_device())
21
+ model = builder.finalize()
22
+ model.joint_attach_ke = 1000.0
23
+ model.joint_attach_kd = 1.0
24
+ self.joint_act_np = np.zeros(model.joint_dof_count, dtype=np.float32)
25
+ self.joint_act_wp = wp.array(
26
+ self.joint_act_np, dtype=float, device=wp.get_device()
48
27
  )
49
- if self.use_cuda_graph:
50
- with wp.ScopedCapture() as capture:
51
- self.simulate()
52
- self.graph = capture.graph
53
-
54
- self.step(actions=[1] * self.num_envs)
28
+ model.joint_act = self.joint_act_wp
29
+ return model
55
30
 
56
31
  def create_cartpole(self):
57
32
  """Create cartpole system using pure Python/Warp API"""
58
33
  builder = wp.sim.ModelBuilder(gravity=-0.3)
59
- pole_size = wp.vec3(0.04, 1.0, 0.06)
60
34
  cart_body = builder.add_body(
61
- origin=wp.transform(wp.vec3(0.0, 2.0, 0.0), wp.quat_identity()), m=1.0
35
+ origin=wp.transform(wp.vec3(0.0, 2.0, 0.0), quat_id), m=1.0
62
36
  )
63
37
  builder.add_shape_sphere(body=cart_body, radius=0.1, density=100.0)
38
+
39
+ # Start angled pole
64
40
  pole_body = builder.add_body(
65
- origin=wp.transform(wp.vec3(0.0, 2.5, 0.0), wp.quat_identity()), m=0.01
41
+ origin=wp.transform(wp.vec3(0.0, 2.5, 0.0), quat_id), m=0.01
66
42
  )
43
+ pole_size = wp.vec3(0.04, 1.0, 0.06)
67
44
  builder.add_shape_box(
68
45
  body=pole_body,
69
- pos=wp.vec3(0.0, 0.0, 0.0),
70
46
  hx=pole_size[0] / 2.0,
71
47
  hy=pole_size[1] / 2.0,
72
48
  hz=pole_size[2] / 2.0,
73
49
  density=50.0,
74
50
  )
51
+ # Joint starts with a small initial angle
52
+ q = wp.quat_from_axis_angle(wp.vec3(0.0, 0.0, 1.0), 0.01)
75
53
  builder.add_joint_revolute(
76
54
  parent=cart_body,
77
55
  child=pole_body,
78
56
  axis=wp.vec3(0.0, 0.0, 1.0), # rotation around Z-axis
79
- parent_xform=wp.transform(wp.vec3(0.0, 0.0, 0.0), wp.quat_identity()),
80
- child_xform=wp.transform(
81
- wp.vec3(0.0, -0.5, 0.0), wp.quat_identity()
82
- ), # joint at pole base
57
+ child_xform=wp.transform(wp.vec3(0.0, -0.5, 0.0), q),
83
58
  limit_ke=1.0e4,
84
59
  limit_kd=1.0e1,
85
60
  )
86
61
  builder.add_joint_prismatic(
87
62
  parent=-1,
88
63
  child=cart_body,
89
- axis=wp.vec3(1.0, 0.0, 0.0),
90
- parent_xform=wp.transform(wp.vec3(0.0, 2.0, 0.0), wp.quat_identity()),
91
- child_xform=wp.transform(wp.vec3(0.0, 0.0, 0.0), wp.quat_identity()),
64
+ parent_xform=wp.transform(wp.vec3(0.0, 2.0, 0.0), quat_id),
92
65
  limit_lower=-5.0,
93
66
  limit_upper=5.0,
94
67
  limit_ke=1.0e4,
@@ -99,7 +72,10 @@ class CartPoleBaseEnv:
99
72
  )
100
73
  return builder
101
74
 
102
- def set_cart_trajectory(self, actions):
75
+ def solver(self):
76
+ return wp.sim.SemiImplicitIntegrator()
77
+
78
+ def apply_actions(self, actions):
103
79
  if len(actions) != self.num_envs:
104
80
  raise ValueError("Length of actions must match number of environments.")
105
81
 
@@ -108,152 +84,20 @@ class CartPoleBaseEnv:
108
84
  act[dof_indices] = self.actions[actions]
109
85
  wp.copy(self.model.joint_act, wp.array(act, dtype=wp.float32))
110
86
 
111
- def is_fallen(self, pole_quat):
112
- qw = float(np.clip(pole_quat[3], -1.0, 1.0))
113
- tilt = 2.0 * np.arccos(qw) # radians, in [0, pi]
114
- max_tilt = np.deg2rad(90.0)
115
- return tilt > max_tilt
116
-
117
- def step(self, actions):
118
- """Apply action and step the simulation for one environment timestep.
119
-
120
- Returns (observation, reward, terminated)
121
- """
122
- self.set_cart_trajectory(actions)
123
- if self.use_cuda_graph:
124
- wp.capture_launch(self.graph)
125
- else:
126
- self.simulate()
127
-
128
- self.sim_time += self.frame_dt
129
- obs = self.get_state_vector()
130
- pole_quat = obs[1:5]
131
- terminated = self.is_fallen(pole_quat)
132
- return obs, 1.0, terminated
133
-
134
- def simulate(self):
135
- for _ in range(self.sim_substeps):
136
- self.state.clear_forces()
137
- self.state = self.integrator.simulate(
138
- self.model, self.state, self.state, self.sim_dt
139
- )
140
-
141
- def reset(self):
142
- self.initialize()
143
- return self.step(actions=[1] * self.num_envs)
144
-
145
- def initialize(self):
146
- self.sim_time = 0.0
147
- builder = wp.sim.ModelBuilder()
148
- offsets = compute_env_offsets(self.num_envs)
149
-
150
- for i in range(self.num_envs):
151
- builder.add_builder(
152
- self.create_cartpole(),
153
- xform=wp.transform(offsets[i], wp.quat_identity()),
154
- )
155
-
156
- self.model = builder.finalize()
157
- self.model.joint_attach_ke = 1000.0
158
- self.model.joint_attach_kd = 1.0
159
- self.state = self.model.state()
160
-
161
- wp.sim.eval_fk(
162
- self.model, self.model.joint_q, self.model.joint_qd, None, self.state
163
- )
164
- self.joint_act_np = np.zeros(self.model.joint_dof_count, dtype=np.float32)
165
- self.joint_act_wp = wp.array(
166
- self.joint_act_np, dtype=float, device=wp.get_device()
167
- )
168
- self.model.joint_act = self.joint_act_wp
169
-
170
- def render(self):
171
- self.renderer.begin_frame(self.sim_time)
172
- self.renderer.render(self.state)
173
- self.renderer.end_frame()
174
-
175
87
  def get_state_vector(self):
176
- cart_id = 0
177
- pole_id = 1
178
-
179
- # convert transforms to numpy
180
- body_q = self.state.body_q.numpy()
181
- body_qd = self.state.body_qd.numpy()
182
-
183
- # --- Cart ---
88
+ cart_id, pole_id = 0, 1 # body indices
89
+ body_q = self.state_0.body_q.numpy()
90
+ body_qd = self.state_0.body_qd.numpy()
184
91
  cart_pos = body_q[cart_id] # [px, py, pz, qx, qy, qz, qw]
185
- # cart_pos = cart_pos[[0, 2]]
186
- cart_pos = cart_pos[[0]]
187
-
188
- # --- Pole ---
92
+ cart_pos = cart_pos[[0]] # cart_pos = cart_pos[[0, 2]]
189
93
  pole_quat = body_q[pole_id][3:] # quaternion part
190
94
  pole_vel = body_qd[pole_id][3:] # angular velocity part
191
-
192
95
  return np.concatenate([cart_pos, pole_quat, pole_vel])
193
96
 
194
-
195
- if __name__ == "__main__":
196
- import argparse
197
-
198
- parser = argparse.ArgumentParser(
199
- formatter_class=argparse.ArgumentDefaultsHelpFormatter
200
- )
201
- parser.add_argument(
202
- "--device", type=str, default=None, help="Override the default Warp device."
203
- )
204
- parser.add_argument(
205
- "--num-frames", type=int, default=1200, help="Total number of frames."
206
- )
207
- parser.add_argument(
208
- "--manual-control", action="store_true", help="Enable manual control."
209
- )
210
-
211
- args = parser.parse_known_args()[0]
212
-
213
- if args.manual_control:
214
- print("Manual control enabled")
215
- import keyboard
216
-
217
- with wp.ScopedDevice(args.device):
218
- example = CartPoleBaseEnv(use_cuda_graph=True)
219
-
220
- terminated = False
221
- check_terminated = True
222
-
223
- for i in range(args.num_frames):
224
- if args.manual_control:
225
- # Manual control logic
226
- if keyboard.is_pressed("k"):
227
- action = 2
228
- elif keyboard.is_pressed("l"):
229
- action = 1
230
- else:
231
- action = 0
232
-
233
- else:
234
- # Example control signals
235
- if i < 200:
236
- action = 0
237
- elif i < 255: # 260
238
- action = 2
239
- else:
240
- action = 0
241
-
242
- obs, reward, terminated = example.step(actions=[action] * example.num_envs)
243
- # print(f"Step {i}")
244
-
245
- if check_terminated and terminated:
246
- print("Pole fallen")
247
- check_terminated = False
248
-
249
- example.render()
250
-
251
- # print("State Vector:", obs)
252
- # print("Reward:", reward)
253
- # print("Terminated:", terminated)
254
-
255
- state = example.reset()
256
- print("Reset State Vector:", state)
257
- example.render()
258
-
259
- example.renderer.save()
97
+ def get_obs(self):
98
+ obs = self.get_state_vector()
99
+ pole_quat = obs[1:5]
100
+ qw = float(np.clip(pole_quat[3], -1.0, 1.0))
101
+ tilt = 2.0 * np.arccos(qw) # radians, in [0, pi]
102
+ max_tilt = np.deg2rad(90.0)
103
+ return obs, 1.0, tilt > max_tilt
@@ -1,37 +1,21 @@
1
- import math
2
- import os
1
+ import pathlib
3
2
 
4
3
  import numpy as np
4
+ import warp as wp
5
+ import warp.examples
5
6
 
6
- try:
7
- import warp as wp
8
- import warp.examples
9
- import warp.sim.render
10
- except ImportError:
11
- raise ImportError(
12
- "Warp is not installed. Install using `pip install tinysim[warp]`"
13
- )
7
+ from tinysim_warp import WarpBaseEnv
14
8
 
15
9
 
16
- def compute_env_offsets(num_envs, env_offset=(5.0, 0.0, 0.0)):
17
- env_offset = np.array(env_offset, dtype=float)
18
- axis = np.nonzero(env_offset)[0]
19
- axis = axis[0] if len(axis) else 0
20
- env_offsets = np.zeros((num_envs, 3))
21
- env_offsets[:, axis] = np.arange(num_envs) * env_offset[axis]
22
- env_offsets -= env_offsets.mean(axis=0)
23
- env_offsets[:, 1] = 0.0
24
- return env_offsets
25
-
26
-
27
- class RobotDogBaseEnv:
28
- def __init__(self, use_cuda_graph=False, headless=False, num_envs=8):
10
+ class RobotDogBaseEnv(WarpBaseEnv):
11
+ def build_model(self):
12
+ builder = wp.sim.ModelBuilder()
29
13
  articulation_builder = wp.sim.ModelBuilder()
30
- rot_x = wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), -math.pi * 0.5)
31
- rot_y = wp.quat_from_axis_angle(wp.vec3(0.0, 1.0, 0.0), math.pi * 0.5)
14
+ rot_x = wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), -np.pi * 0.5)
15
+ rot_y = wp.quat_from_axis_angle(wp.vec3(0.0, 1.0, 0.0), np.pi * 0.5)
32
16
  xform = wp.transform(wp.vec3(0.0, 0.65, 0.0), rot_y * rot_x)
33
17
  wp.sim.parse_urdf(
34
- os.path.join(warp.examples.get_asset_directory(), "quadruped.urdf"),
18
+ str(pathlib.Path(warp.examples.get_asset_directory()) / "quadruped.urdf"),
35
19
  articulation_builder,
36
20
  xform=xform,
37
21
  floating=True,
@@ -47,21 +31,10 @@ class RobotDogBaseEnv:
47
31
  limit_kd=1.0e1,
48
32
  )
49
33
 
50
- builder = wp.sim.ModelBuilder()
51
-
52
- self.sim_time = 0.0
53
- fps = 100
54
- self.frame_dt = 1.0 / fps
55
-
56
- self.sim_substeps = 10
57
- self.sim_dt = self.frame_dt / self.sim_substeps
58
-
59
- self.num_envs = num_envs
60
- offsets = compute_env_offsets(self.num_envs)
61
-
62
34
  for i in range(self.num_envs):
63
35
  builder.add_builder(
64
- articulation_builder, xform=wp.transform(offsets[i], wp.quat_identity())
36
+ articulation_builder,
37
+ xform=wp.transform(self.env_offsets[i], wp.quat_identity()),
65
38
  )
66
39
  builder.joint_q[-12:] = [0.2, 0.4, -0.6, -0.2, -0.4, 0.6, -0.2, 0.4, -0.6, 0.2, -0.4, 0.6] # fmt: skip
67
40
  builder.joint_act[-12:] = [0.2, 0.4, -0.6, -0.2, -0.4, 0.6, -0.2, 0.4, -0.6, 0.2, -0.4, 0.6] # fmt: skip
@@ -69,50 +42,18 @@ class RobotDogBaseEnv:
69
42
  builder.joint_axis_mode
70
43
  )
71
44
 
72
- # finalize model
73
- self.model = builder.finalize()
74
- self.model.ground = True
75
- self.model.joint_attach_ke = 16000.0
76
- self.model.joint_attach_kd = 200.0
77
- self.use_tile_gemm = False
78
- self.fuse_cholesky = False
45
+ model = builder.finalize()
46
+ model.joint_attach_ke = 16000.0
47
+ model.joint_attach_kd = 200.0
48
+ return model
79
49
 
80
- self.integrator = wp.sim.FeatherstoneIntegrator(
81
- self.model,
82
- use_tile_gemm=self.use_tile_gemm,
83
- fuse_cholesky=self.fuse_cholesky,
50
+ def solver(self):
51
+ return wp.sim.FeatherstoneIntegrator(
52
+ self.model, use_tile_gemm=False, fuse_cholesky=False
84
53
  )
85
54
 
86
- self.renderer = wp.sim.render.SimRendererOpenGL(
87
- self.model, "example", headless=headless
88
- )
89
- self.state_0 = self.model.state()
90
- self.state_1 = self.model.state()
91
-
92
- wp.sim.eval_fk(
93
- self.model, self.model.joint_q, self.model.joint_qd, None, self.state_0
94
- )
95
-
96
- self.use_cuda_graph = (
97
- use_cuda_graph
98
- and wp.get_device().is_cuda
99
- and wp.is_mempool_enabled(wp.get_device())
100
- )
101
- if self.use_cuda_graph:
102
- with wp.ScopedCapture() as capture:
103
- self.simulate()
104
- self.graph = capture.graph
105
-
106
- def simulate(self):
107
- for _ in range(self.sim_substeps):
108
- self.state_0.clear_forces()
109
- wp.sim.collide(self.model, self.state_0)
110
- self.integrator.simulate(
111
- self.model, self.state_0, self.state_1, self.sim_dt
112
- )
113
- self.state_0, self.state_1 = self.state_1, self.state_0
114
-
115
- def set_leg_poses(self, actions):
55
+ def apply_actions(self, actions):
56
+ # Set the target positions for all legs
116
57
  action_space_size = 12 * self.num_envs
117
58
  if len(actions) != action_space_size:
118
59
  raise ValueError(
@@ -121,83 +62,5 @@ class RobotDogBaseEnv:
121
62
 
122
63
  wp.copy(self.model.joint_act, wp.array(actions, dtype=wp.float32))
123
64
 
124
- def step(self, actions):
125
- self.set_leg_poses(actions)
126
-
127
- if self.use_cuda_graph:
128
- wp.capture_launch(self.graph)
129
- else:
130
- self.simulate()
131
- self.sim_time += self.frame_dt
132
-
133
- def render(self):
134
- self.renderer.begin_frame(self.sim_time)
135
- self.renderer.render(self.state_0)
136
- self.renderer.end_frame()
137
-
138
-
139
- if __name__ == "__main__":
140
- import argparse
141
-
142
- parser = argparse.ArgumentParser(
143
- formatter_class=argparse.ArgumentDefaultsHelpFormatter
144
- )
145
- parser.add_argument(
146
- "--device", type=str, default=None, help="Override the default Warp device."
147
- )
148
- parser.add_argument(
149
- "--num-frames", type=int, default=300, help="Total number of frames."
150
- )
151
- parser.add_argument(
152
- "--num-envs",
153
- type=int,
154
- default=3,
155
- help="Total number of simulated environments.",
156
- )
157
-
158
- args = parser.parse_known_args()[0]
159
-
160
- with wp.ScopedDevice(args.device):
161
- example = RobotDogBaseEnv(num_envs=args.num_envs)
162
- # [
163
- # (front right leg out),
164
- # (front right leg forward),
165
- # (front right forearm forward),
166
-
167
- # (front left leg out),
168
- # (front left leg forward),
169
- # (front left forearm forward),
170
-
171
- # (back right leg out),
172
- # (back right leg forward),
173
- # (back right forearm forward),
174
-
175
- # (back left leg out),
176
- # (back left leg forward),
177
- # (back left forearm forward),
178
- # ]
179
- # left and right directions are reversed
180
-
181
- actions = [0.2, 0.4, -0.6, -0.2, -0.4, 0.6, -0.2, 0.4, -0.6, 0.2, -0.4, 0.6] * args.num_envs # fmt: skip
182
-
183
- for i in range(args.num_frames):
184
- example.step(actions)
185
- example.render()
186
-
187
- if i % 10 == 0:
188
- # Stretch the right leg to the side
189
- # actions[0] += 0.1
190
-
191
- # Stretch the right leg forward
192
- actions[1] += 0.1
193
-
194
- # Strecth the forearm foward
195
- # actions[2] += 0.1
196
-
197
- # Stretch the left leg forward
198
- actions[4] -= 0.1
199
-
200
- # Back right leg backwards
201
- # actions[7] += 0.1
202
-
203
- example.renderer.save()
65
+ def get_obs(self):
66
+ return