warp-lang 0.11.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 (170) hide show
  1. warp/__init__.py +8 -0
  2. warp/bin/warp-clang.so +0 -0
  3. warp/bin/warp.so +0 -0
  4. warp/build.py +7 -6
  5. warp/build_dll.py +70 -79
  6. warp/builtins.py +10 -6
  7. warp/codegen.py +51 -19
  8. warp/config.py +7 -8
  9. warp/constants.py +3 -0
  10. warp/context.py +948 -245
  11. warp/dlpack.py +198 -113
  12. warp/examples/assets/bunny.usd +0 -0
  13. warp/examples/assets/cartpole.urdf +110 -0
  14. warp/examples/assets/crazyflie.usd +0 -0
  15. warp/examples/assets/cube.usda +42 -0
  16. warp/examples/assets/nv_ant.xml +92 -0
  17. warp/examples/assets/nv_humanoid.xml +183 -0
  18. warp/examples/assets/quadruped.urdf +268 -0
  19. warp/examples/assets/rocks.nvdb +0 -0
  20. warp/examples/assets/rocks.usd +0 -0
  21. warp/examples/assets/sphere.usda +56 -0
  22. warp/examples/assets/torus.usda +105 -0
  23. warp/examples/benchmarks/benchmark_api.py +383 -0
  24. warp/examples/benchmarks/benchmark_cloth.py +279 -0
  25. warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -0
  26. warp/examples/benchmarks/benchmark_cloth_jax.py +100 -0
  27. warp/examples/benchmarks/benchmark_cloth_numba.py +142 -0
  28. warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -0
  29. warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -0
  30. warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -0
  31. warp/examples/benchmarks/benchmark_cloth_warp.py +146 -0
  32. warp/examples/benchmarks/benchmark_launches.py +295 -0
  33. warp/examples/core/example_dem.py +221 -0
  34. warp/examples/core/example_fluid.py +267 -0
  35. warp/examples/core/example_graph_capture.py +129 -0
  36. warp/examples/core/example_marching_cubes.py +177 -0
  37. warp/examples/core/example_mesh.py +154 -0
  38. warp/examples/core/example_mesh_intersect.py +193 -0
  39. warp/examples/core/example_nvdb.py +169 -0
  40. warp/examples/core/example_raycast.py +89 -0
  41. warp/examples/core/example_raymarch.py +178 -0
  42. warp/examples/core/example_render_opengl.py +141 -0
  43. warp/examples/core/example_sph.py +389 -0
  44. warp/examples/core/example_torch.py +181 -0
  45. warp/examples/core/example_wave.py +249 -0
  46. warp/examples/fem/bsr_utils.py +380 -0
  47. warp/examples/fem/example_apic_fluid.py +391 -0
  48. warp/examples/fem/example_convection_diffusion.py +168 -0
  49. warp/examples/fem/example_convection_diffusion_dg.py +209 -0
  50. warp/examples/fem/example_convection_diffusion_dg0.py +194 -0
  51. warp/examples/fem/example_deformed_geometry.py +159 -0
  52. warp/examples/fem/example_diffusion.py +173 -0
  53. warp/examples/fem/example_diffusion_3d.py +152 -0
  54. warp/examples/fem/example_diffusion_mgpu.py +214 -0
  55. warp/examples/fem/example_mixed_elasticity.py +222 -0
  56. warp/examples/fem/example_navier_stokes.py +243 -0
  57. warp/examples/fem/example_stokes.py +192 -0
  58. warp/examples/fem/example_stokes_transfer.py +249 -0
  59. warp/examples/fem/mesh_utils.py +109 -0
  60. warp/examples/fem/plot_utils.py +287 -0
  61. warp/examples/optim/example_bounce.py +248 -0
  62. warp/examples/optim/example_cloth_throw.py +210 -0
  63. warp/examples/optim/example_diffray.py +535 -0
  64. warp/examples/optim/example_drone.py +850 -0
  65. warp/examples/optim/example_inverse_kinematics.py +169 -0
  66. warp/examples/optim/example_inverse_kinematics_torch.py +170 -0
  67. warp/examples/optim/example_spring_cage.py +234 -0
  68. warp/examples/optim/example_trajectory.py +201 -0
  69. warp/examples/sim/example_cartpole.py +128 -0
  70. warp/examples/sim/example_cloth.py +184 -0
  71. warp/examples/sim/example_granular.py +113 -0
  72. warp/examples/sim/example_granular_collision_sdf.py +185 -0
  73. warp/examples/sim/example_jacobian_ik.py +213 -0
  74. warp/examples/sim/example_particle_chain.py +106 -0
  75. warp/examples/sim/example_quadruped.py +179 -0
  76. warp/examples/sim/example_rigid_chain.py +191 -0
  77. warp/examples/sim/example_rigid_contact.py +176 -0
  78. warp/examples/sim/example_rigid_force.py +126 -0
  79. warp/examples/sim/example_rigid_gyroscopic.py +97 -0
  80. warp/examples/sim/example_rigid_soft_contact.py +124 -0
  81. warp/examples/sim/example_soft_body.py +178 -0
  82. warp/fabric.py +29 -20
  83. warp/fem/cache.py +0 -1
  84. warp/fem/dirichlet.py +0 -2
  85. warp/fem/integrate.py +0 -1
  86. warp/jax.py +45 -0
  87. warp/jax_experimental.py +339 -0
  88. warp/native/builtin.h +12 -0
  89. warp/native/bvh.cu +18 -18
  90. warp/native/clang/clang.cpp +8 -3
  91. warp/native/cuda_util.cpp +94 -5
  92. warp/native/cuda_util.h +35 -6
  93. warp/native/cutlass_gemm.cpp +1 -1
  94. warp/native/cutlass_gemm.cu +4 -1
  95. warp/native/error.cpp +66 -0
  96. warp/native/error.h +27 -0
  97. warp/native/mesh.cu +2 -2
  98. warp/native/reduce.cu +4 -4
  99. warp/native/runlength_encode.cu +2 -2
  100. warp/native/scan.cu +2 -2
  101. warp/native/sparse.cu +0 -1
  102. warp/native/temp_buffer.h +2 -2
  103. warp/native/warp.cpp +95 -60
  104. warp/native/warp.cu +1053 -218
  105. warp/native/warp.h +49 -32
  106. warp/optim/linear.py +33 -16
  107. warp/render/render_opengl.py +202 -101
  108. warp/render/render_usd.py +82 -40
  109. warp/sim/__init__.py +13 -4
  110. warp/sim/articulation.py +4 -5
  111. warp/sim/collide.py +320 -175
  112. warp/sim/import_mjcf.py +25 -30
  113. warp/sim/import_urdf.py +94 -63
  114. warp/sim/import_usd.py +51 -36
  115. warp/sim/inertia.py +3 -2
  116. warp/sim/integrator.py +233 -0
  117. warp/sim/integrator_euler.py +447 -469
  118. warp/sim/integrator_featherstone.py +1991 -0
  119. warp/sim/integrator_xpbd.py +1420 -640
  120. warp/sim/model.py +765 -487
  121. warp/sim/particles.py +2 -1
  122. warp/sim/render.py +35 -13
  123. warp/sim/utils.py +222 -11
  124. warp/stubs.py +8 -0
  125. warp/tape.py +16 -1
  126. warp/tests/aux_test_grad_customs.py +23 -0
  127. warp/tests/test_array.py +190 -1
  128. warp/tests/test_async.py +656 -0
  129. warp/tests/test_bool.py +50 -0
  130. warp/tests/test_dlpack.py +164 -11
  131. warp/tests/test_examples.py +166 -74
  132. warp/tests/test_fem.py +8 -1
  133. warp/tests/test_generics.py +15 -5
  134. warp/tests/test_grad.py +1 -1
  135. warp/tests/test_grad_customs.py +172 -12
  136. warp/tests/test_jax.py +254 -0
  137. warp/tests/test_large.py +29 -6
  138. warp/tests/test_launch.py +25 -0
  139. warp/tests/test_linear_solvers.py +20 -3
  140. warp/tests/test_matmul.py +61 -16
  141. warp/tests/test_matmul_lite.py +13 -13
  142. warp/tests/test_mempool.py +186 -0
  143. warp/tests/test_multigpu.py +3 -0
  144. warp/tests/test_options.py +16 -2
  145. warp/tests/test_peer.py +137 -0
  146. warp/tests/test_print.py +3 -1
  147. warp/tests/test_quat.py +23 -0
  148. warp/tests/test_sim_kinematics.py +97 -0
  149. warp/tests/test_snippet.py +126 -3
  150. warp/tests/test_streams.py +108 -79
  151. warp/tests/test_torch.py +16 -8
  152. warp/tests/test_utils.py +32 -27
  153. warp/tests/test_verify_fp.py +65 -0
  154. warp/tests/test_volume.py +1 -1
  155. warp/tests/unittest_serial.py +2 -0
  156. warp/tests/unittest_suites.py +12 -0
  157. warp/tests/unittest_utils.py +14 -7
  158. warp/thirdparty/unittest_parallel.py +15 -3
  159. warp/torch.py +10 -8
  160. warp/types.py +363 -246
  161. warp/utils.py +143 -19
  162. warp_lang-1.0.0.dist-info/LICENSE.md +126 -0
  163. warp_lang-1.0.0.dist-info/METADATA +394 -0
  164. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/RECORD +167 -86
  165. warp/sim/optimizer.py +0 -138
  166. warp_lang-0.11.0.dist-info/LICENSE.md +0 -36
  167. warp_lang-0.11.0.dist-info/METADATA +0 -238
  168. /warp/tests/{walkthough_debug.py → walkthrough_debug.py} +0 -0
  169. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/WHEEL +0 -0
  170. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,248 @@
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
+ # Example Sim Grad Bounce
10
+ #
11
+ # Shows how to use Warp to optimize the initial velocity of a particle
12
+ # such that it bounces off the wall and floor in order to hit a target.
13
+ #
14
+ # This example uses the built-in wp.Tape() object to compute gradients of
15
+ # the distance to target (loss) w.r.t the initial velocity, followed by
16
+ # a simple gradient-descent optimization step.
17
+ #
18
+ ###########################################################################
19
+
20
+ import os
21
+
22
+ import numpy as np
23
+
24
+ import warp as wp
25
+ import warp.sim
26
+ import warp.sim.render
27
+
28
+ wp.init()
29
+
30
+
31
+ @wp.kernel
32
+ def loss_kernel(pos: wp.array(dtype=wp.vec3), target: wp.vec3, loss: wp.array(dtype=float)):
33
+ # distance to target
34
+ delta = pos[0] - target
35
+ loss[0] = wp.dot(delta, delta)
36
+
37
+
38
+ @wp.kernel
39
+ def step_kernel(x: wp.array(dtype=wp.vec3), grad: wp.array(dtype=wp.vec3), alpha: float):
40
+ tid = wp.tid()
41
+
42
+ # gradient descent step
43
+ x[tid] = x[tid] - grad[tid] * alpha
44
+
45
+
46
+ class Example:
47
+ def __init__(self, stage=None, profile=False, verbose=False):
48
+ self.verbose = verbose
49
+
50
+ # seconds
51
+ sim_duration = 0.6
52
+
53
+ # control frequency
54
+ self.frame_dt = 1.0 / 60.0
55
+ frame_steps = int(sim_duration / self.frame_dt)
56
+
57
+ # sim frequency
58
+ self.sim_substeps = 8
59
+ self.sim_steps = frame_steps * self.sim_substeps
60
+ self.sim_dt = self.frame_dt / self.sim_substeps
61
+
62
+ self.iter = 0
63
+ self.render_time = 0.0
64
+
65
+ self.train_iters = 250
66
+ self.train_rate = 0.02
67
+
68
+ ke = 1.0e4
69
+ kf = 0.0
70
+ kd = 1.0e1
71
+ mu = 0.2
72
+
73
+ builder = wp.sim.ModelBuilder()
74
+ builder.add_particle(pos=wp.vec3(-0.5, 1.0, 0.0), vel=wp.vec3(5.0, -5.0, 0.0), mass=1.0)
75
+ builder.add_shape_box(body=-1, pos=wp.vec3(2.0, 1.0, 0.0), hx=0.25, hy=1.0, hz=1.0, ke=ke, kf=kf, kd=kd, mu=mu)
76
+
77
+ self.profile = profile
78
+
79
+ # use `requires_grad=True` to create a model for differentiable simulation
80
+ self.model = builder.finalize(requires_grad=True)
81
+ self.model.ground = True
82
+
83
+ self.model.soft_contact_ke = ke
84
+ self.model.soft_contact_kf = kf
85
+ self.model.soft_contact_kd = kd
86
+ self.model.soft_contact_mu = mu
87
+ self.model.soft_contact_margin = 10.0
88
+ self.model.soft_contact_restitution = 1.0
89
+
90
+ self.integrator = wp.sim.SemiImplicitIntegrator()
91
+
92
+ self.target = (-2.0, 1.5, 0.0)
93
+ self.loss = wp.zeros(1, dtype=wp.float32, requires_grad=True)
94
+
95
+ # allocate sim states for trajectory
96
+ self.states = []
97
+ for i in range(self.sim_steps + 1):
98
+ self.states.append(self.model.state())
99
+
100
+ # one-shot contact creation (valid if we're doing simple collision against a constant normal plane)
101
+ wp.sim.collide(self.model, self.states[0])
102
+
103
+ self.renderer = None
104
+ if stage:
105
+ self.renderer = wp.sim.render.SimRenderer(self.model, stage, scaling=1.0)
106
+
107
+ # capture forward/backward passes
108
+ self.use_graph = wp.get_device().is_cuda
109
+ if self.use_graph:
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
116
+
117
+ def forward(self):
118
+ # run control loop
119
+ for i in range(self.sim_steps):
120
+ self.states[i].clear_forces()
121
+ self.integrator.simulate(self.model, self.states[i], self.states[i + 1], self.sim_dt)
122
+
123
+ # compute loss on final state
124
+ wp.launch(loss_kernel, dim=1, inputs=[self.states[-1].particle_q, self.target, self.loss])
125
+
126
+ return self.loss
127
+
128
+ def step(self):
129
+ with wp.ScopedTimer("step", active=self.profile):
130
+ if self.use_graph:
131
+ wp.capture_launch(self.graph)
132
+ else:
133
+ self.tape = wp.Tape()
134
+ with self.tape:
135
+ self.forward()
136
+ self.tape.backward(self.loss)
137
+
138
+ # gradient descent step
139
+ x = self.states[0].particle_qd
140
+ wp.launch(step_kernel, dim=len(x), inputs=[x, x.grad, self.train_rate])
141
+
142
+ x_grad = self.tape.gradients[self.states[0].particle_qd]
143
+
144
+ if self.verbose:
145
+ print(f"Iter: {self.iter} Loss: {self.loss}")
146
+ print(f" x: {x} g: {x_grad}")
147
+
148
+ # clear grads for next iteration
149
+ self.tape.zero()
150
+
151
+ self.iter = self.iter + 1
152
+
153
+ def render(self):
154
+ if self.renderer is None:
155
+ return
156
+
157
+ with wp.ScopedTimer("render", active=self.profile):
158
+ # draw trajectory
159
+ traj_verts = [self.states[0].particle_q.numpy()[0].tolist()]
160
+
161
+ for i in range(0, self.sim_steps, self.sim_substeps):
162
+ traj_verts.append(self.states[i].particle_q.numpy()[0].tolist())
163
+
164
+ self.renderer.begin_frame(self.render_time)
165
+ self.renderer.render(self.states[i])
166
+ self.renderer.render_box(
167
+ pos=self.target,
168
+ rot=wp.quat_identity(),
169
+ extents=(0.1, 0.1, 0.1),
170
+ name="target",
171
+ color=(0.0, 0.0, 0.0),
172
+ )
173
+ self.renderer.render_line_strip(
174
+ vertices=traj_verts,
175
+ color=wp.render.bourke_color_map(0.0, 7.0, self.loss.numpy()[0]),
176
+ radius=0.02,
177
+ name=f"traj_{self.iter-1}",
178
+ )
179
+ self.renderer.end_frame()
180
+
181
+ from pxr import Gf, UsdGeom
182
+
183
+ particles_prim = self.renderer.stage.GetPrimAtPath("/root/particles")
184
+ particles = UsdGeom.Points.Get(self.renderer.stage, particles_prim.GetPath())
185
+ particles.CreateDisplayColorAttr().Set([Gf.Vec3f(1.0, 1.0, 1.0)], time=self.renderer.time)
186
+
187
+ self.render_time += self.frame_dt
188
+
189
+ def check_grad(self):
190
+ param = self.states[0].particle_qd
191
+
192
+ # initial value
193
+ x_c = param.numpy().flatten()
194
+
195
+ # compute numeric gradient
196
+ x_grad_numeric = np.zeros_like(x_c)
197
+
198
+ for i in range(len(x_c)):
199
+ eps = 1.0e-3
200
+
201
+ step = np.zeros_like(x_c)
202
+ step[i] = eps
203
+
204
+ x_1 = x_c + step
205
+ x_0 = x_c - step
206
+
207
+ param.assign(x_1)
208
+ l_1 = self.forward().numpy()[0]
209
+
210
+ param.assign(x_0)
211
+ l_0 = self.forward().numpy()[0]
212
+
213
+ dldx = (l_1 - l_0) / (eps * 2.0)
214
+
215
+ x_grad_numeric[i] = dldx
216
+
217
+ # reset initial state
218
+ param.assign(x_c)
219
+
220
+ # compute analytic gradient
221
+ tape = wp.Tape()
222
+ with tape:
223
+ l = self.forward()
224
+
225
+ tape.backward(l)
226
+
227
+ x_grad_analytic = tape.gradients[param]
228
+
229
+ print(f"numeric grad: {x_grad_numeric}")
230
+ print(f"analytic grad: {x_grad_analytic}")
231
+
232
+ tape.zero()
233
+
234
+
235
+ if __name__ == "__main__":
236
+ stage_path = os.path.join(os.path.dirname(__file__), "example_bounce.usd")
237
+
238
+ example = Example(stage_path, profile=False, verbose=True)
239
+ example.check_grad()
240
+
241
+ # replay and optimize
242
+ for i in range(example.train_iters):
243
+ example.step()
244
+ if i % 16 == 0:
245
+ example.render()
246
+
247
+ if example.renderer:
248
+ example.renderer.save()
@@ -0,0 +1,210 @@
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
+ # Example Sim Grad Cloth
10
+ #
11
+ # Shows how to use Warp to optimize the initial velocities of a piece of
12
+ # cloth such that its center of mass hits a target after a specified time.
13
+ #
14
+ # This example uses the built-in wp.Tape() object to compute gradients of
15
+ # the distance to target (loss) w.r.t the initial velocity, followed by
16
+ # a simple gradient-descent optimization step.
17
+ #
18
+ ###########################################################################
19
+
20
+ import math
21
+ import os
22
+
23
+ import warp as wp
24
+ import warp.sim
25
+ import warp.sim.render
26
+
27
+ wp.init()
28
+
29
+
30
+ @wp.kernel
31
+ def com_kernel(positions: wp.array(dtype=wp.vec3), n: int, com: wp.array(dtype=wp.vec3)):
32
+ tid = wp.tid()
33
+
34
+ # compute center of mass
35
+ wp.atomic_add(com, 0, positions[tid] / float(n))
36
+
37
+
38
+ @wp.kernel
39
+ def loss_kernel(com: wp.array(dtype=wp.vec3), target: wp.vec3, loss: wp.array(dtype=float)):
40
+ # sq. distance to target
41
+ delta = com[0] - target
42
+
43
+ loss[0] = wp.dot(delta, delta)
44
+
45
+
46
+ @wp.kernel
47
+ def step_kernel(x: wp.array(dtype=wp.vec3), grad: wp.array(dtype=wp.vec3), alpha: float):
48
+ tid = wp.tid()
49
+
50
+ # gradient descent step
51
+ x[tid] = x[tid] - grad[tid] * alpha
52
+
53
+
54
+ class Example:
55
+ def __init__(self, stage, profile=False, verbose=False):
56
+ self.verbose = verbose
57
+
58
+ # seconds
59
+ sim_duration = 2.0
60
+
61
+ # control frequency
62
+ self.frame_dt = 1.0 / 60.0
63
+ frame_steps = int(sim_duration / self.frame_dt)
64
+
65
+ # sim frequency
66
+ self.sim_substeps = 16
67
+ self.sim_steps = frame_steps * self.sim_substeps
68
+ self.sim_dt = self.frame_dt / self.sim_substeps
69
+
70
+ self.iter = 0
71
+ self.render_time = 0.0
72
+
73
+ self.train_iters = 64
74
+ self.train_rate = 5.0
75
+
76
+ builder = wp.sim.ModelBuilder()
77
+ builder.default_particle_radius = 0.01
78
+
79
+ dim_x = 16
80
+ dim_y = 16
81
+
82
+ builder.add_cloth_grid(
83
+ pos=wp.vec3(0.0, 0.0, 0.0),
84
+ vel=wp.vec3(0.1, 0.1, 0.0),
85
+ rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), -math.pi * 0.25),
86
+ dim_x=dim_x,
87
+ dim_y=dim_y,
88
+ cell_x=1.0 / dim_x,
89
+ cell_y=1.0 / dim_y,
90
+ mass=1.0,
91
+ tri_ke=10000.0,
92
+ tri_ka=10000.0,
93
+ tri_kd=100.0,
94
+ tri_lift=10.0,
95
+ tri_drag=5.0,
96
+ )
97
+
98
+ self.profile = profile
99
+
100
+ self.model = builder.finalize()
101
+ self.model.ground = False
102
+
103
+ self.integrator = wp.sim.SemiImplicitIntegrator()
104
+
105
+ self.target = (8.0, 0.0, 0.0)
106
+ self.com = wp.zeros(1, dtype=wp.vec3, requires_grad=True)
107
+ self.loss = wp.zeros(1, dtype=wp.float32, requires_grad=True)
108
+
109
+ # allocate sim states for trajectory
110
+ self.states = []
111
+ for i in range(self.sim_steps + 1):
112
+ self.states.append(self.model.state(requires_grad=True))
113
+
114
+ self.renderer = None
115
+ if stage:
116
+ self.renderer = wp.sim.render.SimRenderer(self.model, stage, scaling=4.0)
117
+
118
+ # capture forward/backward passes
119
+ self.use_graph = wp.get_device().is_cuda
120
+ if self.use_graph:
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
+
128
+ def forward(self):
129
+ # run control loop
130
+ for i in range(self.sim_steps):
131
+ self.states[i].clear_forces()
132
+
133
+ self.integrator.simulate(self.model, self.states[i], self.states[i + 1], self.sim_dt)
134
+
135
+ # compute loss on final state
136
+ self.com.zero_()
137
+ wp.launch(
138
+ com_kernel,
139
+ dim=self.model.particle_count,
140
+ inputs=[self.states[-1].particle_q, self.model.particle_count, self.com],
141
+ )
142
+ wp.launch(loss_kernel, dim=1, inputs=[self.com, self.target, self.loss])
143
+
144
+ def step(self):
145
+ with wp.ScopedTimer("step", active=self.profile):
146
+ if self.use_graph:
147
+ wp.capture_launch(self.graph)
148
+ else:
149
+ self.tape = wp.Tape()
150
+ with self.tape:
151
+ self.forward()
152
+ self.tape.backward(self.loss)
153
+
154
+ # gradient descent step
155
+ x = self.states[0].particle_qd
156
+
157
+ if self.verbose:
158
+ print(f"Iter: {self.iter} Loss: {self.loss}")
159
+
160
+ wp.launch(step_kernel, dim=len(x), inputs=[x, x.grad, self.train_rate])
161
+
162
+ # clear grads for next iteration
163
+ self.tape.zero()
164
+
165
+ self.iter = self.iter + 1
166
+
167
+ def render(self):
168
+ if self.renderer is None:
169
+ return
170
+
171
+ with wp.ScopedTimer("render", active=self.profile):
172
+ # draw trajectory
173
+ traj_verts = [self.states[0].particle_q.numpy().mean(axis=0)]
174
+
175
+ for i in range(0, self.sim_steps, self.sim_substeps):
176
+ traj_verts.append(self.states[i].particle_q.numpy().mean(axis=0))
177
+
178
+ self.renderer.begin_frame(self.render_time)
179
+ self.renderer.render(self.states[i])
180
+ self.renderer.render_box(
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),
186
+ )
187
+ self.renderer.render_line_strip(
188
+ vertices=traj_verts,
189
+ color=wp.render.bourke_color_map(0.0, 269.0, self.loss.numpy()[0]),
190
+ radius=0.02,
191
+ name=f"traj_{self.iter-1}",
192
+ )
193
+ self.renderer.end_frame()
194
+
195
+ self.render_time += self.frame_dt
196
+
197
+
198
+ if __name__ == "__main__":
199
+ stage_path = os.path.join(os.path.dirname(__file__), "example_cloth_throw.usd")
200
+
201
+ example = Example(stage_path, profile=False, verbose=True)
202
+
203
+ # replay and optimize
204
+ for i in range(example.train_iters):
205
+ example.step()
206
+ if i % 4 == 0:
207
+ example.render()
208
+
209
+ if example.renderer:
210
+ example.renderer.save()