warp-lang 1.5.1__py3-none-win_amd64.whl → 1.6.1__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 (131) hide show
  1. warp/__init__.py +5 -0
  2. warp/autograd.py +414 -191
  3. warp/bin/warp-clang.dll +0 -0
  4. warp/bin/warp.dll +0 -0
  5. warp/build.py +40 -12
  6. warp/build_dll.py +13 -6
  7. warp/builtins.py +1077 -481
  8. warp/codegen.py +250 -122
  9. warp/config.py +65 -21
  10. warp/context.py +500 -149
  11. warp/examples/assets/square_cloth.usd +0 -0
  12. warp/examples/benchmarks/benchmark_gemm.py +27 -18
  13. warp/examples/benchmarks/benchmark_interop_paddle.py +3 -3
  14. warp/examples/benchmarks/benchmark_interop_torch.py +3 -3
  15. warp/examples/core/example_marching_cubes.py +1 -1
  16. warp/examples/core/example_mesh.py +1 -1
  17. warp/examples/core/example_torch.py +18 -34
  18. warp/examples/core/example_wave.py +1 -1
  19. warp/examples/fem/example_apic_fluid.py +1 -0
  20. warp/examples/fem/example_mixed_elasticity.py +1 -1
  21. warp/examples/optim/example_bounce.py +1 -1
  22. warp/examples/optim/example_cloth_throw.py +1 -1
  23. warp/examples/optim/example_diffray.py +4 -15
  24. warp/examples/optim/example_drone.py +1 -1
  25. warp/examples/optim/example_softbody_properties.py +392 -0
  26. warp/examples/optim/example_trajectory.py +1 -3
  27. warp/examples/optim/example_walker.py +5 -0
  28. warp/examples/sim/example_cartpole.py +0 -2
  29. warp/examples/sim/example_cloth_self_contact.py +314 -0
  30. warp/examples/sim/example_granular_collision_sdf.py +4 -5
  31. warp/examples/sim/example_jacobian_ik.py +0 -2
  32. warp/examples/sim/example_quadruped.py +5 -2
  33. warp/examples/tile/example_tile_cholesky.py +79 -0
  34. warp/examples/tile/example_tile_convolution.py +2 -2
  35. warp/examples/tile/example_tile_fft.py +2 -2
  36. warp/examples/tile/example_tile_filtering.py +3 -3
  37. warp/examples/tile/example_tile_matmul.py +4 -4
  38. warp/examples/tile/example_tile_mlp.py +12 -12
  39. warp/examples/tile/example_tile_nbody.py +191 -0
  40. warp/examples/tile/example_tile_walker.py +319 -0
  41. warp/math.py +147 -0
  42. warp/native/array.h +12 -0
  43. warp/native/builtin.h +0 -1
  44. warp/native/bvh.cpp +149 -70
  45. warp/native/bvh.cu +287 -68
  46. warp/native/bvh.h +195 -85
  47. warp/native/clang/clang.cpp +6 -2
  48. warp/native/crt.h +1 -0
  49. warp/native/cuda_util.cpp +35 -0
  50. warp/native/cuda_util.h +5 -0
  51. warp/native/exports.h +40 -40
  52. warp/native/intersect.h +17 -0
  53. warp/native/mat.h +57 -3
  54. warp/native/mathdx.cpp +19 -0
  55. warp/native/mesh.cpp +25 -8
  56. warp/native/mesh.cu +153 -101
  57. warp/native/mesh.h +482 -403
  58. warp/native/quat.h +40 -0
  59. warp/native/solid_angle.h +7 -0
  60. warp/native/sort.cpp +85 -0
  61. warp/native/sort.cu +34 -0
  62. warp/native/sort.h +3 -1
  63. warp/native/spatial.h +11 -0
  64. warp/native/tile.h +1189 -664
  65. warp/native/tile_reduce.h +8 -6
  66. warp/native/vec.h +41 -0
  67. warp/native/warp.cpp +8 -1
  68. warp/native/warp.cu +263 -40
  69. warp/native/warp.h +19 -5
  70. warp/optim/linear.py +22 -4
  71. warp/render/render_opengl.py +132 -59
  72. warp/render/render_usd.py +10 -2
  73. warp/sim/__init__.py +6 -1
  74. warp/sim/collide.py +289 -32
  75. warp/sim/import_urdf.py +20 -5
  76. warp/sim/integrator_euler.py +25 -7
  77. warp/sim/integrator_featherstone.py +147 -35
  78. warp/sim/integrator_vbd.py +842 -40
  79. warp/sim/model.py +173 -112
  80. warp/sim/render.py +2 -2
  81. warp/stubs.py +249 -116
  82. warp/tape.py +28 -30
  83. warp/tests/aux_test_module_unload.py +15 -0
  84. warp/tests/{test_sim_grad.py → flaky_test_sim_grad.py} +104 -63
  85. warp/tests/test_array.py +100 -0
  86. warp/tests/test_assert.py +242 -0
  87. warp/tests/test_codegen.py +14 -61
  88. warp/tests/test_collision.py +8 -8
  89. warp/tests/test_examples.py +16 -1
  90. warp/tests/test_grad_debug.py +87 -2
  91. warp/tests/test_hash_grid.py +1 -1
  92. warp/tests/test_ipc.py +116 -0
  93. warp/tests/test_launch.py +77 -26
  94. warp/tests/test_mat.py +213 -168
  95. warp/tests/test_math.py +47 -1
  96. warp/tests/test_matmul.py +11 -7
  97. warp/tests/test_matmul_lite.py +4 -4
  98. warp/tests/test_mesh.py +84 -60
  99. warp/tests/test_mesh_query_aabb.py +165 -0
  100. warp/tests/test_mesh_query_point.py +328 -286
  101. warp/tests/test_mesh_query_ray.py +134 -121
  102. warp/tests/test_mlp.py +2 -2
  103. warp/tests/test_operators.py +43 -0
  104. warp/tests/test_overwrite.py +6 -5
  105. warp/tests/test_quat.py +77 -0
  106. warp/tests/test_reload.py +29 -0
  107. warp/tests/test_sim_grad_bounce_linear.py +204 -0
  108. warp/tests/test_static.py +16 -0
  109. warp/tests/test_tape.py +25 -0
  110. warp/tests/test_tile.py +134 -191
  111. warp/tests/test_tile_load.py +399 -0
  112. warp/tests/test_tile_mathdx.py +61 -8
  113. warp/tests/test_tile_mlp.py +17 -17
  114. warp/tests/test_tile_reduce.py +24 -18
  115. warp/tests/test_tile_shared_memory.py +66 -17
  116. warp/tests/test_tile_view.py +165 -0
  117. warp/tests/test_torch.py +35 -0
  118. warp/tests/test_utils.py +36 -24
  119. warp/tests/test_vec.py +110 -0
  120. warp/tests/unittest_suites.py +29 -4
  121. warp/tests/unittest_utils.py +30 -11
  122. warp/thirdparty/unittest_parallel.py +5 -2
  123. warp/types.py +419 -111
  124. warp/utils.py +9 -5
  125. {warp_lang-1.5.1.dist-info → warp_lang-1.6.1.dist-info}/METADATA +86 -45
  126. {warp_lang-1.5.1.dist-info → warp_lang-1.6.1.dist-info}/RECORD +129 -118
  127. {warp_lang-1.5.1.dist-info → warp_lang-1.6.1.dist-info}/WHEEL +1 -1
  128. warp/examples/benchmarks/benchmark_tile.py +0 -179
  129. warp/native/tile_gemm.h +0 -341
  130. {warp_lang-1.5.1.dist-info → warp_lang-1.6.1.dist-info}/LICENSE.md +0 -0
  131. {warp_lang-1.5.1.dist-info → warp_lang-1.6.1.dist-info}/top_level.txt +0 -0
