warp-lang 1.0.0b2__py3-none-win_amd64.whl → 1.0.0b6__py3-none-win_amd64.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 (271) hide show
  1. docs/conf.py +17 -5
  2. examples/env/env_ant.py +1 -1
  3. examples/env/env_cartpole.py +1 -1
  4. examples/env/env_humanoid.py +1 -1
  5. examples/env/env_usd.py +4 -1
  6. examples/env/environment.py +8 -9
  7. examples/example_dem.py +34 -33
  8. examples/example_diffray.py +364 -337
  9. examples/example_fluid.py +32 -23
  10. examples/example_jacobian_ik.py +97 -93
  11. examples/example_marching_cubes.py +6 -16
  12. examples/example_mesh.py +6 -16
  13. examples/example_mesh_intersect.py +16 -14
  14. examples/example_nvdb.py +14 -16
  15. examples/example_raycast.py +14 -13
  16. examples/example_raymarch.py +16 -23
  17. examples/example_render_opengl.py +19 -10
  18. examples/example_sim_cartpole.py +82 -78
  19. examples/example_sim_cloth.py +45 -48
  20. examples/example_sim_fk_grad.py +51 -44
  21. examples/example_sim_fk_grad_torch.py +47 -40
  22. examples/example_sim_grad_bounce.py +108 -133
  23. examples/example_sim_grad_cloth.py +99 -113
  24. examples/example_sim_granular.py +5 -6
  25. examples/{example_sim_sdf_shape.py → example_sim_granular_collision_sdf.py} +37 -26
  26. examples/example_sim_neo_hookean.py +51 -55
  27. examples/example_sim_particle_chain.py +4 -4
  28. examples/example_sim_quadruped.py +126 -81
  29. examples/example_sim_rigid_chain.py +54 -61
  30. examples/example_sim_rigid_contact.py +66 -70
  31. examples/example_sim_rigid_fem.py +3 -3
  32. examples/example_sim_rigid_force.py +1 -1
  33. examples/example_sim_rigid_gyroscopic.py +3 -4
  34. examples/example_sim_rigid_kinematics.py +28 -39
  35. examples/example_sim_trajopt.py +112 -110
  36. examples/example_sph.py +9 -8
  37. examples/example_wave.py +7 -7
  38. examples/fem/bsr_utils.py +30 -17
  39. examples/fem/example_apic_fluid.py +85 -69
  40. examples/fem/example_convection_diffusion.py +97 -93
  41. examples/fem/example_convection_diffusion_dg.py +142 -149
  42. examples/fem/example_convection_diffusion_dg0.py +141 -136
  43. examples/fem/example_deformed_geometry.py +146 -0
  44. examples/fem/example_diffusion.py +115 -84
  45. examples/fem/example_diffusion_3d.py +116 -86
  46. examples/fem/example_diffusion_mgpu.py +102 -79
  47. examples/fem/example_mixed_elasticity.py +139 -100
  48. examples/fem/example_navier_stokes.py +175 -162
  49. examples/fem/example_stokes.py +143 -111
  50. examples/fem/example_stokes_transfer.py +186 -157
  51. examples/fem/mesh_utils.py +59 -97
  52. examples/fem/plot_utils.py +138 -17
  53. tools/ci/publishing/build_nodes_info.py +54 -0
  54. warp/__init__.py +4 -3
  55. warp/__init__.pyi +1 -0
  56. warp/bin/warp-clang.dll +0 -0
  57. warp/bin/warp.dll +0 -0
  58. warp/build.py +5 -3
  59. warp/build_dll.py +29 -9
  60. warp/builtins.py +836 -492
  61. warp/codegen.py +864 -553
  62. warp/config.py +3 -1
  63. warp/context.py +389 -172
  64. warp/fem/__init__.py +24 -6
  65. warp/fem/cache.py +318 -25
  66. warp/fem/dirichlet.py +7 -3
  67. warp/fem/domain.py +14 -0
  68. warp/fem/field/__init__.py +30 -38
  69. warp/fem/field/field.py +149 -0
  70. warp/fem/field/nodal_field.py +244 -138
  71. warp/fem/field/restriction.py +8 -6
  72. warp/fem/field/test.py +127 -59
  73. warp/fem/field/trial.py +117 -60
  74. warp/fem/geometry/__init__.py +5 -1
  75. warp/fem/geometry/deformed_geometry.py +271 -0
  76. warp/fem/geometry/element.py +24 -1
  77. warp/fem/geometry/geometry.py +86 -14
  78. warp/fem/geometry/grid_2d.py +112 -54
  79. warp/fem/geometry/grid_3d.py +134 -65
  80. warp/fem/geometry/hexmesh.py +953 -0
  81. warp/fem/geometry/partition.py +85 -33
  82. warp/fem/geometry/quadmesh_2d.py +532 -0
  83. warp/fem/geometry/tetmesh.py +451 -115
  84. warp/fem/geometry/trimesh_2d.py +197 -92
  85. warp/fem/integrate.py +534 -268
  86. warp/fem/operator.py +58 -31
  87. warp/fem/polynomial.py +11 -0
  88. warp/fem/quadrature/__init__.py +1 -1
  89. warp/fem/quadrature/pic_quadrature.py +150 -58
  90. warp/fem/quadrature/quadrature.py +209 -57
  91. warp/fem/space/__init__.py +230 -53
  92. warp/fem/space/basis_space.py +489 -0
  93. warp/fem/space/collocated_function_space.py +105 -0
  94. warp/fem/space/dof_mapper.py +49 -2
  95. warp/fem/space/function_space.py +90 -39
  96. warp/fem/space/grid_2d_function_space.py +149 -496
  97. warp/fem/space/grid_3d_function_space.py +173 -538
  98. warp/fem/space/hexmesh_function_space.py +352 -0
  99. warp/fem/space/partition.py +129 -76
  100. warp/fem/space/quadmesh_2d_function_space.py +369 -0
  101. warp/fem/space/restriction.py +46 -34
  102. warp/fem/space/shape/__init__.py +15 -0
  103. warp/fem/space/shape/cube_shape_function.py +738 -0
  104. warp/fem/space/shape/shape_function.py +103 -0
  105. warp/fem/space/shape/square_shape_function.py +611 -0
  106. warp/fem/space/shape/tet_shape_function.py +567 -0
  107. warp/fem/space/shape/triangle_shape_function.py +429 -0
  108. warp/fem/space/tetmesh_function_space.py +132 -1039
  109. warp/fem/space/topology.py +295 -0
  110. warp/fem/space/trimesh_2d_function_space.py +104 -742
  111. warp/fem/types.py +13 -11
  112. warp/fem/utils.py +335 -60
  113. warp/native/array.h +120 -34
  114. warp/native/builtin.h +101 -72
  115. warp/native/bvh.cpp +73 -325
  116. warp/native/bvh.cu +406 -23
  117. warp/native/bvh.h +22 -40
  118. warp/native/clang/clang.cpp +1 -0
  119. warp/native/crt.h +2 -0
  120. warp/native/cuda_util.cpp +8 -3
  121. warp/native/cuda_util.h +1 -0
  122. warp/native/exports.h +1522 -1243
  123. warp/native/intersect.h +19 -4
  124. warp/native/intersect_adj.h +8 -8
  125. warp/native/mat.h +76 -17
  126. warp/native/mesh.cpp +33 -108
  127. warp/native/mesh.cu +114 -18
  128. warp/native/mesh.h +395 -40
  129. warp/native/noise.h +272 -329
  130. warp/native/quat.h +51 -8
  131. warp/native/rand.h +44 -34
  132. warp/native/reduce.cpp +1 -1
  133. warp/native/sparse.cpp +4 -4
  134. warp/native/sparse.cu +163 -155
  135. warp/native/spatial.h +2 -2
  136. warp/native/temp_buffer.h +18 -14
  137. warp/native/vec.h +103 -21
  138. warp/native/warp.cpp +2 -1
  139. warp/native/warp.cu +28 -3
  140. warp/native/warp.h +4 -3
  141. warp/render/render_opengl.py +261 -109
  142. warp/sim/__init__.py +1 -2
  143. warp/sim/articulation.py +385 -185
  144. warp/sim/import_mjcf.py +59 -48
  145. warp/sim/import_urdf.py +15 -15
  146. warp/sim/import_usd.py +174 -102
  147. warp/sim/inertia.py +17 -18
  148. warp/sim/integrator_xpbd.py +4 -3
  149. warp/sim/model.py +330 -250
  150. warp/sim/render.py +1 -1
  151. warp/sparse.py +625 -152
  152. warp/stubs.py +341 -309
  153. warp/tape.py +9 -6
  154. warp/tests/__main__.py +3 -6
  155. warp/tests/assets/curlnoise_golden.npy +0 -0
  156. warp/tests/assets/pnoise_golden.npy +0 -0
  157. warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
  158. warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
  159. warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
  160. warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
  161. warp/tests/aux_test_unresolved_func.py +14 -0
  162. warp/tests/aux_test_unresolved_symbol.py +14 -0
  163. warp/tests/disabled_kinematics.py +239 -0
  164. warp/tests/run_coverage_serial.py +31 -0
  165. warp/tests/test_adam.py +103 -106
  166. warp/tests/test_arithmetic.py +94 -74
  167. warp/tests/test_array.py +82 -101
  168. warp/tests/test_array_reduce.py +57 -23
  169. warp/tests/test_atomic.py +64 -28
  170. warp/tests/test_bool.py +22 -12
  171. warp/tests/test_builtins_resolution.py +1292 -0
  172. warp/tests/test_bvh.py +18 -18
  173. warp/tests/test_closest_point_edge_edge.py +54 -57
  174. warp/tests/test_codegen.py +165 -134
  175. warp/tests/test_compile_consts.py +28 -20
  176. warp/tests/test_conditional.py +108 -24
  177. warp/tests/test_copy.py +10 -12
  178. warp/tests/test_ctypes.py +112 -88
  179. warp/tests/test_dense.py +21 -14
  180. warp/tests/test_devices.py +98 -0
  181. warp/tests/test_dlpack.py +75 -75
  182. warp/tests/test_examples.py +237 -0
  183. warp/tests/test_fabricarray.py +22 -24
  184. warp/tests/test_fast_math.py +15 -11
  185. warp/tests/test_fem.py +1034 -124
  186. warp/tests/test_fp16.py +23 -16
  187. warp/tests/test_func.py +187 -86
  188. warp/tests/test_generics.py +194 -49
  189. warp/tests/test_grad.py +123 -181
  190. warp/tests/test_grad_customs.py +176 -0
  191. warp/tests/test_hash_grid.py +35 -34
  192. warp/tests/test_import.py +10 -23
  193. warp/tests/test_indexedarray.py +24 -25
  194. warp/tests/test_intersect.py +18 -9
  195. warp/tests/test_large.py +141 -0
  196. warp/tests/test_launch.py +14 -41
  197. warp/tests/test_lerp.py +64 -65
  198. warp/tests/test_lvalue.py +493 -0
  199. warp/tests/test_marching_cubes.py +12 -13
  200. warp/tests/test_mat.py +517 -2898
  201. warp/tests/test_mat_lite.py +115 -0
  202. warp/tests/test_mat_scalar_ops.py +2889 -0
  203. warp/tests/test_math.py +103 -9
  204. warp/tests/test_matmul.py +304 -69
  205. warp/tests/test_matmul_lite.py +410 -0
  206. warp/tests/test_mesh.py +60 -22
  207. warp/tests/test_mesh_query_aabb.py +21 -25
  208. warp/tests/test_mesh_query_point.py +111 -22
  209. warp/tests/test_mesh_query_ray.py +12 -24
  210. warp/tests/test_mlp.py +30 -22
  211. warp/tests/test_model.py +92 -89
  212. warp/tests/test_modules_lite.py +39 -0
  213. warp/tests/test_multigpu.py +88 -114
  214. warp/tests/test_noise.py +12 -11
  215. warp/tests/test_operators.py +16 -20
  216. warp/tests/test_options.py +11 -11
  217. warp/tests/test_pinned.py +17 -18
  218. warp/tests/test_print.py +32 -11
  219. warp/tests/test_quat.py +275 -129
  220. warp/tests/test_rand.py +18 -16
  221. warp/tests/test_reload.py +38 -34
  222. warp/tests/test_rounding.py +50 -43
  223. warp/tests/test_runlength_encode.py +168 -20
  224. warp/tests/test_smoothstep.py +9 -11
  225. warp/tests/test_snippet.py +143 -0
  226. warp/tests/test_sparse.py +261 -63
  227. warp/tests/test_spatial.py +276 -243
  228. warp/tests/test_streams.py +110 -85
  229. warp/tests/test_struct.py +268 -63
  230. warp/tests/test_tape.py +39 -21
  231. warp/tests/test_torch.py +90 -86
  232. warp/tests/test_transient_module.py +10 -12
  233. warp/tests/test_types.py +363 -0
  234. warp/tests/test_utils.py +451 -0
  235. warp/tests/test_vec.py +354 -2050
  236. warp/tests/test_vec_lite.py +73 -0
  237. warp/tests/test_vec_scalar_ops.py +2099 -0
  238. warp/tests/test_volume.py +418 -376
  239. warp/tests/test_volume_write.py +124 -134
  240. warp/tests/unittest_serial.py +35 -0
  241. warp/tests/unittest_suites.py +291 -0
  242. warp/tests/unittest_utils.py +342 -0
  243. warp/tests/{test_misc.py → unused_test_misc.py} +13 -5
  244. warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
  245. warp/thirdparty/appdirs.py +36 -45
  246. warp/thirdparty/unittest_parallel.py +589 -0
  247. warp/types.py +622 -211
  248. warp/utils.py +54 -393
  249. warp_lang-1.0.0b6.dist-info/METADATA +238 -0
  250. warp_lang-1.0.0b6.dist-info/RECORD +409 -0
  251. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/WHEEL +1 -1
  252. examples/example_cache_management.py +0 -40
  253. examples/example_multigpu.py +0 -54
  254. examples/example_struct.py +0 -65
  255. examples/fem/example_stokes_transfer_3d.py +0 -210
  256. warp/bin/warp-clang.so +0 -0
  257. warp/bin/warp.so +0 -0
  258. warp/fem/field/discrete_field.py +0 -80
  259. warp/fem/space/nodal_function_space.py +0 -233
  260. warp/tests/test_all.py +0 -223
  261. warp/tests/test_array_scan.py +0 -60
  262. warp/tests/test_base.py +0 -208
  263. warp/tests/test_unresolved_func.py +0 -7
  264. warp/tests/test_unresolved_symbol.py +0 -7
  265. warp_lang-1.0.0b2.dist-info/METADATA +0 -26
  266. warp_lang-1.0.0b2.dist-info/RECORD +0 -380
  267. /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
  268. /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
  269. /warp/tests/{test_square.py → aux_test_square.py} +0 -0
  270. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
  271. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
