warp-lang 0.9.0__py3-none-win_amd64.whl → 0.11.0__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (315) hide show
  1. warp/__init__.py +15 -7
  2. warp/__init__.pyi +1 -0
  3. warp/bin/warp-clang.dll +0 -0
  4. warp/bin/warp.dll +0 -0
  5. warp/build.py +22 -443
  6. warp/build_dll.py +384 -0
  7. warp/builtins.py +998 -488
  8. warp/codegen.py +1307 -739
  9. warp/config.py +5 -3
  10. warp/constants.py +6 -0
  11. warp/context.py +1291 -548
  12. warp/dlpack.py +31 -31
  13. warp/fabric.py +326 -0
  14. warp/fem/__init__.py +27 -0
  15. warp/fem/cache.py +389 -0
  16. warp/fem/dirichlet.py +181 -0
  17. warp/fem/domain.py +263 -0
  18. warp/fem/field/__init__.py +101 -0
  19. warp/fem/field/field.py +149 -0
  20. warp/fem/field/nodal_field.py +299 -0
  21. warp/fem/field/restriction.py +21 -0
  22. warp/fem/field/test.py +181 -0
  23. warp/fem/field/trial.py +183 -0
  24. warp/fem/geometry/__init__.py +19 -0
  25. warp/fem/geometry/closest_point.py +70 -0
  26. warp/fem/geometry/deformed_geometry.py +271 -0
  27. warp/fem/geometry/element.py +744 -0
  28. warp/fem/geometry/geometry.py +186 -0
  29. warp/fem/geometry/grid_2d.py +373 -0
  30. warp/fem/geometry/grid_3d.py +435 -0
  31. warp/fem/geometry/hexmesh.py +953 -0
  32. warp/fem/geometry/partition.py +376 -0
  33. warp/fem/geometry/quadmesh_2d.py +532 -0
  34. warp/fem/geometry/tetmesh.py +840 -0
  35. warp/fem/geometry/trimesh_2d.py +577 -0
  36. warp/fem/integrate.py +1616 -0
  37. warp/fem/operator.py +191 -0
  38. warp/fem/polynomial.py +213 -0
  39. warp/fem/quadrature/__init__.py +2 -0
  40. warp/fem/quadrature/pic_quadrature.py +245 -0
  41. warp/fem/quadrature/quadrature.py +294 -0
  42. warp/fem/space/__init__.py +292 -0
  43. warp/fem/space/basis_space.py +489 -0
  44. warp/fem/space/collocated_function_space.py +105 -0
  45. warp/fem/space/dof_mapper.py +236 -0
  46. warp/fem/space/function_space.py +145 -0
  47. warp/fem/space/grid_2d_function_space.py +267 -0
  48. warp/fem/space/grid_3d_function_space.py +306 -0
  49. warp/fem/space/hexmesh_function_space.py +352 -0
  50. warp/fem/space/partition.py +350 -0
  51. warp/fem/space/quadmesh_2d_function_space.py +369 -0
  52. warp/fem/space/restriction.py +160 -0
  53. warp/fem/space/shape/__init__.py +15 -0
  54. warp/fem/space/shape/cube_shape_function.py +738 -0
  55. warp/fem/space/shape/shape_function.py +103 -0
  56. warp/fem/space/shape/square_shape_function.py +611 -0
  57. warp/fem/space/shape/tet_shape_function.py +567 -0
  58. warp/fem/space/shape/triangle_shape_function.py +429 -0
  59. warp/fem/space/tetmesh_function_space.py +292 -0
  60. warp/fem/space/topology.py +295 -0
  61. warp/fem/space/trimesh_2d_function_space.py +221 -0
  62. warp/fem/types.py +77 -0
  63. warp/fem/utils.py +495 -0
  64. warp/native/array.h +164 -55
  65. warp/native/builtin.h +150 -174
  66. warp/native/bvh.cpp +75 -328
  67. warp/native/bvh.cu +406 -23
  68. warp/native/bvh.h +37 -45
  69. warp/native/clang/clang.cpp +136 -24
  70. warp/native/crt.cpp +1 -76
  71. warp/native/crt.h +111 -104
  72. warp/native/cuda_crt.h +1049 -0
  73. warp/native/cuda_util.cpp +15 -3
  74. warp/native/cuda_util.h +3 -1
  75. warp/native/cutlass/tools/library/scripts/conv2d_operation.py +463 -0
  76. warp/native/cutlass/tools/library/scripts/conv3d_operation.py +321 -0
  77. warp/native/cutlass/tools/library/scripts/gemm_operation.py +988 -0
  78. warp/native/cutlass/tools/library/scripts/generator.py +4625 -0
  79. warp/native/cutlass/tools/library/scripts/library.py +799 -0
  80. warp/native/cutlass/tools/library/scripts/manifest.py +402 -0
  81. warp/native/cutlass/tools/library/scripts/pycutlass/docs/source/conf.py +96 -0
  82. warp/native/cutlass/tools/library/scripts/pycutlass/profile/conv/conv2d_f16_sm80.py +106 -0
  83. warp/native/cutlass/tools/library/scripts/pycutlass/profile/gemm/gemm_f32_sm80.py +91 -0
  84. warp/native/cutlass/tools/library/scripts/pycutlass/setup.py +80 -0
  85. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/__init__.py +48 -0
  86. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/arguments.py +118 -0
  87. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/c_types.py +241 -0
  88. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/compiler.py +432 -0
  89. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/conv2d_operation.py +631 -0
  90. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/epilogue.py +1026 -0
  91. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/frontend.py +104 -0
  92. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/gemm_operation.py +1276 -0
  93. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/library.py +744 -0
  94. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/memory_manager.py +74 -0
  95. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/operation.py +110 -0
  96. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/parser.py +619 -0
  97. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/reduction_operation.py +398 -0
  98. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/tensor_ref.py +70 -0
  99. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/__init__.py +4 -0
  100. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/conv2d_testbed.py +646 -0
  101. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_grouped_testbed.py +235 -0
  102. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_testbed.py +557 -0
  103. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/profiler.py +70 -0
  104. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/type_hint.py +39 -0
  105. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/__init__.py +1 -0
  106. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/device.py +76 -0
  107. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/reference_model.py +255 -0
  108. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/__init__.py +0 -0
  109. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +201 -0
  110. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +177 -0
  111. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +98 -0
  112. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +95 -0
  113. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_few_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +163 -0
  114. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_fixed_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +187 -0
  115. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +309 -0
  116. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +54 -0
  117. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
  118. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
  119. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_strided_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +253 -0
  120. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +97 -0
  121. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +242 -0
  122. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
  123. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
  124. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/run_all_tests.py +10 -0
  125. warp/native/cutlass/tools/library/scripts/pycutlass/test/frontend/test_frontend.py +146 -0
  126. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/__init__.py +0 -0
  127. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_bf16_sm80.py +96 -0
  128. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f16_sm80.py +447 -0
  129. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f32_sm80.py +146 -0
  130. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f64_sm80.py +102 -0
  131. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_grouped_sm80.py +203 -0
  132. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_s8_sm80.py +229 -0
  133. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/run_all_tests.py +9 -0
  134. warp/native/cutlass/tools/library/scripts/pycutlass/test/unit/test_sm80.py +453 -0
  135. warp/native/cutlass/tools/library/scripts/rank_2k_operation.py +398 -0
  136. warp/native/cutlass/tools/library/scripts/rank_k_operation.py +387 -0
  137. warp/native/cutlass/tools/library/scripts/rt.py +796 -0
  138. warp/native/cutlass/tools/library/scripts/symm_operation.py +400 -0
  139. warp/native/cutlass/tools/library/scripts/trmm_operation.py +407 -0
  140. warp/native/cutlass_gemm.cu +5 -3
  141. warp/native/exports.h +1240 -949
  142. warp/native/fabric.h +228 -0
  143. warp/native/hashgrid.cpp +4 -4
  144. warp/native/hashgrid.h +22 -2
  145. warp/native/initializer_array.h +2 -2
  146. warp/native/intersect.h +22 -7
  147. warp/native/intersect_adj.h +8 -8
  148. warp/native/intersect_tri.h +13 -16
  149. warp/native/marching.cu +157 -161
  150. warp/native/mat.h +119 -19
  151. warp/native/matnn.h +2 -2
  152. warp/native/mesh.cpp +108 -83
  153. warp/native/mesh.cu +243 -6
  154. warp/native/mesh.h +1547 -458
  155. warp/native/nanovdb/NanoVDB.h +1 -1
  156. warp/native/noise.h +272 -329
  157. warp/native/quat.h +51 -8
  158. warp/native/rand.h +45 -35
  159. warp/native/range.h +6 -2
  160. warp/native/reduce.cpp +157 -0
  161. warp/native/reduce.cu +348 -0
  162. warp/native/runlength_encode.cpp +62 -0
  163. warp/native/runlength_encode.cu +46 -0
  164. warp/native/scan.cu +11 -13
  165. warp/native/scan.h +1 -0
  166. warp/native/solid_angle.h +442 -0
  167. warp/native/sort.cpp +13 -0
  168. warp/native/sort.cu +9 -1
  169. warp/native/sparse.cpp +338 -0
  170. warp/native/sparse.cu +545 -0
  171. warp/native/spatial.h +2 -2
  172. warp/native/temp_buffer.h +30 -0
  173. warp/native/vec.h +126 -24
  174. warp/native/volume.h +120 -0
  175. warp/native/warp.cpp +658 -53
  176. warp/native/warp.cu +660 -68
  177. warp/native/warp.h +112 -12
  178. warp/optim/__init__.py +1 -0
  179. warp/optim/linear.py +922 -0
  180. warp/optim/sgd.py +92 -0
  181. warp/render/render_opengl.py +392 -152
  182. warp/render/render_usd.py +11 -11
  183. warp/sim/__init__.py +2 -2
  184. warp/sim/articulation.py +385 -185
  185. warp/sim/collide.py +21 -8
  186. warp/sim/import_mjcf.py +297 -106
  187. warp/sim/import_urdf.py +389 -210
  188. warp/sim/import_usd.py +198 -97
  189. warp/sim/inertia.py +17 -18
  190. warp/sim/integrator_euler.py +14 -8
  191. warp/sim/integrator_xpbd.py +161 -19
  192. warp/sim/model.py +795 -291
  193. warp/sim/optimizer.py +2 -6
  194. warp/sim/render.py +65 -3
  195. warp/sim/utils.py +3 -0
  196. warp/sparse.py +1227 -0
  197. warp/stubs.py +665 -223
  198. warp/tape.py +66 -15
  199. warp/tests/__main__.py +3 -6
  200. warp/tests/assets/curlnoise_golden.npy +0 -0
  201. warp/tests/assets/pnoise_golden.npy +0 -0
  202. warp/tests/assets/torus.usda +105 -105
  203. warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
  204. warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
  205. warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
  206. warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
  207. warp/tests/aux_test_unresolved_func.py +14 -0
  208. warp/tests/aux_test_unresolved_symbol.py +14 -0
  209. warp/tests/disabled_kinematics.py +239 -0
  210. warp/tests/run_coverage_serial.py +31 -0
  211. warp/tests/test_adam.py +103 -106
  212. warp/tests/test_arithmetic.py +128 -74
  213. warp/tests/test_array.py +1497 -211
  214. warp/tests/test_array_reduce.py +150 -0
  215. warp/tests/test_atomic.py +64 -28
  216. warp/tests/test_bool.py +99 -0
  217. warp/tests/test_builtins_resolution.py +1292 -0
  218. warp/tests/test_bvh.py +75 -43
  219. warp/tests/test_closest_point_edge_edge.py +54 -57
  220. warp/tests/test_codegen.py +233 -128
  221. warp/tests/test_compile_consts.py +28 -20
  222. warp/tests/test_conditional.py +108 -24
  223. warp/tests/test_copy.py +10 -12
  224. warp/tests/test_ctypes.py +112 -88
  225. warp/tests/test_dense.py +21 -14
  226. warp/tests/test_devices.py +98 -0
  227. warp/tests/test_dlpack.py +136 -108
  228. warp/tests/test_examples.py +277 -0
  229. warp/tests/test_fabricarray.py +955 -0
  230. warp/tests/test_fast_math.py +15 -11
  231. warp/tests/test_fem.py +1271 -0
  232. warp/tests/test_fp16.py +53 -19
  233. warp/tests/test_func.py +187 -74
  234. warp/tests/test_generics.py +194 -49
  235. warp/tests/test_grad.py +180 -116
  236. warp/tests/test_grad_customs.py +176 -0
  237. warp/tests/test_hash_grid.py +52 -37
  238. warp/tests/test_import.py +10 -23
  239. warp/tests/test_indexedarray.py +577 -24
  240. warp/tests/test_intersect.py +18 -9
  241. warp/tests/test_large.py +141 -0
  242. warp/tests/test_launch.py +251 -15
  243. warp/tests/test_lerp.py +64 -65
  244. warp/tests/test_linear_solvers.py +154 -0
  245. warp/tests/test_lvalue.py +493 -0
  246. warp/tests/test_marching_cubes.py +12 -13
  247. warp/tests/test_mat.py +508 -2778
  248. warp/tests/test_mat_lite.py +115 -0
  249. warp/tests/test_mat_scalar_ops.py +2889 -0
  250. warp/tests/test_math.py +103 -9
  251. warp/tests/test_matmul.py +305 -69
  252. warp/tests/test_matmul_lite.py +410 -0
  253. warp/tests/test_mesh.py +71 -14
  254. warp/tests/test_mesh_query_aabb.py +41 -25
  255. warp/tests/test_mesh_query_point.py +325 -34
  256. warp/tests/test_mesh_query_ray.py +39 -22
  257. warp/tests/test_mlp.py +30 -22
  258. warp/tests/test_model.py +92 -89
  259. warp/tests/test_modules_lite.py +39 -0
  260. warp/tests/test_multigpu.py +88 -114
  261. warp/tests/test_noise.py +12 -11
  262. warp/tests/test_operators.py +16 -20
  263. warp/tests/test_options.py +11 -11
  264. warp/tests/test_pinned.py +17 -18
  265. warp/tests/test_print.py +32 -11
  266. warp/tests/test_quat.py +275 -129
  267. warp/tests/test_rand.py +18 -16
  268. warp/tests/test_reload.py +38 -34
  269. warp/tests/test_rounding.py +50 -43
  270. warp/tests/test_runlength_encode.py +190 -0
  271. warp/tests/test_smoothstep.py +9 -11
  272. warp/tests/test_snippet.py +143 -0
  273. warp/tests/test_sparse.py +460 -0
  274. warp/tests/test_spatial.py +276 -243
  275. warp/tests/test_streams.py +110 -85
  276. warp/tests/test_struct.py +331 -85
  277. warp/tests/test_tape.py +39 -21
  278. warp/tests/test_torch.py +118 -89
  279. warp/tests/test_transient_module.py +12 -13
  280. warp/tests/test_types.py +614 -0
  281. warp/tests/test_utils.py +494 -0
  282. warp/tests/test_vec.py +354 -1987
  283. warp/tests/test_vec_lite.py +73 -0
  284. warp/tests/test_vec_scalar_ops.py +2099 -0
  285. warp/tests/test_volume.py +457 -293
  286. warp/tests/test_volume_write.py +124 -134
  287. warp/tests/unittest_serial.py +35 -0
  288. warp/tests/unittest_suites.py +341 -0
  289. warp/tests/unittest_utils.py +568 -0
  290. warp/tests/unused_test_misc.py +71 -0
  291. warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
  292. warp/thirdparty/appdirs.py +36 -45
  293. warp/thirdparty/unittest_parallel.py +549 -0
  294. warp/torch.py +72 -30
  295. warp/types.py +1744 -713
  296. warp/utils.py +360 -350
  297. warp_lang-0.11.0.dist-info/LICENSE.md +36 -0
  298. warp_lang-0.11.0.dist-info/METADATA +238 -0
  299. warp_lang-0.11.0.dist-info/RECORD +332 -0
  300. {warp_lang-0.9.0.dist-info → warp_lang-0.11.0.dist-info}/WHEEL +1 -1
  301. warp/bin/warp-clang.exp +0 -0
  302. warp/bin/warp-clang.lib +0 -0
  303. warp/bin/warp.exp +0 -0
  304. warp/bin/warp.lib +0 -0
  305. warp/tests/test_all.py +0 -215
  306. warp/tests/test_array_scan.py +0 -60
  307. warp/tests/test_base.py +0 -208
  308. warp/tests/test_unresolved_func.py +0 -7
  309. warp/tests/test_unresolved_symbol.py +0 -7
  310. warp_lang-0.9.0.dist-info/METADATA +0 -20
  311. warp_lang-0.9.0.dist-info/RECORD +0 -177
  312. /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
  313. /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
  314. /warp/tests/{test_square.py → aux_test_square.py} +0 -0
  315. {warp_lang-0.9.0.dist-info → warp_lang-0.11.0.dist-info}/top_level.txt +0 -0