warp/sim/model.py CHANGED
@@ -7,6 +7,8 @@
7
7
 
8
8
  """A module for building simulation models and state."""
9
9
 
10
+ from __future__ import annotations
11
+
10
12
  import copy
11
13
  import math
12
14
  from typing import List, Optional, Tuple
@@ -262,47 +264,51 @@ class Mesh:
262
264
 
263
265
 
264
266
  class State:
265
- """The State object holds all *time-varying* data for a model.
267
+ """Time-varying state data for a :class:`Model`.
266
268
 
267
- Time-varying data includes particle positions, velocities, rigid body states, and
269
+ Time-varying state data includes particle positions, velocities, rigid body states, and
268
270
  anything that is output from the integrator as derived data, e.g.: forces.
269
271
 
270
272
  The exact attributes depend on the contents of the model. State objects should
271
273
  generally be created using the :func:`Model.state()` function.
274
+ """
272
275
 
273
- Attributes:
276
+ def __init__(self):
277
+ self.particle_q: Optional[wp.array] = None
278
+ """Array of 3D particle positions with shape ``(particle_count,)`` and type :class:`vec3`."""
274
279
 
275
- particle_q (array): Array of 3D particle positions, shape [particle_count], :class:`vec3`
276
- particle_qd (array): Array of 3D particle velocities, shape [particle_count], :class:`vec3`
277
- particle_f (array): Array of 3D particle forces, shape [particle_count], :class:`vec3`
280
+ self.particle_qd: Optional[wp.array] = None
281
+ """Array of 3D particle velocities with shape ``(particle_count,)`` and type :class:`vec3`."""
278
282
 
279
- body_q (array): Array of body coordinates (7-dof transforms) in maximal coordinates, shape [body_count], :class:`transform`
280
- body_qd (array): Array of body velocities in maximal coordinates (first 3 entries represent angular velocity, last 3 entries represent linear velocity), shape [body_count], :class:`spatial_vector`
281
- body_f (array): Array of body forces in maximal coordinates (first 3 entries represent torque, last 3 entries represent linear force), shape [body_count], :class:`spatial_vector`
283
+ self.particle_f: Optional[wp.array] = None
284
+ """Array of 3D particle forces with shape ``(particle_count,)`` and type :class:`vec3`."""
282
285
 
283
- Note:
286
+ self.body_q: Optional[wp.array] = None
287
+ """Array of body coordinates (7-dof transforms) in maximal coordinates with shape ``(body_count,)`` and type :class:`transform`."""
284
288
 
285
- :attr:`body_f` represents external wrenches in world frame and denotes wrenches measured w.r.t. to the body's center of mass for all integrators except :class:`FeatherstoneIntegrator` which assumes the wrenches are measured w.r.t. world origin.
289
+ self.body_qd: Optional[wp.array] = None
290
+ """Array of body velocities in maximal coordinates (first three entries represent angular velocity,
291
+ last three entries represent linear velocity) with shape ``(body_count,)`` and type :class:`spatial_vector`.
292
+ """
286
293
 
287
- joint_q (array): Array of generalized joint coordinates, shape [joint_coord_count], float
288
- joint_qd (array): Array of generalized joint velocities, shape [joint_dof_count], float
294
+ self.body_f: Optional[wp.array] = None
295
+ """Array of body forces in maximal coordinates (first three entries represent torque, last three
296
+ entries represent linear force) with shape ``(body_count,)`` and type :class:`spatial_vector`.
289
297
 