@@ -6,20 +6,22 @@
6
6
  # license agreement from NVIDIA CORPORATION is strictly prohibited.
7
7
 
8
8
  ###########################################################################
9
- # Example Sim Granular
9
+ # Example Sim Granular Collision SDF
10
10
  #
11
11
  # Shows how to set up a particle-based granular material model using the
12
- # wp.sim.ModelBuilder().
12
+ # wp.sim.ModelBuilder(). This version shows how to create collision geometry
13
+ # objects from SDFs.
13
14
  #
14
15
  ###########################################################################
15
16
 
17
+ import math
16
18
  import os
17
19
 
20
+ import numpy as np
21
+
18
22
  import warp as wp
19
23
  import warp.sim
20
24
  import warp.sim.render
21
- import math
22
- import numpy as np
23
25
 
24
26
  wp.init()
25
27
 
@@ -46,25 +48,29 @@ class Example:
46
48
  cell_x=self.radius * 2.0,
47
49
  cell_y=self.radius * 2.0,
48
50
  cell_z=self.radius * 2.0,
49
- pos=(0.0, 20.0, 0.0),
51
+ pos=wp.vec3(0.0, 20.0, 0.0),
50
52
  rot=wp.quat_identity(),
51
- vel=(2.0, 0.0, 0.0),
53
+ vel=wp.vec3(2.0, 0.0, 0.0),
52
54
  mass=0.1,