warp/sim/articulation.py CHANGED
@@ -7,7 +7,161 @@
7
7
 
8
8
  import warp as wp
9
9
 
10
- from .utils import quat_decompose, quat_twist, quat_twist_angle
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, todo: can probably use fact that rz'*ry'*rx' == rx*ry*rz to avoid some work here
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
11
165
 
12
166
 
13
167
  @wp.kernel
@@ -46,12 +200,6 @@ def eval_articulation_fk(
46
200
  for i in range(joint_start, joint_end):
47
201
  parent = joint_parent[i]
48
202
  child = joint_child[i]
49
- X_wp = wp.transform_identity()
50
- v_wp = wp.spatial_vector()
51
-
52
- if parent >= 0:
53
- X_wp = body_q[parent]
54
- v_wp = body_qd[parent]
55
203
 
56
204
  # compute transform across the joint
57
205
  type = joint_type[i]
@@ -59,14 +207,28 @@ def eval_articulation_fk(
59
207
  X_pj = joint_X_p[i]
60
208
  X_cj = joint_X_c[i]
61
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
+
62
224
  q_start = joint_q_start[i]
63
225
  qd_start = joint_qd_start[i]
64
226
  axis_start = joint_axis_start[i]
65
227
  lin_axis_count = joint_axis_dim[i, 0]
66
228
  ang_axis_count = joint_axis_dim[i, 1]
67
229
 
68
- X_jc = wp.transform_identity()
69
- v_jc = wp.spatial_vector(wp.vec3(), wp.vec3())
230
+ X_j = wp.transform_identity()
231
+ v_j = wp.spatial_vector(wp.vec3(), wp.vec3())
70
232
 
71
233
  if type == wp.sim.JOINT_PRISMATIC:
72
234
  axis = joint_axis[axis_start]
@@ -74,8 +236,8 @@ def eval_articulation_fk(
74
236
  q = joint_q[q_start]
75
237
  qd = joint_qd[qd_start]
76
238
 
77
- X_jc = wp.transform(axis * q, wp.quat_identity())
78
- v_jc = wp.spatial_vector(wp.vec3(), axis * qd)
239
+ X_j = wp.transform(axis * q, wp.quat_identity())
240
+ v_j = wp.spatial_vector(wp.vec3(), axis * qd)
79
241
 
80
242
  if type == wp.sim.JOINT_REVOLUTE:
81
243
  axis = joint_axis[axis_start]
@@ -83,20 +245,18 @@ def eval_articulation_fk(
83
245
  q = joint_q[q_start]
84
246
  qd = joint_qd[qd_start]
85
247
 
86
- X_jc = wp.transform(wp.vec3(), wp.quat_from_axis_angle(axis, q))
87
- v_jc = wp.spatial_vector(axis * qd, wp.vec3())
248
+ X_j = wp.transform(wp.vec3(), wp.quat_from_axis_angle(axis, q))
249
+ v_j = wp.spatial_vector(axis * qd, wp.vec3())
88
250
 
89
251
  if type == wp.sim.JOINT_BALL:
90
252
  r = wp.quat(joint_q[q_start + 0], joint_q[q_start + 1], joint_q[q_start + 2], joint_q[q_start + 3])
91
253
 
92
254
  w = wp.vec3(joint_qd[qd_start + 0], joint_qd[qd_start + 1], joint_qd[qd_start + 2])
93
255
 
94
- # print(r)
95
-
96
- X_jc = wp.transform(wp.vec3(), r)
97
- v_jc = wp.spatial_vector(w, wp.vec3())
256
+ X_j = wp.transform(wp.vec3(), r)
257
+ v_j = wp.spatial_vector(w, wp.vec3())
98
258
 
99
- if type == wp.sim.JOINT_FREE:
259
+ if type == wp.sim.JOINT_FREE or type == wp.sim.JOINT_DISTANCE:
100
260
  t = wp.transform(
101
261
  wp.vec3(joint_q[q_start + 0], joint_q[q_start + 1], joint_q[q_start + 2]),
102
262
  wp.quat(joint_q[q_start + 3], joint_q[q_start + 4], joint_q[q_start + 5], joint_q[q_start + 6]),
@@ -107,46 +267,43 @@ def eval_articulation_fk(
107
267
  wp.vec3(joint_qd[qd_start + 3], joint_qd[qd_start + 4], joint_qd[qd_start + 5]),
108
268
  )
109
269
 
110
- X_jc = t
111
- v_jc = v
270
+ X_j = t
271
+ v_j = v
112
272
 
113
273
  if type == wp.sim.JOINT_COMPOUND:
114
- axis = joint_axis[axis_start]
115
-
116
- # reconstruct rotation axes, todo: can probably use fact that rz'*ry'*rx' == rx*ry*rz to avoid some work here
117
- axis_0 = axis
118
- q_0 = wp.quat_from_axis_angle(axis_0, joint_q[q_start + 0])
119
-
120
- axis_1 = joint_axis[axis_start + 1]
121
- q_1 = wp.quat_from_axis_angle(axis_1, joint_q[q_start + 1])
122
-
123
- axis_2 = joint_axis[axis_start + 2]
124
- q_2 = wp.quat_from_axis_angle(axis_2, joint_q[q_start + 2])
125
-
126
- t = wp.transform(wp.vec3(), q_2 * q_1 * q_0)
127
-
128
- v = wp.spatial_vector(
129
- axis_0 * joint_qd[qd_start + 0] + axis_1 * joint_qd[qd_start + 1] + axis_2 * joint_qd[qd_start + 2],
130
- wp.vec3(),
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],
131
284
  )
132
285
 
133
- X_jc = t
134
- v_jc = v
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))
135
288
 
136
- if type == wp.sim.JOINT_UNIVERSAL:
137
- # reconstruct rotation axes
138
- axis_0 = joint_axis[axis_start]
139
- q_0 = wp.quat_from_axis_angle(axis_0, joint_q[q_start + 0])
140
-
141
- axis_1 = joint_axis[axis_start + 1]
142
- q_1 = wp.quat_from_axis_angle(axis_1, joint_q[q_start + 1])
289
+ X_j = t
290
+ v_j = v
143
291
 
144
- t = wp.transform(wp.vec3(), q_1 * q_0)
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
+ )
145
301
 
146
- v = wp.spatial_vector(axis_0 * joint_qd[qd_start + 0] + axis_1 * joint_qd[qd_start + 1], wp.vec3())
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))
147
304
 