290
- """
291
-
292
- def __init__(self):
293
- self.particle_q = None
294
- self.particle_qd = None
295
- self.particle_f = None
298
+ .. note::
299
+ :attr:`body_f` represents external wrenches in world frame and denotes wrenches measured w.r.t.
300
+ to the body's center of mass for all integrators except :class:`FeatherstoneIntegrator`, which
301
+ assumes the wrenches are measured w.r.t. world origin.
302
+ """
296
303
 
297
- self.body_q = None
298
- self.body_qd = None
299
- self.body_f = None
304
+ self.joint_q: Optional[wp.array] = None
305
+ """Array of generalized joint coordinates with shape ``(joint_coord_count,)`` and type ``float``."""
300
306
 
301
- self.joint_q = None
302
- self.joint_qd = None
307
+ self.joint_qd: Optional[wp.array] = None
308
+ """Array of generalized joint velocities with shape ``(joint_dof_count,)`` and type ``float``."""
303
309
 
304
- def clear_forces(self):
305
- """Clears all forces (for particles and bodies) in the state object."""
310
+ def clear_forces(self) -> None:
311
+ """Clear all forces (for particles and bodies) in the state object."""
306
312
  with wp.ScopedTimer("clear_forces", False):
307
313
  if self.particle_count:
308
314
  self.particle_f.zero_()
@@ -311,7 +317,7 @@ class State:
311
317
  self.body_f.zero_()
312
318
 
313
319
  @property
314
- def requires_grad(self):
320
+ def requires_grad(self) -> bool:
315
321
  """Indicates whether the state arrays have gradient computation enabled."""
316
322
  if self.particle_q:
317
323
  return self.particle_q.requires_grad
@@ -320,28 +326,28 @@ class State:
320
326
  return False
321
327
 
322
328
  @property
323
- def body_count(self):
329
+ def body_count(self) -> int:
324
330
  """The number of bodies represented in the state."""
325
331
  if self.body_q is None:
326
332
  return 0
327
333
  return len(self.body_q)
328
334
 
329
335
  @property
330
- def particle_count(self):
336
+ def particle_count(self) -> int:
331
337
  """The number of particles represented in the state."""
332
338
  if self.particle_q is None:
333
339
  return 0
334
340
  return len(self.particle_q)
335
341
 
336
342
  @property
337
- def joint_coord_count(self):
343
+ def joint_coord_count(self) -> int:
338
344
  """The number of generalized joint position coordinates represented in the state."""
339
345
  if self.joint_q is None:
340
346
  return 0
341
347
  return len(self.joint_q)
342
348
 
343
349
  @property
344
- def joint_dof_count(self):
350
+ def joint_dof_count(self) -> int:
345
351
  """The number of generalized joint velocity coordinates represented in the state."""
346
352
  if self.joint_qd is None:
347
353
  return 0
@@ -349,37 +355,34 @@ class State:
349
355
 
350
356
 
351
357
  class Control:
358
+ """Time-varying control data for a :class:`Model`.
359
+
360
+ Time-varying control data includes joint control inputs, muscle activations,
361
+ and activation forces for triangle and tetrahedral elements.
362
+
363
+ The exact attributes depend on the contents of the model. Control objects
364
+ should generally be created using the :func:`Model.control()` function.
352
365
  """
