warp-lang 1.7.0__py3-none-macosx_10_13_universal2.whl → 1.7.2rc1__py3-none-macosx_10_13_universal2.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/autograd.py +12 -2
- warp/bin/libwarp-clang.dylib +0 -0
- warp/bin/libwarp.dylib +0 -0
- warp/build.py +1 -1
- warp/builtins.py +103 -66
- warp/codegen.py +48 -27
- warp/config.py +1 -1
- warp/context.py +112 -49
- warp/examples/benchmarks/benchmark_cloth.py +1 -1
- warp/examples/distributed/example_jacobi_mpi.py +507 -0
- warp/fem/cache.py +1 -1
- warp/fem/field/field.py +11 -1
- warp/fem/field/nodal_field.py +36 -22
- warp/fem/geometry/adaptive_nanogrid.py +7 -3
- warp/fem/geometry/trimesh.py +4 -12
- warp/jax_experimental/custom_call.py +14 -2
- warp/jax_experimental/ffi.py +100 -67
- warp/native/builtin.h +91 -65
- warp/native/svd.h +59 -49
- warp/native/tile.h +55 -26
- warp/native/volume.cpp +2 -2
- warp/native/volume_builder.cu +33 -22
- warp/native/warp.cu +1 -1
- warp/render/render_opengl.py +41 -34
- warp/render/render_usd.py +96 -6
- warp/sim/collide.py +11 -9
- warp/sim/inertia.py +189 -156
- warp/sim/integrator_euler.py +3 -0
- warp/sim/integrator_xpbd.py +3 -0
- warp/sim/model.py +56 -31
- warp/sim/render.py +4 -0
- warp/sparse.py +1 -1
- warp/stubs.py +73 -25
- warp/tests/assets/torus.usda +1 -1
- warp/tests/cuda/test_streams.py +1 -1
- warp/tests/sim/test_collision.py +237 -206
- warp/tests/sim/test_inertia.py +161 -0
- warp/tests/sim/test_model.py +5 -3
- warp/tests/sim/{flaky_test_sim_grad.py → test_sim_grad.py} +1 -4
- warp/tests/sim/test_xpbd.py +399 -0
- warp/tests/test_array.py +8 -7
- warp/tests/test_atomic.py +181 -2
- warp/tests/test_builtins_resolution.py +38 -38
- warp/tests/test_codegen.py +24 -3
- warp/tests/test_examples.py +16 -6
- warp/tests/test_fem.py +93 -14
- warp/tests/test_func.py +1 -1
- warp/tests/test_mat.py +416 -119
- warp/tests/test_quat.py +321 -137
- warp/tests/test_struct.py +116 -0
- warp/tests/test_vec.py +320 -174
- warp/tests/tile/test_tile.py +27 -0
- warp/tests/tile/test_tile_load.py +124 -0
- warp/tests/unittest_suites.py +2 -5
- warp/types.py +107 -9
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/METADATA +41 -19
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/RECORD +60 -57
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/WHEEL +1 -1
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/licenses/LICENSE.md +0 -26
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/top_level.txt +0 -0
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
warp/sim/integrator_xpbd.py
CHANGED
warp/sim/model.py
CHANGED
|
@@ -633,6 +633,7 @@ class Model:
|
|
|
633
633
|
soft_contact_body_pos (array), Positional offset of soft contact point in body frame, shape [soft_contact_max], vec3
|
|
634
634
|
soft_contact_body_vel (array), Linear velocity of soft contact point in body frame, shape [soft_contact_max], vec3
|
|
635
635
|
soft_contact_normal (array), Contact surface normal of soft contact point in world space, shape [soft_contact_max], vec3
|
|
636
|
+
soft_contact_tids (array), Thread indices of the soft contact points, shape [soft_contact_max], int
|
|
636
637
|
|
|
637
638
|
rigid_contact_max (int): Maximum number of potential rigid body contact points to generate ignoring the `rigid_mesh_contact_max` limit.
|
|
638
639
|
rigid_contact_max_limited (int): Maximum number of potential rigid body contact points to generate respecting the `rigid_mesh_contact_max` limit.
|
|
@@ -650,6 +651,12 @@ class Model:
|
|
|
650
651
|
rigid_contact_thickness (array): Total contact thickness, shape [rigid_contact_max], float
|
|
651
652
|
rigid_contact_shape0 (array): Index of shape 0 per contact, shape [rigid_contact_max], int
|
|
652
653
|
rigid_contact_shape1 (array): Index of shape 1 per contact, shape [rigid_contact_max], int
|
|
654
|
+
rigid_contact_tids (array): Triangle indices of the contact points, shape [rigid_contact_max], int
|
|
655
|
+
rigid_contact_pairwise_counter (array): Pairwise counter for contact generation, shape [rigid_contact_max], int
|
|
656
|
+
rigid_contact_broad_shape0 (array): Broadphase shape index of shape 0 per contact, shape [rigid_contact_max], int
|
|
657
|
+
rigid_contact_broad_shape1 (array): Broadphase shape index of shape 1 per contact, shape [rigid_contact_max], int
|
|
658
|
+
rigid_contact_point_id (array): Contact point ID, shape [rigid_contact_max], int
|
|
659
|
+
rigid_contact_point_limit (array): Contact point limit, shape [rigid_contact_max], int
|
|
653
660
|
|
|
654
661
|
ground (bool): Whether the ground plane and ground contacts are enabled
|
|
655
662
|
ground_plane (array): Ground plane 3D normal and offset, shape [4], float
|
|
@@ -805,6 +812,7 @@ class Model:
|
|
|
805
812
|
self.soft_contact_body_pos = None
|
|
806
813
|
self.soft_contact_body_vel = None
|
|
807
814
|
self.soft_contact_normal = None
|
|
815
|
+
self.soft_contact_tids = None
|
|
808
816
|
|
|
809
817
|
self.rigid_contact_max = 0
|
|
810
818
|
self.rigid_contact_max_limited = 0
|
|
@@ -822,6 +830,12 @@ class Model:
|
|
|
822
830
|
self.rigid_contact_thickness = None
|
|
823
831
|
self.rigid_contact_shape0 = None
|
|
824
832
|
self.rigid_contact_shape1 = None
|
|
833
|
+
self.rigid_contact_tids = None
|
|
834
|
+
self.rigid_contact_pairwise_counter = None
|
|
835
|
+
self.rigid_contact_broad_shape0 = None
|
|
836
|
+
self.rigid_contact_broad_shape1 = None
|
|
837
|
+
self.rigid_contact_point_id = None
|
|
838
|
+
self.rigid_contact_point_limit = None
|
|
825
839
|
|
|
826
840
|
# toggles ground contact for all shapes
|
|
827
841
|
self.ground = True
|
|
@@ -1380,7 +1394,13 @@ class ModelBuilder:
|
|
|
1380
1394
|
def add_articulation(self):
|
|
1381
1395
|
self.articulation_start.append(self.joint_count)
|
|
1382
1396
|
|
|
1383
|
-
def add_builder(
|
|
1397
|
+
def add_builder(
|
|
1398
|
+
self,
|
|
1399
|
+
builder: ModelBuilder,
|
|
1400
|
+
xform: Transform | None = None,
|
|
1401
|
+
update_num_env_count: bool = True,
|
|
1402
|
+
separate_collision_group: bool = True,
|
|
1403
|
+
):
|
|
1384
1404
|
"""Copies the data from `builder`, another `ModelBuilder` to this `ModelBuilder`.
|
|
1385
1405
|
|
|
1386
1406
|
Args:
|
|
@@ -1429,7 +1449,7 @@ class ModelBuilder:
|
|
|
1429
1449
|
self.shape_body.append(-1)
|
|
1430
1450
|
# apply offset transform to root bodies
|
|
1431
1451
|
if xform is not None:
|
|
1432
|
-
self.shape_transform.append(xform * builder.shape_transform[s])
|
|
1452
|
+
self.shape_transform.append(xform * wp.transform(*builder.shape_transform[s]))
|
|
1433
1453
|
else:
|
|
1434
1454
|
self.shape_transform.append(builder.shape_transform[s])
|
|
1435
1455
|
|
|
@@ -1448,7 +1468,7 @@ class ModelBuilder:
|
|
|
1448
1468
|
joint_q[qi : qi + 3] = tf.p
|
|
1449
1469
|
joint_q[qi + 3 : qi + 7] = tf.q
|
|
1450
1470
|
elif builder.joint_parent[i] == -1:
|
|
1451
|
-
joint_X_p[i] = xform * joint_X_p[i]
|
|
1471
|
+
joint_X_p[i] = xform * wp.transform(*joint_X_p[i])
|
|
1452
1472
|
self.joint_X_p.extend(joint_X_p)
|
|
1453
1473
|
self.joint_q.extend(joint_q)
|
|
1454
1474
|
|
|
@@ -1464,7 +1484,7 @@ class ModelBuilder:
|
|
|
1464
1484
|
|
|
1465
1485
|
for i in range(builder.body_count):
|
|
1466
1486
|
if xform is not None:
|
|
1467
|
-
self.body_q.append(xform * builder.body_q[i])
|
|
1487
|
+
self.body_q.append(xform * wp.transform(*builder.body_q[i]))
|
|
1468
1488
|
else:
|
|
1469
1489
|
self.body_q.append(builder.body_q[i])
|
|
1470
1490
|
|
|
@@ -2580,22 +2600,24 @@ class ModelBuilder:
|
|
|
2580
2600
|
)
|
|
2581
2601
|
if last_dynamic_body > -1:
|
|
2582
2602
|
self.shape_body[shape] = body_data[last_dynamic_body]["id"]
|
|
2583
|
-
source_m = body_data[last_dynamic_body]["mass"]
|
|
2584
|
-
source_com = body_data[last_dynamic_body]["com"]
|
|
2585
|
-
# add inertia to last_dynamic_body
|
|
2586
|
-
m = body_data[child_body]["mass"]
|
|
2587
|
-
com = wp.transform_point(incoming_xform, body_data[child_body]["com"])
|
|
2588
|
-
inertia = body_data[child_body]["inertia"]
|
|
2589
|
-
body_data[last_dynamic_body]["inertia"] += wp.sim.transform_inertia(
|
|
2590
|
-
m, inertia, incoming_xform.p, incoming_xform.q
|
|
2591
|
-
)
|
|
2592
|
-
body_data[last_dynamic_body]["mass"] += m
|
|
2593
|
-
body_data[last_dynamic_body]["com"] = (m * com + source_m * source_com) / (m + source_m)
|
|
2594
2603
|
body_data[last_dynamic_body]["shapes"].append(shape)
|
|
2595
|
-
# indicate to recompute inverse mass, inertia for this body
|
|
2596
|
-
body_data[last_dynamic_body]["inv_mass"] = None
|
|
2597
2604
|
else:
|
|
2598
2605
|
self.shape_body[shape] = -1
|
|
2606
|
+
|
|
2607
|
+
if last_dynamic_body > -1:
|
|
2608
|
+
source_m = body_data[last_dynamic_body]["mass"]
|
|
2609
|
+
source_com = body_data[last_dynamic_body]["com"]
|
|
2610
|
+
# add inertia to last_dynamic_body
|
|
2611
|
+
m = body_data[child_body]["mass"]
|
|
2612
|
+
com = wp.transform_point(incoming_xform, body_data[child_body]["com"])
|
|
2613
|
+
inertia = body_data[child_body]["inertia"]
|
|
2614
|
+
body_data[last_dynamic_body]["inertia"] += wp.sim.transform_inertia(
|
|
2615
|
+
m, inertia, incoming_xform.p, incoming_xform.q
|
|
2616
|
+
)
|
|
2617
|
+
body_data[last_dynamic_body]["mass"] += m
|
|
2618
|
+
body_data[last_dynamic_body]["com"] = (m * com + source_m * source_com) / (m + source_m)
|
|
2619
|
+
# indicate to recompute inverse mass, inertia for this body
|
|
2620
|
+
body_data[last_dynamic_body]["inv_mass"] = None
|
|
2599
2621
|
else:
|
|
2600
2622
|
joint["parent_xform"] = incoming_xform * joint["parent_xform"]
|
|
2601
2623
|
joint["parent"] = last_dynamic_body
|
|
@@ -3470,9 +3492,10 @@ class ModelBuilder:
|
|
|
3470
3492
|
self.shape_ground_collision.append(has_ground_collision)
|
|
3471
3493
|
self.shape_shape_collision.append(has_shape_collision)
|
|
3472
3494
|
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3495
|
+
if density > 0.0:
|
|
3496
|
+
(m, c, I) = compute_shape_mass(type, scale, src, density, is_solid, thickness)
|
|
3497
|
+
com_body = wp.transform_point(wp.transform(pos, rot), c)
|
|
3498
|
+
self._update_body_mass(body, m, I, com_body, rot)
|
|
3476
3499
|
return shape
|
|
3477
3500
|
|
|
3478
3501
|
# particles
|
|
@@ -4010,15 +4033,16 @@ class ModelBuilder:
|
|
|
4010
4033
|
) # opposite 0, opposite 1, vertex 0, vertex 1
|
|
4011
4034
|
|
|
4012
4035
|
# skip constraints open edges
|
|
4013
|
-
|
|
4014
|
-
|
|
4036
|
+
spring_indices.add((min(e.v0, e.v1), max(e.v0, e.v1)))
|
|
4037
|
+
if e.f0 != -1:
|
|
4015
4038
|
spring_indices.add((min(e.o0, e.v0), max(e.o0, e.v0)))
|
|
4016
4039
|
spring_indices.add((min(e.o0, e.v1), max(e.o0, e.v1)))
|
|
4017
|
-
|
|
4040
|
+
if e.f1 != -1:
|
|
4018
4041
|
spring_indices.add((min(e.o1, e.v0), max(e.o1, e.v0)))
|
|
4019
4042
|
spring_indices.add((min(e.o1, e.v1), max(e.o1, e.v1)))
|
|
4020
4043
|
|
|
4021
|
-
|
|
4044
|
+
if e.f0 != -1 and e.f1 != -1:
|
|
4045
|
+
spring_indices.add((min(e.o0, e.o1), max(e.o0, e.o1)))
|
|
4022
4046
|
|
|
4023
4047
|
if add_springs:
|
|
4024
4048
|
for i, j in spring_indices:
|
|
@@ -4129,14 +4153,15 @@ class ModelBuilder:
|
|
|
4129
4153
|
if add_springs:
|
|
4130
4154
|
spring_indices = set()
|
|
4131
4155
|
for i, j, k, l in edge_indices:
|
|
4132
|
-
spring_indices.add((min(i, j), max(i, j)))
|
|
4133
|
-
spring_indices.add((min(i, k), max(i, k)))
|
|
4134
|
-
spring_indices.add((min(i, l), max(i, l)))
|
|
4135
|
-
|
|
4136
|
-
spring_indices.add((min(j, k), max(j, k)))
|
|
4137
|
-
spring_indices.add((min(j, l), max(j, l)))
|
|
4138
|
-
|
|
4139
4156
|
spring_indices.add((min(k, l), max(k, l)))
|
|
4157
|
+
if i != -1:
|
|
4158
|
+
spring_indices.add((min(i, k), max(i, k)))
|
|
4159
|
+
spring_indices.add((min(i, l), max(i, l)))
|
|
4160
|
+
if j != -1:
|
|
4161
|
+
spring_indices.add((min(j, k), max(j, k)))
|
|
4162
|
+
spring_indices.add((min(j, l), max(j, l)))
|
|
4163
|
+
if i != -1 and j != -1:
|
|
4164
|
+
spring_indices.add((min(i, j), max(i, j)))
|
|
4140
4165
|
|
|
4141
4166
|
for i, j in spring_indices:
|
|
4142
4167
|
self.add_spring(i, j, spring_ke, spring_kd, control=0.0)
|
warp/sim/render.py
CHANGED
|
@@ -273,6 +273,10 @@ def CreateSimRenderer(renderer):
|
|
|
273
273
|
continue
|
|
274
274
|
tf = joint_tf[i]
|
|
275
275
|
body = int(joint_parent[i])
|
|
276
|
+
if body >= 0 and body < len(self.body_names):
|
|
277
|
+
body = self.body_names[body]
|
|
278
|
+
else:
|
|
279
|
+
body = None
|
|
276
280
|
# if body == -1:
|
|
277
281
|
# continue
|
|
278
282
|
num_linear_axes = int(joint_axis_dim[i][0])
|