warp-lang 0.10.1__py3-none-win_amd64.whl → 0.11.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +10 -4
- warp/__init__.pyi +1 -0
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +5 -3
- warp/build_dll.py +29 -9
- warp/builtins.py +868 -507
- warp/codegen.py +1074 -638
- warp/config.py +3 -3
- warp/constants.py +6 -0
- warp/context.py +715 -222
- warp/fabric.py +326 -0
- warp/fem/__init__.py +27 -0
- warp/fem/cache.py +389 -0
- warp/fem/dirichlet.py +181 -0
- warp/fem/domain.py +263 -0
- warp/fem/field/__init__.py +101 -0
- warp/fem/field/field.py +149 -0
- warp/fem/field/nodal_field.py +299 -0
- warp/fem/field/restriction.py +21 -0
- warp/fem/field/test.py +181 -0
- warp/fem/field/trial.py +183 -0
- warp/fem/geometry/__init__.py +19 -0
- warp/fem/geometry/closest_point.py +70 -0
- warp/fem/geometry/deformed_geometry.py +271 -0
- warp/fem/geometry/element.py +744 -0
- warp/fem/geometry/geometry.py +186 -0
- warp/fem/geometry/grid_2d.py +373 -0
- warp/fem/geometry/grid_3d.py +435 -0
- warp/fem/geometry/hexmesh.py +953 -0
- warp/fem/geometry/partition.py +376 -0
- warp/fem/geometry/quadmesh_2d.py +532 -0
- warp/fem/geometry/tetmesh.py +840 -0
- warp/fem/geometry/trimesh_2d.py +577 -0
- warp/fem/integrate.py +1616 -0
- warp/fem/operator.py +191 -0
- warp/fem/polynomial.py +213 -0
- warp/fem/quadrature/__init__.py +2 -0
- warp/fem/quadrature/pic_quadrature.py +245 -0
- warp/fem/quadrature/quadrature.py +294 -0
- warp/fem/space/__init__.py +292 -0
- warp/fem/space/basis_space.py +489 -0
- warp/fem/space/collocated_function_space.py +105 -0
- warp/fem/space/dof_mapper.py +236 -0
- warp/fem/space/function_space.py +145 -0
- warp/fem/space/grid_2d_function_space.py +267 -0
- warp/fem/space/grid_3d_function_space.py +306 -0
- warp/fem/space/hexmesh_function_space.py +352 -0
- warp/fem/space/partition.py +350 -0
- warp/fem/space/quadmesh_2d_function_space.py +369 -0
- warp/fem/space/restriction.py +160 -0
- warp/fem/space/shape/__init__.py +15 -0
- warp/fem/space/shape/cube_shape_function.py +738 -0
- warp/fem/space/shape/shape_function.py +103 -0
- warp/fem/space/shape/square_shape_function.py +611 -0
- warp/fem/space/shape/tet_shape_function.py +567 -0
- warp/fem/space/shape/triangle_shape_function.py +429 -0
- warp/fem/space/tetmesh_function_space.py +292 -0
- warp/fem/space/topology.py +295 -0
- warp/fem/space/trimesh_2d_function_space.py +221 -0
- warp/fem/types.py +77 -0
- warp/fem/utils.py +495 -0
- warp/native/array.h +147 -44
- warp/native/builtin.h +122 -149
- warp/native/bvh.cpp +73 -325
- warp/native/bvh.cu +406 -23
- warp/native/bvh.h +34 -43
- warp/native/clang/clang.cpp +13 -8
- warp/native/crt.h +2 -0
- warp/native/cuda_crt.h +5 -0
- warp/native/cuda_util.cpp +15 -3
- warp/native/cuda_util.h +3 -1
- warp/native/cutlass/tools/library/scripts/conv2d_operation.py +463 -0
- warp/native/cutlass/tools/library/scripts/conv3d_operation.py +321 -0
- warp/native/cutlass/tools/library/scripts/gemm_operation.py +988 -0
- warp/native/cutlass/tools/library/scripts/generator.py +4625 -0
- warp/native/cutlass/tools/library/scripts/library.py +799 -0
- warp/native/cutlass/tools/library/scripts/manifest.py +402 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/docs/source/conf.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/profile/conv/conv2d_f16_sm80.py +106 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/profile/gemm/gemm_f32_sm80.py +91 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/setup.py +80 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/__init__.py +48 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/arguments.py +118 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/c_types.py +241 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/compiler.py +432 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/conv2d_operation.py +631 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/epilogue.py +1026 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/frontend.py +104 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/gemm_operation.py +1276 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/library.py +744 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/memory_manager.py +74 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/operation.py +110 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/parser.py +619 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/reduction_operation.py +398 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/tensor_ref.py +70 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/__init__.py +4 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/conv2d_testbed.py +646 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_grouped_testbed.py +235 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_testbed.py +557 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/profiler.py +70 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/type_hint.py +39 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/__init__.py +1 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/device.py +76 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/reference_model.py +255 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/__init__.py +0 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +201 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +177 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +98 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +95 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_few_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +163 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_fixed_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +187 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +309 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +54 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_strided_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +253 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +97 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +242 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/run_all_tests.py +10 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/frontend/test_frontend.py +146 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/__init__.py +0 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_bf16_sm80.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f16_sm80.py +447 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f32_sm80.py +146 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f64_sm80.py +102 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_grouped_sm80.py +203 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_s8_sm80.py +229 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/run_all_tests.py +9 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/unit/test_sm80.py +453 -0
- warp/native/cutlass/tools/library/scripts/rank_2k_operation.py +398 -0
- warp/native/cutlass/tools/library/scripts/rank_k_operation.py +387 -0
- warp/native/cutlass/tools/library/scripts/rt.py +796 -0
- warp/native/cutlass/tools/library/scripts/symm_operation.py +400 -0
- warp/native/cutlass/tools/library/scripts/trmm_operation.py +407 -0
- warp/native/cutlass_gemm.cu +5 -3
- warp/native/exports.h +1240 -952
- warp/native/fabric.h +228 -0
- warp/native/hashgrid.cpp +4 -4
- warp/native/hashgrid.h +22 -2
- warp/native/intersect.h +22 -7
- warp/native/intersect_adj.h +8 -8
- warp/native/intersect_tri.h +1 -1
- warp/native/marching.cu +157 -161
- warp/native/mat.h +80 -19
- warp/native/matnn.h +2 -2
- warp/native/mesh.cpp +33 -108
- warp/native/mesh.cu +114 -23
- warp/native/mesh.h +446 -46
- warp/native/noise.h +272 -329
- warp/native/quat.h +51 -8
- warp/native/rand.h +45 -35
- warp/native/range.h +6 -2
- warp/native/reduce.cpp +1 -1
- warp/native/reduce.cu +10 -12
- warp/native/runlength_encode.cu +6 -10
- warp/native/scan.cu +8 -11
- warp/native/sparse.cpp +4 -4
- warp/native/sparse.cu +164 -154
- warp/native/spatial.h +2 -2
- warp/native/temp_buffer.h +14 -30
- warp/native/vec.h +107 -23
- warp/native/volume.h +120 -0
- warp/native/warp.cpp +560 -30
- warp/native/warp.cu +431 -44
- warp/native/warp.h +13 -4
- warp/optim/__init__.py +1 -0
- warp/optim/linear.py +922 -0
- warp/optim/sgd.py +92 -0
- warp/render/render_opengl.py +335 -119
- warp/render/render_usd.py +11 -11
- warp/sim/__init__.py +2 -2
- warp/sim/articulation.py +385 -185
- warp/sim/collide.py +8 -0
- warp/sim/import_mjcf.py +297 -106
- warp/sim/import_urdf.py +389 -210
- warp/sim/import_usd.py +198 -97
- warp/sim/inertia.py +17 -18
- warp/sim/integrator_euler.py +14 -8
- warp/sim/integrator_xpbd.py +158 -16
- warp/sim/model.py +795 -291
- warp/sim/render.py +3 -3
- warp/sim/utils.py +3 -0
- warp/sparse.py +640 -150
- warp/stubs.py +606 -267
- warp/tape.py +61 -10
- warp/tests/__main__.py +3 -6
- warp/tests/assets/curlnoise_golden.npy +0 -0
- warp/tests/assets/pnoise_golden.npy +0 -0
- warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
- warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
- warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
- warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
- warp/tests/aux_test_unresolved_func.py +14 -0
- warp/tests/aux_test_unresolved_symbol.py +14 -0
- warp/tests/disabled_kinematics.py +239 -0
- warp/tests/run_coverage_serial.py +31 -0
- warp/tests/test_adam.py +103 -106
- warp/tests/test_arithmetic.py +128 -74
- warp/tests/test_array.py +212 -97
- warp/tests/test_array_reduce.py +57 -23
- warp/tests/test_atomic.py +64 -28
- warp/tests/test_bool.py +99 -0
- warp/tests/test_builtins_resolution.py +1292 -0
- warp/tests/test_bvh.py +42 -18
- warp/tests/test_closest_point_edge_edge.py +54 -57
- warp/tests/test_codegen.py +208 -130
- warp/tests/test_compile_consts.py +28 -20
- warp/tests/test_conditional.py +108 -24
- warp/tests/test_copy.py +10 -12
- warp/tests/test_ctypes.py +112 -88
- warp/tests/test_dense.py +21 -14
- warp/tests/test_devices.py +98 -0
- warp/tests/test_dlpack.py +75 -75
- warp/tests/test_examples.py +277 -0
- warp/tests/test_fabricarray.py +955 -0
- warp/tests/test_fast_math.py +15 -11
- warp/tests/test_fem.py +1271 -0
- warp/tests/test_fp16.py +53 -19
- warp/tests/test_func.py +187 -86
- warp/tests/test_generics.py +194 -49
- warp/tests/test_grad.py +178 -109
- warp/tests/test_grad_customs.py +176 -0
- warp/tests/test_hash_grid.py +52 -37
- warp/tests/test_import.py +10 -23
- warp/tests/test_indexedarray.py +32 -31
- warp/tests/test_intersect.py +18 -9
- warp/tests/test_large.py +141 -0
- warp/tests/test_launch.py +14 -41
- warp/tests/test_lerp.py +64 -65
- warp/tests/test_linear_solvers.py +154 -0
- warp/tests/test_lvalue.py +493 -0
- warp/tests/test_marching_cubes.py +12 -13
- warp/tests/test_mat.py +517 -2898
- warp/tests/test_mat_lite.py +115 -0
- warp/tests/test_mat_scalar_ops.py +2889 -0
- warp/tests/test_math.py +103 -9
- warp/tests/test_matmul.py +305 -69
- warp/tests/test_matmul_lite.py +410 -0
- warp/tests/test_mesh.py +71 -14
- warp/tests/test_mesh_query_aabb.py +41 -25
- warp/tests/test_mesh_query_point.py +140 -22
- warp/tests/test_mesh_query_ray.py +39 -22
- warp/tests/test_mlp.py +30 -22
- warp/tests/test_model.py +92 -89
- warp/tests/test_modules_lite.py +39 -0
- warp/tests/test_multigpu.py +88 -114
- warp/tests/test_noise.py +12 -11
- warp/tests/test_operators.py +16 -20
- warp/tests/test_options.py +11 -11
- warp/tests/test_pinned.py +17 -18
- warp/tests/test_print.py +32 -11
- warp/tests/test_quat.py +275 -129
- warp/tests/test_rand.py +18 -16
- warp/tests/test_reload.py +38 -34
- warp/tests/test_rounding.py +50 -43
- warp/tests/test_runlength_encode.py +168 -20
- warp/tests/test_smoothstep.py +9 -11
- warp/tests/test_snippet.py +143 -0
- warp/tests/test_sparse.py +261 -63
- warp/tests/test_spatial.py +276 -243
- warp/tests/test_streams.py +110 -85
- warp/tests/test_struct.py +268 -63
- warp/tests/test_tape.py +39 -21
- warp/tests/test_torch.py +118 -89
- warp/tests/test_transient_module.py +12 -13
- warp/tests/test_types.py +614 -0
- warp/tests/test_utils.py +494 -0
- warp/tests/test_vec.py +354 -2050
- warp/tests/test_vec_lite.py +73 -0
- warp/tests/test_vec_scalar_ops.py +2099 -0
- warp/tests/test_volume.py +457 -293
- warp/tests/test_volume_write.py +124 -134
- warp/tests/unittest_serial.py +35 -0
- warp/tests/unittest_suites.py +341 -0
- warp/tests/unittest_utils.py +568 -0
- warp/tests/unused_test_misc.py +71 -0
- warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
- warp/thirdparty/appdirs.py +36 -45
- warp/thirdparty/unittest_parallel.py +549 -0
- warp/torch.py +9 -6
- warp/types.py +1089 -366
- warp/utils.py +93 -387
- warp_lang-0.11.0.dist-info/METADATA +238 -0
- warp_lang-0.11.0.dist-info/RECORD +332 -0
- {warp_lang-0.10.1.dist-info → warp_lang-0.11.0.dist-info}/WHEEL +1 -1
- warp/tests/test_all.py +0 -219
- warp/tests/test_array_scan.py +0 -60
- warp/tests/test_base.py +0 -208
- warp/tests/test_unresolved_func.py +0 -7
- warp/tests/test_unresolved_symbol.py +0 -7
- warp_lang-0.10.1.dist-info/METADATA +0 -21
- warp_lang-0.10.1.dist-info/RECORD +0 -188
- /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
- /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
- /warp/tests/{test_square.py → aux_test_square.py} +0 -0
- {warp_lang-0.10.1.dist-info → warp_lang-0.11.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-0.10.1.dist-info → warp_lang-0.11.0.dist-info}/top_level.txt +0 -0
warp/sim/import_usd.py
CHANGED
|
@@ -10,95 +10,80 @@ import numpy as np
|
|
|
10
10
|
import re
|
|
11
11
|
|
|
12
12
|
import warp as wp
|
|
13
|
-
from . import ModelBuilder
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
def parse_usd(
|
|
17
|
-
|
|
18
|
-
builder
|
|
16
|
+
source,
|
|
17
|
+
builder,
|
|
19
18
|
default_density=1.0e3,
|
|
20
19
|
only_load_enabled_rigid_bodies=False,
|
|
21
20
|
only_load_enabled_joints=True,
|
|
22
21
|
default_ke=1e5,
|
|
23
22
|
default_kd=250.0,
|
|
24
23
|
default_kf=500.0,
|
|
25
|
-
default_mu=0.
|
|
24
|
+
default_mu=0.6,
|
|
26
25
|
default_restitution=0.0,
|
|
27
26
|
default_thickness=0.0,
|
|
28
27
|
joint_limit_ke=100.0,
|
|
29
28
|
joint_limit_kd=10.0,
|
|
29
|
+
invert_rotations=False,
|
|
30
30
|
verbose=False,
|
|
31
31
|
ignore_paths=[],
|
|
32
|
-
export_usda=False,
|
|
33
32
|
):
|
|
33
|
+
"""
|
|
34
|
+
Parses a Universal Scene Description (USD) stage containing UsdPhysics schema definitions for rigid-body articulations and adds the bodies, shapes and joints to the given ModelBuilder.
|
|
35
|
+
|
|
36
|
+
The USD description has to be either a path (file name or URL), or an existing USD stage instance that implements the `UsdStage <https://openusd.org/dev/api/class_usd_stage.html>`_ interface.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
source (str | pxr.UsdStage): The file path to the USD file, or an existing USD stage instance.
|
|
40
|
+
builder (ModelBuilder): The :class:`ModelBuilder` to add the bodies and joints to.
|
|
41
|
+
default_density (float): The default density to use for bodies without a density attribute.
|
|
42
|
+
only_load_enabled_rigid_bodies (bool): If True, only rigid bodies which do not have `physics:rigidBodyEnabled` set to False are loaded.
|
|
43
|
+
only_load_enabled_joints (bool): If True, only joints which do not have `physics:jointEnabled` set to False are loaded.
|
|
44
|
+
default_ke (float): The default contact stiffness to use, only considered by SemiImplicitIntegrator.
|
|
45
|
+
default_kd (float): The default contact damping to use, only considered by SemiImplicitIntegrator.
|
|
46
|
+
default_kf (float): The default friction stiffness to use, only considered by SemiImplicitIntegrator.
|
|
47
|
+
default_mu (float): The default friction coefficient to use if a shape has not friction coefficient defined.
|
|
48
|
+
default_restitution (float): The default coefficient of restitution to use if a shape has not coefficient of restitution defined.
|
|
49
|
+
default_thickness (float): The thickness to add to the shape geometry.
|
|
50
|
+
joint_limit_ke (float): The default stiffness to use for joint limits, only considered by SemiImplicitIntegrator.
|
|
51
|
+
joint_limit_kd (float): The default damping to use for joint limits, only considered by SemiImplicitIntegrator.
|
|
52
|
+
invert_rotations (bool): If True, inverts any rotations defined in the shape transforms.
|
|
53
|
+
verbose (bool): If True, print additional information about the parsed USD file.
|
|
54
|
+
ignore_paths (List[str]): A list of regular expressions matching prim paths to ignore.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
dict: Dictionary with the following entries:
|
|
58
|
+
|
|
59
|
+
.. list-table::
|
|
60
|
+
:widths: 25 75
|
|
61
|
+
|
|
62
|
+
* - "fps"
|
|
63
|
+
- USD stage frames per second
|
|
64
|
+
* - "duration"
|
|
65
|
+
- Difference between end time code and start time code of the USD stage
|
|
66
|
+
* - "up_axis"
|
|
67
|
+
- Upper-case string of the stage's up axis ("X", "Y", or "Z")
|
|
68
|
+
* - "path_shape_map"
|
|
69
|
+
- Mapping from prim path (str) of the UsdGeom to the respective shape index in :class:`ModelBuilder`
|
|
70
|
+
* - "path_body_map"
|
|
71
|
+
- Mapping from prim path (str) of a rigid body prim (e.g. that implements the PhysicsRigidBodyAPI) to the respective body index in :class:`ModelBuilder`
|
|
72
|
+
* - "path_shape_scale"
|
|
73
|
+
- Mapping from prim path (str) of the UsdGeom to its respective 3D world scale
|
|
74
|
+
* - "mass_unit"
|
|
75
|
+
- The stage's Kilograms Per Unit (KGPU) definition (1.0 by default)
|
|
76
|
+
* - "linear_unit"
|
|
77
|
+
- The stage's Meters Per Unit (MPU) definition (1.0 by default)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
Note:
|
|
81
|
+
This importer is experimental and only supports a subset of the USD Physics schema. Please report any issues you encounter.
|
|
82
|
+
"""
|
|
34
83
|
try:
|
|
35
84
|
from pxr import Usd, UsdGeom, UsdPhysics
|
|
36
85
|
except ImportError:
|
|
37
|
-
raise ImportError("Failed to import pxr. Please install USD.")
|
|
38
|
-
|
|
39
|
-
if filename.startswith("http://") or filename.startswith("https://"):
|
|
40
|
-
# download file
|
|
41
|
-
import requests, os, datetime
|
|
42
|
-
|
|
43
|
-
response = requests.get(filename, allow_redirects=True)
|
|
44
|
-
if response.status_code != 200:
|
|
45
|
-
raise RuntimeError(f"Failed to download USD file. Status code: {response.status_code}")
|
|
46
|
-
file = response.content
|
|
47
|
-
dot = os.path.extsep
|
|
48
|
-
base = os.path.basename(filename)
|
|
49
|
-
url_folder = os.path.dirname(filename)
|
|
50
|
-
base_name = dot.join(base.split(dot)[:-1])
|
|
51
|
-
timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
|
52
|
-
folder_name = os.path.join(".usd_cache", f"{base_name}_{timestamp}")
|
|
53
|
-
os.makedirs(folder_name, exist_ok=True)
|
|
54
|
-
target_filename = os.path.join(folder_name, base)
|
|
55
|
-
with open(target_filename, "wb") as f:
|
|
56
|
-
f.write(file)
|
|
57
|
-
|
|
58
|
-
stage = Usd.Stage.Open(target_filename, Usd.Stage.LoadNone)
|
|
59
|
-
stage_str = stage.GetRootLayer().ExportToString()
|
|
60
|
-
print(f"Downloaded USD file to {target_filename}.")
|
|
61
|
-
if export_usda:
|
|
62
|
-
usda_filename = os.path.join(folder_name, base_name + ".usda")
|
|
63
|
-
with open(usda_filename, "w") as f:
|
|
64
|
-
f.write(stage_str)
|
|
65
|
-
print(f"Exported USDA file to {usda_filename}.")
|
|
66
|
-
|
|
67
|
-
# parse referenced USD files like `references = @./franka_collisions.usd@`
|
|
68
|
-
downloaded = set()
|
|
69
|
-
for match in re.finditer(r"references.=.@(.*?)@", stage_str):
|
|
70
|
-
refname = match.group(1)
|
|
71
|
-
if refname.startswith("./"):
|
|
72
|
-
refname = refname[2:]
|
|
73
|
-
if refname in downloaded:
|
|
74
|
-
continue
|
|
75
|
-
try:
|
|
76
|
-
response = requests.get(f"{url_folder}/{refname}", allow_redirects=True)
|
|
77
|
-
if response.status_code != 200:
|
|
78
|
-
print(f"Failed to download reference {refname}. Status code: {response.status_code}")
|
|
79
|
-
continue
|
|
80
|
-
file = response.content
|
|
81
|
-
refdir = os.path.dirname(refname)
|
|
82
|
-
if refdir:
|
|
83
|
-
os.makedirs(os.path.join(folder_name, refdir), exist_ok=True)
|
|
84
|
-
ref_filename = os.path.join(folder_name, refname)
|
|
85
|
-
with open(ref_filename, "wb") as f:
|
|
86
|
-
f.write(file)
|
|
87
|
-
downloaded.add(refname)
|
|
88
|
-
print(f"Downloaded USD reference {refname} to {ref_filename}.")
|
|
89
|
-
if export_usda:
|
|
90
|
-
ref_stage = Usd.Stage.Open(ref_filename, Usd.Stage.LoadNone)
|
|
91
|
-
ref_stage_str = ref_stage.GetRootLayer().ExportToString()
|
|
92
|
-
base = os.path.basename(ref_filename)
|
|
93
|
-
base_name = dot.join(base.split(dot)[:-1])
|
|
94
|
-
usda_filename = os.path.join(folder_name, base_name + ".usda")
|
|
95
|
-
with open(usda_filename, "w") as f:
|
|
96
|
-
f.write(ref_stage_str)
|
|
97
|
-
print(f"Exported USDA file to {usda_filename}.")
|
|
98
|
-
except:
|
|
99
|
-
print(f"Failed to download {refname}.")
|
|
100
|
-
|
|
101
|
-
filename = target_filename
|
|
86
|
+
raise ImportError("Failed to import pxr. Please install USD (e.g. via `pip install usd-core`).")
|
|
102
87
|
|
|
103
88
|
def get_attribute(prim, name):
|
|
104
89
|
if "*" in name:
|
|
@@ -127,7 +112,10 @@ def parse_usd(
|
|
|
127
112
|
if not attr or not attr.HasAuthoredValue():
|
|
128
113
|
return default
|
|
129
114
|
val = attr.Get()
|
|
130
|
-
|
|
115
|
+
if invert_rotations:
|
|
116
|
+
quat = wp.quat(*val.imaginary, -val.real)
|
|
117
|
+
else:
|
|
118
|
+
quat = wp.quat(*val.imaginary, val.real)
|
|
131
119
|
l = wp.length(quat)
|
|
132
120
|
if np.isfinite(l) and l > 0.0:
|
|
133
121
|
return quat
|
|
@@ -153,20 +141,31 @@ def parse_usd(
|
|
|
153
141
|
axis["XYZ".index(s.upper())] = 1.0
|
|
154
142
|
return axis
|
|
155
143
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
mass_unit = UsdPhysics.GetStageKilogramsPerUnit(stage)
|
|
144
|
+
if isinstance(source, str):
|
|
145
|
+
stage = Usd.Stage.Open(source, Usd.Stage.LoadAll)
|
|
159
146
|
else:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
147
|
+
stage = source
|
|
148
|
+
|
|
149
|
+
mass_unit = 1.0
|
|
150
|
+
try:
|
|
151
|
+
if UsdPhysics.StageHasAuthoredKilogramsPerUnit(stage):
|
|
152
|
+
mass_unit = UsdPhysics.GetStageKilogramsPerUnit(stage)
|
|
153
|
+
except:
|
|
154
|
+
pass
|
|
155
|
+
linear_unit = 1.0
|
|
156
|
+
try:
|
|
157
|
+
if UsdGeom.StageHasAuthoredMetersPerUnit(stage):
|
|
158
|
+
linear_unit = UsdGeom.GetStageMetersPerUnit(stage)
|
|
159
|
+
except:
|
|
160
|
+
pass
|
|
165
161
|
|
|
166
162
|
def parse_xform(prim):
|
|
167
163
|
xform = UsdGeom.Xform(prim)
|
|
168
164
|
mat = np.array(xform.GetLocalTransformation(), dtype=np.float32)
|
|
169
|
-
|
|
165
|
+
if invert_rotations:
|
|
166
|
+
rot = wp.quat_from_matrix(wp.mat33(mat[:3, :3].T.flatten()))
|
|
167
|
+
else:
|
|
168
|
+
rot = wp.quat_from_matrix(wp.mat33(mat[:3, :3].flatten()))
|
|
170
169
|
pos = mat[3, :3] * linear_unit
|
|
171
170
|
scale = np.ones(3, dtype=np.float32)
|
|
172
171
|
for op in xform.GetOrderedXformOps():
|
|
@@ -247,12 +246,18 @@ def parse_usd(
|
|
|
247
246
|
else:
|
|
248
247
|
joint_data["linear_axes"].append(axis)
|
|
249
248
|
|
|
250
|
-
|
|
249
|
+
axis_str = "Y"
|
|
250
|
+
try:
|
|
251
|
+
axis_str = UsdGeom.GetStageUpAxis(stage)
|
|
252
|
+
except:
|
|
253
|
+
pass
|
|
254
|
+
upaxis = str2axis(axis_str)
|
|
251
255
|
|
|
252
256
|
shape_types = {"Cube", "Sphere", "Mesh", "Capsule", "Plane", "Cylinder", "Cone"}
|
|
253
257
|
|
|
254
258
|
path_body_map = {}
|
|
255
259
|
path_shape_map = {}
|
|
260
|
+
path_shape_scale = {}
|
|
256
261
|
# maps prim path name to its world transform
|
|
257
262
|
path_world_poses = {}
|
|
258
263
|
# transform from body frame to where the actual joint child frame is
|
|
@@ -347,21 +352,27 @@ def parse_usd(
|
|
|
347
352
|
materials[path] = material
|
|
348
353
|
|
|
349
354
|
elif type_name == "PhysicsScene":
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
355
|
+
try:
|
|
356
|
+
scene = UsdPhysics.Scene(prim)
|
|
357
|
+
g_vec = scene.GetGravityDirectionAttr()
|
|
358
|
+
g_mag = scene.GetGravityMagnitudeAttr()
|
|
359
|
+
if g_mag.HasAuthoredValue() and np.isfinite(g_mag.Get()):
|
|
360
|
+
builder.gravity = -np.abs(g_mag.Get() * linear_unit)
|
|
361
|
+
if g_vec.HasAuthoredValue() and np.linalg.norm(g_vec.Get()) > 0.0:
|
|
362
|
+
builder.up_vector = np.array(g_vec.Get(), dtype=np.float32)
|
|
363
|
+
if np.any(builder.up_vector < 0.0):
|
|
364
|
+
builder.up_vector = -builder.up_vector
|
|
365
|
+
else:
|
|
366
|
+
builder.up_vector = upaxis
|
|
367
|
+
except:
|
|
368
|
+
pass
|
|
359
369
|
|
|
360
370
|
def parse_prim(prim, incoming_xform, incoming_scale, parent_body: int = -1):
|
|
361
371
|
nonlocal builder
|
|
362
372
|
nonlocal joint_data
|
|
363
373
|
nonlocal path_body_map
|
|
364
374
|
nonlocal path_shape_map
|
|
375
|
+
nonlocal path_shape_scale
|
|
365
376
|
nonlocal path_world_poses
|
|
366
377
|
nonlocal prim_joint_xforms
|
|
367
378
|
nonlocal path_collision_filters
|
|
@@ -374,13 +385,14 @@ def parse_usd(
|
|
|
374
385
|
return
|
|
375
386
|
|
|
376
387
|
type_name = str(prim.GetTypeName())
|
|
377
|
-
if (
|
|
378
|
-
type_name.endswith("Joint")
|
|
379
|
-
or type_name.endswith("Light")
|
|
380
|
-
or type_name.endswith("Scene")
|
|
381
|
-
or type_name.endswith("Material")
|
|
382
|
-
):
|
|
388
|
+
if type_name.endswith("Joint") or type_name.endswith("Light") or type_name.endswith("Material"):
|
|
383
389
|
return
|
|
390
|
+
if verbose:
|
|
391
|
+
print(f"parse_prim {prim.GetPath()} ({type_name})")
|
|
392
|
+
if type_name == "PhysicsScene":
|
|
393
|
+
# in case the PhysicsScene has bodies as children...
|
|
394
|
+
for child in prim.GetChildren():
|
|
395
|
+
parse_prim(child, incoming_xform, incoming_scale, parent_body)
|
|
384
396
|
|
|
385
397
|
schemas = set(prim.GetAppliedSchemas())
|
|
386
398
|
children_refs = prim.GetChildren()
|
|
@@ -696,6 +708,7 @@ def parse_usd(
|
|
|
696
708
|
|
|
697
709
|
path_body_map[path] = body_id
|
|
698
710
|
path_shape_map[path] = shape_id
|
|
711
|
+
path_shape_scale[path] = scale
|
|
699
712
|
|
|
700
713
|
if prim.HasRelationship("physics:filteredPairs"):
|
|
701
714
|
other_paths = prim.GetRelationship("physics:filteredPairs").GetTargets()
|
|
@@ -761,5 +774,93 @@ def parse_usd(
|
|
|
761
774
|
return {
|
|
762
775
|
"fps": stage.GetFramesPerSecond(),
|
|
763
776
|
"duration": stage.GetEndTimeCode() - stage.GetStartTimeCode(),
|
|
764
|
-
"up_axis": UsdGeom.GetStageUpAxis(stage).
|
|
777
|
+
"up_axis": UsdGeom.GetStageUpAxis(stage).upper(),
|
|
778
|
+
"path_shape_map": path_shape_map,
|
|
779
|
+
"path_body_map": path_body_map,
|
|
780
|
+
"path_shape_scale": path_shape_scale,
|
|
781
|
+
"mass_unit": mass_unit,
|
|
782
|
+
"linear_unit": linear_unit,
|
|
765
783
|
}
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
def resolve_usd_from_url(url: str, target_folder_name: str = None, export_usda: bool = False):
|
|
787
|
+
"""
|
|
788
|
+
Downloads a USD file from a URL and resolves all references to other USD files to be downloaded to the given target folder.
|
|
789
|
+
|
|
790
|
+
Args:
|
|
791
|
+
url (str): URL to the USD file.
|
|
792
|
+
target_folder_name (str): Target folder name. If None, a timestamped folder will be created in the current directory.
|
|
793
|
+
export_usda (bool): If True, converts each downloaded USD file to USDA and saves the additional USDA file in the target folder with the same base name as the original USD file.
|
|
794
|
+
|
|
795
|
+
Returns:
|
|
796
|
+
str: File path to the downloaded USD file.
|
|
797
|
+
"""
|
|
798
|
+
import requests
|
|
799
|
+
import datetime
|
|
800
|
+
import os
|
|
801
|
+
|
|
802
|
+
try:
|
|
803
|
+
from pxr import Usd
|
|
804
|
+
except ImportError:
|
|
805
|
+
raise ImportError("Failed to import pxr. Please install USD (e.g. via `pip install usd-core`).")
|
|
806
|
+
|
|
807
|
+
response = requests.get(url, allow_redirects=True)
|
|
808
|
+
if response.status_code != 200:
|
|
809
|
+
raise RuntimeError(f"Failed to download USD file. Status code: {response.status_code}")
|
|
810
|
+
file = response.content
|
|
811
|
+
dot = os.path.extsep
|
|
812
|
+
base = os.path.basename(url)
|
|
813
|
+
url_folder = os.path.dirname(url)
|
|
814
|
+
base_name = dot.join(base.split(dot)[:-1])
|
|
815
|
+
if target_folder_name is None:
|
|
816
|
+
timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
|
817
|
+
target_folder_name = os.path.join(".usd_cache", f"{base_name}_{timestamp}")
|
|
818
|
+
os.makedirs(target_folder_name, exist_ok=True)
|
|
819
|
+
target_filename = os.path.join(target_folder_name, base)
|
|
820
|
+
with open(target_filename, "wb") as f:
|
|
821
|
+
f.write(file)
|
|
822
|
+
|
|
823
|
+
stage = Usd.Stage.Open(target_filename, Usd.Stage.LoadNone)
|
|
824
|
+
stage_str = stage.GetRootLayer().ExportToString()
|
|
825
|
+
print(f"Downloaded USD file to {target_filename}.")
|
|
826
|
+
if export_usda:
|
|
827
|
+
usda_filename = os.path.join(target_folder_name, base_name + ".usda")
|
|
828
|
+
with open(usda_filename, "w") as f:
|
|
829
|
+
f.write(stage_str)
|
|
830
|
+
print(f"Exported USDA file to {usda_filename}.")
|
|
831
|
+
|
|
832
|
+
# parse referenced USD files like `references = @./franka_collisions.usd@`
|
|
833
|
+
downloaded = set()
|
|
834
|
+
for match in re.finditer(r"references.=.@(.*?)@", stage_str):
|
|
835
|
+
refname = match.group(1)
|
|
836
|
+
if refname.startswith("./"):
|
|
837
|
+
refname = refname[2:]
|
|
838
|
+
if refname in downloaded:
|
|
839
|
+
continue
|
|
840
|
+
try:
|
|
841
|
+
response = requests.get(f"{url_folder}/{refname}", allow_redirects=True)
|
|
842
|
+
if response.status_code != 200:
|
|
843
|
+
print(f"Failed to download reference {refname}. Status code: {response.status_code}")
|
|
844
|
+
continue
|
|
845
|
+
file = response.content
|
|
846
|
+
refdir = os.path.dirname(refname)
|
|
847
|
+
if refdir:
|
|
848
|
+
os.makedirs(os.path.join(target_folder_name, refdir), exist_ok=True)
|
|
849
|
+
ref_filename = os.path.join(target_folder_name, refname)
|
|
850
|
+
if not os.path.exists(ref_filename):
|
|
851
|
+
with open(ref_filename, "wb") as f:
|
|
852
|
+
f.write(file)
|
|
853
|
+
downloaded.add(refname)
|
|
854
|
+
print(f"Downloaded USD reference {refname} to {ref_filename}.")
|
|
855
|
+
if export_usda:
|
|
856
|
+
ref_stage = Usd.Stage.Open(ref_filename, Usd.Stage.LoadNone)
|
|
857
|
+
ref_stage_str = ref_stage.GetRootLayer().ExportToString()
|
|
858
|
+
base = os.path.basename(ref_filename)
|
|
859
|
+
base_name = dot.join(base.split(dot)[:-1])
|
|
860
|
+
usda_filename = os.path.join(target_folder_name, base_name + ".usda")
|
|
861
|
+
with open(usda_filename, "w") as f:
|
|
862
|
+
f.write(ref_stage_str)
|
|
863
|
+
print(f"Exported USDA file to {usda_filename}.")
|
|
864
|
+
except Exception:
|
|
865
|
+
print(f"Failed to download {refname}.")
|
|
866
|
+
return target_filename
|
warp/sim/inertia.py
CHANGED
|
@@ -149,9 +149,9 @@ def compute_sphere_inertia(density: float, r: float) -> tuple:
|
|
|
149
149
|
m = density * v
|
|
150
150
|
Ia = 2.0 / 5.0 * m * r * r
|
|
151
151
|
|
|
152
|
-
I =
|
|
152
|
+
I = wp.mat33([[Ia, 0.0, 0.0], [0.0, Ia, 0.0], [0.0, 0.0, Ia]])
|
|
153
153
|
|
|
154
|
-
return (m,
|
|
154
|
+
return (m, wp.vec3(), I)
|
|
155
155
|
|
|
156
156
|
|
|
157
157
|
def compute_capsule_inertia(density: float, r: float, h: float) -> tuple:
|
|
@@ -177,9 +177,9 @@ def compute_capsule_inertia(density: float, r: float, h: float) -> tuple:
|
|
|
177
177
|
Ia = mc * (0.25 * r * r + (1.0 / 12.0) * h * h) + ms * (0.4 * r * r + 0.375 * r * h + 0.25 * h * h)
|
|
178
178
|
Ib = (mc * 0.5 + ms * 0.4) * r * r
|
|
179
179
|
|
|
180
|
-
I =
|
|
180
|
+
I = wp.mat33([[Ia, 0.0, 0.0], [0.0, Ib, 0.0], [0.0, 0.0, Ia]])
|
|
181
181
|
|
|
182
|
-
return (m,
|
|
182
|
+
return (m, wp.vec3(), I)
|
|
183
183
|
|
|
184
184
|
|
|
185
185
|
def compute_cylinder_inertia(density: float, r: float, h: float) -> tuple:
|
|
@@ -200,9 +200,9 @@ def compute_cylinder_inertia(density: float, r: float, h: float) -> tuple:
|
|
|
200
200
|
Ia = 1 / 12 * m * (3 * r * r + h * h)
|
|
201
201
|
Ib = 1 / 2 * m * r * r
|
|
202
202
|
|
|
203
|
-
I =
|
|
203
|
+
I = wp.mat33([[Ia, 0.0, 0.0], [0.0, Ib, 0.0], [0.0, 0.0, Ia]])
|
|
204
204
|
|
|
205
|
-
return (m,
|
|
205
|
+
return (m, wp.vec3(), I)
|
|
206
206
|
|
|
207
207
|
|
|
208
208
|
def compute_cone_inertia(density: float, r: float, h: float) -> tuple:
|
|
@@ -223,9 +223,9 @@ def compute_cone_inertia(density: float, r: float, h: float) -> tuple:
|
|
|
223
223
|
Ia = 1 / 20 * m * (3 * r * r + 2 * h * h)
|
|
224
224
|
Ib = 3 / 10 * m * r * r
|
|
225
225
|
|
|
226
|
-
I =
|
|
226
|
+
I = wp.mat33([[Ia, 0.0, 0.0], [0.0, Ib, 0.0], [0.0, 0.0, Ia]])
|
|
227
227
|
|
|
228
|
-
return (m,
|
|
228
|
+
return (m, wp.vec3(), I)
|
|
229
229
|
|
|
230
230
|
|
|
231
231
|
def compute_box_inertia(density: float, w: float, h: float, d: float) -> tuple:
|
|
@@ -249,17 +249,16 @@ def compute_box_inertia(density: float, w: float, h: float, d: float) -> tuple:
|
|
|
249
249
|
Ib = 1.0 / 12.0 * m * (w * w + d * d)
|
|
250
250
|
Ic = 1.0 / 12.0 * m * (w * w + h * h)
|
|
251
251
|
|
|
252
|
-
I =
|
|
252
|
+
I = wp.mat33([[Ia, 0.0, 0.0], [0.0, Ib, 0.0], [0.0, 0.0, Ic]])
|
|
253
253
|
|
|
254
|
-
return (m,
|
|
254
|
+
return (m, wp.vec3(), I)
|
|
255
255
|
|
|
256
256
|
|
|
257
257
|
def compute_mesh_inertia(
|
|
258
258
|
density: float, vertices: list, indices: list, is_solid: bool = True, thickness: Union[List[float], float] = 0.001
|
|
259
259
|
) -> tuple:
|
|
260
260
|
"""Computes mass, center of mass, 3x3 inertia matrix, and volume for a mesh."""
|
|
261
|
-
com = np.mean(vertices, 0)
|
|
262
|
-
com_warp = wp.vec3(com[0], com[1], com[2])
|
|
261
|
+
com = wp.vec3(np.mean(vertices, 0))
|
|
263
262
|
|
|
264
263
|
num_tris = len(indices) // 3
|
|
265
264
|
|
|
@@ -279,7 +278,7 @@ def compute_mesh_inertia(
|
|
|
279
278
|
kernel=compute_solid_mesh_inertia,
|
|
280
279
|
dim=num_tris,
|
|
281
280
|
inputs=[
|
|
282
|
-
|
|
281
|
+
com,
|
|
283
282
|
weight,
|
|
284
283
|
wp.array(indices, dtype=int),
|
|
285
284
|
wp.array(vertices, dtype=wp.vec3),
|
|
@@ -294,7 +293,7 @@ def compute_mesh_inertia(
|
|
|
294
293
|
kernel=compute_hollow_mesh_inertia,
|
|
295
294
|
dim=num_tris,
|
|
296
295
|
inputs=[
|
|
297
|
-
|
|
296
|
+
com,
|
|
298
297
|
weight,
|
|
299
298
|
wp.array(indices, dtype=int),
|
|
300
299
|
wp.array(vertices, dtype=wp.vec3),
|
|
@@ -304,14 +303,14 @@ def compute_mesh_inertia(
|
|
|
304
303
|
)
|
|
305
304
|
|
|
306
305
|
# Extract mass and inertia and save to class attributes.
|
|
307
|
-
mass = mass_warp.numpy()[0] * density
|
|
308
|
-
I = I_warp.numpy()[0] * density
|
|
306
|
+
mass = float(mass_warp.numpy()[0] * density)
|
|
307
|
+
I = wp.mat33(*(I_warp.numpy()[0] * density))
|
|
309
308
|
volume = vol_warp.numpy()[0]
|
|
310
309
|
return mass, com, I, volume
|
|
311
310
|
|
|
312
311
|
|
|
313
312
|
def transform_inertia(m, I, p, q):
|
|
314
|
-
R =
|
|
313
|
+
R = wp.quat_to_matrix(q)
|
|
315
314
|
|
|
316
315
|
# Steiner's theorem
|
|
317
|
-
return R @ I @ R
|
|
316
|
+
return R @ I @ wp.transpose(R) + m * (wp.dot(p, p) * wp.mat33(np.eye(3)) - wp.outer(p, p))
|
warp/sim/integrator_euler.py
CHANGED
|
@@ -12,11 +12,10 @@ models + state forward in time.
|
|
|
12
12
|
|
|
13
13
|
import warp as wp
|
|
14
14
|
|
|
15
|
-
from .
|
|
16
|
-
|
|
15
|
+
from .collide import triangle_closest_point_barycentric
|
|
16
|
+
from .model import PARTICLE_FLAG_ACTIVE, ModelShapeGeometry, ModelShapeMaterials
|
|
17
17
|
from .optimizer import Optimizer
|
|
18
18
|
from .particles import eval_particle_forces
|
|
19
|
-
from .collide import triangle_closest_point_barycentric
|
|
20
19
|
from .utils import quat_decompose, quat_twist
|
|
21
20
|
|
|
22
21
|
|
|
@@ -29,6 +28,7 @@ def integrate_particles(
|
|
|
29
28
|
particle_flags: wp.array(dtype=wp.uint32),
|
|
30
29
|
gravity: wp.vec3,
|
|
31
30
|
dt: float,
|
|
31
|
+
v_max: float,
|
|
32
32
|
x_new: wp.array(dtype=wp.vec3),
|
|
33
33
|
v_new: wp.array(dtype=wp.vec3),
|
|
34
34
|
):
|
|
@@ -44,6 +44,10 @@ def integrate_particles(
|
|
|
44
44
|
|
|
45
45
|
# simple semi-implicit Euler. v1 = v0 + a dt, x1 = x0 + v1 dt
|
|
46
46
|
v1 = v0 + (f0 * inv_mass + gravity * wp.step(0.0 - inv_mass)) * dt
|
|
47
|
+
# enforce velocity limit to prevent instability
|
|
48
|
+
v1_mag = wp.length(v1)
|
|
49
|
+
if v1_mag > v_max:
|
|
50
|
+
v1 *= v_max / v1_mag
|
|
47
51
|
x1 = x0 + v1 * dt
|
|
48
52
|
|
|
49
53
|
x_new[tid] = x1
|
|
@@ -837,10 +841,10 @@ def eval_particle_ground_contacts(
|
|
|
837
841
|
def eval_particle_contacts(
|
|
838
842
|
particle_x: wp.array(dtype=wp.vec3),
|
|
839
843
|
particle_v: wp.array(dtype=wp.vec3),
|
|
840
|
-
particle_radius: wp.array(dtype=float),
|
|
841
|
-
particle_flags: wp.array(dtype=wp.uint32),
|
|
842
844
|
body_q: wp.array(dtype=wp.transform),
|
|
843
845
|
body_qd: wp.array(dtype=wp.spatial_vector),
|
|
846
|
+
particle_radius: wp.array(dtype=float),
|
|
847
|
+
particle_flags: wp.array(dtype=wp.uint32),
|
|
844
848
|
body_com: wp.array(dtype=wp.vec3),
|
|
845
849
|
shape_body: wp.array(dtype=int),
|
|
846
850
|
shape_materials: ModelShapeMaterials,
|
|
@@ -1664,10 +1668,10 @@ def compute_forces(model, state, particle_f, body_f, requires_grad):
|
|
|
1664
1668
|
inputs=[
|
|
1665
1669
|
state.particle_q,
|
|
1666
1670
|
state.particle_qd,
|
|
1667
|
-
model.particle_radius,
|
|
1668
|
-
model.particle_flags,
|
|
1669
1671
|
state.body_q,
|
|
1670
1672
|
state.body_qd,
|
|
1673
|
+
model.particle_radius,
|
|
1674
|
+
model.particle_flags,
|
|
1671
1675
|
model.body_com,
|
|
1672
1676
|
model.shape_body,
|
|
1673
1677
|
model.shape_materials,
|
|
@@ -1825,6 +1829,7 @@ class SemiImplicitIntegrator:
|
|
|
1825
1829
|
model.particle_flags,
|
|
1826
1830
|
model.gravity,
|
|
1827
1831
|
dt,
|
|
1832
|
+
model.particle_max_velocity,
|
|
1828
1833
|
],
|
|
1829
1834
|
outputs=[state_out.particle_q, state_out.particle_qd],
|
|
1830
1835
|
device=model.device,
|
|
@@ -1913,6 +1918,7 @@ def init_state(model, state_in, state_out, dt):
|
|
|
1913
1918
|
model.particle_flags,
|
|
1914
1919
|
model.gravity,
|
|
1915
1920
|
dt,
|
|
1921
|
+
model.particle_max_velocity,
|
|
1916
1922
|
],
|
|
1917
1923
|
outputs=[state_out.particle_q, state_out.particle_qd],
|
|
1918
1924
|
device=model.device,
|
|
@@ -1956,7 +1962,7 @@ class VariationalImplicitIntegrator:
|
|
|
1956
1962
|
compute_forces(model, state_out, self.particle_f, None)
|
|
1957
1963
|
compute_residual(model, state_in, state_out, self.particle_f, dfdx, dt)
|
|
1958
1964
|
|
|
1959
|
-
# initialize
|
|
1965
|
+
# initialize output state using the input velocity to create 'predicted state'
|
|
1960
1966
|
init_state(model, state_in, state_out, dt)
|
|
1961
1967
|
|
|
1962
1968
|
# our optimization variable
|