53
55
  jitter=self.radius * 0.1,
54
56
  )
55
- rock_vdb = wp.Volume.load_from_nvdb(
56
- open(os.path.join(os.path.dirname(__file__), "assets/rocks.nvdb"), "rb").read())
57
+ rock_file = open(os.path.join(os.path.dirname(__file__), "assets/rocks.nvdb"), "rb")
58
+ rock_vdb = wp.Volume.load_from_nvdb(rock_file.read())
59
+ rock_file.close()
60
+
57
61
  rock_sdf = wp.sim.SDF(rock_vdb)
58
- s = builder.add_shape_sdf(
62
+
63
+ builder.add_shape_sdf(
59
64
  ke=1.0e4,
60
65
  kd=1000.0,
61
66
  kf=1000.0,
62
67
  mu=0.5,
63
68
  sdf=rock_sdf,
64
69
  body=-1,
65
- pos=(0.0, 0.0, 0.0),
66
- rot=wp.quat_from_axis_angle((1.0, 0.0, 0.0), -0.5 * math.pi),
67
- scale=(0.01, 0.01, 0.01))
70
+ pos=wp.vec3(0.0, 0.0, 0.0),
71
+ rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), -0.5 * math.pi),
72
+ scale=wp.vec3(0.01, 0.01, 0.01),
73
+ )
68
74
 
