warp-lang 1.9.0__py3-none-win_amd64.whl → 1.10.0rc2__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 +301 -287
- warp/__init__.pyi +2220 -313
- warp/_src/__init__.py +14 -0
- warp/_src/autograd.py +1075 -0
- warp/_src/build.py +618 -0
- warp/_src/build_dll.py +640 -0
- warp/{builtins.py → _src/builtins.py} +1497 -226
- warp/_src/codegen.py +4359 -0
- warp/{config.py → _src/config.py} +178 -169
- warp/_src/constants.py +57 -0
- warp/_src/context.py +8294 -0
- warp/_src/dlpack.py +462 -0
- warp/_src/fabric.py +355 -0
- warp/_src/fem/__init__.py +14 -0
- warp/_src/fem/adaptivity.py +508 -0
- warp/_src/fem/cache.py +687 -0
- warp/_src/fem/dirichlet.py +188 -0
- warp/{fem → _src/fem}/domain.py +40 -30
- warp/_src/fem/field/__init__.py +131 -0
- warp/_src/fem/field/field.py +701 -0
- warp/{fem → _src/fem}/field/nodal_field.py +30 -15
- warp/{fem → _src/fem}/field/restriction.py +1 -1
- warp/{fem → _src/fem}/field/virtual.py +53 -27
- warp/_src/fem/geometry/__init__.py +32 -0
- warp/{fem → _src/fem}/geometry/adaptive_nanogrid.py +77 -163
- warp/_src/fem/geometry/closest_point.py +97 -0
- warp/{fem → _src/fem}/geometry/deformed_geometry.py +14 -22
- warp/{fem → _src/fem}/geometry/element.py +32 -10
- warp/{fem → _src/fem}/geometry/geometry.py +48 -20
- warp/{fem → _src/fem}/geometry/grid_2d.py +12 -23
- warp/{fem → _src/fem}/geometry/grid_3d.py +12 -23
- warp/{fem → _src/fem}/geometry/hexmesh.py +40 -63
- warp/{fem → _src/fem}/geometry/nanogrid.py +255 -248
- warp/{fem → _src/fem}/geometry/partition.py +121 -63
- warp/{fem → _src/fem}/geometry/quadmesh.py +26 -45
- warp/{fem → _src/fem}/geometry/tetmesh.py +40 -63
- warp/{fem → _src/fem}/geometry/trimesh.py +26 -45
- warp/{fem → _src/fem}/integrate.py +164 -158
- warp/_src/fem/linalg.py +383 -0
- warp/_src/fem/operator.py +396 -0
- warp/_src/fem/polynomial.py +229 -0
- warp/{fem → _src/fem}/quadrature/pic_quadrature.py +15 -20
- warp/{fem → _src/fem}/quadrature/quadrature.py +95 -47
- warp/_src/fem/space/__init__.py +248 -0
- warp/{fem → _src/fem}/space/basis_function_space.py +20 -11
- warp/_src/fem/space/basis_space.py +679 -0
- warp/{fem → _src/fem}/space/dof_mapper.py +3 -3
- warp/{fem → _src/fem}/space/function_space.py +14 -13
- warp/{fem → _src/fem}/space/grid_2d_function_space.py +4 -7
- warp/{fem → _src/fem}/space/grid_3d_function_space.py +4 -4
- warp/{fem → _src/fem}/space/hexmesh_function_space.py +4 -10
- warp/{fem → _src/fem}/space/nanogrid_function_space.py +3 -9
- warp/{fem → _src/fem}/space/partition.py +117 -60
- warp/{fem → _src/fem}/space/quadmesh_function_space.py +4 -10
- warp/{fem → _src/fem}/space/restriction.py +66 -33
- warp/_src/fem/space/shape/__init__.py +152 -0
- warp/{fem → _src/fem}/space/shape/cube_shape_function.py +9 -9
- warp/{fem → _src/fem}/space/shape/shape_function.py +8 -9
- warp/{fem → _src/fem}/space/shape/square_shape_function.py +6 -6
- warp/{fem → _src/fem}/space/shape/tet_shape_function.py +3 -3
- warp/{fem → _src/fem}/space/shape/triangle_shape_function.py +3 -3
- warp/{fem → _src/fem}/space/tetmesh_function_space.py +3 -9
- warp/_src/fem/space/topology.py +459 -0
- warp/{fem → _src/fem}/space/trimesh_function_space.py +3 -9
- warp/_src/fem/types.py +112 -0
- warp/_src/fem/utils.py +486 -0
- warp/_src/jax.py +186 -0
- warp/_src/jax_experimental/__init__.py +14 -0
- warp/_src/jax_experimental/custom_call.py +387 -0
- warp/_src/jax_experimental/ffi.py +1284 -0
- warp/_src/jax_experimental/xla_ffi.py +656 -0
- warp/_src/marching_cubes.py +708 -0
- warp/_src/math.py +414 -0
- warp/_src/optim/__init__.py +14 -0
- warp/_src/optim/adam.py +163 -0
- warp/_src/optim/linear.py +1606 -0
- warp/_src/optim/sgd.py +112 -0
- warp/_src/paddle.py +406 -0
- warp/_src/render/__init__.py +14 -0
- warp/_src/render/imgui_manager.py +289 -0
- warp/_src/render/render_opengl.py +3636 -0
- warp/_src/render/render_usd.py +937 -0
- warp/_src/render/utils.py +160 -0
- warp/_src/sparse.py +2716 -0
- warp/_src/tape.py +1206 -0
- warp/{thirdparty → _src/thirdparty}/unittest_parallel.py +9 -2
- warp/_src/torch.py +391 -0
- warp/_src/types.py +5870 -0
- warp/_src/utils.py +1693 -0
- warp/autograd.py +12 -1054
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +8 -588
- warp/build_dll.py +6 -471
- warp/codegen.py +6 -4246
- warp/constants.py +6 -39
- warp/context.py +12 -7851
- warp/dlpack.py +6 -444
- warp/examples/distributed/example_jacobi_mpi.py +4 -5
- warp/examples/fem/example_adaptive_grid.py +1 -1
- warp/examples/fem/example_apic_fluid.py +1 -1
- warp/examples/fem/example_burgers.py +8 -8
- warp/examples/fem/example_diffusion.py +1 -1
- warp/examples/fem/example_distortion_energy.py +1 -1
- warp/examples/fem/example_mixed_elasticity.py +2 -2
- warp/examples/fem/example_navier_stokes.py +1 -1
- warp/examples/fem/example_nonconforming_contact.py +7 -7
- warp/examples/fem/example_stokes.py +1 -1
- warp/examples/fem/example_stokes_transfer.py +1 -1
- warp/examples/fem/utils.py +2 -2
- warp/examples/interop/example_jax_callable.py +1 -1
- warp/examples/interop/example_jax_ffi_callback.py +1 -1
- warp/examples/interop/example_jax_kernel.py +3 -2
- warp/examples/tile/example_tile_mcgp.py +191 -0
- warp/fabric.py +6 -337
- warp/fem/__init__.py +159 -97
- warp/fem/adaptivity.py +7 -489
- warp/fem/cache.py +9 -648
- warp/fem/dirichlet.py +6 -184
- warp/fem/field/__init__.py +8 -109
- warp/fem/field/field.py +7 -652
- warp/fem/geometry/__init__.py +7 -18
- warp/fem/geometry/closest_point.py +11 -77
- warp/fem/linalg.py +18 -366
- warp/fem/operator.py +11 -369
- warp/fem/polynomial.py +9 -209
- warp/fem/space/__init__.py +5 -211
- warp/fem/space/basis_space.py +6 -662
- warp/fem/space/shape/__init__.py +41 -118
- warp/fem/space/topology.py +6 -437
- warp/fem/types.py +6 -81
- warp/fem/utils.py +11 -444
- warp/jax.py +8 -165
- warp/jax_experimental/__init__.py +14 -1
- warp/jax_experimental/custom_call.py +8 -342
- warp/jax_experimental/ffi.py +17 -853
- warp/jax_experimental/xla_ffi.py +5 -596
- warp/marching_cubes.py +5 -689
- warp/math.py +16 -393
- warp/native/array.h +385 -37
- warp/native/builtin.h +316 -39
- warp/native/bvh.cpp +43 -9
- warp/native/bvh.cu +62 -27
- warp/native/bvh.h +310 -309
- warp/native/clang/clang.cpp +102 -97
- warp/native/coloring.cpp +0 -1
- warp/native/crt.h +208 -0
- warp/native/exports.h +156 -0
- warp/native/hashgrid.cu +2 -0
- warp/native/intersect.h +24 -1
- warp/native/intersect_tri.h +44 -35
- warp/native/mat.h +1456 -276
- warp/native/mesh.cpp +4 -4
- warp/native/mesh.cu +4 -2
- warp/native/mesh.h +176 -61
- warp/native/quat.h +0 -52
- warp/native/scan.cu +2 -0
- warp/native/sort.cu +22 -13
- warp/native/sort.h +2 -0
- warp/native/sparse.cu +7 -3
- warp/native/spatial.h +12 -0
- warp/native/tile.h +837 -70
- warp/native/tile_radix_sort.h +1 -1
- warp/native/tile_reduce.h +394 -46
- warp/native/tile_scan.h +4 -4
- warp/native/vec.h +469 -53
- warp/native/version.h +23 -0
- warp/native/volume.cpp +1 -1
- warp/native/volume.cu +1 -0
- warp/native/volume.h +1 -1
- warp/native/volume_builder.cu +2 -0
- warp/native/warp.cpp +60 -32
- warp/native/warp.cu +313 -201
- warp/native/warp.h +14 -11
- warp/optim/__init__.py +6 -3
- warp/optim/adam.py +6 -145
- warp/optim/linear.py +14 -1585
- warp/optim/sgd.py +6 -94
- warp/paddle.py +6 -388
- warp/render/__init__.py +8 -4
- warp/render/imgui_manager.py +7 -267
- warp/render/render_opengl.py +6 -3616
- warp/render/render_usd.py +6 -918
- warp/render/utils.py +6 -142
- warp/sparse.py +37 -2563
- warp/tape.py +6 -1188
- warp/tests/__main__.py +1 -1
- warp/tests/cuda/test_async.py +4 -4
- warp/tests/cuda/test_conditional_captures.py +1 -1
- warp/tests/cuda/test_multigpu.py +1 -1
- warp/tests/cuda/test_streams.py +58 -1
- warp/tests/geometry/test_bvh.py +157 -22
- warp/tests/geometry/test_hash_grid.py +38 -0
- warp/tests/geometry/test_marching_cubes.py +0 -1
- warp/tests/geometry/test_mesh.py +5 -3
- warp/tests/geometry/test_mesh_query_aabb.py +5 -12
- warp/tests/geometry/test_mesh_query_point.py +5 -2
- warp/tests/geometry/test_mesh_query_ray.py +15 -3
- warp/tests/geometry/test_volume_write.py +5 -5
- warp/tests/interop/test_dlpack.py +14 -14
- warp/tests/interop/test_jax.py +1382 -79
- warp/tests/interop/test_paddle.py +1 -1
- warp/tests/test_adam.py +0 -1
- warp/tests/test_arithmetic.py +9 -9
- warp/tests/test_array.py +529 -100
- warp/tests/test_array_reduce.py +3 -3
- warp/tests/test_atomic.py +12 -8
- warp/tests/test_atomic_bitwise.py +209 -0
- warp/tests/test_atomic_cas.py +4 -4
- warp/tests/test_bool.py +2 -2
- warp/tests/test_builtins_resolution.py +5 -571
- warp/tests/test_codegen.py +34 -15
- warp/tests/test_conditional.py +1 -1
- warp/tests/test_context.py +6 -6
- warp/tests/test_copy.py +242 -161
- warp/tests/test_ctypes.py +3 -3
- warp/tests/test_devices.py +24 -2
- warp/tests/test_examples.py +16 -84
- warp/tests/test_fabricarray.py +35 -35
- warp/tests/test_fast_math.py +0 -2
- warp/tests/test_fem.py +60 -14
- warp/tests/test_fixedarray.py +3 -3
- warp/tests/test_func.py +8 -5
- warp/tests/test_generics.py +1 -1
- warp/tests/test_indexedarray.py +24 -24
- warp/tests/test_intersect.py +39 -9
- warp/tests/test_large.py +1 -1
- warp/tests/test_lerp.py +3 -1
- warp/tests/test_linear_solvers.py +1 -1
- warp/tests/test_map.py +49 -4
- warp/tests/test_mat.py +52 -62
- warp/tests/test_mat_constructors.py +4 -5
- warp/tests/test_mat_lite.py +1 -1
- warp/tests/test_mat_scalar_ops.py +121 -121
- warp/tests/test_math.py +34 -0
- warp/tests/test_module_aot.py +4 -4
- warp/tests/test_modules_lite.py +28 -2
- warp/tests/test_print.py +11 -11
- warp/tests/test_quat.py +93 -58
- warp/tests/test_runlength_encode.py +1 -1
- warp/tests/test_scalar_ops.py +38 -10
- warp/tests/test_smoothstep.py +1 -1
- warp/tests/test_sparse.py +126 -15
- warp/tests/test_spatial.py +105 -87
- warp/tests/test_special_values.py +6 -6
- warp/tests/test_static.py +7 -7
- warp/tests/test_struct.py +13 -2
- warp/tests/test_triangle_closest_point.py +48 -1
- warp/tests/test_tuple.py +96 -0
- warp/tests/test_types.py +82 -9
- warp/tests/test_utils.py +52 -52
- warp/tests/test_vec.py +29 -29
- warp/tests/test_vec_constructors.py +5 -5
- warp/tests/test_vec_scalar_ops.py +97 -97
- warp/tests/test_version.py +75 -0
- warp/tests/tile/test_tile.py +239 -0
- warp/tests/tile/test_tile_atomic_bitwise.py +403 -0
- warp/tests/tile/test_tile_cholesky.py +7 -4
- warp/tests/tile/test_tile_load.py +26 -2
- warp/tests/tile/test_tile_mathdx.py +3 -3
- warp/tests/tile/test_tile_matmul.py +1 -1
- warp/tests/tile/test_tile_mlp.py +2 -4
- warp/tests/tile/test_tile_reduce.py +214 -13
- warp/tests/unittest_suites.py +6 -14
- warp/tests/unittest_utils.py +10 -9
- warp/tests/walkthrough_debug.py +3 -1
- warp/torch.py +6 -373
- warp/types.py +29 -5750
- warp/utils.py +10 -1659
- {warp_lang-1.9.0.dist-info → warp_lang-1.10.0rc2.dist-info}/METADATA +47 -103
- warp_lang-1.10.0rc2.dist-info/RECORD +468 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/Gaia-LICENSE.txt +6 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/appdirs-LICENSE.txt +22 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/asset_pixel_jpg-LICENSE.txt +3 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/cuda-LICENSE.txt +1582 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/dlpack-LICENSE.txt +201 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/fp16-LICENSE.txt +28 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/libmathdx-LICENSE.txt +220 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/llvm-LICENSE.txt +279 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/moller-LICENSE.txt +16 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/nanovdb-LICENSE.txt +2 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/nvrtc-LICENSE.txt +1592 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/svd-LICENSE.txt +23 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/unittest_parallel-LICENSE.txt +21 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/usd-LICENSE.txt +213 -0
- warp_lang-1.10.0rc2.dist-info/licenses/licenses/windingnumber-LICENSE.txt +21 -0
- warp/examples/assets/cartpole.urdf +0 -110
- warp/examples/assets/crazyflie.usd +0 -0
- warp/examples/assets/nv_ant.xml +0 -92
- warp/examples/assets/nv_humanoid.xml +0 -183
- warp/examples/assets/quadruped.urdf +0 -268
- warp/examples/optim/example_bounce.py +0 -266
- warp/examples/optim/example_cloth_throw.py +0 -228
- warp/examples/optim/example_drone.py +0 -870
- warp/examples/optim/example_inverse_kinematics.py +0 -182
- warp/examples/optim/example_inverse_kinematics_torch.py +0 -191
- warp/examples/optim/example_softbody_properties.py +0 -400
- warp/examples/optim/example_spring_cage.py +0 -245
- warp/examples/optim/example_trajectory.py +0 -227
- warp/examples/sim/example_cartpole.py +0 -143
- warp/examples/sim/example_cloth.py +0 -225
- warp/examples/sim/example_cloth_self_contact.py +0 -316
- warp/examples/sim/example_granular.py +0 -130
- warp/examples/sim/example_granular_collision_sdf.py +0 -202
- warp/examples/sim/example_jacobian_ik.py +0 -244
- warp/examples/sim/example_particle_chain.py +0 -124
- warp/examples/sim/example_quadruped.py +0 -203
- warp/examples/sim/example_rigid_chain.py +0 -203
- warp/examples/sim/example_rigid_contact.py +0 -195
- warp/examples/sim/example_rigid_force.py +0 -133
- warp/examples/sim/example_rigid_gyroscopic.py +0 -115
- warp/examples/sim/example_rigid_soft_contact.py +0 -140
- warp/examples/sim/example_soft_body.py +0 -196
- warp/examples/tile/example_tile_walker.py +0 -327
- warp/sim/__init__.py +0 -74
- warp/sim/articulation.py +0 -793
- warp/sim/collide.py +0 -2570
- warp/sim/graph_coloring.py +0 -307
- warp/sim/import_mjcf.py +0 -791
- warp/sim/import_snu.py +0 -227
- warp/sim/import_urdf.py +0 -579
- warp/sim/import_usd.py +0 -898
- warp/sim/inertia.py +0 -357
- warp/sim/integrator.py +0 -245
- warp/sim/integrator_euler.py +0 -2000
- warp/sim/integrator_featherstone.py +0 -2101
- warp/sim/integrator_vbd.py +0 -2487
- warp/sim/integrator_xpbd.py +0 -3295
- warp/sim/model.py +0 -4821
- warp/sim/particles.py +0 -121
- warp/sim/render.py +0 -431
- warp/sim/utils.py +0 -431
- warp/tests/sim/disabled_kinematics.py +0 -244
- warp/tests/sim/test_cloth.py +0 -863
- warp/tests/sim/test_collision.py +0 -743
- warp/tests/sim/test_coloring.py +0 -347
- warp/tests/sim/test_inertia.py +0 -161
- warp/tests/sim/test_model.py +0 -226
- warp/tests/sim/test_sim_grad.py +0 -287
- warp/tests/sim/test_sim_grad_bounce_linear.py +0 -212
- warp/tests/sim/test_sim_kinematics.py +0 -98
- warp/thirdparty/__init__.py +0 -0
- warp_lang-1.9.0.dist-info/RECORD +0 -456
- /warp/{fem → _src/fem}/quadrature/__init__.py +0 -0
- /warp/{tests/sim → _src/thirdparty}/__init__.py +0 -0
- /warp/{thirdparty → _src/thirdparty}/appdirs.py +0 -0
- /warp/{thirdparty → _src/thirdparty}/dlpack.py +0 -0
- {warp_lang-1.9.0.dist-info → warp_lang-1.10.0rc2.dist-info}/WHEEL +0 -0
- {warp_lang-1.9.0.dist-info → warp_lang-1.10.0rc2.dist-info}/licenses/LICENSE.md +0 -0
- {warp_lang-1.9.0.dist-info → warp_lang-1.10.0rc2.dist-info}/top_level.txt +0 -0
warp/sim/utils.py
DELETED
|
@@ -1,431 +0,0 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
#
|
|
4
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
# you may not use this file except in compliance with the License.
|
|
6
|
-
# You may obtain a copy of the License at
|
|
7
|
-
#
|
|
8
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
#
|
|
10
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
# See the License for the specific language governing permissions and
|
|
14
|
-
# limitations under the License.
|
|
15
|
-
|
|
16
|
-
from __future__ import annotations
|
|
17
|
-
|
|
18
|
-
import numpy as np
|
|
19
|
-
|
|
20
|
-
import warp as wp
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@wp.func
|
|
24
|
-
def velocity_at_point(qd: wp.spatial_vector, r: wp.vec3):
|
|
25
|
-
"""
|
|
26
|
-
Returns the velocity of a point relative to the frame with the given spatial velocity.
|
|
27
|
-
|
|
28
|
-
Args:
|
|
29
|
-
qd (spatial_vector): The spatial velocity of the frame.
|
|
30
|
-
r (vec3): The position of the point relative to the frame.
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
vec3: The velocity of the point.
|
|
34
|
-
"""
|
|
35
|
-
return wp.cross(wp.spatial_top(qd), r) + wp.spatial_bottom(qd)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
@wp.func
|
|
39
|
-
def quat_twist(axis: wp.vec3, q: wp.quat):
|
|
40
|
-
"""
|
|
41
|
-
Returns the twist around an axis.
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
# project imaginary part onto axis
|
|
45
|
-
a = wp.vec3(q[0], q[1], q[2])
|
|
46
|
-
proj = wp.dot(a, axis)
|
|
47
|
-
a = proj * axis
|
|
48
|
-
# if proj < 0.0:
|
|
49
|
-
# # ensure twist points in same direction as axis
|
|
50
|
-
# a = -a
|
|
51
|
-
return wp.normalize(wp.quat(a[0], a[1], a[2], q[3]))
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
@wp.func
|
|
55
|
-
def quat_twist_angle(axis: wp.vec3, q: wp.quat):
|
|
56
|
-
"""
|
|
57
|
-
Returns the angle of the twist around an axis.
|
|
58
|
-
"""
|
|
59
|
-
return 2.0 * wp.acos(quat_twist(axis, q)[3])
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
@wp.func
|
|
63
|
-
def quat_decompose(q: wp.quat):
|
|
64
|
-
"""
|
|
65
|
-
Decompose a quaternion into a sequence of 3 rotations around x,y',z' respectively, i.e.: q = q_z''q_y'q_x.
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
R = wp.matrix_from_cols(
|
|
69
|
-
wp.quat_rotate(q, wp.vec3(1.0, 0.0, 0.0)),
|
|
70
|
-
wp.quat_rotate(q, wp.vec3(0.0, 1.0, 0.0)),
|
|
71
|
-
wp.quat_rotate(q, wp.vec3(0.0, 0.0, 1.0)),
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
# https://www.sedris.org/wg8home/Documents/WG80485.pdf
|
|
75
|
-
phi = wp.atan2(R[1, 2], R[2, 2])
|
|
76
|
-
sinp = -R[0, 2]
|
|
77
|
-
if wp.abs(sinp) >= 1.0:
|
|
78
|
-
theta = wp.HALF_PI * wp.sign(sinp)
|
|
79
|
-
else:
|
|
80
|
-
theta = wp.asin(-R[0, 2])
|
|
81
|
-
psi = wp.atan2(R[0, 1], R[0, 0])
|
|
82
|
-
|
|
83
|
-
return -wp.vec3(phi, theta, psi)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@wp.func
|
|
87
|
-
def quat_to_rpy(q: wp.quat):
|
|
88
|
-
"""
|
|
89
|
-
Convert a quaternion into Euler angles (roll, pitch, yaw)
|
|
90
|
-
roll is rotation around x in radians (counterclockwise)
|
|
91
|
-
pitch is rotation around y in radians (counterclockwise)
|
|
92
|
-
yaw is rotation around z in radians (counterclockwise)
|
|
93
|
-
"""
|
|
94
|
-
x = q[0]
|
|
95
|
-
y = q[1]
|
|
96
|
-
z = q[2]
|
|
97
|
-
w = q[3]
|
|
98
|
-
t0 = 2.0 * (w * x + y * z)
|
|
99
|
-
t1 = 1.0 - 2.0 * (x * x + y * y)
|
|
100
|
-
roll_x = wp.atan2(t0, t1)
|
|
101
|
-
|
|
102
|
-
t2 = 2.0 * (w * y - z * x)
|
|
103
|
-
t2 = wp.clamp(t2, -1.0, 1.0)
|
|
104
|
-
pitch_y = wp.asin(t2)
|
|
105
|
-
|
|
106
|
-
t3 = 2.0 * (w * z + x * y)
|
|
107
|
-
t4 = 1.0 - 2.0 * (y * y + z * z)
|
|
108
|
-
yaw_z = wp.atan2(t3, t4)
|
|
109
|
-
|
|
110
|
-
return wp.vec3(roll_x, pitch_y, yaw_z)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
@wp.func
|
|
114
|
-
def quat_to_euler(q: wp.quat, i: int, j: int, k: int) -> wp.vec3:
|
|
115
|
-
"""
|
|
116
|
-
Convert a quaternion into Euler angles.
|
|
117
|
-
|
|
118
|
-
:math:`i, j, k` are the indices in :math:`[0, 1, 2]` of the axes to use
|
|
119
|
-
(:math:`i \\neq j, j \\neq k`).
|
|
120
|
-
|
|
121
|
-
Reference: https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0276302
|
|
122
|
-
|
|
123
|
-
Args:
|
|
124
|
-
q (quat): The quaternion to convert
|
|
125
|
-
i (int): The index of the first axis
|
|
126
|
-
j (int): The index of the second axis
|
|
127
|
-
k (int): The index of the third axis
|
|
128
|
-
|
|
129
|
-
Returns:
|
|
130
|
-
vec3: The Euler angles (in radians)
|
|
131
|
-
"""
|
|
132
|
-
# i, j, k are actually assumed to follow 1-based indexing but
|
|
133
|
-
# we want to be compatible with quat_from_euler
|
|
134
|
-
i += 1
|
|
135
|
-
j += 1
|
|
136
|
-
k += 1
|
|
137
|
-
not_proper = True
|
|
138
|
-
if i == k:
|
|
139
|
-
not_proper = False
|
|
140
|
-
k = 6 - i - j # because i + j + k = 1 + 2 + 3 = 6
|
|
141
|
-
e = float((i - j) * (j - k) * (k - i)) / 2.0 # Levi-Civita symbol
|
|
142
|
-
a = q[0]
|
|
143
|
-
b = q[i]
|
|
144
|
-
c = q[j]
|
|
145
|
-
d = q[k] * e
|
|
146
|
-
if not_proper:
|
|
147
|
-
a -= q[j]
|
|
148
|
-
b += q[k] * e
|
|
149
|
-
c += q[0]
|
|
150
|
-
d -= q[i]
|
|
151
|
-
t2 = wp.acos(2.0 * (a * a + b * b) / (a * a + b * b + c * c + d * d) - 1.0)
|
|
152
|
-
tp = wp.atan2(b, a)
|
|
153
|
-
tm = wp.atan2(d, c)
|
|
154
|
-
t1 = 0.0
|
|
155
|
-
t3 = 0.0
|
|
156
|
-
if wp.abs(t2) < 1e-6:
|
|
157
|
-
t3 = 2.0 * tp - t1
|
|
158
|
-
elif wp.abs(t2 - wp.HALF_PI) < 1e-6:
|
|
159
|
-
t3 = 2.0 * tm + t1
|
|
160
|
-
else:
|
|
161
|
-
t1 = tp - tm
|
|
162
|
-
t3 = tp + tm
|
|
163
|
-
if not_proper:
|
|
164
|
-
t2 -= wp.HALF_PI
|
|
165
|
-
t3 *= e
|
|
166
|
-
return wp.vec3(t1, t2, t3)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
@wp.func
|
|
170
|
-
def quat_from_euler(e: wp.vec3, i: int, j: int, k: int) -> wp.quat:
|
|
171
|
-
"""
|
|
172
|
-
Convert Euler angles to a quaternion.
|
|
173
|
-
|
|
174
|
-
:math:`i, j, k` are the indices in :math:`[0, 1, 2]` of the axes in which the Euler angles are provided
|
|
175
|
-
(:math:`i \\neq j, j \\neq k`), e.g. (0, 1, 2) for Euler sequence XYZ.
|
|
176
|
-
|
|
177
|
-
Args:
|
|
178
|
-
e (vec3): The Euler angles (in radians)
|
|
179
|
-
i (int): The index of the first axis
|
|
180
|
-
j (int): The index of the second axis
|
|
181
|
-
k (int): The index of the third axis
|
|
182
|
-
|
|
183
|
-
Returns:
|
|
184
|
-
quat: The quaternion
|
|
185
|
-
"""
|
|
186
|
-
# Half angles
|
|
187
|
-
half_e = e / 2.0
|
|
188
|
-
|
|
189
|
-
# Precompute sines and cosines of half angles
|
|
190
|
-
cr = wp.cos(half_e[i])
|
|
191
|
-
sr = wp.sin(half_e[i])
|
|
192
|
-
cp = wp.cos(half_e[j])
|
|
193
|
-
sp = wp.sin(half_e[j])
|
|
194
|
-
cy = wp.cos(half_e[k])
|
|
195
|
-
sy = wp.sin(half_e[k])
|
|
196
|
-
|
|
197
|
-
# Components of the quaternion based on the rotation sequence
|
|
198
|
-
return wp.quat(
|
|
199
|
-
(cy * sr * cp - sy * cr * sp),
|
|
200
|
-
(cy * cr * sp + sy * sr * cp),
|
|
201
|
-
(sy * cr * cp - cy * sr * sp),
|
|
202
|
-
(cy * cr * cp + sy * sr * sp),
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
@wp.func
|
|
207
|
-
def transform_twist(t: wp.transform, x: wp.spatial_vector):
|
|
208
|
-
# Frank & Park definition 3.20, pg 100
|
|
209
|
-
|
|
210
|
-
q = wp.transform_get_rotation(t)
|
|
211
|
-
p = wp.transform_get_translation(t)
|
|
212
|
-
|
|
213
|
-
w = wp.spatial_top(x)
|
|
214
|
-
v = wp.spatial_bottom(x)
|
|
215
|
-
|
|
216
|
-
w = wp.quat_rotate(q, w)
|
|
217
|
-
v = wp.quat_rotate(q, v) + wp.cross(p, w)
|
|
218
|
-
|
|
219
|
-
return wp.spatial_vector(w, v)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
@wp.func
|
|
223
|
-
def transform_wrench(t: wp.transform, x: wp.spatial_vector):
|
|
224
|
-
q = wp.transform_get_rotation(t)
|
|
225
|
-
p = wp.transform_get_translation(t)
|
|
226
|
-
|
|
227
|
-
w = wp.spatial_top(x)
|
|
228
|
-
v = wp.spatial_bottom(x)
|
|
229
|
-
|
|
230
|
-
v = wp.quat_rotate(q, v)
|
|
231
|
-
w = wp.quat_rotate(q, w) + wp.cross(p, v)
|
|
232
|
-
|
|
233
|
-
return wp.spatial_vector(w, v)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
@wp.func
|
|
237
|
-
def transform_inertia(t: wp.transform, I: wp.spatial_matrix):
|
|
238
|
-
"""
|
|
239
|
-
Computes adj_t^-T*I*adj_t^-1 (tensor change of coordinates).
|
|
240
|
-
(Frank & Park, section 8.2.3, pg 290)
|
|
241
|
-
"""
|
|
242
|
-
|
|
243
|
-
t_inv = wp.transform_inverse(t)
|
|
244
|
-
|
|
245
|
-
q = wp.transform_get_rotation(t_inv)
|
|
246
|
-
p = wp.transform_get_translation(t_inv)
|
|
247
|
-
|
|
248
|
-
r1 = wp.quat_rotate(q, wp.vec3(1.0, 0.0, 0.0))
|
|
249
|
-
r2 = wp.quat_rotate(q, wp.vec3(0.0, 1.0, 0.0))
|
|
250
|
-
r3 = wp.quat_rotate(q, wp.vec3(0.0, 0.0, 1.0))
|
|
251
|
-
|
|
252
|
-
R = wp.matrix_from_cols(r1, r2, r3)
|
|
253
|
-
S = wp.mul(wp.skew(p), R)
|
|
254
|
-
|
|
255
|
-
T = wp.spatial_adjoint(R, S)
|
|
256
|
-
|
|
257
|
-
return wp.mul(wp.mul(wp.transpose(T), I), T)
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
@wp.func
|
|
261
|
-
def boltzmann(a: float, b: float, alpha: float):
|
|
262
|
-
e1 = wp.exp(alpha * a)
|
|
263
|
-
e2 = wp.exp(alpha * b)
|
|
264
|
-
return (a * e1 + b * e2) / (e1 + e2)
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
@wp.func
|
|
268
|
-
def smooth_max(a: float, b: float, eps: float):
|
|
269
|
-
d = a - b
|
|
270
|
-
return 0.5 * (a + b + wp.sqrt(d * d + eps))
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
@wp.func
|
|
274
|
-
def smooth_min(a: float, b: float, eps: float):
|
|
275
|
-
d = a - b
|
|
276
|
-
return 0.5 * (a + b - wp.sqrt(d * d + eps))
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
@wp.func
|
|
280
|
-
def leaky_max(a: float, b: float):
|
|
281
|
-
return smooth_max(a, b, 1e-5)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
@wp.func
|
|
285
|
-
def leaky_min(a: float, b: float):
|
|
286
|
-
return smooth_min(a, b, 1e-5)
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
@wp.func
|
|
290
|
-
def vec_min(a: wp.vec3, b: wp.vec3):
|
|
291
|
-
return wp.vec3(wp.min(a[0], b[0]), wp.min(a[1], b[1]), wp.min(a[2], b[2]))
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
@wp.func
|
|
295
|
-
def vec_max(a: wp.vec3, b: wp.vec3):
|
|
296
|
-
return wp.vec3(wp.max(a[0], b[0]), wp.max(a[1], b[1]), wp.max(a[2], b[2]))
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
@wp.func
|
|
300
|
-
def vec_leaky_min(a: wp.vec3, b: wp.vec3):
|
|
301
|
-
return wp.vec3(leaky_min(a[0], b[0]), leaky_min(a[1], b[1]), leaky_min(a[2], b[2]))
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
@wp.func
|
|
305
|
-
def vec_leaky_max(a: wp.vec3, b: wp.vec3):
|
|
306
|
-
return wp.vec3(leaky_max(a[0], b[0]), leaky_max(a[1], b[1]), leaky_max(a[2], b[2]))
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
@wp.func
|
|
310
|
-
def vec_abs(a: wp.vec3):
|
|
311
|
-
return wp.vec3(wp.abs(a[0]), wp.abs(a[1]), wp.abs(a[2]))
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
def load_mesh(filename: str, method: str | None = None):
|
|
315
|
-
"""Load a 3D triangular surface mesh from a file.
|
|
316
|
-
|
|
317
|
-
Args:
|
|
318
|
-
filename (str): The path to the 3D model file (obj, and other formats
|
|
319
|
-
supported by the different methods) to load.
|
|
320
|
-
method (str): The method to use for loading the mesh (default ``None``).
|
|
321
|
-
Can be either ``"trimesh"``, ``"meshio"``, ``"pcu"``, or ``"openmesh"``.
|
|
322
|
-
If ``None``, every method is tried and the first successful mesh import
|
|
323
|
-
where the number of vertices is greater than 0 is returned.
|
|
324
|
-
|
|
325
|
-
Returns:
|
|
326
|
-
Tuple of (mesh_points, mesh_indices), where mesh_points is a Nx3 numpy array of vertex positions (float32),
|
|
327
|
-
and mesh_indices is a Mx3 numpy array of vertex indices (int32) for the triangular faces.
|
|
328
|
-
"""
|
|
329
|
-
import os
|
|
330
|
-
|
|
331
|
-
if not os.path.exists(filename):
|
|
332
|
-
raise FileNotFoundError(f"File not found: {filename}")
|
|
333
|
-
|
|
334
|
-
def load_mesh_with_method(method):
|
|
335
|
-
if method == "meshio":
|
|
336
|
-
import meshio
|
|
337
|
-
|
|
338
|
-
m = meshio.read(filename)
|
|
339
|
-
mesh_points = np.array(m.points)
|
|
340
|
-
mesh_indices = np.array(m.cells[0].data, dtype=np.int32)
|
|
341
|
-
elif method == "openmesh":
|
|
342
|
-
import openmesh
|
|
343
|
-
|
|
344
|
-
m = openmesh.read_trimesh(filename)
|
|
345
|
-
mesh_points = np.array(m.points())
|
|
346
|
-
mesh_indices = np.array(m.face_vertex_indices(), dtype=np.int32)
|
|
347
|
-
elif method == "pcu":
|
|
348
|
-
import point_cloud_utils as pcu
|
|
349
|
-
|
|
350
|
-
mesh_points, mesh_indices = pcu.load_mesh_vf(filename)
|
|
351
|
-
mesh_indices = mesh_indices.flatten()
|
|
352
|
-
else:
|
|
353
|
-
import trimesh
|
|
354
|
-
|
|
355
|
-
m = trimesh.load(filename)
|
|
356
|
-
if hasattr(m, "geometry"):
|
|
357
|
-
# multiple meshes are contained in a scene; combine to one mesh
|
|
358
|
-
mesh_points = []
|
|
359
|
-
mesh_indices = []
|
|
360
|
-
index_offset = 0
|
|
361
|
-
for geom in m.geometry.values():
|
|
362
|
-
vertices = np.array(geom.vertices, dtype=np.float32)
|
|
363
|
-
faces = np.array(geom.faces.flatten(), dtype=np.int32)
|
|
364
|
-
mesh_points.append(vertices)
|
|
365
|
-
mesh_indices.append(faces + index_offset)
|
|
366
|
-
index_offset += len(vertices)
|
|
367
|
-
mesh_points = np.concatenate(mesh_points, axis=0)
|
|
368
|
-
mesh_indices = np.concatenate(mesh_indices)
|
|
369
|
-
else:
|
|
370
|
-
# a single mesh
|
|
371
|
-
mesh_points = np.array(m.vertices, dtype=np.float32)
|
|
372
|
-
mesh_indices = np.array(m.faces.flatten(), dtype=np.int32)
|
|
373
|
-
return mesh_points, mesh_indices
|
|
374
|
-
|
|
375
|
-
if method is None:
|
|
376
|
-
methods = ["trimesh", "meshio", "pcu", "openmesh"]
|
|
377
|
-
for method in methods:
|
|
378
|
-
try:
|
|
379
|
-
mesh = load_mesh_with_method(method)
|
|
380
|
-
if mesh is not None and len(mesh[0]) > 0:
|
|
381
|
-
return mesh
|
|
382
|
-
except Exception:
|
|
383
|
-
pass
|
|
384
|
-
raise ValueError(f"Failed to load mesh using any of the methods: {methods}")
|
|
385
|
-
else:
|
|
386
|
-
mesh = load_mesh_with_method(method)
|
|
387
|
-
if mesh is None or len(mesh[0]) == 0:
|
|
388
|
-
raise ValueError(f"Failed to load mesh using method {method}")
|
|
389
|
-
return mesh
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
def visualize_meshes(
|
|
393
|
-
meshes: list[tuple[list, list]], num_cols=0, num_rows=0, titles=None, scale_axes=True, show_plot=True
|
|
394
|
-
):
|
|
395
|
-
# render meshes in a grid with matplotlib
|
|
396
|
-
import matplotlib.pyplot as plt
|
|
397
|
-
|
|
398
|
-
if titles is None:
|
|
399
|
-
titles = []
|
|
400
|
-
|
|
401
|
-
num_cols = min(num_cols, len(meshes))
|
|
402
|
-
num_rows = min(num_rows, len(meshes))
|
|
403
|
-
if num_cols and not num_rows:
|
|
404
|
-
num_rows = int(np.ceil(len(meshes) / num_cols))
|
|
405
|
-
elif num_rows and not num_cols:
|
|
406
|
-
num_cols = int(np.ceil(len(meshes) / num_rows))
|
|
407
|
-
else:
|
|
408
|
-
num_cols = len(meshes)
|
|
409
|
-
num_rows = 1
|
|
410
|
-
|
|
411
|
-
vertices = [np.array(v).reshape((-1, 3)) for v, _ in meshes]
|
|
412
|
-
faces = [np.array(f, dtype=np.int32).reshape((-1, 3)) for _, f in meshes]
|
|
413
|
-
if scale_axes:
|
|
414
|
-
ranges = np.array([v.max(axis=0) - v.min(axis=0) for v in vertices])
|
|
415
|
-
max_range = ranges.max()
|
|
416
|
-
mid_points = np.array([v.max(axis=0) + v.min(axis=0) for v in vertices]) * 0.5
|
|
417
|
-
|
|
418
|
-
fig = plt.figure(figsize=(12, 6))
|
|
419
|
-
for i, (vertices, faces) in enumerate(meshes):
|
|
420
|
-
ax = fig.add_subplot(num_rows, num_cols, i + 1, projection="3d")
|
|
421
|
-
if i < len(titles):
|
|
422
|
-
ax.set_title(titles[i])
|
|
423
|
-
ax.plot_trisurf(vertices[:, 0], vertices[:, 1], vertices[:, 2], triangles=faces, edgecolor="k")
|
|
424
|
-
if scale_axes:
|
|
425
|
-
mid = mid_points[i]
|
|
426
|
-
ax.set_xlim(mid[0] - max_range, mid[0] + max_range)
|
|
427
|
-
ax.set_ylim(mid[1] - max_range, mid[1] + max_range)
|
|
428
|
-
ax.set_zlim(mid[2] - max_range, mid[2] + max_range)
|
|
429
|
-
if show_plot:
|
|
430
|
-
plt.show()
|
|
431
|
-
return fig
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
#
|
|
4
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
# you may not use this file except in compliance with the License.
|
|
6
|
-
# You may obtain a copy of the License at
|
|
7
|
-
#
|
|
8
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
#
|
|
10
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
# See the License for the specific language governing permissions and
|
|
14
|
-
# limitations under the License.
|
|
15
|
-
|
|
16
|
-
import math
|
|
17
|
-
import unittest
|
|
18
|
-
|
|
19
|
-
import warp as wp
|
|
20
|
-
import warp.examples
|
|
21
|
-
import warp.sim
|
|
22
|
-
from warp.tests.unittest_utils import *
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def build_ant(num_envs):
|
|
26
|
-
builder = wp.sim.ModelBuilder()
|
|
27
|
-
for i in range(num_envs):
|
|
28
|
-
wp.sim.parse_mjcf(os.path.join(warp.examples.get_asset_directory(), "nv_ant.xml"), builder, up_axis="y")
|
|
29
|
-
|
|
30
|
-
coord_count = 15
|
|
31
|
-
dof_count = 14
|
|
32
|
-
|
|
33
|
-
coord_start = i * coord_count
|
|
34
|
-
dof_start = i * dof_count
|
|
35
|
-
|
|
36
|
-
# base
|
|
37
|
-
p = [i * 2.0, 0.70, 0.0]
|
|
38
|
-
q = wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), -math.pi * 0.5)
|
|
39
|
-
builder.joint_q[coord_start : coord_start + 3] = p
|
|
40
|
-
builder.joint_q[coord_start + 3 : coord_start + 7] = q
|
|
41
|
-
|
|
42
|
-
# joints
|
|
43
|
-
builder.joint_q[coord_start + 7 : coord_start + coord_count] = [0.0, 1.0, 0.0, -1.0, 0.0, -1.0, 0.0, 1.0]
|
|
44
|
-
builder.joint_qd[dof_start + 6 : dof_start + dof_count] = [1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0]
|
|
45
|
-
|
|
46
|
-
return builder
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def build_complex_joint_mechanism(chain_length):
|
|
50
|
-
builder = wp.sim.ModelBuilder()
|
|
51
|
-
com0 = wp.vec3(1.0, 2.0, 3.0)
|
|
52
|
-
com1 = wp.vec3(4.0, 5.0, 6.0)
|
|
53
|
-
com2 = wp.vec3(7.0, 8.0, 9.0)
|
|
54
|
-
ax0 = wp.normalize(wp.vec3(-1.0, 2.0, 3.0))
|
|
55
|
-
ax1 = wp.normalize(wp.vec3(4.0, -1.0, 2.0))
|
|
56
|
-
ax2 = wp.normalize(wp.vec3(-3.0, 4.0, -1.0))
|
|
57
|
-
# declare some transforms with nonzero translation and orientation
|
|
58
|
-
tf0 = wp.transform(wp.vec3(1.0, 2.0, 3.0), wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), math.pi * 0.25))
|
|
59
|
-
tf1 = wp.transform(wp.vec3(4.0, 5.0, 6.0), wp.quat_from_axis_angle(wp.vec3(0.0, 1.0, 0.0), math.pi * 0.5))
|
|
60
|
-
tf2 = wp.transform(wp.vec3(7.0, 8.0, 9.0), wp.quat_from_axis_angle(wp.vec3(0.0, 0.0, 1.0), math.pi * 0.75))
|
|
61
|
-
|
|
62
|
-
parent = -1
|
|
63
|
-
for _i in range(chain_length):
|
|
64
|
-
b0 = builder.add_body(com=com0)
|
|
65
|
-
builder.add_joint_fixed(parent=parent, child=b0, parent_xform=tf1, child_xform=tf0)
|
|
66
|
-
assert builder.articulation_count == 1
|
|
67
|
-
|
|
68
|
-
b1 = builder.add_body(com=com1)
|
|
69
|
-
builder.add_joint_revolute(parent=b0, child=b1, parent_xform=tf1, child_xform=tf2, axis=ax1)
|
|
70
|
-
builder.joint_q[-1] = 0.3
|
|
71
|
-
builder.joint_qd[-1] = 1.0
|
|
72
|
-
|
|
73
|
-
b2 = builder.add_body(com=com2)
|
|
74
|
-
builder.add_joint_universal(parent=b1, child=b2, parent_xform=tf2, child_xform=tf0, axis_0=ax0, axis_1=ax1)
|
|
75
|
-
builder.joint_q[-2:] = [0.3, 0.5]
|
|
76
|
-
builder.joint_qd[-2:] = [1.0, -1.0]
|
|
77
|
-
|
|
78
|
-
b3 = builder.add_body(com=com0)
|
|
79
|
-
builder.add_joint_ball(parent=b2, child=b3, parent_xform=tf0, child_xform=tf1)
|
|
80
|
-
builder.joint_q[-4:] = list(wp.quat_from_axis_angle(ax0, 0.7))
|
|
81
|
-
builder.joint_qd[-3:] = [1.0, -0.6, 1.5]
|
|
82
|
-
|
|
83
|
-
b4 = builder.add_body(com=com1)
|
|
84
|
-
builder.add_joint_compound(
|
|
85
|
-
parent=b3,
|
|
86
|
-
child=b4,
|
|
87
|
-
parent_xform=tf2,
|
|
88
|
-
child_xform=tf1,
|
|
89
|
-
axis_0=(0, 0, 1),
|
|
90
|
-
axis_1=(1, 0, 0),
|
|
91
|
-
axis_2=(0, 1, 0),
|
|
92
|
-
)
|
|
93
|
-
builder.joint_q[-3:] = [0.3, 0.5, 0.27]
|
|
94
|
-
builder.joint_qd[-3:] = [1.23, -1.0, 0.5]
|
|
95
|
-
|
|
96
|
-
b5 = builder.add_body(com=com2)
|
|
97
|
-
builder.add_joint_prismatic(
|
|
98
|
-
parent=b4,
|
|
99
|
-
child=b5,
|
|
100
|
-
parent_xform=tf2,
|
|
101
|
-
child_xform=tf0,
|
|
102
|
-
axis=ax0,
|
|
103
|
-
)
|
|
104
|
-
builder.joint_q[-1] = 0.92
|
|
105
|
-
builder.joint_qd[-1] = -0.63
|
|
106
|
-
|
|
107
|
-
b6 = builder.add_body(com=com0)
|
|
108
|
-
builder.add_joint_d6(
|
|
109
|
-
parent=b5,
|
|
110
|
-
child=b6,
|
|
111
|
-
parent_xform=tf0,
|
|
112
|
-
child_xform=tf2,
|
|
113
|
-
linear_axes=[ax0, ax1, wp.cross(ax0, ax1)],
|
|
114
|
-
angular_axes=[ax1, ax2, wp.cross(ax1, ax2)],
|
|
115
|
-
)
|
|
116
|
-
builder.joint_q[-6:] = [0.3, 0.5, 0.7, 0.9, 1.1, 1.3]
|
|
117
|
-
builder.joint_qd[-6:] = [1.0, -1.0, 0.5, 0.8, -0.3, 0.1]
|
|
118
|
-
|
|
119
|
-
b7 = builder.add_body(com=com1)
|
|
120
|
-
builder.add_joint_free(
|
|
121
|
-
parent=b6,
|
|
122
|
-
child=b7,
|
|
123
|
-
parent_xform=tf1,
|
|
124
|
-
child_xform=tf2,
|
|
125
|
-
)
|
|
126
|
-
builder.joint_q[-7:] = [0.5, -0.9, 1.4, *wp.quat_rpy(0.3, -0.5, 0.7)]
|
|
127
|
-
builder.joint_qd[-6:] = [1.0, -1.0, 0.5, 0.8, -0.3, 0.1]
|
|
128
|
-
|
|
129
|
-
b8 = builder.add_body(com=com2)
|
|
130
|
-
builder.add_joint_distance(
|
|
131
|
-
parent=b7,
|
|
132
|
-
child=b8,
|
|
133
|
-
parent_xform=tf1,
|
|
134
|
-
child_xform=tf2,
|
|
135
|
-
)
|
|
136
|
-
builder.joint_q[-7:] = [-0.3, -0.7, 0.2, *wp.quat_rpy(0.1, 0.1, 0.4)]
|
|
137
|
-
builder.joint_qd[-6:] = [-0.34, 0.5, -0.6, -0.4, 0.2, 0.1]
|
|
138
|
-
|
|
139
|
-
# D6 joint that behaves like a fixed joint
|
|
140
|
-
b9 = builder.add_body(com=com0)
|
|
141
|
-
builder.add_joint_d6(
|
|
142
|
-
parent=b8,
|
|
143
|
-
child=b9,
|
|
144
|
-
parent_xform=tf0,
|
|
145
|
-
child_xform=tf2,
|
|
146
|
-
linear_axes=[],
|
|
147
|
-
angular_axes=[],
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
b10 = builder.add_body(com=com0)
|
|
151
|
-
builder.add_joint_d6(
|
|
152
|
-
parent=b9,
|
|
153
|
-
child=b10,
|
|
154
|
-
parent_xform=tf1,
|
|
155
|
-
child_xform=tf2,
|
|
156
|
-
linear_axes=[ax1],
|
|
157
|
-
angular_axes=[ax2, ax0],
|
|
158
|
-
)
|
|
159
|
-
builder.joint_q[-3:] = [0.3, 0.5, 0.7]
|
|
160
|
-
builder.joint_qd[-3:] = [1.0, -1.0, 0.5]
|
|
161
|
-
|
|
162
|
-
b11 = builder.add_body(com=com1)
|
|
163
|
-
builder.add_joint_d6(
|
|
164
|
-
parent=b10,
|
|
165
|
-
child=b11,
|
|
166
|
-
parent_xform=tf1,
|
|
167
|
-
child_xform=tf2,
|
|
168
|
-
linear_axes=[ax1, ax0, wp.cross(ax1, ax0)],
|
|
169
|
-
angular_axes=[],
|
|
170
|
-
)
|
|
171
|
-
builder.joint_q[-3:] = [0.3, 0.5, 0.7]
|
|
172
|
-
builder.joint_qd[-3:] = [1.0, -1.0, 0.5]
|
|
173
|
-
|
|
174
|
-
b12 = builder.add_body(com=com2)
|
|
175
|
-
builder.add_joint_d6(
|
|
176
|
-
parent=b11,
|
|
177
|
-
child=b12,
|
|
178
|
-
parent_xform=tf1,
|
|
179
|
-
child_xform=tf2,
|
|
180
|
-
linear_axes=[],
|
|
181
|
-
angular_axes=[ax1, ax2, wp.cross(ax1, ax2)],
|
|
182
|
-
)
|
|
183
|
-
builder.joint_q[-3:] = [0.3, 0.5, 0.7]
|
|
184
|
-
builder.joint_qd[-3:] = [1.0, -1.0, 0.5]
|
|
185
|
-
|
|
186
|
-
parent = b12
|
|
187
|
-
|
|
188
|
-
return builder
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
def check_fk_ik(builder, device):
|
|
192
|
-
model = builder.finalize(device)
|
|
193
|
-
state = model.state()
|
|
194
|
-
|
|
195
|
-
q_fk = model.joint_q.numpy()
|
|
196
|
-
qd_fk = model.joint_qd.numpy()
|
|
197
|
-
|
|
198
|
-
wp.sim.eval_fk(model, model.joint_q, model.joint_qd, None, state)
|
|
199
|
-
|
|
200
|
-
q_ik = wp.zeros_like(model.joint_q)
|
|
201
|
-
qd_ik = wp.zeros_like(model.joint_qd)
|
|
202
|
-
|
|
203
|
-
wp.sim.eval_ik(model, state, q_ik, qd_ik)
|
|
204
|
-
|
|
205
|
-
# adjust numpy print settings
|
|
206
|
-
# np.set_printoptions(precision=4, floatmode="fixed", suppress=True)
|
|
207
|
-
# print("q:")
|
|
208
|
-
# print(np.array(q_fk))
|
|
209
|
-
# print(q_ik.numpy())
|
|
210
|
-
|
|
211
|
-
# print("qd:")
|
|
212
|
-
# print(np.array(qd_fk))
|
|
213
|
-
# print(qd_ik.numpy())
|
|
214
|
-
|
|
215
|
-
assert_np_equal(q_ik.numpy(), q_fk, tol=1e-4)
|
|
216
|
-
assert_np_equal(qd_ik.numpy(), qd_fk, tol=1e-4)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
def test_fk_ik_ant(test, device):
|
|
220
|
-
builder = build_ant(3)
|
|
221
|
-
check_fk_ik(builder, device)
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
def test_fk_ik_complex_joint_mechanism(test, device):
|
|
225
|
-
builder = build_complex_joint_mechanism(2)
|
|
226
|
-
check_fk_ik(builder, device)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
devices = get_test_devices()
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
class TestKinematics(unittest.TestCase):
|
|
233
|
-
pass
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
add_function_test(TestKinematics, "test_fk_ik_ant", test_fk_ik_ant, devices=devices)
|
|
237
|
-
add_function_test(
|
|
238
|
-
TestKinematics, "test_fk_ik_complex_joint_mechanism", test_fk_ik_complex_joint_mechanism, devices=devices
|
|
239
|
-
)
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if __name__ == "__main__":
|
|
243
|
-
wp.clear_kernel_cache()
|
|
244
|
-
unittest.main(verbosity=2, failfast=False)
|