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
@@ -148,12 +148,12 @@ class Example:
148
148
  if stage is not None:
149
149
  self.renderer = wp.render.UsdRenderer(stage)
150
150
  self.renderer.render_ground()
151
-
151
+
152
152
  self.use_graph = wp.get_device().is_cuda
153
153
  if self.use_graph:
154
- wp.capture_begin()
155
- self.simulate()
156
- self.graph = wp.capture_end()
154
+ with wp.ScopedCapture() as capture:
155
+ self.simulate()
156
+ self.graph = capture.graph
157
157
 
158
158
  def simulate(self):
159
159
  for _ in range(self.sim_substeps):
@@ -182,12 +182,12 @@ class Example:
182
182
  with wp.ScopedTimer("step", active=True):
183
183
  with wp.ScopedTimer("grid build", active=False):
184
184
  self.grid.build(self.x, self.grid_cell_size)
185
-
185
+
186
186
  if self.use_graph:
187
187
  wp.capture_launch(self.graph)
188
188
  else:
189
189
  self.simulate()
190
-
190
+
191
191
  self.sim_time += self.frame_dt
192
192
 
193
193
  def render(self):
@@ -187,9 +187,9 @@ class Example:
187
187
  # capture pressure solve as a CUDA graph
188
188
  self.use_graph = wp.get_device().is_cuda
189
189
  if self.use_graph:
190
- wp.capture_begin()
191
- self.pressure_iterations()
192
- self.graph = wp.capture_end()
190
+ with wp.ScopedCapture() as capture:
191
+ self.pressure_iterations()
192
+ self.graph = capture.graph
193
193
 
194
194
  def step(self):
195
195
  with wp.ScopedTimer("step"):
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # Shows how to implement CUDA graph capture using Python's try-finally
12
12
  # pattern. The finally block ensures wp.capture_end() gets called, even
13
- # if an exception occurs during capture, which would otherwise
13
+ # if an exception occurs during capture, which would otherwise
14
14
  # trap the stream in a capturing state.
15
15
  #
16
16
  ###########################################################################
@@ -72,12 +72,9 @@ class Example:
72
72
  self.use_graph = wp.get_device().is_cuda
73
73
  if self.use_graph:
74
74
  # record launches
75
- wp.capture_begin()
76
- try:
75
+ with wp.ScopedCapture() as capture:
77
76
  self.fbm()
78
- finally:
79
- # end capture and return a graph object
80
- self.graph = wp.capture_end()
77
+ self.graph = capture.graph
81
78
 
82
79
  def fbm(self):
83
80
  for _ in range(16):
@@ -76,7 +76,8 @@ class Example:
76
76
 
77
77
  self.profile = profile
78
78
 
79
- self.model = builder.finalize()
79
+ # use `requires_grad=True` to create a model for differentiable simulation
80
+ self.model = builder.finalize(requires_grad=True)
80
81
  self.model.ground = True
81
82
 
82
83
  self.model.soft_contact_ke = ke
@@ -94,7 +95,7 @@ class Example:
94
95
  # allocate sim states for trajectory
95
96
  self.states = []
96
97
  for i in range(self.sim_steps + 1):
97
- self.states.append(self.model.state(requires_grad=True))
98
+ self.states.append(self.model.state())
98
99
 
99
100
  # one-shot contact creation (valid if we're doing simple collision against a constant normal plane)
100
101
  wp.sim.collide(self.model, self.states[0])
@@ -106,12 +107,12 @@ class Example:
106
107
  # capture forward/backward passes
107
108
  self.use_graph = wp.get_device().is_cuda
108
109
  if self.use_graph:
109
- wp.capture_begin()
110
- self.tape = wp.Tape()
111
- with self.tape:
112
- self.forward()
113
- self.tape.backward(self.loss)
114
- self.graph = wp.capture_end()
110
+ with wp.ScopedCapture() as capture:
111
+ self.tape = wp.Tape()
112
+ with self.tape:
113
+ self.forward()
114
+ self.tape.backward(self.loss)
115
+ self.graph = capture.graph
115
116
 
116
117
  def forward(self):
117
118
  # run control loop
@@ -118,12 +118,12 @@ class Example:
118
118
  # capture forward/backward passes