69
75
  mins = np.array([-3.0, -3.0, -3.0])
70
76
  voxel_size = 0.2
@@ -83,10 +89,10 @@ class Example:
83
89
  sphere_vdb = wp.Volume.load_from_numpy(sphere_sdf_np, mins, voxel_size, rad + 3.0 * voxel_size)
84
90
  sphere_sdf = wp.sim.SDF(sphere_vdb)
85
91
 
86
- self.sphere_pos = (3.0, 15.0, 0.0)
92
+ self.sphere_pos = wp.vec3(3.0, 15.0, 0.0)
87
93
  self.sphere_scale = 1.0
88
94
  self.sphere_radius = rad
89
- s = builder.add_shape_sdf(
95
+ builder.add_shape_sdf(
90
96
  ke=1.0e4,
91
97
  kd=1000.0,
92
98
  kf=1000.0,
@@ -94,7 +100,8 @@ class Example:
94
100
  sdf=sphere_sdf,
95
101
  body=-1,
96
102
  pos=self.sphere_pos,
97
- scale=(self.sphere_scale, self.sphere_scale, self.sphere_scale))
103
+ scale=wp.vec3(self.sphere_scale, self.sphere_scale, self.sphere_scale),
104
+ )
98
105
 
99
106
  self.model = builder.finalize()
100
107
  self.model.particle_kf = 25.0
@@ -113,7 +120,7 @@ class Example:
113
120
  with wp.ScopedTimer("simulate", active=True):
114
121
  self.model.particle_grid.build(self.state_0.particle_q, self.radius * 2.0)
115
122
 
116
- for s in range(self.sim_substeps):
123
+ for _ in range(self.sim_substeps):
117
124
  self.state_0.clear_forces()
118
125
  wp.sim.collide(self.model, self.state_0)
119
126
  self.integrator.simulate(self.model, self.state_0, self.state_1, self.sim_dt)
@@ -121,37 +128,41 @@ class Example:
121
128
  # swap states
122
129
  (self.state_0, self.state_1) = (self.state_1, self.state_0)
123
130
 
131
+ self.sim_time += self.frame_dt
132
+
124
133
  def render(self, is_live=False):
125
134
  with wp.ScopedTimer("render", active=True):
126
135
  time = 0.0 if is_live else self.sim_time
127
136
 
128
137
  self.renderer.begin_frame(time)
129
138
 
130
- # Note the extra wp.quat_from_axis_angle((1.0, 0.0, 0.0), math.pi) is because .usd is oriented differently from .nvdb
139
+ # Note the extra wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), math.pi) is because .usd is oriented differently from .nvdb
131
140
  self.renderer.render_ref(
132
141
  name="collision",
133
142
  path=os.path.join(os.path.dirname(__file__), "assets/rocks.usd"),
134
- pos=(0.0, 0.0, 0.0),
135
- rot=wp.quat_from_axis_angle((1.0, 0.0, 0.0), -0.5 * math.pi) *
136
- wp.quat_from_axis_angle((1.0, 0.0, 0.0), math.pi),
137
- scale=(0.01, 0.01, 0.01),
143
+ pos=wp.vec3(0.0, 0.0, 0.0),
144
+ rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), -0.5 * math.pi)
145
+ * wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), math.pi),
146
+ scale=wp.vec3(0.01, 0.01, 0.01),
138
147
  )