353
- The Control object holds all *time-varying* control data for a model.
354
366
 
355
- Time-varying control data includes joint control inputs, muscle activations, and activation forces for triangle and tetrahedral elements.
367
+ def __init__(self, model: Model):
368
+ self.model: Model = model
369
+ """Model to use as a reference for the control inputs."""
356
370
 
357
- The exact attributes depend on the contents of the model. Control objects should generally be created using the :func:`Model.control()` function.
371
+ self.joint_act: Optional[wp.array] = None
372
+ """Array of joint control inputs with shape ``(joint_axis_count,)`` and type ``float``."""
358
373
 
359
- Attributes:
374
+ self.tri_activations: Optional[wp.array] = None
375
+ """Array of triangle element activations with shape ``(tri_count,)`` and type ``float``."""
360
376
 
361
- joint_act (array): Array of joint control inputs, shape [joint_axis_count], float
362
- tri_activations (array): Array of triangle element activations, shape [tri_count], float
363
- tet_activations (array): Array of tetrahedral element activations, shape [tet_count], float
364
- muscle_activations (array): Array of muscle activations, shape [muscle_count], float
377
+ self.tet_activations: Optional[wp.array] = None
378
+ """Array of tetrahedral element activations with shape with shape ``(tet_count,) and type ``float``."""
365
379
 
