warp-lang 0.15.0__py3-none-manylinux2014_x86_64.whl → 1.0.0__py3-none-manylinux2014_x86_64.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.

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (80) hide show
  1. warp/__init__.py +1 -0
  2. warp/codegen.py +7 -3
  3. warp/config.py +2 -1
  4. warp/constants.py +3 -0
  5. warp/context.py +44 -21
  6. warp/examples/assets/bunny.usd +0 -0
  7. warp/examples/assets/cartpole.urdf +110 -0
  8. warp/examples/assets/crazyflie.usd +0 -0
  9. warp/examples/assets/cube.usda +42 -0
  10. warp/examples/assets/nv_ant.xml +92 -0
  11. warp/examples/assets/nv_humanoid.xml +183 -0
  12. warp/examples/assets/quadruped.urdf +268 -0
  13. warp/examples/assets/rocks.nvdb +0 -0
  14. warp/examples/assets/rocks.usd +0 -0
  15. warp/examples/assets/sphere.usda +56 -0
  16. warp/examples/assets/torus.usda +105 -0
  17. warp/examples/core/example_dem.py +6 -6
  18. warp/examples/core/example_fluid.py +3 -3
  19. warp/examples/core/example_graph_capture.py +3 -6
  20. warp/examples/optim/example_bounce.py +9 -8
  21. warp/examples/optim/example_cloth_throw.py +12 -8
  22. warp/examples/optim/example_diffray.py +10 -12
  23. warp/examples/optim/example_drone.py +31 -14
  24. warp/examples/optim/example_spring_cage.py +10 -15
  25. warp/examples/optim/example_trajectory.py +7 -24
  26. warp/examples/sim/example_cartpole.py +3 -9
  27. warp/examples/sim/example_cloth.py +10 -10
  28. warp/examples/sim/example_granular.py +3 -3
  29. warp/examples/sim/example_granular_collision_sdf.py +9 -4
  30. warp/examples/sim/example_jacobian_ik.py +0 -10
  31. warp/examples/sim/example_particle_chain.py +4 -4
  32. warp/examples/sim/example_quadruped.py +15 -11
  33. warp/examples/sim/example_rigid_chain.py +13 -8
  34. warp/examples/sim/example_rigid_contact.py +4 -4
  35. warp/examples/sim/example_rigid_force.py +7 -7
  36. warp/examples/sim/example_rigid_soft_contact.py +4 -4
  37. warp/examples/sim/example_soft_body.py +3 -3
  38. warp/jax.py +45 -0
  39. warp/jax_experimental.py +339 -0
  40. warp/render/render_opengl.py +188 -95
  41. warp/render/render_usd.py +34 -10
  42. warp/sim/__init__.py +13 -4
  43. warp/sim/articulation.py +4 -5
  44. warp/sim/collide.py +320 -175
  45. warp/sim/import_mjcf.py +25 -30
  46. warp/sim/import_urdf.py +94 -63
  47. warp/sim/import_usd.py +51 -36
  48. warp/sim/inertia.py +3 -2
  49. warp/sim/integrator.py +233 -0
  50. warp/sim/integrator_euler.py +447 -469
  51. warp/sim/integrator_featherstone.py +1991 -0
  52. warp/sim/integrator_xpbd.py +1420 -640
  53. warp/sim/model.py +741 -487
  54. warp/sim/particles.py +2 -1
  55. warp/sim/render.py +18 -2
  56. warp/sim/utils.py +222 -11
  57. warp/stubs.py +1 -0
  58. warp/tape.py +6 -9
  59. warp/tests/test_examples.py +87 -20
  60. warp/tests/test_grad_customs.py +122 -0
  61. warp/tests/test_jax.py +254 -0
  62. warp/tests/test_options.py +13 -53
  63. warp/tests/test_quat.py +23 -0
  64. warp/tests/test_snippet.py +2 -0
  65. warp/tests/test_utils.py +31 -26
  66. warp/tests/test_verify_fp.py +65 -0
  67. warp/tests/unittest_suites.py +4 -0
  68. warp/utils.py +50 -1
  69. {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/METADATA +1 -1
  70. {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/RECORD +73 -64
  71. warp/examples/env/__init__.py +0 -0
  72. warp/examples/env/env_ant.py +0 -61
  73. warp/examples/env/env_cartpole.py +0 -63
  74. warp/examples/env/env_humanoid.py +0 -65
  75. warp/examples/env/env_usd.py +0 -97
  76. warp/examples/env/environment.py +0 -526
  77. warp/sim/optimizer.py +0 -138
  78. {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/LICENSE.md +0 -0
  79. {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/WHEEL +0 -0
  80. {warp_lang-0.15.0.dist-info → warp_lang-1.0.0.dist-info}/top_level.txt +0 -0
@@ -1,97 +0,0 @@
1
- # Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
2
- # NVIDIA CORPORATION and its licensors retain all intellectual property
3
- # and proprietary rights in and to this software, related documentation
4
- # and any modifications thereto. Any use, reproduction, disclosure or
5
- # distribution of this software and related documentation without an express
6
- # license agreement from NVIDIA CORPORATION is strictly prohibited.
7
-
8
- ###########################################################################
9
- # USD Environment
10
- #
11
- # Shows how to load a USD file containing USD Physics schema definitions.
12
- #
13
- ###########################################################################
14
-
15
- import warp as wp
16
- import warp.sim
17
-
18
- from .environment import Environment, run_env
19
-
20
-
21
- class UsdEnvironment(Environment):
22
- sim_name = "env_usd"
23
- opengl_render_settings = dict(scaling=10.0, draw_grid=True)
24
- usd_render_settings = dict(scaling=100.0)
25
-
26
- episode_duration = 2.0
27
-
28
- sim_substeps_euler = 64
29
- sim_substeps_xpbd = 8
30
-
31
- xpbd_settings = dict(
32
- iterations=10,
33
- enable_restitution=True,
34
- joint_linear_relaxation=0.8,
35
- joint_angular_relaxation=0.45,
36
- rigid_contact_relaxation=1.0,
37
- rigid_contact_con_weighting=True,
38
- )
39
-
40
- # USD files define their own ground plane if necessary
41
- activate_ground_plane = False
42
- num_envs = 1
43
-
44
- plot_body_coords = False
45
-
46
- def create_articulation(self, builder):
47
- usd_filename = wp.sim.resolve_usd_from_url(
48
- "http://omniverse-content-staging.s3-us-west-2.amazonaws.com/Assets/Isaac/2022.2.1/Isaac/Robots/Franka/franka_instanceable.usd",
49
- target_folder_name=".panda_usd_files")
50
- settings = wp.sim.parse_usd(
51
- usd_filename,
52
- builder,
53
- default_thickness=0.01,
54
- # ignore collision meshes from Franka robot
55
- ignore_paths=[".*collisions.*"],
56
- default_ke=1e6,
57
- )
58
-
59
- self.frame_dt = 1.0 / settings["fps"]
60
- if settings["duration"] > 0.0:
61
- self.episode_duration = settings["duration"]
62
- self.sim_substeps = 10
63
- self.sim_dt = self.frame_dt / self.sim_substeps
64
- self.episode_frames = int(self.episode_duration / self.frame_dt)
65
- self.sim_steps = int(self.episode_duration / self.sim_dt)
66
- self.sim_time = 0.0
67
- self.render_time = 0.0
68
- self.up_axis = settings["up_axis"]
69
-
70
- def before_simulate(self):
71
- # print some information about the loaded model
72
- if self.model.shape_count > 0:
73
- print("shape_transform", self.model.shape_transform.numpy())
74
- print("geo_scale", self.model.shape_geo.scale.numpy())
75
- if self.model.joint_count > 0:
76
- print("joint parent", self.model.joint_parent.numpy())
77
- print("joint child", self.model.joint_child.numpy())
78
- if len(self.model.joint_q) > 0:
79
- print("joint q", self.model.joint_q.numpy())
80
- if len(self.model.joint_axis) > 0:
81
- print("joint axis", self.model.joint_axis.numpy())
82
- print("joint target", self.model.joint_target.numpy())
83
- print("joint target ke", self.model.joint_target_ke.numpy())
84
- print("joint target kd", self.model.joint_target_kd.numpy())
85
- print("joint limit lower", self.model.joint_limit_lower.numpy())
86
- print("joint limit upper", self.model.joint_limit_upper.numpy())
87
- print("joint_X_p", self.model.joint_X_p.numpy())
88
- print("joint_X_c", self.model.joint_X_c.numpy())
89
- if self.model.body_count > 0:
90
- print("COM", self.model.body_com.numpy())
91
- print("Mass", self.model.body_mass.numpy())
92
- print("Inertia", self.model.body_inertia.numpy())
93
- print("body_q", self.state.body_q.numpy())
94
-
95
-
96
- if __name__ == "__main__":
97
- run_env(UsdEnvironment)
@@ -1,526 +0,0 @@
1
- # Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
2
- # NVIDIA CORPORATION and its licensors retain all intellectual property
3
- # and proprietary rights in and to this software, related documentation
4
- # and any modifications thereto. Any use, reproduction, disclosure or
5
- # distribution of this software and related documentation without an express
6
- # license agreement from NVIDIA CORPORATION is strictly prohibited.
7
-
8
- import argparse
9
- import os
10
- from enum import Enum
11
- from typing import Tuple
12
-
13
- import numpy as np
14
-
15
- import warp as wp
16
- import warp.sim
17
- import warp.sim.render
18
-
19
- wp.init()
20
-
21
-
22
- class RenderMode(Enum):
23
- NONE = "none"
24
- OPENGL = "opengl"
25
- USD = "usd"
26
-
27
- def __str__(self):
28
- return self.value
29
-
30
-
31
- class IntegratorType(Enum):
32
- EULER = "euler"
33
- XPBD = "xpbd"
34
-
35
- def __str__(self):
36
- return self.value
37
-
38
-
39
- def compute_env_offsets(num_envs, env_offset=(5.0, 0.0, 5.0), up_axis="Y"):
40
- # compute positional offsets per environment
41
- env_offset = np.array(env_offset)
42
- nonzeros = np.nonzero(env_offset)[0]
43
- num_dim = nonzeros.shape[0]
44
- if num_dim > 0:
45
- side_length = int(np.ceil(num_envs ** (1.0 / num_dim)))
46
- env_offsets = []
47
- else:
48
- env_offsets = np.zeros((num_envs, 3))
49
- if num_dim == 1:
50
- for i in range(num_envs):
51
- env_offsets.append(i * env_offset)
52
- elif num_dim == 2:
53
- for i in range(num_envs):
54
- d0 = i // side_length
55
- d1 = i % side_length
56
- offset = np.zeros(3)
57
- offset[nonzeros[0]] = d0 * env_offset[nonzeros[0]]
58
- offset[nonzeros[1]] = d1 * env_offset[nonzeros[1]]
59
- env_offsets.append(offset)
60
- elif num_dim == 3:
61
- for i in range(num_envs):
62
- d0 = i // (side_length * side_length)
63
- d1 = (i // side_length) % side_length
64
- d2 = i % side_length
65
- offset = np.zeros(3)
66
- offset[0] = d0 * env_offset[0]
67
- offset[1] = d1 * env_offset[1]
68
- offset[2] = d2 * env_offset[2]
69
- env_offsets.append(offset)
70
- env_offsets = np.array(env_offsets)
71
- min_offsets = np.min(env_offsets, axis=0)
72
- correction = min_offsets + (np.max(env_offsets, axis=0) - min_offsets) / 2.0
73
- if isinstance(up_axis, str):
74
- up_axis = "XYZ".index(up_axis.upper())
75
- correction[up_axis] = 0.0 # ensure the envs are not shifted below the ground plane
76
- env_offsets -= correction
77
- return env_offsets
78
-
79
-
80
- class Environment:
81
- sim_name: str = "Environment"
82
-
83
- frame_dt = 1.0 / 60.0
84
-
85
- episode_duration = 5.0 # seconds
86
-
87
- # whether to play the simulation indefinitely when using the OpenGL renderer
88
- continuous_opengl_render: bool = True
89
-
90
- sim_substeps_euler: int = 16
91
- sim_substeps_xpbd: int = 5
92
-
93
- euler_settings = dict()
94
- xpbd_settings = dict()
95
-
96
- render_mode: RenderMode = RenderMode.OPENGL
97
- opengl_render_settings = dict()
98
- usd_render_settings = dict(scaling=10.0)
99
- show_rigid_contact_points = False
100
- contact_points_radius = 1e-3
101
- show_joints = False
102
- # whether OpenGLRenderer should render each environment in a separate tile
103
- use_tiled_rendering = False
104
-
105
- # whether to apply model.joint_q, joint_qd to bodies before simulating
106
- eval_fk: bool = True
107
-
108
- profile: bool = False
109
-
110
- use_graph_capture: bool = wp.get_preferred_device().is_cuda
111
-
112
- num_envs: int = 100
113
-
114
- activate_ground_plane: bool = True
115
-
116
- integrator_type: IntegratorType = IntegratorType.XPBD
117
-
118
- up_axis: str = "Y"
119
- gravity: float = -9.81
120
- env_offset: Tuple[float, float, float] = (1.0, 0.0, 1.0)
121
-
122
- # stiffness and damping for joint attachment dynamics used by Euler
123
- joint_attach_ke: float = 32000.0
124
- joint_attach_kd: float = 50.0
125
-
126
- # distance threshold at which contacts are generated
127
- rigid_contact_margin: float = 0.05
128
-
129
- # whether each environment should have its own collision group
130
- # to avoid collisions between environments
131
- separate_collision_group_per_env: bool = True
132
-
133
- plot_body_coords: bool = False
134
- plot_joint_coords: bool = False
135
-
136
- requires_grad: bool = False
137
-
138
- # control-related definitions, to be updated by derived classes
139
- control_dim: int = 0
140
-
141
- def __init__(self):
142
- self.parser = argparse.ArgumentParser()
143
- self.parser.add_argument(
144
- "--integrator",
145
- help="Type of integrator",
146
- type=IntegratorType,
147
- choices=list(IntegratorType),
148
- default=self.integrator_type.value,
149
- )
150
- self.parser.add_argument(
151
- "--visualizer",
152
- help="Type of renderer",
153
- type=RenderMode,
154
- choices=list(RenderMode),
155
- default=self.render_mode.value,
156
- )
157
- self.parser.add_argument(
158
- "--num_envs", help="Number of environments to simulate", type=int, default=self.num_envs
159
- )
160
- self.parser.add_argument("--profile", help="Enable profiling", type=bool, default=self.profile)
161
-
162
- def parse_args(self):
163
- args = self.parser.parse_args()
164
- self.integrator_type = args.integrator
165
- self.render_mode = args.visualizer
166
- self.num_envs = args.num_envs
167
- self.profile = args.profile
168
-
169
- def init(self):
170
- if self.integrator_type == IntegratorType.EULER:
171
- self.sim_substeps = self.sim_substeps_euler
172
- elif self.integrator_type == IntegratorType.XPBD:
173
- self.sim_substeps = self.sim_substeps_xpbd
174
-
175
- self.episode_frames = int(self.episode_duration / self.frame_dt)
176
- self.sim_dt = self.frame_dt / self.sim_substeps
177
- self.sim_steps = int(self.episode_duration / self.sim_dt)
178
-
179
- if self.use_tiled_rendering and self.render_mode == RenderMode.OPENGL:
180
- # no environment offset when using tiled rendering
181
- self.env_offset = (0.0, 0.0, 0.0)
182
-
183
- builder = wp.sim.ModelBuilder()
184
- builder.rigid_contact_margin = self.rigid_contact_margin
185
- try:
186
- articulation_builder = wp.sim.ModelBuilder()
187
- self.create_articulation(articulation_builder)
188
- env_offsets = compute_env_offsets(self.num_envs, self.env_offset, self.up_axis)
189
- for i in range(self.num_envs):
190
- xform = wp.transform(env_offsets[i], wp.quat_identity())
191
- builder.add_builder(
192
- articulation_builder, xform, separate_collision_group=self.separate_collision_group_per_env
193
- )
194
- self.bodies_per_env = len(articulation_builder.body_q)
195
- except NotImplementedError:
196
- # custom simulation setup where something other than an articulation is used
197
- self.setup(builder)
198
- self.bodies_per_env = len(builder.body_q)
199
-
200
- self.model = builder.finalize()
201
- self.device = self.model.device
202
- if not self.device.is_cuda:
203
- self.use_graph_capture = False
204
- self.model.ground = self.activate_ground_plane
205
-
206
- self.model.joint_attach_ke = self.joint_attach_ke
207
- self.model.joint_attach_kd = self.joint_attach_kd
208
-
209
- # set up current and next state to be used by the integrator
210
- self.state_0 = None
211
- self.state_1 = None
212
-
213
- if self.integrator_type == IntegratorType.EULER:
214
- self.integrator = wp.sim.SemiImplicitIntegrator(**self.euler_settings)
215
- elif self.integrator_type == IntegratorType.XPBD:
216
- self.integrator = wp.sim.XPBDIntegrator(**self.xpbd_settings)
217
-
218
- self.renderer = None
219
- if self.profile:
220
- self.render_mode = RenderMode.NONE
221
- if self.render_mode == RenderMode.OPENGL:
222
- self.renderer = wp.sim.render.SimRendererOpenGL(
223
- self.model,
224
- self.sim_name,
225
- up_axis=self.up_axis,
226
- show_rigid_contact_points=self.show_rigid_contact_points,
227
- contact_points_radius=self.contact_points_radius,
228
- show_joints=self.show_joints,
229
- **self.opengl_render_settings,
230
- )
231
- if self.use_tiled_rendering and self.num_envs > 1:
232
- floor_id = self.model.shape_count - 1
233
- # all shapes except the floor
234
- instance_ids = np.arange(floor_id, dtype=np.int32).tolist()
235
- shapes_per_env = floor_id // self.num_envs
236
- additional_instances = []
237
- if self.activate_ground_plane:
238
- additional_instances.append(floor_id)
239
- self.renderer.setup_tiled_rendering(
240
- instances=[
241
- instance_ids[i * shapes_per_env : (i + 1) * shapes_per_env] + additional_instances
242
- for i in range(self.num_envs)
243
- ]
244
- )
245
- elif self.render_mode == RenderMode.USD:
246
- filename = os.path.join(os.path.dirname(__file__), "..", "outputs", self.sim_name + ".usd")
247
- self.renderer = wp.sim.render.SimRendererUsd(
248
- self.model,
249
- filename,
250
- up_axis=self.up_axis,
251
- show_rigid_contact_points=self.show_rigid_contact_points,
252
- **self.usd_render_settings,
253
- )
254
-
255
- def create_articulation(self, builder):
256
- raise NotImplementedError
257
-
258
- def setup(self, builder):
259
- pass
260
-
261
- def customize_model(self, model):
262
- pass
263
-
264
- def before_simulate(self):
265
- pass
266
-
267
- def after_simulate(self):
268
- pass
269
-
270
- def custom_update(self):
271
- pass
272
-
273
- @property
274
- def state(self):
275
- # shortcut to current state
276
- return self.state_0
277
-
278
- def update(self):
279
- for i in range(self.sim_substeps):
280
- self.state_0.clear_forces()
281
- self.custom_update()
282
- wp.sim.collide(self.model, self.state_0)
283
- self.integrator.simulate(self.model, self.state_0, self.state_1, self.sim_dt)
284
- self.state_0, self.state_1 = self.state_1, self.state_0
285
-
286
- def render(self, state=None):
287
- if self.renderer is not None:
288
- with wp.ScopedTimer("render", False):
289
- self.render_time += self.frame_dt
290
- self.renderer.begin_frame(self.render_time)
291
- # render state 1 (swapped with state 0 just before)
292
- self.renderer.render(state or self.state_1)
293
- self.renderer.end_frame()
294
-
295
- def run(self):
296
- # ---------------
297
- # run simulation
298
-
299
- self.sim_time = 0.0
300
- self.render_time = 0.0
301
- self.state_0 = self.model.state()
302
- self.state_1 = self.model.state()
303
-
304
- if self.eval_fk:
305
- wp.sim.eval_fk(self.model, self.model.joint_q, self.model.joint_qd, None, self.state_0)
306
-
307
- self.before_simulate()
308
-
309
- if self.renderer is not None:
310
- self.render(self.state_0)
311
-
312
- if self.render_mode == RenderMode.OPENGL:
313
- self.renderer.paused = True
314
-
315
- profiler = {}
316
-
317
- if self.use_graph_capture:
318
- # create update graph
319
- wp.capture_begin()
320
- try:
321
- self.update()
322
- finally:
323
- graph = wp.capture_end()
324
-
325
- if self.plot_body_coords:
326
- q_history = []
327
- q_history.append(self.state_0.body_q.numpy().copy())
328
- qd_history = []
329
- qd_history.append(self.state_0.body_qd.numpy().copy())
330
- delta_history = []
331
- delta_history.append(self.state_0.body_deltas.numpy().copy())
332
- num_con_history = []
333
- num_con_history.append(self.model.rigid_contact_inv_weight.numpy().copy())
334
- if self.plot_joint_coords:
335
- joint_q_history = []
336
- joint_q = wp.zeros_like(self.model.joint_q)
337
- joint_qd = wp.zeros_like(self.model.joint_qd)
338
-
339
- # simulate
340
- with wp.ScopedTimer("simulate", detailed=False, print=False, active=True, dict=profiler):
341
- running = True
342
- while running:
343
- for f in range(self.episode_frames):
344
- if self.use_graph_capture:
345
- wp.capture_launch(graph)
346
- self.sim_time += self.frame_dt
347
- else:
348
- self.update()
349
- self.sim_time += self.frame_dt
350
-
351
- if not self.profile:
352
- if self.plot_body_coords:
353
- q_history.append(self.state_0.body_q.numpy().copy())
354
- qd_history.append(self.state_0.body_qd.numpy().copy())
355
- delta_history.append(self.state_0.body_deltas.numpy().copy())
356
- num_con_history.append(self.model.rigid_contact_inv_weight.numpy().copy())
357
-
358
- if self.plot_joint_coords:
359
- wp.sim.eval_ik(self.model, self.state_0, joint_q, joint_qd)
360
- joint_q_history.append(joint_q.numpy().copy())
361
-
362
- self.render()
363
- if self.render_mode == RenderMode.OPENGL and self.renderer.has_exit:
364
- running = False
365
- break
366
-
367
- if not self.continuous_opengl_render or self.render_mode != RenderMode.OPENGL:
368
- break
369
-
370
- wp.synchronize()
371
-
372
- self.after_simulate()
373
-
374
- avg_time = np.array(profiler["simulate"]).mean() / self.episode_frames
375
- avg_steps_second = 1000.0 * float(self.num_envs) / avg_time
376
-
377
- print(f"envs: {self.num_envs} steps/second {avg_steps_second} avg_time {avg_time}")
378
-
379
- if self.renderer is not None:
380
- self.renderer.save()
381
-
382
- if self.plot_body_coords:
383
- import matplotlib.pyplot as plt
384
-
385
- q_history = np.array(q_history)
386
- qd_history = np.array(qd_history)
387
- delta_history = np.array(delta_history)
388
- num_con_history = np.array(num_con_history)
389
-
390
- # find bodies with non-zero mass
391
- body_indices = np.where(self.model.body_mass.numpy() > 0)[0]
392
- body_indices = body_indices[:5] # limit number of bodies to plot
393
-
394
- fig, ax = plt.subplots(len(body_indices), 7, figsize=(10, 10), squeeze=False)
395
- fig.subplots_adjust(hspace=0.2, wspace=0.2)
396
- for i, j in enumerate(body_indices):
397
- ax[i, 0].set_title(f"Body {j} Position")
398
- ax[i, 0].grid()
399
- ax[i, 1].set_title(f"Body {j} Orientation")
400
- ax[i, 1].grid()
401
- ax[i, 2].set_title(f"Body {j} Linear Velocity")
402
- ax[i, 2].grid()
403
- ax[i, 3].set_title(f"Body {j} Angular Velocity")
404
- ax[i, 3].grid()
405
- ax[i, 4].set_title(f"Body {j} Linear Delta")
406
- ax[i, 4].grid()
407
- ax[i, 5].set_title(f"Body {j} Angular Delta")
408
- ax[i, 5].grid()
409
- ax[i, 6].set_title(f"Body {j} Num Contacts")
410
- ax[i, 6].grid()
411
- ax[i, 0].plot(q_history[:, j, :3])
412
- ax[i, 1].plot(q_history[:, j, 3:])
413
- ax[i, 2].plot(qd_history[:, j, 3:])
414
- ax[i, 3].plot(qd_history[:, j, :3])
415
- ax[i, 4].plot(delta_history[:, j, 3:])
416
- ax[i, 5].plot(delta_history[:, j, :3])
417
- ax[i, 6].plot(num_con_history[:, j])
418
- ax[i, 0].set_xlim(0, self.sim_steps)
419
- ax[i, 1].set_xlim(0, self.sim_steps)
420
- ax[i, 2].set_xlim(0, self.sim_steps)
421
- ax[i, 3].set_xlim(0, self.sim_steps)
422
- ax[i, 4].set_xlim(0, self.sim_steps)
423
- ax[i, 5].set_xlim(0, self.sim_steps)
424
- ax[i, 6].set_xlim(0, self.sim_steps)
425
- ax[i, 6].yaxis.get_major_locator().set_params(integer=True)
426
- plt.show()
427
-
428
- if self.plot_joint_coords:
429
- import matplotlib.pyplot as plt
430
-
431
- joint_q_history = np.array(joint_q_history)
432
- dof_q = joint_q_history.shape[1]
433
- ncols = int(np.ceil(np.sqrt(dof_q)))
434
- nrows = int(np.ceil(dof_q / float(ncols)))
435
- fig, axes = plt.subplots(
436
- ncols=ncols,
437
- nrows=nrows,
438
- constrained_layout=True,
439
- figsize=(ncols * 3.5, nrows * 3.5),
440
- squeeze=False,
441
- sharex=True,
442
- )
443
-
444
- joint_id = 0
445
- joint_type_names = {
446
- wp.sim.JOINT_BALL: "ball",
447
- wp.sim.JOINT_REVOLUTE: "hinge",
448
- wp.sim.JOINT_PRISMATIC: "slide",
449
- wp.sim.JOINT_UNIVERSAL: "universal",
450
- wp.sim.JOINT_COMPOUND: "compound",
451
- wp.sim.JOINT_FREE: "free",
452
- wp.sim.JOINT_FIXED: "fixed",
453
- wp.sim.JOINT_DISTANCE: "distance",
454
- wp.sim.JOINT_D6: "D6",
455
- }
456
- joint_lower = self.model.joint_limit_lower.numpy()
457
- joint_upper = self.model.joint_limit_upper.numpy()
458
- joint_type = self.model.joint_type.numpy()
459
- while joint_id < len(joint_type) - 1 and joint_type[joint_id] == wp.sim.JOINT_FIXED:
460
- # skip fixed joints
461
- joint_id += 1
462
- q_start = self.model.joint_q_start.numpy()
463
- qd_start = self.model.joint_qd_start.numpy()
464
- qd_i = qd_start[joint_id]
465
- for dim in range(ncols * nrows):
466
- ax = axes[dim // ncols, dim % ncols]
467
- if dim >= dof_q:
468
- ax.axis("off")
469
- continue
470
- ax.grid()
471
- ax.plot(joint_q_history[:, dim])
472
- if joint_type[joint_id] != wp.sim.JOINT_FREE:
473
- lower = joint_lower[qd_i]
474
- if abs(lower) < 2 * np.pi:
475
- ax.axhline(lower, color="red")
476
- upper = joint_upper[qd_i]
477
- if abs(upper) < 2 * np.pi:
478
- ax.axhline(upper, color="red")
479
- joint_name = joint_type_names[joint_type[joint_id]]
480
- ax.set_title(f"$\\mathbf{{q_{{{dim}}}}}$ ({self.model.joint_name[joint_id]} / {joint_name} {joint_id})")
481
- if joint_id < self.model.joint_count - 1 and q_start[joint_id + 1] == dim + 1:
482
- joint_id += 1
483
- qd_i = qd_start[joint_id]
484
- else:
485
- qd_i += 1
486
- plt.tight_layout()
487
- plt.show()
488
-
489
- return 1000.0 * float(self.num_envs) / avg_time
490
-
491
-
492
- def run_env(Demo):
493
- demo = Demo()
494
- demo.parse_args()
495
- if demo.profile:
496
- import matplotlib.pyplot as plt
497
-
498
- env_count = 2
499
- env_times = []
500
- env_size = []
501
-
502
- for i in range(15):
503
- demo.num_envs = env_count
504
- demo.init()
505
- steps_per_second = demo.run()
506
-
507
- env_size.append(env_count)
508
- env_times.append(steps_per_second)
509
-
510
- env_count *= 2
511
-
512
- # dump times
513
- for i in range(len(env_times)):
514
- print(f"envs: {env_size[i]} steps/second: {env_times[i]}")
515
-
516
- # plot
517
- plt.figure(1)
518
- plt.plot(env_size, env_times)
519
- plt.xscale("log")
520
- plt.xlabel("Number of Envs")
521
- plt.yscale("log")
522
- plt.ylabel("Steps/Second")
523
- plt.show()
524
- else:
525
- demo.init()
526
- return demo.run()