139
148
 
140
- self.renderer.render_sphere(name="sphere", pos=self.sphere_pos,
141
- radius=self.sphere_scale * self.sphere_radius, rot=(0.0, 0.0, 0.0, 1.0))
149
+ self.renderer.render_sphere(
150
+ name="sphere",
151
+ pos=self.sphere_pos,
152
+ radius=self.sphere_scale * self.sphere_radius,
153
+ rot=wp.quat(0.0, 0.0, 0.0, 1.0),
154
+ )
142
155
 
143
156
  self.renderer.render(self.state_0)
144
157
  self.renderer.end_frame()
145
158
 
146
- self.sim_time += self.frame_dt
147
-
148
159
 
149
160
  if __name__ == "__main__":
150
161
  stage_path = os.path.join(os.path.dirname(__file__), "outputs/example_sim_sdf_shape.usd")
151
162
 
152
163
  example = Example(stage_path)
153
164
 
154
- for i in range(example.frame_count):
165
+ for _ in range(example.frame_count):
155
166
  example.update()
156
167
  example.render()
157
168
 
@@ -13,8 +13,8 @@
13
13
  #
14
14
  ###########################################################################
15
15
 
16
- import os
17
16
  import math
17
+ import os
18
18
 
19
19
  import warp as wp
20
20
  import warp.sim
@@ -23,22 +23,54 @@ import warp.sim.render
23
23
  wp.init()
24
24
 
25
25
 
26
+ @wp.kernel
27
+ def twist_points(
28
+ rest: wp.array(dtype=wp.vec3), points: wp.array(dtype=wp.vec3), mass: wp.array(dtype=float), xform: wp.transform
29
+ ):
30
+ tid = wp.tid()
31
+
32
+ r = rest[tid]
33
+ p = points[tid]
34
+ m = mass[tid]
35
+
36
+ # twist the top layer of particles in the beam
37
+ if m == 0 and p[1] != 0.0:
38
+ points[tid] = wp.transform_point(xform, r)
39
+
40
+
41
+ @wp.kernel
42
+ def compute_volume(points: wp.array(dtype=wp.vec3), indices: wp.array2d(dtype=int), volume: wp.array(dtype=float)):
43
+ tid = wp.tid()
44
+
45
+ i = indices[tid, 0]
46
+ j = indices[tid, 1]
47
+ k = indices[tid, 2]
48
+ l = indices[tid, 3]
49
+
50
+ x0 = points[i]
51
+ x1 = points[j]
52
+ x2 = points[k]
53
+ x3 = points[l]
54
+
55
+ x10 = x1 - x0
56
+ x20 = x2 - x0
57
+ x30 = x3 - x0
58
+
59
+ v = wp.dot(x10, wp.cross(x20, x30)) / 6.0
60
+
61
+ wp.atomic_add(volume, 0, v)
62
+
63
+
26
64
  class Example:
27
65
  def __init__(self, stage):
28
- self.sim_width = 8
29
- self.sim_height = 8
30
-
31
- self.sim_fps = 60.0
66
+ sim_fps = 60.0
32
67
  self.sim_substeps = 64
33
- self.sim_duration = 5.0
34
- self.sim_frames = int(self.sim_duration * self.sim_fps)
35
- self.sim_dt = (1.0 / self.sim_fps) / self.sim_substeps
68
+ sim_duration = 5.0
69
+ self.sim_frames = int(sim_duration * sim_fps)
70
+ self.sim_dt = (1.0 / sim_fps) / self.sim_substeps
36
71
  self.sim_time = 0.0
37
- self.sim_render = True
38
- self.sim_iterations = 1
39
- self.sim_relaxation = 1.0
40
- self.lift_speed = 2.5 / self.sim_duration * 2.0 # from Smith et al.
41
- self.rot_speed = math.pi / self.sim_duration
72
+ self.lift_speed = 2.5 / sim_duration * 2.0 # from Smith et al.
73
+ self.rot_speed = math.pi / sim_duration
42
74
 
43
75
  builder = wp.sim.ModelBuilder()
44
76
 
@@ -48,9 +80,9 @@ class Example:
48
80
  center = cell_size * cell_dim * 0.5
49
81
 