366
- """
380
+ self.muscle_activations: Optional[wp.array] = None
381
+ """Array of muscle activations with shape ``(muscle_count,)`` and type ``float``."""
367
382
 
368
- def __init__(self, model):
369
- """
370
- Args:
371
- model (Model): The model to use as a reference for the control inputs
372
- """
373
- self.model = model
374
- self.joint_act = None
375
- self.tri_activations = None
376
- self.tet_activations = None
377
- self.muscle_activations = None
383
+ def reset(self) -> None:
384
+ """Reset the control inputs to their initial state defined in :attr:`model`."""
378
385
 
379
- def reset(self):
380
- """
381
- Resets the control inputs to their initial state defined in :class:`Model`.
382
- """
383
386
  if self.joint_act is not None:
384
387
  self.joint_act.assign(self.model.joint_act)
385
388
  if self.tri_activations is not None:
@@ -591,6 +594,7 @@ class Model:
591
594
  joint_attach_ke (float): Joint attachment force stiffness (used by :class:`SemiImplicitIntegrator`)
592
595
  joint_attach_kd (float): Joint attachment force damping (used by :class:`SemiImplicitIntegrator`)
593
596
 
597
+ soft_contact_radius (float): Contact radius used for self-collisions in the VBD integrator.
594
598
  soft_contact_margin (float): Contact margin for generation of soft contacts
595
599
  soft_contact_ke (float): Stiffness of soft contacts (used by the Euler integrators)
596
600
  soft_contact_kd (float): Damping of soft contacts (used by the Euler integrators)
@@ -761,6 +765,7 @@ class Model:
761
765
  self.joint_attach_ke = 1.0e3
762
766
  self.joint_attach_kd = 1.0e2
763
767
 
768
+ self.soft_contact_radius = 0.2
764
769
  self.soft_contact_margin = 0.2
765
770
  self.soft_contact_ke = 1.0e3
766
771
  self.soft_contact_kd = 10.0
@@ -1046,6 +1051,8 @@ class Model:
1046
1051
  @property
1047
1052
  def soft_contact_max(self):
1048
1053
  """Maximum number of soft contacts that can be registered"""
1054
+ if self.soft_contact_particle is None:
1055
+ return 0
1049
1056
  return len(self.soft_contact_particle)
1050
1057
 
1051
1058
 
@@ -1392,6 +1399,8 @@ class ModelBuilder:
1392
1399
  # apply offset transform to root bodies
1393
1400
  if xform is not None:
1394
1401
  self.shape_transform.append(xform * builder.shape_transform[s])
1402
+ else:
1403
+ self.shape_transform.append(builder.shape_transform[s])
1395
1404
 
1396
1405
  for b, shapes in builder.body_shapes.items():
1397
1406
  self.body_shapes[b + start_body_idx] = [s + start_shape_idx for s in shapes]
@@ -1414,18 +1423,16 @@ class ModelBuilder:
1414
1423
 
1415
1424
  # offset the indices
1416
1425
  self.articulation_start.extend([a + self.joint_count for a in builder.articulation_start])
1417
- self.joint_parent.extend([p + self.joint_count if p != -1 else -1 for p in builder.joint_parent])
1418
- self.joint_child.extend([c + self.joint_count for c in builder.joint_child])
1426
+ self.joint_parent.extend([p + self.body_count if p != -1 else -1 for p in builder.joint_parent])
1427
+ self.joint_child.extend([c + self.body_count for c in builder.joint_child])
1419
1428
 
1420
1429
  self.joint_q_start.extend([c + self.joint_coord_count for c in builder.joint_q_start])
1421
1430
  self.joint_qd_start.extend([c + self.joint_dof_count for c in builder.joint_qd_start])
1422
1431
 
1423
1432
  self.joint_axis_start.extend([a + self.joint_axis_total_count for a in builder.joint_axis_start])
1424
1433
 
1425
- joint_children = set(builder.joint_child)
1426
1434
  for i in range(builder.body_count):
1427
- if xform is not None and i not in joint_children:
1428
- # rigid body is not attached to a joint, so apply input transform directly
1435
+ if xform is not None:
1429
1436
  self.body_q.append(xform * builder.body_q[i])
1430
1437
  else:
1431
1438
  self.body_q.append(builder.body_q[i])
@@ -1747,8 +1754,8 @@ class ModelBuilder:
1747
1754
  mode: int = JOINT_MODE_FORCE,
1748
1755
  limit_lower: float = -2 * math.pi,
1749
1756
  limit_upper: float = 2 * math.pi,
1750
- limit_ke: float = default_joint_limit_ke,
1751
- limit_kd: float = default_joint_limit_kd,
1757
+ limit_ke: float = None,
1758
+ limit_kd: float = None,
1752
1759
  linear_compliance: float = 0.0,
1753
1760
  angular_compliance: float = 0.0,
1754
1761
  armature: float = 1e-2,
@@ -1769,8 +1776,8 @@ class ModelBuilder:
1769
1776
  target_kd: The damping of the joint target
1770
1777
  limit_lower: The lower limit of the joint
1771
1778
  limit_upper: The upper limit of the joint
1772
- limit_ke: The stiffness of the joint limit
1773
- limit_kd: The damping of the joint limit
1779
+ limit_ke: The stiffness of the joint limit (None to use the default value :attr:`default_joint_limit_ke`)
1780
+ limit_kd: The damping of the joint limit (None to use the default value :attr:`default_joint_limit_kd`)
1774
1781
  linear_compliance: The linear compliance of the joint
1775
1782
  angular_compliance: The angular compliance of the joint
1776
1783
  armature: Artificial inertia added around the joint axis
@@ -1788,6 +1795,9 @@ class ModelBuilder:
1788
1795
  if child_xform is None:
1789
1796
  child_xform = wp.transform()
1790
1797
 
1798
+ limit_ke = limit_ke if limit_ke is not None else self.default_joint_limit_ke
1799
+ limit_kd = limit_kd if limit_kd is not None else self.default_joint_limit_kd
1800
+
1791
1801
  action = 0.0
1792
1802
  if target is None and mode == JOINT_MODE_TARGET_POSITION:
1793
1803
  action = 0.5 * (limit_lower + limit_upper)
@@ -1834,8 +1844,8 @@ class ModelBuilder:
1834
1844
  mode: int = JOINT_MODE_FORCE,
1835
1845
  limit_lower: float = -1e4,
1836
1846
  limit_upper: float = 1e4,
1837
- limit_ke: float = default_joint_limit_ke,
1838
- limit_kd: float = default_joint_limit_kd,
1847
+ limit_ke: float = None,
1848
+ limit_kd: float = None,
1839
1849
  linear_compliance: float = 0.0,
1840
1850
  angular_compliance: float = 0.0,
1841
1851
  armature: float = 1e-2,
@@ -1856,8 +1866,8 @@ class ModelBuilder:
1856
1866
  target_kd: The damping of the joint target
1857
1867
  limit_lower: The lower limit of the joint
1858
1868
  limit_upper: The upper limit of the joint
1859
- limit_ke: The stiffness of the joint limit
1860
- limit_kd: The damping of the joint limit
1869
+ limit_ke: The stiffness of the joint limit (None to use the default value :attr:`default_joint_limit_ke`)
1870
+ limit_kd: The damping of the joint limit (None to use the default value :attr:`default_joint_limit_ke`)
1861
1871
  linear_compliance: The linear compliance of the joint
1862
1872
  angular_compliance: The angular compliance of the joint
1863
1873
  armature: Artificial inertia added around the joint axis
@@ -1875,6 +1885,9 @@ class ModelBuilder:
1875
1885
  if child_xform is None:
1876
1886
  child_xform = wp.transform()
1877
1887
 
1888
+ limit_ke = limit_ke if limit_ke is not None else self.default_joint_limit_ke
1889
+ limit_kd = limit_kd if limit_kd is not None else self.default_joint_limit_kd
1890
+
1878
1891
  action = 0.0
1879
1892
  if target is None and mode == JOINT_MODE_TARGET_POSITION:
1880
1893
  action = 0.5 * (limit_lower + limit_upper)
@@ -2523,7 +2536,7 @@ class ModelBuilder:
2523
2536
  last_dynamic_body_name = self.body_name[last_dynamic_body] if last_dynamic_body > -1 else "world"
2524
2537
  if verbose:
2525
2538
  print(
2526
- f'Remove fixed joint {joint["name"]} between {parent_name} and {child_name}, '
2539
+ f"Remove fixed joint {joint['name']} between {parent_name} and {child_name}, "
2527
2540
  f"merging {child_name} into {last_dynamic_body_name}"
2528
2541
  )
2529
2542
  child_id = body_data[child_body]["original_id"]
@@ -2775,7 +2788,7 @@ class ModelBuilder:
2775
2788
  c = np.cross(normal, (0.0, 1.0, 0.0))
2776
2789
  angle = np.arcsin(np.linalg.norm(c))
2777
2790
  axis = np.abs(c) / np.linalg.norm(c)
2778
- rot = wp.quat_from_axis_angle(axis, angle)
2791
+ rot = wp.quat_from_axis_angle(wp.vec3(*axis), wp.float32(angle))
2779
2792
  scale = wp.vec3(width, length, 0.0)
2780
2793
 
2781
2794
  return self._add_shape(
@@ -3501,11 +3514,11 @@ class ModelBuilder:
3501
3514
  i: int,
3502
3515
  j: int,
3503
3516
  k: int,
3504
- tri_ke: float = default_tri_ke,
3505
- tri_ka: float = default_tri_ka,
3506
- tri_kd: float = default_tri_kd,
3507
- tri_drag: float = default_tri_drag,
3508
- tri_lift: float = default_tri_lift,
3517
+ tri_ke: float = None,
3518
+ tri_ka: float = None,
3519
+ tri_kd: float = None,
3520
+ tri_drag: float = None,
3521
+ tri_lift: float = None,
3509
3522
  ) -> float:
3510
3523
  """Adds a triangular FEM element between three particles in the system.
