roboticstoolbox-python 1.4.0__py3-none-any.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.
Files changed (610) hide show
  1. roboticstoolbox/__init__.py +107 -0
  2. roboticstoolbox/backends/Connector.py +113 -0
  3. roboticstoolbox/backends/Dynamixel/README.md +9 -0
  4. roboticstoolbox/backends/Dynamixel/dynamixel.json +581 -0
  5. roboticstoolbox/backends/Dynamixel/dynamixel_io.py +450 -0
  6. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/LICENSE +201 -0
  7. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/README.md +28 -0
  8. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/ReleaseNote.md +181 -0
  9. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/__init__.py +27 -0
  10. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/group_bulk_read.py +163 -0
  11. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/group_bulk_write.py +109 -0
  12. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/group_sync_read.py +166 -0
  13. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/group_sync_write.py +99 -0
  14. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/packet_handler.py +33 -0
  15. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/port_handler.py +155 -0
  16. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/protocol1_packet_handler.py +548 -0
  17. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/protocol2_packet_handler.py +1080 -0
  18. roboticstoolbox/backends/Dynamixel/dynamixel_sdk/robotis_def.py +75 -0
  19. roboticstoolbox/backends/Dynamixel/dyndata.py +121 -0
  20. roboticstoolbox/backends/PyPlot/EllipsePlot.py +256 -0
  21. roboticstoolbox/backends/PyPlot/PyPlot.py +778 -0
  22. roboticstoolbox/backends/PyPlot/PyPlot2.py +537 -0
  23. roboticstoolbox/backends/PyPlot/README.md +67 -0
  24. roboticstoolbox/backends/PyPlot/RobotPlot.py +247 -0
  25. roboticstoolbox/backends/PyPlot/RobotPlot2.py +123 -0
  26. roboticstoolbox/backends/PyPlot/__init__.py +4 -0
  27. roboticstoolbox/backends/ROS/ROS.py +129 -0
  28. roboticstoolbox/backends/ROS/__init__.py +3 -0
  29. roboticstoolbox/backends/__init__.py +39 -0
  30. roboticstoolbox/backends/swift/__init__.py +165 -0
  31. roboticstoolbox/bin/__init__.py +0 -0
  32. roboticstoolbox/bin/_bintools.py +61 -0
  33. roboticstoolbox/bin/rtbtool.py +404 -0
  34. roboticstoolbox/blocks/Icons/250x250/armplot.png +0 -0
  35. roboticstoolbox/blocks/Icons/250x250/bicycle.png +0 -0
  36. roboticstoolbox/blocks/Icons/250x250/camera.png +0 -0
  37. roboticstoolbox/blocks/Icons/250x250/circlepath.png +0 -0
  38. roboticstoolbox/blocks/Icons/250x250/coriolis.png +0 -0
  39. roboticstoolbox/blocks/Icons/250x250/ctraj.png +0 -0
  40. roboticstoolbox/blocks/Icons/250x250/delta2tr.png +0 -0
  41. roboticstoolbox/blocks/Icons/250x250/diffsteer.png +0 -0
  42. roboticstoolbox/blocks/Icons/250x250/fdyn.png +0 -0
  43. roboticstoolbox/blocks/Icons/250x250/fdynx.png +0 -0
  44. roboticstoolbox/blocks/Icons/250x250/fkine.png +0 -0
  45. roboticstoolbox/blocks/Icons/250x250/gravload.png +0 -0
  46. roboticstoolbox/blocks/Icons/250x250/idyn.png +0 -0
  47. roboticstoolbox/blocks/Icons/250x250/idynx.png +0 -0
  48. roboticstoolbox/blocks/Icons/250x250/ikine.png +0 -0
  49. roboticstoolbox/blocks/Icons/250x250/inertia.png +0 -0
  50. roboticstoolbox/blocks/Icons/250x250/jacobian.png +0 -0
  51. roboticstoolbox/blocks/Icons/250x250/jtraj.png +0 -0
  52. roboticstoolbox/blocks/Icons/250x250/lspb.png +0 -0
  53. roboticstoolbox/blocks/Icons/250x250/multirotor.png +0 -0
  54. roboticstoolbox/blocks/Icons/250x250/multirotormixer.png +0 -0
  55. roboticstoolbox/blocks/Icons/250x250/multirotorplot.png +0 -0
  56. roboticstoolbox/blocks/Icons/250x250/point2tr.png +0 -0
  57. roboticstoolbox/blocks/Icons/250x250/tr2delta.png +0 -0
  58. roboticstoolbox/blocks/Icons/250x250/tr2t.png +0 -0
  59. roboticstoolbox/blocks/Icons/250x250/unicycle.png +0 -0
  60. roboticstoolbox/blocks/Icons/250x250/vehicleplot.png +0 -0
  61. roboticstoolbox/blocks/Icons/50x50/armplot.png +0 -0
  62. roboticstoolbox/blocks/Icons/50x50/bicycle.png +0 -0
  63. roboticstoolbox/blocks/Icons/50x50/camera.png +0 -0
  64. roboticstoolbox/blocks/Icons/50x50/circlepath.png +0 -0
  65. roboticstoolbox/blocks/Icons/50x50/coriolis.png +0 -0
  66. roboticstoolbox/blocks/Icons/50x50/delta2tr.png +0 -0
  67. roboticstoolbox/blocks/Icons/50x50/diffsteer.png +0 -0
  68. roboticstoolbox/blocks/Icons/50x50/fdyn.png +0 -0
  69. roboticstoolbox/blocks/Icons/50x50/fdynx.png +0 -0
  70. roboticstoolbox/blocks/Icons/50x50/fkine.png +0 -0
  71. roboticstoolbox/blocks/Icons/50x50/gravload.png +0 -0
  72. roboticstoolbox/blocks/Icons/50x50/idyn.png +0 -0
  73. roboticstoolbox/blocks/Icons/50x50/idynx.png +0 -0
  74. roboticstoolbox/blocks/Icons/50x50/ikine.png +0 -0
  75. roboticstoolbox/blocks/Icons/50x50/inertia.png +0 -0
  76. roboticstoolbox/blocks/Icons/50x50/jacobian.png +0 -0
  77. roboticstoolbox/blocks/Icons/50x50/jtraj.png +0 -0
  78. roboticstoolbox/blocks/Icons/50x50/lspb.png +0 -0
  79. roboticstoolbox/blocks/Icons/50x50/multirotor.png +0 -0
  80. roboticstoolbox/blocks/Icons/50x50/multirotormixer.png +0 -0
  81. roboticstoolbox/blocks/Icons/50x50/multirotorplot.png +0 -0
  82. roboticstoolbox/blocks/Icons/50x50/point2tr.png +0 -0
  83. roboticstoolbox/blocks/Icons/50x50/tr2delta.png +0 -0
  84. roboticstoolbox/blocks/Icons/50x50/tr2t.png +0 -0
  85. roboticstoolbox/blocks/Icons/50x50/unicycle.png +0 -0
  86. roboticstoolbox/blocks/Icons/50x50/vehicleplot.png +0 -0
  87. roboticstoolbox/blocks/Icons/armplot.png +0 -0
  88. roboticstoolbox/blocks/Icons/bicycle.png +0 -0
  89. roboticstoolbox/blocks/Icons/camera.png +0 -0
  90. roboticstoolbox/blocks/Icons/circlepath.png +0 -0
  91. roboticstoolbox/blocks/Icons/coriolis.png +0 -0
  92. roboticstoolbox/blocks/Icons/ctraj.png +0 -0
  93. roboticstoolbox/blocks/Icons/delta2tr.png +0 -0
  94. roboticstoolbox/blocks/Icons/diffsteer.png +0 -0
  95. roboticstoolbox/blocks/Icons/fdyn.png +0 -0
  96. roboticstoolbox/blocks/Icons/fdynx.png +0 -0
  97. roboticstoolbox/blocks/Icons/fkine.png +0 -0
  98. roboticstoolbox/blocks/Icons/gravload.png +0 -0
  99. roboticstoolbox/blocks/Icons/idyn.png +0 -0
  100. roboticstoolbox/blocks/Icons/idynx.png +0 -0
  101. roboticstoolbox/blocks/Icons/ikine.png +0 -0
  102. roboticstoolbox/blocks/Icons/inertia.png +0 -0
  103. roboticstoolbox/blocks/Icons/jacobian.png +0 -0
  104. roboticstoolbox/blocks/Icons/jtraj.png +0 -0
  105. roboticstoolbox/blocks/Icons/lspb.png +0 -0
  106. roboticstoolbox/blocks/Icons/multirotor.png +0 -0
  107. roboticstoolbox/blocks/Icons/multirotormixer.png +0 -0
  108. roboticstoolbox/blocks/Icons/multirotorplot.png +0 -0
  109. roboticstoolbox/blocks/Icons/point2tr.png +0 -0
  110. roboticstoolbox/blocks/Icons/tr2delta.png +0 -0
  111. roboticstoolbox/blocks/Icons/tr2t.png +0 -0
  112. roboticstoolbox/blocks/Icons/unicycle.png +0 -0
  113. roboticstoolbox/blocks/Icons/vehicleplot.png +0 -0
  114. roboticstoolbox/blocks/README.md +43 -0
  115. roboticstoolbox/blocks/__init__.py +6 -0
  116. roboticstoolbox/blocks/arm.py +1591 -0
  117. roboticstoolbox/blocks/mobile.py +522 -0
  118. roboticstoolbox/blocks/quad_model.py +132 -0
  119. roboticstoolbox/blocks/spatial.py +245 -0
  120. roboticstoolbox/blocks/uav.py +949 -0
  121. roboticstoolbox/demo/__init__.py +0 -0
  122. roboticstoolbox/demo/eigdemo.py +112 -0
  123. roboticstoolbox/demo/tripleangledemo.py +239 -0
  124. roboticstoolbox/demo/twistdemo.py +175 -0
  125. roboticstoolbox/ets/ET.py +439 -0
  126. roboticstoolbox/ets/ET2.py +179 -0
  127. roboticstoolbox/ets/ETS.py +2013 -0
  128. roboticstoolbox/ets/ETS2.py +449 -0
  129. roboticstoolbox/ets/_ET.py +668 -0
  130. roboticstoolbox/ets/_ETS.py +781 -0
  131. roboticstoolbox/ets/__init__.py +11 -0
  132. roboticstoolbox/ets/cpp-extensions/Eigen/Cholesky +45 -0
  133. roboticstoolbox/ets/cpp-extensions/Eigen/CholmodSupport +48 -0
  134. roboticstoolbox/ets/cpp-extensions/Eigen/Core +384 -0
  135. roboticstoolbox/ets/cpp-extensions/Eigen/Dense +7 -0
  136. roboticstoolbox/ets/cpp-extensions/Eigen/Eigen +2 -0
  137. roboticstoolbox/ets/cpp-extensions/Eigen/Eigenvalues +60 -0
  138. roboticstoolbox/ets/cpp-extensions/Eigen/Geometry +59 -0
  139. roboticstoolbox/ets/cpp-extensions/Eigen/Householder +29 -0
  140. roboticstoolbox/ets/cpp-extensions/Eigen/IterativeLinearSolvers +48 -0
  141. roboticstoolbox/ets/cpp-extensions/Eigen/Jacobi +32 -0
  142. roboticstoolbox/ets/cpp-extensions/Eigen/KLUSupport +41 -0
  143. roboticstoolbox/ets/cpp-extensions/Eigen/LU +47 -0
  144. roboticstoolbox/ets/cpp-extensions/Eigen/MetisSupport +35 -0
  145. roboticstoolbox/ets/cpp-extensions/Eigen/OrderingMethods +70 -0
  146. roboticstoolbox/ets/cpp-extensions/Eigen/PaStiXSupport +49 -0
  147. roboticstoolbox/ets/cpp-extensions/Eigen/PardisoSupport +35 -0
  148. roboticstoolbox/ets/cpp-extensions/Eigen/QR +50 -0
  149. roboticstoolbox/ets/cpp-extensions/Eigen/QtAlignedMalloc +39 -0
  150. roboticstoolbox/ets/cpp-extensions/Eigen/SPQRSupport +34 -0
  151. roboticstoolbox/ets/cpp-extensions/Eigen/SVD +50 -0
  152. roboticstoolbox/ets/cpp-extensions/Eigen/Sparse +34 -0
  153. roboticstoolbox/ets/cpp-extensions/Eigen/SparseCholesky +37 -0
  154. roboticstoolbox/ets/cpp-extensions/Eigen/SparseCore +69 -0
  155. roboticstoolbox/ets/cpp-extensions/Eigen/SparseLU +50 -0
  156. roboticstoolbox/ets/cpp-extensions/Eigen/SparseQR +36 -0
  157. roboticstoolbox/ets/cpp-extensions/Eigen/StdDeque +27 -0
  158. roboticstoolbox/ets/cpp-extensions/Eigen/StdList +26 -0
  159. roboticstoolbox/ets/cpp-extensions/Eigen/StdVector +27 -0
  160. roboticstoolbox/ets/cpp-extensions/Eigen/SuperLUSupport +64 -0
  161. roboticstoolbox/ets/cpp-extensions/Eigen/UmfPackSupport +40 -0
  162. roboticstoolbox/ets/cpp-extensions/Eigen/src/Cholesky/LDLT.h +688 -0
  163. roboticstoolbox/ets/cpp-extensions/Eigen/src/Cholesky/LLT.h +558 -0
  164. roboticstoolbox/ets/cpp-extensions/Eigen/src/Cholesky/LLT_LAPACKE.h +99 -0
  165. roboticstoolbox/ets/cpp-extensions/Eigen/src/CholmodSupport/CholmodSupport.h +682 -0
  166. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/ArithmeticSequence.h +413 -0
  167. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Array.h +417 -0
  168. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/ArrayBase.h +226 -0
  169. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/ArrayWrapper.h +209 -0
  170. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Assign.h +90 -0
  171. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/AssignEvaluator.h +1010 -0
  172. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Assign_MKL.h +178 -0
  173. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/BandMatrix.h +353 -0
  174. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Block.h +448 -0
  175. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/BooleanRedux.h +162 -0
  176. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/CommaInitializer.h +164 -0
  177. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/ConditionEstimator.h +175 -0
  178. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/CoreEvaluators.h +1741 -0
  179. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/CoreIterators.h +132 -0
  180. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/CwiseBinaryOp.h +183 -0
  181. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/CwiseNullaryOp.h +1001 -0
  182. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/CwiseTernaryOp.h +197 -0
  183. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/CwiseUnaryOp.h +103 -0
  184. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/CwiseUnaryView.h +132 -0
  185. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/DenseBase.h +701 -0
  186. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/DenseCoeffsBase.h +685 -0
  187. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/DenseStorage.h +652 -0
  188. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Diagonal.h +258 -0
  189. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/DiagonalMatrix.h +391 -0
  190. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/DiagonalProduct.h +28 -0
  191. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Dot.h +318 -0
  192. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/EigenBase.h +160 -0
  193. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/ForceAlignedAccess.h +150 -0
  194. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Fuzzy.h +155 -0
  195. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/GeneralProduct.h +465 -0
  196. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/GenericPacketMath.h +1040 -0
  197. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/GlobalFunctions.h +194 -0
  198. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/IO.h +258 -0
  199. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/IndexedView.h +237 -0
  200. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Inverse.h +117 -0
  201. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Map.h +171 -0
  202. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/MapBase.h +310 -0
  203. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/MathFunctions.h +2057 -0
  204. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/MathFunctionsImpl.h +200 -0
  205. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Matrix.h +565 -0
  206. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/MatrixBase.h +547 -0
  207. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/NestByValue.h +85 -0
  208. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/NoAlias.h +109 -0
  209. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/NumTraits.h +335 -0
  210. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/PartialReduxEvaluator.h +232 -0
  211. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/PermutationMatrix.h +605 -0
  212. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/PlainObjectBase.h +1128 -0
  213. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Product.h +191 -0
  214. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/ProductEvaluators.h +1179 -0
  215. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Random.h +218 -0
  216. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Redux.h +515 -0
  217. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Ref.h +381 -0
  218. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Replicate.h +142 -0
  219. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Reshaped.h +454 -0
  220. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/ReturnByValue.h +119 -0
  221. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Reverse.h +217 -0
  222. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Select.h +164 -0
  223. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/SelfAdjointView.h +365 -0
  224. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/SelfCwiseBinaryOp.h +47 -0
  225. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Solve.h +188 -0
  226. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/SolveTriangular.h +235 -0
  227. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/SolverBase.h +168 -0
  228. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/StableNorm.h +251 -0
  229. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/StlIterators.h +463 -0
  230. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Stride.h +116 -0
  231. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Swap.h +68 -0
  232. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Transpose.h +464 -0
  233. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Transpositions.h +386 -0
  234. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/TriangularMatrix.h +1001 -0
  235. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/VectorBlock.h +96 -0
  236. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/VectorwiseOp.h +784 -0
  237. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/Visitor.h +381 -0
  238. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AVX/Complex.h +372 -0
  239. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AVX/MathFunctions.h +228 -0
  240. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AVX/PacketMath.h +1574 -0
  241. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AVX/TypeCasting.h +115 -0
  242. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AVX512/Complex.h +422 -0
  243. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AVX512/MathFunctions.h +362 -0
  244. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AVX512/PacketMath.h +2303 -0
  245. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AVX512/TypeCasting.h +89 -0
  246. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AltiVec/Complex.h +417 -0
  247. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AltiVec/MathFunctions.h +90 -0
  248. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AltiVec/MatrixProduct.h +2937 -0
  249. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AltiVec/MatrixProductCommon.h +221 -0
  250. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h +629 -0
  251. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/AltiVec/PacketMath.h +2711 -0
  252. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/CUDA/Complex.h +258 -0
  253. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/Default/BFloat16.h +700 -0
  254. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/Default/ConjHelper.h +117 -0
  255. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h +1649 -0
  256. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/Default/GenericPacketMathFunctionsFwd.h +110 -0
  257. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/Default/Half.h +942 -0
  258. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/Default/Settings.h +49 -0
  259. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/Default/TypeCasting.h +120 -0
  260. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/GPU/MathFunctions.h +103 -0
  261. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/GPU/PacketMath.h +1685 -0
  262. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/GPU/TypeCasting.h +80 -0
  263. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/HIP/hcc/math_constants.h +23 -0
  264. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/MSA/Complex.h +648 -0
  265. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/MSA/MathFunctions.h +387 -0
  266. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/MSA/PacketMath.h +1233 -0
  267. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/NEON/Complex.h +584 -0
  268. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/NEON/GeneralBlockPanelKernel.h +183 -0
  269. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/NEON/MathFunctions.h +75 -0
  270. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/NEON/PacketMath.h +4587 -0
  271. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/NEON/TypeCasting.h +1419 -0
  272. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SSE/Complex.h +351 -0
  273. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SSE/MathFunctions.h +199 -0
  274. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SSE/PacketMath.h +1505 -0
  275. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SSE/TypeCasting.h +142 -0
  276. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SVE/MathFunctions.h +44 -0
  277. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SVE/PacketMath.h +752 -0
  278. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SVE/TypeCasting.h +49 -0
  279. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SYCL/InteropHeaders.h +232 -0
  280. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SYCL/MathFunctions.h +301 -0
  281. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SYCL/PacketMath.h +670 -0
  282. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SYCL/SyclMemoryModel.h +694 -0
  283. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/SYCL/TypeCasting.h +85 -0
  284. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/ZVector/Complex.h +426 -0
  285. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/ZVector/MathFunctions.h +233 -0
  286. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/arch/ZVector/PacketMath.h +1060 -0
  287. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/functors/AssignmentFunctors.h +177 -0
  288. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/functors/BinaryFunctors.h +541 -0
  289. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/functors/NullaryFunctors.h +189 -0
  290. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/functors/StlFunctors.h +166 -0
  291. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/functors/TernaryFunctors.h +25 -0
  292. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/functors/UnaryFunctors.h +1131 -0
  293. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/GeneralBlockPanelKernel.h +2645 -0
  294. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/GeneralMatrixMatrix.h +517 -0
  295. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h +317 -0
  296. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h +145 -0
  297. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h +124 -0
  298. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/GeneralMatrixVector.h +518 -0
  299. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h +136 -0
  300. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/Parallelizer.h +180 -0
  301. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/SelfadjointMatrixMatrix.h +544 -0
  302. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h +295 -0
  303. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/SelfadjointMatrixVector.h +262 -0
  304. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h +118 -0
  305. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/SelfadjointProduct.h +133 -0
  306. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/SelfadjointRank2Update.h +94 -0
  307. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/TriangularMatrixMatrix.h +472 -0
  308. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h +317 -0
  309. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/TriangularMatrixVector.h +350 -0
  310. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h +255 -0
  311. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/TriangularSolverMatrix.h +337 -0
  312. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h +167 -0
  313. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/products/TriangularSolverVector.h +148 -0
  314. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/BlasUtil.h +583 -0
  315. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/ConfigureVectorization.h +512 -0
  316. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/Constants.h +563 -0
  317. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/DisableStupidWarnings.h +106 -0
  318. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/ForwardDeclarations.h +322 -0
  319. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/IndexedViewHelper.h +186 -0
  320. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/IntegralConstant.h +272 -0
  321. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/MKL_support.h +137 -0
  322. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/Macros.h +1464 -0
  323. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/Memory.h +1163 -0
  324. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/Meta.h +812 -0
  325. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/NonMPL2.h +3 -0
  326. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/ReenableStupidWarnings.h +31 -0
  327. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/ReshapedHelper.h +51 -0
  328. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/StaticAssert.h +221 -0
  329. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/SymbolicIndex.h +293 -0
  330. roboticstoolbox/ets/cpp-extensions/Eigen/src/Core/util/XprHelper.h +856 -0
  331. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/ComplexEigenSolver.h +346 -0
  332. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/ComplexSchur.h +462 -0
  333. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h +91 -0
  334. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/EigenSolver.h +622 -0
  335. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h +418 -0
  336. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h +226 -0
  337. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/HessenbergDecomposition.h +374 -0
  338. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h +158 -0
  339. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/RealQZ.h +657 -0
  340. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/RealSchur.h +558 -0
  341. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h +77 -0
  342. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h +904 -0
  343. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h +87 -0
  344. roboticstoolbox/ets/cpp-extensions/Eigen/src/Eigenvalues/Tridiagonalization.h +561 -0
  345. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/AlignedBox.h +486 -0
  346. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/AngleAxis.h +247 -0
  347. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/EulerAngles.h +114 -0
  348. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/Homogeneous.h +501 -0
  349. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/Hyperplane.h +282 -0
  350. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/OrthoMethods.h +235 -0
  351. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/ParametrizedLine.h +232 -0
  352. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/Quaternion.h +870 -0
  353. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/Rotation2D.h +199 -0
  354. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/RotationBase.h +206 -0
  355. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/Scaling.h +188 -0
  356. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/Transform.h +1563 -0
  357. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/Translation.h +202 -0
  358. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/Umeyama.h +166 -0
  359. roboticstoolbox/ets/cpp-extensions/Eigen/src/Geometry/arch/Geometry_SIMD.h +168 -0
  360. roboticstoolbox/ets/cpp-extensions/Eigen/src/Householder/BlockHouseholder.h +110 -0
  361. roboticstoolbox/ets/cpp-extensions/Eigen/src/Householder/Householder.h +176 -0
  362. roboticstoolbox/ets/cpp-extensions/Eigen/src/Householder/HouseholderSequence.h +545 -0
  363. roboticstoolbox/ets/cpp-extensions/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h +226 -0
  364. roboticstoolbox/ets/cpp-extensions/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h +212 -0
  365. roboticstoolbox/ets/cpp-extensions/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h +229 -0
  366. roboticstoolbox/ets/cpp-extensions/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h +394 -0
  367. roboticstoolbox/ets/cpp-extensions/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h +453 -0
  368. roboticstoolbox/ets/cpp-extensions/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h +444 -0
  369. roboticstoolbox/ets/cpp-extensions/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h +198 -0
  370. roboticstoolbox/ets/cpp-extensions/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h +117 -0
  371. roboticstoolbox/ets/cpp-extensions/Eigen/src/Jacobi/Jacobi.h +483 -0
  372. roboticstoolbox/ets/cpp-extensions/Eigen/src/KLUSupport/KLUSupport.h +358 -0
  373. roboticstoolbox/ets/cpp-extensions/Eigen/src/LU/Determinant.h +117 -0
  374. roboticstoolbox/ets/cpp-extensions/Eigen/src/LU/FullPivLU.h +877 -0
  375. roboticstoolbox/ets/cpp-extensions/Eigen/src/LU/InverseImpl.h +432 -0
  376. roboticstoolbox/ets/cpp-extensions/Eigen/src/LU/PartialPivLU.h +624 -0
  377. roboticstoolbox/ets/cpp-extensions/Eigen/src/LU/PartialPivLU_LAPACKE.h +83 -0
  378. roboticstoolbox/ets/cpp-extensions/Eigen/src/LU/arch/InverseSize4.h +351 -0
  379. roboticstoolbox/ets/cpp-extensions/Eigen/src/MetisSupport/MetisSupport.h +137 -0
  380. roboticstoolbox/ets/cpp-extensions/Eigen/src/OrderingMethods/Amd.h +435 -0
  381. roboticstoolbox/ets/cpp-extensions/Eigen/src/OrderingMethods/Eigen_Colamd.h +1863 -0
  382. roboticstoolbox/ets/cpp-extensions/Eigen/src/OrderingMethods/Ordering.h +153 -0
  383. roboticstoolbox/ets/cpp-extensions/Eigen/src/PaStiXSupport/PaStiXSupport.h +678 -0
  384. roboticstoolbox/ets/cpp-extensions/Eigen/src/PardisoSupport/PardisoSupport.h +545 -0
  385. roboticstoolbox/ets/cpp-extensions/Eigen/src/QR/ColPivHouseholderQR.h +674 -0
  386. roboticstoolbox/ets/cpp-extensions/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h +97 -0
  387. roboticstoolbox/ets/cpp-extensions/Eigen/src/QR/CompleteOrthogonalDecomposition.h +635 -0
  388. roboticstoolbox/ets/cpp-extensions/Eigen/src/QR/FullPivHouseholderQR.h +713 -0
  389. roboticstoolbox/ets/cpp-extensions/Eigen/src/QR/HouseholderQR.h +434 -0
  390. roboticstoolbox/ets/cpp-extensions/Eigen/src/QR/HouseholderQR_LAPACKE.h +68 -0
  391. roboticstoolbox/ets/cpp-extensions/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h +335 -0
  392. roboticstoolbox/ets/cpp-extensions/Eigen/src/SVD/BDCSVD.h +1366 -0
  393. roboticstoolbox/ets/cpp-extensions/Eigen/src/SVD/JacobiSVD.h +812 -0
  394. roboticstoolbox/ets/cpp-extensions/Eigen/src/SVD/JacobiSVD_LAPACKE.h +91 -0
  395. roboticstoolbox/ets/cpp-extensions/Eigen/src/SVD/SVDBase.h +376 -0
  396. roboticstoolbox/ets/cpp-extensions/Eigen/src/SVD/UpperBidiagonalization.h +414 -0
  397. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCholesky/SimplicialCholesky.h +697 -0
  398. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h +174 -0
  399. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/AmbiVector.h +378 -0
  400. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/CompressedStorage.h +274 -0
  401. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h +352 -0
  402. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/MappedSparseMatrix.h +67 -0
  403. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseAssign.h +270 -0
  404. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseBlock.h +571 -0
  405. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseColEtree.h +206 -0
  406. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseCompressedBase.h +370 -0
  407. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +722 -0
  408. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +150 -0
  409. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseDenseProduct.h +342 -0
  410. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseDiagonalProduct.h +138 -0
  411. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseDot.h +98 -0
  412. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseFuzzy.h +29 -0
  413. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseMap.h +305 -0
  414. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseMatrix.h +1518 -0
  415. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseMatrixBase.h +398 -0
  416. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparsePermutation.h +178 -0
  417. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseProduct.h +181 -0
  418. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseRedux.h +49 -0
  419. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseRef.h +397 -0
  420. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseSelfAdjointView.h +659 -0
  421. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseSolverBase.h +124 -0
  422. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseSparseProductWithPruning.h +198 -0
  423. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseTranspose.h +92 -0
  424. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseTriangularView.h +189 -0
  425. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseUtil.h +186 -0
  426. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseVector.h +478 -0
  427. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/SparseView.h +254 -0
  428. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseCore/TriangularSolver.h +315 -0
  429. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU.h +923 -0
  430. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLUImpl.h +66 -0
  431. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_Memory.h +226 -0
  432. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_Structs.h +110 -0
  433. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h +375 -0
  434. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_Utils.h +80 -0
  435. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_column_bmod.h +181 -0
  436. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_column_dfs.h +179 -0
  437. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h +107 -0
  438. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_gemm_kernel.h +280 -0
  439. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h +126 -0
  440. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_kernel_bmod.h +130 -0
  441. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_panel_bmod.h +223 -0
  442. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_panel_dfs.h +258 -0
  443. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_pivotL.h +137 -0
  444. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_pruneL.h +136 -0
  445. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseLU/SparseLU_relax_snode.h +83 -0
  446. roboticstoolbox/ets/cpp-extensions/Eigen/src/SparseQR/SparseQR.h +758 -0
  447. roboticstoolbox/ets/cpp-extensions/Eigen/src/StlSupport/StdDeque.h +116 -0
  448. roboticstoolbox/ets/cpp-extensions/Eigen/src/StlSupport/StdList.h +106 -0
  449. roboticstoolbox/ets/cpp-extensions/Eigen/src/StlSupport/StdVector.h +131 -0
  450. roboticstoolbox/ets/cpp-extensions/Eigen/src/StlSupport/details.h +84 -0
  451. roboticstoolbox/ets/cpp-extensions/Eigen/src/SuperLUSupport/SuperLUSupport.h +1025 -0
  452. roboticstoolbox/ets/cpp-extensions/Eigen/src/UmfPackSupport/UmfPackSupport.h +642 -0
  453. roboticstoolbox/ets/cpp-extensions/Eigen/src/misc/Image.h +82 -0
  454. roboticstoolbox/ets/cpp-extensions/Eigen/src/misc/Kernel.h +79 -0
  455. roboticstoolbox/ets/cpp-extensions/Eigen/src/misc/RealSvd2x2.h +55 -0
  456. roboticstoolbox/ets/cpp-extensions/Eigen/src/misc/blas.h +440 -0
  457. roboticstoolbox/ets/cpp-extensions/Eigen/src/misc/lapack.h +152 -0
  458. roboticstoolbox/ets/cpp-extensions/Eigen/src/misc/lapacke.h +16292 -0
  459. roboticstoolbox/ets/cpp-extensions/Eigen/src/misc/lapacke_mangling.h +17 -0
  460. roboticstoolbox/ets/cpp-extensions/Eigen/src/plugins/ArrayCwiseBinaryOps.h +358 -0
  461. roboticstoolbox/ets/cpp-extensions/Eigen/src/plugins/ArrayCwiseUnaryOps.h +696 -0
  462. roboticstoolbox/ets/cpp-extensions/Eigen/src/plugins/BlockMethods.h +1442 -0
  463. roboticstoolbox/ets/cpp-extensions/Eigen/src/plugins/CommonCwiseBinaryOps.h +115 -0
  464. roboticstoolbox/ets/cpp-extensions/Eigen/src/plugins/CommonCwiseUnaryOps.h +177 -0
  465. roboticstoolbox/ets/cpp-extensions/Eigen/src/plugins/IndexedViewMethods.h +262 -0
  466. roboticstoolbox/ets/cpp-extensions/Eigen/src/plugins/MatrixCwiseBinaryOps.h +152 -0
  467. roboticstoolbox/ets/cpp-extensions/Eigen/src/plugins/MatrixCwiseUnaryOps.h +95 -0
  468. roboticstoolbox/ets/cpp-extensions/Eigen/src/plugins/ReshapedMethods.h +149 -0
  469. roboticstoolbox/ets/cpp-extensions/README.md +73 -0
  470. roboticstoolbox/ets/cpp-extensions/fknm_nb.cpp +534 -0
  471. roboticstoolbox/ets/cpp-extensions/ik.cpp +301 -0
  472. roboticstoolbox/ets/cpp-extensions/ik.h +59 -0
  473. roboticstoolbox/ets/cpp-extensions/linalg.cpp +316 -0
  474. roboticstoolbox/ets/cpp-extensions/linalg.h +64 -0
  475. roboticstoolbox/ets/cpp-extensions/methods.cpp +372 -0
  476. roboticstoolbox/ets/cpp-extensions/methods.h +32 -0
  477. roboticstoolbox/ets/cpp-extensions/structs.cpp +24 -0
  478. roboticstoolbox/ets/cpp-extensions/structs.h +62 -0
  479. roboticstoolbox/ets/fknm.py +366 -0
  480. roboticstoolbox/mobile/Animations.py +485 -0
  481. roboticstoolbox/mobile/Bug2.py +455 -0
  482. roboticstoolbox/mobile/CurvaturePolyPlanner.py +179 -0
  483. roboticstoolbox/mobile/DistanceTransformPlanner.py +395 -0
  484. roboticstoolbox/mobile/DstarPlanner.py +591 -0
  485. roboticstoolbox/mobile/DubinsPlanner.py +474 -0
  486. roboticstoolbox/mobile/EKF.py +1617 -0
  487. roboticstoolbox/mobile/LatticePlanner.py +419 -0
  488. roboticstoolbox/mobile/OccGrid.py +613 -0
  489. roboticstoolbox/mobile/PRMPlanner.py +348 -0
  490. roboticstoolbox/mobile/ParticleFilter.py +706 -0
  491. roboticstoolbox/mobile/PlannerBase.py +1009 -0
  492. roboticstoolbox/mobile/PoseGraph.py +544 -0
  493. roboticstoolbox/mobile/QuinticPolyPlanner.py +349 -0
  494. roboticstoolbox/mobile/RRTPlanner.py +359 -0
  495. roboticstoolbox/mobile/ReedsSheppPlanner.py +545 -0
  496. roboticstoolbox/mobile/Vehicle.py +1909 -0
  497. roboticstoolbox/mobile/__init__.py +194 -0
  498. roboticstoolbox/mobile/drivers.py +397 -0
  499. roboticstoolbox/mobile/landmarkmap.py +181 -0
  500. roboticstoolbox/mobile/sensors.py +789 -0
  501. roboticstoolbox/models/DH/AL5D.py +121 -0
  502. roboticstoolbox/models/DH/Ball.py +87 -0
  503. roboticstoolbox/models/DH/Baxter.py +91 -0
  504. roboticstoolbox/models/DH/Cobra600.py +63 -0
  505. roboticstoolbox/models/DH/Coil.py +80 -0
  506. roboticstoolbox/models/DH/Hyper.py +81 -0
  507. roboticstoolbox/models/DH/Hyper3d.py +83 -0
  508. roboticstoolbox/models/DH/IRB140.py +159 -0
  509. roboticstoolbox/models/DH/Jaco.py +102 -0
  510. roboticstoolbox/models/DH/KR5.py +112 -0
  511. roboticstoolbox/models/DH/LWR4.py +80 -0
  512. roboticstoolbox/models/DH/Mico.py +102 -0
  513. roboticstoolbox/models/DH/Orion5.py +91 -0
  514. roboticstoolbox/models/DH/P8.py +80 -0
  515. roboticstoolbox/models/DH/Panda.py +213 -0
  516. roboticstoolbox/models/DH/Planar2.py +69 -0
  517. roboticstoolbox/models/DH/Planar3.py +51 -0
  518. roboticstoolbox/models/DH/Puma560.py +326 -0
  519. roboticstoolbox/models/DH/README.md +216 -0
  520. roboticstoolbox/models/DH/Sawyer.py +85 -0
  521. roboticstoolbox/models/DH/Stanford.py +147 -0
  522. roboticstoolbox/models/DH/TwoLink.py +153 -0
  523. roboticstoolbox/models/DH/UR10.py +124 -0
  524. roboticstoolbox/models/DH/UR3.py +98 -0
  525. roboticstoolbox/models/DH/UR5.py +98 -0
  526. roboticstoolbox/models/DH/Uprighttl.py +24 -0
  527. roboticstoolbox/models/DH/__init__.py +52 -0
  528. roboticstoolbox/models/ETS/Frankie.py +90 -0
  529. roboticstoolbox/models/ETS/GenericSeven.py +54 -0
  530. roboticstoolbox/models/ETS/Omni.py +74 -0
  531. roboticstoolbox/models/ETS/Panda.py +69 -0
  532. roboticstoolbox/models/ETS/Planar2.py +49 -0
  533. roboticstoolbox/models/ETS/Planar_Y.py +65 -0
  534. roboticstoolbox/models/ETS/Puma560.py +70 -0
  535. roboticstoolbox/models/ETS/XYPanda.py +84 -0
  536. roboticstoolbox/models/ETS/__init__.py +20 -0
  537. roboticstoolbox/models/README.md +9 -0
  538. roboticstoolbox/models/URDF/AL5D.py +45 -0
  539. roboticstoolbox/models/URDF/Fetch.py +96 -0
  540. roboticstoolbox/models/URDF/Frankie.py +67 -0
  541. roboticstoolbox/models/URDF/FrankieOmni.py +94 -0
  542. roboticstoolbox/models/URDF/Jaco.py +49 -0
  543. roboticstoolbox/models/URDF/KinovaGen3.py +63 -0
  544. roboticstoolbox/models/URDF/LBR.py +57 -0
  545. roboticstoolbox/models/URDF/PR2.py +66 -0
  546. roboticstoolbox/models/URDF/Panda.py +60 -0
  547. roboticstoolbox/models/URDF/Puma560.py +90 -0
  548. roboticstoolbox/models/URDF/UR10.py +43 -0
  549. roboticstoolbox/models/URDF/UR3.py +43 -0
  550. roboticstoolbox/models/URDF/UR5.py +64 -0
  551. roboticstoolbox/models/URDF/URDFRobot.py +402 -0
  552. roboticstoolbox/models/URDF/Valkyrie.py +110 -0
  553. roboticstoolbox/models/URDF/YuMi.py +107 -0
  554. roboticstoolbox/models/URDF/__init__.py +51 -0
  555. roboticstoolbox/models/URDF/px100.py +48 -0
  556. roboticstoolbox/models/URDF/px150.py +48 -0
  557. roboticstoolbox/models/URDF/rx150.py +48 -0
  558. roboticstoolbox/models/URDF/rx200.py +48 -0
  559. roboticstoolbox/models/URDF/vx300.py +48 -0
  560. roboticstoolbox/models/URDF/vx300s.py +48 -0
  561. roboticstoolbox/models/URDF/wx200.py +48 -0
  562. roboticstoolbox/models/URDF/wx250.py +48 -0
  563. roboticstoolbox/models/URDF/wx250s.py +48 -0
  564. roboticstoolbox/models/__init__.py +7 -0
  565. roboticstoolbox/models/catalog.py +226 -0
  566. roboticstoolbox/robot/BaseRobot.py +2589 -0
  567. roboticstoolbox/robot/DHFactor.py +522 -0
  568. roboticstoolbox/robot/DHLink.py +949 -0
  569. roboticstoolbox/robot/DHRobot.py +2591 -0
  570. roboticstoolbox/robot/Dynamics.py +1537 -0
  571. roboticstoolbox/robot/ELink.py +23 -0
  572. roboticstoolbox/robot/ERobot.py +25 -0
  573. roboticstoolbox/robot/Gripper.py +242 -0
  574. roboticstoolbox/robot/IK.py +1378 -0
  575. roboticstoolbox/robot/Link.py +1557 -0
  576. roboticstoolbox/robot/PoERobot.py +352 -0
  577. roboticstoolbox/robot/Robot.py +2157 -0
  578. roboticstoolbox/robot/RobotKinematics.py +1505 -0
  579. roboticstoolbox/robot/RobotPlottingMPL.py +355 -0
  580. roboticstoolbox/robot/RobotProto.py +156 -0
  581. roboticstoolbox/robot/__init__.py +57 -0
  582. roboticstoolbox/robot/cpp-extensions/README.md +29 -0
  583. roboticstoolbox/robot/cpp-extensions/frne.h +96 -0
  584. roboticstoolbox/robot/cpp-extensions/frne_nb.cpp +237 -0
  585. roboticstoolbox/robot/cpp-extensions/ne.c +495 -0
  586. roboticstoolbox/robot/cpp-extensions/vmath.c +163 -0
  587. roboticstoolbox/robot/cpp-extensions/vmath.h +32 -0
  588. roboticstoolbox/robot/frne.py +51 -0
  589. roboticstoolbox/tools/DHFactor.py +375 -0
  590. roboticstoolbox/tools/Ticker.py +53 -0
  591. roboticstoolbox/tools/__init__.py +54 -0
  592. roboticstoolbox/tools/data.py +187 -0
  593. roboticstoolbox/tools/jsingu.py +51 -0
  594. roboticstoolbox/tools/null.py +48 -0
  595. roboticstoolbox/tools/numerical.py +96 -0
  596. roboticstoolbox/tools/p_servo.py +108 -0
  597. roboticstoolbox/tools/params.py +11 -0
  598. roboticstoolbox/tools/plot.py +109 -0
  599. roboticstoolbox/tools/trajectory.py +1152 -0
  600. roboticstoolbox/tools/types.py +13 -0
  601. roboticstoolbox/tools/urdf/__init__.py +45 -0
  602. roboticstoolbox/tools/urdf/tests/data/ur5.urdf +341 -0
  603. roboticstoolbox/tools/urdf/tests/test_urdf.py +116 -0
  604. roboticstoolbox/tools/urdf/urdf.py +1930 -0
  605. roboticstoolbox/tools/urdf/utils.py +50 -0
  606. roboticstoolbox_python-1.4.0.dist-info/METADATA +664 -0
  607. roboticstoolbox_python-1.4.0.dist-info/RECORD +610 -0
  608. roboticstoolbox_python-1.4.0.dist-info/WHEEL +5 -0
  609. roboticstoolbox_python-1.4.0.dist-info/entry_points.txt +6 -0
  610. roboticstoolbox_python-1.4.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,2591 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ @author Jesse Haviland