50
82
  builder.add_soft_grid(
51
- pos=(-center, 0.0, -center),
83
+ pos=wp.vec3(-center, 0.0, -center),
52
84
  rot=wp.quat_identity(),
53
- vel=(0.0, 0.0, 0.0),
85
+ vel=wp.vec3(0.0, 0.0, 0.0),
54
86
  dim_x=cell_dim,
55
87
  dim_y=cell_dim,
56
88
  dim_z=cell_dim,
@@ -85,15 +117,15 @@ class Example:
85
117
  with wp.ScopedTimer("simulate"):
86
118
  xform = wp.transform(
87
119
  (0.0, self.lift_speed * self.sim_time, 0.0),
88
- wp.quat_from_axis_angle((0.0, 1.0, 0.0), self.rot_speed * self.sim_time),
120
+ wp.quat_from_axis_angle(wp.vec3(0.0, 1.0, 0.0), self.rot_speed * self.sim_time),
89
121
  )
90
122
  wp.launch(
91
- kernel=self.twist_points,
123
+ kernel=twist_points,
92
124
  dim=len(self.state_0.particle_q),
93
125
  inputs=[self.rest.particle_q, self.state_0.particle_q, self.model.particle_mass, xform],
94
126
  )
95
127
 
96
- for s in range(self.sim_substeps):
128
+ for _ in range(self.sim_substeps):
97
129
  self.state_0.clear_forces()
98
130
  self.state_1.clear_forces()
99
131
 
@@ -105,7 +137,7 @@ class Example:
105
137
 
106
138
  self.volume.zero_()
107
139
  wp.launch(
108
- kernel=self.compute_volume,
140
+ kernel=compute_volume,
109
141
  dim=self.model.tet_count,
110
142
  inputs=[self.state_0.particle_q, self.model.tet_indices, self.volume],
111
143
  )
@@ -118,42 +150,6 @@ class Example:
118
150
  self.renderer.render(self.state_0)
119
151
  self.renderer.end_frame()
120
152
 
121
- @wp.kernel
122
- def twist_points(
123
- rest: wp.array(dtype=wp.vec3), points: wp.array(dtype=wp.vec3), mass: wp.array(dtype=float), xform: wp.transform
124
- ):
125
- tid = wp.tid()
126
-
127
- r = rest[tid]
128
- p = points[tid]
129
- m = mass[tid]
130
-
131
- # twist the top layer of particles in the beam
132
- if m == 0 and p[1] != 0.0:
133
- points[tid] = wp.transform_point(xform, r)
134
-
135
- @wp.kernel
136
- def compute_volume(points: wp.array(dtype=wp.vec3), indices: wp.array2d(dtype=int), volume: wp.array(dtype=float)):
137
- tid = wp.tid()
138
-
139
- i = indices[tid, 0]
140
- j = indices[tid, 1]
141
- k = indices[tid, 2]
142
- l = indices[tid, 3]
143
-
144
- x0 = points[i]
145
- x1 = points[j]
146
- x2 = points[k]
147
- x3 = points[l]
148
-
149
- x10 = x1 - x0
150
- x20 = x2 - x0
151
- x30 = x3 - x0
152
-
153
- v = wp.dot(x10, wp.cross(x20, x30)) / 6.0
154
-
155
- wp.atomic_add(volume, 0, v)
156
-
157
153
 
158
154
  if __name__ == "__main__":
159
155
  stage_path = os.path.join(os.path.dirname(__file__), "outputs/example_sim_neo_hookean.usd")
@@ -13,8 +13,8 @@
13
13
  #
14
14
  ###########################################################################
15
15
 
16
- import os
17
16
  import math
17
+ import os
18
18
 
19
19
  import warp as wp
20
20
  import warp.sim
@@ -38,13 +38,13 @@ class Example:
38
38
  builder = wp.sim.ModelBuilder()
39
39
 
40
40
  # anchor
41
- builder.add_particle((0.0, 1.0, 0.0), (0.0, 0.0, 0.0), 0.0)
41
+ builder.add_particle(wp.vec3(0.0, 1.0, 0.0), wp.vec3(0.0, 0.0, 0.0), 0.0)
42
42
 
43
43
  # chain
44
44
  for i in range(1, 10):
45
45
  radius = math.sqrt(i) * 0.2
46
46
  mass = math.pi * radius * radius * radius
47
- builder.add_particle((i, 1.0, 0.0), (0.0, 0.0, 0.0), mass, radius=radius)
47
+ builder.add_particle(wp.vec3(i, 1.0, 0.0), wp.vec3(0.0, 0.0, 0.0), mass, radius=radius)
48
48
  builder.add_spring(i - 1, i, 1.0e6, 0.0, 0)
49
49
 
50
50
  self.model = builder.finalize()
@@ -59,7 +59,7 @@ class Example:
59
59
 
60
60
  def update(self):
61
61
  with wp.ScopedTimer("simulate"):
62
- for s in range(self.sim_substeps):
62
+ for _ in range(self.sim_substeps):
63
63
  self.state_0.clear_forces()
64
64
  self.state_1.clear_forces()
65
65
 
@@ -15,39 +15,68 @@
15
15
  ###########################################################################
16
16
 
17
17
  import math
18
- import numpy as np
19
18
  import os
20
19
 
20
+ import numpy as np
21
+
21
22
  import warp as wp
22
23
  import warp.sim
23
24
  import warp.sim.render
24
- from env.environment import compute_env_offsets
25
25
 
26
26
  wp.init()
27
27
 
28
28
 
29
- class Example:
30
- frame_dt = 1.0 / 100.0
31
-
32
- episode_duration = 5.0 # seconds
33
- episode_frames = int(episode_duration / frame_dt)
34
-
35
- sim_substeps = 5
36
- sim_dt = frame_dt / sim_substeps
37
- sim_steps = int(episode_duration / sim_dt)
38
-
39
- sim_time = 0.0
40
- render_time = 0.0
29
+ # Taken from env/environment.py
30
+ def compute_env_offsets(num_envs, env_offset=(5.0, 0.0, 5.0), up_axis="Y"):
31
+ # compute positional offsets per environment
32
+ env_offset = np.array(env_offset)
33
+ nonzeros = np.nonzero(env_offset)[0]
34
+ num_dim = nonzeros.shape[0]
35
+ if num_dim > 0:
36
+ side_length = int(np.ceil(num_envs ** (1.0 / num_dim)))
37
+ env_offsets = []
38
+ else:
39
+ env_offsets = np.zeros((num_envs, 3))
40
+ if num_dim == 1:
41
+ for i in range(num_envs):
42
+ env_offsets.append(i * env_offset)
43
+ elif num_dim == 2:
44
+ for i in range(num_envs):
45
+ d0 = i // side_length
46
+ d1 = i % side_length
47
+ offset = np.zeros(3)
48
+ offset[nonzeros[0]] = d0 * env_offset[nonzeros[0]]
49
+ offset[nonzeros[1]] = d1 * env_offset[nonzeros[1]]
50
+ env_offsets.append(offset)
51
+ elif num_dim == 3:
52
+ for i in range(num_envs):
53
+ d0 = i // (side_length * side_length)
54
+ d1 = (i // side_length) % side_length
55
+ d2 = i % side_length
56
+ offset = np.zeros(3)
57
+ offset[0] = d0 * env_offset[0]
58
+ offset[1] = d1 * env_offset[1]
59
+ offset[2] = d2 * env_offset[2]
60
+ env_offsets.append(offset)
61
+ env_offsets = np.array(env_offsets)
62
+ min_offsets = np.min(env_offsets, axis=0)
63
+ correction = min_offsets + (np.max(env_offsets, axis=0) - min_offsets) / 2.0
64
+ if isinstance(up_axis, str):
65
+ up_axis = "XYZ".index(up_axis.upper())
66
+ correction[up_axis] = 0.0 # ensure the envs are not shifted below the ground plane
67
+ env_offsets -= correction
68
+ return env_offsets
41
69
 
42
- def __init__(self, stage=None, render=True, num_envs=1):
43
- self.enable_rendering = render
44
70
 
71
+ class Example:
72
+ def __init__(self, stage=None, num_envs=1, enable_rendering=True, print_timers=True):
73
+ self.device = wp.get_device()
45
74
  self.num_envs = num_envs
46
75
  articulation_builder = wp.sim.ModelBuilder()
47
76
  wp.sim.parse_urdf(
48
77
  os.path.join(os.path.dirname(__file__), "assets/quadruped.urdf"),
49
78
  articulation_builder,
50
- xform=wp.transform([0.0, 0.7, 0.0], wp.quat_from_axis_angle((1.0, 0.0, 0.0), -math.pi * 0.5)),
79
+ xform=wp.transform([0.0, 0.7, 0.0], wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), -math.pi * 0.5)),
51
80
  floating=True,
52
81
  density=1000,
53
82
  armature=0.01,
@@ -62,6 +91,16 @@ class Example:
62
91
  )
