warp-lang 1.6.2__py3-none-win_amd64.whl → 1.7.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.
- warp/__init__.py +7 -1
- warp/autograd.py +12 -2
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +410 -0
- warp/build_dll.py +6 -14
- warp/builtins.py +463 -372
- warp/codegen.py +196 -124
- warp/config.py +42 -6
- warp/context.py +496 -271
- warp/dlpack.py +8 -6
- warp/examples/assets/nonuniform.usd +0 -0
- warp/examples/assets/nvidia_logo.png +0 -0
- warp/examples/benchmarks/benchmark_cloth.py +1 -1
- warp/examples/benchmarks/benchmark_tile_load_store.py +103 -0
- warp/examples/core/example_sample_mesh.py +300 -0
- warp/examples/distributed/example_jacobi_mpi.py +507 -0
- warp/examples/fem/example_apic_fluid.py +1 -1
- warp/examples/fem/example_burgers.py +2 -2
- warp/examples/fem/example_deformed_geometry.py +1 -1
- warp/examples/fem/example_distortion_energy.py +1 -1
- warp/examples/fem/example_magnetostatics.py +6 -6
- warp/examples/fem/utils.py +9 -3
- warp/examples/interop/example_jax_callable.py +116 -0
- warp/examples/interop/example_jax_ffi_callback.py +132 -0
- warp/examples/interop/example_jax_kernel.py +205 -0
- warp/examples/optim/example_fluid_checkpoint.py +497 -0
- warp/examples/tile/example_tile_matmul.py +2 -4
- warp/fem/__init__.py +11 -1
- warp/fem/adaptivity.py +4 -4
- warp/fem/field/field.py +11 -1
- warp/fem/field/nodal_field.py +56 -88
- warp/fem/field/virtual.py +62 -23
- warp/fem/geometry/adaptive_nanogrid.py +16 -13
- warp/fem/geometry/closest_point.py +1 -1
- warp/fem/geometry/deformed_geometry.py +5 -2
- warp/fem/geometry/geometry.py +5 -0
- warp/fem/geometry/grid_2d.py +12 -12
- warp/fem/geometry/grid_3d.py +12 -15
- warp/fem/geometry/hexmesh.py +5 -7
- warp/fem/geometry/nanogrid.py +9 -11
- warp/fem/geometry/quadmesh.py +13 -13
- warp/fem/geometry/tetmesh.py +3 -4
- warp/fem/geometry/trimesh.py +7 -20
- warp/fem/integrate.py +262 -93
- warp/fem/linalg.py +5 -5
- warp/fem/quadrature/pic_quadrature.py +37 -22
- warp/fem/quadrature/quadrature.py +194 -25
- warp/fem/space/__init__.py +1 -1
- warp/fem/space/basis_function_space.py +4 -2
- warp/fem/space/basis_space.py +25 -18
- warp/fem/space/hexmesh_function_space.py +2 -2
- warp/fem/space/partition.py +6 -2
- warp/fem/space/quadmesh_function_space.py +8 -8
- warp/fem/space/shape/cube_shape_function.py +23 -23
- warp/fem/space/shape/square_shape_function.py +12 -12
- warp/fem/space/shape/triangle_shape_function.py +1 -1
- warp/fem/space/tetmesh_function_space.py +3 -3
- warp/fem/space/trimesh_function_space.py +2 -2
- warp/fem/utils.py +12 -6
- warp/jax.py +14 -1
- warp/jax_experimental/__init__.py +16 -0
- warp/{jax_experimental.py → jax_experimental/custom_call.py} +28 -29
- warp/jax_experimental/ffi.py +702 -0
- warp/jax_experimental/xla_ffi.py +602 -0
- warp/math.py +89 -0
- warp/native/array.h +13 -0
- warp/native/builtin.h +29 -3
- warp/native/bvh.cpp +3 -1
- warp/native/bvh.cu +42 -14
- warp/native/bvh.h +2 -1
- warp/native/clang/clang.cpp +30 -3
- warp/native/cuda_util.cpp +14 -0
- warp/native/cuda_util.h +2 -0
- warp/native/exports.h +68 -63
- warp/native/intersect.h +26 -26
- warp/native/intersect_adj.h +33 -33
- warp/native/marching.cu +1 -1
- warp/native/mat.h +513 -9
- warp/native/mesh.h +10 -10
- warp/native/quat.h +99 -11
- warp/native/rand.h +6 -0
- warp/native/sort.cpp +122 -59
- warp/native/sort.cu +152 -15
- warp/native/sort.h +8 -1
- warp/native/sparse.cpp +43 -22
- warp/native/sparse.cu +52 -17
- warp/native/svd.h +116 -0
- warp/native/tile.h +312 -116
- warp/native/tile_reduce.h +46 -3
- warp/native/vec.h +68 -7
- warp/native/volume.cpp +85 -113
- warp/native/volume_builder.cu +25 -10
- warp/native/volume_builder.h +6 -0
- warp/native/warp.cpp +5 -6
- warp/native/warp.cu +100 -11
- warp/native/warp.h +19 -10
- warp/optim/linear.py +10 -10
- warp/render/render_opengl.py +19 -17
- warp/render/render_usd.py +93 -3
- warp/sim/articulation.py +4 -4
- warp/sim/collide.py +32 -19
- warp/sim/import_mjcf.py +449 -155
- warp/sim/import_urdf.py +32 -12
- warp/sim/inertia.py +189 -156
- warp/sim/integrator_euler.py +8 -5
- warp/sim/integrator_featherstone.py +3 -10
- warp/sim/integrator_vbd.py +207 -2
- warp/sim/integrator_xpbd.py +8 -5
- warp/sim/model.py +71 -25
- warp/sim/render.py +4 -0
- warp/sim/utils.py +2 -2
- warp/sparse.py +642 -555
- warp/stubs.py +217 -20
- warp/tests/__main__.py +0 -15
- warp/tests/assets/torus.usda +1 -1
- warp/tests/cuda/__init__.py +0 -0
- warp/tests/{test_mempool.py → cuda/test_mempool.py} +39 -0
- warp/tests/{test_streams.py → cuda/test_streams.py} +71 -0
- warp/tests/geometry/__init__.py +0 -0
- warp/tests/{test_mesh_query_point.py → geometry/test_mesh_query_point.py} +66 -63
- warp/tests/{test_mesh_query_ray.py → geometry/test_mesh_query_ray.py} +1 -1
- warp/tests/{test_volume.py → geometry/test_volume.py} +41 -6
- warp/tests/interop/__init__.py +0 -0
- warp/tests/{test_dlpack.py → interop/test_dlpack.py} +28 -5
- warp/tests/sim/__init__.py +0 -0
- warp/tests/{disabled_kinematics.py → sim/disabled_kinematics.py} +9 -10
- warp/tests/{test_collision.py → sim/test_collision.py} +236 -205
- warp/tests/sim/test_inertia.py +161 -0
- warp/tests/{test_model.py → sim/test_model.py} +40 -0
- warp/tests/{flaky_test_sim_grad.py → sim/test_sim_grad.py} +4 -0
- warp/tests/{test_sim_kinematics.py → sim/test_sim_kinematics.py} +2 -1
- warp/tests/sim/test_vbd.py +597 -0
- warp/tests/sim/test_xpbd.py +399 -0
- warp/tests/test_bool.py +1 -1
- warp/tests/test_codegen.py +24 -3
- warp/tests/test_examples.py +40 -38
- warp/tests/test_fem.py +98 -14
- warp/tests/test_linear_solvers.py +0 -11
- warp/tests/test_mat.py +577 -156
- warp/tests/test_mat_scalar_ops.py +4 -4
- warp/tests/test_overwrite.py +0 -60
- warp/tests/test_quat.py +356 -151
- warp/tests/test_rand.py +44 -37
- warp/tests/test_sparse.py +47 -6
- warp/tests/test_spatial.py +75 -0
- warp/tests/test_static.py +1 -1
- warp/tests/test_utils.py +84 -4
- warp/tests/test_vec.py +336 -178
- warp/tests/tile/__init__.py +0 -0
- warp/tests/{test_tile.py → tile/test_tile.py} +136 -51
- warp/tests/{test_tile_load.py → tile/test_tile_load.py} +98 -1
- warp/tests/{test_tile_mathdx.py → tile/test_tile_mathdx.py} +9 -6
- warp/tests/{test_tile_mlp.py → tile/test_tile_mlp.py} +25 -14
- warp/tests/{test_tile_reduce.py → tile/test_tile_reduce.py} +60 -1
- warp/tests/{test_tile_view.py → tile/test_tile_view.py} +1 -1
- warp/tests/unittest_serial.py +1 -0
- warp/tests/unittest_suites.py +45 -62
- warp/tests/unittest_utils.py +2 -1
- warp/thirdparty/unittest_parallel.py +3 -1
- warp/types.py +175 -666
- warp/utils.py +137 -72
- {warp_lang-1.6.2.dist-info → warp_lang-1.7.1.dist-info}/METADATA +46 -12
- {warp_lang-1.6.2.dist-info → warp_lang-1.7.1.dist-info}/RECORD +184 -171
- {warp_lang-1.6.2.dist-info → warp_lang-1.7.1.dist-info}/WHEEL +1 -1
- {warp_lang-1.6.2.dist-info → warp_lang-1.7.1.dist-info/licenses}/LICENSE.md +0 -26
- warp/examples/optim/example_walker.py +0 -317
- warp/native/cutlass_gemm.cpp +0 -43
- warp/native/cutlass_gemm.cu +0 -382
- warp/tests/test_matmul.py +0 -511
- warp/tests/test_matmul_lite.py +0 -411
- warp/tests/test_vbd.py +0 -386
- warp/tests/unused_test_misc.py +0 -77
- /warp/tests/{test_async.py → cuda/test_async.py} +0 -0
- /warp/tests/{test_ipc.py → cuda/test_ipc.py} +0 -0
- /warp/tests/{test_multigpu.py → cuda/test_multigpu.py} +0 -0
- /warp/tests/{test_peer.py → cuda/test_peer.py} +0 -0
- /warp/tests/{test_pinned.py → cuda/test_pinned.py} +0 -0
- /warp/tests/{test_bvh.py → geometry/test_bvh.py} +0 -0
- /warp/tests/{test_hash_grid.py → geometry/test_hash_grid.py} +0 -0
- /warp/tests/{test_marching_cubes.py → geometry/test_marching_cubes.py} +0 -0
- /warp/tests/{test_mesh.py → geometry/test_mesh.py} +0 -0
- /warp/tests/{test_mesh_query_aabb.py → geometry/test_mesh_query_aabb.py} +0 -0
- /warp/tests/{test_volume_write.py → geometry/test_volume_write.py} +0 -0
- /warp/tests/{test_jax.py → interop/test_jax.py} +0 -0
- /warp/tests/{test_paddle.py → interop/test_paddle.py} +0 -0
- /warp/tests/{test_torch.py → interop/test_torch.py} +0 -0
- /warp/tests/{test_coloring.py → sim/test_coloring.py} +0 -0
- /warp/tests/{test_sim_grad_bounce_linear.py → sim/test_sim_grad_bounce_linear.py} +0 -0
- /warp/tests/{test_tile_shared_memory.py → tile/test_tile_shared_memory.py} +0 -0
- {warp_lang-1.6.2.dist-info → warp_lang-1.7.1.dist-info}/top_level.txt +0 -0
warp/sim/import_urdf.py
CHANGED
|
@@ -20,7 +20,6 @@ from typing import Union
|
|
|
20
20
|
import numpy as np
|
|
21
21
|
|
|
22
22
|
import warp as wp
|
|
23
|
-
import warp.sim
|
|
24
23
|
from warp.sim.model import Mesh
|
|
25
24
|
|
|
26
25
|
|
|
@@ -46,6 +45,7 @@ def parse_urdf(
|
|
|
46
45
|
joint_limit_lower=-1e6,
|
|
47
46
|
joint_limit_upper=1e6,
|
|
48
47
|
scale=1.0,
|
|
48
|
+
hide_visuals=False,
|
|
49
49
|
parse_visuals_as_colliders=False,
|
|
50
50
|
force_show_colliders=False,
|
|
51
51
|
enable_self_collisions=True,
|
|
@@ -79,6 +79,7 @@ def parse_urdf(
|
|
|
79
79
|
joint_limit_lower (float): The default lower joint limit if not specified in the URDF.
|
|
80
80
|
joint_limit_upper (float): The default upper joint limit if not specified in the URDF.
|
|
81
81
|
scale (float): The scaling factor to apply to the imported mechanism.
|
|
82
|
+
hide_visuals (bool): If True, hide visual shapes.
|
|
82
83
|
parse_visuals_as_colliders (bool): If True, the geometry defined under the `<visual>` tags is used for collision handling instead of the `<collision>` geometries.
|
|
83
84
|
force_show_colliders (bool): If True, the collision shapes are always shown, even if there are visual shapes.
|
|
84
85
|
enable_self_collisions (bool): If True, self-collisions are enabled.
|
|
@@ -173,6 +174,22 @@ def parse_urdf(
|
|
|
173
174
|
)
|
|
174
175
|
shapes.append(s)
|
|
175
176
|
|
|
177
|
+
for capsule in geo.findall("capsule"):
|
|
178
|
+
s = builder.add_shape_capsule(
|
|
179
|
+
body=link,
|
|
180
|
+
pos=wp.vec3(tf.p),
|
|
181
|
+
rot=wp.quat(tf.q),
|
|
182
|
+
radius=float(capsule.get("radius") or "1") * scale,
|
|
183
|
+
half_height=float(capsule.get("height") or "1") * 0.5 * scale,
|
|
184
|
+
density=density,
|
|
185
|
+
up_axis=2, # capsules in URDF are aligned with z-axis
|
|
186
|
+
is_visible=visible,
|
|
187
|
+
has_ground_collision=not just_visual,
|
|
188
|
+
has_shape_collision=not just_visual,
|
|
189
|
+
**contact_vars,
|
|
190
|
+
)
|
|
191
|
+
shapes.append(s)
|
|
192
|
+
|
|
176
193
|
for mesh in geo.findall("mesh"):
|
|
177
194
|
filename = mesh.get("filename")
|
|
178
195
|
if filename is None:
|
|
@@ -219,15 +236,15 @@ def parse_urdf(
|
|
|
219
236
|
scaling = np.array([float(x) * scale for x in scaling.split()])
|
|
220
237
|
if hasattr(m, "geometry"):
|
|
221
238
|
# multiple meshes are contained in a scene
|
|
222
|
-
for
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
239
|
+
for m_geom in m.geometry.values():
|
|
240
|
+
m_vertices = np.array(m_geom.vertices, dtype=np.float32) * scaling
|
|
241
|
+
m_faces = np.array(m_geom.faces.flatten(), dtype=np.int32)
|
|
242
|
+
m_mesh = Mesh(m_vertices, m_faces)
|
|
226
243
|
s = builder.add_shape_mesh(
|
|
227
244
|
body=link,
|
|
228
245
|
pos=wp.vec3(tf.p),
|
|
229
246
|
rot=wp.quat(tf.q),
|
|
230
|
-
mesh=
|
|
247
|
+
mesh=m_mesh,
|
|
231
248
|
density=density,
|
|
232
249
|
is_visible=visible,
|
|
233
250
|
has_ground_collision=not just_visual,
|
|
@@ -278,7 +295,7 @@ def parse_urdf(
|
|
|
278
295
|
if parse_visuals_as_colliders:
|
|
279
296
|
colliders = visuals
|
|
280
297
|
else:
|
|
281
|
-
s = parse_shapes(link, visuals, density=0.0, just_visual=True)
|
|
298
|
+
s = parse_shapes(link, visuals, density=0.0, just_visual=True, visible=not hide_visuals)
|
|
282
299
|
visual_shapes.extend(s)
|
|
283
300
|
|
|
284
301
|
show_colliders = force_show_colliders
|
|
@@ -309,10 +326,13 @@ def parse_urdf(
|
|
|
309
326
|
I_m = rot @ wp.mat33(I_m)
|
|
310
327
|
m = float(inertial.find("mass").get("value") or "0")
|
|
311
328
|
builder.body_mass[link] = m
|
|
312
|
-
builder.body_inv_mass[link] = 1.0 / m
|
|
329
|
+
builder.body_inv_mass[link] = 1.0 / m if m > 0.0 else 0.0
|
|
313
330
|
builder.body_com[link] = com
|
|
314
331
|
builder.body_inertia[link] = I_m
|
|
315
|
-
|
|
332
|
+
if any(x for x in I_m):
|
|
333
|
+
builder.body_inv_inertia[link] = wp.inverse(I_m)
|
|
334
|
+
else:
|
|
335
|
+
builder.body_inv_inertia[link] = I_m
|
|
316
336
|
if m == 0.0 and ensure_nonstatic_links:
|
|
317
337
|
# set the mass to something nonzero to ensure the body is dynamic
|
|
318
338
|
m = static_link_mass
|
|
@@ -369,7 +389,7 @@ def parse_urdf(
|
|
|
369
389
|
|
|
370
390
|
# topological sorting of joints because the FK solver will resolve body transforms
|
|
371
391
|
# in joint order and needs the parent link transform to be resolved before the child
|
|
372
|
-
visited =
|
|
392
|
+
visited = dict.fromkeys(link_index.keys(), False)
|
|
373
393
|
sorted_joints = []
|
|
374
394
|
|
|
375
395
|
# depth-first search
|
|
@@ -520,7 +540,7 @@ def parse_urdf(
|
|
|
520
540
|
|
|
521
541
|
builder.add_joint_d6(
|
|
522
542
|
linear_axes=[
|
|
523
|
-
|
|
543
|
+
wp.sim.JointAxis(
|
|
524
544
|
u,
|
|
525
545
|
limit_lower=lower * scale,
|
|
526
546
|
limit_upper=upper * scale,
|
|
@@ -530,7 +550,7 @@ def parse_urdf(
|
|
|
530
550
|
target_kd=joint_damping,
|
|
531
551
|
mode=joint_mode,
|
|
532
552
|
),
|
|
533
|
-
|
|
553
|
+
wp.sim.JointAxis(
|
|
534
554
|
v,
|
|
535
555
|
limit_lower=lower * scale,
|
|
536
556
|
limit_upper=upper * scale,
|
warp/sim/inertia.py
CHANGED
|
@@ -15,131 +15,14 @@
|
|
|
15
15
|
|
|
16
16
|
"""Helper functions for computing rigid body inertia properties."""
|
|
17
17
|
|
|
18
|
-
import
|
|
19
|
-
from typing import List, Union
|
|
18
|
+
from __future__ import annotations
|
|
20
19
|
|
|
21
20
|
import numpy as np
|
|
22
21
|
|
|
23
22
|
import warp as wp
|
|
24
23
|
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
def triangle_inertia(
|
|
28
|
-
p: wp.vec3,
|
|
29
|
-
q: wp.vec3,
|
|
30
|
-
r: wp.vec3,
|
|
31
|
-
density: float,
|
|
32
|
-
com: wp.vec3,
|
|
33
|
-
# outputs
|
|
34
|
-
mass: wp.array(dtype=float, ndim=1),
|
|
35
|
-
inertia: wp.array(dtype=wp.mat33, ndim=1),
|
|
36
|
-
):
|
|
37
|
-
pcom = p - com
|
|
38
|
-
qcom = q - com
|
|
39
|
-
rcom = r - com
|
|
40
|
-
|
|
41
|
-
Dm = wp.mat33(pcom[0], qcom[0], rcom[0], pcom[1], qcom[1], rcom[1], pcom[2], qcom[2], rcom[2])
|
|
42
|
-
|
|
43
|
-
volume = wp.abs(wp.determinant(Dm) / 6.0)
|
|
44
|
-
|
|
45
|
-
# accumulate mass
|
|
46
|
-
wp.atomic_add(mass, 0, 4.0 * density * volume)
|
|
47
|
-
|
|
48
|
-
alpha = wp.sqrt(5.0) / 5.0
|
|
49
|
-
mid = (com + p + q + r) / 4.0
|
|
50
|
-
off_mid = mid - com
|
|
51
|
-
|
|
52
|
-
# displacement of quadrature point from COM
|
|
53
|
-
d0 = alpha * (p - mid) + off_mid
|
|
54
|
-
d1 = alpha * (q - mid) + off_mid
|
|
55
|
-
d2 = alpha * (r - mid) + off_mid
|
|
56
|
-
d3 = alpha * (com - mid) + off_mid
|
|
57
|
-
|
|
58
|
-
# accumulate inertia
|
|
59
|
-
identity = wp.mat33(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
|
|
60
|
-
I = wp.dot(d0, d0) * identity - wp.outer(d0, d0)
|
|
61
|
-
I += wp.dot(d1, d1) * identity - wp.outer(d1, d1)
|
|
62
|
-
I += wp.dot(d2, d2) * identity - wp.outer(d2, d2)
|
|
63
|
-
I += wp.dot(d3, d3) * identity - wp.outer(d3, d3)
|
|
64
|
-
|
|
65
|
-
wp.atomic_add(inertia, 0, (density * volume) * I)
|
|
66
|
-
|
|
67
|
-
return volume
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@wp.kernel
|
|
71
|
-
def compute_solid_mesh_inertia(
|
|
72
|
-
# inputs
|
|
73
|
-
com: wp.vec3,
|
|
74
|
-
weight: float,
|
|
75
|
-
indices: wp.array(dtype=int, ndim=1),
|
|
76
|
-
vertices: wp.array(dtype=wp.vec3, ndim=1),
|
|
77
|
-
# outputs
|
|
78
|
-
mass: wp.array(dtype=float, ndim=1),
|
|
79
|
-
inertia: wp.array(dtype=wp.mat33, ndim=1),
|
|
80
|
-
volume: wp.array(dtype=float, ndim=1),
|
|
81
|
-
):
|
|
82
|
-
i = wp.tid()
|
|
83
|
-
|
|
84
|
-
p = vertices[indices[i * 3 + 0]]
|
|
85
|
-
q = vertices[indices[i * 3 + 1]]
|
|
86
|
-
r = vertices[indices[i * 3 + 2]]
|
|
87
|
-
|
|
88
|
-
vol = triangle_inertia(p, q, r, weight, com, mass, inertia)
|
|
89
|
-
wp.atomic_add(volume, 0, vol)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
@wp.kernel
|
|
93
|
-
def compute_hollow_mesh_inertia(
|
|
94
|
-
# inputs
|
|
95
|
-
com: wp.vec3,
|
|
96
|
-
density: float,
|
|
97
|
-
indices: wp.array(dtype=int, ndim=1),
|
|
98
|
-
vertices: wp.array(dtype=wp.vec3, ndim=1),
|
|
99
|
-
thickness: wp.array(dtype=float, ndim=1),
|
|
100
|
-
# outputs
|
|
101
|
-
mass: wp.array(dtype=float, ndim=1),
|
|
102
|
-
inertia: wp.array(dtype=wp.mat33, ndim=1),
|
|
103
|
-
volume: wp.array(dtype=float, ndim=1),
|
|
104
|
-
):
|
|
105
|
-
tid = wp.tid()
|
|
106
|
-
i = indices[tid * 3 + 0]
|
|
107
|
-
j = indices[tid * 3 + 1]
|
|
108
|
-
k = indices[tid * 3 + 2]
|
|
109
|
-
|
|
110
|
-
vi = vertices[i]
|
|
111
|
-
vj = vertices[j]
|
|
112
|
-
vk = vertices[k]
|
|
113
|
-
|
|
114
|
-
normal = -wp.normalize(wp.cross(vj - vi, vk - vi))
|
|
115
|
-
ti = normal * thickness[i]
|
|
116
|
-
tj = normal * thickness[j]
|
|
117
|
-
tk = normal * thickness[k]
|
|
118
|
-
|
|
119
|
-
# wedge vertices
|
|
120
|
-
vi0 = vi - ti
|
|
121
|
-
vi1 = vi + ti
|
|
122
|
-
vj0 = vj - tj
|
|
123
|
-
vj1 = vj + tj
|
|
124
|
-
vk0 = vk - tk
|
|
125
|
-
vk1 = vk + tk
|
|
126
|
-
|
|
127
|
-
triangle_inertia(vi0, vj0, vk0, density, com, mass, inertia)
|
|
128
|
-
triangle_inertia(vj0, vk1, vk0, density, com, mass, inertia)
|
|
129
|
-
triangle_inertia(vj0, vj1, vk1, density, com, mass, inertia)
|
|
130
|
-
triangle_inertia(vj0, vi1, vj1, density, com, mass, inertia)
|
|
131
|
-
triangle_inertia(vj0, vi0, vi1, density, com, mass, inertia)
|
|
132
|
-
triangle_inertia(vj1, vi1, vk1, density, com, mass, inertia)
|
|
133
|
-
triangle_inertia(vi1, vi0, vk0, density, com, mass, inertia)
|
|
134
|
-
triangle_inertia(vi1, vk0, vk1, density, com, mass, inertia)
|
|
135
|
-
|
|
136
|
-
# compute volume
|
|
137
|
-
a = wp.length(wp.cross(vj - vi, vk - vi)) * 0.5
|
|
138
|
-
vol = a * (thickness[i] + thickness[j] + thickness[k]) / 3.0
|
|
139
|
-
wp.atomic_add(volume, 0, vol)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
def compute_sphere_inertia(density: float, r: float) -> tuple:
|
|
25
|
+
def compute_sphere_inertia(density: float, r: float) -> tuple[float, wp.vec3, wp.mat33]:
|
|
143
26
|
"""Helper to compute mass and inertia of a solid sphere
|
|
144
27
|
|
|
145
28
|
Args:
|
|
@@ -151,7 +34,7 @@ def compute_sphere_inertia(density: float, r: float) -> tuple:
|
|
|
151
34
|
A tuple of (mass, inertia) with inertia specified around the origin
|
|
152
35
|
"""
|
|
153
36
|
|
|
154
|
-
v = 4.0 / 3.0 *
|
|
37
|
+
v = 4.0 / 3.0 * wp.pi * r * r * r
|
|
155
38
|
|
|
156
39
|
m = density * v
|
|
157
40
|
Ia = 2.0 / 5.0 * m * r * r
|
|
@@ -161,7 +44,7 @@ def compute_sphere_inertia(density: float, r: float) -> tuple:
|
|
|
161
44
|
return (m, wp.vec3(), I)
|
|
162
45
|
|
|
163
46
|
|
|
164
|
-
def compute_capsule_inertia(density: float, r: float, h: float) -> tuple:
|
|
47
|
+
def compute_capsule_inertia(density: float, r: float, h: float) -> tuple[float, wp.vec3, wp.mat33]:
|
|
165
48
|
"""Helper to compute mass and inertia of a solid capsule extending along the y-axis
|
|
166
49
|
|
|
167
50
|
Args:
|
|
@@ -174,8 +57,8 @@ def compute_capsule_inertia(density: float, r: float, h: float) -> tuple:
|
|
|
174
57
|
A tuple of (mass, inertia) with inertia specified around the origin
|
|
175
58
|
"""
|
|
176
59
|
|
|
177
|
-
ms = density * (4.0 / 3.0) *
|
|
178
|
-
mc = density *
|
|
60
|
+
ms = density * (4.0 / 3.0) * wp.pi * r * r * r
|
|
61
|
+
mc = density * wp.pi * r * r * h
|
|
179
62
|
|
|
180
63
|
# total mass
|
|
181
64
|
m = ms + mc
|
|
@@ -189,7 +72,7 @@ def compute_capsule_inertia(density: float, r: float, h: float) -> tuple:
|
|
|
189
72
|
return (m, wp.vec3(), I)
|
|
190
73
|
|
|
191
74
|
|
|
192
|
-
def compute_cylinder_inertia(density: float, r: float, h: float) -> tuple:
|
|
75
|
+
def compute_cylinder_inertia(density: float, r: float, h: float) -> tuple[float, wp.vec3, wp.mat33]:
|
|
193
76
|
"""Helper to compute mass and inertia of a solid cylinder extending along the y-axis
|
|
194
77
|
|
|
195
78
|
Args:
|
|
@@ -202,7 +85,7 @@ def compute_cylinder_inertia(density: float, r: float, h: float) -> tuple:
|
|
|
202
85
|
A tuple of (mass, inertia) with inertia specified around the origin
|
|
203
86
|
"""
|
|
204
87
|
|
|
205
|
-
m = density *
|
|
88
|
+
m = density * wp.pi * r * r * h
|
|
206
89
|
|
|
207
90
|
Ia = 1 / 12 * m * (3 * r * r + h * h)
|
|
208
91
|
Ib = 1 / 2 * m * r * r
|
|
@@ -212,7 +95,7 @@ def compute_cylinder_inertia(density: float, r: float, h: float) -> tuple:
|
|
|
212
95
|
return (m, wp.vec3(), I)
|
|
213
96
|
|
|
214
97
|
|
|
215
|
-
def compute_cone_inertia(density: float, r: float, h: float) -> tuple:
|
|
98
|
+
def compute_cone_inertia(density: float, r: float, h: float) -> tuple[float, wp.vec3, wp.mat33]:
|
|
216
99
|
"""Helper to compute mass and inertia of a solid cone extending along the y-axis
|
|
217
100
|
|
|
218
101
|
Args:
|
|
@@ -225,7 +108,7 @@ def compute_cone_inertia(density: float, r: float, h: float) -> tuple:
|
|
|
225
108
|
A tuple of (mass, inertia) with inertia specified around the origin
|
|
226
109
|
"""
|
|
227
110
|
|
|
228
|
-
m = density *
|
|
111
|
+
m = density * wp.pi * r * r * h / 3.0
|
|
229
112
|
|
|
230
113
|
Ia = 1 / 20 * m * (3 * r * r + 2 * h * h)
|
|
231
114
|
Ib = 3 / 10 * m * r * r
|
|
@@ -235,7 +118,7 @@ def compute_cone_inertia(density: float, r: float, h: float) -> tuple:
|
|
|
235
118
|
return (m, wp.vec3(), I)
|
|
236
119
|
|
|
237
120
|
|
|
238
|
-
def compute_box_inertia(density: float, w: float, h: float, d: float) -> tuple:
|
|
121
|
+
def compute_box_inertia(density: float, w: float, h: float, d: float) -> tuple[float, wp.vec3, wp.mat33]:
|
|
239
122
|
"""Helper to compute mass and inertia of a solid box
|
|
240
123
|
|
|
241
124
|
Args:
|
|
@@ -261,63 +144,213 @@ def compute_box_inertia(density: float, w: float, h: float, d: float) -> tuple:
|
|
|
261
144
|
return (m, wp.vec3(), I)
|
|
262
145
|
|
|
263
146
|
|
|
147
|
+
@wp.func
|
|
148
|
+
def triangle_inertia(
|
|
149
|
+
v0: wp.vec3,
|
|
150
|
+
v1: wp.vec3,
|
|
151
|
+
v2: wp.vec3,
|
|
152
|
+
):
|
|
153
|
+
vol = wp.dot(v0, wp.cross(v1, v2)) / 6.0 # tetra volume (0,v0,v1,v2)
|
|
154
|
+
first = vol * (v0 + v1 + v2) / 4.0 # first-order integral
|
|
155
|
+
|
|
156
|
+
# second-order integral (symmetric)
|
|
157
|
+
o00, o11, o22 = wp.outer(v0, v0), wp.outer(v1, v1), wp.outer(v2, v2)
|
|
158
|
+
o01, o02, o12 = wp.outer(v0, v1), wp.outer(v0, v2), wp.outer(v1, v2)
|
|
159
|
+
o01t, o02t, o12t = wp.transpose(o01), wp.transpose(o02), wp.transpose(o12)
|
|
160
|
+
|
|
161
|
+
second = (vol / 10.0) * (o00 + o11 + o22)
|
|
162
|
+
second += (vol / 20.0) * (o01 + o01t + o02 + o02t + o12 + o12t)
|
|
163
|
+
|
|
164
|
+
return vol, first, second
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@wp.kernel
|
|
168
|
+
def compute_solid_mesh_inertia(
|
|
169
|
+
indices: wp.array(dtype=int),
|
|
170
|
+
vertices: wp.array(dtype=wp.vec3),
|
|
171
|
+
# outputs
|
|
172
|
+
volume: wp.array(dtype=float),
|
|
173
|
+
first: wp.array(dtype=wp.vec3),
|
|
174
|
+
second: wp.array(dtype=wp.mat33),
|
|
175
|
+
):
|
|
176
|
+
i = wp.tid()
|
|
177
|
+
p = vertices[indices[i * 3 + 0]]
|
|
178
|
+
q = vertices[indices[i * 3 + 1]]
|
|
179
|
+
r = vertices[indices[i * 3 + 2]]
|
|
180
|
+
|
|
181
|
+
v, f, s = triangle_inertia(p, q, r)
|
|
182
|
+
wp.atomic_add(volume, 0, v)
|
|
183
|
+
wp.atomic_add(first, 0, f)
|
|
184
|
+
wp.atomic_add(second, 0, s)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@wp.kernel
|
|
188
|
+
def compute_hollow_mesh_inertia(
|
|
189
|
+
indices: wp.array(dtype=int),
|
|
190
|
+
vertices: wp.array(dtype=wp.vec3),
|
|
191
|
+
thickness: wp.array(dtype=float),
|
|
192
|
+
# outputs
|
|
193
|
+
volume: wp.array(dtype=float),
|
|
194
|
+
first: wp.array(dtype=wp.vec3),
|
|
195
|
+
second: wp.array(dtype=wp.mat33),
|
|
196
|
+
):
|
|
197
|
+
tid = wp.tid()
|
|
198
|
+
i = indices[tid * 3 + 0]
|
|
199
|
+
j = indices[tid * 3 + 1]
|
|
200
|
+
k = indices[tid * 3 + 2]
|
|
201
|
+
|
|
202
|
+
vi = vertices[i]
|
|
203
|
+
vj = vertices[j]
|
|
204
|
+
vk = vertices[k]
|
|
205
|
+
|
|
206
|
+
normal = -wp.normalize(wp.cross(vj - vi, vk - vi))
|
|
207
|
+
ti = normal * thickness[i]
|
|
208
|
+
tj = normal * thickness[j]
|
|
209
|
+
tk = normal * thickness[k]
|
|
210
|
+
|
|
211
|
+
# wedge vertices
|
|
212
|
+
vi0 = vi - ti
|
|
213
|
+
vi1 = vi + ti
|
|
214
|
+
vj0 = vj - tj
|
|
215
|
+
vj1 = vj + tj
|
|
216
|
+
vk0 = vk - tk
|
|
217
|
+
vk1 = vk + tk
|
|
218
|
+
|
|
219
|
+
v_total = 0.0
|
|
220
|
+
f_total = wp.vec3(0.0)
|
|
221
|
+
s_total = wp.mat33(0.0)
|
|
222
|
+
|
|
223
|
+
v, f, s = triangle_inertia(vi0, vj0, vk0)
|
|
224
|
+
v_total += v
|
|
225
|
+
f_total += f
|
|
226
|
+
s_total += s
|
|
227
|
+
v, f, s = triangle_inertia(vj0, vk1, vk0)
|
|
228
|
+
v_total += v
|
|
229
|
+
f_total += f
|
|
230
|
+
s_total += s
|
|
231
|
+
v, f, s = triangle_inertia(vj0, vj1, vk1)
|
|
232
|
+
v_total += v
|
|
233
|
+
f_total += f
|
|
234
|
+
s_total += s
|
|
235
|
+
v, f, s = triangle_inertia(vj0, vi1, vj1)
|
|
236
|
+
v_total += v
|
|
237
|
+
f_total += f
|
|
238
|
+
s_total += s
|
|
239
|
+
v, f, s = triangle_inertia(vj0, vi0, vi1)
|
|
240
|
+
v_total += v
|
|
241
|
+
f_total += f
|
|
242
|
+
s_total += s
|
|
243
|
+
v, f, s = triangle_inertia(vj1, vi1, vk1)
|
|
244
|
+
v_total += v
|
|
245
|
+
f_total += f
|
|
246
|
+
s_total += s
|
|
247
|
+
v, f, s = triangle_inertia(vi1, vi0, vk0)
|
|
248
|
+
v_total += v
|
|
249
|
+
f_total += f
|
|
250
|
+
s_total += s
|
|
251
|
+
v, f, s = triangle_inertia(vi1, vk0, vk1)
|
|
252
|
+
v_total += v
|
|
253
|
+
f_total += f
|
|
254
|
+
s_total += s
|
|
255
|
+
|
|
256
|
+
wp.atomic_add(volume, 0, v_total)
|
|
257
|
+
wp.atomic_add(first, 0, f_total)
|
|
258
|
+
wp.atomic_add(second, 0, s_total)
|
|
259
|
+
|
|
260
|
+
|
|
264
261
|
def compute_mesh_inertia(
|
|
265
|
-
density: float,
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
262
|
+
density: float,
|
|
263
|
+
vertices: list,
|
|
264
|
+
indices: list,
|
|
265
|
+
is_solid: bool = True,
|
|
266
|
+
thickness: list[float] | float = 0.001,
|
|
267
|
+
) -> tuple[float, wp.vec3, wp.mat33, float]:
|
|
268
|
+
"""
|
|
269
|
+
Compute the mass, center of mass, inertia, and volume of a triangular mesh.
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
density: The density of the mesh material.
|
|
273
|
+
vertices: A list of vertex positions (3D coordinates).
|
|
274
|
+
indices: A list of triangle indices (each triangle is defined by 3 vertex indices).
|
|
275
|
+
is_solid: If True, compute inertia for a solid mesh; if False, for a hollow mesh using the given thickness.
|
|
276
|
+
thickness: Thickness of the mesh if it is hollow. Can be a single value or a list of values for each vertex.
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
A tuple containing:
|
|
280
|
+
- mass: The mass of the mesh.
|
|
281
|
+
- com: The center of mass (3D coordinates).
|
|
282
|
+
- I: The inertia tensor (3x3 matrix).
|
|
283
|
+
- volume: The signed volume of the mesh.
|
|
284
|
+
"""
|
|
269
285
|
|
|
270
286
|
indices = np.array(indices).flatten()
|
|
271
287
|
num_tris = len(indices) // 3
|
|
272
288
|
|
|
273
|
-
# compute signed inertia for each tetrahedron
|
|
274
|
-
# formed with the interior point, using an order-2
|
|
275
|
-
# quadrature: https://www.sciencedirect.com/science/article/pii/S0377042712001604#br000040
|
|
276
|
-
|
|
277
289
|
# Allocating for mass and inertia
|
|
290
|
+
com_warp = wp.zeros(1, dtype=wp.vec3)
|
|
278
291
|
I_warp = wp.zeros(1, dtype=wp.mat33)
|
|
279
|
-
mass_warp = wp.zeros(1, dtype=float)
|
|
280
292
|
vol_warp = wp.zeros(1, dtype=float)
|
|
281
293
|
|
|
294
|
+
wp_vertices = wp.array(vertices, dtype=wp.vec3)
|
|
295
|
+
wp_indices = wp.array(indices, dtype=int)
|
|
296
|
+
|
|
282
297
|
if is_solid:
|
|
283
|
-
weight = 0.25
|
|
284
|
-
# alpha = math.sqrt(5.0) / 5.0
|
|
285
298
|
wp.launch(
|
|
286
299
|
kernel=compute_solid_mesh_inertia,
|
|
287
300
|
dim=num_tris,
|
|
288
301
|
inputs=[
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
302
|
+
wp_indices,
|
|
303
|
+
wp_vertices,
|
|
304
|
+
],
|
|
305
|
+
outputs=[
|
|
306
|
+
vol_warp,
|
|
307
|
+
com_warp,
|
|
308
|
+
I_warp,
|
|
293
309
|
],
|
|
294
|
-
outputs=[mass_warp, I_warp, vol_warp],
|
|
295
310
|
)
|
|
296
311
|
else:
|
|
297
|
-
weight = 0.25 * density
|
|
298
312
|
if isinstance(thickness, float):
|
|
299
313
|
thickness = [thickness] * len(vertices)
|
|
300
314
|
wp.launch(
|
|
301
315
|
kernel=compute_hollow_mesh_inertia,
|
|
302
316
|
dim=num_tris,
|
|
303
317
|
inputs=[
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
wp.array(indices, dtype=int),
|
|
307
|
-
wp.array(vertices, dtype=wp.vec3),
|
|
318
|
+
wp_indices,
|
|
319
|
+
wp_vertices,
|
|
308
320
|
wp.array(thickness, dtype=float),
|
|
309
321
|
],
|
|
310
|
-
outputs=[
|
|
322
|
+
outputs=[
|
|
323
|
+
vol_warp,
|
|
324
|
+
com_warp,
|
|
325
|
+
I_warp,
|
|
326
|
+
],
|
|
311
327
|
)
|
|
312
328
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
329
|
+
V_tot = float(vol_warp.numpy()[0]) # signed volume
|
|
330
|
+
F_tot = com_warp.numpy()[0] # first moment
|
|
331
|
+
S_tot = I_warp.numpy()[0] # second moment
|
|
332
|
+
|
|
333
|
+
# If the winding is inward, flip signs
|
|
334
|
+
if V_tot < 0:
|
|
335
|
+
V_tot = -V_tot
|
|
336
|
+
F_tot = -F_tot
|
|
337
|
+
S_tot = -S_tot
|
|
338
|
+
|
|
339
|
+
mass = density * V_tot
|
|
340
|
+
if V_tot > 0.0:
|
|
341
|
+
com = F_tot / V_tot
|
|
342
|
+
else:
|
|
343
|
+
com = F_tot
|
|
344
|
+
|
|
345
|
+
S_tot *= density # include density
|
|
346
|
+
I_origin = np.trace(S_tot) * np.eye(3) - S_tot # inertia about origin
|
|
347
|
+
r = com
|
|
348
|
+
I_com = I_origin - mass * ((r @ r) * np.eye(3) - np.outer(r, r))
|
|
349
|
+
|
|
350
|
+
return mass, wp.vec3(*com), wp.mat33(*I_com), V_tot
|
|
318
351
|
|
|
319
352
|
|
|
320
|
-
def transform_inertia(m, I, p, q):
|
|
353
|
+
def transform_inertia(m, I, p, q) -> wp.mat33:
|
|
321
354
|
R = wp.quat_to_matrix(q)
|
|
322
355
|
|
|
323
356
|
# Steiner's theorem
|
warp/sim/integrator_euler.py
CHANGED
|
@@ -42,6 +42,9 @@ def eval_springs(
|
|
|
42
42
|
i = spring_indices[tid * 2 + 0]
|
|
43
43
|
j = spring_indices[tid * 2 + 1]
|
|
44
44
|
|
|
45
|
+
if i == -1 or j == -1:
|
|
46
|
+
return
|
|
47
|
+
|
|
45
48
|
ke = spring_stiffness[tid]
|
|
46
49
|
kd = spring_damping[tid]
|
|
47
50
|
rest = spring_rest_lengths[tid]
|
|
@@ -559,7 +562,7 @@ def eval_tetrahedra(
|
|
|
559
562
|
v20 = v2 - v0
|
|
560
563
|
v30 = v3 - v0
|
|
561
564
|
|
|
562
|
-
Ds = wp.
|
|
565
|
+
Ds = wp.matrix_from_cols(x10, x20, x30)
|
|
563
566
|
Dm = pose[tid]
|
|
564
567
|
|
|
565
568
|
inv_rest_volume = wp.determinant(Dm) * 6.0
|
|
@@ -574,7 +577,7 @@ def eval_tetrahedra(
|
|
|
574
577
|
|
|
575
578
|
# F = Xs*Xm^-1
|
|
576
579
|
F = Ds * Dm
|
|
577
|
-
dFdt = wp.
|
|
580
|
+
dFdt = wp.matrix_from_cols(v10, v20, v30) * Dm
|
|
578
581
|
|
|
579
582
|
col1 = wp.vec3(F[0, 0], F[1, 0], F[2, 0])
|
|
580
583
|
col2 = wp.vec3(F[0, 1], F[1, 1], F[2, 1])
|
|
@@ -660,9 +663,9 @@ def eval_tetrahedra(
|
|
|
660
663
|
|
|
661
664
|
# alpha = 1.0
|
|
662
665
|
|
|
663
|
-
# I = wp.
|
|
664
|
-
#
|
|
665
|
-
#
|
|
666
|
+
# I = wp.matrix_from_cols(wp.vec3(1.0, 0.0, 0.0),
|
|
667
|
+
# wp.vec3(0.0, 1.0, 0.0),
|
|
668
|
+
# wp.vec3(0.0, 0.0, 1.0))
|
|
666
669
|
|
|
667
670
|
# P = (F + wp.transpose(F) + I*(0.0-2.0))*k_mu
|
|
668
671
|
# H = P * wp.transpose(Dm)
|
|
@@ -128,7 +128,7 @@ def spatial_transform_inertia(t: wp.transform, I: wp.spatial_matrix):
|
|
|
128
128
|
r2 = wp.quat_rotate(q, wp.vec3(0.0, 1.0, 0.0))
|
|
129
129
|
r3 = wp.quat_rotate(q, wp.vec3(0.0, 0.0, 1.0))
|
|
130
130
|
|
|
131
|
-
R = wp.
|
|
131
|
+
R = wp.matrix_from_cols(r1, r2, r3)
|
|
132
132
|
S = wp.skew(p) @ R
|
|
133
133
|
|
|
134
134
|
T = spatial_adjoint(R, S)
|
|
@@ -298,7 +298,7 @@ def jcalc_motion(
|
|
|
298
298
|
if type == wp.sim.JOINT_UNIVERSAL:
|
|
299
299
|
axis_0 = joint_axis[axis_start + 0]
|
|
300
300
|
axis_1 = joint_axis[axis_start + 1]
|
|
301
|
-
q_off = wp.quat_from_matrix(wp.
|
|
301
|
+
q_off = wp.quat_from_matrix(wp.matrix_from_cols(axis_0, axis_1, wp.cross(axis_0, axis_1)))
|
|
302
302
|
local_0 = wp.quat_rotate(q_off, wp.vec3(1.0, 0.0, 0.0))
|
|
303
303
|
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
304
304
|
|
|
@@ -319,7 +319,7 @@ def jcalc_motion(
|
|
|
319
319
|
axis_0 = joint_axis[axis_start + 0]
|
|
320
320
|
axis_1 = joint_axis[axis_start + 1]
|
|
321
321
|
axis_2 = joint_axis[axis_start + 2]
|
|
322
|
-
q_off = wp.quat_from_matrix(wp.
|
|
322
|
+
q_off = wp.quat_from_matrix(wp.matrix_from_cols(axis_0, axis_1, axis_2))
|
|
323
323
|
local_0 = wp.quat_rotate(q_off, wp.vec3(1.0, 0.0, 0.0))
|
|
324
324
|
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
325
325
|
local_2 = wp.quat_rotate(q_off, wp.vec3(0.0, 0.0, 1.0))
|
|
@@ -2066,13 +2066,6 @@ class FeatherstoneIntegrator(Integrator):
|
|
|
2066
2066
|
],
|
|
2067
2067
|
device=model.device,
|
|
2068
2068
|
)
|
|
2069
|
-
# if wp.context.runtime.tape:
|
|
2070
|
-
# wp.context.runtime.tape.record_func(
|
|
2071
|
-
# backward=lambda: adj_matmul(
|
|
2072
|
-
# a, b, c, a.grad, b.grad, c.grad, d.grad, alpha, beta, allow_tf32x3_arith, device
|
|
2073
|
-
# ),
|
|
2074
|
-
# arrays=[a, b, c, d],
|
|
2075
|
-
# )
|
|
2076
2069
|
# print("joint_qdd:")
|
|
2077
2070
|
# print(state_aug.joint_qdd.numpy())
|
|
2078
2071
|
# print("\n\n")
|