3511
3524
 
@@ -3525,6 +3538,11 @@ class ModelBuilder:
3525
3538
  between the particles in their initial configuration.
3526
3539
  """
3527
3540
  # TODO: Expose elastic parameters on a per-element basis
3541
+ tri_ke = tri_ke if tri_ke is not None else self.default_tri_ke
3542
+ tri_ka = tri_ka if tri_ka is not None else self.default_tri_ka
3543
+ tri_kd = tri_kd if tri_kd is not None else self.default_tri_kd
3544
+ tri_drag = tri_drag if tri_drag is not None else self.default_tri_drag
3545
+ tri_lift = tri_lift if tri_lift is not None else self.default_tri_lift
3528
3546
 
3529
3547
  # compute basis for 2D rest pose
3530
3548
  p = self.particle_q[i]
@@ -3705,8 +3723,8 @@ class ModelBuilder:
3705
3723
  k: int,
3706
3724
  l: int,
3707
3725
  rest: float = None,
3708
- edge_ke: float = default_edge_ke,
3709
- edge_kd: float = default_edge_kd,
3726
+ edge_ke: float = None,
3727
+ edge_kd: float = None,
3710
3728
  ):
3711
3729
  """Adds a bending edge element between four particles in the system.
3712
3730
 
@@ -3727,6 +3745,9 @@ class ModelBuilder:
3727
3745
  winding: (i, k, l), (j, l, k).
3728
3746
 
3729
3747
  """
3748
+ edge_ke = edge_ke if edge_ke is not None else self.default_edge_ke
3749
+ edge_kd = edge_kd if edge_kd is not None else self.default_edge_kd
3750
+
3730
3751
  # compute rest angle
3731
3752
  if rest is None:
3732
3753
  x1 = self.particle_q[i]
@@ -3834,17 +3855,17 @@ class ModelBuilder:
3834
3855
  fix_right: bool = False,
3835
3856
  fix_top: bool = False,
3836
3857
  fix_bottom: bool = False,
3837
- tri_ke: float = default_tri_ke,
3838
- tri_ka: float = default_tri_ka,
3839
- tri_kd: float = default_tri_kd,
3840
- tri_drag: float = default_tri_drag,
3841
- tri_lift: float = default_tri_lift,
3842
- edge_ke: float = default_edge_ke,
3843
- edge_kd: float = default_edge_kd,
3858
+ tri_ke: float = None,
3859
+ tri_ka: float = None,
3860
+ tri_kd: float = None,
3861
+ tri_drag: float = None,
3862
+ tri_lift: float = None,
3863
+ edge_ke: float = None,
3864
+ edge_kd: float = None,
3844
3865
  add_springs: bool = False,
3845
- spring_ke: float = default_spring_ke,
3846
- spring_kd: float = default_spring_kd,
3847
- particle_radius: float = default_particle_radius,
3866
+ spring_ke: float = None,
3867
+ spring_kd: float = None,
3868
+ particle_radius: float = None,
3848
3869
  ):
3849
3870
  """Helper to create a regular planar cloth grid