63
92
 
64
93
  builder = wp.sim.ModelBuilder()
94
+
95
+ self.sim_time = 0.0
96
+ self.frame_dt = 1.0 / 100.0
97
+
98
+ episode_duration = 5.0 # seconds
99
+ self.episode_frames = int(episode_duration / self.frame_dt)
100
+
101
+ self.sim_substeps = 5
102
+ self.sim_dt = self.frame_dt / self.sim_substeps
103
+
65
104
  offsets = compute_env_offsets(num_envs)
66
105
  for i in range(num_envs):
67
106
  builder.add_builder(articulation_builder, xform=wp.transform(offsets[i], wp.quat_identity()))
@@ -80,60 +119,65 @@ class Example:
80
119
 
81
120
  self.integrator = wp.sim.XPBDIntegrator()
82
121
 
83
- # -----------------------
84
- # set up Usd renderer
122
+ self.enable_rendering = enable_rendering
85
123
  self.renderer = None
86
- if render:
124
+ if self.enable_rendering:
87
125
  self.renderer = wp.sim.render.SimRenderer(self.model, stage)
88
126
 
89
- def update(self):
90
- for _ in range(self.sim_substeps):
91
- self.state_0.clear_forces()
92
- wp.sim.collide(self.model, self.state_0)
93
- self.integrator.simulate(self.model, self.state_0, self.state_1, self.sim_dt)
94
- self.state_0, self.state_1 = self.state_1, self.state_0
95
-
96
- def render(self, is_live=False):
97
- time = 0.0 if is_live else self.sim_time
98
-
99
- self.renderer.begin_frame(time)
100
- self.renderer.render(self.state_0)
101
- self.renderer.end_frame()
127
+ self.print_timers = print_timers
102
128
 
103
- def run(self, render=True):
104
- # ---------------
105
- # run simulation
106
-
107
- self.sim_time = 0.0
108
129
  self.state_0 = self.model.state()
109
130
  self.state_1 = self.model.state()
