warp-lang 0.11.0__py3-none-manylinux2014_x86_64.whl → 1.0.0__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/__init__.py +8 -0
- warp/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/build.py +7 -6
- warp/build_dll.py +70 -79
- warp/builtins.py +10 -6
- warp/codegen.py +51 -19
- warp/config.py +7 -8
- warp/constants.py +3 -0
- warp/context.py +948 -245
- warp/dlpack.py +198 -113
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/assets/cartpole.urdf +110 -0
- warp/examples/assets/crazyflie.usd +0 -0
- warp/examples/assets/cube.usda +42 -0
- warp/examples/assets/nv_ant.xml +92 -0
- warp/examples/assets/nv_humanoid.xml +183 -0
- warp/examples/assets/quadruped.urdf +268 -0
- warp/examples/assets/rocks.nvdb +0 -0
- warp/examples/assets/rocks.usd +0 -0
- warp/examples/assets/sphere.usda +56 -0
- warp/examples/assets/torus.usda +105 -0
- warp/examples/benchmarks/benchmark_api.py +383 -0
- warp/examples/benchmarks/benchmark_cloth.py +279 -0
- warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -0
- warp/examples/benchmarks/benchmark_cloth_jax.py +100 -0
- warp/examples/benchmarks/benchmark_cloth_numba.py +142 -0
- warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -0
- warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -0
- warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -0
- warp/examples/benchmarks/benchmark_cloth_warp.py +146 -0
- warp/examples/benchmarks/benchmark_launches.py +295 -0
- warp/examples/core/example_dem.py +221 -0
- warp/examples/core/example_fluid.py +267 -0
- warp/examples/core/example_graph_capture.py +129 -0
- warp/examples/core/example_marching_cubes.py +177 -0
- warp/examples/core/example_mesh.py +154 -0
- warp/examples/core/example_mesh_intersect.py +193 -0
- warp/examples/core/example_nvdb.py +169 -0
- warp/examples/core/example_raycast.py +89 -0
- warp/examples/core/example_raymarch.py +178 -0
- warp/examples/core/example_render_opengl.py +141 -0
- warp/examples/core/example_sph.py +389 -0
- warp/examples/core/example_torch.py +181 -0
- warp/examples/core/example_wave.py +249 -0
- warp/examples/fem/bsr_utils.py +380 -0
- warp/examples/fem/example_apic_fluid.py +391 -0
- warp/examples/fem/example_convection_diffusion.py +168 -0
- warp/examples/fem/example_convection_diffusion_dg.py +209 -0
- warp/examples/fem/example_convection_diffusion_dg0.py +194 -0
- warp/examples/fem/example_deformed_geometry.py +159 -0
- warp/examples/fem/example_diffusion.py +173 -0
- warp/examples/fem/example_diffusion_3d.py +152 -0
- warp/examples/fem/example_diffusion_mgpu.py +214 -0
- warp/examples/fem/example_mixed_elasticity.py +222 -0
- warp/examples/fem/example_navier_stokes.py +243 -0
- warp/examples/fem/example_stokes.py +192 -0
- warp/examples/fem/example_stokes_transfer.py +249 -0
- warp/examples/fem/mesh_utils.py +109 -0
- warp/examples/fem/plot_utils.py +287 -0
- warp/examples/optim/example_bounce.py +248 -0
- warp/examples/optim/example_cloth_throw.py +210 -0
- warp/examples/optim/example_diffray.py +535 -0
- warp/examples/optim/example_drone.py +850 -0
- warp/examples/optim/example_inverse_kinematics.py +169 -0
- warp/examples/optim/example_inverse_kinematics_torch.py +170 -0
- warp/examples/optim/example_spring_cage.py +234 -0
- warp/examples/optim/example_trajectory.py +201 -0
- warp/examples/sim/example_cartpole.py +128 -0
- warp/examples/sim/example_cloth.py +184 -0
- warp/examples/sim/example_granular.py +113 -0
- warp/examples/sim/example_granular_collision_sdf.py +185 -0
- warp/examples/sim/example_jacobian_ik.py +213 -0
- warp/examples/sim/example_particle_chain.py +106 -0
- warp/examples/sim/example_quadruped.py +179 -0
- warp/examples/sim/example_rigid_chain.py +191 -0
- warp/examples/sim/example_rigid_contact.py +176 -0
- warp/examples/sim/example_rigid_force.py +126 -0
- warp/examples/sim/example_rigid_gyroscopic.py +97 -0
- warp/examples/sim/example_rigid_soft_contact.py +124 -0
- warp/examples/sim/example_soft_body.py +178 -0
- warp/fabric.py +29 -20
- warp/fem/cache.py +0 -1
- warp/fem/dirichlet.py +0 -2
- warp/fem/integrate.py +0 -1
- warp/jax.py +45 -0
- warp/jax_experimental.py +339 -0
- warp/native/builtin.h +12 -0
- warp/native/bvh.cu +18 -18
- warp/native/clang/clang.cpp +8 -3
- warp/native/cuda_util.cpp +94 -5
- warp/native/cuda_util.h +35 -6
- warp/native/cutlass_gemm.cpp +1 -1
- warp/native/cutlass_gemm.cu +4 -1
- warp/native/error.cpp +66 -0
- warp/native/error.h +27 -0
- warp/native/mesh.cu +2 -2
- warp/native/reduce.cu +4 -4
- warp/native/runlength_encode.cu +2 -2
- warp/native/scan.cu +2 -2
- warp/native/sparse.cu +0 -1
- warp/native/temp_buffer.h +2 -2
- warp/native/warp.cpp +95 -60
- warp/native/warp.cu +1053 -218
- warp/native/warp.h +49 -32
- warp/optim/linear.py +33 -16
- warp/render/render_opengl.py +202 -101
- warp/render/render_usd.py +82 -40
- warp/sim/__init__.py +13 -4
- warp/sim/articulation.py +4 -5
- warp/sim/collide.py +320 -175
- warp/sim/import_mjcf.py +25 -30
- warp/sim/import_urdf.py +94 -63
- warp/sim/import_usd.py +51 -36
- warp/sim/inertia.py +3 -2
- warp/sim/integrator.py +233 -0
- warp/sim/integrator_euler.py +447 -469
- warp/sim/integrator_featherstone.py +1991 -0
- warp/sim/integrator_xpbd.py +1420 -640
- warp/sim/model.py +765 -487
- warp/sim/particles.py +2 -1
- warp/sim/render.py +35 -13
- warp/sim/utils.py +222 -11
- warp/stubs.py +8 -0
- warp/tape.py +16 -1
- warp/tests/aux_test_grad_customs.py +23 -0
- warp/tests/test_array.py +190 -1
- warp/tests/test_async.py +656 -0
- warp/tests/test_bool.py +50 -0
- warp/tests/test_dlpack.py +164 -11
- warp/tests/test_examples.py +166 -74
- warp/tests/test_fem.py +8 -1
- warp/tests/test_generics.py +15 -5
- warp/tests/test_grad.py +1 -1
- warp/tests/test_grad_customs.py +172 -12
- warp/tests/test_jax.py +254 -0
- warp/tests/test_large.py +29 -6
- warp/tests/test_launch.py +25 -0
- warp/tests/test_linear_solvers.py +20 -3
- warp/tests/test_matmul.py +61 -16
- warp/tests/test_matmul_lite.py +13 -13
- warp/tests/test_mempool.py +186 -0
- warp/tests/test_multigpu.py +3 -0
- warp/tests/test_options.py +16 -2
- warp/tests/test_peer.py +137 -0
- warp/tests/test_print.py +3 -1
- warp/tests/test_quat.py +23 -0
- warp/tests/test_sim_kinematics.py +97 -0
- warp/tests/test_snippet.py +126 -3
- warp/tests/test_streams.py +108 -79
- warp/tests/test_torch.py +16 -8
- warp/tests/test_utils.py +32 -27
- warp/tests/test_verify_fp.py +65 -0
- warp/tests/test_volume.py +1 -1
- warp/tests/unittest_serial.py +2 -0
- warp/tests/unittest_suites.py +12 -0
- warp/tests/unittest_utils.py +14 -7
- warp/thirdparty/unittest_parallel.py +15 -3
- warp/torch.py +10 -8
- warp/types.py +363 -246
- warp/utils.py +143 -19
- warp_lang-1.0.0.dist-info/LICENSE.md +126 -0
- warp_lang-1.0.0.dist-info/METADATA +394 -0
- {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/RECORD +167 -86
- warp/sim/optimizer.py +0 -138
- warp_lang-0.11.0.dist-info/LICENSE.md +0 -36
- warp_lang-0.11.0.dist-info/METADATA +0 -238
- /warp/tests/{walkthough_debug.py → walkthrough_debug.py} +0 -0
- {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/WHEEL +0 -0
- {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/top_level.txt +0 -0
warp/sim/import_mjcf.py
CHANGED
|
@@ -25,8 +25,10 @@ def parse_mjcf(
|
|
|
25
25
|
contact_ke=1000.0,
|
|
26
26
|
contact_kd=100.0,
|
|
27
27
|
contact_kf=100.0,
|
|
28
|
+
contact_ka=0.0,
|
|
28
29
|
contact_mu=0.5,
|
|
29
30
|
contact_restitution=0.5,
|
|
31
|
+
contact_thickness=0.0,
|
|
30
32
|
limit_ke=100.0,
|
|
31
33
|
limit_kd=10.0,
|
|
32
34
|
scale=1.0,
|
|
@@ -48,13 +50,15 @@ def parse_mjcf(
|
|
|
48
50
|
density (float): The density of the shapes in kg/m^3 which will be used to calculate the body mass and inertia.
|
|
49
51
|
stiffness (float): The stiffness of the joints.
|
|
50
52
|
damping (float): The damping of the joints.
|
|
51
|
-
contact_ke (float): The stiffness of the shape contacts
|
|
52
|
-
contact_kd (float): The damping of the shape contacts
|
|
53
|
-
contact_kf (float): The friction stiffness of the shape contacts
|
|
53
|
+
contact_ke (float): The stiffness of the shape contacts.
|
|
54
|
+
contact_kd (float): The damping of the shape contacts.
|
|
55
|
+
contact_kf (float): The friction stiffness of the shape contacts.
|
|
56
|
+
contact_ka (float): The adhesion distance of the shape contacts.
|
|
54
57
|
contact_mu (float): The friction coefficient of the shape contacts.
|
|
55
58
|
contact_restitution (float): The restitution coefficient of the shape contacts.
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
contact_thickness (float): The thickness to add to the shape geometry.
|
|
60
|
+
limit_ke (float): The stiffness of the joint limits.
|
|
61
|
+
limit_kd (float): The damping of the joint limits.
|
|
58
62
|
scale (float): The scaling factor to apply to the imported mechanism.
|
|
59
63
|
armature (float): Default joint armature to use if `armature` has not been defined for a joint in the MJCF.
|
|
60
64
|
armature_scale (float): Scaling factor to apply to the MJCF-defined joint armature values.
|
|
@@ -73,6 +77,16 @@ def parse_mjcf(
|
|
|
73
77
|
file = ET.parse(mjcf_filename)
|
|
74
78
|
root = file.getroot()
|
|
75
79
|
|
|
80
|
+
contact_vars = dict(
|
|
81
|
+
ke=contact_ke,
|
|
82
|
+
kd=contact_kd,
|
|
83
|
+
kf=contact_kf,
|
|
84
|
+
ka=contact_ka,
|
|
85
|
+
mu=contact_mu,
|
|
86
|
+
restitution=contact_restitution,
|
|
87
|
+
thickness=contact_thickness,
|
|
88
|
+
)
|
|
89
|
+
|
|
76
90
|
use_degrees = True # angles are in degrees by default
|
|
77
91
|
euler_seq = [1, 2, 3] # XYZ by default
|
|
78
92
|
|
|
@@ -265,7 +279,7 @@ def parse_mjcf(
|
|
|
265
279
|
joint_type = wp.sim.JOINT_FIXED
|
|
266
280
|
break
|
|
267
281
|
is_angular = joint_type_str == "hinge"
|
|
268
|
-
mode = wp.sim.
|
|
282
|
+
mode = wp.sim.JOINT_MODE_FORCE
|
|
269
283
|
if stiffness > 0.0 or "stiffness" in joint_attrib:
|
|
270
284
|
mode = wp.sim.JOINT_MODE_TARGET_POSITION
|
|
271
285
|
axis_vec = parse_vec(joint_attrib, "axis", (0.0, 0.0, 0.0))
|
|
@@ -355,11 +369,7 @@ def parse_mjcf(
|
|
|
355
369
|
rot=geom_rot,
|
|
356
370
|
radius=geom_size[0],
|
|
357
371
|
density=geom_density,
|
|
358
|
-
|
|
359
|
-
kd=contact_kd,
|
|
360
|
-
kf=contact_kf,
|
|
361
|
-
mu=contact_mu,
|
|
362
|
-
restitution=contact_restitution,
|
|
372
|
+
**contact_vars,
|
|
363
373
|
)
|
|
364
374
|
|
|
365
375
|
elif geom_type == "box":
|
|
@@ -371,11 +381,7 @@ def parse_mjcf(
|
|
|
371
381
|
hy=geom_size[1],
|
|
372
382
|
hz=geom_size[2],
|
|
373
383
|
density=geom_density,
|
|
374
|
-
|
|
375
|
-
kd=contact_kd,
|
|
376
|
-
kf=contact_kf,
|
|
377
|
-
mu=contact_mu,
|
|
378
|
-
restitution=contact_restitution,
|
|
384
|
+
**contact_vars,
|
|
379
385
|
)
|
|
380
386
|
|
|
381
387
|
elif geom_type == "mesh" and parse_meshes:
|
|
@@ -393,10 +399,7 @@ def parse_mjcf(
|
|
|
393
399
|
mesh=mesh,
|
|
394
400
|
scale=mesh_scale,
|
|
395
401
|
density=density,
|
|
396
|
-
|
|
397
|
-
kd=contact_kd,
|
|
398
|
-
kf=contact_kf,
|
|
399
|
-
mu=contact_mu,
|
|
402
|
+
**contact_vars,
|
|
400
403
|
)
|
|
401
404
|
|
|
402
405
|
elif geom_type in {"capsule", "cylinder"}:
|
|
@@ -431,12 +434,8 @@ def parse_mjcf(
|
|
|
431
434
|
radius=geom_radius,
|
|
432
435
|
half_height=geom_height,
|
|
433
436
|
density=density,
|
|
434
|
-
ke=contact_ke,
|
|
435
|
-
kd=contact_kd,
|
|
436
|
-
kf=contact_kf,
|
|
437
|
-
mu=contact_mu,
|
|
438
|
-
restitution=contact_restitution,
|
|
439
437
|
up_axis=geom_up_axis,
|
|
438
|
+
**contact_vars,
|
|
440
439
|
)
|
|
441
440
|
else:
|
|
442
441
|
builder.add_shape_capsule(
|
|
@@ -446,12 +445,8 @@ def parse_mjcf(
|
|
|
446
445
|
radius=geom_radius,
|
|
447
446
|
half_height=geom_height,
|
|
448
447
|
density=density,
|
|
449
|
-
ke=contact_ke,
|
|
450
|
-
kd=contact_kd,
|
|
451
|
-
kf=contact_kf,
|
|
452
|
-
mu=contact_mu,
|
|
453
|
-
restitution=contact_restitution,
|
|
454
448
|
up_axis=geom_up_axis,
|
|
449
|
+
**contact_vars,
|
|
455
450
|
)
|
|
456
451
|
|
|
457
452
|
else:
|
warp/sim/import_urdf.py
CHANGED
|
@@ -14,6 +14,8 @@ import numpy as np
|
|
|
14
14
|
import warp as wp
|
|
15
15
|
from warp.sim.model import Mesh
|
|
16
16
|
|
|
17
|
+
from typing import Union
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
def parse_urdf(
|
|
19
21
|
urdf_filename,
|
|
@@ -25,16 +27,20 @@ def parse_urdf(
|
|
|
25
27
|
stiffness=100.0,
|
|
26
28
|
damping=10.0,
|
|
27
29
|
armature=0.0,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
contact_ke=1.0e4,
|
|
31
|
+
contact_kd=1.0e3,
|
|
32
|
+
contact_kf=1.0e2,
|
|
33
|
+
contact_ka=0.0,
|
|
34
|
+
contact_mu=0.25,
|
|
35
|
+
contact_restitution=0.5,
|
|
36
|
+
contact_thickness=0.0,
|
|
34
37
|
limit_ke=100.0,
|
|
35
38
|
limit_kd=10.0,
|
|
39
|
+
joint_limit_lower=-1e6,
|
|
40
|
+
joint_limit_upper=1e6,
|
|
36
41
|
scale=1.0,
|
|
37
42
|
parse_visuals_as_colliders=False,
|
|
43
|
+
force_show_colliders=False,
|
|
38
44
|
enable_self_collisions=True,
|
|
39
45
|
ignore_inertial_definitions=True,
|
|
40
46
|
ensure_nonstatic_links=True,
|
|
@@ -54,16 +60,20 @@ def parse_urdf(
|
|
|
54
60
|
stiffness (float): The stiffness of the joints.
|
|
55
61
|
damping (float): The damping of the joints.
|
|
56
62
|
armature (float): The armature of the joints (bias to add to the inertia diagonals that may stabilize the simulation).
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
contact_ke (float): The stiffness of the shape contacts (used by the Euler integrators).
|
|
64
|
+
contact_kd (float): The damping of the shape contacts (used by the Euler integrators).
|
|
65
|
+
contact_kf (float): The friction stiffness of the shape contacts (used by the Euler integrators).
|
|
66
|
+
contact_ka (float): The adhesion distance of the shape contacts (used by the Euler integrators).
|
|
67
|
+
contact_mu (float): The friction coefficient of the shape contacts.
|
|
68
|
+
contact_restitution (float): The restitution coefficient of the shape contacts.
|
|
69
|
+
contact_thickness (float): The thickness to add to the shape geometry.
|
|
70
|
+
limit_ke (float): The stiffness of the joint limits (used by the Euler integrators).
|
|
71
|
+
limit_kd (float): The damping of the joint limits (used by the Euler integrators).
|
|
72
|
+
joint_limit_lower (float): The default lower joint limit if not specified in the URDF.
|
|
73
|
+
joint_limit_upper (float): The default upper joint limit if not specified in the URDF.
|
|
65
74
|
scale (float): The scaling factor to apply to the imported mechanism.
|
|
66
|
-
parse_visuals_as_colliders (bool): If True, the geometry defined under the `<visual>` tags is used for collision handling instead of the `<collision>`
|
|
75
|
+
parse_visuals_as_colliders (bool): If True, the geometry defined under the `<visual>` tags is used for collision handling instead of the `<collision>` geoemtries.
|
|
76
|
+
force_show_colliders (bool): If True, the collision shapes are always shown, even if there are visual shapes.
|
|
67
77
|
enable_self_collisions (bool): If True, self-collisions are enabled.
|
|
68
78
|
ignore_inertial_definitions (bool): If True, the inertial parameters defined in the URDF are ignored and the inertia is calculated from the shape geometry.
|
|
69
79
|
ensure_nonstatic_links (bool): If True, links with zero mass are given a small mass (see `static_link_mass`) to ensure they are dynamic.
|
|
@@ -74,6 +84,16 @@ def parse_urdf(
|
|
|
74
84
|
file = ET.parse(urdf_filename)
|
|
75
85
|
root = file.getroot()
|
|
76
86
|
|
|
87
|
+
contact_vars = dict(
|
|
88
|
+
ke=contact_ke,
|
|
89
|
+
kd=contact_kd,
|
|
90
|
+
kf=contact_kf,
|
|
91
|
+
ka=contact_ka,
|
|
92
|
+
mu=contact_mu,
|
|
93
|
+
restitution=contact_restitution,
|
|
94
|
+
thickness=contact_thickness,
|
|
95
|
+
)
|
|
96
|
+
|
|
77
97
|
def parse_transform(element):
|
|
78
98
|
if element is None or element.find("origin") is None:
|
|
79
99
|
return wp.transform()
|
|
@@ -84,21 +104,22 @@ def parse_urdf(
|
|
|
84
104
|
rpy = [float(x) for x in rpy.split()]
|
|
85
105
|
return wp.transform(xyz, wp.quat_rpy(*rpy))
|
|
86
106
|
|
|
87
|
-
def parse_shapes(link,
|
|
107
|
+
def parse_shapes(link, geoms, density, incoming_xform=None, visible=True, just_visual=False):
|
|
108
|
+
shapes = []
|
|
88
109
|
# add geometry
|
|
89
|
-
for
|
|
90
|
-
geo =
|
|
110
|
+
for geom_group in geoms:
|
|
111
|
+
geo = geom_group.find("geometry")
|
|
91
112
|
if geo is None:
|
|
92
113
|
continue
|
|
93
114
|
|
|
94
|
-
tf = parse_transform(
|
|
115
|
+
tf = parse_transform(geom_group)
|
|
95
116
|
if incoming_xform is not None:
|
|
96
117
|
tf = incoming_xform * tf
|
|
97
118
|
|
|
98
119
|
for box in geo.findall("box"):
|
|
99
120
|
size = box.get("size") or "1 1 1"
|
|
100
121
|
size = [float(x) for x in size.split()]
|
|
101
|
-
builder.add_shape_box(
|
|
122
|
+
s = builder.add_shape_box(
|
|
102
123
|
body=link,
|
|
103
124
|
pos=wp.vec3(tf.p),
|
|
104
125
|
rot=wp.quat(tf.q),
|
|
@@ -106,45 +127,39 @@ def parse_urdf(
|
|
|
106
127
|
hy=size[1] * 0.5 * scale,
|
|
107
128
|
hz=size[2] * 0.5 * scale,
|
|
108
129
|
density=density,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
mu=shape_mu,
|
|
113
|
-
restitution=shape_restitution,
|
|
114
|
-
thickness=shape_thickness,
|
|
130
|
+
is_visible=visible,
|
|
131
|
+
has_ground_collision=not just_visual,
|
|
132
|
+
**contact_vars,
|
|
115
133
|
)
|
|
134
|
+
shapes.append(s)
|
|
116
135
|
|
|
117
136
|
for sphere in geo.findall("sphere"):
|
|
118
|
-
builder.add_shape_sphere(
|
|
137
|
+
s = builder.add_shape_sphere(
|
|
119
138
|
body=link,
|
|
120
139
|
pos=wp.vec3(tf.p),
|
|
121
140
|
rot=wp.quat(tf.q),
|
|
122
141
|
radius=float(sphere.get("radius") or "1") * scale,
|
|
123
142
|
density=density,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
mu=shape_mu,
|
|
128
|
-
restitution=shape_restitution,
|
|
129
|
-
thickness=shape_thickness,
|
|
143
|
+
is_visible=visible,
|
|
144
|
+
has_ground_collision=not just_visual,
|
|
145
|
+
**contact_vars,
|
|
130
146
|
)
|
|
147
|
+
shapes.append(s)
|
|
131
148
|
|
|
132
149
|
for cylinder in geo.findall("cylinder"):
|
|
133
|
-
builder.add_shape_capsule(
|
|
150
|
+
s = builder.add_shape_capsule(
|
|
134
151
|
body=link,
|
|
135
152
|
pos=wp.vec3(tf.p),
|
|
136
153
|
rot=wp.quat(tf.q),
|
|
137
154
|
radius=float(cylinder.get("radius") or "1") * scale,
|
|
138
155
|
half_height=float(cylinder.get("length") or "1") * 0.5 * scale,
|
|
139
156
|
density=density,
|
|
140
|
-
ke=shape_ke,
|
|
141
|
-
kd=shape_kd,
|
|
142
|
-
kf=shape_kf,
|
|
143
|
-
mu=shape_mu,
|
|
144
157
|
up_axis=2, # cylinders in URDF are aligned with z-axis
|
|
145
|
-
|
|
146
|
-
|
|
158
|
+
is_visible=visible,
|
|
159
|
+
has_ground_collision=not just_visual,
|
|
160
|
+
**contact_vars,
|
|
147
161
|
)
|
|
162
|
+
shapes.append(s)
|
|
148
163
|
|
|
149
164
|
for mesh in geo.findall("mesh"):
|
|
150
165
|
filename = mesh.get("filename")
|
|
@@ -182,59 +197,70 @@ def parse_urdf(
|
|
|
182
197
|
vertices = np.array(geom.vertices, dtype=np.float32) * scaling
|
|
183
198
|
faces = np.array(geom.faces.flatten(), dtype=np.int32)
|
|
184
199
|
mesh = Mesh(vertices, faces)
|
|
185
|
-
builder.add_shape_mesh(
|
|
200
|
+
s = builder.add_shape_mesh(
|
|
186
201
|
body=link,
|
|
187
202
|
pos=wp.vec3(tf.p),
|
|
188
203
|
rot=wp.quat(tf.q),
|
|
189
204
|
mesh=mesh,
|
|
190
205
|
density=density,
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
mu=shape_mu,
|
|
195
|
-
restitution=shape_restitution,
|
|
196
|
-
thickness=shape_thickness,
|
|
206
|
+
is_visible=visible,
|
|
207
|
+
has_ground_collision=not just_visual,
|
|
208
|
+
**contact_vars,
|
|
197
209
|
)
|
|
210
|
+
shapes.append(s)
|
|
198
211
|
else:
|
|
199
212
|
# a single mesh
|
|
200
213
|
vertices = np.array(m.vertices, dtype=np.float32) * scaling
|
|
201
214
|
faces = np.array(m.faces.flatten(), dtype=np.int32)
|
|
202
215
|
mesh = Mesh(vertices, faces)
|
|
203
|
-
builder.add_shape_mesh(
|
|
216
|
+
s = builder.add_shape_mesh(
|
|
204
217
|
body=link,
|
|
205
218
|
pos=tf.p,
|
|
206
219
|
rot=tf.q,
|
|
207
220
|
mesh=mesh,
|
|
208
221
|
density=density,
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
mu=shape_mu,
|
|
213
|
-
restitution=shape_restitution,
|
|
214
|
-
thickness=shape_thickness,
|
|
222
|
+
is_visible=visible,
|
|
223
|
+
has_ground_collision=not just_visual,
|
|
224
|
+
**contact_vars,
|
|
215
225
|
)
|
|
226
|
+
shapes.append(s)
|
|
227
|
+
|
|
228
|
+
return shapes
|
|
216
229
|
|
|
217
230
|
# maps from link name -> link index
|
|
218
231
|
link_index = {}
|
|
219
232
|
|
|
233
|
+
visual_shapes = []
|
|
234
|
+
|
|
220
235
|
builder.add_articulation()
|
|
221
236
|
|
|
222
237
|
start_shape_count = len(builder.shape_geo_type)
|
|
223
238
|
|
|
224
239
|
# add links
|
|
225
240
|
for i, urdf_link in enumerate(root.findall("link")):
|
|
226
|
-
if parse_visuals_as_colliders:
|
|
227
|
-
colliders = urdf_link.findall("visual")
|
|
228
|
-
else:
|
|
229
|
-
colliders = urdf_link.findall("collision")
|
|
230
|
-
|
|
231
241
|
name = urdf_link.get("name")
|
|
232
242
|
link = builder.add_body(origin=wp.transform_identity(), armature=armature, name=name)
|
|
233
243
|
|
|
234
244
|
# add ourselves to the index
|
|
235
245
|
link_index[name] = link
|
|
236
246
|
|
|
237
|
-
|
|
247
|
+
visuals = urdf_link.findall("visual")
|
|
248
|
+
colliders = urdf_link.findall("collision")
|
|
249
|
+
|
|
250
|
+
if parse_visuals_as_colliders:
|
|
251
|
+
colliders = visuals
|
|
252
|
+
else:
|
|
253
|
+
s = parse_shapes(link, visuals, density=0.0, just_visual=True)
|
|
254
|
+
visual_shapes.extend(s)
|
|
255
|
+
|
|
256
|
+
show_colliders = force_show_colliders
|
|
257
|
+
if parse_visuals_as_colliders:
|
|
258
|
+
show_colliders = True
|
|
259
|
+
elif len(visuals) == 0:
|
|
260
|
+
# we need to show the collision shapes since there are no visual shapes
|
|
261
|
+
show_colliders = True
|
|
262
|
+
|
|
263
|
+
parse_shapes(link, colliders, density=density, visible=show_colliders)
|
|
238
264
|
m = builder.body_mass[link]
|
|
239
265
|
if not ignore_inertial_definitions and urdf_link.find("inertial") is not None:
|
|
240
266
|
# overwrite inertial parameters if defined
|
|
@@ -264,6 +290,7 @@ def parse_urdf(
|
|
|
264
290
|
m = static_link_mass
|
|
265
291
|
# cube with side length 0.5
|
|
266
292
|
I_m = wp.mat33(np.eye(3)) * m / 12.0 * (0.5 * scale) ** 2 * 2.0
|
|
293
|
+
I_m += wp.mat33(armature * np.eye(3))
|
|
267
294
|
builder.body_mass[link] = m
|
|
268
295
|
builder.body_inv_mass[link] = 1.0 / m
|
|
269
296
|
builder.body_inertia[link] = I_m
|
|
@@ -289,8 +316,8 @@ def parse_urdf(
|
|
|
289
316
|
"origin": parse_transform(joint),
|
|
290
317
|
"damping": damping,
|
|
291
318
|
"friction": 0.0,
|
|
292
|
-
"limit_lower":
|
|
293
|
-
"limit_upper":
|
|
319
|
+
"limit_lower": joint_limit_lower,
|
|
320
|
+
"limit_upper": joint_limit_upper,
|
|
294
321
|
}
|
|
295
322
|
if joint.find("axis") is not None:
|
|
296
323
|
joint_data["axis"] = joint.find("axis").get("xyz")
|
|
@@ -408,7 +435,7 @@ def parse_urdf(
|
|
|
408
435
|
parent_xform = joint["origin"]
|
|
409
436
|
child_xform = wp.transform_identity()
|
|
410
437
|
|
|
411
|
-
joint_mode = wp.sim.
|
|
438
|
+
joint_mode = wp.sim.JOINT_MODE_FORCE
|
|
412
439
|
if stiffness > 0.0:
|
|
413
440
|
joint_mode = wp.sim.JOINT_MODE_TARGET_POSITION
|
|
414
441
|
|
|
@@ -476,6 +503,10 @@ def parse_urdf(
|
|
|
476
503
|
else:
|
|
477
504
|
raise Exception("Unsupported joint type: " + joint["type"])
|
|
478
505
|
|
|
506
|
+
for i in range(start_shape_count, end_shape_count):
|
|
507
|
+
for j in visual_shapes:
|
|
508
|
+
builder.shape_collision_filter_pairs.add((i, j))
|
|
509
|
+
|
|
479
510
|
if not enable_self_collisions:
|
|
480
511
|
for i in range(start_shape_count, end_shape_count):
|
|
481
512
|
for j in range(i + 1, end_shape_count):
|
warp/sim/import_usd.py
CHANGED
|
@@ -18,14 +18,16 @@ def parse_usd(
|
|
|
18
18
|
default_density=1.0e3,
|
|
19
19
|
only_load_enabled_rigid_bodies=False,
|
|
20
20
|
only_load_enabled_joints=True,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
contact_ke=1e5, # TODO rename to contact...
|
|
22
|
+
contact_kd=250.0,
|
|
23
|
+
contact_kf=500.0,
|
|
24
|
+
contact_ka=0.0,
|
|
25
|
+
contact_mu=0.6,
|
|
26
|
+
contact_restitution=0.0,
|
|
27
|
+
contact_thickness=0.0,
|
|
27
28
|
joint_limit_ke=100.0,
|
|
28
29
|
joint_limit_kd=10.0,
|
|
30
|
+
armature=0.0,
|
|
29
31
|
invert_rotations=False,
|
|
30
32
|
verbose=False,
|
|
31
33
|
ignore_paths=[],
|
|
@@ -41,14 +43,16 @@ def parse_usd(
|
|
|
41
43
|
default_density (float): The default density to use for bodies without a density attribute.
|
|
42
44
|
only_load_enabled_rigid_bodies (bool): If True, only rigid bodies which do not have `physics:rigidBodyEnabled` set to False are loaded.
|
|
43
45
|
only_load_enabled_joints (bool): If True, only joints which do not have `physics:jointEnabled` set to False are loaded.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
contact_ke (float): The default contact stiffness to use, only considered by the Euler integrators.
|
|
47
|
+
contact_kd (float): The default contact damping to use, only considered by the Euler integrators.
|
|
48
|
+
contact_kf (float): The default friction stiffness to use, only considered by the Euler integrators.
|
|
49
|
+
contact_ka (float): The default adhesion distance to use, only considered by the Euler integrators.
|
|
50
|
+
contact_mu (float): The default friction coefficient to use if a shape has not friction coefficient defined.
|
|
51
|
+
contact_restitution (float): The default coefficient of restitution to use if a shape has not coefficient of restitution defined.
|
|
52
|
+
contact_thickness (float): The thickness to add to the shape geometry.
|
|
53
|
+
joint_limit_ke (float): The default stiffness to use for joint limits, only considered by the Euler integrators.
|
|
54
|
+
joint_limit_kd (float): The default damping to use for joint limits, only considered by the Euler integrators.
|
|
55
|
+
armature (float): The armature to use for the bodies.
|
|
52
56
|
invert_rotations (bool): If True, inverts any rotations defined in the shape transforms.
|
|
53
57
|
verbose (bool): If True, print additional information about the parsed USD file.
|
|
54
58
|
ignore_paths (List[str]): A list of regular expressions matching prim paths to ignore.
|
|
@@ -150,14 +154,16 @@ def parse_usd(
|
|
|
150
154
|
try:
|
|
151
155
|
if UsdPhysics.StageHasAuthoredKilogramsPerUnit(stage):
|
|
152
156
|
mass_unit = UsdPhysics.GetStageKilogramsPerUnit(stage)
|
|
153
|
-
except:
|
|
154
|
-
|
|
157
|
+
except Exception as e:
|
|
158
|
+
if verbose:
|
|
159
|
+
print(f"Failed to get mass unit: {e}")
|
|
155
160
|
linear_unit = 1.0
|
|
156
161
|
try:
|
|
157
162
|
if UsdGeom.StageHasAuthoredMetersPerUnit(stage):
|
|
158
163
|
linear_unit = UsdGeom.GetStageMetersPerUnit(stage)
|
|
159
|
-
except:
|
|
160
|
-
|
|
164
|
+
except Exception as e:
|
|
165
|
+
if verbose:
|
|
166
|
+
print(f"Failed to get linear unit: {e}")
|
|
161
167
|
|
|
162
168
|
def parse_xform(prim):
|
|
163
169
|
xform = UsdGeom.Xform(prim)
|
|
@@ -221,7 +227,8 @@ def parse_usd(
|
|
|
221
227
|
high = joint_data["upperLimit"]
|
|
222
228
|
else:
|
|
223
229
|
high *= linear_unit
|
|
224
|
-
|
|
230
|
+
|
|
231
|
+
mode = wp.sim.JOINT_MODE_FORCE
|
|
225
232
|
if f"DriveAPI:{type}" in schemas_str:
|
|
226
233
|
if target_vel is not None and target_vel != 0.0:
|
|
227
234
|
mode = wp.sim.JOINT_MODE_TARGET_VELOCITY
|
|
@@ -234,7 +241,7 @@ def parse_usd(
|
|
|
234
241
|
axis=(axis or joint_data["axis"]),
|
|
235
242
|
limit_lower=low,
|
|
236
243
|
limit_upper=high,
|
|
237
|
-
|
|
244
|
+
action=(target_pos or target_vel or (low + high) / 2),
|
|
238
245
|
target_ke=stiffness,
|
|
239
246
|
target_kd=damping,
|
|
240
247
|
mode=mode,
|
|
@@ -249,8 +256,9 @@ def parse_usd(
|
|
|
249
256
|
axis_str = "Y"
|
|
250
257
|
try:
|
|
251
258
|
axis_str = UsdGeom.GetStageUpAxis(stage)
|
|
252
|
-
except:
|
|
253
|
-
|
|
259
|
+
except Exception as e:
|
|
260
|
+
if verbose:
|
|
261
|
+
print(f"Failed to parse stage up axis: {e}")
|
|
254
262
|
upaxis = str2axis(axis_str)
|
|
255
263
|
|
|
256
264
|
shape_types = {"Cube", "Sphere", "Mesh", "Capsule", "Plane", "Cylinder", "Cone"}
|
|
@@ -344,11 +352,11 @@ def parse_usd(
|
|
|
344
352
|
if has_attribute(prim, "physics:density"):
|
|
345
353
|
material["density"] = parse_float(prim, "physics:density") * mass_unit # / (linear_unit**3)
|
|
346
354
|
if has_attribute(prim, "physics:restitution"):
|
|
347
|
-
material["restitution"] = parse_float(prim, "physics:restitution",
|
|
355
|
+
material["restitution"] = parse_float(prim, "physics:restitution", contact_restitution)
|
|
348
356
|
if has_attribute(prim, "physics:staticFriction"):
|
|
349
|
-
material["staticFriction"] = parse_float(prim, "physics:staticFriction",
|
|
357
|
+
material["staticFriction"] = parse_float(prim, "physics:staticFriction", contact_mu)
|
|
350
358
|
if has_attribute(prim, "physics:dynamicFriction"):
|
|
351
|
-
material["dynamicFriction"] = parse_float(prim, "physics:dynamicFriction",
|
|
359
|
+
material["dynamicFriction"] = parse_float(prim, "physics:dynamicFriction", contact_mu)
|
|
352
360
|
materials[path] = material
|
|
353
361
|
|
|
354
362
|
elif type_name == "PhysicsScene":
|
|
@@ -364,8 +372,9 @@ def parse_usd(
|
|
|
364
372
|
builder.up_vector = -builder.up_vector
|
|
365
373
|
else:
|
|
366
374
|
builder.up_vector = upaxis
|
|
367
|
-
except:
|
|
368
|
-
|
|
375
|
+
except Exception as e:
|
|
376
|
+
if verbose:
|
|
377
|
+
print(f"Failed to parse physics scene: {e}")
|
|
369
378
|
|
|
370
379
|
def parse_prim(prim, incoming_xform, incoming_scale, parent_body: int = -1):
|
|
371
380
|
nonlocal builder
|
|
@@ -412,6 +421,7 @@ def parse_usd(
|
|
|
412
421
|
body_id = builder.add_body(
|
|
413
422
|
origin=xform,
|
|
414
423
|
name=prim.GetName(),
|
|
424
|
+
armature=armature,
|
|
415
425
|
)
|
|
416
426
|
path_body_map[path] = body_id
|
|
417
427
|
body_density[body_id] = 0.0
|
|
@@ -562,7 +572,12 @@ def parse_usd(
|
|
|
562
572
|
elif type_name in shape_types:
|
|
563
573
|
# parse shapes
|
|
564
574
|
shape_params = dict(
|
|
565
|
-
ke=
|
|
575
|
+
ke=contact_ke,
|
|
576
|
+
kd=contact_kd,
|
|
577
|
+
kf=contact_kf,
|
|
578
|
+
ka=contact_ka,
|
|
579
|
+
mu=contact_mu,
|
|
580
|
+
restitution=contact_restitution,
|
|
566
581
|
)
|
|
567
582
|
if material is not None:
|
|
568
583
|
if "restitution" in material:
|
|
@@ -590,7 +605,7 @@ def parse_usd(
|
|
|
590
605
|
hy=extents[1] / 2,
|
|
591
606
|
hz=extents[2] / 2,
|
|
592
607
|
density=density,
|
|
593
|
-
thickness=
|
|
608
|
+
thickness=contact_thickness,
|
|
594
609
|
**shape_params,
|
|
595
610
|
)
|
|
596
611
|
elif type_name == "Sphere":
|
|
@@ -626,7 +641,7 @@ def parse_usd(
|
|
|
626
641
|
rot=geo_rot,
|
|
627
642
|
width=width,
|
|
628
643
|
length=length,
|
|
629
|
-
thickness=
|
|
644
|
+
thickness=contact_thickness,
|
|
630
645
|
**shape_params,
|
|
631
646
|
)
|
|
632
647
|
elif type_name == "Capsule":
|
|
@@ -699,7 +714,7 @@ def parse_usd(
|
|
|
699
714
|
scale=scale,
|
|
700
715
|
mesh=m,
|
|
701
716
|
density=density,
|
|
702
|
-
thickness=
|
|
717
|
+
thickness=contact_thickness,
|
|
703
718
|
**shape_params,
|
|
704
719
|
)
|
|
705
720
|
else:
|
|
@@ -738,19 +753,19 @@ def parse_usd(
|
|
|
738
753
|
builder.body_inv_mass[body_id] = 0.0
|
|
739
754
|
# update inertia
|
|
740
755
|
builder.body_inertia[body_id] *= mass_ratio
|
|
741
|
-
if builder.body_inertia[body_id].any():
|
|
742
|
-
builder.body_inv_inertia[body_id] =
|
|
756
|
+
if np.array(builder.body_inertia[body_id]).any():
|
|
757
|
+
builder.body_inv_inertia[body_id] = wp.inverse(builder.body_inertia[body_id])
|
|
743
758
|
else:
|
|
744
|
-
builder.body_inv_inertia[body_id] = np.zeros((3, 3), dtype=np.float32)
|
|
759
|
+
builder.body_inv_inertia[body_id] = wp.mat33(*np.zeros((3, 3), dtype=np.float32))
|
|
745
760
|
|
|
746
761
|
if np.linalg.norm(i_diag) > 0.0:
|
|
747
762
|
rot = np.array(wp.quat_to_matrix(i_rot), dtype=np.float32).reshape(3, 3)
|
|
748
763
|
inertia = rot @ np.diag(i_diag) @ rot.T
|
|
749
764
|
builder.body_inertia[body_id] = inertia
|
|
750
765
|
if inertia.any():
|
|
751
|
-
builder.body_inv_inertia[body_id] =
|
|
766
|
+
builder.body_inv_inertia[body_id] = wp.inverse(wp.mat33(*inertia))
|
|
752
767
|
else:
|
|
753
|
-
builder.body_inv_inertia[body_id] = np.zeros((3, 3), dtype=np.float32)
|
|
768
|
+
builder.body_inv_inertia[body_id] = wp.mat33(*np.zeros((3, 3), dtype=np.float32))
|
|
754
769
|
|
|
755
770
|
parse_prim(
|
|
756
771
|
stage.GetDefaultPrim(), incoming_xform=wp.transform(), incoming_scale=np.ones(3, dtype=np.float32) * linear_unit
|
warp/sim/inertia.py
CHANGED
|
@@ -33,7 +33,7 @@ def triangle_inertia(
|
|
|
33
33
|
|
|
34
34
|
Dm = wp.mat33(pcom[0], qcom[0], rcom[0], pcom[1], qcom[1], rcom[1], pcom[2], qcom[2], rcom[2])
|
|
35
35
|
|
|
36
|
-
volume = wp.determinant(Dm) / 6.0
|
|
36
|
+
volume = wp.abs(wp.determinant(Dm) / 6.0)
|
|
37
37
|
|
|
38
38
|
# accumulate mass
|
|
39
39
|
wp.atomic_add(mass, 0, 4.0 * density * volume)
|
|
@@ -260,6 +260,7 @@ def compute_mesh_inertia(
|
|
|
260
260
|
"""Computes mass, center of mass, 3x3 inertia matrix, and volume for a mesh."""
|
|
261
261
|
com = wp.vec3(np.mean(vertices, 0))
|
|
262
262
|
|
|
263
|
+
indices = np.array(indices).flatten()
|
|
263
264
|
num_tris = len(indices) // 3
|
|
264
265
|
|
|
265
266
|
# compute signed inertia for each tetrahedron
|
|
@@ -305,7 +306,7 @@ def compute_mesh_inertia(
|
|
|
305
306
|
# Extract mass and inertia and save to class attributes.
|
|
306
307
|
mass = float(mass_warp.numpy()[0] * density)
|
|
307
308
|
I = wp.mat33(*(I_warp.numpy()[0] * density))
|
|
308
|
-
volume = vol_warp.numpy()[0]
|
|
309
|
+
volume = float(vol_warp.numpy()[0])
|
|
309
310
|
return mass, com, I, volume
|
|
310
311
|
|
|
311
312
|
|