4
+ """
5
+
6
+ from __future__ import annotations
7
+ from collections import namedtuple
8
+ from email import message
9
+ from roboticstoolbox.tools.data import rtb_path_to_datafile
10
+ import warnings
11
+ import copy
12
+ import numpy as np
13
+ from roboticstoolbox.robot.Robot import Robot # DHLink
14
+ from roboticstoolbox.robot.BaseRobot import _is_symbolic
15
+ from roboticstoolbox.ets.ETS import ETS, ET
16
+ from roboticstoolbox.robot.DHLink import DHLink
17
+ from roboticstoolbox.tools.params import rtb_set_param
18
+ from spatialmath.base.argcheck import getvector, isscalar, verifymatrix, getmatrix
19
+
20
+ # from spatialmath import base
21
+ from spatialmath.base import (
22
+ tr2jac,
23
+ tr2eul,
24
+ tr2rpy,
25
+ t2r,
26
+ trlog,
27
+ rotvelxform,
28
+ )
29
+ from spatialmath import SE3, Twist3
30
+ import spatialmath.base.symbolic as sym
31
+
32
+ # from scipy.optimize import minimize, Bounds
33
+ from ansitable import ANSITable, Column
34
+ from scipy.linalg import block_diag
35
+ from roboticstoolbox.robot.DHLink import DHLink
36
+ from roboticstoolbox.tools.params import rtb_get_param
37
+ from roboticstoolbox.robot.frne import init, frne, delete
38
+ from numpy import any
39
+ from numpy.typing import ArrayLike, NDArray
40
+ from roboticstoolbox.robot.IK import IKSolution
41
+
42
+ # iksol = namedtuple("IKsolution", "q, success, reason")
43
+
44
+
45
+ class DHRobot(Robot):
46
+ """
47
+ Class for robots defined using Denavit-Hartenberg notation
48
+
49
+ :param L: List of links which define the robot
50
+ :type L: list(n)
51
+ :param name: Name of the robot
52
+ :type name: str
53
+ :param manufacturer: Manufacturer of the robot
54
+ :type manufacturer: str
55
+ :param base: Location of the base
56
+ :type base: SE3
57
+ :param tool: Location of the tool
58
+ :type tool: SE3
59
+ :param gravity: gravitational acceleration in the world frame,
60
+ downwards gravitational force is equivalent to robot base
61
+ acceleration upwards (positive)
62
+ :type gravity: ndarray(3)
63
+
64
+ A concrete superclass for arm type robots defined using Denavit-Hartenberg
65
+ notation, that represents a serial-link arm-type robot. Each link and
66
+ joint in the chain is described by a DHLink-class object using
67
+ Denavit-Hartenberg parameters (standard or modified).
68
+
69
+ .. note:: Link subclass elements passed in must be all standard, or all
70
+ modified, DH parameters.
71
+
72
+ :reference:
73
+
74
+ - Robotics, Vision & Control in Python, 3e, P. Corke, Springer 2023, Chap 7-9.
75
+ - Robot, Modeling & Control,
76
+ M.Spong, S. Hutchinson & M. Vidyasagar, Wiley 2006.
77
+
78
+ """
79
+
80
+ def __init__(self, links, meshdir=None, **kwargs):
81
+ # Verify L
82
+ if not isinstance(links, list):
83
+ raise TypeError("The links must be stored in a list.")
84
+
85
+ all_links = []
86
+ self._n = 0
87
+
88
+ # If we are given a list of standard DH Links, we must convert
89
+ # them to modified DH links
90
+ # if any([isinstance(link, StandardDH) for link in links]):
91
+ # links = DHLink.StandardDH(links)
92
+
93
+ for link in links:
94
+ if isinstance(link, DHLink):
95
+ # got a link
96
+ all_links.append(link)
97
+ link.number = self._n + 1
98
+ link.jindex = self._n
99
+ self._n += 1
100
+
101
+ link.name = f"link{self._n}"
102
+
103
+ elif isinstance(link, DHRobot):
104
+ # link is actually a robot
105
+
106
+ # copy the links
107
+ rlinks = copy.copy(link.links)
108
+ for rlink in rlinks:
109
+ all_links.append(rlink)
110
+ rlink.number = self._n
111
+ rlink.jindex = self._n
112
+ self._n += 1
113
+
114
+ rlink.name = f"link{self._n}"
115
+ else:
116
+ raise TypeError("Input can be only DHLink or DHRobot")
117
+
118
+ for i, link in enumerate(all_links):
119
+ if i > 0:
120
+ link.parent = all_links[i - 1]
121
+ else:
122
+ link.parent = None
123
+
124
+ super().__init__(all_links, **kwargs)
125
+
126
+ self._ee_links = [self.links[-1]]
127
+
128
+ # Check the DH convention
129
+ self._mdh = self.links[0].mdh
130
+ if not all([link.mdh == self.mdh for link in self.links]):
131
+ raise ValueError("Robot has mixed D&H link conventions")
132
+
133
+ # load meshes if required
134
+ if meshdir is not None:
135
+ self.meshdir = rtb_path_to_datafile(meshdir)
136
+ self.basemesh = self.meshdir / "link0.stl"
137
+ for j, link in enumerate(self._links, start=1):
138
+ link.mesh = self.meshdir / "link{:d}.stl".format(j)
139
+ self._hasgeometry = True
140
+ else:
141
+ self.basemesh = None
142
+
143
+ # frne parameters
144
+ self._frne = None
145
+
146
+ @property
147
+ def links(self) -> list[DHLink]: # type: ignore[override]
148
+ return self._links # type: ignore[return-value]
149
+
150
+ def __str__(self):
151
+ """
152
+ Pretty prints the DH Model of the robot. Will output angles in degrees
153
+
154
+ :return: Pretty print of the robot model
155
+ :rtype: str
156
+ """
157
+
158
+ if np.array_equal(self.base.A, np.eye(4)):
159
+ base = None
160
+ else:
161
+ base = self.base
162
+
163
+ if np.array_equal(self.tool.A, np.eye(4)):
164
+ tool = None
165
+ else:
166
+ tool = self.tool
167
+
168
+ unicode = rtb_get_param("unicode")
169
+ border = "thin" if unicode else "ascii"
170
+ s = f"DHRobot: {self.name}"
171
+
172
+ if self.manufacturer is not None and len(self.manufacturer) > 0:
173
+ s += f" (by {self.manufacturer})"
174
+ s += f", {self.n} joints ({self.structure})"
175
+
176
+ deg = 180 / np.pi
177
+
178
+ if self._hasdynamics:
179
+ s += ", dynamics"
180
+ if any([link.mesh is not None for link in self.links]):
181
+ s += ", geometry"
182
+
183
+ if self.mdh:
184
+ dh = "modified"
185
+ else:
186
+ dh = "standard"
187
+ s += f", {dh} DH parameters\n"
188
+
189
+ def qstr(j, link):
190
+ j += 1
191
+ if link.isflip:
192
+ s = f"-q{j:d}"
193
+ else:
194
+ s = f" q{j:d}"
195
+
196
+ if L.offset != 0:
197
+ sign = "+" if L.offset > 0 else "-"
198
+ offset = abs(L.offset)
199
+ if link.isprismatic:
200
+ s += f" {sign} {offset:}"
201
+ else:
202
+ s += f" {sign} {offset * deg:.3g}\u00b0"
203
+ return s
204
+
205
+ def angle(theta, fmt=None):
206
+ if sym.issymbol(theta): # pragma nocover
207
+ return "<<red>>" + str(theta)
208
+ else:
209
+ if fmt is not None:
210
+ return fmt.format(theta * deg) + "\u00b0"
211
+ else:
212
+ return str(theta * deg) + "\u00b0"
213
+
214
+ def format_attr(attr) -> str:
215
+ if isinstance(attr, float):
216
+ return f"{attr:.4g}"
217
+ else:
218
+ return str(attr)
219
+
220
+ has_qlim = any([link.qlim is not None for link in self])
221
+ if has_qlim:
222
+ qlim_columns = [
223
+ Column("q⁻", headalign="^"),
224
+ Column("q⁺", headalign="^"),
225
+ ]
226
+ qlim = self.qlim
227
+
228
+ else:
229
+ qlim = np.array([]) # satisfy type checker
230
+ qlim_columns = []
231
+
232
+ if self.mdh:
233
+ # MDH format
234
+ table = ANSITable(
235
+ Column("aⱼ₋₁", headalign="^"),
236
+ Column("⍺ⱼ₋₁", headalign="^"),
237
+ Column("θⱼ", headalign="^"),
238
+ Column("dⱼ", headalign="^"),
239
+ *qlim_columns,
240
+ border=border,
241
+ )
242
+ for j, L in enumerate(self):
243
+ if has_qlim:
244
+ if L.isprismatic:
245
+ ql = [qlim[0, j], qlim[1, j]]
246
+ else:
247
+ ql = [angle(qlim[k, j], "{:.1f}") for k in [0, 1]]
248
+ else:
249
+ ql = []
250
+ if L.isprismatic:
251
+ table.row(L.a, angle(L.alpha), angle(L.theta), qstr(j, L), *ql)
252
+ else:
253
+ table.row(L.a, angle(L.alpha), qstr(j, L), L.d, *ql)
254
+ else:
255
+ # DH format
256
+ table = ANSITable(
257
+ Column("θⱼ", headalign="^", colalign="<"),
258
+ Column("dⱼ", headalign="^"),
259
+ Column("aⱼ", headalign="^"),
260
+ Column("⍺ⱼ", headalign="^"),
261
+ *qlim_columns,
262
+ border=border,
263
+ )
264
+
265
+ for j, L in enumerate(self):
266
+ if has_qlim:
267
+ if L.isprismatic:
268
+ ql = [qlim[0, j], qlim[1, j]]
269
+ else:
270
+ ql = [angle(qlim[k, j], "{:.1f}") for k in [0, 1]]
271
+ else:
272
+ ql = []
273
+ if L.isprismatic:
274
+ table.row(
275
+ angle(L.theta),
276
+ qstr(j, L),
277
+ format_attr(L.a),
278
+ angle(L.alpha),
279
+ *ql,
280
+ )
281
+ else:
282
+ table.row(
283
+ qstr(j, L),
284
+ format_attr(L.d),
285
+ format_attr(L.a),
286
+ angle(L.alpha),
287
+ *ql,
288
+ )
289
+
290
+ s += str(table)
291
+
292
+ # show tool and base
293
+ if tool is not None or base is not None:
294
+ table = ANSITable(
295
+ Column("", colalign=">"),
296
+ Column("", colalign="<"),
297
+ border=border,
298
+ header=False,
299
+ )
300
+ if base is not None:
301
+ table.row(
302
+ "base",
303
+ base.printline(orient="rpy/xyz", fmt="{:.2g}", file=None),
304
+ )
305
+ if tool is not None:
306
+ table.row(
307
+ "tool",
308
+ tool.strline(orient="rpy/xyz", fmt="{:.2g}"),
309
+ )
310
+ s += "\n" + str(table)
311
+
312
+ # show named configurations
313
+ s += self.configurations_str(border=border)
314
+
315
+ return s
316
+
317
+ def __add__(self, L):
318
+ nlinks = []
319
+
320
+ # TODO - Should I do a deep copy here a physically copy the DHLinks
321
+ # and not just the references?
322
+ # Copy DHLink references to new list
323
+ for i in range(self.n):
324
+ nlinks.append(self.links[i])
325
+
326
+ if isinstance(L, DHLink):
327
+ nlinks.append(L)
328
+ elif isinstance(L, DHRobot):
329
+ for j in range(L.n):
330
+ nlinks.append(L.links[j])
331
+ else:
332
+ raise TypeError("Can only combine DHRobots with other DHRobots or DHLinks")
333
+
334
+ return DHRobot(
335
+ nlinks,
336
+ name=self.name,
337
+ manufacturer=self.manufacturer,
338
+ base=self.base,
339
+ tool=self.tool,
340
+ gravity=self.gravity,
341
+ )
342
+
343
+ def __deepcopy__(self, memo):
344
+ links = []
345
+
346
+ for link in self.links:
347
+ links.append(copy.deepcopy(link))
348
+
349
+ name = copy.deepcopy(self.name)
350
+ manufacturer = copy.deepcopy(self.manufacturer)
351
+ comment = copy.deepcopy(self.comment)
352
+ base = copy.deepcopy(self.base)
353
+ tool = copy.deepcopy(self.tool)
354
+ gravity = copy.deepcopy(self.gravity)
355
+ keywords = copy.deepcopy(self.keywords)
356
+ symbolic = copy.deepcopy(self.symbolic)
357
+ configs = copy.deepcopy(self.configs)
358
+
359
+ try:
360
+ if self.meshdir:
361
+ meshdir = copy.deepcopy(self.meshdir)
362
+ else:
363
+ meshdir = None
364
+ except AttributeError:
365
+ meshdir = None
366
+
367
+ # cls = self.__class__
368
+ result = DHRobot(
369
+ links,
370
+ meshdir=meshdir,
371
+ name=name,
372
+ manufacturer=manufacturer,
373
+ comment=comment,
374
+ base=base,
375
+ tool=tool,
376
+ gravity=gravity,
377
+ keywords=keywords,
378
+ symbolic=symbolic,
379
+ configs=configs,
380
+ )
381
+
382
+ # if a configuration was an attribute of original robot, make it an
383
+ # attribute of the deep copy
384
+ for config in configs:
385
+ if hasattr(self, config):
386
+ setattr(result, config, configs[config])
387
+
388
+ try:
389
+ setattr(result, "ikine_a", getattr(self, "ikine_a"))
390
+ except AttributeError:
391
+ pass
392
+
393
+ memo[id(self)] = result
394
+ return result
395
+
396
+ # def copy(self):
397
+ # """
398
+ # Copy a robot
399
+
400
+ # :return: A deepish copy of the robot
401
+ # :rtype: Robot subclass instance
402
+ # """
403
+
404
+ # L = [link.copy() for link in self]
405
+
406
+ # new = DHRobot(
407
+ # L,
408
+ # name=self.name,
409
+ # manufacturer=self.manufacturer,
410
+ # base=self.base,
411
+ # tool=self.tool,
412
+ # gravity=self.gravity)
413
+
414
+ # new.q = self.q
415
+ # new.qd = self.qd
416
+ # new.qdd = self.qdd
417
+
418
+ # return new
419
+
420
+ # --------------------------------------------------------------------- #
421
+
422
+ def _set_link_fk(self, q):
423
+ """
424
+ robot._set_link_fk(q) evaluates fkine for each link within a
425
+ robot and stores that pose in a private variable within the link.
426
+
427
+ This method is not for general use.
428
+
429
+ :param q: The joint angles/configuration of the robot
430
+ :type q: float ndarray(n)
431
+
432
+ .. note::
433
+
434
+ - The robot's base transform, if present, are incorporated
435
+ into the result.
436
+ """
437
+
438
+ q = getvector(q, self.n)
439
+
440
+ # t = self.base
441
+
442
+ tall = self.fkine_all(q, old=True)
443
+
444
+ for i, link in enumerate(self.links):
445
+ # Update the link model transforms
446
+ for col in link.collision:
447
+ col.wT = tall[i]
448
+
449
+ for gi in link.geometry:
450
+ gi.wT = tall[i]
451
+
452
+ # --------------------------------------------------------------------- #
453
+
454
+ @property
455
+ def mdh(self):
456
+ """
457
+ Modified Denavit-Hartenberg status
458
+
459
+ :return: whether robot is defined using modified Denavit-Hartenberg
460
+ notation
461
+ :rtype: bool
462
+
463
+ Example:
464
+
465
+ .. runblock:: pycon
466
+
467
+ >>> import roboticstoolbox as rtb
468
+ >>> puma = rtb.models.DH.Puma560()
469
+ >>> puma.mdh
470
+ >>> panda = rtb.models.DH.Panda()
471
+ >>> panda.mdh
472
+
473
+ """
474
+ return self._mdh
475
+
476
+ @property
477
+ def d(self):
478
+ r"""
479
+ Link offset values
480
+
481
+ :return: List of link offset values :math:`d_j`.
482
+ :rtype: ndarray(n,)
483
+
484
+ The following are equivalent::
485
+
486
+ robot.links[j].d
487
+ robot.d[j]
488
+
489
+ Example:
490
+
491
+ .. runblock:: pycon
492
+
493
+ >>> import roboticstoolbox as rtb
494
+ >>> robot = rtb.models.DH.Puma560()
495
+ >>> robot.d
496
+ """
497
+ v = []
498
+ for i in range(self.n):
499
+ v.append(self.links[i].d)
500
+ return v
501
+
502
+ @property
503
+ def a(self):
504
+ r"""
505
+ Link length values
506
+
507
+ :return: List of link length values :math:`a_j`.
508
+ :rtype: ndarray(n,)
509
+
510
+ The following are equivalent::
511
+
512
+ robot.links[j].a
513
+ robot.a[j]
514
+
515
+ Example:
516
+
517
+ .. runblock:: pycon
518
+
519
+ >>> import roboticstoolbox as rtb
520
+ >>> robot = rtb.models.DH.Puma560()
521
+ >>> robot.a
522
+ """
523
+ v = []
524
+ for i in range(self.n):
525
+ v.append(self.links[i].a)
526
+ return v
527
+
528
+ @property
529
+ def theta(self):
530
+ r"""
531
+ Joint angle values
532
+
533
+ :return: List of joint angle values :math:`\theta_j`.
534
+ :rtype: ndarray(n,)
535
+
536
+ The following are equivalent::
537
+
538
+ robot.links[j].theta
539
+ robot.theta[j]
540
+
541
+ Example:
542
+
543
+ .. runblock:: pycon
544
+
545
+ >>> import roboticstoolbox as rtb
546
+ >>> robot = rtb.models.DH.Puma560()
547
+ >>> robot.theta
548
+ """
549
+ v = []
550
+ for i in range(self.n):
551
+ v.append(self.links[i].theta)
552
+ return v
553
+
554
+ @property
555
+ def alpha(self):
556
+ r"""
557
+ Link twist values
558
+
559
+ :return: List of link twist values :math:`\alpha_j`.
560
+ :rtype: ndarray(n,)
561
+
562
+ The following are equivalent::
563
+
564
+ robot.links[j].alpha
565
+ robot.alpha[j]
566
+
567
+ Example:
568
+
569
+ .. runblock:: pycon
570
+
571
+ >>> import roboticstoolbox as rtb
572
+ >>> robot = rtb.models.DH.Puma560()
573
+ >>> robot.alpha
574
+ """
575
+ v = []
576
+ for i in range(self.n):
577
+ v.append(self.links[i].alpha)
578
+ return v
579
+
580
+ @property
581
+ def r(self):
582
+ r"""
583
+ Link centre of mass values
584
+
585
+ :return: Array of link centre of mass values :math:`r_j`.
586
+ :rtype: ndarray(3,n)
587
+
588
+ Example:
589
+
590
+ .. runblock:: pycon
591
+
592
+ >>> import roboticstoolbox as rtb
593
+ >>> robot = rtb.models.DH.Puma560()
594
+ >>> robot.r
595
+ """
596
+ # TODO tidyup
597
+ v = np.copy(self.links[0].r)
598
+ for i in range(1, self.n):
599
+ v = np.c_[v, self.links[i].r]
600
+ return v
601
+
602
+ @property
603
+ def offset(self):
604
+ r"""
605
+ Joint offset values
606
+
607
+ :return: List of joint offset values :math:`\bar{q}_j`.
608
+ :rtype: ndarray(n,)
609
+
610
+ Example:
611
+
612
+ .. runblock:: pycon
613
+
614
+ >>> import roboticstoolbox as rtb
615
+ >>> robot = rtb.models.DH.Puma560()
616
+ >>> robot.offset
617
+ """
618
+ v = []
619
+ for i in range(self.n):
620
+ v.append(self.links[i].offset)
621
+ return v
622
+
623
+ @property
624
+ def reach(self):
625
+ r"""
626
+ Reach of the robot
627
+
628
+ :return: Maximum reach of the robot
629
+ :rtype: float
630
+
631
+ A conservative estimate of the reach of the robot. It is computed as
632
+ :math:`\sum_j |a_j| + |d_j|` where :math:`d_j` is taken as the maximum
633
+ joint coordinate (``qlim``) if the joint is primsmatic.
634
+
635
+ .. note::
636
+
637
+ - This is the *length sum* referred to in Craig's book
638
+ - Probably an overestimate of the actual reach
639
+ - Used by numerical inverse kinematics to scale translational
640
+ error.
641
+ - For a prismatic joint, uses ``qlim`` if it is set
642
+
643
+ .. warning:: Computed on the first access. If kinematic parameters
644
+ subsequently change this will not be reflected.
645
+ """
646
+ if self._reach is None:
647
+ d = 0
648
+ for link in self:
649
+ d += abs(link.a) + (link.d)
650
+ if link.isprismatic and link.qlim is not None:
651
+ d += link.qlim[1]
652
+ self._reach = d
653
+ return self._reach
654
+
655
+ @property
656
+ def nbranches(self):
657
+ """
658
+ Number of branches
659
+
660
+ :return: number of branches in the robot's kinematic tree
661
+ :rtype: int
662
+
663
+ Number of branches in this robot.
664
+
665
+ Example:
666
+
667
+ .. runblock:: pycon
668
+
669
+ >>> import roboticstoolbox as rtb
670
+ >>> robot = rtb.models.DH.Panda()
671
+ >>> robot.nbranches
672
+
673
+ :seealso: :func:`n`, :func:`nlinks`
674
+ """
675
+ return 1
676
+
677
+ def A(self, j, q=None):
678
+ """
679
+ Link forward kinematics
680
+
681
+ :param j: Joints to compute link transform for
682
+ :type j: int, 2-tuple
683
+ :param q: The joint configuration of the robot (Optional,
684
+ if not supplied will use the stored q values)
685
+ :type q: float ndarray(1,n)
686
+ :return T: The transform between link frames
687
+ :rtype T: SE3
688
+
689
+ - ``robot.A(j, q)`` transform between link frames {0} and {j}. ``q``
690
+ is a vector (n) of joint variables.
691
+ - ``robot.A([j1, j2], q)`` as above between link frames {j1} and {j2}.
692
+ - ``robot.A(j)`` as above except uses the stored q value of the
693
+ robot object.
694
+
695
+ .. note:: Base and tool transforms are not applied.
696
+
697
+ """
698
+
699
+ if isscalar(j):
700
+ j0 = 0
701
+ jn = int(j)
702
+ else:
703
+ j = getvector(j, 2)
704
+ j0 = int(j[0])
705
+ jn = int(j[1])
706
+
707
+ jn += 1
708
+
709
+ if jn > self.n:
710
+ raise ValueError("The joints value out of range")
711
+
712
+ q = getvector(q)
713
+
714
+ T = SE3()
715
+ for i in range(j0, jn):
716
+ T *= self.links[i].A(q[i])
717
+
718
+ return T
719
+
720
+ def islimit(self, q=None):
721
+ """
722
+ Joint limit test
723
+
724
+ :param q: The joint configuration of the robot (Optional,
725
+ if not supplied will use the stored q values)
726
+ :type q: ndarray(n
727
+ :return v: is a vector of boolean values, one per joint, False if
728
+ ``q[j]`` is within the joint limits, else True
729
+ :rtype v: bool list
730
+
731
+ - ``robot.islimit(q)`` is a list of boolean values indicating if the
732
+ joint configuration ``q`` is in violation of the joint limits.
733
+
734
+ - ``robot.jointlimit()`` as above except uses the stored q value of the
735
+ robot object.
736
+
737
+ Example:
738
+
739
+ .. runblock:: pycon
740
+
741
+ >>> import roboticstoolbox as rtb
742
+ >>> robot = rtb.models.DH.Puma560()
743
+ >>> robot.islimit([0, 0, -4, 4, 0, 0])
744
+
745
+ """
746
+ if q is None:
747
+ q = self.q
748
+
749
+ return [link.islimit(qk) for (link, qk) in zip(self, q)]
750
+
751
+ def isspherical(self):
752
+ """
753
+ Test for spherical wrist
754
+
755
+ :return: True if spherical wrist
756
+ :rtype: bool
757
+
758
+ Tests if the robot has a spherical wrist, that is, the last 3 axes are
759
+ revolute and their axes intersect at a point.
760
+
761
+ .. runblock:: pycon
762
+
763
+ >>> import roboticstoolbox as rtb
764
+ >>> robot = rtb.models.DH.Puma560()
765
+ >>> robot.isspherical()
766
+
767
+ """
768
+ if self.n < 3:
769
+ return False
770
+
771
+ L = self.links[self.n - 3 : self.n]
772
+
773
+ alpha = [-np.pi / 2, np.pi / 2]
774
+
775
+ return (
776
+ L[0].a == 0
777
+ and L[1].a == 0
778
+ and L[1].d == 0
779
+ and (
780
+ (L[0].alpha == alpha[0] and L[1].alpha == alpha[1])
781
+ or (L[0].alpha == alpha[1] and L[1].alpha == alpha[0])
782
+ )
783
+ and L[0].sigma == 0
784
+ and L[1].sigma == 0
785
+ and L[2].sigma == 0
786
+ )
787
+
788
+ def dhunique(self):
789
+ """
790
+ Print the unique DH parameters
791
+
792
+ Print a table showing all the non-zero DH parameters, and their
793
+ values. This is the minimum set of kinematic parameters required
794
+ to describe the robot.
795
+
796
+ Example:
797
+
798
+ .. runblock:: pycon
799
+
800
+ >>> import roboticstoolbox as rtb
801
+ >>> puma = rtb.models.DH.Puma560()
802
+ >>> puma.dhunique()
803
+ """
804
+
805
+ table = ANSITable(
806
+ Column("param"),
807
+ Column("value", headalign="^", colalign="<", fmt="{:.4g}"),
808
+ border="thin",
809
+ )
810
+ for j, link in enumerate(self):
811
+ if link.isprismatic:
812
+ if link.theta != 0:
813
+ table.row(f"θ{j}", link.theta)
814
+ elif link.isrevolute:
815
+ if link.d != 0:
816
+ table.row(f"d{j}", link.d)
817
+ if link.a != 0:
818
+ table.row(f"a{j}", link.a)
819
+ if link.alpha != 0:
820
+ table.row(f"⍺{j}", link.alpha)
821
+ table.print()
822
+
823
+ def twists(self, q=None):
824
+ """
825
+ Joint axes as twists
826
+
827
+ :param q: The joint configuration of the robot, defaults to zero
828
+ :return: a vector of joint axis twists
829
+ :rtype: Twist3 instance
830
+ :return: Pose of the tool
831
+ :rtype: SE3 instance
832
+
833
+ - ``tw, T0 = twists(q)`` calculates a vector of Twist objects (n) that
834
+ represent the axes of the joints for the robot with joint coordinates
835
+ ``q`` (n). Also returns T0 which is an SE3 object representing the
836
+ pose of the tool.
837
+
838
+ - ``tw, T0 = twists()`` as above but the joint coordinates are taken
839
+ to be zero.
840
+
841
+ Example:
842
+
843
+ .. runblock:: pycon
844
+
845
+ >>> import roboticstoolbox as rtb
846
+ >>> robot = rtb.models.DH.Puma560()
847
+ >>> tw, T0 = robot.twists()
848
+ >>> tw
849
+ >>> T0
850
+
851
+ """
852
+
853
+ if q is None:
854
+ q = np.zeros((self.n,))
855
+
856
+ T = self.fkine_all(q)[1:] # don't use first transform which is base
857
+ tw = Twist3.Alloc(self.n)
858
+ if self.mdh:
859
+ # MDH case
860
+ for j, link in enumerate(self):
861
+ if link.sigma == 0:
862
+ tw[j] = Twist3.UnitRevolute(T[j].a, T[j].t) # type: ignore[union-attr]
863
+ else:
864
+ tw[j] = Twist3.UnitPrismatic(T[j].a) # type: ignore[union-attr]
865
+ else:
866
+ # DH case
867
+ for j, link in enumerate(self):
868
+ if j == 0:
869
+ # first link case
870
+ if link.sigma == 0:
871
+ # revolute
872
+ tw[j] = Twist3.UnitRevolute([0, 0, 1], [0, 0, 0])
873
+ else:
874
+ tw[j] = Twist3.UnitPrismatic([0, 0, 1]) # prismatic
875
+ else:
876
+ # subsequent links
877
+ if link.sigma == 0:
878
+ tw[j] = Twist3.UnitRevolute(T[j - 1].a, T[j - 1].t) # type: ignore[union-attr] # revolute
879
+ else:
880
+ tw[j] = Twist3.UnitPrismatic(T[j - 1].a) # prismatic
881
+
882
+ return tw, T[-1]
883
+
884
+ def ets(self, *args, **kwargs) -> ETS:
885
+ """
886
+ Robot kinematics as an elemenary transform sequence
887
+
888
+ :return: elementary transform sequence
889
+ :rtype: ETS
890
+
891
+ Example:
892
+
893
+ .. runblock:: pycon
894
+
895
+ >>> import roboticstoolbox as rtb
896
+ >>> puma = rtb.models.DH.Puma560()
897
+ >>> puma.ets()
898
+ """
899
+
900
+ # optionally start with the base transform
901
+ if np.array_equal(self.base.A, np.eye(4)):
902
+ base = None
903
+ else:
904
+ base = self.base.A
905
+
906
+ if np.array_equal(self.tool.A, np.eye(4)):
907
+ tool = None
908
+ else:
909
+ tool = self.tool.A
910
+
911
+ if base is None:
912
+ ets = ETS()
913
+ else:
914
+ ets = ET.SE3(base)
915
+
916
+ # add the links
917
+ for link in self:
918
+ ets *= link.ets
919
+
920
+ # optionally add the base transform
921
+ if tool is not None:
922
+ ets *= ET.SE3(tool)
923
+
924
+ return ets
925
+
926
+ def fkine(self, q, **kwargs):
927
+ """
928
+ Forward kinematics
929
+
930
+ :param q: The joint configuration
931
+ :type q: ndarray(n) or ndarray(m,n)
932
+ :return: Forward kinematics as an SE(3) matrix
933
+ :rtype: SE3 instance
934
+
935
+ - ``robot.fkine(q)`` computes the forward kinematics for the robot at
936
+ joint configuration ``q``.
937
+
938
+ If q is a 2D array, the rows are interpreted as the generalized joint
939
+ coordinates for a sequence of points along a trajectory. ``q[k,j]`` is
940
+ the j'th joint coordinate for the k'th trajectory configuration, and
941
+ the returned ``SE3`` instance contains ``n`` values.
942
+
943
+ Example:
944
+
945
+ .. runblock:: pycon
946
+
947
+ >>> import roboticstoolbox as rtb
948
+ >>> puma = rtb.models.DH.Puma560()
949
+ >>> puma.fkine([0, 0, 0, 0, 0, 0])
950
+
951
+ .. note::
952
+
953
+ - The robot's base or tool transform, if present, are incorporated
954
+ into the result.
955
+ - Joint offsets, if defined, are added to ``q`` before the forward
956
+ kinematics are computed.
957
+ """
958
+
959
+ if np.array_equal(self.base.A, np.eye(4)):
960
+ base = None
961
+ else:
962
+ base = self.base
963
+
964
+ if np.array_equal(self.tool.A, np.eye(4)):
965
+ tool = None
966
+ else:
967
+ tool = self.tool
968
+
969
+ T = SE3.Empty()
970
+ for qr in getmatrix(q, (None, self.n)):
971
+ first = True
972
+ for q, L in zip(qr, self.links):
973
+ if first:
974
+ Tr = L.A(q)
975
+ first = False
976
+ else:
977
+ Tr *= L.A(q) # type: ignore
978
+
979
+ if base is not None:
980
+ Tr = base * Tr # type: ignore
981
+ if tool is not None:
982
+ Tr = Tr * tool # type: ignore
983
+ T.append(Tr) # type: ignore
984
+
985
+ return T
986
+
987
+ def fkine_path(self, q, old=None):
988
+ """
989
+ Compute the pose of every link frame
990
+
991
+ :param q: The joint configuration
992
+ :type q: darray(n)
993
+ :return: Pose of all links
994
+ :rtype: SE3 instance
995
+
996
+ ``T = robot.fkine_path(q)`` is an SE3 instance with ``robot.nlinks +
997
+ 1`` values:
998
+
999
+ - ``T[0]`` is the base transform
1000
+ - ``T[i+1]`` is the pose of link whose ``number`` is ``i``
1001
+
1002
+ :references:
1003
+ - Kinematic Derivatives using the Elementary Transform
1004
+ Sequence, J. Haviland and P. Corke
1005
+ """
1006
+ T = self.base
1007
+ q = getvector(q)
1008
+ Tj = T
1009
+
1010
+ for q, L in zip(q, self.links):
1011
+ Tj *= L.A(q)
1012
+ T.append(Tj)
1013
+
1014
+ if self._tool is not None:
1015
+ T[-1] *= self._tool
1016
+
1017
+ return T
1018
+
1019
+ def segments(self):
1020
+ segments = [None]
1021
+ segments.extend(self.links)
1022
+ return [segments]
1023
+
1024
+ def fkine_all(self, q=None, old=True):
1025
+ """
1026
+ Forward kinematics for all link frames
1027
+
1028
+ :param q: The joint configuration of the robot (Optional,
1029
+ if not supplied will use the stored q values).
1030
+ :type q: ndarray(n) or ndarray(m,n)
1031
+ :param old: "old" behaviour, defaults to True
1032
+ :type old: bool, optional
1033
+ :return: Forward kinematics as an SE(3) matrix
1034
+ :rtype: SE3 instance with ``n`` values
1035
+
1036
+ - ``fkine_all(q)`` evaluates fkine for each joint within a robot and
1037
+ returns a sequence of link frame poses.
1038
+
1039
+ - ``fkine_all()`` as above except uses the stored q value of the
1040
+ robot object.
1041
+
1042
+ Example:
1043
+
1044
+ .. runblock:: pycon
1045
+
1046
+ >>> import roboticstoolbox as rtb
1047
+ >>> puma = rtb.models.DH.Puma560()
1048
+ >>> T = puma.fkine_all([0, 0, 0, 0, 0, 0])
1049
+ >>> len(T)
1050
+
1051
+ .. note::
1052
+ - Old behaviour is to return a list of ``n`` frames {1} to {n}, but
1053
+ if ``old=False`` it returns ``n`` + 1 frames {0} to {n}, ie. it
1054
+ includes the base frame.
1055
+ - The robot's base or tool transform, if present, are incorporated
1056
+ into the result.
1057
+ - Joint offsets, if defined, are added to q before the forward
1058
+ kinematics are computed.
1059
+ """
1060
+
1061
+ if q is None:
1062
+ q = self.q
1063
+
1064
+ Tj = self.base.copy()
1065
+ Tall = Tj
1066
+
1067
+ for q, L in zip(q, self.links):
1068
+ Tj *= L.A(q)
1069
+ Tall.append(Tj)
1070
+ return Tall
1071
+
1072
+ def jacobe(self, q, half=None, **kwargs):
1073
+ r"""
1074
+ Manipulator Jacobian in end-effector frame
1075
+
1076
+ :param q: Joint coordinate vector
1077
+ :type q: ndarray(n)
1078
+ :param half: return half Jacobian: 'trans' or 'rot'
1079
+ :type half: str
1080
+ :return J: The manipulator Jacobian in the end-effector frame
1081
+ :rtype: ndarray(6,n)
1082
+
1083
+ - ``robot.jacobe(q)`` is the manipulator Jacobian matrix which maps
1084
+ joint velocity to end-effector spatial velocity.
1085
+
1086
+ End-effector spatial velocity :math:`\nu = (v_x, v_y, v_z, \omega_x, \omega_y, \omega_z)^T`
1087
+ is related to joint velocity by :math:`{}^{E}\!\nu = \mathbf{J}_m(q) \dot{q}`.
1088
+
1089
+ Example:
1090
+
1091
+ .. runblock:: pycon
1092
+
1093
+ >>> import roboticstoolbox as rtb
1094
+ >>> puma = rtb.models.DH.Puma560()
1095
+ >>> puma.jacobe([0, 0, 0, 0, 0, 0])
1096
+
1097
+ .. warning:: This is the **geometric Jacobian** as described in texts by
1098
+ Corke, Spong etal., Siciliano etal. The end-effector velocity is
1099
+ described in terms of translational and angular velocity, not a
1100
+ velocity twist as per the text by Lynch & Park.
1101
+ """
1102
+
1103
+ q = getvector(q, self.n)
1104
+
1105
+ n = self.n
1106
+ L = self.links
1107
+ J = np.zeros((6, self.n), dtype=q.dtype) # type: ignore
1108
+
1109
+ U: NDArray = np.asarray(self.tool.A)
1110
+
1111
+ for j in range(n - 1, -1, -1):
1112
+ if self.mdh == 0:
1113
+ # standard DH convention
1114
+ U = L[j].A(q[j]).A @ U # type: ignore
1115
+
1116
+ if not L[j].sigma:
1117
+ # revolute axis
1118
+ d = np.array(
1119
+ [
1120
+ -U[0, 0] * U[1, 3] + U[1, 0] * U[0, 3],
1121
+ -U[0, 1] * U[1, 3] + U[1, 1] * U[0, 3],
1122
+ -U[0, 2] * U[1, 3] + U[1, 2] * U[0, 3],
1123
+ ]
1124
+ )
1125
+ delta = U[2, :3] # nz oz az
1126
+ else:
1127
+ # prismatic axis
1128
+ d = U[2, :3] # nz oz az
1129
+ delta = np.zeros((3,))
1130
+
1131
+ J[:, j] = np.r_[d, delta]
1132
+
1133
+ if self.mdh != 0:
1134
+ # modified DH convention
1135
+ U = L[j].A(q[j]).A @ U # type: ignore
1136
+
1137
+ # return top or bottom half if asked
1138
+ if half is not None:
1139
+ if half == "trans":
1140
+ return J[:3, :]
1141
+ elif half == "rot":
1142
+ return J[3:, :]
1143
+ else:
1144
+ raise ValueError("bad half specified")
1145
+
1146
+ return J
1147
+
1148
+ def jacob0(self, q=None, T=None, half=None, start=None, end=None):
1149
+ r"""
1150
+ Manipulator Jacobian in world frame
1151
+
1152
+ :param q: Joint coordinate vector
1153
+ :type q: ndarray(n)
1154
+ :param T: Forward kinematics if known, SE(3 matrix)
1155
+ :type T: SE3 instance
1156
+ :param half: return half Jacobian: 'trans' or 'rot'
1157
+ :type half: str
1158
+ :return J: The manipulator Jacobian in the world frame
1159
+ :rtype: ndarray(6,n)
1160
+
1161
+ - ``robot.jacob0(q)`` is the manipulator geometric Jacobian matrix which maps
1162
+ joint velocity to end-effector spatial velocity.
1163
+
1164
+ End-effector spatial velocity :math:`\nu = (v_x, v_y, v_z, \omega_x, \omega_y, \omega_z)^T`
1165
+ is related to joint velocity by :math:`{}^{0}\!\nu = \mathbf{J}_0(q) \dot{q}`.
1166
+
1167
+ Example:
1168
+
1169
+ .. runblock:: pycon
1170
+
1171
+ >>> import roboticstoolbox as rtb
1172
+ >>> puma = rtb.models.DH.Puma560()
1173
+ >>> puma.jacob0([0, 0, 0, 0, 0, 0])
1174
+
1175
+ .. warning:: This is the **geometric Jacobian** is as described in texts by
1176
+ Corke, Spong etal., Siciliano etal. The end-effector velocity is
1177
+ described in terms of translational and angular velocity, not a
1178
+ velocity twist as per the text by Lynch & Park.
1179
+
1180
+ .. note:: ``T`` can be passed in to save the cost of computing forward
1181
+ kinematics which is needed to transform velocity from end-effector
1182
+ frame to world frame.
1183
+
1184
+ """
1185
+ q = getvector(q, self.n)
1186
+
1187
+ if T is None:
1188
+ T = self.fkine(q)
1189
+ T = T.A
1190
+
1191
+ # compute Jacobian in EE frame and transform to world frame
1192
+ J0 = tr2jac(T) @ self.jacobe(q)
1193
+
1194
+ # TODO optimize computation above if half matrix is returned
1195
+
1196
+ # return top or bottom half if asked
1197
+ if half is not None:
1198
+ if half == "trans":
1199
+ J0 = J0[:3, :]
1200
+ elif half == "rot":
1201
+ J0 = J0[3:, :]
1202
+ else:
1203
+ raise ValueError("bad half specified")
1204
+ return J0
1205
+
1206
+ def jacob0_analytical(self, q, representation=None, T=None):
1207
+ r"""
1208
+ Manipulator Jacobian in world frame
1209
+
1210
+ :param q: Joint coordinate vector
1211
+ :type q: ndarray(n)
1212
+ :param representation: return analytical Jacobian instead of geometric Jacobian
1213
+ :type representation: str
1214
+ :param T: Forward kinematics if known, SE(3 matrix)
1215
+ :type T: SE3 instance
1216
+ :return J: The manipulator analytical Jacobian in the world frame
1217
+ :rtype: ndarray(6,n)
1218
+
1219
+ Return the manipulator's analytical Jacobian matrix which maps
1220
+ joint velocity to end-effector spatial velocity.
1221
+
1222
+ End-effector spatial velocity :math:`\nu_a = (v_x, v_y, v_z, \dot{\Gamma}_1, \dot{\Gamma}_2, \dot{\Gamma}_3)^T`
1223
+ is related to joint velocity by :math:`{}^{0}\!\nu_a = \mathbf{J}_{a,0}(q) \dot{q}`.
1224
+ Where :math:`\dvec{\Gamma} = (\dot{\Gamma}_1, \dot{\Gamma}_2, \dot{\Gamma}_3)` is
1225
+ orientation rate expressed as one of:
1226
+
1227
+ ================== ==================================
1228
+ ``representation`` Rotational representation
1229
+ ================== ==================================
1230
+ ``'rpy/xyz'`` RPY angular rates in XYZ order
1231
+ ``'rpy/zyx'`` RPY angular rates in XYZ order
1232
+ ``'eul'`` Euler angular rates in ZYZ order
1233
+ ``'exp'`` exponential coordinate rates
1234
+ ================== ==================================
1235
+
1236
+ Example:
1237
+
1238
+ .. runblock:: pycon
1239
+
1240
+ >>> import roboticstoolbox as rtb
1241
+ >>> puma = rtb.models.DH.Puma560()
1242
+ >>> puma.jacob0_analytical([0, 0, 0, 0, 0, 0], "rpy/xyz")
1243
+
1244
+ .. warning:: The **geometric Jacobian** is as described in texts by
1245
+ Corke, Spong etal., Siciliano etal. The end-effector velocity is
1246
+ described in terms of translational and angular velocity, not a
1247
+ velocity twist as per the text by Lynch & Park.
1248
+
1249
+ .. note:: ``T`` can be passed in to save the cost of computing forward
1250
+ kinematics which is needed to transform velocity from end-effector
1251
+ frame to world frame.
1252
+
1253
+ """
1254
+ q = getvector(q, self.n)
1255
+
1256
+ # compute forward kinematics if not provided
1257
+ if T is None:
1258
+ T = self.fkine(q)
1259
+
1260
+ # compute Jacobian in world frame
1261
+ J0 = self.jacob0(q, T)
1262
+
1263
+ if representation is None:
1264
+ return J0
1265
+
1266
+ # compute rotational transform if analytical Jacobian required
1267
+
1268
+ if representation == "rpy/xyz":
1269
+ gamma = tr2rpy(T.A, order="xyz")
1270
+ elif representation == "rpy/zyx":
1271
+ gamma = tr2rpy(T.A, order="zyx")
1272
+ elif representation == "eul":
1273
+ gamma = tr2eul(T.A)
1274
+ elif representation == "exp":
1275
+ # TODO: move to SMTB.base, Horner form with skew(v)
1276
+ gamma = trlog(t2r(T.A), twist=True)
1277
+ else:
1278
+ raise ValueError("bad analytical value specified")
1279
+
1280
+ A = rotvelxform(gamma, representation=representation, inverse=True, full=True)
1281
+ return A @ J0
1282
+
1283
+ def hessian0(self, q=None, J0=None, start=None, end=None):
1284
+ r"""
1285
+ Manipulator Hessian in base frame
1286
+
1287
+ :param q: joint coordinates
1288
+ :type q: array_like
1289
+ :param J0: Jacobian in {0} frame
1290
+ :type J0: ndarray(6,n)
1291
+ :return: Hessian matrix
1292
+ :rtype: ndarray(6,n,n)
1293
+
1294
+ This method calculates the Hessian in the base frame. One of ``J0`` or
1295
+ ``q`` is required. If ``J0`` is already calculated for the joint
1296
+ coordinates ``q`` it can be passed in to to save computation time.
1297
+
1298
+ If we take the time derivative of the differential kinematic
1299
+ relationship
1300
+
1301
+ .. math::
1302
+
1303
+ \nu &= \mat{J}(\vec{q}) \dvec{q} \\
1304
+ \alpha &= \dmat{J} \dvec{q} + \mat{J} \ddvec{q}
1305
+
1306
+ where
1307
+
1308
+ .. math::
1309
+
1310
+ \dmat{J} = \mat{H} \dvec{q}
1311
+
1312
+ and :math:`\mat{H} \in \mathbb{R}^{6\times n \times n}` is the
1313
+ Hessian tensor.
1314
+
1315
+ The elements of the Hessian are
1316
+
1317
+ .. math::
1318
+
1319
+ \mat{H}_{i,j,k} = \frac{d^2 u_i}{d q_j d q_k}
1320
+
1321
+ where :math:`u = \{t_x, t_y, t_z, r_x, r_y, r_z\}` are the elements
1322
+ of the spatial velocity vector.
1323
+
1324
+ Similarly, we can write
1325
+
1326
+ .. math::
1327
+
1328
+ \mat{J}_{i,j} = \frac{d u_i}{d q_j}
1329
+
1330
+ :references:
1331
+ - Kinematic Derivatives using the Elementary Transform
1332
+ Sequence, J. Haviland and P. Corke
1333
+
1334
+ :seealso: :func:`jacob0`, :func:`jacob_dot`
1335
+ """
1336
+
1337
+ return self.ets().hessian0(q, J0)
1338
+
1339
+ def _get_limit_links(self, end=None, start=None):
1340
+ # For compatibility with ERobot
1341
+
1342
+ return None, None, None
1343
+
1344
+ # -------------------------------------------------------------------------- #
1345
+
1346
+ def _copy_to_cpp(self):
1347
+ # Compress link data into a 1D array
1348
+ L = np.zeros(24 * self.n)
1349
+
1350
+ for i in range(self.n):
1351
+ j = i * 24
1352
+ L[j] = self.links[i].alpha
1353
+ L[j + 1] = self.links[i].a
1354
+ L[j + 2] = self.links[i].theta
1355
+ L[j + 3] = self.links[i].d
1356
+ L[j + 4] = self.links[i].sigma
1357
+ L[j + 5] = self.links[i].offset
1358
+ L[j + 6] = self.links[i].m
1359
+ L[j + 7 : j + 10] = self.links[i].r.flatten()
1360
+ L[j + 10 : j + 19] = self.links[i].I.flatten()
1361
+ L[j + 19] = self.links[i].Jm
1362
+ L[j + 20] = self.links[i].G
1363
+ L[j + 21] = self.links[i].B
1364
+ L[j + 22 : j + 24] = self.links[i].Tc.flatten()
1365
+
1366
+ if self._frne is not None:
1367
+ delete(self._frne)
1368
+ self._frne = init(self.n, self.mdh, L)
1369
+ self._frne_stale = False
1370
+
1371
+ def delete_rne(self):
1372
+ """
1373
+ Frees the memory holding the robot object in C if it has been
1374
+ initialised. Not normally needed — the destructor handles this
1375
+ automatically. Use as an explicit early-free escape hatch.
1376
+ """
1377
+ if self._frne is not None:
1378
+ delete(self._frne)
1379
+ self._frne = None
1380
+ self._frne_stale = True
1381
+
1382
+ def rne(self, q, qd=None, qdd=None, gravity=None, fext=None, base_wrench=False):
1383
+ r"""
1384
+ Inverse dynamics
1385
+
1386
+ :param q: Joint coordinates
1387
+ :type q: ndarray(n)
1388
+ :param qd: Joint velocity
1389
+ :type qd: ndarray(n)
1390
+ :param qdd: The joint accelerations of the robot
1391
+ :type qdd: ndarray(n)
1392
+ :param gravity: gravitational acceleration in the world frame,
1393
+ downwards gravitational force is equivalent to robot base
1394
+ acceleration upwards (positive); overrides robot's gravity
1395
+ value if given
1396
+ :type gravity: ndarray(3)
1397
+ :param fext: Specify wrench acting on the end-effector
1398
+ :math:`W=[F_x F_y F_z M_x M_y M_z]`
1399
+ :type fext: ndarray(6)
1400
+
1401
+ ``tau = rne(q, qd, qdd, grav, fext)`` is the joint torque required for
1402
+ the robot to achieve the specified joint position ``q`` (1xn), velocity
1403
+ ``qd`` (1xn) and acceleration ``qdd`` (1xn), where n is the number of
1404
+ robot joints. ``fext`` describes the wrench acting on the end-effector
1405
+
1406
+ Trajectory operation:
1407
+ If q, qd and qdd (mxn) are matrices with m cols representing a
1408
+ trajectory then tau (mxn) is a matrix with cols corresponding to each
1409
+ trajectory step.
1410
+
1411
+ .. note::
1412
+ - The torque computed contains a contribution due to armature
1413
+ inertia and joint friction.
1414
+ - If a model has no dynamic parameters set the result is zero.
1415
+
1416
+ :seealso: :func:`rne_python`
1417
+ """
1418
+
1419
+ # Symbolic-aware dispatch (rne.md issues 1/2/4): the C extension
1420
+ # requires float64 link/state data throughout, so route straight to
1421
+ # rne_python() -- the always-works fallback -- if the model itself
1422
+ # was built from symbolic parameters (self.symbolic, now
1423
+ # auto-detected at construction time regardless of whether the
1424
+ # caller remembered to pass symbolic=True -- see BaseRobot.__init__)
1425
+ # or if q/qd/qdd for *this call* are symbolic, mirroring the same
1426
+ # is-symbolic-before-touching-C idiom used throughout
1427
+ # roboticstoolbox.ets.fknm for fkine/jacobian dispatch.
1428
+ if self.symbolic or _is_symbolic(q) or _is_symbolic(qd) or _is_symbolic(qdd):
1429
+ return self.rne_python(
1430
+ q, qd, qdd, gravity=gravity, fext=fext, base_wrench=base_wrench
1431
+ )
1432
+
1433
+ if self._frne is None or self._frne_stale:
1434
+ self._copy_to_cpp()
1435
+
1436
+ if self._frne is None:
1437
+ return self.rne_python(
1438
+ q, qd, qdd, gravity=gravity, fext=fext, base_wrench=base_wrench
1439
+ )
1440
+
1441
+ # Belt-and-suspenders: any *other* unanticipated incompatibility
1442
+ # with the C path (e.g. a shape/type quirk the checks above didn't
1443
+ # anticipate) degrades gracefully to the pure-Python implementation
1444
+ # rather than propagating a raw TypeError/ValueError from the C
1445
+ # extension's argument marshalling.
1446
+ q_in, qd_in, qdd_in = q, qd, qdd
1447
+ try:
1448
+ trajn = 1
1449
+
1450
+ try:
1451
+ q = getvector(q, self.n, "row")
1452
+ qd = getvector(qd, self.n, "row")
1453
+ qdd = getvector(qdd, self.n, "row")
1454
+ except ValueError:
1455
+ trajn = q.shape[0]
1456
+ verifymatrix(q, (trajn, self.n))
1457
+ verifymatrix(qd, (trajn, self.n))
1458
+ verifymatrix(qdd, (trajn, self.n))
1459
+
1460
+ # Ensure row slices are C-contiguous (frne C code assumes stride-1 arrays)
1461
+ q = np.ascontiguousarray(q, dtype=float)
1462
+ qd = np.ascontiguousarray(qd, dtype=float)
1463
+ qdd = np.ascontiguousarray(qdd, dtype=float)
1464
+
1465
+ if gravity is None:
1466
+ gravity = self.gravity
1467
+ else:
1468
+ gravity = getvector(gravity, 3)
1469
+ gravity = np.ascontiguousarray(gravity, dtype=float)
1470
+
1471
+ # base rotation and the gravity sign convention are handled inside
1472
+ # frne() itself now -- pass self.base.R through rather than
1473
+ # pre-rotating/negating by hand (see rne.md)
1474
+ base_rot = np.ascontiguousarray(self.base.R, dtype=float)
1475
+
1476
+ if fext is None:
1477
+ fext = np.zeros(6)
1478
+ else:
1479
+ fext = getvector(fext, 6)
1480
+
1481
+ # Whole trajectory in a single C call -- frne() loops over all
1482
+ # trajn rows internally now, rather than once per Python->C
1483
+ # round trip (rne.md plan step 7: ~35% of wall time on a
1484
+ # 1000-row trajectory was previously Python-side looping/
1485
+ # marshalling overhead, not the C computation itself).
1486
+ tau_flat, wbase_flat = frne(
1487
+ self._frne,
1488
+ q,
1489
+ qd,
1490
+ qdd,
1491
+ gravity,
1492
+ base_rot,
1493
+ fext,
1494
+ )
1495
+ tau = np.asarray(tau_flat).reshape(trajn, self.n)
1496
+ wbase = np.asarray(wbase_flat).reshape(trajn, 6)
1497
+ except (TypeError, ValueError):
1498
+ return self.rne_python(
1499
+ q_in, qd_in, qdd_in,
1500
+ gravity=gravity, fext=fext, base_wrench=base_wrench,
1501
+ )
1502
+
1503
+ if base_wrench:
1504
+ if trajn == 1:
1505
+ return tau[0, :], wbase[0, :]
1506
+ else:
1507
+ return tau, wbase
1508
+ else:
1509
+ if trajn == 1:
1510
+ return tau[0, :]
1511
+ else:
1512
+ return tau
1513
+
1514
+ def rne_python(
1515
+ self,
1516
+ Q,
1517
+ QD=None,
1518
+ QDD=None,
1519
+ gravity=None,
1520
+ fext=None,
1521
+ debug=False,
1522
+ base_wrench=False,
1523
+ ):
1524
+ """
1525
+ Compute inverse dynamics via recursive Newton-Euler formulation
1526
+
1527
+ :param Q: Joint coordinates
1528
+ :param QD: Joint velocity
1529
+ :param QDD: Joint acceleration
1530
+ :param gravity: gravitational acceleration in the world frame,
1531
+ downwards gravitational force is equivalent to robot base
1532
+ acceleration upwards (positive); defaults to attribute of self
1533
+ :type gravity: array_like(3), optional
1534
+ :param fext: end-effector wrench, defaults to None
1535
+ :type fext: array-like(6), optional
1536
+ :param debug: print debug information to console, defaults to False
1537
+ :type debug: bool, optional
1538
+ :param base_wrench: compute the base wrench, defaults to False
1539
+ :type base_wrench: bool, optional
1540
+ :raises ValueError: for misshaped inputs
1541
+ :return: Joint force/torques
1542
+ :rtype: NumPy array
1543
+
1544
+ Recursive Newton-Euler for standard or modified Denavit-Hartenberg notation.
1545
+
1546
+ - ``rne_python(q, qd, qdd)`` where the arguments have shape (n,) where
1547
+ n is the number of robot joints. The result has shape (n,).
1548
+ - ``rne_python(q, qd, qdd)`` where the arguments have shape (m,n)
1549
+ where n is the number of robot joints and where m is the number of
1550
+ steps in the joint trajectory. The result has shape (m,n).
1551
+ - ``rne_python(p)`` where the input is a 1D array ``p`` = [q, qd, qdd]
1552
+ with shape (3n,), and the result has shape (n,).
1553
+ - ``rne_python(p)`` where the input is a 2D array ``p`` = [q, qd, qdd]
1554
+ with shape (m,3n) and the result has shape (m,n).
1555
+
1556
+ .. note::
1557
+ - This is a pure Python implementation and slower than the .rne()
1558
+ which is written in C.
1559
+ - This version supports symbolic model parameters
1560
+ - Verified against MATLAB code
1561
+
1562
+ :seealso: :func:`rne`
1563
+ """
1564
+
1565
+ if np.array_equal(self.base.A, np.eye(4)):
1566
+ base = None
1567
+ else:
1568
+ base = self.base.A
1569
+
1570
+ def removesmall(x):
1571
+ return x
1572
+
1573
+ n = self.n
1574
+
1575
+ # dtype must reflect this *call's* symbolic-ness, not just the
1576
+ # model's: self.symbolic is a construction-time flag over the link
1577
+ # parameters, but Q/QD/QDD can be symbolic even for a robot built
1578
+ # entirely from numeric parameters (e.g. differentiating tau
1579
+ # symbolically w.r.t. q for a concrete, numeric-mass robot) -- see
1580
+ # rne.md issue 4. Using only self.symbolic here left rne_python()
1581
+ # allocating float64 arrays that crashed on the first symbolic
1582
+ # intermediate value, even though it's supposed to be the
1583
+ # always-works fallback DHRobot.rne() dispatches to.
1584
+ symbolic_call = (
1585
+ self.symbolic or _is_symbolic(Q) or _is_symbolic(QD) or _is_symbolic(QDD)
1586
+ )
1587
+ if symbolic_call:
1588
+ dtype = "O"
1589
+ else:
1590
+ dtype = None
1591
+
1592
+ z0 = np.array([0, 0, 1], dtype=dtype)
1593
+
1594
+ if gravity is None:
1595
+ gravity = self.gravity # default gravity from the object
1596
+ else:
1597
+ gravity = getvector(gravity, 3)
1598
+
1599
+ if fext is None:
1600
+ fext = np.zeros((6,), dtype=dtype)
1601
+ else:
1602
+ fext = getvector(fext, 6)
1603
+
1604
+ if debug:
1605
+ print("grav", gravity)
1606
+ print("fext", fext)
1607
+
1608
+ # unpack the joint coordinates and derivatives
1609
+ if Q is not None and QD is None and QDD is None:
1610
+ # single argument case
1611
+ Q = getmatrix(Q, (None, self.n * 3))
1612
+ q = Q[:, 0:n]
1613
+ qd = Q[:, n : 2 * n]
1614
+ qdd = Q[:, 2 * n :]
1615
+
1616
+ else:
1617
+ # 3 argument case
1618
+ q = getmatrix(Q, (None, self.n))
1619
+ qd = getmatrix(QD, (None, self.n))
1620
+ qdd = getmatrix(QDD, (None, self.n))
1621
+
1622
+ nk = q.shape[0]
1623
+
1624
+ tau = np.zeros((nk, n), dtype=dtype)
1625
+ if base_wrench:
1626
+ # always 6 (a wrench), not n (joint count) -- previously used n,
1627
+ # which happened to work for 6-DOF robots by coincidence and
1628
+ # crashed with a shape mismatch for any other DOF count
1629
+ wbase = np.zeros((nk, 6), dtype=dtype)
1630
+
1631
+ for k in range(nk):
1632
+ # take the k'th row of data
1633
+ q_k = q[k, :]
1634
+ qd_k = qd[k, :]
1635
+ qdd_k = qdd[k, :]
1636
+
1637
+ if debug:
1638
+ print("q_k", q_k)
1639
+ print("qd_k", qd_k)
1640
+ print("qdd_k", qdd_k)
1641
+ print()
1642
+
1643
+ # joint vector quantities stored columwise in matrix
1644
+ # m suffix for matrix
1645
+ Fm = np.zeros((3, n), dtype=dtype)
1646
+ Nm = np.zeros((3, n), dtype=dtype)
1647
+ # if robot.issym
1648
+ # pstarm = sym([]);
1649
+ # else
1650
+ # pstarm = [];
1651
+ pstarm = np.zeros((3, n), dtype=dtype)
1652
+ Rm = []
1653
+
1654
+ # rotate base velocity and acceleration into L1 frame
1655
+ # base has zero angular velocity
1656
+ w = np.zeros((3,), dtype=dtype)
1657
+ # base has zero angular acceleration
1658
+ wd = np.zeros((3,), dtype=dtype)
1659
+ vd = -gravity # type: ignore
1660
+
1661
+ if base is not None:
1662
+ Rb = t2r(base).T
1663
+ w = Rb @ w
1664
+ wd = Rb @ wd
1665
+ # rotate the already-negated vd (was missing the negation --
1666
+ # this branch used to compute +Rb @ gravity while the
1667
+ # identity-base case above correctly used -gravity)
1668
+ vd = Rb @ vd
1669
+
1670
+ # ---------------- initialize some variables ----------------- #
1671
+
1672
+ for j in range(n):
1673
+ link = self.links[j]
1674
+
1675
+ # compute the link rotation matrix
1676
+ if link.sigma == 0:
1677
+ # revolute axis
1678
+ Tj = link.A(q_k[j]).A
1679
+ d = link.d
1680
+ else:
1681
+ # prismatic
1682
+ Tj = link.A(link.theta).A
1683
+ d = q_k[j]
1684
+
1685
+ # compute pstar:
1686
+ # O_{j-1} to O_j in {j}, negative inverse of link xform
1687
+ alpha = link.alpha
1688
+ if self.mdh:
1689
+ pstar = np.r_[link.a, -d * sym.sin(alpha), d * sym.cos(alpha)]
1690
+ # NOT baking base into Tj/pstar here (this block used to,
1691
+ # before being removed): base rotation is already applied
1692
+ # exactly once, to gravity/vd before this loop starts.
1693
+ # Also folding it into Rm[0] here double-counted it --
1694
+ # confirmed by tracing TwoLink(mdh=True)'s gravity-only
1695
+ # case, where vd ended up rotated by the base twice.
1696
+ # ne.c matches this: it only ever rotates gravity by the
1697
+ # base (in the nanobind glue), never any per-link R.
1698
+ else:
1699
+ pstar = np.r_[link.a, d * sym.sin(alpha), d * sym.cos(alpha)]
1700
+
1701
+ # stash them for later
1702
+ Rm.append(t2r(Tj))
1703
+ pstarm[:, j] = pstar
1704
+
1705
+ # ----------------- the forward recursion -------------------- #
1706
+
1707
+ for j, link in enumerate(self.links):
1708
+ Rt = Rm[j].T # transpose!!
1709
+ pstar = pstarm[:, j]
1710
+ r = link.r
1711
+
1712
+ # statement order is important here
1713
+
1714
+ if self.mdh:
1715
+ if link.isrevolute:
1716
+ # revolute axis
1717
+ w_ = Rt @ w + z0 * qd_k[j]
1718
+ wd_ = Rt @ wd + z0 * qdd_k[j] + _cross(Rt @ w, z0 * qd_k[j])
1719
+ # Rt must distribute over the whole bracket, not just
1720
+ # the first term -- matches ne.c's MODIFIED-DH branch,
1721
+ # which does rot_trans_vect_mult() (= Rt @ ...) on the
1722
+ # full OMEGADOT(j-1)xPSTAR + OMEGA(j-1)x(OMEGA(j-1)xPSTAR)
1723
+ # + ACC(j-1) sum. The prismatic case below already has
1724
+ # this right; this revolute case was missing the
1725
+ # parentheses (and therefore wrong for any MDH robot).
1726
+ vd_ = Rt @ (_cross(wd, pstar) + _cross(w, _cross(w, pstar)) + vd)
1727
+ else:
1728
+ # prismatic axis
1729
+ w_ = Rt @ w
1730
+ wd_ = Rt @ wd
1731
+ vd_ = (
1732
+ Rt @ (_cross(wd, pstar) + _cross(w, _cross(w, pstar)) + vd)
1733
+ + 2 * _cross(Rt @ w, z0 * qd_k[j])
1734
+ + z0 * qdd_k[j]
1735
+ )
1736
+ # trailing underscore means new value, update here
1737
+ w = w_
1738
+ wd = wd_
1739
+ vd = vd_
1740
+ else:
1741
+ if link.isrevolute:
1742
+ # revolute axis
1743
+ wd = Rt @ (wd + z0 * qdd_k[j] + _cross(w, z0 * qd_k[j]))
1744
+ w = Rt @ (w + z0 * qd_k[j])
1745
+ vd = _cross(wd, pstar) + _cross(w, _cross(w, pstar)) + Rt @ vd
1746
+ else:
1747
+ # prismatic axis
1748
+ w = Rt @ w
1749
+ wd = Rt @ wd
1750
+ vd = (
1751
+ Rt @ (z0 * qdd_k[j] + vd)
1752
+ + _cross(wd, pstar)
1753
+ + 2 * _cross(w, Rt @ z0 * qd_k[j])
1754
+ + _cross(w, _cross(w, pstar))
1755
+ )
1756
+
1757
+ vhat = _cross(wd, r) + _cross(w, _cross(w, r)) + vd
1758
+ Fm[:, j] = link.m * vhat
1759
+ Nm[:, j] = link.I @ wd + _cross(w, link.I @ w)
1760
+
1761
+ if debug:
1762
+ print("w: ", removesmall(w))
1763
+ print("wd: ", removesmall(wd))
1764
+ print("vd: ", removesmall(vd))
1765
+ print("vdbar: ", removesmall(vhat))
1766
+ print()
1767
+
1768
+ if debug:
1769
+ print("Fm\n", Fm)
1770
+ print("Nm\n", Nm)
1771
+
1772
+ # ----------------- the backward recursion -------------------- #
1773
+
1774
+ f = fext[:3] # force/moments on end of arm
1775
+ nn = fext[3:]
1776
+
1777
+ for j in range(n - 1, -1, -1):
1778
+ link = self.links[j]
1779
+ r = link.r
1780
+
1781
+ #
1782
+ # order of these statements is important, since both
1783
+ # nn and f are functions of previous f.
1784
+ #
1785
+ if self.mdh:
1786
+ if j == (n - 1):
1787
+ R = np.eye(3, dtype=dtype)
1788
+ pstar = np.zeros((3,), dtype=dtype)
1789
+ else:
1790
+ R = Rm[j + 1]
1791
+ pstar = pstarm[:, j + 1]
1792
+
1793
+ f_ = R @ f + Fm[:, j]
1794
+ nn_ = (
1795
+ R @ nn
1796
+ + _cross(pstar, R @ f)
1797
+ # this link's own force acts through its own CoM
1798
+ # offset r, not pstar (which is the offset to the
1799
+ # *next* link's origin) -- matches ne.c's MODIFIED
1800
+ # branch: vect_cross(&t2, R_COG(j), &F) uses R_COG(j)
1801
+ # (this link's r), not PSTAR(j+1)
1802
+ + _cross(r, Fm[:, j])
1803
+ + Nm[:, j]
1804
+ )
1805
+ f = f_
1806
+ nn = nn_
1807
+
1808
+ else:
1809
+ pstar = pstarm[:, j]
1810
+ if j == (n - 1):
1811
+ R = np.eye(3, dtype=dtype)
1812
+ else:
1813
+ R = Rm[j + 1]
1814
+
1815
+ nn = (
1816
+ R @ (nn + _cross(R.T @ pstar, f))
1817
+ + _cross(pstar + r, Fm[:, j])
1818
+ + Nm[:, j]
1819
+ )
1820
+ f = R @ f + Fm[:, j]
1821
+
1822
+ if debug:
1823
+ print("f: ", removesmall(f))
1824
+ print("n: ", removesmall(nn))
1825
+
1826
+ R = Rm[j]
1827
+ if self.mdh:
1828
+ if link.isrevolute:
1829
+ # revolute axis
1830
+ t = nn @ z0
1831
+ else:
1832
+ # prismatic
1833
+ t = f @ z0
1834
+ else:
1835
+ if link.isrevolute:
1836
+ # revolute axis
1837
+ t = nn @ (R.T @ z0)
1838
+ else:
1839
+ # prismatic
1840
+ t = f @ (R.T @ z0)
1841
+
1842
+ # add joint inertia and friction
1843
+ # no Coulomb friction if model is symbolic
1844
+ tau[k, j] = (
1845
+ t
1846
+ + link.G**2 * link.Jm * qdd_k[j]
1847
+ - link.friction(qd_k[j], coulomb=not symbolic_call)
1848
+ )
1849
+ if debug:
1850
+ print(
1851
+ f"j={j:}, G={link.G:}, Jm={link.Jm:},"
1852
+ f" friction={link.friction(qd_k[j], coulomb=False):}"
1853
+ )
1854
+ print()
1855
+
1856
+ # compute the base wrench and save it
1857
+ if base_wrench:
1858
+ R = Rm[0]
1859
+ nn = R @ nn
1860
+ f = R @ f
1861
+ wbase[k, :] = np.r_[f, nn]
1862
+
1863
+ if base_wrench:
1864
+ if tau.shape[0] == 1:
1865
+ return tau.flatten(), wbase.flatten()
1866
+ else:
1867
+ return tau, wbase
1868
+ else:
1869
+ if tau.shape[0] == 1:
1870
+ return tau.flatten()
1871
+ else:
1872
+ return tau
1873
+
1874
+ # -------------------------------------------------------------------------- #
1875
+
1876
+ def ikine_6s(self, T, config, ikfunc):
1877
+ # Undo base and tool transformations, but if they are not
1878
+ # set, skip the operation. Nicer for symbolics
1879
+ if np.array_equal(self.base.A, np.eye(4)):
1880
+ base = None
1881
+ else:
1882
+ base = self.base
1883
+
1884
+ if np.array_equal(self.tool.A, np.eye(4)):
1885
+ tool = None
1886
+ else:
1887
+ tool = self.tool
1888
+
1889
+ if base is not None:
1890
+ T = base.inv() * T
1891
+ if tool is not None:
1892
+ T = tool.inv() * T
1893
+
1894
+ # q = np.zeros((6,))
1895
+ solutions = []
1896
+
1897
+ for k, Tk in enumerate(T):
1898
+ # get model specific solution for first 3 joints
1899
+ theta = ikfunc(self, Tk, config)
1900
+
1901
+ if isinstance(theta, np.ndarray):
1902
+ # Solve for the wrist rotation
1903
+ # We need to account for some random translations between the
1904
+ # first and last 3 joints (d4) and also d6,a6,alpha6 in the
1905
+ # final frame.
1906
+
1907
+ # Transform of first 3 joints
1908
+ T13 = self.A([0, 2], theta)
1909
+
1910
+ # T = T13 * Tz(d4) * R * Tz(d6) Tx(a5)
1911
+ Td4 = SE3(0, 0, self.links[3].d) # Tz(d4)
1912
+
1913
+ # Tz(d6) Tx(a5) Rx(alpha6)
1914
+ Tt = SE3(self.links[5].a, 0, self.links[5].d) * SE3.Rx(
1915
+ self.links[5].alpha
1916
+ )
1917
+
1918
+ R = Td4.inv() * T13.inv() * Tk * Tt.inv() # type: ignore[union-attr]
1919
+
1920
+ # The spherical wrist implements Euler angles
1921
+ if "f" in config:
1922
+ eul = R.eul(flip=True)
1923
+ else:
1924
+ eul = R.eul()
1925
+ theta = np.r_[theta, eul]
1926
+ if self.links[3].alpha > 0:
1927
+ theta[4] = -theta[4]
1928
+
1929
+ # Remove the link offset angles
1930
+ theta = theta - self.offset
1931
+
1932
+ # solution = iksol(theta, True, "")
1933
+ solution = IKSolution(q=theta, success=True)
1934
+
1935
+ else:
1936
+ # ikfunc can return None or a str reason
1937
+ if theta is None:
1938
+ solution = IKSolution(q=None, success=False)
1939
+ else:
1940
+ solution = IKSolution(q=None, success=False, reason=theta)
1941
+
1942
+ solutions.append(solution)
1943
+
1944
+ if len(T) == 1:
1945
+ return solutions[0]
1946
+ else:
1947
+ return IKSolution(
1948
+ np.vstack([sol.q for sol in solutions]),
1949
+ np.array([sol.success for sol in solutions]),
1950
+ [sol.reason for sol in solutions],
1951
+ )
1952
+
1953
+ def config_validate(self, config, allowables):
1954
+ """
1955
+ Validate a configuration string
1956
+
1957
+ :param config: a configuration string
1958
+ :type config: str
1959
+ :param allowable: [description]
1960
+ :type allowable: tuple of str
1961
+ :raises ValueError: bad character in configuration string
1962
+ :return: configuration string
1963
+ :rtype: str
1964
+
1965
+ For analytic inverse kinematics the Toolbox uses a string whose
1966
+ letters indicate particular solutions, eg. for the Puma 560
1967
+
1968
+ ========= ===================
1969
+ Character Meaning
1970
+ ========= ===================
1971
+ 'l' lefty
1972
+ 'r' righty
1973
+ 'u' elbow up
1974
+ 'd' elbow down
1975
+ 'n' wrist not flipped
1976
+ 'f' wrist flipped
1977
+ ========= ===================
1978
+
1979
+ This method checks that the configuration string is valid and adds
1980
+ default values for missing characters. For example:
1981
+
1982
+ config = self.config_validate(config, ('lr', 'ud', 'nf'))
1983
+
1984
+ indicates the valid characters, and the first character in each
1985
+ string is the default, ie. if neither 'l' or 'r' is given then
1986
+ 'l' will be added to the string.
1987
+
1988
+ """
1989
+ for c in config:
1990
+ if not any([c in allowable for allowable in allowables]):
1991
+ raise ValueError(f"bad config specifier <{c}>")
1992
+ for allowable in allowables:
1993
+ if all([a not in config for a in allowable]):
1994
+ config += allowable[0]
1995
+ return config
1996
+
1997
+ # -------------------------------------------------------------------------- #
1998
+
1999
+ def ik_lm_chan(
2000
+ self,
2001
+ Tep: np.ndarray | SE3,
2002
+ q0: np.ndarray | None = None,
2003
+ ilimit: int = 30,
2004
+ slimit: int = 100,
2005
+ tol: float = 1e-6,
2006
+ reject_jl: bool = True,
2007
+ we: np.ndarray | None = None,
2008
+ λ: float = 1.0,
2009
+ ) -> tuple[np.ndarray, int, int, int, float]:
2010
+ """
2011
+ Numerical inverse kinematics by Levenberg-Marquadt optimization (Chan's Method)
2012
+
2013
+ :param Tep: The desired end-effector pose or pose trajectory
2014
+ :param q0: initial joint configuration (default to random valid joint
2015
+ configuration constrained by the joint limits of the robot)
2016
+ :param ilimit: maximum number of iterations per search
2017
+ :param slimit: maximum number of search attempts
2018
+ :param tol: final error tolerance
2019
+ :param reject_jl: constrain the solution to being within the joint limits of
2020
+ the robot (reject solution with invalid joint configurations and perform
2021
+ another search up to the slimit)
2022
+ :param we: a mask vector which weights the end-effector error priority.
2023
+ Corresponds to translation in X, Y and Z and rotation about X, Y and Z
2024
+ respectively
2025
+ :param λ: value of lambda for the damping matrix Wn
2026
+
2027
+ :return: inverse kinematic solution
2028
+ :rtype: tuple (q, success, iterations, searches, residual)
2029
+
2030
+ ``sol = ets.ik_lm_chan(Tep)`` are the joint coordinates (n) corresponding
2031
+ to the robot end-effector pose ``Tep`` which is an ``SE3`` or ``ndarray`` object.
2032
+ This method can be used for robots with any number of degrees of freedom.
2033
+ The return value ``sol`` is a tuple with elements:
2034
+
2035
+ ============== ========== ===============================================
2036
+ Element Type Description
2037
+ ============== ========== ===============================================
2038
+ ``q`` ndarray(n) joint coordinates in units of radians or metres
2039
+ ``success`` int whether a solution was found
2040
+ ``iterations`` int total number of iterations
2041
+ ``searches`` int total number of searches
2042
+ ``residual`` float final value of cost function
2043
+ ============== ========== ===============================================
2044
+
2045
+ If ``success == 0`` the ``q`` values will be valid numbers, but the
2046
+ solution will be in error. The amount of error is indicated by
2047
+ the ``residual``.
2048
+
2049
+ **Joint Limits**:
2050
+
2051
+ ``sol = robot.ikine_LM(T, slimit=100)`` which is the deafualt for this method.
2052
+ The solver will initialise a solution attempt with a random valid q0 and
2053
+ perform a maximum of ilimit steps within this attempt. If a solution is not
2054
+ found, this process is repeated up to slimit times.
2055
+
2056
+ **Global search**:
2057
+
2058
+ ``sol = robot.ikine_LM(T, reject_jl=True)`` is the deafualt for this method.
2059
+ By setting reject_jl to True, the solver will discard any solution which
2060
+ violates the defined joint limits of the robot. The solver will then
2061
+ re-initialise with a new random q0 and repeat the process up to slimit times.
2062
+ Note that finding a solution with valid joint coordinates takes longer than
2063
+ without.
2064
+
2065
+ **Underactuated robots:**
2066
+
2067
+ For the case where the manipulator has fewer than 6 DOF the
2068
+ solution space has more dimensions than can be spanned by the
2069
+ manipulator joint coordinates.
2070
+
2071
+ In this case we specify the ``we`` option where the ``we`` vector
2072
+ (6) specifies the Cartesian DOF (in the wrist coordinate frame) that
2073
+ will be ignored in reaching a solution. The we vector has six
2074
+ elements that correspond to translation in X, Y and Z, and rotation
2075
+ about X, Y and Z respectively. The value can be 0 (for ignore)
2076
+ or above to assign a priority relative to other Cartesian DoF. The number
2077
+ of non-zero elements must equal the number of manipulator DOF.
2078
+
2079
+ For example when using a 3 DOF manipulator tool orientation might
2080
+ be unimportant, in which case use the option ``we=[1, 1, 1, 0, 0, 0]``.
2081
+
2082
+
2083
+
2084
+ .. note::
2085
+
2086
+ - See `Toolbox kinematics wiki page <https://github.com/petercorke/robotics-toolbox-python/wiki/Kinematics>`_
2087
+ - Implements a Levenberg-Marquadt variable-damping solver.
2088
+ - The tolerance is computed on the norm of the error between
2089
+ current and desired tool pose. This norm is computed from
2090
+ distances and angles without any kind of weighting.
2091
+ - The inverse kinematic solution is generally not unique, and
2092
+ depends on the initial guess ``q0``.
2093
+
2094
+ :references:
2095
+ TODO
2096
+
2097
+ :seealso:
2098
+ TODO
2099
+ """
2100
+
2101
+ return self.ets().ik_lm_chan(Tep, q0, ilimit, slimit, tol, reject_jl, we, λ) # type: ignore[attr-defined]
2102
+
2103
+ def ik_lm_wampler(
2104
+ self,
2105
+ Tep: np.ndarray | SE3,
2106
+ q0: np.ndarray | None = None,
2107
+ ilimit: int = 30,
2108
+ slimit: int = 100,
2109
+ tol: float = 1e-6,
2110
+ reject_jl: bool = True,
2111
+ we: np.ndarray | None = None,
2112
+ λ: float = 1.0,
2113
+ ) -> tuple[np.ndarray, int, int, int, float]:
2114
+ """
2115
+ Numerical inverse kinematics by Levenberg-Marquadt optimization (Wamplers's Method)
2116
+
2117
+ :param Tep: The desired end-effector pose or pose trajectory
2118
+ :param q0: initial joint configuration (default to random valid joint
2119
+ configuration constrained by the joint limits of the robot)
2120
+ :param ilimit: maximum number of iterations per search
2121
+ :param slimit: maximum number of search attempts
2122
+ :param tol: final error tolerance
2123
+ :param reject_jl: constrain the solution to being within the joint limits of
2124
+ the robot (reject solution with invalid joint configurations and perform
2125
+ another search up to the slimit)
2126
+ :param we: a mask vector which weights the end-effector error priority.
2127
+ Corresponds to translation in X, Y and Z and rotation about X, Y and Z
2128
+ respectively
2129
+ :param λ: value of lambda for the damping matrix Wn
2130
+
2131
+ :return: inverse kinematic solution
2132
+ :rtype: tuple (q, success, iterations, searches, residual)
2133
+
2134
+ ``sol = ets.ik_lm_chan(Tep)`` are the joint coordinates (n) corresponding
2135
+ to the robot end-effector pose ``Tep`` which is an ``SE3`` or ``ndarray`` object.
2136
+ This method can be used for robots with any number of degrees of freedom.
2137
+ The return value ``sol`` is a tuple with elements:
2138
+
2139
+ ============== ========== ===============================================
2140
+ Element Type Description
2141
+ ============== ========== ===============================================
2142
+ ``q`` ndarray(n) joint coordinates in units of radians or metres
2143
+ ``success`` int whether a solution was found
2144
+ ``iterations`` int total number of iterations
2145
+ ``searches`` int total number of searches
2146
+ ``residual`` float final value of cost function
2147
+ ============== ========== ===============================================
2148
+
2149
+ If ``success == 0`` the ``q`` values will be valid numbers, but the
2150
+ solution will be in error. The amount of error is indicated by
2151
+ the ``residual``.
2152
+
2153
+ **Joint Limits**:
2154
+
2155
+ ``sol = robot.ikine_LM(T, slimit=100)`` which is the deafualt for this method.
2156
+ The solver will initialise a solution attempt with a random valid q0 and
2157
+ perform a maximum of ilimit steps within this attempt. If a solution is not
2158
+ found, this process is repeated up to slimit times.
2159
+
2160
+ **Global search**:
2161
+
2162
+ ``sol = robot.ikine_LM(T, reject_jl=True)`` is the deafualt for this method.
2163
+ By setting reject_jl to True, the solver will discard any solution which
2164
+ violates the defined joint limits of the robot. The solver will then
2165
+ re-initialise with a new random q0 and repeat the process up to slimit times.
2166
+ Note that finding a solution with valid joint coordinates takes longer than
2167
+ without.
2168
+
2169
+ **Underactuated robots:**
2170
+
2171
+ For the case where the manipulator has fewer than 6 DOF the
2172
+ solution space has more dimensions than can be spanned by the
2173
+ manipulator joint coordinates.
2174
+
2175
+ In this case we specify the ``we`` option where the ``we`` vector
2176
+ (6) specifies the Cartesian DOF (in the wrist coordinate frame) that
2177
+ will be ignored in reaching a solution. The we vector has six
2178
+ elements that correspond to translation in X, Y and Z, and rotation
2179
+ about X, Y and Z respectively. The value can be 0 (for ignore)
2180
+ or above to assign a priority relative to other Cartesian DoF. The number
2181
+ of non-zero elements must equal the number of manipulator DOF.
2182
+
2183
+ For example when using a 3 DOF manipulator tool orientation might
2184
+ be unimportant, in which case use the option ``we=[1, 1, 1, 0, 0, 0]``.
2185
+
2186
+
2187
+
2188
+ .. note::
2189
+
2190
+ - See `Toolbox kinematics wiki page <https://github.com/petercorke/robotics-toolbox-python/wiki/Kinematics>`_
2191
+ - Implements a Levenberg-Marquadt variable-damping solver.
2192
+ - The tolerance is computed on the norm of the error between
2193
+ current and desired tool pose. This norm is computed from
2194
+ distances and angles without any kind of weighting.
2195
+ - The inverse kinematic solution is generally not unique, and
2196
+ depends on the initial guess ``q0``.
2197
+
2198
+ :references:
2199
+ TODO
2200
+
2201
+ :seealso:
2202
+ TODO
2203
+ """
2204
+
2205
+ return self.ets().ik_lm_wampler(Tep, q0, ilimit, slimit, tol, reject_jl, we, λ) # type: ignore[attr-defined]
2206
+
2207
+ def ik_lm_sugihara(
2208
+ self,
2209
+ Tep: np.ndarray | SE3,
2210
+ q0: np.ndarray | None = None,
2211
+ ilimit: int = 30,
2212
+ slimit: int = 100,
2213
+ tol: float = 1e-6,
2214
+ reject_jl: bool = True,
2215
+ we: np.ndarray | None = None,
2216
+ λ: float = 1.0,
2217
+ ) -> tuple[np.ndarray, int, int, int, float]:
2218
+ """
2219
+ Numerical inverse kinematics by Levenberg-Marquadt optimization (Sugihara's Method)
2220
+
2221
+ :param Tep: The desired end-effector pose or pose trajectory
2222
+ :param q0: initial joint configuration (default to random valid joint
2223
+ configuration constrained by the joint limits of the robot)
2224
+ :param ilimit: maximum number of iterations per search
2225
+ :param slimit: maximum number of search attempts
2226
+ :param tol: final error tolerance
2227
+ :param reject_jl: constrain the solution to being within the joint limits of
2228
+ the robot (reject solution with invalid joint configurations and perform
2229
+ another search up to the slimit)
2230
+ :param we: a mask vector which weights the end-effector error priority.
2231
+ Corresponds to translation in X, Y and Z and rotation about X, Y and Z
2232
+ respectively
2233
+ :param λ: value of lambda for the damping matrix Wn
2234
+
2235
+ :return: inverse kinematic solution
2236
+ :rtype: tuple (q, success, iterations, searches, residual)
2237
+
2238
+ ``sol = ets.ik_lm_chan(Tep)`` are the joint coordinates (n) corresponding
2239
+ to the robot end-effector pose ``Tep`` which is an ``SE3`` or ``ndarray`` object.
2240
+ This method can be used for robots with any number of degrees of freedom.
2241
+ The return value ``sol`` is a tuple with elements:
2242
+
2243
+ ============== ========== ===============================================
2244
+ Element Type Description
2245
+ ============== ========== ===============================================
2246
+ ``q`` ndarray(n) joint coordinates in units of radians or metres
2247
+ ``success`` int whether a solution was found
2248
+ ``iterations`` int total number of iterations
2249
+ ``searches`` int total number of searches
2250
+ ``residual`` float final value of cost function
2251
+ ============== ========== ===============================================
2252
+
2253
+ If ``success == 0`` the ``q`` values will be valid numbers, but the
2254
+ solution will be in error. The amount of error is indicated by
2255
+ the ``residual``.
2256
+
2257
+ **Joint Limits**:
2258
+
2259
+ ``sol = robot.ikine_LM(T, slimit=100)`` which is the deafualt for this method.
2260
+ The solver will initialise a solution attempt with a random valid q0 and
2261
+ perform a maximum of ilimit steps within this attempt. If a solution is not
2262
+ found, this process is repeated up to slimit times.
2263
+
2264
+ **Global search**:
2265
+
2266
+ ``sol = robot.ikine_LM(T, reject_jl=True)`` is the deafualt for this method.
2267
+ By setting reject_jl to True, the solver will discard any solution which
2268
+ violates the defined joint limits of the robot. The solver will then
2269
+ re-initialise with a new random q0 and repeat the process up to slimit times.
2270
+ Note that finding a solution with valid joint coordinates takes longer than
2271
+ without.
2272
+
2273
+ **Underactuated robots:**
2274
+
2275
+ For the case where the manipulator has fewer than 6 DOF the
2276
+ solution space has more dimensions than can be spanned by the
2277
+ manipulator joint coordinates.
2278
+
2279
+ In this case we specify the ``we`` option where the ``we`` vector
2280
+ (6) specifies the Cartesian DOF (in the wrist coordinate frame) that
2281
+ will be ignored in reaching a solution. The we vector has six
2282
+ elements that correspond to translation in X, Y and Z, and rotation
2283
+ about X, Y and Z respectively. The value can be 0 (for ignore)
2284
+ or above to assign a priority relative to other Cartesian DoF. The number
2285
+ of non-zero elements must equal the number of manipulator DOF.
2286
+
2287
+ For example when using a 3 DOF manipulator tool orientation might
2288
+ be unimportant, in which case use the option ``we=[1, 1, 1, 0, 0, 0]``.
2289
+
2290
+
2291
+
2292
+ .. note::
2293
+
2294
+ - See `Toolbox kinematics wiki page <https://github.com/petercorke/robotics-toolbox-python/wiki/Kinematics>`_
2295
+ - Implements a Levenberg-Marquadt variable-damping solver.
2296
+ - The tolerance is computed on the norm of the error between
2297
+ current and desired tool pose. This norm is computed from
2298
+ distances and angles without any kind of weighting.
2299
+ - The inverse kinematic solution is generally not unique, and
2300
+ depends on the initial guess ``q0``.
2301
+
2302
+ :references:
2303
+ TODO
2304
+
2305
+ :seealso:
2306
+ TODO
2307
+ """
2308
+
2309
+ return self.ets().ik_lm_sugihara(Tep, q0, ilimit, slimit, tol, reject_jl, we, λ) # type: ignore[attr-defined]
2310
+
2311
+ def ik_nr(
2312
+ self,
2313
+ Tep: np.ndarray | SE3,
2314
+ q0: np.ndarray | None = None,
2315
+ ilimit: int = 30,
2316
+ slimit: int = 100,
2317
+ tol: float = 1e-6,
2318
+ reject_jl: bool = True,
2319
+ we: np.ndarray | None = None,
2320
+ use_pinv: int = True,
2321
+ pinv_damping: float = 0.0,
2322
+ ) -> tuple[np.ndarray, int, int, int, float]:
2323
+ """
2324
+ Numerical inverse kinematics by Levenberg-Marquadt optimization (Newton-Raphson Method)
2325
+
2326
+ :param Tep: The desired end-effector pose or pose trajectory
2327
+ :param q0: initial joint configuration (default to random valid joint
2328
+ configuration constrained by the joint limits of the robot)
2329
+ :param ilimit: maximum number of iterations per search
2330
+ :param slimit: maximum number of search attempts
2331
+ :param tol: final error tolerance
2332
+ :param reject_jl: constrain the solution to being within the joint limits of
2333
+ the robot (reject solution with invalid joint configurations and perform
2334
+ another search up to the slimit)
2335
+ :param we: a mask vector which weights the end-effector error priority.
2336
+ Corresponds to translation in X, Y and Z and rotation about X, Y and Z
2337
+ respectively
2338
+ :param λ: value of lambda for the damping matrix Wn
2339
+
2340
+ :return: inverse kinematic solution
2341
+ :rtype: tuple (q, success, iterations, searches, residual)
2342
+
2343
+ ``sol = ets.ik_lm_chan(Tep)`` are the joint coordinates (n) corresponding
2344
+ to the robot end-effector pose ``Tep`` which is an ``SE3`` or ``ndarray`` object.
2345
+ This method can be used for robots with any number of degrees of freedom.
2346
+ The return value ``sol`` is a tuple with elements:
2347
+
2348
+ ============== ========== ===============================================
2349
+ Element Type Description
2350
+ ============== ========== ===============================================
2351
+ ``q`` ndarray(n) joint coordinates in units of radians or metres
2352
+ ``success`` int whether a solution was found
2353
+ ``iterations`` int total number of iterations
2354
+ ``searches`` int total number of searches
2355
+ ``residual`` float final value of cost function
2356
+ ============== ========== ===============================================
2357
+
2358
+ If ``success == 0`` the ``q`` values will be valid numbers, but the
2359
+ solution will be in error. The amount of error is indicated by
2360
+ the ``residual``.
2361
+
2362
+ **Joint Limits**:
2363
+
2364
+ ``sol = robot.ikine_LM(T, slimit=100)`` which is the deafualt for this method.
2365
+ The solver will initialise a solution attempt with a random valid q0 and
2366
+ perform a maximum of ilimit steps within this attempt. If a solution is not
2367
+ found, this process is repeated up to slimit times.
2368
+
2369
+ **Global search**:
2370
+
2371
+ ``sol = robot.ikine_LM(T, reject_jl=True)`` is the deafualt for this method.
2372
+ By setting reject_jl to True, the solver will discard any solution which
2373
+ violates the defined joint limits of the robot. The solver will then
2374
+ re-initialise with a new random q0 and repeat the process up to slimit times.
2375
+ Note that finding a solution with valid joint coordinates takes longer than
2376
+ without.
2377
+
2378
+ **Underactuated robots:**
2379
+
2380
+ For the case where the manipulator has fewer than 6 DOF the
2381
+ solution space has more dimensions than can be spanned by the
2382
+ manipulator joint coordinates.
2383
+
2384
+ In this case we specify the ``we`` option where the ``we`` vector
2385
+ (6) specifies the Cartesian DOF (in the wrist coordinate frame) that
2386
+ will be ignored in reaching a solution. The we vector has six
2387
+ elements that correspond to translation in X, Y and Z, and rotation
2388
+ about X, Y and Z respectively. The value can be 0 (for ignore)
2389
+ or above to assign a priority relative to other Cartesian DoF. The number
2390
+ of non-zero elements must equal the number of manipulator DOF.
2391
+
2392
+ For example when using a 3 DOF manipulator tool orientation might
2393
+ be unimportant, in which case use the option ``we=[1, 1, 1, 0, 0, 0]``.
2394
+
2395
+
2396
+
2397
+ .. note::
2398
+
2399
+ - See `Toolbox kinematics wiki page <https://github.com/petercorke/robotics-toolbox-python/wiki/Kinematics>`_
2400
+ - Implements a Levenberg-Marquadt variable-damping solver.
2401
+ - The tolerance is computed on the norm of the error between
2402
+ current and desired tool pose. This norm is computed from
2403
+ distances and angles without any kind of weighting.
2404
+ - The inverse kinematic solution is generally not unique, and
2405
+ depends on the initial guess ``q0``.
2406
+
2407
+ :references:
2408
+ TODO
2409
+
2410
+ :seealso:
2411
+ TODO
2412
+ """
2413
+
2414
+ return self.ets().ik_nr( # type: ignore[attr-defined]
2415
+ Tep, q0, ilimit, slimit, tol, reject_jl, we, use_pinv, pinv_damping
2416
+ )
2417
+
2418
+ def ik_gn(
2419
+ self,
2420
+ Tep: np.ndarray | SE3,
2421
+ q0: np.ndarray | None = None,
2422
+ ilimit: int = 30,
2423
+ slimit: int = 100,
2424
+ tol: float = 1e-6,
2425
+ reject_jl: bool = True,
2426
+ we: np.ndarray | None = None,
2427
+ use_pinv: int = True,
2428
+ pinv_damping: float = 0.0,
2429
+ ) -> tuple[np.ndarray, int, int, int, float]:
2430
+ """
2431
+ Numerical inverse kinematics by Levenberg-Marquadt optimization (Gauss-Newton Method)
2432
+
2433
+ :param Tep: The desired end-effector pose or pose trajectory
2434
+ :param q0: initial joint configuration (default to random valid joint
2435
+ configuration constrained by the joint limits of the robot)
2436
+ :param ilimit: maximum number of iterations per search
2437
+ :param slimit: maximum number of search attempts
2438
+ :param tol: final error tolerance
2439
+ :param reject_jl: constrain the solution to being within the joint limits of
2440
+ the robot (reject solution with invalid joint configurations and perform
2441
+ another search up to the slimit)
2442
+ :param we: a mask vector which weights the end-effector error priority.
2443
+ Corresponds to translation in X, Y and Z and rotation about X, Y and Z
2444
+ respectively
2445
+ :param λ: value of lambda for the damping matrix Wn
2446
+
2447
+ :return: inverse kinematic solution
2448
+ :rtype: tuple (q, success, iterations, searches, residual)
2449
+
2450
+ ``sol = ets.ik_lm_chan(Tep)`` are the joint coordinates (n) corresponding
2451
+ to the robot end-effector pose ``Tep`` which is an ``SE3`` or ``ndarray`` object.
2452
+ This method can be used for robots with any number of degrees of freedom.
2453
+ The return value ``sol`` is a tuple with elements:
2454
+
2455
+ ============== ========== ===============================================
2456
+ Element Type Description
2457
+ ============== ========== ===============================================
2458
+ ``q`` ndarray(n) joint coordinates in units of radians or metres
2459
+ ``success`` int whether a solution was found
2460
+ ``iterations`` int total number of iterations
2461
+ ``searches`` int total number of searches
2462
+ ``residual`` float final value of cost function
2463
+ ============== ========== ===============================================
2464
+
2465
+ If ``success == 0`` the ``q`` values will be valid numbers, but the
2466
+ solution will be in error. The amount of error is indicated by
2467
+ the ``residual``.
2468
+
2469
+ **Joint Limits**:
2470
+
2471
+ ``sol = robot.ikine_LM(T, slimit=100)`` which is the deafualt for this method.
2472
+ The solver will initialise a solution attempt with a random valid q0 and
2473
+ perform a maximum of ilimit steps within this attempt. If a solution is not
2474
+ found, this process is repeated up to slimit times.
2475
+
2476
+ **Global search**:
2477
+
2478
+ ``sol = robot.ikine_LM(T, reject_jl=True)`` is the deafualt for this method.
2479
+ By setting reject_jl to True, the solver will discard any solution which
2480
+ violates the defined joint limits of the robot. The solver will then
2481
+ re-initialise with a new random q0 and repeat the process up to slimit times.
2482
+ Note that finding a solution with valid joint coordinates takes longer than
2483
+ without.
2484
+
2485
+ **Underactuated robots:**
2486
+
2487
+ For the case where the manipulator has fewer than 6 DOF the
2488
+ solution space has more dimensions than can be spanned by the
2489
+ manipulator joint coordinates.
2490
+
2491
+ In this case we specify the ``we`` option where the ``we`` vector
2492
+ (6) specifies the Cartesian DOF (in the wrist coordinate frame) that
2493
+ will be ignored in reaching a solution. The we vector has six
2494
+ elements that correspond to translation in X, Y and Z, and rotation
2495
+ about X, Y and Z respectively. The value can be 0 (for ignore)
2496
+ or above to assign a priority relative to other Cartesian DoF. The number
2497
+ of non-zero elements must equal the number of manipulator DOF.
2498
+
2499
+ For example when using a 3 DOF manipulator tool orientation might
2500
+ be unimportant, in which case use the option ``we=[1, 1, 1, 0, 0, 0]``.
2501
+
2502
+
2503
+
2504
+ .. note::
2505
+
2506
+ - See `Toolbox kinematics wiki page <https://github.com/petercorke/robotics-toolbox-python/wiki/Kinematics>`_
2507
+ - Implements a Levenberg-Marquadt variable-damping solver.
2508
+ - The tolerance is computed on the norm of the error between
2509
+ current and desired tool pose. This norm is computed from
2510
+ distances and angles without any kind of weighting.
2511
+ - The inverse kinematic solution is generally not unique, and
2512
+ depends on the initial guess ``q0``.
2513
+
2514
+ :references:
2515
+ TODO
2516
+
2517
+ :seealso:
2518
+ TODO
2519
+ """
2520
+
2521
+ return self.ets().ik_gn( # type: ignore[attr-defined]
2522
+ Tep, q0, ilimit, slimit, tol, reject_jl, we, use_pinv, pinv_damping
2523
+ )
2524
+
2525
+ def ikine_LM(
2526
+ self,
2527
+ Tep: np.ndarray | SE3,
2528
+ q0: ArrayLike | None = None,
2529
+ ilimit: int = 30,
2530
+ slimit: int = 100,
2531
+ tol: float = 1e-6,
2532
+ joint_limits: bool = False,
2533
+ mask: ArrayLike | None = None,
2534
+ seed: int | None = None,
2535
+ ):
2536
+ return self.ets().ikine_LM(
2537
+ Tep=Tep,
2538
+ q0=q0,
2539
+ ilimit=ilimit,
2540
+ slimit=slimit,
2541
+ tol=tol,
2542
+ joint_limits=joint_limits,
2543
+ mask=mask,
2544
+ seed=seed,
2545
+ )
2546
+
2547
+
2548
+ class SerialLink(DHRobot):
2549
+ def __init__(self, *args, **kwargs):
2550
+ warnings.warn(
2551
+ "SerialLink is deprecated, use DHRobot instead", DeprecationWarning
2552
+ )
2553
+ super().__init__(*args, **kwargs)
2554
+
2555
+
2556
+ def _cross(a, b):
2557
+ return np.r_[
2558
+ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]
2559
+ ]
2560
+
2561
+
2562
+ if __name__ == "__main__": # pragma nocover
2563
+ import roboticstoolbox as rtb
2564
+
2565
+ # import spatialmath.base.symbolic as sym
2566
+
2567
+ # planar = rtb.models.DH.Planar2()
2568
+ # J = puma.jacob0(puma.qn)
2569
+ # print(J)
2570
+ # print(puma.manipulability(puma.qn))
2571
+ # print(puma.manipulability(puma.qn, 'asada'))
2572
+ # tw, T0 = puma.twists(puma.qz)
2573
+ # print(planar)
2574
+
2575
+ puma = rtb.models.DH.Puma560()
2576
+ print(puma)
2577
+ # print(puma.jacob0(puma.qn, analytical="eul"))
2578
+ # puma.base = None
2579
+ # print('base', puma.base)
2580
+ # print('tool', puma.tool)
2581
+
2582
+ # print(puma.ets())
2583
+
2584
+ # puma[2].flip = True
2585
+ # puma[3].offset = 1
2586
+ # puma[4].flip = True
2587
+ # puma[4].offset = -1
2588
+ # print(puma)
2589
+ # print(puma.ets())
2590
+
2591
+ # print(puma.dyntable())