warp-lang 1.6.0__py3-none-manylinux2014_x86_64.whl → 1.6.1__py3-none-manylinux2014_x86_64.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/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/builtins.py +1 -1
- warp/codegen.py +10 -3
- warp/config.py +65 -21
- warp/context.py +202 -65
- warp/examples/core/example_marching_cubes.py +1 -1
- warp/examples/core/example_mesh.py +1 -1
- warp/examples/core/example_wave.py +1 -1
- warp/examples/sim/example_cloth_self_contact.py +81 -27
- warp/examples/tile/example_tile_nbody.py +26 -15
- warp/native/clang/clang.cpp +1 -1
- warp/native/crt.h +1 -0
- warp/native/mat.h +16 -3
- warp/native/tile.h +12 -8
- warp/render/render_opengl.py +23 -15
- warp/render/render_usd.py +10 -2
- warp/sim/collide.py +29 -16
- warp/sim/import_urdf.py +20 -5
- warp/sim/integrator_featherstone.py +4 -11
- warp/sim/model.py +62 -59
- warp/sim/render.py +2 -2
- warp/stubs.py +1 -1
- warp/tests/test_array.py +26 -0
- warp/tests/test_collision.py +6 -6
- warp/tests/test_examples.py +7 -1
- warp/tests/test_launch.py +77 -26
- warp/tests/test_mat.py +75 -1
- warp/tests/test_overwrite.py +4 -3
- warp/tests/test_tile_load.py +44 -1
- warp/thirdparty/unittest_parallel.py +3 -0
- warp/types.py +66 -68
- {warp_lang-1.6.0.dist-info → warp_lang-1.6.1.dist-info}/METADATA +34 -17
- {warp_lang-1.6.0.dist-info → warp_lang-1.6.1.dist-info}/RECORD +37 -37
- {warp_lang-1.6.0.dist-info → warp_lang-1.6.1.dist-info}/WHEEL +1 -1
- {warp_lang-1.6.0.dist-info → warp_lang-1.6.1.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.6.0.dist-info → warp_lang-1.6.1.dist-info}/top_level.txt +0 -0
warp/sim/collide.py
CHANGED
|
@@ -837,6 +837,7 @@ def count_contact_points(
|
|
|
837
837
|
num_actual_contacts = 8 + 4
|
|
838
838
|
else:
|
|
839
839
|
num_contacts = 8
|
|
840
|
+
num_actual_contacts = 8
|
|
840
841
|
elif actual_type_a == wp.sim.GEO_MESH:
|
|
841
842
|
mesh_a = wp.mesh_get(geo.source[actual_shape_a])
|
|
842
843
|
num_contacts_a = mesh_a.points.shape[0]
|
|
@@ -1744,7 +1745,7 @@ def compute_tri_aabbs(
|
|
|
1744
1745
|
v2 = pos[tri_indices[t_id, 1]]
|
|
1745
1746
|
v3 = pos[tri_indices[t_id, 2]]
|
|
1746
1747
|
|
|
1747
|
-
|
|
1748
|
+
lower, upper = compute_tri_aabb(v1, v2, v3)
|
|
1748
1749
|
|
|
1749
1750
|
lower_bounds[t_id] = lower
|
|
1750
1751
|
upper_bounds[t_id] = upper
|
|
@@ -1809,7 +1810,7 @@ def init_triangle_collision_data_kernel(
|
|
|
1809
1810
|
@wp.kernel
|
|
1810
1811
|
def vertex_triangle_collision_detection_kernel(
|
|
1811
1812
|
query_radius: float,
|
|
1812
|
-
|
|
1813
|
+
bvh_id: wp.uint64,
|
|
1813
1814
|
pos: wp.array(dtype=wp.vec3),
|
|
1814
1815
|
tri_indices: wp.array(dtype=wp.int32, ndim=2),
|
|
1815
1816
|
vertex_colliding_triangles_offsets: wp.array(dtype=wp.int32),
|
|
@@ -1840,7 +1841,7 @@ def vertex_triangle_collision_detection_kernel(
|
|
|
1840
1841
|
and vertex_colliding_triangles_count.
|
|
1841
1842
|
|
|
1842
1843
|
Attributes:
|
|
1843
|
-
|
|
1844
|
+
bvh_id (int): the bvh id you want to collide with
|
|
1844
1845
|
query_radius (float): the contact radius. vertex-triangle pairs whose distance are less than this will get detected
|
|
1845
1846
|
pos (array): positions of all the vertices that make up triangles
|
|
1846
1847
|
vertex_colliding_triangles (array): flattened buffer of vertices' collision triangles
|
|
@@ -1862,12 +1863,12 @@ def vertex_triangle_collision_detection_kernel(
|
|
|
1862
1863
|
lower = wp.vec3(v[0] - query_radius, v[1] - query_radius, v[2] - query_radius)
|
|
1863
1864
|
upper = wp.vec3(v[0] + query_radius, v[1] + query_radius, v[2] + query_radius)
|
|
1864
1865
|
|
|
1865
|
-
query = wp.
|
|
1866
|
+
query = wp.bvh_query_aabb(bvh_id, lower, upper)
|
|
1866
1867
|
|
|
1867
1868
|
tri_index = wp.int32(0)
|
|
1868
1869
|
vertex_num_collisions = wp.int32(0)
|
|
1869
1870
|
min_dis_to_tris = query_radius
|
|
1870
|
-
while wp.
|
|
1871
|
+
while wp.bvh_query_next(query, tri_index):
|
|
1871
1872
|
t1 = tri_indices[tri_index, 0]
|
|
1872
1873
|
t2 = tri_indices[tri_index, 1]
|
|
1873
1874
|
t3 = tri_indices[tri_index, 2]
|
|
@@ -1991,7 +1992,7 @@ def edge_colliding_edges_detection_kernel(
|
|
|
1991
1992
|
|
|
1992
1993
|
@wp.kernel
|
|
1993
1994
|
def triangle_triangle_collision_detection_kernel(
|
|
1994
|
-
|
|
1995
|
+
bvh_id: wp.uint64,
|
|
1995
1996
|
pos: wp.array(dtype=wp.vec3),
|
|
1996
1997
|
tri_indices: wp.array(dtype=wp.int32, ndim=2),
|
|
1997
1998
|
triangle_intersecting_triangles_offsets: wp.array(dtype=wp.int32),
|
|
@@ -2014,10 +2015,10 @@ def triangle_triangle_collision_detection_kernel(
|
|
|
2014
2015
|
buffer_offset = triangle_intersecting_triangles_offsets[tri_index]
|
|
2015
2016
|
buffer_size = triangle_intersecting_triangles_offsets[tri_index + 1] - buffer_offset
|
|
2016
2017
|
|
|
2017
|
-
query = wp.
|
|
2018
|
+
query = wp.bvh_query_aabb(bvh_id, lower, upper)
|
|
2018
2019
|
tri_index_2 = wp.int32(0)
|
|
2019
2020
|
intersection_count = wp.int32(0)
|
|
2020
|
-
while wp.
|
|
2021
|
+
while wp.bvh_query_next(query, tri_index_2):
|
|
2021
2022
|
t2_v1 = tri_indices[tri_index_2, 0]
|
|
2022
2023
|
t2_v2 = tri_indices[tri_index_2, 1]
|
|
2023
2024
|
t2_v3 = tri_indices[tri_index_2, 2]
|
|
@@ -2129,7 +2130,16 @@ class TriMeshCollisionDetector:
|
|
|
2129
2130
|
|
|
2130
2131
|
self.edge_edge_parallel_epsilon = edge_edge_parallel_epsilon
|
|
2131
2132
|
|
|
2132
|
-
self.
|
|
2133
|
+
self.lower_bounds_tris = wp.array(shape=(model.tri_count,), dtype=wp.vec3, device=model.device)
|
|
2134
|
+
self.upper_bounds_tris = wp.array(shape=(model.tri_count,), dtype=wp.vec3, device=model.device)
|
|
2135
|
+
wp.launch(
|
|
2136
|
+
kernel=compute_tri_aabbs,
|
|
2137
|
+
inputs=[self.vertex_positions, model.tri_indices, self.lower_bounds_tris, self.upper_bounds_tris],
|
|
2138
|
+
dim=model.tri_count,
|
|
2139
|
+
device=model.device,
|
|
2140
|
+
)
|
|
2141
|
+
|
|
2142
|
+
self.bvh_tris = wp.Bvh(self.lower_bounds_tris, self.upper_bounds_tris)
|
|
2133
2143
|
|
|
2134
2144
|
# collision detections results
|
|
2135
2145
|
|
|
@@ -2244,15 +2254,18 @@ class TriMeshCollisionDetector:
|
|
|
2244
2254
|
def refit(self, new_pos=None):
|
|
2245
2255
|
if new_pos is not None:
|
|
2246
2256
|
self.vertex_positions = new_pos
|
|
2247
|
-
# this will automatically apply refit
|
|
2248
|
-
self.mesh_tris.points = new_pos
|
|
2249
|
-
else:
|
|
2250
|
-
self.refit_triangles()
|
|
2251
2257
|
|
|
2258
|
+
self.refit_triangles()
|
|
2252
2259
|
self.refit_edges()
|
|
2253
2260
|
|
|
2254
2261
|
def refit_triangles(self):
|
|
2255
|
-
|
|
2262
|
+
wp.launch(
|
|
2263
|
+
kernel=compute_tri_aabbs,
|
|
2264
|
+
inputs=[self.vertex_positions, self.model.tri_indices, self.lower_bounds_tris, self.upper_bounds_tris],
|
|
2265
|
+
dim=self.model.tri_count,
|
|
2266
|
+
device=self.model.device,
|
|
2267
|
+
)
|
|
2268
|
+
self.bvh_tris.refit()
|
|
2256
2269
|
|
|
2257
2270
|
def refit_edges(self):
|
|
2258
2271
|
wp.launch(
|
|
@@ -2282,7 +2295,7 @@ class TriMeshCollisionDetector:
|
|
|
2282
2295
|
kernel=vertex_triangle_collision_detection_kernel,
|
|
2283
2296
|
inputs=[
|
|
2284
2297
|
query_radius,
|
|
2285
|
-
self.
|
|
2298
|
+
self.bvh_tris.id,
|
|
2286
2299
|
self.vertex_positions,
|
|
2287
2300
|
self.model.tri_indices,
|
|
2288
2301
|
self.vertex_colliding_triangles_offsets,
|
|
@@ -2348,7 +2361,7 @@ class TriMeshCollisionDetector:
|
|
|
2348
2361
|
wp.launch(
|
|
2349
2362
|
kernel=triangle_triangle_collision_detection_kernel,
|
|
2350
2363
|
inputs=[
|
|
2351
|
-
self.
|
|
2364
|
+
self.bvh_tris.id,
|
|
2352
2365
|
self.vertex_positions,
|
|
2353
2366
|
self.model.tri_indices,
|
|
2354
2367
|
self.triangle_intersecting_triangles_offsets,
|
warp/sim/import_urdf.py
CHANGED
|
@@ -12,6 +12,7 @@ from typing import Union
|
|
|
12
12
|
import numpy as np
|
|
13
13
|
|
|
14
14
|
import warp as wp
|
|
15
|
+
import warp.sim
|
|
15
16
|
from warp.sim.model import Mesh
|
|
16
17
|
|
|
17
18
|
|
|
@@ -20,7 +21,7 @@ def parse_urdf(
|
|
|
20
21
|
builder,
|
|
21
22
|
xform=None,
|
|
22
23
|
floating=False,
|
|
23
|
-
base_joint: Union[dict, str] = None,
|
|
24
|
+
base_joint: Union[dict, str, None] = None,
|
|
24
25
|
density=1000.0,
|
|
25
26
|
stiffness=100.0,
|
|
26
27
|
damping=10.0,
|
|
@@ -511,11 +512,25 @@ def parse_urdf(
|
|
|
511
512
|
|
|
512
513
|
builder.add_joint_d6(
|
|
513
514
|
linear_axes=[
|
|
514
|
-
|
|
515
|
-
u,
|
|
515
|
+
warp.sim.JointAxis(
|
|
516
|
+
u,
|
|
517
|
+
limit_lower=lower * scale,
|
|
518
|
+
limit_upper=upper * scale,
|
|
519
|
+
limit_ke=limit_ke,
|
|
520
|
+
limit_kd=limit_kd,
|
|
521
|
+
target_ke=stiffness,
|
|
522
|
+
target_kd=joint_damping,
|
|
523
|
+
mode=joint_mode,
|
|
516
524
|
),
|
|
517
|
-
|
|
518
|
-
v,
|
|
525
|
+
warp.sim.JointAxis(
|
|
526
|
+
v,
|
|
527
|
+
limit_lower=lower * scale,
|
|
528
|
+
limit_upper=upper * scale,
|
|
529
|
+
limit_ke=limit_ke,
|
|
530
|
+
limit_kd=limit_kd,
|
|
531
|
+
target_ke=stiffness,
|
|
532
|
+
target_kd=joint_damping,
|
|
533
|
+
mode=joint_mode,
|
|
519
534
|
),
|
|
520
535
|
],
|
|
521
536
|
**joint_params,
|
|
@@ -1177,14 +1177,7 @@ def create_inertia_matrix_kernel(num_joints, num_dofs):
|
|
|
1177
1177
|
P_body = wp.tile_matmul(M_body, J_body)
|
|
1178
1178
|
|
|
1179
1179
|
# assign to the P slice
|
|
1180
|
-
wp.tile_assign(
|
|
1181
|
-
P,
|
|
1182
|
-
P_body,
|
|
1183
|
-
offset=(
|
|
1184
|
-
i * 6,
|
|
1185
|
-
0,
|
|
1186
|
-
),
|
|
1187
|
-
)
|
|
1180
|
+
wp.tile_assign(P, P_body, offset=(i * 6, 0))
|
|
1188
1181
|
|
|
1189
1182
|
# compute H = J^T*P
|
|
1190
1183
|
H = wp.tile_matmul(wp.tile_transpose(J), P)
|
|
@@ -1205,9 +1198,9 @@ def create_batched_cholesky_kernel(num_dofs):
|
|
|
1205
1198
|
|
|
1206
1199
|
a = wp.tile_load(A[articulation], shape=(num_dofs, num_dofs), storage="shared")
|
|
1207
1200
|
r = wp.tile_load(R[articulation], shape=num_dofs, storage="shared")
|
|
1208
|
-
wp.tile_diag_add(a, r)
|
|
1209
|
-
wp.tile_cholesky(
|
|
1210
|
-
wp.tile_store(L[articulation], wp.tile_transpose(
|
|
1201
|
+
a_r = wp.tile_diag_add(a, r)
|
|
1202
|
+
l = wp.tile_cholesky(a_r)
|
|
1203
|
+
wp.tile_store(L[articulation], wp.tile_transpose(l))
|
|
1211
1204
|
|
|
1212
1205
|
return eval_tiled_dense_cholesky_batched
|
|
1213
1206
|
|
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
|
-
"""
|
|
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
|
-
|
|
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
|
-
|
|
276
|
-
|
|
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
|
-
|
|
280
|
-
|
|
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
|
-
|
|
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
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
+
"""
|
|
289
293
|
|
|
290
|
-
|
|
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`.
|
|
291
297
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
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.
|
|
298
|
-
|
|
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.
|
|
302
|
-
|
|
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
|
-
"""
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
374
|
+
self.tri_activations: Optional[wp.array] = None
|
|
375
|
+
"""Array of triangle element activations with shape ``(tri_count,)`` and type ``float``."""
|
|
360
376
|
|
|
361
|
-
|
|
362
|
-
|
|
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
|
|
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:
|
|
@@ -1396,6 +1399,8 @@ class ModelBuilder:
|
|
|
1396
1399
|
# apply offset transform to root bodies
|
|
1397
1400
|
if xform is not None:
|
|
1398
1401
|
self.shape_transform.append(xform * builder.shape_transform[s])
|
|
1402
|
+
else:
|
|
1403
|
+
self.shape_transform.append(builder.shape_transform[s])
|
|
1399
1404
|
|
|
1400
1405
|
for b, shapes in builder.body_shapes.items():
|
|
1401
1406
|
self.body_shapes[b + start_body_idx] = [s + start_shape_idx for s in shapes]
|
|
@@ -1418,18 +1423,16 @@ class ModelBuilder:
|
|
|
1418
1423
|
|
|
1419
1424
|
# offset the indices
|
|
1420
1425
|
self.articulation_start.extend([a + self.joint_count for a in builder.articulation_start])
|
|
1421
|
-
self.joint_parent.extend([p + self.
|
|
1422
|
-
self.joint_child.extend([c + self.
|
|
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])
|
|
1423
1428
|
|
|
1424
1429
|
self.joint_q_start.extend([c + self.joint_coord_count for c in builder.joint_q_start])
|
|
1425
1430
|
self.joint_qd_start.extend([c + self.joint_dof_count for c in builder.joint_qd_start])
|
|
1426
1431
|
|
|
1427
1432
|
self.joint_axis_start.extend([a + self.joint_axis_total_count for a in builder.joint_axis_start])
|
|
1428
1433
|
|
|
1429
|
-
joint_children = set(builder.joint_child)
|
|
1430
1434
|
for i in range(builder.body_count):
|
|
1431
|
-
if xform is not None
|
|
1432
|
-
# rigid body is not attached to a joint, so apply input transform directly
|
|
1435
|
+
if xform is not None:
|
|
1433
1436
|
self.body_q.append(xform * builder.body_q[i])
|
|
1434
1437
|
else:
|
|
1435
1438
|
self.body_q.append(builder.body_q[i])
|
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=
|
|
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=(
|
|
331
|
+
colors=(0.75, 0.25, 0.0),
|
|
332
332
|
)
|
|
333
333
|
|
|
334
334
|
# render springs
|
warp/stubs.py
CHANGED
|
@@ -1785,7 +1785,7 @@ def rand_init(seed: int32, offset: int32) -> uint32:
|
|
|
1785
1785
|
|
|
1786
1786
|
@over
|
|
1787
1787
|
def randi(state: uint32) -> int:
|
|
1788
|
-
"""Return a random integer in the range [
|
|
1788
|
+
"""Return a random integer in the range [-2^31, 2^31)."""
|
|
1789
1789
|
...
|
|
1790
1790
|
|
|
1791
1791
|
|
warp/tests/test_array.py
CHANGED
|
@@ -2836,6 +2836,31 @@ def test_array_len(test, device):
|
|
|
2836
2836
|
test.assertEqual(out.numpy()[1], 2)
|
|
2837
2837
|
|
|
2838
2838
|
|
|
2839
|
+
def test_cuda_interface_conversion(test, device):
|
|
2840
|
+
class MyArrayInterface:
|
|
2841
|
+
def __init__(self, data):
|
|
2842
|
+
self.data = np.array(data)
|
|
2843
|
+
self.__array_interface__ = self.data.__array_interface__
|
|
2844
|
+
self.__cuda_array_interface__ = self.data.__array_interface__
|
|
2845
|
+
self.__len__ = self.data.__len__
|
|
2846
|
+
|
|
2847
|
+
array = MyArrayInterface((1, 2, 3))
|
|
2848
|
+
wp_array = wp.array(array, dtype=wp.int8, device=device)
|
|
2849
|
+
assert wp_array.ptr != 0
|
|
2850
|
+
|
|
2851
|
+
array = MyArrayInterface((1, 2, 3))
|
|
2852
|
+
wp_array = wp.array(array, dtype=wp.float32, device=device)
|
|
2853
|
+
assert wp_array.ptr != 0
|
|
2854
|
+
|
|
2855
|
+
array = MyArrayInterface((1, 2, 3))
|
|
2856
|
+
wp_array = wp.array(array, dtype=wp.vec3, device=device)
|
|
2857
|
+
assert wp_array.ptr != 0
|
|
2858
|
+
|
|
2859
|
+
array = MyArrayInterface((1, 2, 3, 4))
|
|
2860
|
+
wp_array = wp.array(array, dtype=wp.mat22, device=device)
|
|
2861
|
+
assert wp_array.ptr != 0
|
|
2862
|
+
|
|
2863
|
+
|
|
2839
2864
|
devices = get_test_devices()
|
|
2840
2865
|
|
|
2841
2866
|
|
|
@@ -2908,6 +2933,7 @@ add_function_test(TestArray, "test_indexing_types", test_indexing_types, devices
|
|
|
2908
2933
|
add_function_test(TestArray, "test_alloc_strides", test_alloc_strides, devices=devices)
|
|
2909
2934
|
add_function_test(TestArray, "test_casting", test_casting, devices=devices)
|
|
2910
2935
|
add_function_test(TestArray, "test_array_len", test_array_len, devices=devices)
|
|
2936
|
+
add_function_test(TestArray, "test_cuda_interface_conversion", test_cuda_interface_conversion, devices=devices)
|
|
2911
2937
|
|
|
2912
2938
|
try:
|
|
2913
2939
|
import torch
|
warp/tests/test_collision.py
CHANGED
|
@@ -18,7 +18,7 @@ from warp.tests.unittest_utils import *
|
|
|
18
18
|
@wp.kernel
|
|
19
19
|
def vertex_triangle_collision_detection_brute_force(
|
|
20
20
|
query_radius: float,
|
|
21
|
-
|
|
21
|
+
bvh_id: wp.uint64,
|
|
22
22
|
pos: wp.array(dtype=wp.vec3),
|
|
23
23
|
tri_indices: wp.array(dtype=wp.int32, ndim=2),
|
|
24
24
|
vertex_colliding_triangles: wp.array(dtype=wp.int32),
|
|
@@ -67,7 +67,7 @@ def vertex_triangle_collision_detection_brute_force(
|
|
|
67
67
|
@wp.kernel
|
|
68
68
|
def validate_vertex_collisions(
|
|
69
69
|
query_radius: float,
|
|
70
|
-
|
|
70
|
+
bvh_id: wp.uint64,
|
|
71
71
|
pos: wp.array(dtype=wp.vec3),
|
|
72
72
|
tri_indices: wp.array(dtype=wp.int32, ndim=2),
|
|
73
73
|
vertex_colliding_triangles: wp.array(dtype=wp.int32),
|
|
@@ -107,7 +107,7 @@ def validate_vertex_collisions(
|
|
|
107
107
|
@wp.kernel
|
|
108
108
|
def validate_triangle_collisions(
|
|
109
109
|
query_radius: float,
|
|
110
|
-
|
|
110
|
+
bvh_id: wp.uint64,
|
|
111
111
|
pos: wp.array(dtype=wp.vec3),
|
|
112
112
|
tri_indices: wp.array(dtype=wp.int32, ndim=2),
|
|
113
113
|
triangle_colliding_vertices: wp.array(dtype=wp.int32),
|
|
@@ -303,7 +303,7 @@ class Example:
|
|
|
303
303
|
kernel=vertex_triangle_collision_detection_brute_force,
|
|
304
304
|
inputs=[
|
|
305
305
|
query_radius,
|
|
306
|
-
self.collision_detector.
|
|
306
|
+
self.collision_detector.bvh_tris.id,
|
|
307
307
|
self.collision_detector.model.particle_q,
|
|
308
308
|
self.collision_detector.model.tri_indices,
|
|
309
309
|
self.collision_detector.vertex_colliding_triangles,
|
|
@@ -337,7 +337,7 @@ class Example:
|
|
|
337
337
|
kernel=validate_vertex_collisions,
|
|
338
338
|
inputs=[
|
|
339
339
|
query_radius,
|
|
340
|
-
self.collision_detector.
|
|
340
|
+
self.collision_detector.bvh_tris.id,
|
|
341
341
|
self.collision_detector.model.particle_q,
|
|
342
342
|
self.collision_detector.model.tri_indices,
|
|
343
343
|
self.collision_detector.vertex_colliding_triangles,
|
|
@@ -355,7 +355,7 @@ class Example:
|
|
|
355
355
|
kernel=validate_triangle_collisions,
|
|
356
356
|
inputs=[
|
|
357
357
|
query_radius,
|
|
358
|
-
self.collision_detector.
|
|
358
|
+
self.collision_detector.bvh_tris.id,
|
|
359
359
|
self.collision_detector.model.particle_q,
|
|
360
360
|
self.collision_detector.model.tri_indices,
|
|
361
361
|
self.collision_detector.triangle_colliding_vertices,
|
warp/tests/test_examples.py
CHANGED
|
@@ -234,7 +234,13 @@ add_example_test(
|
|
|
234
234
|
devices=test_devices,
|
|
235
235
|
test_options={"height": 512, "width": 1024, "headless": True},
|
|
236
236
|
)
|
|
237
|
-
add_example_test(
|
|
237
|
+
add_example_test(
|
|
238
|
+
TestCoreExamples,
|
|
239
|
+
name="core.example_sph",
|
|
240
|
+
devices=test_devices,
|
|
241
|
+
test_options_cpu={"num_frames": 1},
|
|
242
|
+
test_options_cuda={"test_timeout": 600},
|
|
243
|
+
)
|
|
238
244
|
add_example_test(
|
|
239
245
|
TestCoreExamples,
|
|
240
246
|
name="core.example_torch",
|