119
119
  self.use_graph = wp.get_device().is_cuda
120
120
  if self.use_graph:
121
- wp.capture_begin()
122
- self.tape = wp.Tape()
123
- with self.tape:
124
- self.forward()
125
- self.tape.backward(self.loss)
126
- self.graph = wp.capture_end()
121
+ with wp.ScopedCapture() as capture:
122
+ self.tape = wp.Tape()
123
+ with self.tape:
124
+ self.forward()
125
+ self.tape.backward(self.loss)
126
+ self.graph = capture.graph
127
127
 
128
128
  def forward(self):
129
129
  # run control loop
@@ -137,7 +137,7 @@ class Example:
137
137
  wp.launch(
138
138
  com_kernel,
139
139
  dim=self.model.particle_count,
140
- inputs=[self.states[-1].particle_q, self.model.particle_count, self.com]
140
+ inputs=[self.states[-1].particle_q, self.model.particle_count, self.com],
141
141
  )
142
142
  wp.launch(loss_kernel, dim=1, inputs=[self.com, self.target, self.loss])
143
143
 
@@ -178,7 +178,11 @@ class Example:
178
178
  self.renderer.begin_frame(self.render_time)
179
179
  self.renderer.render(self.states[i])
180
180
  self.renderer.render_box(
181
- pos=self.target, rot=wp.quat_identity(), extents=(0.1, 0.1, 0.1), name="target", color=(1.0, 0.0, 0.0),
181
+ pos=self.target,
182
+ rot=wp.quat_identity(),
183
+ extents=(0.1, 0.1, 0.1),
184
+ name="target",
185
+ color=(1.0, 0.0, 0.0),
182
186
  )
183
187
  self.renderer.render_line_strip(
184
188
  vertices=traj_verts,
@@ -411,12 +411,12 @@ class Example:
411
411
  # capture graph
412
412
  self.use_graph = wp.get_device().is_cuda
413
413
  if self.use_graph:
414
- wp.capture_begin()
415
- self.tape = wp.Tape()
416
- with self.tape:
417
- self.forward()
418
- self.tape.backward(self.loss)
419
- self.graph = wp.capture_end()
414
+ with wp.ScopedCapture() as capture:
415
+ self.tape = wp.Tape()
416
+ with self.tape:
417
+ self.forward()
418
+ self.tape.backward(self.loss)
419
+ self.graph = capture.graph
420
420
 
421
421
  self.optimizer = SGD(
422
422
  [self.render_mesh.rot],
@@ -440,23 +440,21 @@ class Example:
440
440
  self.rays,
441
441
  self.lights,
442
442
  self.render_mode,
443
- ]
443
+ ],
444
444
  )
445
445
 
446
446
  # downsample
447
447
  wp.launch(
448
448
  kernel=downsample_kernel,
449
449
  dim=self.num_pixels,
450
- inputs=[self.rays, self.pixels, self.rays_width, pow(2, self.num_samples)]
450
+ inputs=[self.rays, self.pixels, self.rays_width, pow(2, self.num_samples)],
451
451
  )
452
452
 
453
453
  def forward(self):
454
454
  self.ray_cast()
455
455
 
456
456
  # compute pixel loss
457
- wp.launch(
458
- loss_kernel, dim=self.num_pixels, inputs=[self.pixels, self.target_pixels, self.loss]
459
- )
457
+ wp.launch(loss_kernel, dim=self.num_pixels, inputs=[self.pixels, self.target_pixels, self.loss])
460
458
 
461
459
  def step(self):
462
460
  if self.use_graph:
@@ -529,7 +527,7 @@ if __name__ == "__main__":
529
527
 
530
528
  if i % example.period == 0:
531
529
  example.render()
532
-
530
+
533
531
  final_image = example.get_image()
534
532
  img.imsave(output_dir + "/example_diffray_final_image.png", final_image)
535
533
 
@@ -9,7 +9,8 @@
9
9
  # Example Drone
10
10
  #
11
11
  # A drone and its 4 propellers is simulated with the goal of reaching
12
- # different targets by finding the best trajectory at each point in time.
12
+ # different targets via model-predictive control (MPC) that continuously
13
+ # optimizes the control trajectory.
13
14
  #
14
15
  ###########################################################################