3850
3871
 
@@ -3866,6 +3887,16 @@ class ModelBuilder:
3866
3887
  fix_top: Make the top-most edge of particles kinematic
3867
3888
  fix_bottom: Make the bottom-most edge of particles kinematic
3868
3889
  """
3890
+ tri_ke = tri_ke if tri_ke is not None else self.default_tri_ke
3891
+ tri_ka = tri_ka if tri_ka is not None else self.default_tri_ka
3892
+ tri_kd = tri_kd if tri_kd is not None else self.default_tri_kd
3893
+ tri_drag = tri_drag if tri_drag is not None else self.default_tri_drag
3894
+ tri_lift = tri_lift if tri_lift is not None else self.default_tri_lift
3895
+ edge_ke = edge_ke if edge_ke is not None else self.default_edge_ke
3896
+ edge_kd = edge_kd if edge_kd is not None else self.default_edge_kd
3897
+ spring_ke = spring_ke if spring_ke is not None else self.default_spring_ke
3898
+ spring_kd = spring_kd if spring_kd is not None else self.default_spring_kd
3899
+ particle_radius = particle_radius if particle_radius is not None else self.default_particle_radius
3869
3900
 
3870
3901
  def grid_index(x, y, dim_x):
3871
3902
  return y * dim_x + x
@@ -3968,17 +3999,17 @@ class ModelBuilder:
3968
3999
  density: float,
3969
4000
  edge_callback=None,
3970
4001
  face_callback=None,
3971
- tri_ke: float = default_tri_ke,
3972
- tri_ka: float = default_tri_ka,
3973
- tri_kd: float = default_tri_kd,
3974
- tri_drag: float = default_tri_drag,
3975
- tri_lift: float = default_tri_lift,
3976
- edge_ke: float = default_edge_ke,
3977
- edge_kd: float = default_edge_kd,
4002
+ tri_ke: float = None,
4003
+ tri_ka: float = None,
4004
+ tri_kd: float = None,
4005
+ tri_drag: float = None,
4006
+ tri_lift: float = None,
4007
+ edge_ke: float = None,
4008
+ edge_kd: float = None,
3978
4009
  add_springs: bool = False,
3979
- spring_ke: float = default_spring_ke,
3980
- spring_kd: float = default_spring_kd,
3981
- particle_radius: float = default_particle_radius,
4010
+ spring_ke: float = None,
4011
+ spring_kd: float = None,
4012
+ particle_radius: float = None,
3982
4013
  ):
3983
4014
  """Helper to create a cloth model from a regular triangle mesh
3984
4015
 
@@ -3999,6 +4030,17 @@ class ModelBuilder:
3999
4030
 
4000
4031
  The mesh should be two manifold.
4001
4032
  """
4033
+ tri_ke = tri_ke if tri_ke is not None else self.default_tri_ke
4034
+ tri_ka = tri_ka if tri_ka is not None else self.default_tri_ka
4035
+ tri_kd = tri_kd if tri_kd is not None else self.default_tri_kd
4036
+ tri_drag = tri_drag if tri_drag is not None else self.default_tri_drag
4037
+ tri_lift = tri_lift if tri_lift is not None else self.default_tri_lift
4038
+ edge_ke = edge_ke if edge_ke is not None else self.default_edge_ke
4039
+ edge_kd = edge_kd if edge_kd is not None else self.default_edge_kd
4040
+ spring_ke = spring_ke if spring_ke is not None else self.default_spring_ke
4041
+ spring_kd = spring_kd if spring_kd is not None else self.default_spring_kd
4042
+ particle_radius = particle_radius if particle_radius is not None else self.default_particle_radius
4043
+
4002
4044
  num_tris = int(len(indices) / 3)
4003
4045
 
4004
4046
  start_vertex = len(self.particle_q)
@@ -4076,9 +4118,11 @@ class ModelBuilder:
4076
4118
  cell_z: float,
4077
4119
  mass: float,
4078
4120
  jitter: float,
4079
- radius_mean: float = default_particle_radius,
4121
+ radius_mean: float = None,
4080
4122
  radius_std: float = 0.0,
4081
4123
  ):
4124
+ radius_mean = radius_mean if radius_mean is not None else self.default_particle_radius
4125
+
4082
4126
  rng = np.random.default_rng(42)
4083
4127
  for z in range(dim_z):
4084
4128
  for y in range(dim_y):
@@ -4113,11 +4157,11 @@ class ModelBuilder:
4113
4157
  fix_right: bool = False,
4114
4158
  fix_top: bool = False,
4115
4159
  fix_bottom: bool = False,
4116
- tri_ke: float = default_tri_ke,
4117
- tri_ka: float = default_tri_ka,
4118
- tri_kd: float = default_tri_kd,
4119
- tri_drag: float = default_tri_drag,
4120
- tri_lift: float = default_tri_lift,
4160
+ tri_ke: float = None,
4161
+ tri_ka: float = None,
4162
+ tri_kd: float = None,
4163
+ tri_drag: float = None,
4164
+ tri_lift: float = None,
4121
4165
  ):
4122
4166
  """Helper to create a rectangular tetrahedral FEM grid
