warp-lang 1.7.0__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/autograd.py +12 -2
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +1 -1
- warp/builtins.py +11 -10
- warp/codegen.py +17 -5
- warp/config.py +1 -1
- warp/context.py +6 -0
- warp/examples/benchmarks/benchmark_cloth.py +1 -1
- warp/examples/distributed/example_jacobi_mpi.py +507 -0
- 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 +5 -1
- warp/native/tile.h +11 -11
- warp/native/warp.cu +1 -1
- warp/render/render_opengl.py +19 -17
- warp/render/render_usd.py +93 -3
- 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 +29 -12
- warp/sim/render.py +4 -0
- warp/stubs.py +1 -1
- warp/tests/assets/torus.usda +1 -1
- warp/tests/sim/test_collision.py +237 -206
- warp/tests/sim/test_inertia.py +161 -0
- warp/tests/sim/{flaky_test_sim_grad.py → test_sim_grad.py} +4 -0
- warp/tests/sim/test_xpbd.py +399 -0
- warp/tests/test_codegen.py +24 -3
- warp/tests/test_examples.py +16 -6
- warp/tests/test_fem.py +75 -10
- warp/tests/test_mat.py +370 -103
- warp/tests/test_quat.py +321 -137
- warp/tests/test_vec.py +320 -174
- warp/tests/tile/test_tile_load.py +97 -0
- warp/tests/unittest_suites.py +2 -5
- warp/types.py +65 -8
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.1.dist-info}/METADATA +21 -9
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.1.dist-info}/RECORD +46 -43
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.1.dist-info}/WHEEL +1 -1
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.1.dist-info}/licenses/LICENSE.md +0 -26
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.1.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
|
|
@@ -3471,8 +3485,9 @@ class ModelBuilder:
|
|
|
3471
3485
|
self.shape_shape_collision.append(has_shape_collision)
|
|
3472
3486
|
|
|
3473
3487
|
(m, c, I) = compute_shape_mass(type, scale, src, density, is_solid, thickness)
|
|
3488
|
+
com_body = wp.transform_point(wp.transform(pos, rot), c)
|
|
3474
3489
|
|
|
3475
|
-
self._update_body_mass(body, m, I,
|
|
3490
|
+
self._update_body_mass(body, m, I, com_body, rot)
|
|
3476
3491
|
return shape
|
|
3477
3492
|
|
|
3478
3493
|
# particles
|
|
@@ -4010,15 +4025,16 @@ class ModelBuilder:
|
|
|
4010
4025
|
) # opposite 0, opposite 1, vertex 0, vertex 1
|
|
4011
4026
|
|
|
4012
4027
|
# skip constraints open edges
|
|
4013
|
-
|
|
4014
|
-
|
|
4028
|
+
spring_indices.add((min(e.v0, e.v1), max(e.v0, e.v1)))
|
|
4029
|
+
if e.f0 != -1:
|
|
4015
4030
|
spring_indices.add((min(e.o0, e.v0), max(e.o0, e.v0)))
|
|
4016
4031
|
spring_indices.add((min(e.o0, e.v1), max(e.o0, e.v1)))
|
|
4017
|
-
|
|
4032
|
+
if e.f1 != -1:
|
|
4018
4033
|
spring_indices.add((min(e.o1, e.v0), max(e.o1, e.v0)))
|
|
4019
4034
|
spring_indices.add((min(e.o1, e.v1), max(e.o1, e.v1)))
|
|
4020
4035
|
|
|
4021
|
-
|
|
4036
|
+
if e.f0 != -1 and e.f1 != -1:
|
|
4037
|
+
spring_indices.add((min(e.o0, e.o1), max(e.o0, e.o1)))
|
|
4022
4038
|
|
|
4023
4039
|
if add_springs:
|
|
4024
4040
|
for i, j in spring_indices:
|
|
@@ -4129,14 +4145,15 @@ class ModelBuilder:
|
|
|
4129
4145
|
if add_springs:
|
|
4130
4146
|
spring_indices = set()
|
|
4131
4147
|
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
4148
|
spring_indices.add((min(k, l), max(k, l)))
|
|
4149
|
+
if i != -1:
|
|
4150
|
+
spring_indices.add((min(i, k), max(i, k)))
|
|
4151
|
+
spring_indices.add((min(i, l), max(i, l)))
|
|
4152
|
+
if j != -1:
|
|
4153
|
+
spring_indices.add((min(j, k), max(j, k)))
|
|
4154
|
+
spring_indices.add((min(j, l), max(j, l)))
|
|
4155
|
+
if i != -1 and j != -1:
|
|
4156
|
+
spring_indices.add((min(i, j), max(i, j)))
|
|
4140
4157
|
|
|
4141
4158
|
for i, j in spring_indices:
|
|
4142
4159
|
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])
|
warp/stubs.py
CHANGED
|
@@ -713,7 +713,7 @@ def quaternion(dtype: Float) -> Quaternion[Float]:
|
|
|
713
713
|
|
|
714
714
|
|
|
715
715
|
@over
|
|
716
|
-
def quaternion(x: Float, y: Float, z: Float, w: Float) -> Quaternion[Float]:
|
|
716
|
+
def quaternion(x: Float, y: Float, z: Float, w: Float, dtype: Scalar) -> Quaternion[Float]:
|
|
717
717
|
"""Create a quaternion using the supplied components (type inferred from component type)."""
|
|
718
718
|
...
|
|
719
719
|
|