15
16
 
@@ -415,15 +416,18 @@ class Drone:
415
416
 
416
417
  # Initialize the required simulation states.
417
418
  if requires_grad:
418
- self.states = tuple(self.model.state(requires_grad=True) for _ in range(state_count + 1))
419
+ self.states = tuple(self.model.state() for _ in range(state_count + 1))
420
+ self.controls = tuple(self.model.control() for _ in range(state_count))
419
421
  else:
420
422
  # When only running a forward simulation, we don't need to store
421
423
  # the history of the states at each step, instead we use double
422
424
  # buffering to represent the previous and next states.
423
425
  self.states = [self.model.state(), self.model.state()]
426
+ self.controls = (self.model.control(),)
424
427
 
425
- for state in self.states:
426
- state.prop_controls = wp.zeros(len(self.props), dtype=float, requires_grad=requires_grad)
428
+ # create array for the propeller controls
429
+ for control in self.controls:
430
+ control.prop_controls = wp.zeros(len(self.props), dtype=float, requires_grad=requires_grad)
427
431
 
428
432
  # Define the trajectories as arrays of control points.
429
433
  # The point data has an additional item to support linear interpolation.
@@ -446,6 +450,10 @@ class Drone:
446
450
  def next_state(self) -> wp.sim.State:
447
451
  return self.states[self.sim_tick + 1 if self.requires_grad else 1]
448
452
 
453
+ @property
454
+ def control(self) -> wp.sim.Control:
455
+ return self.controls[min(len(self.controls) - 1, self.sim_tick) if self.requires_grad else 0]
456
+
449
457
 
450
458
  class Example:
451
459
  def __init__(
@@ -602,7 +610,7 @@ class Example:
602
610
  drone.sim_tick / (self.sim_substep_count * self.control_point_step),
603
611
  self.control_dim,
604
612
  ),
605
- outputs=(drone.state.prop_controls,),
613
+ outputs=(drone.control.prop_controls,),
606
614
  )
607
615
 
608
616
  wp.sim.collide(drone.model, drone.state)
@@ -612,7 +620,7 @@ class Example:
612
620
  dim=len(drone.props),
613
621
  inputs=(
614
622
  drone.props,
615
- drone.state.prop_controls,
623
+ drone.control.prop_controls,
616
624
  drone.state.body_q,
617
625
  drone.model.body_com,
618
626
  ),
@@ -624,6 +632,7 @@ class Example:
624
632
  drone.state,
625
633
  drone.next_state,
626
634
  self.sim_dt,
635
+ drone.control,
627
636
  )
628
637
 
629
638
  drone.sim_tick += 1
@@ -657,7 +666,7 @@ class Example:
657
666
  self.rollouts.state.body_q,
658
667
  self.rollouts.state.body_qd,
659
668
  self.targets[self.target_idx],
660
- self.rollouts.state.prop_controls,
669
+ self.rollouts.control.prop_controls,
661
670
  i,
662
671
  self.rollout_step_count,
663
672
  1e3,
@@ -711,15 +720,13 @@ class Example:
711
720
  self.optim_graph = None
712
721
 
713
722
  if self.use_cuda_graph and self.optim_graph is None:
714
- wp.capture_begin()
715
- try:
723
+ with wp.ScopedCapture() as capture:
716
724
  self.tape = wp.Tape()
717
725
  with self.tape:
718
726
  self.forward()
719
727
  self.rollout_costs.grad.fill_(1.0)
720
728
  self.tape.backward()
721
- finally:
722
- self.optim_graph = wp.capture_end()
729
+ self.optim_graph = capture.graph
723
730
 
724
731
  # Sample control waypoints around the nominal trajectory.
725
732
  self.seed.zero_()
@@ -817,17 +824,27 @@ class Example:
817
824
 
818
825
 
819
826
  if __name__ == "__main__":
820
- stage_path = os.path.join(os.path.dirname(__file__), "example_drone.usd")
821
- drone_path = os.path.join(os.path.dirname(__file__), "..", "assets", "crazyflie.usd")
827
+ this_dir = os.path.realpath(os.path.dirname(__file__))
828
+ stage_path = os.path.join(this_dir, "example_drone.usd")
829
+ drone_path = os.path.join(this_dir, "..", "assets", "crazyflie.usd")
822
830
 