4123
4167
 
@@ -4144,6 +4188,11 @@ class ModelBuilder:
4144
4188
  fix_top: Make the top-most edge of particles kinematic
4145
4189
  fix_bottom: Make the bottom-most edge of particles kinematic
4146
4190
  """
4191
+ tri_ke = tri_ke if tri_ke is not None else self.default_tri_ke
4192
+ tri_ka = tri_ka if tri_ka is not None else self.default_tri_ka
4193
+ tri_kd = tri_kd if tri_kd is not None else self.default_tri_kd
4194
+ tri_drag = tri_drag if tri_drag is not None else self.default_tri_drag
4195
+ tri_lift = tri_lift if tri_lift is not None else self.default_tri_lift
4147
4196
 
4148
4197
  start_vertex = len(self.particle_q)
4149
4198
 
@@ -4235,11 +4284,11 @@ class ModelBuilder:
4235
4284
  k_mu: float,
4236
4285
  k_lambda: float,
4237
4286
  k_damp: float,
4238
- tri_ke: float = default_tri_ke,
4239
- tri_ka: float = default_tri_ka,
4240
- tri_kd: float = default_tri_kd,
4241
- tri_drag: float = default_tri_drag,
4242
- tri_lift: float = default_tri_lift,
4287
+ tri_ke: float = None,
4288
+ tri_ka: float = None,
4289
+ tri_kd: float = None,
4290
+ tri_drag: float = None,
4291
+ tri_lift: float = None,
4243
4292
  ):
4244
4293
  """Helper to create a tetrahedral model from an input tetrahedral mesh
4245
4294
 
@@ -4254,6 +4303,12 @@ class ModelBuilder:
4254
4303
  k_lambda: The second elastic Lame parameter
4255
4304
  k_damp: The damping stiffness
4256
4305
  """
4306
+ tri_ke = tri_ke if tri_ke is not None else self.default_tri_ke
4307
+ tri_ka = tri_ka if tri_ka is not None else self.default_tri_ka
4308
+ tri_kd = tri_kd if tri_kd is not None else self.default_tri_kd
4309
+ tri_drag = tri_drag if tri_drag is not None else self.default_tri_drag
4310
+ tri_lift = tri_lift if tri_lift is not None else self.default_tri_lift
4311
+
4257
4312
  num_tets = int(len(indices) / 4)
4258
4313
 
4259
4314
  start_vertex = len(self.particle_q)
@@ -4344,16 +4399,22 @@ class ModelBuilder:
4344
4399
  self,
4345
4400
  normal=None,
4346
4401
  offset=0.0,
4347
- ke: float = default_shape_ke,
4348
- kd: float = default_shape_kd,
4349
- kf: float = default_shape_kf,
4350
- mu: float = default_shape_mu,
4351
- restitution: float = default_shape_restitution,
4402
+ ke: float = None,
4403
+ kd: float = None,
4404
+ kf: float = None,
4405
+ mu: float = None,
4406
+ restitution: float = None,
4352
4407
  ):
4353
4408
  """
4354
4409
  Creates a ground plane for the world. If the normal is not specified,
4355
4410
  the up_vector of the ModelBuilder is used.
4356
4411
  """
4412
+ ke = ke if ke is not None else self.default_shape_ke
4413
+ kd = kd if kd is not None else self.default_shape_kd
4414
+ kf = kf if kf is not None else self.default_shape_kf
4415
+ mu = mu if mu is not None else self.default_shape_mu
4416
+ restitution = restitution if restitution is not None else self.default_shape_restitution
4417
+
4357
4418
  if normal is None:
4358
4419
  normal = self.up_vector
4359
4420
  self._ground_params = {
warp/sim/render.py CHANGED
@@ -213,7 +213,7 @@ def CreateSimRenderer(renderer):
213
213
  pos=p,
214
214
  rot=q,
215
215
  scale=geo_scale,
216
- colors=[color],
216
+ colors=color,
217
217
  parent_body=body,
218
218
  is_template=True,
219
219
  )
@@ -328,7 +328,7 @@ def CreateSimRenderer(renderer):
328
328
  "surface",
329
329
  particle_q,
330
330
  self.model.tri_indices.numpy().flatten(),
331
- colors=(((0.75, 0.25, 0.0),) * len(particle_q)),
331
+ colors=(0.75, 0.25, 0.0),
332
332
  )
333
333
 
334
334
  # render springs