110
131
 
111
132
  wp.sim.eval_fk(self.model, self.model.joint_q, self.model.joint_qd, None, self.state_0)
112
133
 
113
- profiler = {}
134
+ self.use_graph = wp.get_device().is_cuda
135
+ self.graph = None
136
+
137
+ if self.use_graph:
138
+ # create update graph
139
+ wp.capture_begin(self.device)
140
+ try:
141
+ self.update()
142
+ finally:
143
+ self.graph = wp.capture_end(self.device)
114
144
 
115
- # create update graph
116
- wp.capture_begin()
145
+ def update(self):
146
+ with wp.ScopedTimer("simulate", active=True, print=self.print_timers):
147
+ if not self.use_graph or self.graph is None:
148
+ for _ in range(self.sim_substeps):
149
+ self.state_0.clear_forces()
150
+ wp.sim.collide(self.model, self.state_0)
151
+ self.integrator.simulate(self.model, self.state_0, self.state_1, self.sim_dt)
152
+ self.state_0, self.state_1 = self.state_1, self.state_0
153
+ else:
154
+ wp.capture_launch(self.graph)
155
+
156
+ if not wp.get_device().is_capturing:
157
+ self.sim_time += self.frame_dt
117
158
 
118
- # simulate
119
- self.update()
159
+ def render(self, is_live=False):
160
+ if self.enable_rendering:
161
+ with wp.ScopedTimer("render", active=True, print=self.print_timers):
162
+ time = 0.0 if is_live else self.sim_time
120
163
 
121
- graph = wp.capture_end()
164
+ self.renderer.begin_frame(time)
165
+ self.renderer.render(self.state_0)
166
+ self.renderer.end_frame()
122
167
 
123
- # simulate
124
- with wp.ScopedTimer("simulate", detailed=False, print=False, active=True, dict=profiler):
125
- for f in range(0, self.episode_frames):
126
- with wp.ScopedTimer("simulate", active=True):
127
- wp.capture_launch(graph)
128
- self.sim_time += self.frame_dt
168
+ def run(self):
169
+ profiler = {}
129
170
 
130
- if self.enable_rendering:
131
- with wp.ScopedTimer("render", active=True):
132
- self.render()
133
- self.renderer.save()
171
+ with wp.ScopedTimer("simulate", detailed=False, print=False, active=True, dict=profiler):
172
+ for _ in range(self.episode_frames):
173
+ self.update()
174
+ self.render()
134
175
 
135
176
  wp.synchronize()
136
177
 
178
+ if self.enable_rendering:
179
+ self.renderer.save()
180
+
137
181
  avg_time = np.array(profiler["simulate"]).mean() / self.episode_frames
138
182
  avg_steps_second = 1000.0 * float(self.num_envs) / avg_time
139
183
 
@@ -142,38 +186,39 @@ class Example:
142
186
  return 1000.0 * float(self.num_envs) / avg_time
143
187
 
144
188
 
145
- profile = False
189
+ if __name__ == "__main__":
190
+ profile = False
146
191
 
147
- if profile:
148
- env_count = 2
149
- env_times = []
150
- env_size = []
192
+ if profile:
193
+ env_count = 2
194
+ env_times = []
195
+ env_size = []
151
196
 
152
- for i in range(15):
153
- robot = Example(render=False, num_envs=env_count)
154
- steps_per_second = robot.run()
197
+ for i in range(15):
198
+ example = Example(num_envs=env_count, enable_rendering=False, print_timers=False)
199
+ steps_per_second = example.run()
155
200
 
156
- env_size.append(env_count)
157
- env_times.append(steps_per_second)
201
+ env_size.append(env_count)
202
+ env_times.append(steps_per_second)
158
203
 
159
- env_count *= 2
204
+ env_count *= 2
160
205
 
161
- # dump times
162
- for i in range(len(env_times)):
163
- print(f"envs: {env_size[i]} steps/second: {env_times[i]}")
206
+ # dump times
207
+ for i in range(len(env_times)):
208
+ print(f"envs: {env_size[i]} steps/second: {env_times[i]}")
164
209
 
165
- # plot
166
- import matplotlib.pyplot as plt
210
+ # plot
211
+ import matplotlib.pyplot as plt
167
212
 
168
- plt.figure(1)
169
- plt.plot(env_size, env_times)
170
- plt.xscale("log")
171
- plt.xlabel("Number of Envs")
172
- plt.yscale("log")
173
- plt.ylabel("Steps/Second")
174
- plt.show()
213
+ plt.figure(1)
214
+ plt.plot(env_size, env_times)
215
+ plt.xscale("log")
216
+ plt.xlabel("Number of Envs")
217
+ plt.yscale("log")
218
+ plt.ylabel("Steps/Second")
219
+ plt.show()
175
220
 
176
- else:
177
- stage = os.path.join(os.path.dirname(__file__), "outputs/example_sim_quadruped.usd")
178
- robot = Example(stage, render=True, num_envs=25)
179
- robot.run()
221
+ else:
222
+ stage = os.path.join(os.path.dirname(__file__), "outputs/example_sim_quadruped.usd")
223
+ example = Example(stage, num_envs=25, enable_rendering=True)
224
+ example.run()