823
831
  example = Example(stage_path, drone_path, verbose=True)
824
832
  for i in range(example.frame_count):
833
+ if i > 0 and i % int((example.frame_count / len(example.targets))) == 0:
834
+ example.target_idx += 1
835
+ if example.verbose:
836
+ print(f"Choosing new flight target: {example.target_idx + 1}")
837
+
838
+ # Force recapturing the CUDA graph for the optimisation pass
839
+ # by invalidating it.
840
+ example.optim_graph = None
841
+
825
842
  example.step()
826
843
  example.render()
827
844
 
828
845
  if example.verbose:
829
846
  loss = np.min(example.rollout_costs.numpy())
830
- print(f"[{example.frame:3d}] loss={loss:.8f}")
847
+ print(f"[{i+1:3d}/{example.frame_count}] loss={loss:.8f}")
831
848
 
832
849
  if example.renderer is not None:
833
850
  example.renderer.save()
@@ -113,9 +113,7 @@ class Example:
113
113
  self.integrator = warp.sim.SemiImplicitIntegrator()
114
114
 
115
115
  # Initialize a state for each simulation step.
116
- self.states = tuple(
117
- self.model.state(requires_grad=True) for _ in range(self.frame_count * self.sim_substep_count + 1)
118
- )
116
+ self.states = tuple(self.model.state() for _ in range(self.frame_count * self.sim_substep_count + 1))
119
117
 
120
118
  # Initialize a loss value that will represent the distance of the main
121
119
  # particle to the target position. It needs to be defined as an array
@@ -126,7 +124,7 @@ class Example:
126
124
  import warp.sim.render
127
125
 
128
126
  # Helper to render the physics scene as a USD file.
129
- self.renderer = warp.sim.render.SimRenderer(self.model, stage, fps=self.fps)
127
+ self.renderer = warp.sim.render.SimRenderer(self.model, stage, fps=self.fps, scaling=10.0)
130
128
 
131
129
  # Allows rendering one simulation to USD every N training iterations.
132
130
  self.render_iteration_steps = 2
@@ -140,12 +138,12 @@ class Example:
140
138
  if self.use_graph:
141
139
  # Capture all the kernel launches into a CUDA graph so that they can
142
140
  # all be run in a single graph launch, which helps with performance.
143
- wp.capture_begin()
144
- self.tape = wp.Tape()
145
- with self.tape:
146
- self.forward()
147
- self.tape.backward(loss=self.loss)
148
- self.graph = wp.capture_end()
141
+ with wp.ScopedCapture() as capture:
142
+ self.tape = wp.Tape()
143
+ with self.tape:
144
+ self.forward()
145
+ self.tape.backward(loss=self.loss)
146
+ self.graph = capture.graph
149
147
 
150
148
  self.verbose = verbose
151
149
 
@@ -220,7 +218,7 @@ if __name__ == "__main__":
220
218
  stage_path = os.path.join(os.path.dirname(__file__), "example_spring_cage.usd")
221
219
 
222
220
  example = Example(stage_path, verbose=True)
223
-
221
+
224
222
  for iteration in range(example.train_iters):
225
223
  example.step()
226
224
 
@@ -229,10 +227,7 @@ if __name__ == "__main__":
229
227
  if example.verbose:
230
228
  print(f"[{iteration:3d}] loss={loss:.8f}")
231
229
 
232
- if (
233
- iteration == example.train_iters - 1
234
- or iteration % example.render_iteration_steps == 0
235
- ):
230
+ if iteration == example.train_iters - 1 or iteration % example.render_iteration_steps == 0:
236
231
  example.render()
237
232
 
238
233
  if example.renderer:
@@ -100,9 +100,7 @@ class Example:
100
100
 
101
101
  # initial guess
102
102
  self.actions = wp.array(
103
- np.zeros(self.episode_frames * self.action_dim) * 100.0,
104
- dtype=wp.float32,
105
- requires_grad=True
103
+ np.zeros(self.episode_frames * self.action_dim) * 100.0, dtype=wp.float32, requires_grad=True
106
104
  )
107
105
 
108
106
  self.optimizer = Adam([self.actions], lr=1e2)
