warp-lang 1.0.2__py3-none-manylinux2014_x86_64.whl → 1.2.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 +108 -97
- warp/__init__.pyi +1 -1
- warp/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/build.py +88 -113
- warp/build_dll.py +383 -375
- warp/builtins.py +3693 -3354
- warp/codegen.py +2925 -2792
- warp/config.py +40 -36
- warp/constants.py +49 -45
- warp/context.py +5409 -5102
- warp/dlpack.py +442 -442
- warp/examples/__init__.py +16 -16
- warp/examples/assets/bear.usd +0 -0
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/assets/cartpole.urdf +110 -110
- warp/examples/assets/crazyflie.usd +0 -0
- warp/examples/assets/cube.usd +0 -0
- warp/examples/assets/nv_ant.xml +92 -92
- warp/examples/assets/nv_humanoid.xml +183 -183
- warp/examples/assets/quadruped.urdf +267 -267
- warp/examples/assets/rocks.nvdb +0 -0
- warp/examples/assets/rocks.usd +0 -0
- warp/examples/assets/sphere.usd +0 -0
- warp/examples/benchmarks/benchmark_api.py +381 -383
- warp/examples/benchmarks/benchmark_cloth.py +278 -277
- warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -88
- warp/examples/benchmarks/benchmark_cloth_jax.py +97 -100
- warp/examples/benchmarks/benchmark_cloth_numba.py +146 -142
- warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -77
- warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -86
- warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -112
- warp/examples/benchmarks/benchmark_cloth_warp.py +145 -146
- warp/examples/benchmarks/benchmark_launches.py +293 -295
- warp/examples/browse.py +29 -29
- warp/examples/core/example_dem.py +232 -219
- warp/examples/core/example_fluid.py +291 -267
- warp/examples/core/example_graph_capture.py +142 -126
- warp/examples/core/example_marching_cubes.py +186 -174
- warp/examples/core/example_mesh.py +172 -155
- warp/examples/core/example_mesh_intersect.py +203 -193
- warp/examples/core/example_nvdb.py +174 -170
- warp/examples/core/example_raycast.py +103 -90
- warp/examples/core/example_raymarch.py +197 -178
- warp/examples/core/example_render_opengl.py +183 -141
- warp/examples/core/example_sph.py +403 -387
- warp/examples/core/example_torch.py +219 -181
- warp/examples/core/example_wave.py +261 -248
- warp/examples/fem/bsr_utils.py +378 -380
- warp/examples/fem/example_apic_fluid.py +432 -389
- warp/examples/fem/example_burgers.py +262 -0
- warp/examples/fem/example_convection_diffusion.py +180 -168
- warp/examples/fem/example_convection_diffusion_dg.py +217 -209
- warp/examples/fem/example_deformed_geometry.py +175 -159
- warp/examples/fem/example_diffusion.py +199 -173
- warp/examples/fem/example_diffusion_3d.py +178 -152
- warp/examples/fem/example_diffusion_mgpu.py +219 -214
- warp/examples/fem/example_mixed_elasticity.py +242 -222
- warp/examples/fem/example_navier_stokes.py +257 -243
- warp/examples/fem/example_stokes.py +218 -192
- warp/examples/fem/example_stokes_transfer.py +263 -249
- warp/examples/fem/mesh_utils.py +133 -109
- warp/examples/fem/plot_utils.py +292 -287
- warp/examples/optim/example_bounce.py +258 -246
- warp/examples/optim/example_cloth_throw.py +220 -209
- warp/examples/optim/example_diffray.py +564 -536
- warp/examples/optim/example_drone.py +862 -835
- warp/examples/optim/example_inverse_kinematics.py +174 -168
- warp/examples/optim/example_inverse_kinematics_torch.py +183 -169
- warp/examples/optim/example_spring_cage.py +237 -231
- warp/examples/optim/example_trajectory.py +221 -199
- warp/examples/optim/example_walker.py +304 -293
- warp/examples/sim/example_cartpole.py +137 -129
- warp/examples/sim/example_cloth.py +194 -186
- warp/examples/sim/example_granular.py +122 -111
- warp/examples/sim/example_granular_collision_sdf.py +195 -186
- warp/examples/sim/example_jacobian_ik.py +234 -214
- warp/examples/sim/example_particle_chain.py +116 -105
- warp/examples/sim/example_quadruped.py +191 -180
- warp/examples/sim/example_rigid_chain.py +195 -187
- warp/examples/sim/example_rigid_contact.py +187 -177
- warp/examples/sim/example_rigid_force.py +125 -125
- warp/examples/sim/example_rigid_gyroscopic.py +107 -95
- warp/examples/sim/example_rigid_soft_contact.py +132 -122
- warp/examples/sim/example_soft_body.py +188 -177
- warp/fabric.py +337 -335
- warp/fem/__init__.py +61 -27
- warp/fem/cache.py +403 -388
- warp/fem/dirichlet.py +178 -179
- warp/fem/domain.py +262 -263
- warp/fem/field/__init__.py +100 -101
- warp/fem/field/field.py +148 -149
- warp/fem/field/nodal_field.py +298 -299
- warp/fem/field/restriction.py +22 -21
- warp/fem/field/test.py +180 -181
- warp/fem/field/trial.py +183 -183
- warp/fem/geometry/__init__.py +16 -19
- warp/fem/geometry/closest_point.py +69 -70
- warp/fem/geometry/deformed_geometry.py +270 -271
- warp/fem/geometry/element.py +748 -744
- warp/fem/geometry/geometry.py +184 -186
- warp/fem/geometry/grid_2d.py +380 -373
- warp/fem/geometry/grid_3d.py +437 -435
- warp/fem/geometry/hexmesh.py +953 -953
- warp/fem/geometry/nanogrid.py +455 -0
- warp/fem/geometry/partition.py +374 -376
- warp/fem/geometry/quadmesh_2d.py +532 -532
- warp/fem/geometry/tetmesh.py +840 -840
- warp/fem/geometry/trimesh_2d.py +577 -577
- warp/fem/integrate.py +1684 -1615
- warp/fem/operator.py +190 -191
- warp/fem/polynomial.py +214 -213
- warp/fem/quadrature/__init__.py +2 -2
- warp/fem/quadrature/pic_quadrature.py +243 -245
- warp/fem/quadrature/quadrature.py +295 -294
- warp/fem/space/__init__.py +179 -292
- warp/fem/space/basis_space.py +522 -489
- warp/fem/space/collocated_function_space.py +100 -105
- warp/fem/space/dof_mapper.py +236 -236
- warp/fem/space/function_space.py +148 -145
- warp/fem/space/grid_2d_function_space.py +148 -267
- warp/fem/space/grid_3d_function_space.py +167 -306
- warp/fem/space/hexmesh_function_space.py +253 -352
- warp/fem/space/nanogrid_function_space.py +202 -0
- warp/fem/space/partition.py +350 -350
- warp/fem/space/quadmesh_2d_function_space.py +261 -369
- warp/fem/space/restriction.py +161 -160
- warp/fem/space/shape/__init__.py +90 -15
- warp/fem/space/shape/cube_shape_function.py +728 -738
- warp/fem/space/shape/shape_function.py +102 -103
- warp/fem/space/shape/square_shape_function.py +611 -611
- warp/fem/space/shape/tet_shape_function.py +565 -567
- warp/fem/space/shape/triangle_shape_function.py +429 -429
- warp/fem/space/tetmesh_function_space.py +224 -292
- warp/fem/space/topology.py +297 -295
- warp/fem/space/trimesh_2d_function_space.py +153 -221
- warp/fem/types.py +77 -77
- warp/fem/utils.py +495 -495
- warp/jax.py +166 -141
- warp/jax_experimental.py +341 -339
- warp/native/array.h +1081 -1025
- warp/native/builtin.h +1603 -1560
- warp/native/bvh.cpp +402 -398
- warp/native/bvh.cu +533 -525
- warp/native/bvh.h +430 -429
- warp/native/clang/clang.cpp +496 -464
- warp/native/crt.cpp +42 -32
- warp/native/crt.h +352 -335
- warp/native/cuda_crt.h +1049 -1049
- warp/native/cuda_util.cpp +549 -540
- warp/native/cuda_util.h +288 -203
- warp/native/cutlass_gemm.cpp +34 -34
- warp/native/cutlass_gemm.cu +372 -372
- warp/native/error.cpp +66 -66
- warp/native/error.h +27 -27
- warp/native/exports.h +187 -0
- warp/native/fabric.h +228 -228
- warp/native/hashgrid.cpp +301 -278
- warp/native/hashgrid.cu +78 -77
- warp/native/hashgrid.h +227 -227
- warp/native/initializer_array.h +32 -32
- warp/native/intersect.h +1204 -1204
- warp/native/intersect_adj.h +365 -365
- warp/native/intersect_tri.h +322 -322
- warp/native/marching.cpp +2 -2
- warp/native/marching.cu +497 -497
- warp/native/marching.h +2 -2
- warp/native/mat.h +1545 -1498
- warp/native/matnn.h +333 -333
- warp/native/mesh.cpp +203 -203
- warp/native/mesh.cu +292 -293
- warp/native/mesh.h +1887 -1887
- warp/native/nanovdb/GridHandle.h +366 -0
- warp/native/nanovdb/HostBuffer.h +590 -0
- warp/native/nanovdb/NanoVDB.h +6624 -4782
- warp/native/nanovdb/PNanoVDB.h +3390 -2553
- warp/native/noise.h +850 -850
- warp/native/quat.h +1112 -1085
- warp/native/rand.h +303 -299
- warp/native/range.h +108 -108
- warp/native/reduce.cpp +156 -156
- warp/native/reduce.cu +348 -348
- warp/native/runlength_encode.cpp +61 -61
- warp/native/runlength_encode.cu +46 -46
- warp/native/scan.cpp +30 -30
- warp/native/scan.cu +36 -36
- warp/native/scan.h +7 -7
- warp/native/solid_angle.h +442 -442
- warp/native/sort.cpp +94 -94
- warp/native/sort.cu +97 -97
- warp/native/sort.h +14 -14
- warp/native/sparse.cpp +337 -337
- warp/native/sparse.cu +544 -544
- warp/native/spatial.h +630 -630
- warp/native/svd.h +562 -562
- warp/native/temp_buffer.h +30 -30
- warp/native/vec.h +1177 -1133
- warp/native/volume.cpp +529 -297
- warp/native/volume.cu +58 -32
- warp/native/volume.h +960 -538
- warp/native/volume_builder.cu +446 -425
- warp/native/volume_builder.h +34 -19
- warp/native/volume_impl.h +61 -0
- warp/native/warp.cpp +1057 -1052
- warp/native/warp.cu +2949 -2828
- warp/native/warp.h +321 -305
- warp/optim/__init__.py +9 -9
- warp/optim/adam.py +120 -120
- warp/optim/linear.py +1104 -939
- warp/optim/sgd.py +104 -92
- warp/render/__init__.py +10 -10
- warp/render/render_opengl.py +3356 -3204
- warp/render/render_usd.py +768 -749
- warp/render/utils.py +152 -150
- warp/sim/__init__.py +52 -59
- warp/sim/articulation.py +685 -685
- warp/sim/collide.py +1594 -1590
- warp/sim/import_mjcf.py +489 -481
- warp/sim/import_snu.py +220 -221
- warp/sim/import_urdf.py +536 -516
- warp/sim/import_usd.py +887 -881
- warp/sim/inertia.py +316 -317
- warp/sim/integrator.py +234 -233
- warp/sim/integrator_euler.py +1956 -1956
- warp/sim/integrator_featherstone.py +1917 -1991
- warp/sim/integrator_xpbd.py +3288 -3312
- warp/sim/model.py +4473 -4314
- warp/sim/particles.py +113 -112
- warp/sim/render.py +417 -403
- warp/sim/utils.py +413 -410
- warp/sparse.py +1289 -1227
- warp/stubs.py +2192 -2469
- warp/tape.py +1162 -225
- warp/tests/__init__.py +1 -1
- warp/tests/__main__.py +4 -4
- warp/tests/assets/test_index_grid.nvdb +0 -0
- warp/tests/assets/torus.usda +105 -105
- warp/tests/aux_test_class_kernel.py +26 -26
- warp/tests/aux_test_compile_consts_dummy.py +10 -10
- warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -21
- warp/tests/aux_test_dependent.py +20 -22
- warp/tests/aux_test_grad_customs.py +21 -23
- warp/tests/aux_test_reference.py +9 -11
- warp/tests/aux_test_reference_reference.py +8 -10
- warp/tests/aux_test_square.py +15 -17
- warp/tests/aux_test_unresolved_func.py +14 -14
- warp/tests/aux_test_unresolved_symbol.py +14 -14
- warp/tests/disabled_kinematics.py +237 -239
- warp/tests/run_coverage_serial.py +31 -31
- warp/tests/test_adam.py +155 -157
- warp/tests/test_arithmetic.py +1088 -1124
- warp/tests/test_array.py +2415 -2326
- warp/tests/test_array_reduce.py +148 -150
- warp/tests/test_async.py +666 -656
- warp/tests/test_atomic.py +139 -141
- warp/tests/test_bool.py +212 -149
- warp/tests/test_builtins_resolution.py +1290 -1292
- warp/tests/test_bvh.py +162 -171
- warp/tests/test_closest_point_edge_edge.py +227 -228
- warp/tests/test_codegen.py +562 -553
- warp/tests/test_compile_consts.py +217 -101
- warp/tests/test_conditional.py +244 -246
- warp/tests/test_copy.py +230 -215
- warp/tests/test_ctypes.py +630 -632
- warp/tests/test_dense.py +65 -67
- warp/tests/test_devices.py +89 -98
- warp/tests/test_dlpack.py +528 -529
- warp/tests/test_examples.py +403 -378
- warp/tests/test_fabricarray.py +952 -955
- warp/tests/test_fast_math.py +60 -54
- warp/tests/test_fem.py +1298 -1278
- warp/tests/test_fp16.py +128 -130
- warp/tests/test_func.py +336 -337
- warp/tests/test_generics.py +596 -571
- warp/tests/test_grad.py +885 -640
- warp/tests/test_grad_customs.py +331 -336
- warp/tests/test_hash_grid.py +208 -164
- warp/tests/test_import.py +37 -39
- warp/tests/test_indexedarray.py +1132 -1134
- warp/tests/test_intersect.py +65 -67
- warp/tests/test_jax.py +305 -307
- warp/tests/test_large.py +169 -164
- warp/tests/test_launch.py +352 -354
- warp/tests/test_lerp.py +217 -261
- warp/tests/test_linear_solvers.py +189 -171
- warp/tests/test_lvalue.py +419 -493
- warp/tests/test_marching_cubes.py +63 -65
- warp/tests/test_mat.py +1799 -1827
- warp/tests/test_mat_lite.py +113 -115
- warp/tests/test_mat_scalar_ops.py +2905 -2889
- warp/tests/test_math.py +124 -193
- warp/tests/test_matmul.py +498 -499
- warp/tests/test_matmul_lite.py +408 -410
- warp/tests/test_mempool.py +186 -190
- warp/tests/test_mesh.py +281 -324
- warp/tests/test_mesh_query_aabb.py +226 -241
- warp/tests/test_mesh_query_point.py +690 -702
- warp/tests/test_mesh_query_ray.py +290 -303
- warp/tests/test_mlp.py +274 -276
- warp/tests/test_model.py +108 -110
- warp/tests/test_module_hashing.py +111 -0
- warp/tests/test_modules_lite.py +36 -39
- warp/tests/test_multigpu.py +161 -163
- warp/tests/test_noise.py +244 -248
- warp/tests/test_operators.py +248 -250
- warp/tests/test_options.py +121 -125
- warp/tests/test_peer.py +131 -137
- warp/tests/test_pinned.py +76 -78
- warp/tests/test_print.py +52 -54
- warp/tests/test_quat.py +2084 -2086
- warp/tests/test_rand.py +324 -288
- warp/tests/test_reload.py +207 -217
- warp/tests/test_rounding.py +177 -179
- warp/tests/test_runlength_encode.py +188 -190
- warp/tests/test_sim_grad.py +241 -0
- warp/tests/test_sim_kinematics.py +89 -97
- warp/tests/test_smoothstep.py +166 -168
- warp/tests/test_snippet.py +303 -266
- warp/tests/test_sparse.py +466 -460
- warp/tests/test_spatial.py +2146 -2148
- warp/tests/test_special_values.py +362 -0
- warp/tests/test_streams.py +484 -473
- warp/tests/test_struct.py +708 -675
- warp/tests/test_tape.py +171 -148
- warp/tests/test_torch.py +741 -743
- warp/tests/test_transient_module.py +85 -87
- warp/tests/test_types.py +554 -659
- warp/tests/test_utils.py +488 -499
- warp/tests/test_vec.py +1262 -1268
- warp/tests/test_vec_lite.py +71 -73
- warp/tests/test_vec_scalar_ops.py +2097 -2099
- warp/tests/test_verify_fp.py +92 -94
- warp/tests/test_volume.py +961 -736
- warp/tests/test_volume_write.py +338 -265
- warp/tests/unittest_serial.py +38 -37
- warp/tests/unittest_suites.py +367 -359
- warp/tests/unittest_utils.py +434 -578
- warp/tests/unused_test_misc.py +69 -71
- warp/tests/walkthrough_debug.py +85 -85
- warp/thirdparty/appdirs.py +598 -598
- warp/thirdparty/dlpack.py +143 -143
- warp/thirdparty/unittest_parallel.py +563 -561
- warp/torch.py +321 -295
- warp/types.py +4941 -4450
- warp/utils.py +1008 -821
- {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/LICENSE.md +126 -126
- {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/METADATA +365 -400
- warp_lang-1.2.0.dist-info/RECORD +359 -0
- warp/examples/assets/cube.usda +0 -42
- warp/examples/assets/sphere.usda +0 -56
- warp/examples/assets/torus.usda +0 -105
- warp/examples/fem/example_convection_diffusion_dg0.py +0 -194
- warp/native/nanovdb/PNanoVDBWrite.h +0 -295
- warp_lang-1.0.2.dist-info/RECORD +0 -352
- {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/WHEEL +0 -0
- {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/top_level.txt +0 -0
warp/sim/articulation.py
CHANGED
|
@@ -1,685 +1,685 @@
|
|
|
1
|
-
# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
-
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
-
# and proprietary rights in and to this software, related documentation
|
|
4
|
-
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
-
# distribution of this software and related documentation without an express
|
|
6
|
-
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
-
|
|
8
|
-
import warp as wp
|
|
9
|
-
|
|
10
|
-
from .utils import quat_decompose, quat_twist
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@wp.func
|
|
14
|
-
def compute_2d_rotational_dofs(
|
|
15
|
-
axis_0: wp.vec3,
|
|
16
|
-
axis_1: wp.vec3,
|
|
17
|
-
q0: float,
|
|
18
|
-
q1: float,
|
|
19
|
-
qd0: float,
|
|
20
|
-
qd1: float,
|
|
21
|
-
):
|
|
22
|
-
"""
|
|
23
|
-
Computes the rotation quaternion and 3D angular velocity given the joint axes, coordinates and velocities.
|
|
24
|
-
"""
|
|
25
|
-
q_off = wp.quat_from_matrix(wp.mat33(axis_0, axis_1, wp.cross(axis_0, axis_1)))
|
|
26
|
-
|
|
27
|
-
# body local axes
|
|
28
|
-
local_0 = wp.quat_rotate(q_off, wp.vec3(1.0, 0.0, 0.0))
|
|
29
|
-
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
30
|
-
|
|
31
|
-
axis_0 = local_0
|
|
32
|
-
q_0 = wp.quat_from_axis_angle(axis_0, q0)
|
|
33
|
-
|
|
34
|
-
axis_1 = wp.quat_rotate(q_0, local_1)
|
|
35
|
-
q_1 = wp.quat_from_axis_angle(axis_1, q1)
|
|
36
|
-
|
|
37
|
-
rot = q_1 * q_0
|
|
38
|
-
|
|
39
|
-
vel = axis_0 * qd0 + axis_1 * qd1
|
|
40
|
-
|
|
41
|
-
return rot, vel
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@wp.func
|
|
45
|
-
def invert_2d_rotational_dofs(
|
|
46
|
-
axis_0: wp.vec3,
|
|
47
|
-
axis_1: wp.vec3,
|
|
48
|
-
q_p: wp.quat,
|
|
49
|
-
q_c: wp.quat,
|
|
50
|
-
w_err: wp.vec3,
|
|
51
|
-
):
|
|
52
|
-
"""
|
|
53
|
-
Computes generalized joint position and velocity coordinates for a 2D rotational joint given the joint axes, relative orientations and angular velocity differences between the two bodies the joint connects.
|
|
54
|
-
"""
|
|
55
|
-
q_off = wp.quat_from_matrix(wp.mat33(axis_0, axis_1, wp.cross(axis_0, axis_1)))
|
|
56
|
-
q_pc = wp.quat_inverse(q_off) * wp.quat_inverse(q_p) * q_c * q_off
|
|
57
|
-
|
|
58
|
-
# decompose to a compound rotation each axis
|
|
59
|
-
angles = quat_decompose(q_pc)
|
|
60
|
-
|
|
61
|
-
# find rotation axes
|
|
62
|
-
local_0 = wp.quat_rotate(q_off, wp.vec3(1.0, 0.0, 0.0))
|
|
63
|
-
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
64
|
-
local_2 = wp.quat_rotate(q_off, wp.vec3(0.0, 0.0, 1.0))
|
|
65
|
-
|
|
66
|
-
axis_0 = local_0
|
|
67
|
-
q_0 = wp.quat_from_axis_angle(axis_0, angles[0])
|
|
68
|
-
|
|
69
|
-
axis_1 = wp.quat_rotate(q_0, local_1)
|
|
70
|
-
q_1 = wp.quat_from_axis_angle(axis_1, angles[1])
|
|
71
|
-
|
|
72
|
-
axis_2 = wp.quat_rotate(q_1 * q_0, local_2)
|
|
73
|
-
|
|
74
|
-
# convert angular velocity to local space
|
|
75
|
-
w_err_p = wp.quat_rotate_inv(q_p, w_err)
|
|
76
|
-
|
|
77
|
-
# given joint axes and angular velocity error, solve for joint velocities
|
|
78
|
-
c12 = wp.cross(axis_1, axis_2)
|
|
79
|
-
c02 = wp.cross(axis_0, axis_2)
|
|
80
|
-
|
|
81
|
-
vel = wp.vec2(wp.dot(w_err_p, c12) / wp.dot(axis_0, c12), wp.dot(w_err_p, c02) / wp.dot(axis_1, c02))
|
|
82
|
-
|
|
83
|
-
return wp.vec2(angles[0], angles[1]), vel
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@wp.func
|
|
87
|
-
def compute_3d_rotational_dofs(
|
|
88
|
-
axis_0: wp.vec3,
|
|
89
|
-
axis_1: wp.vec3,
|
|
90
|
-
axis_2: wp.vec3,
|
|
91
|
-
q0: float,
|
|
92
|
-
q1: float,
|
|
93
|
-
q2: float,
|
|
94
|
-
qd0: float,
|
|
95
|
-
qd1: float,
|
|
96
|
-
qd2: float,
|
|
97
|
-
):
|
|
98
|
-
"""
|
|
99
|
-
Computes the rotation quaternion and 3D angular velocity given the joint axes, coordinates and velocities.
|
|
100
|
-
"""
|
|
101
|
-
q_off = wp.quat_from_matrix(wp.mat33(axis_0, axis_1, axis_2))
|
|
102
|
-
|
|
103
|
-
# body local axes
|
|
104
|
-
local_0 = wp.quat_rotate(q_off, wp.vec3(1.0, 0.0, 0.0))
|
|
105
|
-
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
106
|
-
local_2 = wp.quat_rotate(q_off, wp.vec3(0.0, 0.0, 1.0))
|
|
107
|
-
|
|
108
|
-
# reconstruct rotation axes
|
|
109
|
-
axis_0 = local_0
|
|
110
|
-
q_0 = wp.quat_from_axis_angle(axis_0, q0)
|
|
111
|
-
|
|
112
|
-
axis_1 = wp.quat_rotate(q_0, local_1)
|
|
113
|
-
q_1 = wp.quat_from_axis_angle(axis_1, q1)
|
|
114
|
-
|
|
115
|
-
axis_2 = wp.quat_rotate(q_1 * q_0, local_2)
|
|
116
|
-
q_2 = wp.quat_from_axis_angle(axis_2, q2)
|
|
117
|
-
|
|
118
|
-
rot = q_2 * q_1 * q_0
|
|
119
|
-
vel = axis_0 * qd0 + axis_1 * qd1 + axis_2 * qd2
|
|
120
|
-
|
|
121
|
-
return rot, vel
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
@wp.func
|
|
125
|
-
def invert_3d_rotational_dofs(
|
|
126
|
-
axis_0: wp.vec3, axis_1: wp.vec3, axis_2: wp.vec3, q_p: wp.quat, q_c: wp.quat, w_err: wp.vec3
|
|
127
|
-
):
|
|
128
|
-
"""
|
|
129
|
-
Computes generalized joint position and velocity coordinates for a 3D rotational joint given the joint axes, relative orientations and angular velocity differences between the two bodies the joint connects.
|
|
130
|
-
"""
|
|
131
|
-
q_off = wp.quat_from_matrix(wp.mat33(axis_0, axis_1, axis_2))
|
|
132
|
-
q_pc = wp.quat_inverse(q_off) * wp.quat_inverse(q_p) * q_c * q_off
|
|
133
|
-
|
|
134
|
-
# decompose to a compound rotation each axis
|
|
135
|
-
angles = quat_decompose(q_pc)
|
|
136
|
-
|
|
137
|
-
# find rotation axes
|
|
138
|
-
local_0 = wp.quat_rotate(q_off, wp.vec3(1.0, 0.0, 0.0))
|
|
139
|
-
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
140
|
-
local_2 = wp.quat_rotate(q_off, wp.vec3(0.0, 0.0, 1.0))
|
|
141
|
-
|
|
142
|
-
axis_0 = local_0
|
|
143
|
-
q_0 = wp.quat_from_axis_angle(axis_0, angles[0])
|
|
144
|
-
|
|
145
|
-
axis_1 = wp.quat_rotate(q_0, local_1)
|
|
146
|
-
q_1 = wp.quat_from_axis_angle(axis_1, angles[1])
|
|
147
|
-
|
|
148
|
-
axis_2 = wp.quat_rotate(q_1 * q_0, local_2)
|
|
149
|
-
|
|
150
|
-
# convert angular velocity to local space
|
|
151
|
-
w_err_p = wp.quat_rotate_inv(q_p, w_err)
|
|
152
|
-
|
|
153
|
-
# given joint axes and angular velocity error, solve for joint velocities
|
|
154
|
-
c12 = wp.cross(axis_1, axis_2)
|
|
155
|
-
c02 = wp.cross(axis_0, axis_2)
|
|
156
|
-
c01 = wp.cross(axis_0, axis_1)
|
|
157
|
-
|
|
158
|
-
velocities = wp.vec3(
|
|
159
|
-
wp.dot(w_err_p, c12) / wp.dot(axis_0, c12),
|
|
160
|
-
wp.dot(w_err_p, c02) / wp.dot(axis_1, c02),
|
|
161
|
-
wp.dot(w_err_p, c01) / wp.dot(axis_2, c01),
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
return angles, velocities
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
@wp.kernel
|
|
168
|
-
def eval_articulation_fk(
|
|
169
|
-
articulation_start: wp.array(dtype=int),
|
|
170
|
-
articulation_mask: wp.array(
|
|
171
|
-
dtype=int
|
|
172
|
-
), # used to enable / disable FK for an articulation, if None then treat all as enabled
|
|
173
|
-
joint_q: wp.array(dtype=float),
|
|
174
|
-
joint_qd: wp.array(dtype=float),
|
|
175
|
-
joint_q_start: wp.array(dtype=int),
|
|
176
|
-
joint_qd_start: wp.array(dtype=int),
|
|
177
|
-
joint_type: wp.array(dtype=int),
|
|
178
|
-
joint_parent: wp.array(dtype=int),
|
|
179
|
-
joint_child: wp.array(dtype=int),
|
|
180
|
-
joint_X_p: wp.array(dtype=wp.transform),
|
|
181
|
-
joint_X_c: wp.array(dtype=wp.transform),
|
|
182
|
-
joint_axis: wp.array(dtype=wp.vec3),
|
|
183
|
-
joint_axis_start: wp.array(dtype=int),
|
|
184
|
-
joint_axis_dim: wp.array(dtype=int, ndim=2),
|
|
185
|
-
body_com: wp.array(dtype=wp.vec3),
|
|
186
|
-
# outputs
|
|
187
|
-
body_q: wp.array(dtype=wp.transform),
|
|
188
|
-
body_qd: wp.array(dtype=wp.spatial_vector),
|
|
189
|
-
):
|
|
190
|
-
tid = wp.tid()
|
|
191
|
-
|
|
192
|
-
# early out if disabling FK for this articulation
|
|
193
|
-
if articulation_mask:
|
|
194
|
-
if articulation_mask[tid] == 0:
|
|
195
|
-
return
|
|
196
|
-
|
|
197
|
-
joint_start = articulation_start[tid]
|
|
198
|
-
joint_end = articulation_start[tid + 1]
|
|
199
|
-
|
|
200
|
-
for i in range(joint_start, joint_end):
|
|
201
|
-
parent = joint_parent[i]
|
|
202
|
-
child = joint_child[i]
|
|
203
|
-
|
|
204
|
-
# compute transform across the joint
|
|
205
|
-
type = joint_type[i]
|
|
206
|
-
|
|
207
|
-
X_pj = joint_X_p[i]
|
|
208
|
-
X_cj = joint_X_c[i]
|
|
209
|
-
|
|
210
|
-
# parent anchor frame in world space
|
|
211
|
-
X_wpj = X_pj
|
|
212
|
-
# velocity of parent anchor point in world space
|
|
213
|
-
v_wpj = wp.spatial_vector()
|
|
214
|
-
if parent >= 0:
|
|
215
|
-
X_wp = body_q[parent]
|
|
216
|
-
X_wpj = X_wp * X_wpj
|
|
217
|
-
r_p = wp.transform_get_translation(X_wpj) - wp.transform_point(X_wp, body_com[parent])
|
|
218
|
-
|
|
219
|
-
v_wp = body_qd[parent]
|
|
220
|
-
w_p = wp.spatial_top(v_wp)
|
|
221
|
-
v_p = wp.spatial_bottom(v_wp) + wp.cross(w_p, r_p)
|
|
222
|
-
v_wpj = wp.spatial_vector(w_p, v_p)
|
|
223
|
-
|
|
224
|
-
q_start = joint_q_start[i]
|
|
225
|
-
qd_start = joint_qd_start[i]
|
|
226
|
-
axis_start = joint_axis_start[i]
|
|
227
|
-
lin_axis_count = joint_axis_dim[i, 0]
|
|
228
|
-
ang_axis_count = joint_axis_dim[i, 1]
|
|
229
|
-
|
|
230
|
-
X_j = wp.transform_identity()
|
|
231
|
-
v_j = wp.spatial_vector(wp.vec3(), wp.vec3())
|
|
232
|
-
|
|
233
|
-
if type == wp.sim.JOINT_PRISMATIC:
|
|
234
|
-
axis = joint_axis[axis_start]
|
|
235
|
-
|
|
236
|
-
q = joint_q[q_start]
|
|
237
|
-
qd = joint_qd[qd_start]
|
|
238
|
-
|
|
239
|
-
X_j = wp.transform(axis * q, wp.quat_identity())
|
|
240
|
-
v_j = wp.spatial_vector(wp.vec3(), axis * qd)
|
|
241
|
-
|
|
242
|
-
if type == wp.sim.JOINT_REVOLUTE:
|
|
243
|
-
axis = joint_axis[axis_start]
|
|
244
|
-
|
|
245
|
-
q = joint_q[q_start]
|
|
246
|
-
qd = joint_qd[qd_start]
|
|
247
|
-
|
|
248
|
-
X_j = wp.transform(wp.vec3(), wp.quat_from_axis_angle(axis, q))
|
|
249
|
-
v_j = wp.spatial_vector(axis * qd, wp.vec3())
|
|
250
|
-
|
|
251
|
-
if type == wp.sim.JOINT_BALL:
|
|
252
|
-
r = wp.quat(joint_q[q_start + 0], joint_q[q_start + 1], joint_q[q_start + 2], joint_q[q_start + 3])
|
|
253
|
-
|
|
254
|
-
w = wp.vec3(joint_qd[qd_start + 0], joint_qd[qd_start + 1], joint_qd[qd_start + 2])
|
|
255
|
-
|
|
256
|
-
X_j = wp.transform(wp.vec3(), r)
|
|
257
|
-
v_j = wp.spatial_vector(w, wp.vec3())
|
|
258
|
-
|
|
259
|
-
if type == wp.sim.JOINT_FREE or type == wp.sim.JOINT_DISTANCE:
|
|
260
|
-
t = wp.transform(
|
|
261
|
-
wp.vec3(joint_q[q_start + 0], joint_q[q_start + 1], joint_q[q_start + 2]),
|
|
262
|
-
wp.quat(joint_q[q_start + 3], joint_q[q_start + 4], joint_q[q_start + 5], joint_q[q_start + 6]),
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
v = wp.spatial_vector(
|
|
266
|
-
wp.vec3(joint_qd[qd_start + 0], joint_qd[qd_start + 1], joint_qd[qd_start + 2]),
|
|
267
|
-
wp.vec3(joint_qd[qd_start + 3], joint_qd[qd_start + 4], joint_qd[qd_start + 5]),
|
|
268
|
-
)
|
|
269
|
-
|
|
270
|
-
X_j = t
|
|
271
|
-
v_j = v
|
|
272
|
-
|
|
273
|
-
if type == wp.sim.JOINT_COMPOUND:
|
|
274
|
-
rot, vel_w = compute_3d_rotational_dofs(
|
|
275
|
-
joint_axis[axis_start],
|
|
276
|
-
joint_axis[axis_start + 1],
|
|
277
|
-
joint_axis[axis_start + 2],
|
|
278
|
-
joint_q[q_start + 0],
|
|
279
|
-
joint_q[q_start + 1],
|
|
280
|
-
joint_q[q_start + 2],
|
|
281
|
-
joint_qd[qd_start + 0],
|
|
282
|
-
joint_qd[qd_start + 1],
|
|
283
|
-
joint_qd[qd_start + 2],
|
|
284
|
-
)
|
|
285
|
-
|
|
286
|
-
t = wp.transform(wp.vec3(0.0, 0.0, 0.0), rot)
|
|
287
|
-
v = wp.spatial_vector(vel_w, wp.vec3(0.0, 0.0, 0.0))
|
|
288
|
-
|
|
289
|
-
X_j = t
|
|
290
|
-
v_j = v
|
|
291
|
-
|
|
292
|
-
if type == wp.sim.JOINT_UNIVERSAL:
|
|
293
|
-
rot, vel_w = compute_2d_rotational_dofs(
|
|
294
|
-
joint_axis[axis_start],
|
|
295
|
-
joint_axis[axis_start + 1],
|
|
296
|
-
joint_q[q_start + 0],
|
|
297
|
-
joint_q[q_start + 1],
|
|
298
|
-
joint_qd[qd_start + 0],
|
|
299
|
-
joint_qd[qd_start + 1],
|
|
300
|
-
)
|
|
301
|
-
|
|
302
|
-
t = wp.transform(wp.vec3(0.0, 0.0, 0.0), rot)
|
|
303
|
-
v = wp.spatial_vector(vel_w, wp.vec3(0.0, 0.0, 0.0))
|
|
304
|
-
|
|
305
|
-
X_j = t
|
|
306
|
-
v_j = v
|
|
307
|
-
|
|
308
|
-
if type == wp.sim.JOINT_D6:
|
|
309
|
-
pos = wp.vec3(0.0)
|
|
310
|
-
rot = wp.quat_identity()
|
|
311
|
-
vel_v = wp.vec3(0.0)
|
|
312
|
-
vel_w = wp.vec3(0.0)
|
|
313
|
-
|
|
314
|
-
# unroll for loop to ensure joint actions remain differentiable
|
|
315
|
-
# (since differentiating through a for loop that updates a local variable is not supported)
|
|
316
|
-
|
|
317
|
-
if lin_axis_count > 0:
|
|
318
|
-
axis = joint_axis[axis_start + 0]
|
|
319
|
-
pos += axis * joint_q[q_start + 0]
|
|
320
|
-
vel_v += axis * joint_qd[qd_start + 0]
|
|
321
|
-
if lin_axis_count > 1:
|
|
322
|
-
axis = joint_axis[axis_start + 1]
|
|
323
|
-
pos += axis * joint_q[q_start + 1]
|
|
324
|
-
vel_v += axis * joint_qd[qd_start + 1]
|
|
325
|
-
if lin_axis_count > 2:
|
|
326
|
-
axis = joint_axis[axis_start + 2]
|
|
327
|
-
pos += axis * joint_q[q_start + 2]
|
|
328
|
-
vel_v += axis * joint_qd[qd_start + 2]
|
|
329
|
-
|
|
330
|
-
ia = axis_start + lin_axis_count
|
|
331
|
-
iq = q_start + lin_axis_count
|
|
332
|
-
iqd = qd_start + lin_axis_count
|
|
333
|
-
if ang_axis_count == 1:
|
|
334
|
-
axis = joint_axis[ia]
|
|
335
|
-
rot = wp.quat_from_axis_angle(axis, joint_q[iq])
|
|
336
|
-
vel_w = joint_qd[iqd] * axis
|
|
337
|
-
if ang_axis_count == 2:
|
|
338
|
-
rot, vel_w = compute_2d_rotational_dofs(
|
|
339
|
-
joint_axis[ia + 0],
|
|
340
|
-
joint_axis[ia + 1],
|
|
341
|
-
joint_q[iq + 0],
|
|
342
|
-
joint_q[iq + 1],
|
|
343
|
-
joint_qd[iqd + 0],
|
|
344
|
-
joint_qd[iqd + 1],
|
|
345
|
-
)
|
|
346
|
-
if ang_axis_count == 3:
|
|
347
|
-
rot, vel_w = compute_3d_rotational_dofs(
|
|
348
|
-
joint_axis[ia + 0],
|
|
349
|
-
joint_axis[ia + 1],
|
|
350
|
-
joint_axis[ia + 2],
|
|
351
|
-
joint_q[iq + 0],
|
|
352
|
-
joint_q[iq + 1],
|
|
353
|
-
joint_q[iq + 2],
|
|
354
|
-
joint_qd[iqd + 0],
|
|
355
|
-
joint_qd[iqd + 1],
|
|
356
|
-
joint_qd[iqd + 2],
|
|
357
|
-
)
|
|
358
|
-
|
|
359
|
-
X_j = wp.transform(pos, rot)
|
|
360
|
-
v_j = wp.spatial_vector(vel_w, vel_v)
|
|
361
|
-
|
|
362
|
-
# transform from world to joint anchor frame at child body
|
|
363
|
-
X_wcj = X_wpj * X_j
|
|
364
|
-
# transform from world to child body frame
|
|
365
|
-
X_wc = X_wcj * wp.transform_inverse(X_cj)
|
|
366
|
-
|
|
367
|
-
# transform velocity across the joint to world space
|
|
368
|
-
angular_vel = wp.transform_vector(X_wpj, wp.spatial_top(v_j))
|
|
369
|
-
linear_vel = wp.transform_vector(X_wpj, wp.spatial_bottom(v_j))
|
|
370
|
-
|
|
371
|
-
v_wc = v_wpj + wp.spatial_vector(angular_vel, linear_vel)
|
|
372
|
-
|
|
373
|
-
body_q[child] = X_wc
|
|
374
|
-
body_qd[child] = v_wc
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
# updates state body information based on joint coordinates
|
|
378
|
-
def eval_fk(model, joint_q, joint_qd, mask, state):
|
|
379
|
-
"""
|
|
380
|
-
Evaluates the model's forward kinematics given the joint coordinates and updates the state's body information (:attr:`State.body_q` and :attr:`State.body_qd`).
|
|
381
|
-
|
|
382
|
-
Args:
|
|
383
|
-
model (Model): The model to evaluate.
|
|
384
|
-
joint_q (array): Generalized joint position coordinates, shape [joint_coord_count], float
|
|
385
|
-
joint_qd (array): Generalized joint velocity coordinates, shape [joint_dof_count], float
|
|
386
|
-
mask (array): The mask to use to enable / disable FK for an articulation. If None then treat all as enabled, shape [articulation_count], int
|
|
387
|
-
state (State): The state to update.
|
|
388
|
-
"""
|
|
389
|
-
wp.launch(
|
|
390
|
-
kernel=eval_articulation_fk,
|
|
391
|
-
dim=model.articulation_count,
|
|
392
|
-
inputs=[
|
|
393
|
-
model.articulation_start,
|
|
394
|
-
mask,
|
|
395
|
-
joint_q,
|
|
396
|
-
joint_qd,
|
|
397
|
-
model.joint_q_start,
|
|
398
|
-
model.joint_qd_start,
|
|
399
|
-
model.joint_type,
|
|
400
|
-
model.joint_parent,
|
|
401
|
-
model.joint_child,
|
|
402
|
-
model.joint_X_p,
|
|
403
|
-
model.joint_X_c,
|
|
404
|
-
model.joint_axis,
|
|
405
|
-
model.joint_axis_start,
|
|
406
|
-
model.joint_axis_dim,
|
|
407
|
-
model.body_com,
|
|
408
|
-
],
|
|
409
|
-
outputs=[
|
|
410
|
-
state.body_q,
|
|
411
|
-
state.body_qd,
|
|
412
|
-
],
|
|
413
|
-
device=model.device,
|
|
414
|
-
)
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
@wp.func
|
|
418
|
-
def reconstruct_angular_q_qd(q_pc: wp.quat, w_err: wp.vec3, X_wp: wp.transform, axis: wp.vec3):
|
|
419
|
-
"""
|
|
420
|
-
Reconstructs the angular joint coordinates and velocities given the relative rotation and angular velocity
|
|
421
|
-
between a parent and child body.
|
|
422
|
-
|
|
423
|
-
Args:
|
|
424
|
-
q_pc (quat): The relative rotation between the parent and child body.
|
|
425
|
-
w_err (vec3): The angular velocity between the parent and child body.
|
|
426
|
-
X_wp (transform): The parent body's transform in world space.
|
|
427
|
-
axis (vec3): The joint axis in the frame of the parent body.
|
|
428
|
-
|
|
429
|
-
Returns:
|
|
430
|
-
q (float): The joint position coordinate.
|
|
431
|
-
qd (float): The joint velocity coordinate.
|
|
432
|
-
"""
|
|
433
|
-
axis_p = wp.transform_vector(X_wp, axis)
|
|
434
|
-
twist = quat_twist(axis, q_pc)
|
|
435
|
-
q = wp.acos(twist[3]) * 2.0 * wp.sign(wp.dot(axis, wp.vec3(twist[0], twist[1], twist[2])))
|
|
436
|
-
qd = wp.dot(w_err, axis_p)
|
|
437
|
-
return q, qd
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
@wp.kernel
|
|
441
|
-
def eval_articulation_ik(
|
|
442
|
-
body_q: wp.array(dtype=wp.transform),
|
|
443
|
-
body_qd: wp.array(dtype=wp.spatial_vector),
|
|
444
|
-
body_com: wp.array(dtype=wp.vec3),
|
|
445
|
-
joint_type: wp.array(dtype=int),
|
|
446
|
-
joint_parent: wp.array(dtype=int),
|
|
447
|
-
joint_child: wp.array(dtype=int),
|
|
448
|
-
joint_X_p: wp.array(dtype=wp.transform),
|
|
449
|
-
joint_X_c: wp.array(dtype=wp.transform),
|
|
450
|
-
joint_axis: wp.array(dtype=wp.vec3),
|
|
451
|
-
joint_axis_start: wp.array(dtype=int),
|
|
452
|
-
joint_axis_dim: wp.array(dtype=int, ndim=2),
|
|
453
|
-
joint_q_start: wp.array(dtype=int),
|
|
454
|
-
joint_qd_start: wp.array(dtype=int),
|
|
455
|
-
joint_q: wp.array(dtype=float),
|
|
456
|
-
joint_qd: wp.array(dtype=float),
|
|
457
|
-
):
|
|
458
|
-
tid = wp.tid()
|
|
459
|
-
|
|
460
|
-
parent = joint_parent[tid]
|
|
461
|
-
child = joint_child[tid]
|
|
462
|
-
|
|
463
|
-
X_pj = joint_X_p[tid]
|
|
464
|
-
X_cj = joint_X_c[tid]
|
|
465
|
-
|
|
466
|
-
w_p = wp.vec3()
|
|
467
|
-
v_p = wp.vec3()
|
|
468
|
-
v_wp = wp.spatial_vector()
|
|
469
|
-
|
|
470
|
-
# parent anchor frame in world space
|
|
471
|
-
X_wpj = X_pj
|
|
472
|
-
if parent >= 0:
|
|
473
|
-
X_wp = body_q[parent]
|
|
474
|
-
X_wpj = X_wp * X_pj
|
|
475
|
-
r_p = wp.transform_get_translation(X_wpj) - wp.transform_point(X_wp, body_com[parent])
|
|
476
|
-
|
|
477
|
-
v_wp = body_qd[parent]
|
|
478
|
-
w_p = wp.spatial_top(v_wp)
|
|
479
|
-
v_p = wp.spatial_bottom(v_wp) + wp.cross(w_p, r_p)
|
|
480
|
-
|
|
481
|
-
# child transform and moment arm
|
|
482
|
-
X_wc = body_q[child]
|
|
483
|
-
X_wcj = X_wc * X_cj
|
|
484
|
-
|
|
485
|
-
v_wc = body_qd[child]
|
|
486
|
-
|
|
487
|
-
w_c = wp.spatial_top(v_wc)
|
|
488
|
-
v_c = wp.spatial_bottom(v_wc)
|
|
489
|
-
|
|
490
|
-
# joint properties
|
|
491
|
-
type = joint_type[tid]
|
|
492
|
-
|
|
493
|
-
# compute position and orientation differences between anchor frames
|
|
494
|
-
x_p = wp.transform_get_translation(X_wpj)
|
|
495
|
-
x_c = wp.transform_get_translation(X_wcj)
|
|
496
|
-
|
|
497
|
-
q_p = wp.transform_get_rotation(X_wpj)
|
|
498
|
-
q_c = wp.transform_get_rotation(X_wcj)
|
|
499
|
-
|
|
500
|
-
x_err = x_c - x_p
|
|
501
|
-
v_err = v_c - v_p
|
|
502
|
-
w_err = w_c - w_p
|
|
503
|
-
|
|
504
|
-
q_start = joint_q_start[tid]
|
|
505
|
-
qd_start = joint_qd_start[tid]
|
|
506
|
-
axis_start = joint_axis_start[tid]
|
|
507
|
-
lin_axis_count = joint_axis_dim[tid, 0]
|
|
508
|
-
ang_axis_count = joint_axis_dim[tid, 1]
|
|
509
|
-
|
|
510
|
-
if type == wp.sim.JOINT_PRISMATIC:
|
|
511
|
-
axis = joint_axis[axis_start]
|
|
512
|
-
|
|
513
|
-
# world space joint axis
|
|
514
|
-
axis_p = wp.quat_rotate(q_p, axis)
|
|
515
|
-
|
|
516
|
-
# evaluate joint coordinates
|
|
517
|
-
q = wp.dot(x_err, axis_p)
|
|
518
|
-
qd = wp.dot(v_err, axis_p)
|
|
519
|
-
|
|
520
|
-
joint_q[q_start] = q
|
|
521
|
-
joint_qd[qd_start] = qd
|
|
522
|
-
|
|
523
|
-
return
|
|
524
|
-
|
|
525
|
-
if type == wp.sim.JOINT_REVOLUTE:
|
|
526
|
-
axis = joint_axis[axis_start]
|
|
527
|
-
q_pc = wp.quat_inverse(q_p) * q_c
|
|
528
|
-
|
|
529
|
-
q, qd = reconstruct_angular_q_qd(q_pc, w_err, X_wpj, axis)
|
|
530
|
-
|
|
531
|
-
joint_q[q_start] = q
|
|
532
|
-
joint_qd[qd_start] = qd
|
|
533
|
-
|
|
534
|
-
return
|
|
535
|
-
|
|
536
|
-
if type == wp.sim.JOINT_BALL:
|
|
537
|
-
q_pc = wp.quat_inverse(q_p) * q_c
|
|
538
|
-
|
|
539
|
-
joint_q[q_start + 0] = q_pc[0]
|
|
540
|
-
joint_q[q_start + 1] = q_pc[1]
|
|
541
|
-
joint_q[q_start + 2] = q_pc[2]
|
|
542
|
-
joint_q[q_start + 3] = q_pc[3]
|
|
543
|
-
|
|
544
|
-
ang_vel = wp.transform_vector(wp.transform_inverse(X_wpj), w_err)
|
|
545
|
-
joint_qd[qd_start + 0] = ang_vel[0]
|
|
546
|
-
joint_qd[qd_start + 1] = ang_vel[1]
|
|
547
|
-
joint_qd[qd_start + 2] = ang_vel[2]
|
|
548
|
-
|
|
549
|
-
return
|
|
550
|
-
|
|
551
|
-
if type == wp.sim.JOINT_FIXED:
|
|
552
|
-
return
|
|
553
|
-
|
|
554
|
-
if type == wp.sim.JOINT_FREE or type == wp.sim.JOINT_DISTANCE:
|
|
555
|
-
q_pc = wp.quat_inverse(q_p) * q_c
|
|
556
|
-
|
|
557
|
-
x_err_c = wp.quat_rotate_inv(q_p, x_err)
|
|
558
|
-
v_err_c = wp.quat_rotate_inv(q_p, v_err)
|
|
559
|
-
w_err_c = wp.quat_rotate_inv(q_p, w_err)
|
|
560
|
-
|
|
561
|
-
joint_q[q_start + 0] = x_err_c[0]
|
|
562
|
-
joint_q[q_start + 1] = x_err_c[1]
|
|
563
|
-
joint_q[q_start + 2] = x_err_c[2]
|
|
564
|
-
|
|
565
|
-
joint_q[q_start + 3] = q_pc[0]
|
|
566
|
-
joint_q[q_start + 4] = q_pc[1]
|
|
567
|
-
joint_q[q_start + 5] = q_pc[2]
|
|
568
|
-
joint_q[q_start + 6] = q_pc[3]
|
|
569
|
-
|
|
570
|
-
joint_qd[qd_start + 0] = w_err_c[0]
|
|
571
|
-
joint_qd[qd_start + 1] = w_err_c[1]
|
|
572
|
-
joint_qd[qd_start + 2] = w_err_c[2]
|
|
573
|
-
|
|
574
|
-
joint_qd[qd_start + 3] = v_err_c[0]
|
|
575
|
-
joint_qd[qd_start + 4] = v_err_c[1]
|
|
576
|
-
joint_qd[qd_start + 5] = v_err_c[2]
|
|
577
|
-
|
|
578
|
-
return
|
|
579
|
-
|
|
580
|
-
if type == wp.sim.JOINT_COMPOUND:
|
|
581
|
-
axis_0 = joint_axis[axis_start + 0]
|
|
582
|
-
axis_1 = joint_axis[axis_start + 1]
|
|
583
|
-
axis_2 = joint_axis[axis_start + 2]
|
|
584
|
-
qs, qds = invert_3d_rotational_dofs(axis_0, axis_1, axis_2, q_p, q_c, w_err)
|
|
585
|
-
joint_q[q_start + 0] = qs[0]
|
|
586
|
-
joint_q[q_start + 1] = qs[1]
|
|
587
|
-
joint_q[q_start + 2] = qs[2]
|
|
588
|
-
joint_qd[qd_start + 0] = qds[0]
|
|
589
|
-
joint_qd[qd_start + 1] = qds[1]
|
|
590
|
-
joint_qd[qd_start + 2] = qds[2]
|
|
591
|
-
|
|
592
|
-
return
|
|
593
|
-
|
|
594
|
-
if type == wp.sim.JOINT_UNIVERSAL:
|
|
595
|
-
axis_0 = joint_axis[axis_start + 0]
|
|
596
|
-
axis_1 = joint_axis[axis_start + 1]
|
|
597
|
-
qs2, qds2 = invert_2d_rotational_dofs(axis_0, axis_1, q_p, q_c, w_err)
|
|
598
|
-
joint_q[q_start + 0] = qs2[0]
|
|
599
|
-
joint_q[q_start + 1] = qs2[1]
|
|
600
|
-
joint_qd[qd_start + 0] = qds2[0]
|
|
601
|
-
joint_qd[qd_start + 1] = qds2[1]
|
|
602
|
-
|
|
603
|
-
return
|
|
604
|
-
|
|
605
|
-
if type == wp.sim.JOINT_D6:
|
|
606
|
-
x_err_c = wp.quat_rotate_inv(q_p, x_err)
|
|
607
|
-
v_err_c = wp.quat_rotate_inv(q_p, v_err)
|
|
608
|
-
if lin_axis_count > 0:
|
|
609
|
-
axis = joint_axis[axis_start + 0]
|
|
610
|
-
joint_q[q_start + 0] = wp.dot(x_err_c, axis)
|
|
611
|
-
joint_qd[qd_start + 0] = wp.dot(v_err_c, axis)
|
|
612
|
-
|
|
613
|
-
if lin_axis_count > 1:
|
|
614
|
-
axis = joint_axis[axis_start + 1]
|
|
615
|
-
joint_q[q_start + 1] = wp.dot(x_err_c, axis)
|
|
616
|
-
joint_qd[qd_start + 1] = wp.dot(v_err_c, axis)
|
|
617
|
-
|
|
618
|
-
if lin_axis_count > 2:
|
|
619
|
-
axis = joint_axis[axis_start + 2]
|
|
620
|
-
joint_q[q_start + 2] = wp.dot(x_err_c, axis)
|
|
621
|
-
joint_qd[qd_start + 2] = wp.dot(v_err_c, axis)
|
|
622
|
-
|
|
623
|
-
if ang_axis_count == 1:
|
|
624
|
-
axis = joint_axis[axis_start]
|
|
625
|
-
q_pc = wp.quat_inverse(q_p) * q_c
|
|
626
|
-
q, qd = reconstruct_angular_q_qd(q_pc, w_err, X_wpj, joint_axis[axis_start + lin_axis_count])
|
|
627
|
-
joint_q[q_start + lin_axis_count] = q
|
|
628
|
-
joint_qd[qd_start + lin_axis_count] = qd
|
|
629
|
-
|
|
630
|
-
if ang_axis_count == 2:
|
|
631
|
-
axis_0 = joint_axis[axis_start + lin_axis_count + 0]
|
|
632
|
-
axis_1 = joint_axis[axis_start + lin_axis_count + 1]
|
|
633
|
-
qs2, qds2 = invert_2d_rotational_dofs(axis_0, axis_1, q_p, q_c, w_err)
|
|
634
|
-
joint_q[q_start + lin_axis_count + 0] = qs2[0]
|
|
635
|
-
joint_q[q_start + lin_axis_count + 1] = qs2[1]
|
|
636
|
-
joint_qd[qd_start + lin_axis_count + 0] = qds2[0]
|
|
637
|
-
joint_qd[qd_start + lin_axis_count + 1] = qds2[1]
|
|
638
|
-
|
|
639
|
-
if ang_axis_count == 3:
|
|
640
|
-
axis_0 = joint_axis[axis_start + lin_axis_count + 0]
|
|
641
|
-
axis_1 = joint_axis[axis_start + lin_axis_count + 1]
|
|
642
|
-
axis_2 = joint_axis[axis_start + lin_axis_count + 2]
|
|
643
|
-
qs3, qds3 = invert_3d_rotational_dofs(axis_0, axis_1, axis_2, q_p, q_c, w_err)
|
|
644
|
-
joint_q[q_start + lin_axis_count + 0] = qs3[0]
|
|
645
|
-
joint_q[q_start + lin_axis_count + 1] = qs3[1]
|
|
646
|
-
joint_q[q_start + lin_axis_count + 2] = qs3[2]
|
|
647
|
-
joint_qd[qd_start + lin_axis_count + 0] = qds3[0]
|
|
648
|
-
joint_qd[qd_start + lin_axis_count + 1] = qds3[1]
|
|
649
|
-
joint_qd[qd_start + lin_axis_count + 2] = qds3[2]
|
|
650
|
-
|
|
651
|
-
return
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
# given maximal coordinate model computes ik (closest point projection)
|
|
655
|
-
def eval_ik(model, state, joint_q, joint_qd):
|
|
656
|
-
"""
|
|
657
|
-
Evaluates the model's inverse kinematics given the state's body information (:attr:`State.body_q` and :attr:`State.body_qd`) and updates the generalized joint coordinates `joint_q` and `joint_qd`.
|
|
658
|
-
|
|
659
|
-
Args:
|
|
660
|
-
model (Model): The model to evaluate.
|
|
661
|
-
state (State): The state with the body's maximal coordinates (positions :attr:`State.body_q` and velocities :attr:`State.body_qd`) to use.
|
|
662
|
-
joint_q (array): Generalized joint position coordinates, shape [joint_coord_count], float
|
|
663
|
-
joint_qd (array): Generalized joint velocity coordinates, shape [joint_dof_count], float
|
|
664
|
-
"""
|
|
665
|
-
wp.launch(
|
|
666
|
-
kernel=eval_articulation_ik,
|
|
667
|
-
dim=model.joint_count,
|
|
668
|
-
inputs=[
|
|
669
|
-
state.body_q,
|
|
670
|
-
state.body_qd,
|
|
671
|
-
model.body_com,
|
|
672
|
-
model.joint_type,
|
|
673
|
-
model.joint_parent,
|
|
674
|
-
model.joint_child,
|
|
675
|
-
model.joint_X_p,
|
|
676
|
-
model.joint_X_c,
|
|
677
|
-
model.joint_axis,
|
|
678
|
-
model.joint_axis_start,
|
|
679
|
-
model.joint_axis_dim,
|
|
680
|
-
model.joint_q_start,
|
|
681
|
-
model.joint_qd_start,
|
|
682
|
-
],
|
|
683
|
-
outputs=[joint_q, joint_qd],
|
|
684
|
-
device=model.device,
|
|
685
|
-
)
|
|
1
|
+
# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
+
# and proprietary rights in and to this software, related documentation
|
|
4
|
+
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
+
# distribution of this software and related documentation without an express
|
|
6
|
+
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
+
|
|
8
|
+
import warp as wp
|
|
9
|
+
|
|
10
|
+
from .utils import quat_decompose, quat_twist
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@wp.func
|
|
14
|
+
def compute_2d_rotational_dofs(
|
|
15
|
+
axis_0: wp.vec3,
|
|
16
|
+
axis_1: wp.vec3,
|
|
17
|
+
q0: float,
|
|
18
|
+
q1: float,
|
|
19
|
+
qd0: float,
|
|
20
|
+
qd1: float,
|
|
21
|
+
):
|
|
22
|
+
"""
|
|
23
|
+
Computes the rotation quaternion and 3D angular velocity given the joint axes, coordinates and velocities.
|
|
24
|
+
"""
|
|
25
|
+
q_off = wp.quat_from_matrix(wp.mat33(axis_0, axis_1, wp.cross(axis_0, axis_1)))
|
|
26
|
+
|
|
27
|
+
# body local axes
|
|
28
|
+
local_0 = wp.quat_rotate(q_off, wp.vec3(1.0, 0.0, 0.0))
|
|
29
|
+
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
30
|
+
|
|
31
|
+
axis_0 = local_0
|
|
32
|
+
q_0 = wp.quat_from_axis_angle(axis_0, q0)
|
|
33
|
+
|
|
34
|
+
axis_1 = wp.quat_rotate(q_0, local_1)
|
|
35
|
+
q_1 = wp.quat_from_axis_angle(axis_1, q1)
|
|
36
|
+
|
|
37
|
+
rot = q_1 * q_0
|
|
38
|
+
|
|
39
|
+
vel = axis_0 * qd0 + axis_1 * qd1
|
|
40
|
+
|
|
41
|
+
return rot, vel
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@wp.func
|
|
45
|
+
def invert_2d_rotational_dofs(
|
|
46
|
+
axis_0: wp.vec3,
|
|
47
|
+
axis_1: wp.vec3,
|
|
48
|
+
q_p: wp.quat,
|
|
49
|
+
q_c: wp.quat,
|
|
50
|
+
w_err: wp.vec3,
|
|
51
|
+
):
|
|
52
|
+
"""
|
|
53
|
+
Computes generalized joint position and velocity coordinates for a 2D rotational joint given the joint axes, relative orientations and angular velocity differences between the two bodies the joint connects.
|
|
54
|
+
"""
|
|
55
|
+
q_off = wp.quat_from_matrix(wp.mat33(axis_0, axis_1, wp.cross(axis_0, axis_1)))
|
|
56
|
+
q_pc = wp.quat_inverse(q_off) * wp.quat_inverse(q_p) * q_c * q_off
|
|
57
|
+
|
|
58
|
+
# decompose to a compound rotation each axis
|
|
59
|
+
angles = quat_decompose(q_pc)
|
|
60
|
+
|
|
61
|
+
# find rotation axes
|
|
62
|
+
local_0 = wp.quat_rotate(q_off, wp.vec3(1.0, 0.0, 0.0))
|
|
63
|
+
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
64
|
+
local_2 = wp.quat_rotate(q_off, wp.vec3(0.0, 0.0, 1.0))
|
|
65
|
+
|
|
66
|
+
axis_0 = local_0
|
|
67
|
+
q_0 = wp.quat_from_axis_angle(axis_0, angles[0])
|
|
68
|
+
|
|
69
|
+
axis_1 = wp.quat_rotate(q_0, local_1)
|
|
70
|
+
q_1 = wp.quat_from_axis_angle(axis_1, angles[1])
|
|
71
|
+
|
|
72
|
+
axis_2 = wp.quat_rotate(q_1 * q_0, local_2)
|
|
73
|
+
|
|
74
|
+
# convert angular velocity to local space
|
|
75
|
+
w_err_p = wp.quat_rotate_inv(q_p, w_err)
|
|
76
|
+
|
|
77
|
+
# given joint axes and angular velocity error, solve for joint velocities
|
|
78
|
+
c12 = wp.cross(axis_1, axis_2)
|
|
79
|
+
c02 = wp.cross(axis_0, axis_2)
|
|
80
|
+
|
|
81
|
+
vel = wp.vec2(wp.dot(w_err_p, c12) / wp.dot(axis_0, c12), wp.dot(w_err_p, c02) / wp.dot(axis_1, c02))
|
|
82
|
+
|
|
83
|
+
return wp.vec2(angles[0], angles[1]), vel
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@wp.func
|
|
87
|
+
def compute_3d_rotational_dofs(
|
|
88
|
+
axis_0: wp.vec3,
|
|
89
|
+
axis_1: wp.vec3,
|
|
90
|
+
axis_2: wp.vec3,
|
|
91
|
+
q0: float,
|
|
92
|
+
q1: float,
|
|
93
|
+
q2: float,
|
|
94
|
+
qd0: float,
|
|
95
|
+
qd1: float,
|
|
96
|
+
qd2: float,
|
|
97
|
+
):
|
|
98
|
+
"""
|
|
99
|
+
Computes the rotation quaternion and 3D angular velocity given the joint axes, coordinates and velocities.
|
|
100
|
+
"""
|
|
101
|
+
q_off = wp.quat_from_matrix(wp.mat33(axis_0, axis_1, axis_2))
|
|
102
|
+
|
|
103
|
+
# body local axes
|
|
104
|
+
local_0 = wp.quat_rotate(q_off, wp.vec3(1.0, 0.0, 0.0))
|
|
105
|
+
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
106
|
+
local_2 = wp.quat_rotate(q_off, wp.vec3(0.0, 0.0, 1.0))
|
|
107
|
+
|
|
108
|
+
# reconstruct rotation axes
|
|
109
|
+
axis_0 = local_0
|
|
110
|
+
q_0 = wp.quat_from_axis_angle(axis_0, q0)
|
|
111
|
+
|
|
112
|
+
axis_1 = wp.quat_rotate(q_0, local_1)
|
|
113
|
+
q_1 = wp.quat_from_axis_angle(axis_1, q1)
|
|
114
|
+
|
|
115
|
+
axis_2 = wp.quat_rotate(q_1 * q_0, local_2)
|
|
116
|
+
q_2 = wp.quat_from_axis_angle(axis_2, q2)
|
|
117
|
+
|
|
118
|
+
rot = q_2 * q_1 * q_0
|
|
119
|
+
vel = axis_0 * qd0 + axis_1 * qd1 + axis_2 * qd2
|
|
120
|
+
|
|
121
|
+
return rot, vel
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@wp.func
|
|
125
|
+
def invert_3d_rotational_dofs(
|
|
126
|
+
axis_0: wp.vec3, axis_1: wp.vec3, axis_2: wp.vec3, q_p: wp.quat, q_c: wp.quat, w_err: wp.vec3
|
|
127
|
+
):
|
|
128
|
+
"""
|
|
129
|
+
Computes generalized joint position and velocity coordinates for a 3D rotational joint given the joint axes, relative orientations and angular velocity differences between the two bodies the joint connects.
|
|
130
|
+
"""
|
|
131
|
+
q_off = wp.quat_from_matrix(wp.mat33(axis_0, axis_1, axis_2))
|
|
132
|
+
q_pc = wp.quat_inverse(q_off) * wp.quat_inverse(q_p) * q_c * q_off
|
|
133
|
+
|
|
134
|
+
# decompose to a compound rotation each axis
|
|
135
|
+
angles = quat_decompose(q_pc)
|
|
136
|
+
|
|
137
|
+
# find rotation axes
|
|
138
|
+
local_0 = wp.quat_rotate(q_off, wp.vec3(1.0, 0.0, 0.0))
|
|
139
|
+
local_1 = wp.quat_rotate(q_off, wp.vec3(0.0, 1.0, 0.0))
|
|
140
|
+
local_2 = wp.quat_rotate(q_off, wp.vec3(0.0, 0.0, 1.0))
|
|
141
|
+
|
|
142
|
+
axis_0 = local_0
|
|
143
|
+
q_0 = wp.quat_from_axis_angle(axis_0, angles[0])
|
|
144
|
+
|
|
145
|
+
axis_1 = wp.quat_rotate(q_0, local_1)
|
|
146
|
+
q_1 = wp.quat_from_axis_angle(axis_1, angles[1])
|
|
147
|
+
|
|
148
|
+
axis_2 = wp.quat_rotate(q_1 * q_0, local_2)
|
|
149
|
+
|
|
150
|
+
# convert angular velocity to local space
|
|
151
|
+
w_err_p = wp.quat_rotate_inv(q_p, w_err)
|
|
152
|
+
|
|
153
|
+
# given joint axes and angular velocity error, solve for joint velocities
|
|
154
|
+
c12 = wp.cross(axis_1, axis_2)
|
|
155
|
+
c02 = wp.cross(axis_0, axis_2)
|
|
156
|
+
c01 = wp.cross(axis_0, axis_1)
|
|
157
|
+
|
|
158
|
+
velocities = wp.vec3(
|
|
159
|
+
wp.dot(w_err_p, c12) / wp.dot(axis_0, c12),
|
|
160
|
+
wp.dot(w_err_p, c02) / wp.dot(axis_1, c02),
|
|
161
|
+
wp.dot(w_err_p, c01) / wp.dot(axis_2, c01),
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
return angles, velocities
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@wp.kernel
|
|
168
|
+
def eval_articulation_fk(
|
|
169
|
+
articulation_start: wp.array(dtype=int),
|
|
170
|
+
articulation_mask: wp.array(
|
|
171
|
+
dtype=int
|
|
172
|
+
), # used to enable / disable FK for an articulation, if None then treat all as enabled
|
|
173
|
+
joint_q: wp.array(dtype=float),
|
|
174
|
+
joint_qd: wp.array(dtype=float),
|
|
175
|
+
joint_q_start: wp.array(dtype=int),
|
|
176
|
+
joint_qd_start: wp.array(dtype=int),
|
|
177
|
+
joint_type: wp.array(dtype=int),
|
|
178
|
+
joint_parent: wp.array(dtype=int),
|
|
179
|
+
joint_child: wp.array(dtype=int),
|
|
180
|
+
joint_X_p: wp.array(dtype=wp.transform),
|
|
181
|
+
joint_X_c: wp.array(dtype=wp.transform),
|
|
182
|
+
joint_axis: wp.array(dtype=wp.vec3),
|
|
183
|
+
joint_axis_start: wp.array(dtype=int),
|
|
184
|
+
joint_axis_dim: wp.array(dtype=int, ndim=2),
|
|
185
|
+
body_com: wp.array(dtype=wp.vec3),
|
|
186
|
+
# outputs
|
|
187
|
+
body_q: wp.array(dtype=wp.transform),
|
|
188
|
+
body_qd: wp.array(dtype=wp.spatial_vector),
|
|
189
|
+
):
|
|
190
|
+
tid = wp.tid()
|
|
191
|
+
|
|
192
|
+
# early out if disabling FK for this articulation
|
|
193
|
+
if articulation_mask:
|
|
194
|
+
if articulation_mask[tid] == 0:
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
joint_start = articulation_start[tid]
|
|
198
|
+
joint_end = articulation_start[tid + 1]
|
|
199
|
+
|
|
200
|
+
for i in range(joint_start, joint_end):
|
|
201
|
+
parent = joint_parent[i]
|
|
202
|
+
child = joint_child[i]
|
|
203
|
+
|
|
204
|
+
# compute transform across the joint
|
|
205
|
+
type = joint_type[i]
|
|
206
|
+
|
|
207
|
+
X_pj = joint_X_p[i]
|
|
208
|
+
X_cj = joint_X_c[i]
|
|
209
|
+
|
|
210
|
+
# parent anchor frame in world space
|
|
211
|
+
X_wpj = X_pj
|
|
212
|
+
# velocity of parent anchor point in world space
|
|
213
|
+
v_wpj = wp.spatial_vector()
|
|
214
|
+
if parent >= 0:
|
|
215
|
+
X_wp = body_q[parent]
|
|
216
|
+
X_wpj = X_wp * X_wpj
|
|
217
|
+
r_p = wp.transform_get_translation(X_wpj) - wp.transform_point(X_wp, body_com[parent])
|
|
218
|
+
|
|
219
|
+
v_wp = body_qd[parent]
|
|
220
|
+
w_p = wp.spatial_top(v_wp)
|
|
221
|
+
v_p = wp.spatial_bottom(v_wp) + wp.cross(w_p, r_p)
|
|
222
|
+
v_wpj = wp.spatial_vector(w_p, v_p)
|
|
223
|
+
|
|
224
|
+
q_start = joint_q_start[i]
|
|
225
|
+
qd_start = joint_qd_start[i]
|
|
226
|
+
axis_start = joint_axis_start[i]
|
|
227
|
+
lin_axis_count = joint_axis_dim[i, 0]
|
|
228
|
+
ang_axis_count = joint_axis_dim[i, 1]
|
|
229
|
+
|
|
230
|
+
X_j = wp.transform_identity()
|
|
231
|
+
v_j = wp.spatial_vector(wp.vec3(), wp.vec3())
|
|
232
|
+
|
|
233
|
+
if type == wp.sim.JOINT_PRISMATIC:
|
|
234
|
+
axis = joint_axis[axis_start]
|
|
235
|
+
|
|
236
|
+
q = joint_q[q_start]
|
|
237
|
+
qd = joint_qd[qd_start]
|
|
238
|
+
|
|
239
|
+
X_j = wp.transform(axis * q, wp.quat_identity())
|
|
240
|
+
v_j = wp.spatial_vector(wp.vec3(), axis * qd)
|
|
241
|
+
|
|
242
|
+
if type == wp.sim.JOINT_REVOLUTE:
|
|
243
|
+
axis = joint_axis[axis_start]
|
|
244
|
+
|
|
245
|
+
q = joint_q[q_start]
|
|
246
|
+
qd = joint_qd[qd_start]
|
|
247
|
+
|
|
248
|
+
X_j = wp.transform(wp.vec3(), wp.quat_from_axis_angle(axis, q))
|
|
249
|
+
v_j = wp.spatial_vector(axis * qd, wp.vec3())
|
|
250
|
+
|
|
251
|
+
if type == wp.sim.JOINT_BALL:
|
|
252
|
+
r = wp.quat(joint_q[q_start + 0], joint_q[q_start + 1], joint_q[q_start + 2], joint_q[q_start + 3])
|
|
253
|
+
|
|
254
|
+
w = wp.vec3(joint_qd[qd_start + 0], joint_qd[qd_start + 1], joint_qd[qd_start + 2])
|
|
255
|
+
|
|
256
|
+
X_j = wp.transform(wp.vec3(), r)
|
|
257
|
+
v_j = wp.spatial_vector(w, wp.vec3())
|
|
258
|
+
|
|
259
|
+
if type == wp.sim.JOINT_FREE or type == wp.sim.JOINT_DISTANCE:
|
|
260
|
+
t = wp.transform(
|
|
261
|
+
wp.vec3(joint_q[q_start + 0], joint_q[q_start + 1], joint_q[q_start + 2]),
|
|
262
|
+
wp.quat(joint_q[q_start + 3], joint_q[q_start + 4], joint_q[q_start + 5], joint_q[q_start + 6]),
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
v = wp.spatial_vector(
|
|
266
|
+
wp.vec3(joint_qd[qd_start + 0], joint_qd[qd_start + 1], joint_qd[qd_start + 2]),
|
|
267
|
+
wp.vec3(joint_qd[qd_start + 3], joint_qd[qd_start + 4], joint_qd[qd_start + 5]),
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
X_j = t
|
|
271
|
+
v_j = v
|
|
272
|
+
|
|
273
|
+
if type == wp.sim.JOINT_COMPOUND:
|
|
274
|
+
rot, vel_w = compute_3d_rotational_dofs(
|
|
275
|
+
joint_axis[axis_start],
|
|
276
|
+
joint_axis[axis_start + 1],
|
|
277
|
+
joint_axis[axis_start + 2],
|
|
278
|
+
joint_q[q_start + 0],
|
|
279
|
+
joint_q[q_start + 1],
|
|
280
|
+
joint_q[q_start + 2],
|
|
281
|
+
joint_qd[qd_start + 0],
|
|
282
|
+
joint_qd[qd_start + 1],
|
|
283
|
+
joint_qd[qd_start + 2],
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
t = wp.transform(wp.vec3(0.0, 0.0, 0.0), rot)
|
|
287
|
+
v = wp.spatial_vector(vel_w, wp.vec3(0.0, 0.0, 0.0))
|
|
288
|
+
|
|
289
|
+
X_j = t
|
|
290
|
+
v_j = v
|
|
291
|
+
|
|
292
|
+
if type == wp.sim.JOINT_UNIVERSAL:
|
|
293
|
+
rot, vel_w = compute_2d_rotational_dofs(
|
|
294
|
+
joint_axis[axis_start],
|
|
295
|
+
joint_axis[axis_start + 1],
|
|
296
|
+
joint_q[q_start + 0],
|
|
297
|
+
joint_q[q_start + 1],
|
|
298
|
+
joint_qd[qd_start + 0],
|
|
299
|
+
joint_qd[qd_start + 1],
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
t = wp.transform(wp.vec3(0.0, 0.0, 0.0), rot)
|
|
303
|
+
v = wp.spatial_vector(vel_w, wp.vec3(0.0, 0.0, 0.0))
|
|
304
|
+
|
|
305
|
+
X_j = t
|
|
306
|
+
v_j = v
|
|
307
|
+
|
|
308
|
+
if type == wp.sim.JOINT_D6:
|
|
309
|
+
pos = wp.vec3(0.0)
|
|
310
|
+
rot = wp.quat_identity()
|
|
311
|
+
vel_v = wp.vec3(0.0)
|
|
312
|
+
vel_w = wp.vec3(0.0)
|
|
313
|
+
|
|
314
|
+
# unroll for loop to ensure joint actions remain differentiable
|
|
315
|
+
# (since differentiating through a for loop that updates a local variable is not supported)
|
|
316
|
+
|
|
317
|
+
if lin_axis_count > 0:
|
|
318
|
+
axis = joint_axis[axis_start + 0]
|
|
319
|
+
pos += axis * joint_q[q_start + 0]
|
|
320
|
+
vel_v += axis * joint_qd[qd_start + 0]
|
|
321
|
+
if lin_axis_count > 1:
|
|
322
|
+
axis = joint_axis[axis_start + 1]
|
|
323
|
+
pos += axis * joint_q[q_start + 1]
|
|
324
|
+
vel_v += axis * joint_qd[qd_start + 1]
|
|
325
|
+
if lin_axis_count > 2:
|
|
326
|
+
axis = joint_axis[axis_start + 2]
|
|
327
|
+
pos += axis * joint_q[q_start + 2]
|
|
328
|
+
vel_v += axis * joint_qd[qd_start + 2]
|
|
329
|
+
|
|
330
|
+
ia = axis_start + lin_axis_count
|
|
331
|
+
iq = q_start + lin_axis_count
|
|
332
|
+
iqd = qd_start + lin_axis_count
|
|
333
|
+
if ang_axis_count == 1:
|
|
334
|
+
axis = joint_axis[ia]
|
|
335
|
+
rot = wp.quat_from_axis_angle(axis, joint_q[iq])
|
|
336
|
+
vel_w = joint_qd[iqd] * axis
|
|
337
|
+
if ang_axis_count == 2:
|
|
338
|
+
rot, vel_w = compute_2d_rotational_dofs(
|
|
339
|
+
joint_axis[ia + 0],
|
|
340
|
+
joint_axis[ia + 1],
|
|
341
|
+
joint_q[iq + 0],
|
|
342
|
+
joint_q[iq + 1],
|
|
343
|
+
joint_qd[iqd + 0],
|
|
344
|
+
joint_qd[iqd + 1],
|
|
345
|
+
)
|
|
346
|
+
if ang_axis_count == 3:
|
|
347
|
+
rot, vel_w = compute_3d_rotational_dofs(
|
|
348
|
+
joint_axis[ia + 0],
|
|
349
|
+
joint_axis[ia + 1],
|
|
350
|
+
joint_axis[ia + 2],
|
|
351
|
+
joint_q[iq + 0],
|
|
352
|
+
joint_q[iq + 1],
|
|
353
|
+
joint_q[iq + 2],
|
|
354
|
+
joint_qd[iqd + 0],
|
|
355
|
+
joint_qd[iqd + 1],
|
|
356
|
+
joint_qd[iqd + 2],
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
X_j = wp.transform(pos, rot)
|
|
360
|
+
v_j = wp.spatial_vector(vel_w, vel_v)
|
|
361
|
+
|
|
362
|
+
# transform from world to joint anchor frame at child body
|
|
363
|
+
X_wcj = X_wpj * X_j
|
|
364
|
+
# transform from world to child body frame
|
|
365
|
+
X_wc = X_wcj * wp.transform_inverse(X_cj)
|
|
366
|
+
|
|
367
|
+
# transform velocity across the joint to world space
|
|
368
|
+
angular_vel = wp.transform_vector(X_wpj, wp.spatial_top(v_j))
|
|
369
|
+
linear_vel = wp.transform_vector(X_wpj, wp.spatial_bottom(v_j))
|
|
370
|
+
|
|
371
|
+
v_wc = v_wpj + wp.spatial_vector(angular_vel, linear_vel)
|
|
372
|
+
|
|
373
|
+
body_q[child] = X_wc
|
|
374
|
+
body_qd[child] = v_wc
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
# updates state body information based on joint coordinates
|
|
378
|
+
def eval_fk(model, joint_q, joint_qd, mask, state):
|
|
379
|
+
"""
|
|
380
|
+
Evaluates the model's forward kinematics given the joint coordinates and updates the state's body information (:attr:`State.body_q` and :attr:`State.body_qd`).
|
|
381
|
+
|
|
382
|
+
Args:
|
|
383
|
+
model (Model): The model to evaluate.
|
|
384
|
+
joint_q (array): Generalized joint position coordinates, shape [joint_coord_count], float
|
|
385
|
+
joint_qd (array): Generalized joint velocity coordinates, shape [joint_dof_count], float
|
|
386
|
+
mask (array): The mask to use to enable / disable FK for an articulation. If None then treat all as enabled, shape [articulation_count], int
|
|
387
|
+
state (State): The state to update.
|
|
388
|
+
"""
|
|
389
|
+
wp.launch(
|
|
390
|
+
kernel=eval_articulation_fk,
|
|
391
|
+
dim=model.articulation_count,
|
|
392
|
+
inputs=[
|
|
393
|
+
model.articulation_start,
|
|
394
|
+
mask,
|
|
395
|
+
joint_q,
|
|
396
|
+
joint_qd,
|
|
397
|
+
model.joint_q_start,
|
|
398
|
+
model.joint_qd_start,
|
|
399
|
+
model.joint_type,
|
|
400
|
+
model.joint_parent,
|
|
401
|
+
model.joint_child,
|
|
402
|
+
model.joint_X_p,
|
|
403
|
+
model.joint_X_c,
|
|
404
|
+
model.joint_axis,
|
|
405
|
+
model.joint_axis_start,
|
|
406
|
+
model.joint_axis_dim,
|
|
407
|
+
model.body_com,
|
|
408
|
+
],
|
|
409
|
+
outputs=[
|
|
410
|
+
state.body_q,
|
|
411
|
+
state.body_qd,
|
|
412
|
+
],
|
|
413
|
+
device=model.device,
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
@wp.func
|
|
418
|
+
def reconstruct_angular_q_qd(q_pc: wp.quat, w_err: wp.vec3, X_wp: wp.transform, axis: wp.vec3):
|
|
419
|
+
"""
|
|
420
|
+
Reconstructs the angular joint coordinates and velocities given the relative rotation and angular velocity
|
|
421
|
+
between a parent and child body.
|
|
422
|
+
|
|
423
|
+
Args:
|
|
424
|
+
q_pc (quat): The relative rotation between the parent and child body.
|
|
425
|
+
w_err (vec3): The angular velocity between the parent and child body.
|
|
426
|
+
X_wp (transform): The parent body's transform in world space.
|
|
427
|
+
axis (vec3): The joint axis in the frame of the parent body.
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
q (float): The joint position coordinate.
|
|
431
|
+
qd (float): The joint velocity coordinate.
|
|
432
|
+
"""
|
|
433
|
+
axis_p = wp.transform_vector(X_wp, axis)
|
|
434
|
+
twist = quat_twist(axis, q_pc)
|
|
435
|
+
q = wp.acos(twist[3]) * 2.0 * wp.sign(wp.dot(axis, wp.vec3(twist[0], twist[1], twist[2])))
|
|
436
|
+
qd = wp.dot(w_err, axis_p)
|
|
437
|
+
return q, qd
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
@wp.kernel
|
|
441
|
+
def eval_articulation_ik(
|
|
442
|
+
body_q: wp.array(dtype=wp.transform),
|
|
443
|
+
body_qd: wp.array(dtype=wp.spatial_vector),
|
|
444
|
+
body_com: wp.array(dtype=wp.vec3),
|
|
445
|
+
joint_type: wp.array(dtype=int),
|
|
446
|
+
joint_parent: wp.array(dtype=int),
|
|
447
|
+
joint_child: wp.array(dtype=int),
|
|
448
|
+
joint_X_p: wp.array(dtype=wp.transform),
|
|
449
|
+
joint_X_c: wp.array(dtype=wp.transform),
|
|
450
|
+
joint_axis: wp.array(dtype=wp.vec3),
|
|
451
|
+
joint_axis_start: wp.array(dtype=int),
|
|
452
|
+
joint_axis_dim: wp.array(dtype=int, ndim=2),
|
|
453
|
+
joint_q_start: wp.array(dtype=int),
|
|
454
|
+
joint_qd_start: wp.array(dtype=int),
|
|
455
|
+
joint_q: wp.array(dtype=float),
|
|
456
|
+
joint_qd: wp.array(dtype=float),
|
|
457
|
+
):
|
|
458
|
+
tid = wp.tid()
|
|
459
|
+
|
|
460
|
+
parent = joint_parent[tid]
|
|
461
|
+
child = joint_child[tid]
|
|
462
|
+
|
|
463
|
+
X_pj = joint_X_p[tid]
|
|
464
|
+
X_cj = joint_X_c[tid]
|
|
465
|
+
|
|
466
|
+
w_p = wp.vec3()
|
|
467
|
+
v_p = wp.vec3()
|
|
468
|
+
v_wp = wp.spatial_vector()
|
|
469
|
+
|
|
470
|
+
# parent anchor frame in world space
|
|
471
|
+
X_wpj = X_pj
|
|
472
|
+
if parent >= 0:
|
|
473
|
+
X_wp = body_q[parent]
|
|
474
|
+
X_wpj = X_wp * X_pj
|
|
475
|
+
r_p = wp.transform_get_translation(X_wpj) - wp.transform_point(X_wp, body_com[parent])
|
|
476
|
+
|
|
477
|
+
v_wp = body_qd[parent]
|
|
478
|
+
w_p = wp.spatial_top(v_wp)
|
|
479
|
+
v_p = wp.spatial_bottom(v_wp) + wp.cross(w_p, r_p)
|
|
480
|
+
|
|
481
|
+
# child transform and moment arm
|
|
482
|
+
X_wc = body_q[child]
|
|
483
|
+
X_wcj = X_wc * X_cj
|
|
484
|
+
|
|
485
|
+
v_wc = body_qd[child]
|
|
486
|
+
|
|
487
|
+
w_c = wp.spatial_top(v_wc)
|
|
488
|
+
v_c = wp.spatial_bottom(v_wc)
|
|
489
|
+
|
|
490
|
+
# joint properties
|
|
491
|
+
type = joint_type[tid]
|
|
492
|
+
|
|
493
|
+
# compute position and orientation differences between anchor frames
|
|
494
|
+
x_p = wp.transform_get_translation(X_wpj)
|
|
495
|
+
x_c = wp.transform_get_translation(X_wcj)
|
|
496
|
+
|
|
497
|
+
q_p = wp.transform_get_rotation(X_wpj)
|
|
498
|
+
q_c = wp.transform_get_rotation(X_wcj)
|
|
499
|
+
|
|
500
|
+
x_err = x_c - x_p
|
|
501
|
+
v_err = v_c - v_p
|
|
502
|
+
w_err = w_c - w_p
|
|
503
|
+
|
|
504
|
+
q_start = joint_q_start[tid]
|
|
505
|
+
qd_start = joint_qd_start[tid]
|
|
506
|
+
axis_start = joint_axis_start[tid]
|
|
507
|
+
lin_axis_count = joint_axis_dim[tid, 0]
|
|
508
|
+
ang_axis_count = joint_axis_dim[tid, 1]
|
|
509
|
+
|
|
510
|
+
if type == wp.sim.JOINT_PRISMATIC:
|
|
511
|
+
axis = joint_axis[axis_start]
|
|
512
|
+
|
|
513
|
+
# world space joint axis
|
|
514
|
+
axis_p = wp.quat_rotate(q_p, axis)
|
|
515
|
+
|
|
516
|
+
# evaluate joint coordinates
|
|
517
|
+
q = wp.dot(x_err, axis_p)
|
|
518
|
+
qd = wp.dot(v_err, axis_p)
|
|
519
|
+
|
|
520
|
+
joint_q[q_start] = q
|
|
521
|
+
joint_qd[qd_start] = qd
|
|
522
|
+
|
|
523
|
+
return
|
|
524
|
+
|
|
525
|
+
if type == wp.sim.JOINT_REVOLUTE:
|
|
526
|
+
axis = joint_axis[axis_start]
|
|
527
|
+
q_pc = wp.quat_inverse(q_p) * q_c
|
|
528
|
+
|
|
529
|
+
q, qd = reconstruct_angular_q_qd(q_pc, w_err, X_wpj, axis)
|
|
530
|
+
|
|
531
|
+
joint_q[q_start] = q
|
|
532
|
+
joint_qd[qd_start] = qd
|
|
533
|
+
|
|
534
|
+
return
|
|
535
|
+
|
|
536
|
+
if type == wp.sim.JOINT_BALL:
|
|
537
|
+
q_pc = wp.quat_inverse(q_p) * q_c
|
|
538
|
+
|
|
539
|
+
joint_q[q_start + 0] = q_pc[0]
|
|
540
|
+
joint_q[q_start + 1] = q_pc[1]
|
|
541
|
+
joint_q[q_start + 2] = q_pc[2]
|
|
542
|
+
joint_q[q_start + 3] = q_pc[3]
|
|
543
|
+
|
|
544
|
+
ang_vel = wp.transform_vector(wp.transform_inverse(X_wpj), w_err)
|
|
545
|
+
joint_qd[qd_start + 0] = ang_vel[0]
|
|
546
|
+
joint_qd[qd_start + 1] = ang_vel[1]
|
|
547
|
+
joint_qd[qd_start + 2] = ang_vel[2]
|
|
548
|
+
|
|
549
|
+
return
|
|
550
|
+
|
|
551
|
+
if type == wp.sim.JOINT_FIXED:
|
|
552
|
+
return
|
|
553
|
+
|
|
554
|
+
if type == wp.sim.JOINT_FREE or type == wp.sim.JOINT_DISTANCE:
|
|
555
|
+
q_pc = wp.quat_inverse(q_p) * q_c
|
|
556
|
+
|
|
557
|
+
x_err_c = wp.quat_rotate_inv(q_p, x_err)
|
|
558
|
+
v_err_c = wp.quat_rotate_inv(q_p, v_err)
|
|
559
|
+
w_err_c = wp.quat_rotate_inv(q_p, w_err)
|
|
560
|
+
|
|
561
|
+
joint_q[q_start + 0] = x_err_c[0]
|
|
562
|
+
joint_q[q_start + 1] = x_err_c[1]
|
|
563
|
+
joint_q[q_start + 2] = x_err_c[2]
|
|
564
|
+
|
|
565
|
+
joint_q[q_start + 3] = q_pc[0]
|
|
566
|
+
joint_q[q_start + 4] = q_pc[1]
|
|
567
|
+
joint_q[q_start + 5] = q_pc[2]
|
|
568
|
+
joint_q[q_start + 6] = q_pc[3]
|
|
569
|
+
|
|
570
|
+
joint_qd[qd_start + 0] = w_err_c[0]
|
|
571
|
+
joint_qd[qd_start + 1] = w_err_c[1]
|
|
572
|
+
joint_qd[qd_start + 2] = w_err_c[2]
|
|
573
|
+
|
|
574
|
+
joint_qd[qd_start + 3] = v_err_c[0]
|
|
575
|
+
joint_qd[qd_start + 4] = v_err_c[1]
|
|
576
|
+
joint_qd[qd_start + 5] = v_err_c[2]
|
|
577
|
+
|
|
578
|
+
return
|
|
579
|
+
|
|
580
|
+
if type == wp.sim.JOINT_COMPOUND:
|
|
581
|
+
axis_0 = joint_axis[axis_start + 0]
|
|
582
|
+
axis_1 = joint_axis[axis_start + 1]
|
|
583
|
+
axis_2 = joint_axis[axis_start + 2]
|
|
584
|
+
qs, qds = invert_3d_rotational_dofs(axis_0, axis_1, axis_2, q_p, q_c, w_err)
|
|
585
|
+
joint_q[q_start + 0] = qs[0]
|
|
586
|
+
joint_q[q_start + 1] = qs[1]
|
|
587
|
+
joint_q[q_start + 2] = qs[2]
|
|
588
|
+
joint_qd[qd_start + 0] = qds[0]
|
|
589
|
+
joint_qd[qd_start + 1] = qds[1]
|
|
590
|
+
joint_qd[qd_start + 2] = qds[2]
|
|
591
|
+
|
|
592
|
+
return
|
|
593
|
+
|
|
594
|
+
if type == wp.sim.JOINT_UNIVERSAL:
|
|
595
|
+
axis_0 = joint_axis[axis_start + 0]
|
|
596
|
+
axis_1 = joint_axis[axis_start + 1]
|
|
597
|
+
qs2, qds2 = invert_2d_rotational_dofs(axis_0, axis_1, q_p, q_c, w_err)
|
|
598
|
+
joint_q[q_start + 0] = qs2[0]
|
|
599
|
+
joint_q[q_start + 1] = qs2[1]
|
|
600
|
+
joint_qd[qd_start + 0] = qds2[0]
|
|
601
|
+
joint_qd[qd_start + 1] = qds2[1]
|
|
602
|
+
|
|
603
|
+
return
|
|
604
|
+
|
|
605
|
+
if type == wp.sim.JOINT_D6:
|
|
606
|
+
x_err_c = wp.quat_rotate_inv(q_p, x_err)
|
|
607
|
+
v_err_c = wp.quat_rotate_inv(q_p, v_err)
|
|
608
|
+
if lin_axis_count > 0:
|
|
609
|
+
axis = joint_axis[axis_start + 0]
|
|
610
|
+
joint_q[q_start + 0] = wp.dot(x_err_c, axis)
|
|
611
|
+
joint_qd[qd_start + 0] = wp.dot(v_err_c, axis)
|
|
612
|
+
|
|
613
|
+
if lin_axis_count > 1:
|
|
614
|
+
axis = joint_axis[axis_start + 1]
|
|
615
|
+
joint_q[q_start + 1] = wp.dot(x_err_c, axis)
|
|
616
|
+
joint_qd[qd_start + 1] = wp.dot(v_err_c, axis)
|
|
617
|
+
|
|
618
|
+
if lin_axis_count > 2:
|
|
619
|
+
axis = joint_axis[axis_start + 2]
|
|
620
|
+
joint_q[q_start + 2] = wp.dot(x_err_c, axis)
|
|
621
|
+
joint_qd[qd_start + 2] = wp.dot(v_err_c, axis)
|
|
622
|
+
|
|
623
|
+
if ang_axis_count == 1:
|
|
624
|
+
axis = joint_axis[axis_start]
|
|
625
|
+
q_pc = wp.quat_inverse(q_p) * q_c
|
|
626
|
+
q, qd = reconstruct_angular_q_qd(q_pc, w_err, X_wpj, joint_axis[axis_start + lin_axis_count])
|
|
627
|
+
joint_q[q_start + lin_axis_count] = q
|
|
628
|
+
joint_qd[qd_start + lin_axis_count] = qd
|
|
629
|
+
|
|
630
|
+
if ang_axis_count == 2:
|
|
631
|
+
axis_0 = joint_axis[axis_start + lin_axis_count + 0]
|
|
632
|
+
axis_1 = joint_axis[axis_start + lin_axis_count + 1]
|
|
633
|
+
qs2, qds2 = invert_2d_rotational_dofs(axis_0, axis_1, q_p, q_c, w_err)
|
|
634
|
+
joint_q[q_start + lin_axis_count + 0] = qs2[0]
|
|
635
|
+
joint_q[q_start + lin_axis_count + 1] = qs2[1]
|
|
636
|
+
joint_qd[qd_start + lin_axis_count + 0] = qds2[0]
|
|
637
|
+
joint_qd[qd_start + lin_axis_count + 1] = qds2[1]
|
|
638
|
+
|
|
639
|
+
if ang_axis_count == 3:
|
|
640
|
+
axis_0 = joint_axis[axis_start + lin_axis_count + 0]
|
|
641
|
+
axis_1 = joint_axis[axis_start + lin_axis_count + 1]
|
|
642
|
+
axis_2 = joint_axis[axis_start + lin_axis_count + 2]
|
|
643
|
+
qs3, qds3 = invert_3d_rotational_dofs(axis_0, axis_1, axis_2, q_p, q_c, w_err)
|
|
644
|
+
joint_q[q_start + lin_axis_count + 0] = qs3[0]
|
|
645
|
+
joint_q[q_start + lin_axis_count + 1] = qs3[1]
|
|
646
|
+
joint_q[q_start + lin_axis_count + 2] = qs3[2]
|
|
647
|
+
joint_qd[qd_start + lin_axis_count + 0] = qds3[0]
|
|
648
|
+
joint_qd[qd_start + lin_axis_count + 1] = qds3[1]
|
|
649
|
+
joint_qd[qd_start + lin_axis_count + 2] = qds3[2]
|
|
650
|
+
|
|
651
|
+
return
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
# given maximal coordinate model computes ik (closest point projection)
|
|
655
|
+
def eval_ik(model, state, joint_q, joint_qd):
|
|
656
|
+
"""
|
|
657
|
+
Evaluates the model's inverse kinematics given the state's body information (:attr:`State.body_q` and :attr:`State.body_qd`) and updates the generalized joint coordinates `joint_q` and `joint_qd`.
|
|
658
|
+
|
|
659
|
+
Args:
|
|
660
|
+
model (Model): The model to evaluate.
|
|
661
|
+
state (State): The state with the body's maximal coordinates (positions :attr:`State.body_q` and velocities :attr:`State.body_qd`) to use.
|
|
662
|
+
joint_q (array): Generalized joint position coordinates, shape [joint_coord_count], float
|
|
663
|
+
joint_qd (array): Generalized joint velocity coordinates, shape [joint_dof_count], float
|
|
664
|
+
"""
|
|
665
|
+
wp.launch(
|
|
666
|
+
kernel=eval_articulation_ik,
|
|
667
|
+
dim=model.joint_count,
|
|
668
|
+
inputs=[
|
|
669
|
+
state.body_q,
|
|
670
|
+
state.body_qd,
|
|
671
|
+
model.body_com,
|
|
672
|
+
model.joint_type,
|
|
673
|
+
model.joint_parent,
|
|
674
|
+
model.joint_child,
|
|
675
|
+
model.joint_X_p,
|
|
676
|
+
model.joint_X_c,
|
|
677
|
+
model.joint_axis,
|
|
678
|
+
model.joint_axis_start,
|
|
679
|
+
model.joint_axis_dim,
|
|
680
|
+
model.joint_q_start,
|
|
681
|
+
model.joint_qd_start,
|
|
682
|
+
],
|
|
683
|
+
outputs=[joint_q, joint_qd],
|
|
684
|
+
device=model.device,
|
|
685
|
+
)
|