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,2157 @@
1
+ #!/usr/bin/env python
2
+
3
+ """
4
+ @author: Jesse Haviland
5
+ @author: Peter Corke
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ # import sys
11
+ from os.path import splitext
12
+ from copy import deepcopy
13
+ from warnings import warn
14
+ from pathlib import PurePosixPath, Path
15
+ from typing import TextIO, TypeVar, Literal as L, overload, cast
16
+
17
+
18
+ import numpy as np
19
+
20
+ import spatialmath.base as smb
21
+ from spatialmath.base.argcheck import (
22
+ getvector,
23
+ getmatrix,
24
+ verifymatrix,
25
+ )
26
+
27
+ from spatialgeometry import Shape, CollisionShape, Cylinder
28
+
29
+ from spatialmath import (
30
+ SE3,
31
+ SE2,
32
+ SpatialAcceleration,
33
+ SpatialVelocity,
34
+ SpatialInertia,
35
+ SpatialForce,
36
+ )
37
+
38
+ import roboticstoolbox as rtb
39
+ from roboticstoolbox.robot.BaseRobot import BaseRobot
40
+ from roboticstoolbox.robot.RobotKinematics import RobotKinematicsMixin
41
+ from roboticstoolbox.robot.Gripper import Gripper
42
+ from roboticstoolbox.robot.Link import BaseLink, Link, Link2
43
+ from roboticstoolbox.ets.ETS import ETS
44
+ from roboticstoolbox.ets.ETS2 import ETS2
45
+ from roboticstoolbox.tools import URDF
46
+ from roboticstoolbox.tools.types import ArrayLike, NDArray
47
+ from roboticstoolbox.tools.data import rtb_path_to_datafile
48
+
49
+ # A generic type variable representing any subclass of BaseLink
50
+ LinkType = TypeVar("LinkType", bound=BaseLink)
51
+
52
+ # Shared default objects for Robot.__init__'s gravity/keywords parameters,
53
+ # identity-compared in the clone-from-Robot branch to detect "caller didn't
54
+ # override this" (a plain equality/falsy check can't tell a genuine [0, 0,
55
+ # -9.81] override apart from the unset default).
56
+ _GRAVITY_DEFAULT: list[float] = [0, 0, -9.81]
57
+ _KEYWORDS_DEFAULT: list[str] = []
58
+
59
+
60
+ # ==================================================================================== #
61
+ # ================= Robot Class ====================================================== #
62
+ # ==================================================================================== #
63
+
64
+
65
+ class Robot(BaseRobot[Link], RobotKinematicsMixin):
66
+ _color = True
67
+
68
+ def __init__(
69
+ self,
70
+ arg: list[Link] | ETS | Robot,
71
+ gripper_links: Link | list[Link] | None = None,
72
+ name: str = "",
73
+ manufacturer: str = "",
74
+ comment: str = "",
75
+ base: NDArray | SE3 | None = None,
76
+ tool: NDArray | SE3 | None = None,
77
+ gravity: ArrayLike = _GRAVITY_DEFAULT,
78
+ keywords: list[str] | tuple[str, ...] = _KEYWORDS_DEFAULT,
79
+ symbolic: bool = False,
80
+ configs: dict[str, NDArray] | None = None,
81
+ check_jindex: bool = True,
82
+ ):
83
+ # Process links
84
+ if isinstance(arg, Robot):
85
+ # We're passed a Robot, clone it
86
+ # We need to preserve the parent link as we copy
87
+
88
+ # Copy each link within the robot
89
+ links = [deepcopy(link) for link in arg.links]
90
+ gripper_links = []
91
+
92
+ for gripper in arg.grippers:
93
+ glinks = []
94
+ for link in gripper.links:
95
+ glinks.append(deepcopy(link))
96
+
97
+ gripper_links.append(glinks[0])
98
+ links = links + glinks
99
+
100
+ # Sever parent connection, but save the string
101
+ # The constructor will piece this together for us
102
+ for link in links:
103
+ link._children = []
104
+ if link.parent is not None:
105
+ link._parent_name = link.parent.name
106
+ link._parent = None
107
+
108
+ # Clone the source robot's own attributes for anything the
109
+ # caller didn't explicitly override (name="" / base=None /
110
+ # etc. are the "not given" markers matching this signature's
111
+ # own defaults above).
112
+ super().__init__(
113
+ links,
114
+ gripper_links=gripper_links,
115
+ name=name or arg.name,
116
+ manufacturer=manufacturer or arg.manufacturer,
117
+ comment=comment or arg.comment,
118
+ base=base if base is not None else arg.base,
119
+ tool=tool if tool is not None else arg.tool,
120
+ gravity=gravity if gravity is not _GRAVITY_DEFAULT else arg.gravity,
121
+ keywords=keywords if keywords is not _KEYWORDS_DEFAULT else arg.keywords,
122
+ symbolic=symbolic,
123
+ configs=configs if configs is not None else arg.configs,
124
+ check_jindex=check_jindex,
125
+ )
126
+
127
+ for i, gripper in enumerate(self.grippers):
128
+ gripper.tool = arg.grippers[i].tool.copy()
129
+
130
+ self._urdf_filepath = arg.urdf_filepath
131
+ else:
132
+ if isinstance(arg, ETS):
133
+ # We're passed an ETS string
134
+ links = []
135
+ # chop it up into segments, a link frame after every joint
136
+ # split()'s default "last" method folds any base content into
137
+ # the first segment, so `base` is always empty and dropped;
138
+ # `gripper` holds trailing constant content, if any, and
139
+ # becomes one extra static (non-joint) link.
140
+ _, *segs, gripper = arg.split()
141
+ if gripper:
142
+ segs.append(gripper)
143
+ parent = None
144
+ for j, ets_j in enumerate(segs):
145
+ elink = Link(ETS(ets_j), parent=parent, name=f"link{j:d}")
146
+ if (
147
+ elink.qlim is None
148
+ and elink.v is not None
149
+ and elink.v.qlim is not None # type: ignore[union-attr]
150
+ ):
151
+ elink.qlim = elink.v.qlim # type: ignore[union-attr] # pragma nocover
152
+ parent = elink
153
+ links.append(elink)
154
+
155
+ elif smb.islistof(arg, Link):
156
+ links = arg
157
+
158
+ else:
159
+ raise TypeError("arg was invalid, must be List[Link], ETS, or Robot")
160
+
161
+ # Initialise Base Robot object
162
+ super().__init__(
163
+ links=links,
164
+ gripper_links=gripper_links,
165
+ name=name,
166
+ manufacturer=manufacturer,
167
+ comment=comment,
168
+ base=base,
169
+ tool=tool,
170
+ gravity=gravity,
171
+ keywords=keywords,
172
+ symbolic=symbolic,
173
+ configs=configs,
174
+ check_jindex=check_jindex,
175
+ )
176
+
177
+ # --------------------------------------------------------------------- #
178
+ # --------- Swift Methods --------------------------------------------- #
179
+ # --------------------------------------------------------------------- #
180
+
181
+ def _to_dict(self, robot_alpha=1.0, collision_alpha=0.0):
182
+ ob = []
183
+
184
+ for link in self.links:
185
+ if robot_alpha > 0:
186
+ for gi in link.geometry:
187
+ gi.opacity = robot_alpha
188
+ ob.append(gi.to_dict())
189
+ if collision_alpha > 0:
190
+ for gi in link.collision:
191
+ gi.opacity = collision_alpha
192
+ ob.append(gi.to_dict())
193
+
194
+ # Do the grippers now
195
+ for gripper in self.grippers:
196
+ for link in gripper.links:
197
+ if robot_alpha > 0:
198
+ for gi in link.geometry:
199
+ gi.opacity = robot_alpha
200
+ ob.append(gi.to_dict())
201
+ if collision_alpha > 0:
202
+ for gi in link.collision:
203
+ gi.opacity = collision_alpha
204
+ ob.append(gi.to_dict())
205
+
206
+ # for o in ob:
207
+ # print(o)
208
+
209
+ return ob
210
+
211
+ def _fk_dict(self, robot_alpha=1.0, collision_alpha=0.0):
212
+ ob = []
213
+
214
+ # Do the robot
215
+ for link in self.links:
216
+ if robot_alpha > 0:
217
+ for gi in link.geometry:
218
+ ob.append(gi.fk_dict())
219
+ if collision_alpha > 0:
220
+ for gi in link.collision:
221
+ ob.append(gi.fk_dict())
222
+
223
+ # Do the grippers now
224
+ for gripper in self.grippers:
225
+ for link in gripper.links:
226
+ if robot_alpha > 0:
227
+ for gi in link.geometry:
228
+ ob.append(gi.fk_dict())
229
+ if collision_alpha > 0:
230
+ for gi in link.collision:
231
+ ob.append(gi.fk_dict())
232
+
233
+ return ob
234
+
235
+ # --------------------------------------------------------------------- #
236
+ # --------- URDF Methods ---------------------------------------------- #
237
+ # --------------------------------------------------------------------- #
238
+
239
+ # @staticmethod
240
+ # def URDF_read(
241
+ # file_path, tld=None, xacro_tld=None
242
+ # ) -> Tuple[List[Link], str, str, Union[Path, PurePosixPath]]:
243
+ # """
244
+ # Read a URDF file as Links
245
+
246
+ # File should be specified relative to ``RTBDATA/URDF/xacro``
247
+
248
+ # Parameters
249
+ # ----------
250
+ # file_path
251
+ # File path relative to the xacro folder
252
+ # tld
253
+ # A custom top-level directory which holds the xacro data,
254
+ # defaults to None
255
+ # xacro_tld
256
+ # A custom top-level within the xacro data,
257
+ # defaults to None
258
+
259
+ # Returns
260
+ # -------
261
+ # links
262
+ # a list of links
263
+ # name
264
+ # the name of the robot
265
+ # urdf
266
+ # a string representing the URDF
267
+ # file_path
268
+ # a path to the original file
269
+
270
+ # Notes
271
+ # -----
272
+ # If ``tld`` is not supplied, filepath pointing to xacro data should
273
+ # be directly under ``RTBDATA/URDF/xacro`` OR under ``./xacro`` relative
274
+ # to the model file calling this method. If ``tld`` is supplied, then
275
+ # ```file_path``` needs to be relative to ``tld``
276
+
277
+ # """
278
+
279
+ # # Get the path to the class that defines the robot
280
+ # if tld is None:
281
+ # base_path = rtb_path_to_datafile("xacro")
282
+ # else:
283
+ # base_path = PurePosixPath(tld)
284
+
285
+ # # Add on relative path to get to the URDF or xacro file
286
+ # # base_path = PurePath(classpath).parent.parent / 'URDF' / 'xacro'
287
+ # file_path = base_path / PurePosixPath(file_path)
288
+ # _, ext = splitext(file_path)
289
+
290
+ # if ext == ".xacro":
291
+ # # it's a xacro file, preprocess it
292
+ # if xacro_tld is not None:
293
+ # xacro_tld = base_path / PurePosixPath(xacro_tld)
294
+ # urdf_string = xacro.main(file_path, xacro_tld)
295
+ # try:
296
+ # urdf = URDF.loadstr(urdf_string, file_path, base_path)
297
+ # except BaseException as e: # pragma nocover
298
+ # print("error parsing URDF file", file_path)
299
+ # raise e
300
+ # else: # pragma nocover
301
+ # urdf_string = open(file_path).read()
302
+ # urdf = URDF.loadstr(urdf_string, file_path, base_path)
303
+
304
+ # if not isinstance(urdf_string, str): # pragma nocover
305
+ # raise ValueError("Parsing failed, did not get valid URDF string back")
306
+
307
+ # return urdf.elinks, urdf.name, urdf_string, file_path
308
+
309
+ # def urdf_load(self, file: str|Path|TextIO, manufacturer: str|None = None, model: str|None = None):
310
+ # from roboticstoolbox.tools.urdf import URDF
311
+ # from xacrodoc import XacroDoc
312
+ # from xacrodoc import packages
313
+
314
+ # # Explicitly map package names to their paths (no ROS / package.xml needed)
315
+ # import rtbdata
316
+ # xacro_root = Path(rtbdata.__file__).parent / "xacro"
317
+ # packages.update_package_cache({
318
+ # d.name: str(d) for d in xacro_root.iterdir() if d.is_dir()
319
+ # })
320
+
321
+
322
+ # # Compile xacro → URDF string, resolve all mesh file path
323
+
324
+ # if isinstance(file, (str, Path)):
325
+ # doc = XacroDoc.from_file(xacro_root / file)
326
+ # else:
327
+ # doc = XacroDoc.from_string(file.read())
328
+
329
+ # urdf_str = doc.to_urdf_string()
330
+
331
+ # urdf = URDF.loadstr(urdf_str, None)
332
+
333
+ # # links, name, urdf_string, urdf_filepath = self.URDF_read(
334
+ # # "trossen_descriptions/urdf/vx300.urdf.xacro"
335
+ # # )
336
+
337
+ # super().__init__(
338
+ # urdf.elinks,
339
+ # name=urdf.name,
340
+ # manufacturer=manufacturer,
341
+ # # urdf_string=urdf_string,
342
+ # # urdf_filepath=urdf_filepath,
343
+ # )
344
+
345
+ @classmethod
346
+ def URDF(cls, file, gripper=None, manufacturer=None):
347
+ """Deprecated. Use :class:`~roboticstoolbox.models.URDF.URDFRobot` as a
348
+ base class, or call ``URDF_read()`` from
349
+ ``roboticstoolbox.models.URDF.URDFRobot`` and construct ``Robot``
350
+ directly."""
351
+ import warnings
352
+
353
+ warnings.warn(
354
+ "Robot.URDF() is deprecated. "
355
+ "Subclass roboticstoolbox.models.URDF.URDFRobot, or call "
356
+ "URDF_read() from that module and construct Robot directly.",
357
+ DeprecationWarning,
358
+ stacklevel=2,
359
+ )
360
+ from roboticstoolbox.models.URDF.URDFRobot import URDF_file
361
+
362
+ elinks, name, _ = URDF_file(file)
363
+ gripper_link = None
364
+ if isinstance(gripper, int):
365
+ gripper_link = elinks[gripper]
366
+ elif isinstance(gripper, str):
367
+ for link in elinks:
368
+ if link.name == gripper:
369
+ gripper_link = link
370
+ break
371
+ else:
372
+ raise ValueError(f"no link named '{gripper}'")
373
+ return cls(
374
+ elinks,
375
+ name=name,
376
+ manufacturer=manufacturer or "",
377
+ gripper_links=gripper_link,
378
+ )
379
+
380
+ # # --------------------------------------------------------------------- #
381
+ # # --------- Utility Methods ------------------------------------------- #
382
+ # # --------------------------------------------------------------------- #
383
+
384
+ # def showgraph(self, display_graph: bool = True, **kwargs) -> Union[None, str]:
385
+ # """
386
+ # Display a link transform graph in browser
387
+
388
+ # ``robot.showgraph()`` displays a graph of the robot's link frames
389
+ # and the ETS between them. It uses GraphViz dot.
390
+
391
+ # The nodes are:
392
+ # - Base is shown as a grey square. This is the world frame origin,
393
+ # but can be changed using the ``base`` attribute of the robot.
394
+ # - Link frames are indicated by circles
395
+ # - ETS transforms are indicated by rounded boxes
396
+
397
+ # The edges are:
398
+ # - an arrow if `jtype` is False or the joint is fixed
399
+ # - an arrow with a round head if `jtype` is True and the joint is
400
+ # revolute
401
+ # - an arrow with a box head if `jtype` is True and the joint is
402
+ # prismatic
403
+
404
+ # Edge labels or nodes in blue have a fixed transformation to the
405
+ # preceding link.
406
+
407
+ # Parameters
408
+ # ----------
409
+ # display_graph
410
+ # Open the graph in a browser if True. Otherwise will return the
411
+ # file path
412
+ # etsbox
413
+ # Put the link ETS in a box, otherwise an edge label
414
+ # jtype
415
+ # Arrowhead to node indicates revolute or prismatic type
416
+ # static
417
+ # Show static joints in blue and bold
418
+
419
+ # Examples
420
+ # --------
421
+ # >>> import roboticstoolbox as rtb
422
+ # >>> panda = rtb.models.URDF.Panda()
423
+ # >>> panda.showgraph()
424
+
425
+ # .. image:: ../figs/panda-graph.svg
426
+ # :width: 600
427
+
428
+ # See Also
429
+ # --------
430
+ # :func:`dotfile`
431
+
432
+ # """
433
+
434
+ # # Lazy import
435
+ # import tempfile
436
+ # import subprocess
437
+ # import webbrowser
438
+
439
+ # # create the temporary dotfile
440
+ # dotfile = tempfile.TemporaryFile(mode="w")
441
+ # self.dotfile(dotfile, **kwargs)
442
+
443
+ # # rewind the dot file, create PDF file in the filesystem, run dot
444
+ # dotfile.seek(0)
445
+ # pdffile = tempfile.NamedTemporaryFile(suffix=".pdf", delete=False)
446
+ # subprocess.run("dot -Tpdf", shell=True, stdin=dotfile, stdout=pdffile)
447
+
448
+ # # open the PDF file in browser (hopefully portable), then cleanup
449
+ # if display_graph: # pragma nocover
450
+ # webbrowser.open(f"file://{pdffile.name}")
451
+ # else:
452
+ # return pdffile.name
453
+
454
+ # def dotfile(
455
+ # self,
456
+ # filename: Union[str, IO[str]],
457
+ # etsbox: bool = False,
458
+ # ets: L["full", "brief"] = "full",
459
+ # jtype: bool = False,
460
+ # static: bool = True,
461
+ # ):
462
+ # """
463
+ # Write a link transform graph as a GraphViz dot file
464
+
465
+ # The file can be processed using dot:
466
+ # % dot -Tpng -o out.png dotfile.dot
467
+
468
+ # The nodes are:
469
+ # - Base is shown as a grey square. This is the world frame origin,
470
+ # but can be changed using the ``base`` attribute of the robot.
471
+ # - Link frames are indicated by circles
472
+ # - ETS transforms are indicated by rounded boxes
473
+
474
+ # The edges are:
475
+ # - an arrow if `jtype` is False or the joint is fixed
476
+ # - an arrow with a round head if `jtype` is True and the joint is
477
+ # revolute
478
+ # - an arrow with a box head if `jtype` is True and the joint is
479
+ # prismatic
480
+
481
+ # Edge labels or nodes in blue have a fixed transformation to the
482
+ # preceding link.
483
+
484
+ # Note
485
+ # ----
486
+ # If ``filename`` is a file object then the file will *not*
487
+ # be closed after the GraphViz model is written.
488
+
489
+ # Parameters
490
+ # ----------
491
+ # file
492
+ # Name of file to write to
493
+ # etsbox
494
+ # Put the link ETS in a box, otherwise an edge label
495
+ # ets
496
+ # Display the full ets with "full" or a brief version with "brief"
497
+ # jtype
498
+ # Arrowhead to node indicates revolute or prismatic type
499
+ # static
500
+ # Show static joints in blue and bold
501
+
502
+ # See Also
503
+ # --------
504
+ # :func:`showgraph`
505
+
506
+ # """
507
+
508
+ # if isinstance(filename, str):
509
+ # file = open(filename, "w")
510
+ # else:
511
+ # file = filename
512
+
513
+ # header = r"""digraph G {
514
+ # graph [rankdir=LR];
515
+ # """
516
+
517
+ # def draw_edge(link, etsbox, jtype, static):
518
+ # # draw the edge
519
+ # if jtype:
520
+ # if link.isprismatic:
521
+ # edge_options = 'arrowhead="box", arrowtail="inv", dir="both"'
522
+ # elif link.isrevolute:
523
+ # edge_options = 'arrowhead="dot", arrowtail="inv", dir="both"'
524
+ # else:
525
+ # edge_options = 'arrowhead="normal"'
526
+ # else:
527
+ # edge_options = 'arrowhead="normal"'
528
+
529
+ # if link.parent is None:
530
+ # parent = "BASE"
531
+ # else:
532
+ # parent = link.parent.name
533
+
534
+ # if etsbox:
535
+ # # put the ets fragment in a box
536
+ # if not link.isjoint and static:
537
+ # node_options = ', fontcolor="blue"'
538
+ # else:
539
+ # node_options = ""
540
+
541
+ # try:
542
+ # file.write(
543
+ # ' {}_ets [shape=box, style=rounded, label="{}"{}];\n'.format(
544
+ # link.name,
545
+ # link.ets.__str__(q=f"q{link.jindex}"),
546
+ # node_options,
547
+ # )
548
+ # )
549
+ # except UnicodeEncodeError: # pragma nocover
550
+ # file.write(
551
+ # ' {}_ets [shape=box, style=rounded, label="{}"{}];\n'.format(
552
+ # link.name,
553
+ # link.ets.__str__(q=f"q{link.jindex}")
554
+ # .encode("ascii", "ignore")
555
+ # .decode("ascii"),
556
+ # node_options,
557
+ # )
558
+ # )
559
+
560
+ # file.write(" {} -> {}_ets;\n".format(parent, link.name))
561
+ # file.write(
562
+ # " {}_ets -> {} [{}];\n".format(link.name, link.name, edge_options)
563
+ # )
564
+ # else:
565
+ # # put the ets fragment as an edge label
566
+ # if not link.isjoint and static:
567
+ # edge_options += 'fontcolor="blue"'
568
+ # if ets == "full":
569
+ # estr = link.ets.__str__(q=f"q{link.jindex}")
570
+ # elif ets == "brief":
571
+ # if link.jindex is None:
572
+ # estr = ""
573
+ # else:
574
+ # estr = f"...q{link.jindex}"
575
+ # else:
576
+ # return
577
+ # try:
578
+ # file.write(
579
+ # ' {} -> {} [label="{}", {}];\n'.format(
580
+ # parent,
581
+ # link.name,
582
+ # estr,
583
+ # edge_options,
584
+ # )
585
+ # )
586
+ # except UnicodeEncodeError: # pragma nocover
587
+ # file.write(
588
+ # ' {} -> {} [label="{}", {}];\n'.format(
589
+ # parent,
590
+ # link.name,
591
+ # estr.encode("ascii", "ignore").decode("ascii"),
592
+ # edge_options,
593
+ # )
594
+ # )
595
+
596
+ # file.write(header)
597
+
598
+ # # add the base link
599
+ # file.write(" BASE [shape=square, style=filled, fillcolor=gray]\n")
600
+
601
+ # # add the links
602
+ # for link in self:
603
+ # # draw the link frame node (circle) or ee node (doublecircle)
604
+ # if link in self.ee_links:
605
+ # # end-effector
606
+ # node_options = 'shape="doublecircle", color="blue", fontcolor="blue"'
607
+ # else:
608
+ # node_options = 'shape="circle"'
609
+
610
+ # file.write(" {} [{}];\n".format(link.name, node_options))
611
+
612
+ # draw_edge(link, etsbox, jtype, static)
613
+
614
+ # for gripper in self.grippers:
615
+ # for link in gripper.links:
616
+ # file.write(" {} [shape=cds];\n".format(link.name))
617
+ # draw_edge(link, etsbox, jtype, static)
618
+
619
+ # file.write("}\n")
620
+
621
+ # if isinstance(filename, str):
622
+ # file.close()
623
+
624
+ # --------------------------------------------------------------------- #
625
+ # --------- Kinematic Methods ----------------------------------------- #
626
+ # --------------------------------------------------------------------- #
627
+
628
+ @property
629
+ def reach(self) -> float:
630
+ r"""
631
+ Reach of the robot
632
+
633
+ :returns: Maximum reach of the robot
634
+ :rtype: float
635
+
636
+ A conservative estimate of the reach of the robot. It is computed as
637
+ the sum of the translational ETs that define the link transform.
638
+
639
+ Computed on the first access. If kinematic parameters
640
+ subsequently change this will not be reflected.
641
+
642
+ .. rubric:: Notes
643
+
644
+ - Probably an overestimate of reach
645
+ - Used by numerical inverse kinematics to scale translational
646
+ error.
647
+ - For a prismatic joint, uses ``qlim`` if it is set
648
+
649
+ """
650
+
651
+ # TODO
652
+ # This should be a start, end method and compute the reach based on the
653
+ # given ets. Then use an lru_cache to speed up return
654
+
655
+ if self._reach is None:
656
+ d_all = []
657
+ for link in self.ee_links:
658
+ d = 0
659
+ while True:
660
+ for et in link.ets:
661
+ if et.istranslation:
662
+ if et.isjoint:
663
+ # the length of a prismatic joint depends on the
664
+ # joint limits. They might be set in the ET
665
+ # or in the Link depending on how the robot
666
+ # was constructed
667
+ if link.qlim is not None:
668
+ d += max(link.qlim)
669
+ elif et.qlim is not None: # pragma nocover
670
+ d += max(et.qlim)
671
+ else:
672
+ d += abs(et.param)
673
+ link = link.parent
674
+ if link is None or isinstance(link, str):
675
+ d_all.append(d)
676
+ break
677
+
678
+ self._reach = max(d_all)
679
+ return self._reach
680
+
681
+ def fkine_all(self, q: ArrayLike) -> SE3:
682
+ """
683
+ Compute the pose of every link frame
684
+
685
+ :param q: The joint configuration
686
+ :returns: Pose of all links
687
+
688
+ ``T = robot.fkine_all(q)`` is an SE3 instance with ``robot.nlinks +
689
+ 1`` values:
690
+
691
+ - ``T[0]`` is the base transform
692
+ - ``T[i]`` is the pose of link whose ``number`` is ``i``
693
+
694
+ .. rubric:: References
695
+
696
+ - J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
697
+ Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
698
+
699
+ """
700
+
701
+ q = getvector(q)
702
+
703
+ Tbase = SE3(self.base) # add base, also sets the type
704
+
705
+ linkframes = Tbase.__class__.Alloc(self.nlinks + 1)
706
+ linkframes[0] = Tbase
707
+
708
+ def recurse(Tall, Tparent, q, link):
709
+ # if joint??
710
+ T = Tparent
711
+ while True:
712
+ T *= SE3(link.A(q[link.jindex]))
713
+
714
+ Tall[link.number] = T
715
+
716
+ if link.nchildren == 0:
717
+ # no children
718
+ return
719
+ elif link.nchildren == 1:
720
+ # one child
721
+ if link in self.ee_links: # pragma nocover
722
+ # this link is an end-effector, go no further
723
+ return
724
+ link = link.children[0]
725
+ continue
726
+ else:
727
+ # multiple children
728
+ for child in link.children:
729
+ recurse(Tall, T, q, child)
730
+ return
731
+
732
+ recurse(linkframes, Tbase, q, self.links[0])
733
+
734
+ return linkframes
735
+
736
+ def fkine_geometry(
737
+ self, q: ArrayLike, robot_alpha: float = 1.0, collision_alpha: float = 0.0
738
+ ) -> list[SE3]:
739
+ """
740
+ Compute the world-frame pose of every rendered geometry part
741
+
742
+ :param q: the joint configuration of the main kinematic chain
743
+ :param robot_alpha: include visual geometry if > 0, matches
744
+ ``_to_dict``/``_fk_dict``'s own gating
745
+ :param collision_alpha: include collision geometry if > 0
746
+ :returns: one pose per geometry part, in the same order as
747
+ ``_to_dict()``/``_fk_dict()``
748
+ :rtype: list of SE3
749
+
750
+ Pure with respect to ``q`` -- computed directly via
751
+ :meth:`fkine_all` and each geometry's fixed local offset
752
+ (``geom._T``, spatialgeometry's ``SceneNode``), not via
753
+ ``SceneNode._propogate_scene_tree()``'s cached/mutated world
754
+ transform. Intended for consumers (e.g. a Swift animation loop)
755
+ that want link/geometry poses without needing a robot to carry
756
+ live scene-graph state.
757
+
758
+ Gripper geometry is included, using each gripper's own current
759
+ ``.q`` (grippers keep their own separate joint state -- not a
760
+ parameter of this method, and not yet part of the pure-`q`
761
+ computation this method provides for the main chain).
762
+ """
763
+ linkframes = self.fkine_all(q)
764
+
765
+ poses: list[SE3] = []
766
+
767
+ for link in self.links:
768
+ if robot_alpha > 0:
769
+ for gi in link.geometry:
770
+ poses.append(linkframes[link.number] * SE3(gi._T, check=False))
771
+ if collision_alpha > 0:
772
+ for gi in link.collision:
773
+ poses.append(linkframes[link.number] * SE3(gi._T, check=False))
774
+
775
+ for gripper in self.grippers:
776
+ attach_link = next(
777
+ l for l in self.links if l.name == gripper.links[0].parent_name
778
+ )
779
+ base_T = linkframes[attach_link.number]
780
+
781
+ gripper_frames: dict[str, SE3] = {}
782
+
783
+ def recurse(Tparent, link):
784
+ T = Tparent
785
+ while True:
786
+ T = T * SE3(link.A(gripper.q[link.jindex]), check=False)
787
+ gripper_frames[link.name] = T
788
+
789
+ if link.nchildren == 0:
790
+ return
791
+ elif link.nchildren == 1:
792
+ link = link.children[0]
793
+ continue
794
+ else:
795
+ for child in link.children:
796
+ recurse(T, child)
797
+ return
798
+
799
+ recurse(base_T, gripper.links[0])
800
+
801
+ for link in gripper.links:
802
+ T_link = gripper_frames[link.name]
803
+ if robot_alpha > 0:
804
+ for gi in link.geometry:
805
+ poses.append(T_link * SE3(gi._T, check=False))
806
+ if collision_alpha > 0:
807
+ for gi in link.collision:
808
+ poses.append(T_link * SE3(gi._T, check=False))
809
+
810
+ return poses
811
+
812
+ @overload
813
+ def manipulability(
814
+ self,
815
+ q: ArrayLike = ...,
816
+ J: None = None,
817
+ end: str | Link | Gripper | None = None,
818
+ start: str | Link | Gripper | None = None,
819
+ method: L[
820
+ "yoshikawa", "asada", "minsingular", "invcondition"
821
+ ] = "yoshikawa",
822
+ axes: L["all", "trans", "rot"] | list[bool] = "all",
823
+ **kwargs,
824
+ ) -> float | NDArray: # pragma nocover
825
+ ...
826
+
827
+ @overload
828
+ def manipulability(
829
+ self,
830
+ q: None = None,
831
+ J: NDArray = ...,
832
+ end: str | Link | Gripper | None = None,
833
+ start: str | Link | Gripper | None = None,
834
+ method: L[
835
+ "yoshikawa", "asada", "minsingular", "invcondition"
836
+ ] = "yoshikawa",
837
+ axes: L["all", "trans", "rot"] | list[bool] = "all",
838
+ **kwargs,
839
+ ) -> float | NDArray: # pragma nocover
840
+ ...
841
+
842
+ def manipulability(
843
+ self,
844
+ q=None,
845
+ J=None,
846
+ end: str | Link | Gripper | None = None,
847
+ start: str | Link | Gripper | None = None,
848
+ method: L[
849
+ "yoshikawa", "asada", "minsingular", "invcondition"
850
+ ] = "yoshikawa",
851
+ axes: L["all", "trans", "rot"] | list[bool] = "all",
852
+ **kwargs,
853
+ ):
854
+ """
855
+ Manipulability measure
856
+
857
+ :param q: Joint coordinates, one of J or q required
858
+ :param J: Jacobian in base frame if already computed, one of J or q required
859
+ :param method: method to use, "yoshikawa" (default), "invcondition",
860
+ "minsingular" or "asada"
861
+ :param axes: Task space axes to consider: "all" [default], "trans", or "rot"
862
+ :returns: manipulability index
863
+
864
+ ``manipulability(q)`` is the scalar manipulability index
865
+ for the robot at the joint configuration ``q``. It indicates
866
+ dexterity, that is, how well conditioned the robot is for motion
867
+ with respect to the 6 degrees of Cartesian motion. The values is
868
+ zero if the robot is at a singularity.
869
+
870
+ Various measures are supported:
871
+
872
+ - ``"yoshikawa"`` -- volume of the velocity ellipsoid, *distance*
873
+ from singularity [Yoshikawa85]_
874
+ - ``"invcondition"`` -- inverse condition number of Jacobian,
875
+ isotropy of the velocity ellipsoid [Klein87]_
876
+ - ``"minsingular"`` -- minimum singular value of the Jacobian,
877
+ *distance* from singularity [Klein87]_
878
+ - ``"asada"`` -- isotropy of the task-space acceleration ellipsoid
879
+ which is a function of the Cartesian inertia matrix which depends
880
+ on the inertial parameters [Asada83]_
881
+
882
+ **Trajectory operation**:
883
+
884
+ If ``q`` is a matrix (m,n) then the result (m,) is a vector of
885
+ manipulability indices for each joint configuration specified by a row
886
+ of ``q``.
887
+
888
+ .. rubric:: Notes
889
+
890
+ - Invokes the ``jacob0`` method of the robot if ``J`` is not passed
891
+ - The "all" option includes rotational and translational
892
+ dexterity, but this involves adding different units. It can be
893
+ more useful to look at the translational and rotational
894
+ manipulability separately.
895
+ - Examples in the RVC book (1st edition) can be replicated by
896
+ using the "all" option
897
+ - Asada's measure requires inertial a robot model with inertial
898
+ parameters.
899
+
900
+ .. rubric:: References
901
+
902
+ .. [Yoshikawa85] Manipulability of Robotic Mechanisms. Yoshikawa T.,
903
+ The International Journal of Robotics Research.
904
+ 1985;4(2):3-9. doi:10.1177/027836498500400201
905
+ .. [Asada83] A geometrical representation of manipulator dynamics and
906
+ its application to arm design, H. Asada,
907
+ Journal of Dynamic Systems, Measurement, and Control,
908
+ vol. 105, p. 131, 1983.
909
+ .. [Klein87] Dexterity Measures for the Design and Control of
910
+ Kinematically Redundant Manipulators. Klein CA, Blaho BE.
911
+ The International Journal of Robotics Research.
912
+ 1987;6(2):72-83. doi:10.1177/027836498700600206
913
+
914
+ - Robotics, Vision & Control, Chap 8, P. Corke, Springer 2011.
915
+
916
+ .. versionchanged:: 1.0.3
917
+ Removed 'both' option for axes, added a custom list option.
918
+
919
+ """
920
+
921
+ ets = self.ets(end, start)
922
+
923
+ axes_list: list[bool] = []
924
+
925
+ if isinstance(axes, list):
926
+ axes_list = axes
927
+ elif axes == "all":
928
+ axes_list = [True, True, True, True, True, True]
929
+ elif axes.startswith("trans"):
930
+ axes_list = [True, True, True, False, False, False]
931
+ elif axes.startswith("rot"):
932
+ axes_list = [False, False, False, True, True, True]
933
+ elif axes == "both":
934
+ return (
935
+ self.manipulability(
936
+ q=q, J=J, end=end, start=start, method=method, axes="trans"
937
+ ),
938
+ self.manipulability(
939
+ q=q, J=J, end=end, start=start, method=method, axes="rot"
940
+ ),
941
+ )
942
+ else:
943
+ raise ValueError("axes must be all, trans, rot or both")
944
+
945
+ def yoshikawa(robot, J, q, axes_list):
946
+ J = J[axes_list, :]
947
+ if J.shape[0] == J.shape[1]:
948
+ # simplified case for square matrix
949
+ return abs(np.linalg.det(J))
950
+ else:
951
+ m2 = np.linalg.det(J @ J.T)
952
+ return np.sqrt(abs(m2))
953
+
954
+ def condition(robot, J, q, axes_list):
955
+ J = J[axes_list, :]
956
+
957
+ # return 1/cond(J)
958
+ return 1 / np.linalg.cond(J)
959
+
960
+ def minsingular(robot, J, q, axes_list):
961
+ J = J[axes_list, :]
962
+ s = np.linalg.svd(J, compute_uv=False)
963
+
964
+ # return last/smallest singular value of J
965
+ return s[-1]
966
+
967
+ def asada(robot, J, q, axes_list):
968
+ # dof = np.sum(axes_list)
969
+ if np.linalg.matrix_rank(J) < 6:
970
+ return 0
971
+ Ji = np.linalg.pinv(J)
972
+ Mx = Ji.T @ robot.inertia(q) @ Ji
973
+ d = np.where(axes_list)[0]
974
+ Mx = Mx[d]
975
+ Mx = Mx[:, d.tolist()]
976
+ e, _ = np.linalg.eig(Mx)
977
+ return np.min(e) / np.max(e)
978
+
979
+ # choose the handler function
980
+ if method.lower().startswith("yoshi"):
981
+ mfunc = yoshikawa
982
+ elif method.lower().startswith("invc"):
983
+ mfunc = condition
984
+ elif method.lower().startswith("mins"):
985
+ mfunc = minsingular
986
+ elif method.lower().startswith("asa"):
987
+ mfunc = asada
988
+ else:
989
+ raise ValueError("Invalid method chosen")
990
+
991
+ # Calculate manipulability based on supplied Jacobian
992
+ if J is not None:
993
+ w = [mfunc(self, J, q, axes_list)]
994
+
995
+ # Otherwise use the q vector/matrix
996
+ else:
997
+ if q is None:
998
+ raise ValueError("Either J or q must be supplied")
999
+
1000
+ q = getmatrix(q, (None, self.n))
1001
+ q = np.array(getmatrix(q, (None, self.n)))
1002
+ w = np.zeros(q.shape[0])
1003
+
1004
+ for k, qk in enumerate(q):
1005
+ Jk = ets.jacob0(qk)
1006
+ w[k] = mfunc(self, Jk, qk, axes_list)
1007
+
1008
+ if len(w) == 1:
1009
+ return w[0]
1010
+ else:
1011
+ return w
1012
+
1013
+ def jtraj(
1014
+ self,
1015
+ T1: NDArray | SE3,
1016
+ T2: NDArray | SE3,
1017
+ t: NDArray | int,
1018
+ **kwargs,
1019
+ ):
1020
+ """
1021
+ Joint-space trajectory between SE(3) poses
1022
+
1023
+ :param T1: initial end-effector pose
1024
+ :param T2: final end-effector pose
1025
+ :param t: time vector or number of steps
1026
+ :param kwargs: arguments passed to the IK solver
1027
+ :returns: trajectory
1028
+
1029
+ The initial and final poses are mapped to joint space using inverse
1030
+ kinematics:
1031
+
1032
+ - if the object has an analytic solution ``ikine_a`` that will be used,
1033
+ - otherwise the general numerical algorithm ``ikine_lm`` will be used.
1034
+
1035
+ ``traj = obot.jtraj(T1, T2, t)`` is a trajectory object whose
1036
+ attribute ``traj.q`` is a row-wise joint-space trajectory.
1037
+
1038
+ """
1039
+
1040
+ if hasattr(self, "ikine_a"):
1041
+ ik = self.ikine_a # type: ignore
1042
+ else:
1043
+ ik = self.ikine_LM
1044
+
1045
+ q1 = ik(T1, **kwargs)
1046
+ q2 = ik(T2, **kwargs)
1047
+
1048
+ return rtb.jtraj(q1.q, q2.q, t)
1049
+
1050
+ @overload
1051
+ def jacob0_dot(
1052
+ self,
1053
+ q: ArrayLike,
1054
+ qd: ArrayLike,
1055
+ J0: None = None,
1056
+ representation: L["rpy/xyz", "rpy/zyx", "eul", "exp"] | None = None,
1057
+ ) -> NDArray: # pragma no cover
1058
+ ...
1059
+
1060
+ @overload
1061
+ def jacob0_dot(
1062
+ self,
1063
+ q: None,
1064
+ qd: ArrayLike,
1065
+ J0: NDArray = ...,
1066
+ representation: L["rpy/xyz", "rpy/zyx", "eul", "exp"] | None = None,
1067
+ ) -> NDArray: # pragma no cover
1068
+ ...
1069
+
1070
+ def jacob0_dot(
1071
+ self,
1072
+ q,
1073
+ qd: ArrayLike,
1074
+ J0=None,
1075
+ representation: L["rpy/xyz", "rpy/zyx", "eul", "exp"] | None = None,
1076
+ ):
1077
+ r"""
1078
+ Derivative of Jacobian
1079
+
1080
+ :param q: The joint configuration of the robot
1081
+ :param qd: The joint velocity of the robot
1082
+ :param J0: Jacobian in {0} frame
1083
+ :param representation: angular representation
1084
+ :returns: The derivative of the manipulator Jacobian
1085
+
1086
+ ``robot.jacob_dot(q, qd)`` computes the rate of change of the
1087
+ Jacobian elements
1088
+
1089
+ .. math::
1090
+
1091
+ \dmat{J} = \frac{d \mat{J}}{d \vec{q}} \frac{d \vec{q}}{dt}
1092
+
1093
+ where the first term is the rank-3 Hessian.
1094
+
1095
+ If ``J0`` is already calculated for the joint
1096
+ coordinates ``q`` it can be passed in to to save computation time.
1097
+
1098
+ It is computed as the mode-3 product of the Hessian tensor and the
1099
+ velocity vector.
1100
+
1101
+ The derivative of an analytical Jacobian can be obtained by setting
1102
+ ``representation`` as
1103
+
1104
+ .. list-table::
1105
+ :header-rows: 1
1106
+
1107
+ * - ``representation``
1108
+ - Rotational representation
1109
+ * - ``'rpy/xyz'``
1110
+ - RPY angular rates in XYZ order
1111
+ * - ``'rpy/zyx'``
1112
+ - RPY angular rates in ZYX order
1113
+ * - ``'eul'``
1114
+ - Euler angular rates in ZYZ order
1115
+ * - ``'exp'``
1116
+ - exponential coordinate rates
1117
+
1118
+ .. rubric:: References
1119
+
1120
+ - Kinematic Derivatives using the Elementary Transform
1121
+ Sequence, J. Haviland and P. Corke
1122
+
1123
+ See Also
1124
+ --------
1125
+ :func:`jacob0`
1126
+ :func:`hessian0`
1127
+
1128
+ """
1129
+
1130
+ qd = np.array(qd)
1131
+
1132
+ if representation is None:
1133
+ if J0 is None:
1134
+ J0 = self.jacob0(q)
1135
+ H = self.hessian0(q, J0=J0)
1136
+
1137
+ else:
1138
+ # # determine analytic rotation
1139
+ # T = self.fkine(q).A
1140
+ # gamma = smb.r2x(smb.t2r(T), representation=representation)
1141
+
1142
+ # # get transformation angular velocity to analytic velocity
1143
+ # Ai = smb.rotvelxform(
1144
+ # gamma, representation=representation, inverse=True, full=True
1145
+ # )
1146
+
1147
+ # # get analytic rate from joint rates
1148
+ # omega = J0[3:, :] @ qd
1149
+ # gamma_dot = Ai[3:, 3:] @ omega
1150
+ # Ai_dot = smb.rotvelxform_inv_dot(gamma, gamma_dot, full=True)
1151
+ # Ai_dot = sp.linalg.block_diag(np.zeros((3, 3)), Ai_dot)
1152
+
1153
+ # Jd = Ai_dot @ J0 + Ai @ Jd
1154
+
1155
+ # not actually sure this can be written in closed form
1156
+
1157
+ H = smb.numhess(
1158
+ lambda q: self.jacob0_analytical(q, representation=representation), q
1159
+ )
1160
+
1161
+ # Jd = Ai @ Jd
1162
+
1163
+ # return Jd
1164
+
1165
+ return np.tensordot(H, qd, (0, 0))
1166
+
1167
+ @overload
1168
+ def jacobm(
1169
+ self,
1170
+ q: ArrayLike = ...,
1171
+ J: None = None,
1172
+ H: None = None,
1173
+ end: str | Link | Gripper | None = None,
1174
+ start: str | Link | Gripper | None = None,
1175
+ axes: L["all", "trans", "rot"] | list[bool] = "all",
1176
+ ) -> NDArray: # pragma no cover
1177
+ ...
1178
+
1179
+ @overload
1180
+ def jacobm(
1181
+ self,
1182
+ q: None = None,
1183
+ J: NDArray = ...,
1184
+ H: NDArray = ...,
1185
+ end: str | Link | Gripper | None = None,
1186
+ start: str | Link | Gripper | None = None,
1187
+ axes: L["all", "trans", "rot"] | list[bool] = "all",
1188
+ ) -> NDArray: # pragma no cover
1189
+ ...
1190
+
1191
+ def jacobm(
1192
+ self,
1193
+ q=None,
1194
+ J=None,
1195
+ H=None,
1196
+ end: str | Link | Gripper | None = None,
1197
+ start: str | Link | Gripper | None = None,
1198
+ axes: L["all", "trans", "rot"] | list[bool] = "all",
1199
+ ) -> NDArray:
1200
+ r"""
1201
+ The manipulability Jacobian
1202
+
1203
+ :param q: The joint angles/configuration of the robot (Optional,
1204
+ if not supplied will use the stored q values).
1205
+ :param J: The manipulator Jacobian in any frame
1206
+ :param H: The manipulator Hessian in any frame
1207
+ :param end: the final link or Gripper which the Hessian represents
1208
+ :param start: the first link which the Hessian represents
1209
+ :returns: The manipulability Jacobian
1210
+
1211
+ This measure relates the rate of change of the manipulability to the
1212
+ joint velocities of the robot. One of J or q is required. Supply J
1213
+ and H if already calculated to save computation time.
1214
+
1215
+ Yoshikawa's manipulability measure
1216
+
1217
+ .. math::
1218
+
1219
+ m(\vec{q}) = \sqrt{\mat{J}(\vec{q}) \mat{J}(\vec{q})^T}
1220
+
1221
+ This method returns its Jacobian with respect to configuration
1222
+
1223
+ .. math::
1224
+
1225
+ \frac{\partial m(\vec{q})}{\partial \vec{q}}
1226
+
1227
+ .. rubric:: References
1228
+
1229
+ - J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
1230
+ Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
1231
+ - J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
1232
+ Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
1233
+
1234
+ """
1235
+
1236
+ end, start, _ = self._get_limit_links(end, start)
1237
+
1238
+ #
1239
+ if not isinstance(axes, list):
1240
+ if axes.startswith("all"):
1241
+ axes = [True, True, True, True, True, True]
1242
+ elif axes.startswith("trans"):
1243
+ axes = [True, True, True, False, False, False]
1244
+ elif axes.startswith("rot"):
1245
+ axes = [False, False, False, True, True, True]
1246
+ else:
1247
+ raise ValueError("axes must be all, trans or rot")
1248
+
1249
+ if J is None:
1250
+ if q is None:
1251
+ q = np.copy(self.q)
1252
+ else:
1253
+ q = getvector(q, self.n)
1254
+
1255
+ J = self.jacob0(q, start=start, end=end)
1256
+ else:
1257
+ verifymatrix(J, (6, self.n))
1258
+
1259
+ n = J.shape[1]
1260
+
1261
+ if H is None:
1262
+ H = self.hessian0(J0=J, start=start, end=end)
1263
+ # else:
1264
+ # verifymatrix(H, (6, self.n, self.n))
1265
+ elif not isinstance(H, np.ndarray):
1266
+ raise TypeError("Hessian must be numpy array of shape 6xnxn")
1267
+ elif H.shape != (6, self.n, self.n):
1268
+ raise ValueError("Hessian must be numpy array of shape 6xnxn")
1269
+
1270
+ manipulability = self.manipulability(
1271
+ q, # type: ignore[arg-type]
1272
+ J=J,
1273
+ start=start,
1274
+ end=end,
1275
+ axes=axes, # type: ignore
1276
+ )
1277
+
1278
+ J = J[axes, :] # type: ignore
1279
+ H = H[:, axes, :] # type: ignore
1280
+
1281
+ b = np.linalg.inv(J @ np.transpose(J))
1282
+ Jm = np.zeros((n, 1))
1283
+
1284
+ for i in range(n):
1285
+ c = J @ np.transpose(H[i, :, :])
1286
+ Jm[i, 0] = manipulability * np.transpose(c.flatten("F")) @ b.flatten("F")
1287
+
1288
+ return Jm
1289
+
1290
+ # --------------------------------------------------------------------- #
1291
+ # --------- Collision Methods ----------------------------------------- #
1292
+ # --------------------------------------------------------------------- #
1293
+
1294
+ def closest_point(
1295
+ self, q: ArrayLike, shape: Shape, inf_dist: float = 1.0, skip: bool = False
1296
+ ) -> tuple[int | None, NDArray | None, NDArray | None]:
1297
+ """
1298
+ Find the closest point between robot and shape
1299
+
1300
+ :param shape: The shape to compare distance to
1301
+ :param inf_dist: The minimum distance within which to consider the shape
1302
+ :param skip: Skip setting all shape transforms based on q, use this
1303
+ option if using this method in conjuction with Swift to save time
1304
+ :returns: tuple of (distance, point on robot, point on shape)
1305
+
1306
+ ``closest_point(shape, inf_dist)`` returns the minimum euclidean
1307
+ distance between this robot and shape, provided it is less than
1308
+ inf_dist. It will also return the points on self and shape in the
1309
+ world frame which connect the line of length distance between the
1310
+ shapes. If the distance is negative then the shapes are collided.
1311
+
1312
+ """
1313
+
1314
+ if not skip:
1315
+ self._update_link_tf(q)
1316
+ self.update()
1317
+ shape.update()
1318
+
1319
+ d = 10000
1320
+ p1 = None
1321
+ p2 = None
1322
+
1323
+ for link in self.links:
1324
+ td, tp1, tp2 = link.closest_point(shape, inf_dist, skip=True)
1325
+
1326
+ if td is not None and td < d:
1327
+ d = td
1328
+ p1 = tp1
1329
+ p2 = tp2
1330
+
1331
+ if d == 10000:
1332
+ d = None
1333
+
1334
+ return d, p1, p2
1335
+
1336
+ def iscollided(self, q, shape: Shape, skip: bool = False) -> bool:
1337
+ """
1338
+ Check if the robot is in collision with a shape
1339
+
1340
+ :param shape: The shape to compare distance to
1341
+ :param skip: Skip setting all shape transforms based on q, use this
1342
+ option if using this method in conjuction with Swift to save time
1343
+ :returns: True if shapes have collided
1344
+
1345
+ ``iscollided(shape)`` checks if this robot and shape have collided
1346
+
1347
+ """
1348
+
1349
+ if not skip:
1350
+ self._update_link_tf(q)
1351
+ self.update()
1352
+ shape.update()
1353
+
1354
+ for link in self.links:
1355
+ if link.iscollided(shape, skip=True):
1356
+ return True
1357
+
1358
+ if isinstance(self, rtb.Robot):
1359
+ for gripper in self.grippers:
1360
+ for link in gripper.links:
1361
+ if link.iscollided(shape, skip=True):
1362
+ return True
1363
+
1364
+ return False
1365
+
1366
+ def collided(self, q, shape: Shape, skip: bool = False) -> bool:
1367
+ """
1368
+ Check if the robot is in collision with a shape
1369
+
1370
+ :param shape: The shape to compare distance to
1371
+ :param skip: Skip setting all shape transforms based on q, use this
1372
+ option if using this method in conjuction with Swift to save time
1373
+ :returns: True if shapes have collided
1374
+
1375
+ ``collided(shape)`` checks if this robot and shape have collided
1376
+
1377
+ """
1378
+
1379
+ warn("method collided is deprecated, use iscollided instead", FutureWarning)
1380
+ return self.iscollided(q, shape, skip=skip)
1381
+
1382
+ # --------------------------------------------------------------------- #
1383
+ # --------- Constraint Methods ---------------------------------------- #
1384
+ # --------------------------------------------------------------------- #
1385
+
1386
+ def joint_velocity_damper(
1387
+ self,
1388
+ q=None,
1389
+ ps: float = 0.05,
1390
+ pi: float = 0.1,
1391
+ n: int | None = None,
1392
+ gain: float = 1.0,
1393
+ ) -> tuple[NDArray, NDArray]:
1394
+ """
1395
+ Compute the joint velocity damper for QP motion control
1396
+
1397
+ :param ps: The minimum angle (in radians) in which the joint is
1398
+ allowed to approach to its limit
1399
+ :param pi: The influence angle (in radians) in which the velocity
1400
+ damper becomes active
1401
+ :param n: The number of joints to consider. Defaults to all joints
1402
+ :param gain: The gain for the velocity damper
1403
+ :returns: tuple of (Ain, Bin) inequality constraint matrices for an optimiser
1404
+
1405
+ Formulates an inequality contraint which, when optimised for will
1406
+ make it impossible for the robot to run into joint limits. Requires
1407
+ the joint limits of the robot to be specified. See examples/mmc.py
1408
+ for use case.
1409
+
1410
+ """
1411
+
1412
+ if n is None:
1413
+ n = self.n
1414
+
1415
+ if q is None:
1416
+ q = np.copy(self.q)
1417
+
1418
+ Ain = np.zeros((n, n))
1419
+ Bin = np.zeros(n)
1420
+
1421
+ for i in range(n):
1422
+ if self.q[i] - self.qlim[0, i] <= pi:
1423
+ Bin[i] = -gain * (((self.qlim[0, i] - q[i]) + ps) / (pi - ps))
1424
+ Ain[i, i] = -1
1425
+ if self.qlim[1, i] - self.q[i] <= pi:
1426
+ Bin[i] = gain * ((self.qlim[1, i] - q[i]) - ps) / (pi - ps)
1427
+ Ain[i, i] = 1
1428
+
1429
+ return Ain, Bin
1430
+
1431
+ def link_collision_damper(
1432
+ self,
1433
+ shape: CollisionShape,
1434
+ q: ArrayLike,
1435
+ di: float = 0.3,
1436
+ ds: float = 0.05,
1437
+ xi: float = 1.0,
1438
+ end: Link | None = None,
1439
+ start: Link | None = None,
1440
+ collision_list: list[Shape] | None = None,
1441
+ ):
1442
+ """
1443
+ Compute a collision constrain for QP motion control
1444
+
1445
+ :param ds: The minimum distance in which a joint is allowed to
1446
+ approach the collision object shape
1447
+ :param di: The influence distance in which the velocity
1448
+ damper becomes active
1449
+ :param xi: The gain for the velocity damper
1450
+ :param end: The end link of the robot to consider
1451
+ :param start: The start link of the robot to consider
1452
+ :param collision_list: A list of shapes to consider for collision
1453
+ :returns: tuple of (Ain, Bin) inequality constraint matrices for an optimiser
1454
+
1455
+ Formulates an inequality contraint which, when optimised for will
1456
+ make it impossible for the robot to run into a collision. Requires
1457
+ See examples/neo.py for use case.
1458
+
1459
+ """
1460
+
1461
+ end, start, _ = self._get_limit_links(start=start, end=end)
1462
+
1463
+ links, n, _ = self.get_path(start=start, end=end)
1464
+
1465
+ q = np.array(q)
1466
+ j = 0
1467
+ Ain = None
1468
+ bin = None
1469
+
1470
+ def indiv_calculation(link: Link, link_col: CollisionShape, q: NDArray):
1471
+ d, wTlp, wTcp = link_col.closest_point(shape, di)
1472
+
1473
+ if d is not None and wTlp is not None and wTcp is not None:
1474
+ lpTcp = -wTlp + wTcp
1475
+
1476
+ norm = lpTcp / d
1477
+ norm_h = np.expand_dims(
1478
+ np.concatenate((norm, [0.0, 0.0, 0.0])),
1479
+ axis=0, # type: ignore
1480
+ )
1481
+
1482
+ # tool = (self.fkine(q, end=link).inv() * SE3(wTlp)).A[:3, 3]
1483
+
1484
+ # Je = self.jacob0(q, end=link, tool=tool)
1485
+ # Je[:3, :] = self._T[:3, :3] @ Je[:3, :]
1486
+
1487
+ # n_dim = Je.shape[1]
1488
+ # dp = norm_h @ shape.v
1489
+ # l_Ain = zeros((1, self.n))
1490
+
1491
+ Je = self.jacobe(q, start=start, end=link, tool=link_col.T)
1492
+ n_dim = Je.shape[1]
1493
+ dp = norm_h @ shape.v
1494
+ l_Ain = np.zeros((1, n))
1495
+
1496
+ l_Ain[0, :n_dim] = 1 * norm_h @ Je
1497
+ l_bin = (xi * (d - ds) / (di - ds)) + dp
1498
+ else: # pragma nocover
1499
+ l_Ain = None
1500
+ l_bin = None
1501
+
1502
+ return l_Ain, l_bin
1503
+
1504
+ for link in links:
1505
+ if link.isjoint:
1506
+ j += 1
1507
+
1508
+ if collision_list is None:
1509
+ col_list = link.collision
1510
+
1511
+ for c in col_list:
1512
+ pass
1513
+ else:
1514
+ col_list = [collision_list[j - 1]] # pragma nocover
1515
+
1516
+ for link_col in col_list:
1517
+ l_Ain, l_bin = indiv_calculation(link, link_col, q) # type: ignore
1518
+
1519
+ if l_Ain is not None and l_bin is not None:
1520
+ if Ain is None:
1521
+ Ain = l_Ain
1522
+ else:
1523
+ Ain = np.concatenate((Ain, l_Ain))
1524
+
1525
+ if bin is None:
1526
+ bin = np.array(l_bin)
1527
+ else:
1528
+ bin = np.concatenate((bin, l_bin))
1529
+
1530
+ return Ain, bin
1531
+
1532
+ def vision_collision_damper(
1533
+ self,
1534
+ shape: CollisionShape,
1535
+ camera: Robot | SE3 | None = None,
1536
+ camera_n: int = 0,
1537
+ q=None,
1538
+ di=0.3,
1539
+ ds=0.05,
1540
+ xi=1.0,
1541
+ end=None,
1542
+ start=None,
1543
+ collision_list=None,
1544
+ ): # pragma nocover
1545
+ """
1546
+ Compute a vision collision constrain for QP motion control
1547
+
1548
+ :param camera: The camera link, either as a robotic link or SE3 pose
1549
+ :param camera_n: Degrees of freedom of the camera link
1550
+ :param ds: The minimum distance in which a joint is allowed to
1551
+ approach the collision object shape
1552
+ :param di: The influence distance in which the velocity
1553
+ damper becomes active
1554
+ :param xi: The gain for the velocity damper
1555
+ :param end: The end link of the robot to consider
1556
+ :param start: The start link of the robot to consider
1557
+ :param collision_list: A list of shapes to consider for collision
1558
+ :returns: tuple of (Ain, Bin) inequality constraint matrices for an optimiser
1559
+
1560
+ Formulates an inequality contraint which, when optimised for will
1561
+ make it impossible for the robot to run into a line of sight.
1562
+ See examples/fetch_vision.py for use case.
1563
+
1564
+ """
1565
+
1566
+ end, start, _ = self._get_limit_links(start=start, end=end)
1567
+
1568
+ links, n, _ = self.get_path(start=start, end=end)
1569
+
1570
+ q = np.array(q)
1571
+ j = 0
1572
+ Ain = None
1573
+ bin = None
1574
+
1575
+ def rotation_between_vectors(a, b):
1576
+ a = a / np.linalg.norm(a)
1577
+ b = b / np.linalg.norm(b)
1578
+
1579
+ angle = np.arccos(np.dot(a, b))
1580
+ axis = np.cross(a, b)
1581
+
1582
+ return SE3.AngleAxis(angle, axis)
1583
+
1584
+ if isinstance(camera, rtb.BaseRobot):
1585
+ wTcp = cast(NDArray, camera.fkine(camera.q).A)[:3, 3]
1586
+ elif isinstance(camera, SE3):
1587
+ wTcp = camera.t
1588
+ else:
1589
+ raise TypeError("Camera must be a robotic link or SE3 pose")
1590
+
1591
+ wTtp = shape.T[:3, -1]
1592
+
1593
+ # Create line of sight object
1594
+ los_mid = SE3((wTcp + wTtp) / 2)
1595
+ los_orientation = rotation_between_vectors(
1596
+ np.array([0.0, 0.0, 1.0]),
1597
+ wTcp - wTtp, # type: ignore
1598
+ )
1599
+
1600
+ los = Cylinder(
1601
+ radius=0.001,
1602
+ length=np.linalg.norm(wTcp - wTtp), # type: ignore
1603
+ base=(los_mid * los_orientation),
1604
+ )
1605
+
1606
+ def indiv_calculation(link: Link, link_col: CollisionShape, q: NDArray):
1607
+ d, wTlp, wTvp = link_col.closest_point(los, di)
1608
+
1609
+ if d is not None and wTlp is not None and wTvp is not None:
1610
+ lpTvp = -wTlp + wTvp
1611
+
1612
+ norm = lpTvp / d
1613
+ norm_h = np.expand_dims(np.concatenate((norm, [0.0, 0.0, 0.0])), axis=0) # type: ignore
1614
+
1615
+ tool = SE3(
1616
+ (np.linalg.inv(self.fkine(q, end=link).A) @ SE3(wTlp).A)[:3, 3]
1617
+ )
1618
+
1619
+ Je = self.jacob0(q, end=link, tool=cast(NDArray, tool.A))
1620
+ Je[:3, :] = self._T[:3, :3] @ Je[:3, :]
1621
+ n_dim = Je.shape[1]
1622
+
1623
+ if isinstance(camera, "Robot"):
1624
+ Jv = camera.jacob0(camera.q)
1625
+ Jv[:3, :] = self._T[:3, :3] @ Jv[:3, :]
1626
+
1627
+ Jv *= np.linalg.norm(wTvp - shape.T[:3, -1]) / los.length # type: ignore
1628
+
1629
+ dpc = norm_h @ Jv
1630
+ dpc = np.concatenate(
1631
+ (
1632
+ dpc[0, :-camera_n],
1633
+ np.zeros(self.n - (camera.n - camera_n)),
1634
+ dpc[0, -camera_n:],
1635
+ )
1636
+ )
1637
+ else:
1638
+ dpc = np.zeros((1, self.n + camera_n))
1639
+
1640
+ dpt = norm_h @ shape.v
1641
+ dpt *= np.linalg.norm(wTvp - wTcp) / los.length # type: ignore
1642
+
1643
+ l_Ain = np.zeros((1, self.n + camera_n))
1644
+ l_Ain[0, :n_dim] = norm_h @ Je
1645
+ l_Ain -= dpc
1646
+ l_bin = (xi * (d - ds) / (di - ds)) + dpt
1647
+ else:
1648
+ l_Ain = None
1649
+ l_bin = None
1650
+
1651
+ return l_Ain, l_bin
1652
+
1653
+ for link in links:
1654
+ if link.isjoint:
1655
+ j += 1
1656
+
1657
+ if collision_list is None:
1658
+ col_list = link.collision
1659
+ else:
1660
+ col_list = collision_list[j - 1]
1661
+
1662
+ for link_col in col_list:
1663
+ l_Ain, l_bin = indiv_calculation(link, link_col, q)
1664
+
1665
+ if l_Ain is not None and l_bin is not None:
1666
+ if Ain is None:
1667
+ Ain = l_Ain
1668
+ else:
1669
+ Ain = np.concatenate((Ain, l_Ain))
1670
+
1671
+ if bin is None:
1672
+ bin = np.array(l_bin)
1673
+ else:
1674
+ bin = np.concatenate((bin, l_bin))
1675
+
1676
+ return Ain, bin
1677
+
1678
+ # --------------------------------------------------------------------- #
1679
+ # --------- Dynamics Methods ------------------------------------------ #
1680
+ # --------------------------------------------------------------------- #
1681
+
1682
+ def rne(
1683
+ self,
1684
+ q: NDArray,
1685
+ qd: NDArray,
1686
+ qdd: NDArray,
1687
+ symbolic: bool = False,
1688
+ gravity: ArrayLike | None = None,
1689
+ ):
1690
+ """
1691
+ Compute inverse dynamics via recursive Newton-Euler formulation
1692
+
1693
+ :param q: Joint coordinates
1694
+ :param qd: Joint velocity
1695
+ :param qdd: Joint acceleration
1696
+ :param symbolic: If True, supports symbolic expressions
1697
+ :param gravity: gravitational acceleration in the world frame,
1698
+ downwards gravitational force is equivalent to robot base
1699
+ acceleration upwards (positive); defaults to attribute of self
1700
+ :returns: Joint force/torques
1701
+
1702
+ ``rne_dh(q, qd, qdd)`` where the arguments have shape (n,) where n is
1703
+ the number of robot joints. The result has shape (n,).
1704
+
1705
+ ``rne_dh(q, qd, qdd)`` where the arguments have shape (m,n) where n
1706
+ is the number of robot joints and where m is the number of steps in
1707
+ the joint trajectory. The result has shape (m,n).
1708
+
1709
+ ``rne_dh(p)`` where the input is a 1D array ``p`` = [q, qd, qdd] with
1710
+ shape (3n,), and the result has shape (n,).
1711
+
1712
+ ``rne_dh(p)`` where the input is a 2D array ``p`` = [q, qd, qdd] with
1713
+ shape (m,3n) and the result has shape (m,n).
1714
+
1715
+ .. rubric:: Notes
1716
+
1717
+ - This version supports symbolic model parameters
1718
+ - Verified against MATLAB code
1719
+
1720
+ .. warning::
1721
+
1722
+ Assumes each link's joint is the *last* element of its own ETS
1723
+ segment (Featherstone's spatial-vector convention -- fixed
1724
+ geometry gets you *to* the joint, the joint is the last thing
1725
+ applied before the next link's frame). This is guaranteed for
1726
+ any ``Robot``/``ERobot`` built normally, either from a raw ETS
1727
+ (``Robot.__init__`` splits it via ``ETS.split()``, whose
1728
+ default "last" method enforces this per segment), from a URDF
1729
+ (each link's ETS is built fixed-transform-then-joint, in that
1730
+ order), or from a ``PoERobot`` (``_update_ets()`` appends the
1731
+ joint ET last too). It does **not** hold for a ``DHRobot``
1732
+ using standard DH conventions (``mdh=False``), where the joint
1733
+ comes *first*, followed by ``d``/``a``/``alpha`` -- calling
1734
+ ``Robot.rne(dh_instance, ...)`` directly (bypassing
1735
+ ``DHRobot``'s own correct ``rne()``/``rne_python()``) gives
1736
+ silently wrong answers. A ``DHRobot`` built with ``mdh=True``
1737
+ *is* joint-last (``DHLink._to_ets()``'s MDH branch reorders a
1738
+ revolute link's ``d`` translation to precede the joint
1739
+ rotation -- valid since a z-rotation and a z-translation
1740
+ commute -- so the joint ET is always last regardless of ``d``)
1741
+ and works correctly through this path. See rne.md. Revisit this
1742
+ guard if the Robot/Link class hierarchy is ever redesigned --
1743
+ see https://github.com/petercorke/robotics-toolbox-python/issues/571.
1744
+ """
1745
+
1746
+ # Checked via the `mdh` attribute rather than isinstance/class name:
1747
+ # joint-last compliance tracks the DH convention actually in use
1748
+ # (DHLink._to_ets() puts the joint last for mdh=True, not for
1749
+ # mdh=False), not the DHRobot class itself -- a DHRobot(mdh=True)
1750
+ # instance is structurally fine here (verified numerically against
1751
+ # rne_python() with nonzero d/alpha/mass/inertia). Non-DHRobot
1752
+ # types have no `mdh` attribute and default (via getattr) to True,
1753
+ # since their construction (ETS.split(), URDF, PoERobot's
1754
+ # _update_ets()) already guarantees joint-last independently of DH
1755
+ # conventions.
1756
+ assert getattr(self, "mdh", True), (
1757
+ "Robot.rne() assumes each link's joint is the last element of "
1758
+ "its own ETS segment, which does not hold for a DHRobot built "
1759
+ "with mdh=False (standard DH). Call DHRobot's own "
1760
+ "rne()/rne_python() instead of Robot.rne(dh_instance, ...) "
1761
+ "directly."
1762
+ )
1763
+
1764
+ n = self.n
1765
+ # n = len(self.links)
1766
+
1767
+ # allocate intermediate variables
1768
+ Xup = SE3.Alloc(n)
1769
+
1770
+ v = SpatialVelocity.Alloc(n)
1771
+ a = SpatialAcceleration.Alloc(n)
1772
+ f = SpatialForce.Alloc(n)
1773
+ I = SpatialInertia.Alloc(n)
1774
+ s = [] # joint motion subspace
1775
+
1776
+ # Handle trajectory case
1777
+ q = getmatrix(q, (None, None))
1778
+ qd = getmatrix(qd, (None, None))
1779
+ qdd = getmatrix(qdd, (None, None))
1780
+ l, _ = q.shape
1781
+
1782
+ if symbolic: # pragma: nocover
1783
+ Q = np.empty((l, n), dtype="O") # joint torque/force
1784
+ else:
1785
+ Q = np.empty((l, n)) # joint torque/force
1786
+
1787
+ link_groups: list[list[int]] = []
1788
+
1789
+ # Group links together based on whether they are joints or not
1790
+ # Static links are grouped with the first joint encountered
1791
+ current_group = []
1792
+ for i, link in enumerate(self.links):
1793
+ current_group.append(i)
1794
+
1795
+ # Break after adding the first link
1796
+ if link.isjoint:
1797
+ link_groups.append(current_group)
1798
+ current_group = []
1799
+
1800
+ # Make some intermediate variables
1801
+ for i, group in enumerate(link_groups):
1802
+ I_int = SpatialInertia()
1803
+
1804
+ for idx in group:
1805
+ link = self.links[idx]
1806
+
1807
+ I_int = I_int + SpatialInertia(m=link.m, r=link.r, I=link.I)
1808
+
1809
+ if link.v is not None:
1810
+ s.append(link.v.s) # type: ignore[union-attr]
1811
+
1812
+ I[i] = I_int
1813
+
1814
+ if gravity is None:
1815
+ gravity = self.gravity
1816
+ # no dtype= here: gravity may contain SymPy symbols (test_symdyn),
1817
+ # and forcing float would break that -- let numpy infer object dtype
1818
+ gravity = np.asarray(gravity)
1819
+ # gravity is defined in the world frame; rotate into the root link
1820
+ # frame via the base orientation before negating to the effective
1821
+ # upward acceleration RNE expects -- see rne_python()'s equivalent
1822
+ # handling, and rne.md for the bug this fixes (previously ignored
1823
+ # self.base entirely). Skipped for an identity base rather than
1824
+ # multiplying by R.T unconditionally: with symbolic gravity
1825
+ # components, an identity-matrix matmul still introduces spurious
1826
+ # "1.0*" float literals into the resulting expression.
1827
+ if not np.array_equal(self.base.R, np.eye(3)):
1828
+ gravity = self.base.R.T @ gravity
1829
+ a_grav = -SpatialAcceleration(gravity)
1830
+
1831
+ # For the following, v, a, f, I, s, Xup are all lists of length n
1832
+ # where the indices correspond to the index of the group within
1833
+ # link_groups
1834
+ # As always, q, qd, qdd are lists of length n, where indices correspond
1835
+ # to the jindex of the joint, which will be the last link in the group
1836
+ # within link_groups
1837
+
1838
+ for k in range(l):
1839
+ qk = q[k, :]
1840
+ qdk = qd[k, :]
1841
+ qddk = qdd[k, :]
1842
+
1843
+ # forward recursion
1844
+ for j, group in enumerate(link_groups):
1845
+ # The joint is the last link in the group
1846
+ joint = self.links[group[-1]]
1847
+ jindex = joint.jindex
1848
+
1849
+ vJ = SpatialVelocity(s[j] * qdk[jindex])
1850
+
1851
+ # transform from parent(j) to j
1852
+ # Xup_int = SE3()
1853
+ first_element = True
1854
+ for idx in group:
1855
+ link = self.links[idx]
1856
+
1857
+ if link.isjoint and link.jindex is not None:
1858
+ if first_element:
1859
+ Xup_int = SE3(link.A(qk[link.jindex]))
1860
+ first_element = False
1861
+ else:
1862
+ Xup_int = Xup_int * SE3(link.A(qk[link.jindex]))
1863
+ else:
1864
+ if first_element:
1865
+ Xup_int = SE3(link.A())
1866
+ first_element = False
1867
+ else:
1868
+ Xup_int = Xup_int * SE3(link.A())
1869
+
1870
+ Xup[j] = Xup_int.inv() # type: ignore[union-attr]
1871
+
1872
+ # The first link in the group
1873
+ first_link = self.links[group[0]]
1874
+
1875
+ if first_link.parent is None:
1876
+ v[j] = vJ
1877
+ a[j] = Xup[j] * a_grav + SpatialAcceleration(s[j] * qddk[jindex])
1878
+ else:
1879
+ # The index of `link`s parent within self.links
1880
+ parent_idx = self.links.index(first_link.parent)
1881
+
1882
+ # The index of the group that the parent link is in
1883
+ group_idx = [
1884
+ i for i, group in enumerate(link_groups) if parent_idx in group
1885
+ ][0]
1886
+
1887
+ v[j] = Xup[j] * v[group_idx] + vJ
1888
+ a[j] = (
1889
+ Xup[j] * a[group_idx]
1890
+ + SpatialAcceleration(s[j] * qddk[jindex])
1891
+ + v[j] @ vJ
1892
+ )
1893
+
1894
+ f[j] = I[j] * a[j] + v[j] @ (I[j] * v[j])
1895
+
1896
+ # Backward recursion
1897
+ for j in reversed(range(n)):
1898
+ group = link_groups[j]
1899
+ joint = self.links[group[-1]]
1900
+ first_link = self.links[group[0]]
1901
+ # link = self.links[j]
1902
+
1903
+ # next line could be dot(), but fails for symbolic arguments
1904
+ Q[k, j] = sum(f[j].A * s[j])
1905
+
1906
+ # add armature inertia and friction -- consistent with
1907
+ # DHRobot.rne_python()/ne.c, which both add G^2*Jm*qdd
1908
+ # (armature) and subtract link.friction() (viscous B +
1909
+ # Coulomb Tc).
1910
+ jindex = joint.jindex
1911
+ Q[k, j] += (
1912
+ joint.G**2 * joint.Jm * qddk[jindex]
1913
+ - joint.friction(qdk[jindex], coulomb=not symbolic)
1914
+ )
1915
+
1916
+ if first_link.parent is not None:
1917
+ # The index of `link`s parent within self.links
1918
+ parent_idx = self.links.index(first_link.parent)
1919
+
1920
+ # The index of the group that the parent link is in
1921
+ group_idx = [
1922
+ i for i, group in enumerate(link_groups) if parent_idx in group
1923
+ ][0]
1924
+
1925
+ f[group_idx] = f[group_idx] + Xup[j] * f[j]
1926
+
1927
+ # The current Q has the length equal to the number of links within the robot
1928
+ # rather than the number of joints. We need to remove the static links
1929
+ # from the Q array
1930
+ # joint_idx = [i for i, link in enumerate(self.links) if link.isjoint]
1931
+
1932
+ if l == 1:
1933
+ return Q[0]
1934
+ else: # pragma nocover
1935
+ return Q
1936
+
1937
+
1938
+ # ============================================================================= #
1939
+ # ================= URDFRobot Class =========================================== #
1940
+ # ============================================================================= #
1941
+
1942
+
1943
+ # class URDFRobot(Robot):
1944
+ # """A Robot subclass that initialises from a URDF or xacro file.
1945
+
1946
+ # Model classes should subclass this and call ``super().__init__()`` with
1947
+ # the path and manufacturer::
1948
+
1949
+ # class vx300(URDFRobot):
1950
+ # def __init__(self):
1951
+ # super().__init__(
1952
+ # "trossen_descriptions/urdf/vx300.urdf.xacro",
1953
+ # manufacturer="Trossen Robotics",
1954
+ # )
1955
+ # """
1956
+
1957
+ # def __init__(
1958
+ # self,
1959
+ # urdf_path: "str | Path",
1960
+ # manufacturer: str = "",
1961
+ # gripper_link_index: "int | None" = None,
1962
+ # **kwargs,
1963
+ # ):
1964
+ # elinks, name = self.URDF_file(urdf_path)
1965
+ # if gripper_link_index is not None:
1966
+ # kwargs["gripper_links"] = elinks[gripper_link_index]
1967
+ # super().__init__(elinks, name=name, manufacturer=manufacturer, **kwargs)
1968
+
1969
+
1970
+ # ============================================================================= #
1971
+ # ================= Robot2 Class ============================================== #
1972
+ # ============================================================================= #
1973
+
1974
+
1975
+ class Robot2(BaseRobot[Link2]):
1976
+ def __init__(self, arg, **kwargs):
1977
+ if isinstance(arg, ETS2):
1978
+ # we're passed an ETS string
1979
+ links = []
1980
+ # chop it up into segments, a link frame after every joint
1981
+ # split()'s default "last" method folds any base content into
1982
+ # the first segment, so `base` is always empty and dropped;
1983
+ # `gripper` holds trailing constant content, if any, and
1984
+ # becomes one extra static (non-joint) link.
1985
+ _, *segs, gripper = arg.split()
1986
+ if gripper:
1987
+ segs.append(gripper)
1988
+ parent = None
1989
+ for j, ets_j in enumerate(segs):
1990
+ elink = Link2(ETS2(ets_j), parent=parent, name=f"link{j:d}")
1991
+ parent = elink
1992
+ if (
1993
+ elink.qlim is None
1994
+ and elink.v is not None
1995
+ and elink.v.qlim is not None
1996
+ ): # pragma nocover
1997
+ elink.qlim = elink.v.qlim
1998
+ links.append(elink)
1999
+
2000
+ elif smb.islistof(arg, Link2):
2001
+ links = arg
2002
+
2003
+ else: # pragma nocover
2004
+ raise TypeError("constructor argument must be ETS2 or list of Link2")
2005
+
2006
+ super().__init__(links, **kwargs)
2007
+
2008
+ # Should just set it to None
2009
+ self.base = SE2() # override superclass
2010
+
2011
+ @property
2012
+ def base(self) -> SE2:
2013
+ """
2014
+ Get/set robot base transform (Robot superclass)
2015
+
2016
+ :returns: robot tool transform
2017
+
2018
+ ``robot.base`` is the robot base transform
2019
+
2020
+ - ``robot.base = ...`` checks and sets the robot base transform
2021
+
2022
+ .. rubric:: Notes
2023
+
2024
+ - The private attribute ``_base`` will be None in the case of
2025
+ no base transform, but this property will return ``SE3()`` which
2026
+ is an identity matrix.
2027
+ """
2028
+ if self._base is None: # pragma nocover
2029
+ self._base = SE2()
2030
+
2031
+ # return a copy, otherwise somebody with
2032
+ # reference to the base can change it
2033
+ return self._base.copy()
2034
+
2035
+ @base.setter
2036
+ def base(self, T):
2037
+ if isinstance(T, SE2):
2038
+ self._base = T
2039
+ elif SE2.isvalid(T): # pragma nocover
2040
+ self._tool = SE2(T, check=True)
2041
+
2042
+ def jacob0(self, q, start=None, end=None):
2043
+ return self.ets(start, end).jacob0(q)
2044
+
2045
+ def jacobe(self, q, start=None, end=None):
2046
+ return self.ets(start, end).jacobe(q)
2047
+
2048
+ def fkine(self, q, end=None, start=None):
2049
+ return self.ets(start, end).fkine(q)
2050
+
2051
+ @property
2052
+ def reach(self) -> float:
2053
+ r"""
2054
+ Reach of the robot
2055
+
2056
+ :returns: Maximum reach of the robot
2057
+ :rtype: float
2058
+
2059
+ A conservative estimate of the reach of the robot. It is computed as
2060
+ the sum of the translational ETs that define the link transform.
2061
+
2062
+ Computed on the first access. If kinematic parameters
2063
+ subsequently change this will not be reflected.
2064
+
2065
+ .. rubric:: Notes
2066
+
2067
+ - Probably an overestimate of reach
2068
+ - Used by numerical inverse kinematics to scale translational
2069
+ error.
2070
+ - For a prismatic joint, uses ``qlim`` if it is set
2071
+
2072
+ """
2073
+
2074
+ # TODO
2075
+ # This should be a start, end method and compute the reach based on the
2076
+ # given ets. Then use an lru_cache to speed up return
2077
+
2078
+ if self._reach is None:
2079
+ d_all = []
2080
+ for link in self.ee_links:
2081
+ d = 0
2082
+ while True:
2083
+ for et in link.ets:
2084
+ if et.istranslation:
2085
+ if et.isjoint:
2086
+ # the length of a prismatic joint depends on the
2087
+ # joint limits. They might be set in the ET
2088
+ # or in the Link depending on how the robot
2089
+ # was constructed
2090
+ if link.qlim is not None:
2091
+ d += max(link.qlim)
2092
+ elif et.qlim is not None: # pragma nocover
2093
+ d += max(et.qlim)
2094
+ else:
2095
+ d += abs(et.param)
2096
+ link = link.parent
2097
+ if link is None or isinstance(link, str):
2098
+ d_all.append(d)
2099
+ break
2100
+
2101
+ self._reach = max(d_all)
2102
+ return self._reach
2103
+
2104
+ def fkine_all(self, q: ArrayLike) -> SE2:
2105
+ """
2106
+ Compute the pose of every link frame
2107
+
2108
+ :param q: The joint configuration
2109
+ :returns: Pose of all links
2110
+
2111
+ ``T = robot.fkine_all(q)`` is an SE3 instance with ``robot.nlinks +
2112
+ 1`` values:
2113
+
2114
+ - ``T[0]`` is the base transform
2115
+ - ``T[i]`` is the pose of link whose ``number`` is ``i``
2116
+
2117
+ .. rubric:: References
2118
+
2119
+ - J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
2120
+ Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
2121
+
2122
+ """
2123
+
2124
+ q = getvector(q)
2125
+
2126
+ Tbase = SE2(self.base) # add base, also sets the type
2127
+
2128
+ linkframes = Tbase.__class__.Alloc(self.nlinks + 1)
2129
+ linkframes[0] = Tbase
2130
+
2131
+ def recurse(Tall, Tparent, q, link):
2132
+ # if joint??
2133
+ T = Tparent
2134
+ while True:
2135
+ T *= SE2(link.A(q[link.jindex]))
2136
+
2137
+ Tall[link.number] = T
2138
+
2139
+ if link.nchildren == 0:
2140
+ # no children
2141
+ return
2142
+ elif link.nchildren == 1:
2143
+ # one child
2144
+ if link in self.ee_links: # pragma nocover
2145
+ # this link is an end-effector, go no further
2146
+ return
2147
+ link = link.children[0]
2148
+ continue
2149
+ else:
2150
+ # multiple children
2151
+ for child in link.children:
2152
+ recurse(Tall, T, q, child)
2153
+ return
2154
+
2155
+ recurse(linkframes, Tbase, q, self.links[0])
2156
+
2157
+ return linkframes