148
- X_jc = t
149
- v_jc = v
305
+ X_j = t
306
+ v_j = v
150
307
 
151
308
  if type == wp.sim.JOINT_D6:
152
309
  pos = wp.vec3(0.0)
@@ -170,34 +327,49 @@ def eval_articulation_fk(
170
327
  pos += axis * joint_q[q_start + 2]
171
328
  vel_v += axis * joint_qd[qd_start + 2]
172
329
 
173
- if ang_axis_count > 0:
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:
174
334
  axis = joint_axis[axis_start + lin_axis_count + 0]
175
335
  qi = wp.quat_from_axis_angle(axis, joint_q[q_start + lin_axis_count + 0])
176
336
  rot = qi * rot
177
- vel_w += joint_qd[qd_start + lin_axis_count + 0] * axis
178
- if ang_axis_count > 1:
179
- axis = joint_axis[axis_start + lin_axis_count + 1]
180
- qi = wp.quat_from_axis_angle(axis, joint_q[q_start + lin_axis_count + 1])
181
- rot = qi * rot
182
- vel_w += joint_qd[qd_start + lin_axis_count + 1] * axis
183
- if ang_axis_count > 2:
184
- axis = joint_axis[axis_start + lin_axis_count + 2]
185
- qi = wp.quat_from_axis_angle(axis, joint_q[q_start + lin_axis_count + 2])
186
- rot = qi * rot
187
- vel_w += joint_qd[qd_start + lin_axis_count + 2] * axis
188
-
189
- X_jc = wp.transform(pos, rot)
190
- v_jc = wp.spatial_vector(vel_w, vel_v)
191
-
192
- X_wj = X_wp * X_pj
193
- X_wc = X_wj * X_jc
194
- X_wc *= wp.transform_inverse(X_cj)
337
+ vel_w = joint_qd[qd_start + lin_axis_count + 0] * axis
338
+ if ang_axis_count == 2:
339
+ rot, vel_w = compute_2d_rotational_dofs(
340
+ joint_axis[ia + 0],
341
+ joint_axis[ia + 1],
342
+ joint_q[iq + 0],
343
+ joint_q[iq + 1],
344
+ joint_qd[iqd + 0],
345
+ joint_qd[iqd + 1],
346
+ )
347
+ if ang_axis_count == 3:
348
+ rot, vel_w = compute_3d_rotational_dofs(
349
+ joint_axis[ia + 0],
350
+ joint_axis[ia + 1],
351
+ joint_axis[ia + 2],
352
+ joint_q[iq + 0],
353
+ joint_q[iq + 1],
354
+ joint_q[iq + 2],
355
+ joint_qd[iqd + 0],
356
+ joint_qd[iqd + 1],
357
+ joint_qd[iqd + 2],
358
+ )
359
+
360
+ X_j = wp.transform(pos, rot)
361
+ v_j = wp.spatial_vector(vel_w, vel_v)
362
+
363
+ # transform from world to joint anchor frame at child body
364
+ X_wcj = X_wpj * X_j
365
+ # transform from world to child body frame
366
+ X_wc = X_wcj * wp.transform_inverse(X_cj)
195
367
 
196
368
  # transform velocity across the joint to world space
197
- angular_vel = wp.transform_vector(X_wj, wp.spatial_top(v_jc))
198
- linear_vel = wp.transform_vector(X_wj, wp.spatial_bottom(v_jc))
369
+ angular_vel = wp.transform_vector(X_wpj, wp.spatial_top(v_j))
370
+ linear_vel = wp.transform_vector(X_wpj, wp.spatial_bottom(v_j))
199
371
 
200
- v_wc = v_wp + wp.spatial_vector(angular_vel, linear_vel + wp.cross(angular_vel, body_com[i]))
372
+ v_wc = v_wpj + wp.spatial_vector(angular_vel, linear_vel)
201
373
 
202
374
  body_q[child] = X_wc
203
375
  body_qd[child] = v_wc
@@ -205,6 +377,16 @@ def eval_articulation_fk(
205
377
 
206
378
  # updates state body information based on joint coordinates
207
379
  def eval_fk(model, joint_q, joint_qd, mask, state):
380
+ """
381
+ 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`).
382
+
383
+ Args:
384
+ model (Model): The model to evaluate.
385
+ joint_q (array): Generalized joint position coordinates, shape [joint_coord_count], float
386
+ joint_qd (array): Generalized joint velocity coordinates, shape [joint_dof_count], float
387
+ mask (array): The mask to use to enable / disable FK for an articulation. If None then treat all as enabled, shape [articulation_count], int
388
+ state (State): The state to update.
389
+ """
208
390
  wp.launch(
209
391
  kernel=eval_articulation_fk,
210
392
  dim=model.articulation_count,
@@ -233,6 +415,29 @@ def eval_fk(model, joint_q, joint_qd, mask, state):
233
415
  )
234
416
 
235
417
 
418
+ @wp.func
419
+ def reconstruct_angular_q_qd(q_pc: wp.quat, w_err: wp.vec3, X_wp: wp.transform, axis: wp.vec3):
420
+ """
421
+ Reconstructs the angular joint coordinates and velocities given the relative rotation and angular velocity
422
+ between a parent and child body.
423
+
424
+ Args:
425
+ q_pc (quat): The relative rotation between the parent and child body.
426
+ w_err (vec3): The angular velocity between the parent and child body.
427
+ X_wp (transform): The parent body's transform in world space.
428
+ axis (vec3): The joint axis in the frame of the parent body.
429
+
430
+ Returns:
431
+ q (float): The joint position coordinate.
432
+ qd (float): The joint velocity coordinate.
433
+ """
434
+ axis_p = wp.transform_vector(X_wp, axis)
435
+ twist = quat_twist(axis, q_pc)
436
+ q = wp.acos(twist[3]) * 2.0 * wp.sign(wp.dot(axis, wp.vec3(twist[0], twist[1], twist[2])))
437
+ qd = wp.dot(w_err, axis_p)
438
+ return q, qd
439
+
440
+
236
441
  @wp.kernel
237
442
  def eval_articulation_ik(
238
443
  body_q: wp.array(dtype=wp.transform),
@@ -253,46 +458,46 @@ def eval_articulation_ik(
253
458
  ):
254
459
  tid = wp.tid()
255
460
 
256
- c_parent = joint_parent[tid]
257
- c_child = joint_child[tid]
461
+ parent = joint_parent[tid]
462
+ child = joint_child[tid]
258
463
 
259
464
  X_pj = joint_X_p[tid]
260
465
  X_cj = joint_X_c[tid]
261
466
 
262
- X_wp = X_pj
263
- r_p = wp.vec3()
264
467
  w_p = wp.vec3()
265
468
  v_p = wp.vec3()
469
+ v_wp = wp.spatial_vector()
266
470
 
267
- # parent transform and moment arm
268
- if c_parent >= 0:
269
- X_wp = body_q[c_parent] * X_wp
270
- r_wp = wp.transform_get_translation(X_wp) - wp.transform_point(body_q[c_parent], body_com[c_parent])
471
+ # parent anchor frame in world space
472
+ X_wpj = X_pj
473
+ if parent >= 0:
474
+ X_wp = body_q[parent]
475
+ X_wpj = X_wp * X_pj
476
+ r_p = wp.transform_get_translation(X_wpj) - wp.transform_point(X_wp, body_com[parent])
271
477
 
272
- twist_p = body_qd[c_parent]
273
-
274
- w_p = wp.spatial_top(twist_p)
275
- v_p = wp.spatial_bottom(twist_p) + wp.cross(w_p, r_wp)
478
+ v_wp = body_qd[parent]
479
+ w_p = wp.spatial_top(v_wp)
480
+ v_p = wp.spatial_bottom(v_wp) + wp.cross(w_p, r_p)
276
481
 
277
482
  # child transform and moment arm
278
- X_wc = body_q[c_child] * joint_X_c[tid]
279
- r_c = wp.transform_get_translation(X_wc) - wp.transform_point(body_q[c_child], body_com[c_child])
483
+ X_wc = body_q[child]
484
+ X_wcj = X_wc * X_cj
280
485
 
281
- twist_c = body_qd[c_child]
486
+ v_wc = body_qd[child]
282
487
 
283
- w_c = wp.spatial_top(twist_c)
284
- v_c = wp.spatial_bottom(twist_c) + wp.cross(w_c, r_c)
488
+ w_c = wp.spatial_top(v_wc)
489
+ v_c = wp.spatial_bottom(v_wc)
285
490
 
286
491
  # joint properties
287
492
  type = joint_type[tid]
288
493
 
289
- x_p = wp.transform_get_translation(X_wp)
290
- x_c = wp.transform_get_translation(X_wc)
494
+ # compute position and orientation differences between anchor frames
495
+ x_p = wp.transform_get_translation(X_wpj)
496
+ x_c = wp.transform_get_translation(X_wcj)
291
497
 
292
- q_p = wp.transform_get_rotation(X_wp)
293
- q_c = wp.transform_get_rotation(X_wc)
498
+ q_p = wp.transform_get_rotation(X_wpj)
499
+ q_c = wp.transform_get_rotation(X_wcj)
294
500
 
295
- # translational error
296
501
  x_err = x_c - x_p
297
502
  v_err = v_c - v_p
298
503
  w_err = w_c - w_p
@@ -307,7 +512,7 @@ def eval_articulation_ik(
307
512
  axis = joint_axis[axis_start]
308
513
 
309
514
  # world space joint axis
310
- axis_p = wp.transform_vector(X_wp, axis)
515
+ axis_p = wp.quat_rotate(q_p, axis)
311
516
 
312
517
  # evaluate joint coordinates
313
518
  q = wp.dot(x_err, axis_p)
@@ -320,16 +525,9 @@ def eval_articulation_ik(
320
525
 
321
526
  if type == wp.sim.JOINT_REVOLUTE:
322
527
  axis = joint_axis[axis_start]
323
-
324
- axis_p = wp.transform_vector(X_wp, axis)
325
- axis_c = wp.transform_vector(X_wc, axis)
326
-
327
- # swing twist decomposition
328
528
  q_pc = wp.quat_inverse(q_p) * q_c
329
- twist = quat_twist(axis, q_pc)
330
529
 
331
- q = wp.acos(twist[3]) * 2.0 * wp.sign(wp.dot(axis, wp.vec3(twist[0], twist[1], twist[2])))
332
- qd = wp.dot(w_err, axis_p)
530
+ q, qd = reconstruct_angular_q_qd(q_pc, w_err, X_wpj, axis)
333
531
 
334
532
  joint_q[q_start] = q
335
533
  joint_qd[qd_start] = qd
@@ -344,125 +542,127 @@ def eval_articulation_ik(
344
542
  joint_q[q_start + 2] = q_pc[2]
345
543
  joint_q[q_start + 3] = q_pc[3]
346
544
 
347
- joint_qd[qd_start + 0] = w_err[0]
348
- joint_qd[qd_start + 1] = w_err[1]
349
- joint_qd[qd_start + 2] = w_err[2]
545
+ ang_vel = wp.transform_vector(wp.transform_inverse(X_wpj), w_err)
546
+ joint_qd[qd_start + 0] = ang_vel[0]
547
+ joint_qd[qd_start + 1] = ang_vel[1]
548
+ joint_qd[qd_start + 2] = ang_vel[2]
350
549
 
351
550
  return
352
551
 
353
552
  if type == wp.sim.JOINT_FIXED:
354
553
  return
355
554
 
356
- if type == wp.sim.JOINT_FREE:
555
+ if type == wp.sim.JOINT_FREE or type == wp.sim.JOINT_DISTANCE:
357
556
  q_pc = wp.quat_inverse(q_p) * q_c
358
557
 
359
- joint_q[q_start + 0] = x_err[0]
360
- joint_q[q_start + 1] = x_err[1]
361
- joint_q[q_start + 2] = x_err[2]
558
+ x_err_c = wp.quat_rotate_inv(q_p, x_err)
559
+ v_err_c = wp.quat_rotate_inv(q_p, v_err)
560
+ w_err_c = wp.quat_rotate_inv(q_p, w_err)
561
+
562
+ joint_q[q_start + 0] = x_err_c[0]
563
+ joint_q[q_start + 1] = x_err_c[1]
564
+ joint_q[q_start + 2] = x_err_c[2]
362
565
 
363
566
  joint_q[q_start + 3] = q_pc[0]
364
567
  joint_q[q_start + 4] = q_pc[1]
365
568
  joint_q[q_start + 5] = q_pc[2]
366
569
  joint_q[q_start + 6] = q_pc[3]
367
570
 
368
- joint_qd[qd_start + 0] = w_err[0]
369
- joint_qd[qd_start + 1] = w_err[1]
370
- joint_qd[qd_start + 2] = w_err[2]
371
-
372
- joint_qd[qd_start + 3] = v_err[0]
373
- joint_qd[qd_start + 4] = v_err[1]
374
- joint_qd[qd_start + 5] = v_err[2]
375
-
376
- if type == wp.sim.JOINT_COMPOUND:
377
- q_off = wp.transform_get_rotation(X_cj)
378
- q_pc = wp.quat_inverse(q_off) * wp.quat_inverse(q_p) * q_c * q_off
379
-
380
- # decompose to a compound rotation each axis
381
- angles = quat_decompose(q_pc)
382
-
383
- # reconstruct rotation axes
384
- axis_0 = wp.vec3(1.0, 0.0, 0.0)
385
- q_0 = wp.quat_from_axis_angle(axis_0, angles[0])
571
+ joint_qd[qd_start + 0] = w_err_c[0]
572
+ joint_qd[qd_start + 1] = w_err_c[1]
573
+ joint_qd[qd_start + 2] = w_err_c[2]
386
574
 
387
- axis_1 = wp.quat_rotate(q_0, wp.vec3(0.0, 1.0, 0.0))
388
- q_1 = wp.quat_from_axis_angle(axis_1, angles[1])
575
+ joint_qd[qd_start + 3] = v_err_c[0]
576
+ joint_qd[qd_start + 4] = v_err_c[1]
577
+ joint_qd[qd_start + 5] = v_err_c[2]
389
578
 
390
- axis_2 = wp.quat_rotate(q_1 * q_0, wp.vec3(0.0, 0.0, 1.0))
391
- q_2 = wp.quat_from_axis_angle(axis_2, angles[2])
392
-
393
- q_w = q_p * q_off
394
-
395
- joint_q[q_start + 0] = angles[0]
396
- joint_q[q_start + 1] = angles[1]
397
- joint_q[q_start + 2] = angles[2]
579
+ return
398
580
 
399
- joint_qd[qd_start + 0] = wp.dot(wp.quat_rotate(q_w, axis_0), w_err)
400
- joint_qd[qd_start + 1] = wp.dot(wp.quat_rotate(q_w, axis_1), w_err)
401
- joint_qd[qd_start + 2] = wp.dot(wp.quat_rotate(q_w, axis_2), w_err)
581
+ if type == wp.sim.JOINT_COMPOUND:
582
+ axis_0 = joint_axis[axis_start + 0]
583
+ axis_1 = joint_axis[axis_start + 1]
584
+ axis_2 = joint_axis[axis_start + 2]
585
+ qs, qds = invert_3d_rotational_dofs(axis_0, axis_1, axis_2, q_p, q_c, w_err)
586
+ joint_q[q_start + 0] = qs[0]
587
+ joint_q[q_start + 1] = qs[1]
588
+ joint_q[q_start + 2] = qs[2]
589
+ joint_qd[qd_start + 0] = qds[0]
590
+ joint_qd[qd_start + 1] = qds[1]
591
+ joint_qd[qd_start + 2] = qds[2]
402
592
 
403
593
  return
404
594
 
405
595
  if type == wp.sim.JOINT_UNIVERSAL:
406
- q_off = wp.transform_get_rotation(X_cj)
407
- q_pc = wp.quat_inverse(q_off) * wp.quat_inverse(q_p) * q_c * q_off
408
-
409
- # decompose to a compound rotation each axis
410
- angles = quat_decompose(q_pc)
411
-
412
- # reconstruct rotation axes
413
- axis_0 = wp.vec3(1.0, 0.0, 0.0)
414
- q_0 = wp.quat_from_axis_angle(axis_0, angles[0])
415
-
416
- axis_1 = wp.quat_rotate(q_0, wp.vec3(0.0, 1.0, 0.0))
417
- q_1 = wp.quat_from_axis_angle(axis_1, angles[1])
418
-
419
- q_w = q_p * q_off
420
-
421
- joint_q[q_start + 0] = angles[0]
422
- joint_q[q_start + 1] = angles[1]
423
-
424
- joint_qd[qd_start + 0] = wp.dot(wp.quat_rotate(q_w, axis_0), w_err)
425
- joint_qd[qd_start + 1] = wp.dot(wp.quat_rotate(q_w, axis_1), w_err)
596
+ axis_0 = joint_axis[axis_start + 0]
597
+ axis_1 = joint_axis[axis_start + 1]
598
+ qs2, qds2 = invert_2d_rotational_dofs(axis_0, axis_1, q_p, q_c, w_err)
599
+ joint_q[q_start + 0] = qs2[0]
600
+ joint_q[q_start + 1] = qs2[1]
601
+ joint_qd[qd_start + 0] = qds2[0]
602
+ joint_qd[qd_start + 1] = qds2[1]
426
603
 
427
604
  return
428
605
 
429
606
  if type == wp.sim.JOINT_D6:
607
+ x_err_c = wp.quat_rotate_inv(q_p, x_err)
608
+ v_err_c = wp.quat_rotate_inv(q_p, v_err)
430
609
  if lin_axis_count > 0:
431
- axis = wp.transform_vector(X_wp, joint_axis[axis_start + 0])
432
- joint_q[q_start + 0] = wp.dot(x_err, axis)
433
- joint_qd[qd_start + 0] = wp.dot(v_err, axis)
610
+ axis = joint_axis[axis_start + 0]
611
+ joint_q[q_start + 0] = wp.dot(x_err_c, axis)
612
+ joint_qd[qd_start + 0] = wp.dot(v_err_c, axis)
434
613
 
435
614
  if lin_axis_count > 1:
436
- axis = wp.transform_vector(X_wp, joint_axis[axis_start + 1])
437
- joint_q[q_start + 1] = wp.dot(x_err, axis)
438
- joint_qd[qd_start + 1] = wp.dot(v_err, axis)
615
+ axis = joint_axis[axis_start + 1]
616
+ joint_q[q_start + 1] = wp.dot(x_err_c, axis)
617
+ joint_qd[qd_start + 1] = wp.dot(v_err_c, axis)
439
618
 
440
619
  if lin_axis_count > 2:
441
- axis = wp.transform_vector(X_wp, joint_axis[axis_start + 2])
442
- joint_q[q_start + 2] = wp.dot(x_err, axis)
443
- joint_qd[qd_start + 2] = wp.dot(v_err, axis)
444
-
445
- q_pc = wp.quat_inverse(q_p) * q_c
446
- if ang_axis_count > 0:
447
- axis = wp.transform_vector(X_wp, joint_axis[axis_start + lin_axis_count + 0])
448
- joint_q[q_start + lin_axis_count + 0] = quat_twist_angle(axis, q_pc)
449
- joint_qd[qd_start + lin_axis_count + 0] = wp.dot(w_err, axis)
620
+ axis = joint_axis[axis_start + 2]
621
+ joint_q[q_start + 2] = wp.dot(x_err_c, axis)
622
+ joint_qd[qd_start + 2] = wp.dot(v_err_c, axis)
450
623
 
451
- if ang_axis_count > 1:
452
- axis = wp.transform_vector(X_wp, joint_axis[axis_start + lin_axis_count + 1])
453
- joint_q[q_start + lin_axis_count + 1] = quat_twist_angle(axis, q_pc)
454
- joint_qd[qd_start + lin_axis_count + 1] = wp.dot(w_err, axis)
455
-
456
- if ang_axis_count > 2:
457
- axis = wp.transform_vector(X_wp, joint_axis[axis_start + lin_axis_count + 2])
458
- joint_q[q_start + lin_axis_count + 2] = quat_twist_angle(axis, q_pc)
459
- joint_qd[qd_start + lin_axis_count + 2] = wp.dot(w_err, axis)
624
+ if ang_axis_count == 1:
625
+ axis = joint_axis[axis_start]
626
+ q_pc = wp.quat_inverse(q_p) * q_c
627
+ q, qd = reconstruct_angular_q_qd(q_pc, w_err, X_wpj, joint_axis[axis_start + lin_axis_count])
628
+ joint_q[q_start + lin_axis_count] = q
629
+ joint_qd[qd_start + lin_axis_count] = qd
630
+
631
+ if ang_axis_count == 2:
632
+ axis_0 = joint_axis[axis_start + lin_axis_count + 0]
633
+ axis_1 = joint_axis[axis_start + lin_axis_count + 1]
634
+ qs2, qds2 = invert_2d_rotational_dofs(axis_0, axis_1, q_p, q_c, w_err)
635
+ joint_q[q_start + lin_axis_count + 0] = qs2[0]
636
+ joint_q[q_start + lin_axis_count + 1] = qs2[1]
637
+ joint_qd[qd_start + lin_axis_count + 0] = qds2[0]
638
+ joint_qd[qd_start + lin_axis_count + 1] = qds2[1]
639
+
640
+ if ang_axis_count == 3:
641
+ axis_0 = joint_axis[axis_start + lin_axis_count + 0]
642
+ axis_1 = joint_axis[axis_start + lin_axis_count + 1]
643
+ axis_2 = joint_axis[axis_start + lin_axis_count + 2]
644
+ qs3, qds3 = invert_3d_rotational_dofs(axis_0, axis_1, axis_2, q_p, q_c, w_err)
645
+ joint_q[q_start + lin_axis_count + 0] = qs3[0]
646
+ joint_q[q_start + lin_axis_count + 1] = qs3[1]
647
+ joint_q[q_start + lin_axis_count + 2] = qs3[2]
648
+ joint_qd[qd_start + lin_axis_count + 0] = qds3[0]
649
+ joint_qd[qd_start + lin_axis_count + 1] = qds3[1]
650
+ joint_qd[qd_start + lin_axis_count + 2] = qds3[2]
460
651
 
461
652
  return
462
653
 
463
654
 
464
655
  # given maximal coordinate model computes ik (closest point projection)
465
656
  def eval_ik(model, state, joint_q, joint_qd):
657
+ """
658
+ 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`.
659
+
660
+ Args:
661
+ model (Model): The model to evaluate.
662
+ state (State): The state with the body's maximal coordinates (positions :attr:`State.body_q` and velocities :attr:`State.body_qd`) to use.
663
+ joint_q (array): Generalized joint position coordinates, shape [joint_coord_count], float
664
+ joint_qd (array): Generalized joint velocity coordinates, shape [joint_dof_count], float
665
+ """
466
666
  wp.launch(
467
667
  kernel=eval_articulation_ik,
468
668
  dim=model.joint_count,