@@ -115,7 +113,7 @@ class Example:
115
113
  # allocate sim states for trajectory
116
114
  self.states = []
117
115
  for _ in range(self.episode_frames + 1):
118
- self.states.append(self.model.state(requires_grad=True))
116
+ self.states.append(self.model.state())
119
117
 
120
118
  def forward(self):
121
119
  """
@@ -134,32 +132,17 @@ class Example:
134
132
  wp.sim.collide(self.model, state)
135
133
 
136
134
  # apply generalized torques to rigid body here, instead of planar joints
137
- wp.launch(
138
- apply_torque,
139
- 1,
140
- inputs=[self.actions, i * self.action_dim],
141
- outputs=[state.body_f]
142
- )
135
+ wp.launch(apply_torque, 1, inputs=[self.actions, i * self.action_dim], outputs=[state.body_f])
143
136
 
144
- state = self.integrator.simulate(self.model, state, next_state, self.sim_dt, requires_grad=True)
137
+ state = self.integrator.simulate(self.model, state, next_state, self.sim_dt)
145
138
 
146
139
  self.states[i + 1] = state
147
140
 
148
141
  # save state
149
- wp.launch(
150
- save_state,
151
- dim=1,
152
- inputs=[self.states[i + 1].body_q, i],
153
- outputs=[self.last_traj]
154
- )
142
+ wp.launch(save_state, dim=1, inputs=[self.states[i + 1].body_q, i], outputs=[self.last_traj])
155
143
 
156
144
  # compute loss
157
- wp.launch(
158
- loss_l2,
159
- dim=self.last_traj.shape,
160
- inputs=[self.last_traj, self.ref_traj],
161
- outputs=[self.loss]
162
- )
145
+ wp.launch(loss_l2, dim=self.last_traj.shape, inputs=[self.last_traj, self.ref_traj], outputs=[self.loss])
163
146
 
164
147
  def step(self):
165
148
  """Runs a single optimizer iteration"""
@@ -168,7 +151,7 @@ class Example:
168
151
  with tape:
169
152
  self.forward()
170
153
  tape.backward(loss=self.loss)
171
-
154
+
172
155
  if self.verbose and (self.iter + 1) % 10 == 0:
173
156
  print(f"Iter {self.iter+1} Loss: {self.loss.numpy()[0]:.3f}")
174
157
 
@@ -43,10 +43,6 @@ class Example:
43
43
  armature=0.1,
44
44
  stiffness=0.0,
45
45
  damping=0.0,
46
- shape_ke=1.0e4,
47
- shape_kd=1.0e2,
48
- shape_kf=1.0e2,
49
- shape_mu=1.0,
50
46
  limit_ke=1.0e4,
51
47
  limit_kd=1.0e1,
52
48
  enable_self_collisions=False,
@@ -71,8 +67,6 @@ class Example:
71
67
  # joint initial positions
72
68
  builder.joint_q[-3:] = [0.0, 0.3, 0.0]
73
69
 
74
- builder.joint_target[:3] = [0.0, 0.0, 0.0]
75
-
76
70
  # finalize model
77
71
  self.model = builder.finalize()
78
72
  self.model.ground = False
@@ -94,9 +88,9 @@ class Example:
94
88
 
95
89
  self.use_graph = wp.get_device().is_cuda
96
90
  if self.use_graph:
97
- wp.capture_begin()
98
- self.simulate()
99
- self.graph = wp.capture_end()
91
+ with wp.ScopedCapture() as capture:
92
+ self.simulate()
93
+ self.graph = capture.graph
100
94
 
101
95
  def simulate(self):
102
96
  for _ in range(self.sim_substeps):
@@ -105,28 +105,28 @@ class Example:
105
105
  kf=1.0e1,
106
106
  )
107
107
 
108
- self.model = builder.finalize()
109
- self.model.ground = True
110
- self.model.soft_contact_ke = 1.0e4
111
- self.model.soft_contact_kd = 1.0e2
112
-
113
108
  if self.integrator_type == IntegratorType.EULER:
114
109
  self.integrator = wp.sim.SemiImplicitIntegrator()
115
110
  else:
116
111
  self.integrator = wp.sim.XPBDIntegrator(iterations=1)
117
112
 
113
+ self.model = builder.finalize()
114
+ self.model.ground = True
115
+ self.model.soft_contact_ke = 1.0e4
116
+ self.model.soft_contact_kd = 1.0e2
117
+
118
118
  self.state_0 = self.model.state()
119
119
  self.state_1 = self.model.state()
120
120
 
121
121
  self.renderer = None
122
122
  if stage:
123
123
  self.renderer = wp.sim.render.SimRenderer(self.model, stage, scaling=40.0)
124
-
124
+
125
125
  self.use_graph = wp.get_device().is_cuda
126
126
  if self.use_graph:
127
- wp.capture_begin()
128
- self.simulate()
129
- self.graph = wp.capture_end()
127
+ with wp.ScopedCapture() as capture:
128
+ self.simulate()
129
+ self.graph = capture.graph
130
130
 
131
131
  def simulate(self):
132
132
  wp.sim.collide(self.model, self.state_0)
@@ -150,7 +150,7 @@ class Example:
150
150
  def render(self):
151
151
  if self.renderer is None:
152
152
  return
153
-
153
+
154
154
  with wp.ScopedTimer("render", active=True):
155
155
  self.renderer.begin_frame(self.sim_time)
156
156
  self.renderer.render(self.state_0)
@@ -68,9 +68,9 @@ class Example:
68
68
 
69
69
  self.use_graph = wp.get_device().is_cuda
70
70
  if self.use_graph:
71
- wp.capture_begin()
72
- self.simulate()
73
- self.graph = wp.capture_end()
71
+ with wp.ScopedCapture() as capture:
72
+ self.simulate()
73
+ self.graph = capture.graph
74
74
 
75
75
  def simulate(self):
76
76
  for _ in range(self.sim_substeps):
@@ -119,9 +119,11 @@ class Example:
119
119
  if stage:
120
120
  self.renderer = wp.sim.render.SimRenderer(self.model, stage, scaling=20.0)
121
121
 
122
- wp.capture_begin()
123
- self.simulate()
124
- self.graph = wp.capture_end()
122
+ self.use_graph = wp.get_device().is_cuda
123
+ if self.use_graph:
124
+ with wp.ScopedCapture() as capture:
125
+ self.simulate()
126
+ self.graph = capture.graph
125
127
 
126
128
  def simulate(self):
127
129
  for _ in range(self.sim_substeps):
@@ -135,7 +137,10 @@ class Example:
135
137
  def step(self):
136
138
  with wp.ScopedTimer("step", active=True):
137
139
  self.model.particle_grid.build(self.state_0.particle_q, self.radius * 2.0)
138
- wp.capture_launch(self.graph)
140
+ if self.use_graph:
141
+ wp.capture_launch(self.graph)
142
+ else:
143
+ self.simulate()
139
144
 
140
145
  self.sim_time += self.frame_dt
141
146
 
@@ -60,16 +60,6 @@ class Example:
60
60
  articulation_builder,
61
61
  xform=wp.transform_identity(),
62
62
  floating=False,
63
- density=0,
64
- armature=0.1,
65
- stiffness=0.0,
66
- damping=0.0,
67
- shape_ke=1.0e4,
68
- shape_kd=1.0e2,
69
- shape_kf=1.0e2,
70
- shape_mu=1.0,
71
- limit_ke=1.0e4,
72
- limit_kd=1.0e1,
73
63
  )
74
64
 
75
65
  builder = wp.sim.ModelBuilder()
@@ -62,9 +62,9 @@ class Example:
62
62
 
63
63
  self.use_graph = wp.get_device().is_cuda
64
64
  if self.use_graph:
65
- wp.capture_begin()
66
- self.simulate()
67
- self.graph = wp.capture_end()
65
+ with wp.ScopedCapture() as capture:
66
+ self.simulate()
67
+ self.graph = capture.graph
68
68
 
69
69
  def simulate(self):
70
70
  for _ in range(self.sim_substeps):
@@ -80,7 +80,7 @@ class Example:
80
80
  if self.use_graph:
81
81
  wp.capture_launch(self.graph)
82
82
  else:
83
- self.simulate()
83
+ self.simulate()
84
84
  self.sim_time += self.frame_dt
85
85
 
86
86
  def render(self):