roboticstoolbox-python 1.3.0__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (673) hide show
  1. roboticstoolbox/__init__.py +104 -0
  2. roboticstoolbox/backends/Connector.py +107 -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 +253 -0
  21. roboticstoolbox/backends/PyPlot/PyPlot.py +769 -0
  22. roboticstoolbox/backends/PyPlot/PyPlot2.py +526 -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 +26 -0
  31. roboticstoolbox/bin/__init__.py +0 -0
  32. roboticstoolbox/bin/rtbtool.py +307 -0
  33. roboticstoolbox/blocks/Icons/250x250/armplot.png +0 -0
  34. roboticstoolbox/blocks/Icons/250x250/bicycle.png +0 -0
  35. roboticstoolbox/blocks/Icons/250x250/camera.png +0 -0
  36. roboticstoolbox/blocks/Icons/250x250/circlepath.png +0 -0
  37. roboticstoolbox/blocks/Icons/250x250/coriolis.png +0 -0
  38. roboticstoolbox/blocks/Icons/250x250/ctraj.png +0 -0
  39. roboticstoolbox/blocks/Icons/250x250/delta2tr.png +0 -0
  40. roboticstoolbox/blocks/Icons/250x250/diffsteer.png +0 -0
  41. roboticstoolbox/blocks/Icons/250x250/fdyn.png +0 -0
  42. roboticstoolbox/blocks/Icons/250x250/fdynx.png +0 -0
  43. roboticstoolbox/blocks/Icons/250x250/fkine.png +0 -0
  44. roboticstoolbox/blocks/Icons/250x250/gravload.png +0 -0
  45. roboticstoolbox/blocks/Icons/250x250/idyn.png +0 -0
  46. roboticstoolbox/blocks/Icons/250x250/idynx.png +0 -0
  47. roboticstoolbox/blocks/Icons/250x250/ikine.png +0 -0
  48. roboticstoolbox/blocks/Icons/250x250/inertia.png +0 -0
  49. roboticstoolbox/blocks/Icons/250x250/jacobian.png +0 -0
  50. roboticstoolbox/blocks/Icons/250x250/jtraj.png +0 -0
  51. roboticstoolbox/blocks/Icons/250x250/lspb.png +0 -0
  52. roboticstoolbox/blocks/Icons/250x250/multirotor.png +0 -0
  53. roboticstoolbox/blocks/Icons/250x250/multirotormixer.png +0 -0
  54. roboticstoolbox/blocks/Icons/250x250/multirotorplot.png +0 -0
  55. roboticstoolbox/blocks/Icons/250x250/point2tr.png +0 -0
  56. roboticstoolbox/blocks/Icons/250x250/tr2delta.png +0 -0
  57. roboticstoolbox/blocks/Icons/250x250/tr2t.png +0 -0
  58. roboticstoolbox/blocks/Icons/250x250/unicycle.png +0 -0
  59. roboticstoolbox/blocks/Icons/250x250/vehicleplot.png +0 -0
  60. roboticstoolbox/blocks/Icons/50x50/armplot.png +0 -0
  61. roboticstoolbox/blocks/Icons/50x50/bicycle.png +0 -0
  62. roboticstoolbox/blocks/Icons/50x50/camera.png +0 -0
  63. roboticstoolbox/blocks/Icons/50x50/circlepath.png +0 -0
  64. roboticstoolbox/blocks/Icons/50x50/coriolis.png +0 -0
  65. roboticstoolbox/blocks/Icons/50x50/delta2tr.png +0 -0
  66. roboticstoolbox/blocks/Icons/50x50/diffsteer.png +0 -0
  67. roboticstoolbox/blocks/Icons/50x50/fdyn.png +0 -0
  68. roboticstoolbox/blocks/Icons/50x50/fdynx.png +0 -0
  69. roboticstoolbox/blocks/Icons/50x50/fkine.png +0 -0
  70. roboticstoolbox/blocks/Icons/50x50/gravload.png +0 -0
  71. roboticstoolbox/blocks/Icons/50x50/idyn.png +0 -0
  72. roboticstoolbox/blocks/Icons/50x50/idynx.png +0 -0
  73. roboticstoolbox/blocks/Icons/50x50/ikine.png +0 -0
  74. roboticstoolbox/blocks/Icons/50x50/inertia.png +0 -0
  75. roboticstoolbox/blocks/Icons/50x50/jacobian.png +0 -0
  76. roboticstoolbox/blocks/Icons/50x50/jtraj.png +0 -0
  77. roboticstoolbox/blocks/Icons/50x50/lspb.png +0 -0
  78. roboticstoolbox/blocks/Icons/50x50/multirotor.png +0 -0
  79. roboticstoolbox/blocks/Icons/50x50/multirotormixer.png +0 -0
  80. roboticstoolbox/blocks/Icons/50x50/multirotorplot.png +0 -0
  81. roboticstoolbox/blocks/Icons/50x50/point2tr.png +0 -0
  82. roboticstoolbox/blocks/Icons/50x50/tr2delta.png +0 -0
  83. roboticstoolbox/blocks/Icons/50x50/tr2t.png +0 -0
  84. roboticstoolbox/blocks/Icons/50x50/unicycle.png +0 -0
  85. roboticstoolbox/blocks/Icons/50x50/vehicleplot.png +0 -0
  86. roboticstoolbox/blocks/Icons/armplot.png +0 -0
  87. roboticstoolbox/blocks/Icons/bicycle.png +0 -0
  88. roboticstoolbox/blocks/Icons/camera.png +0 -0
  89. roboticstoolbox/blocks/Icons/circlepath.png +0 -0
  90. roboticstoolbox/blocks/Icons/coriolis.png +0 -0
  91. roboticstoolbox/blocks/Icons/ctraj.png +0 -0
  92. roboticstoolbox/blocks/Icons/delta2tr.png +0 -0
  93. roboticstoolbox/blocks/Icons/diffsteer.png +0 -0
  94. roboticstoolbox/blocks/Icons/fdyn.png +0 -0
  95. roboticstoolbox/blocks/Icons/fdynx.png +0 -0
  96. roboticstoolbox/blocks/Icons/fkine.png +0 -0
  97. roboticstoolbox/blocks/Icons/gravload.png +0 -0
  98. roboticstoolbox/blocks/Icons/idyn.png +0 -0
  99. roboticstoolbox/blocks/Icons/idynx.png +0 -0
  100. roboticstoolbox/blocks/Icons/ikine.png +0 -0
  101. roboticstoolbox/blocks/Icons/inertia.png +0 -0
  102. roboticstoolbox/blocks/Icons/jacobian.png +0 -0
  103. roboticstoolbox/blocks/Icons/jtraj.png +0 -0
  104. roboticstoolbox/blocks/Icons/lspb.png +0 -0
  105. roboticstoolbox/blocks/Icons/multirotor.png +0 -0
  106. roboticstoolbox/blocks/Icons/multirotormixer.png +0 -0
  107. roboticstoolbox/blocks/Icons/multirotorplot.png +0 -0
  108. roboticstoolbox/blocks/Icons/point2tr.png +0 -0
  109. roboticstoolbox/blocks/Icons/tr2delta.png +0 -0
  110. roboticstoolbox/blocks/Icons/tr2t.png +0 -0
  111. roboticstoolbox/blocks/Icons/unicycle.png +0 -0
  112. roboticstoolbox/blocks/Icons/vehicleplot.png +0 -0
  113. roboticstoolbox/blocks/README.md +43 -0
  114. roboticstoolbox/blocks/__init__.py +6 -0
  115. roboticstoolbox/blocks/arm.py +1587 -0
  116. roboticstoolbox/blocks/mobile.py +500 -0
  117. roboticstoolbox/blocks/quad_model.py +132 -0
  118. roboticstoolbox/blocks/spatial.py +245 -0
  119. roboticstoolbox/blocks/uav.py +949 -0
  120. roboticstoolbox/core/Eigen/Cholesky +45 -0
  121. roboticstoolbox/core/Eigen/CholmodSupport +48 -0
  122. roboticstoolbox/core/Eigen/Core +384 -0
  123. roboticstoolbox/core/Eigen/Dense +7 -0
  124. roboticstoolbox/core/Eigen/Eigen +2 -0
  125. roboticstoolbox/core/Eigen/Eigenvalues +60 -0
  126. roboticstoolbox/core/Eigen/Geometry +59 -0
  127. roboticstoolbox/core/Eigen/Householder +29 -0
  128. roboticstoolbox/core/Eigen/IterativeLinearSolvers +48 -0
  129. roboticstoolbox/core/Eigen/Jacobi +32 -0
  130. roboticstoolbox/core/Eigen/KLUSupport +41 -0
  131. roboticstoolbox/core/Eigen/LU +47 -0
  132. roboticstoolbox/core/Eigen/MetisSupport +35 -0
  133. roboticstoolbox/core/Eigen/OrderingMethods +70 -0
  134. roboticstoolbox/core/Eigen/PaStiXSupport +49 -0
  135. roboticstoolbox/core/Eigen/PardisoSupport +35 -0
  136. roboticstoolbox/core/Eigen/QR +50 -0
  137. roboticstoolbox/core/Eigen/QtAlignedMalloc +39 -0
  138. roboticstoolbox/core/Eigen/SPQRSupport +34 -0
  139. roboticstoolbox/core/Eigen/SVD +50 -0
  140. roboticstoolbox/core/Eigen/Sparse +34 -0
  141. roboticstoolbox/core/Eigen/SparseCholesky +37 -0
  142. roboticstoolbox/core/Eigen/SparseCore +69 -0
  143. roboticstoolbox/core/Eigen/SparseLU +50 -0
  144. roboticstoolbox/core/Eigen/SparseQR +36 -0
  145. roboticstoolbox/core/Eigen/StdDeque +27 -0
  146. roboticstoolbox/core/Eigen/StdList +26 -0
  147. roboticstoolbox/core/Eigen/StdVector +27 -0
  148. roboticstoolbox/core/Eigen/SuperLUSupport +64 -0
  149. roboticstoolbox/core/Eigen/UmfPackSupport +40 -0
  150. roboticstoolbox/core/Eigen/src/Cholesky/LDLT.h +688 -0
  151. roboticstoolbox/core/Eigen/src/Cholesky/LLT.h +558 -0
  152. roboticstoolbox/core/Eigen/src/Cholesky/LLT_LAPACKE.h +99 -0
  153. roboticstoolbox/core/Eigen/src/CholmodSupport/CholmodSupport.h +682 -0
  154. roboticstoolbox/core/Eigen/src/Core/ArithmeticSequence.h +413 -0
  155. roboticstoolbox/core/Eigen/src/Core/Array.h +417 -0
  156. roboticstoolbox/core/Eigen/src/Core/ArrayBase.h +226 -0
  157. roboticstoolbox/core/Eigen/src/Core/ArrayWrapper.h +209 -0
  158. roboticstoolbox/core/Eigen/src/Core/Assign.h +90 -0
  159. roboticstoolbox/core/Eigen/src/Core/AssignEvaluator.h +1010 -0
  160. roboticstoolbox/core/Eigen/src/Core/Assign_MKL.h +178 -0
  161. roboticstoolbox/core/Eigen/src/Core/BandMatrix.h +353 -0
  162. roboticstoolbox/core/Eigen/src/Core/Block.h +448 -0
  163. roboticstoolbox/core/Eigen/src/Core/BooleanRedux.h +162 -0
  164. roboticstoolbox/core/Eigen/src/Core/CommaInitializer.h +164 -0
  165. roboticstoolbox/core/Eigen/src/Core/ConditionEstimator.h +175 -0
  166. roboticstoolbox/core/Eigen/src/Core/CoreEvaluators.h +1741 -0
  167. roboticstoolbox/core/Eigen/src/Core/CoreIterators.h +132 -0
  168. roboticstoolbox/core/Eigen/src/Core/CwiseBinaryOp.h +183 -0
  169. roboticstoolbox/core/Eigen/src/Core/CwiseNullaryOp.h +1001 -0
  170. roboticstoolbox/core/Eigen/src/Core/CwiseTernaryOp.h +197 -0
  171. roboticstoolbox/core/Eigen/src/Core/CwiseUnaryOp.h +103 -0
  172. roboticstoolbox/core/Eigen/src/Core/CwiseUnaryView.h +132 -0
  173. roboticstoolbox/core/Eigen/src/Core/DenseBase.h +701 -0
  174. roboticstoolbox/core/Eigen/src/Core/DenseCoeffsBase.h +685 -0
  175. roboticstoolbox/core/Eigen/src/Core/DenseStorage.h +652 -0
  176. roboticstoolbox/core/Eigen/src/Core/Diagonal.h +258 -0
  177. roboticstoolbox/core/Eigen/src/Core/DiagonalMatrix.h +391 -0
  178. roboticstoolbox/core/Eigen/src/Core/DiagonalProduct.h +28 -0
  179. roboticstoolbox/core/Eigen/src/Core/Dot.h +318 -0
  180. roboticstoolbox/core/Eigen/src/Core/EigenBase.h +160 -0
  181. roboticstoolbox/core/Eigen/src/Core/ForceAlignedAccess.h +150 -0
  182. roboticstoolbox/core/Eigen/src/Core/Fuzzy.h +155 -0
  183. roboticstoolbox/core/Eigen/src/Core/GeneralProduct.h +465 -0
  184. roboticstoolbox/core/Eigen/src/Core/GenericPacketMath.h +1040 -0
  185. roboticstoolbox/core/Eigen/src/Core/GlobalFunctions.h +194 -0
  186. roboticstoolbox/core/Eigen/src/Core/IO.h +258 -0
  187. roboticstoolbox/core/Eigen/src/Core/IndexedView.h +237 -0
  188. roboticstoolbox/core/Eigen/src/Core/Inverse.h +117 -0
  189. roboticstoolbox/core/Eigen/src/Core/Map.h +171 -0
  190. roboticstoolbox/core/Eigen/src/Core/MapBase.h +310 -0
  191. roboticstoolbox/core/Eigen/src/Core/MathFunctions.h +2057 -0
  192. roboticstoolbox/core/Eigen/src/Core/MathFunctionsImpl.h +200 -0
  193. roboticstoolbox/core/Eigen/src/Core/Matrix.h +565 -0
  194. roboticstoolbox/core/Eigen/src/Core/MatrixBase.h +547 -0
  195. roboticstoolbox/core/Eigen/src/Core/NestByValue.h +85 -0
  196. roboticstoolbox/core/Eigen/src/Core/NoAlias.h +109 -0
  197. roboticstoolbox/core/Eigen/src/Core/NumTraits.h +335 -0
  198. roboticstoolbox/core/Eigen/src/Core/PartialReduxEvaluator.h +232 -0
  199. roboticstoolbox/core/Eigen/src/Core/PermutationMatrix.h +605 -0
  200. roboticstoolbox/core/Eigen/src/Core/PlainObjectBase.h +1128 -0
  201. roboticstoolbox/core/Eigen/src/Core/Product.h +191 -0
  202. roboticstoolbox/core/Eigen/src/Core/ProductEvaluators.h +1179 -0
  203. roboticstoolbox/core/Eigen/src/Core/Random.h +218 -0
  204. roboticstoolbox/core/Eigen/src/Core/Redux.h +515 -0
  205. roboticstoolbox/core/Eigen/src/Core/Ref.h +381 -0
  206. roboticstoolbox/core/Eigen/src/Core/Replicate.h +142 -0
  207. roboticstoolbox/core/Eigen/src/Core/Reshaped.h +454 -0
  208. roboticstoolbox/core/Eigen/src/Core/ReturnByValue.h +119 -0
  209. roboticstoolbox/core/Eigen/src/Core/Reverse.h +217 -0
  210. roboticstoolbox/core/Eigen/src/Core/Select.h +164 -0
  211. roboticstoolbox/core/Eigen/src/Core/SelfAdjointView.h +365 -0
  212. roboticstoolbox/core/Eigen/src/Core/SelfCwiseBinaryOp.h +47 -0
  213. roboticstoolbox/core/Eigen/src/Core/Solve.h +188 -0
  214. roboticstoolbox/core/Eigen/src/Core/SolveTriangular.h +235 -0
  215. roboticstoolbox/core/Eigen/src/Core/SolverBase.h +168 -0
  216. roboticstoolbox/core/Eigen/src/Core/StableNorm.h +251 -0
  217. roboticstoolbox/core/Eigen/src/Core/StlIterators.h +463 -0
  218. roboticstoolbox/core/Eigen/src/Core/Stride.h +116 -0
  219. roboticstoolbox/core/Eigen/src/Core/Swap.h +68 -0
  220. roboticstoolbox/core/Eigen/src/Core/Transpose.h +464 -0
  221. roboticstoolbox/core/Eigen/src/Core/Transpositions.h +386 -0
  222. roboticstoolbox/core/Eigen/src/Core/TriangularMatrix.h +1001 -0
  223. roboticstoolbox/core/Eigen/src/Core/VectorBlock.h +96 -0
  224. roboticstoolbox/core/Eigen/src/Core/VectorwiseOp.h +784 -0
  225. roboticstoolbox/core/Eigen/src/Core/Visitor.h +381 -0
  226. roboticstoolbox/core/Eigen/src/Core/arch/AVX/Complex.h +372 -0
  227. roboticstoolbox/core/Eigen/src/Core/arch/AVX/MathFunctions.h +228 -0
  228. roboticstoolbox/core/Eigen/src/Core/arch/AVX/PacketMath.h +1574 -0
  229. roboticstoolbox/core/Eigen/src/Core/arch/AVX/TypeCasting.h +115 -0
  230. roboticstoolbox/core/Eigen/src/Core/arch/AVX512/Complex.h +422 -0
  231. roboticstoolbox/core/Eigen/src/Core/arch/AVX512/MathFunctions.h +362 -0
  232. roboticstoolbox/core/Eigen/src/Core/arch/AVX512/PacketMath.h +2303 -0
  233. roboticstoolbox/core/Eigen/src/Core/arch/AVX512/TypeCasting.h +89 -0
  234. roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/Complex.h +417 -0
  235. roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/MathFunctions.h +90 -0
  236. roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/MatrixProduct.h +2937 -0
  237. roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/MatrixProductCommon.h +221 -0
  238. roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h +629 -0
  239. roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/PacketMath.h +2711 -0
  240. roboticstoolbox/core/Eigen/src/Core/arch/CUDA/Complex.h +258 -0
  241. roboticstoolbox/core/Eigen/src/Core/arch/Default/BFloat16.h +700 -0
  242. roboticstoolbox/core/Eigen/src/Core/arch/Default/ConjHelper.h +117 -0
  243. roboticstoolbox/core/Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h +1649 -0
  244. roboticstoolbox/core/Eigen/src/Core/arch/Default/GenericPacketMathFunctionsFwd.h +110 -0
  245. roboticstoolbox/core/Eigen/src/Core/arch/Default/Half.h +942 -0
  246. roboticstoolbox/core/Eigen/src/Core/arch/Default/Settings.h +49 -0
  247. roboticstoolbox/core/Eigen/src/Core/arch/Default/TypeCasting.h +120 -0
  248. roboticstoolbox/core/Eigen/src/Core/arch/GPU/MathFunctions.h +103 -0
  249. roboticstoolbox/core/Eigen/src/Core/arch/GPU/PacketMath.h +1685 -0
  250. roboticstoolbox/core/Eigen/src/Core/arch/GPU/TypeCasting.h +80 -0
  251. roboticstoolbox/core/Eigen/src/Core/arch/HIP/hcc/math_constants.h +23 -0
  252. roboticstoolbox/core/Eigen/src/Core/arch/MSA/Complex.h +648 -0
  253. roboticstoolbox/core/Eigen/src/Core/arch/MSA/MathFunctions.h +387 -0
  254. roboticstoolbox/core/Eigen/src/Core/arch/MSA/PacketMath.h +1233 -0
  255. roboticstoolbox/core/Eigen/src/Core/arch/NEON/Complex.h +584 -0
  256. roboticstoolbox/core/Eigen/src/Core/arch/NEON/GeneralBlockPanelKernel.h +183 -0
  257. roboticstoolbox/core/Eigen/src/Core/arch/NEON/MathFunctions.h +75 -0
  258. roboticstoolbox/core/Eigen/src/Core/arch/NEON/PacketMath.h +4587 -0
  259. roboticstoolbox/core/Eigen/src/Core/arch/NEON/TypeCasting.h +1419 -0
  260. roboticstoolbox/core/Eigen/src/Core/arch/SSE/Complex.h +351 -0
  261. roboticstoolbox/core/Eigen/src/Core/arch/SSE/MathFunctions.h +199 -0
  262. roboticstoolbox/core/Eigen/src/Core/arch/SSE/PacketMath.h +1505 -0
  263. roboticstoolbox/core/Eigen/src/Core/arch/SSE/TypeCasting.h +142 -0
  264. roboticstoolbox/core/Eigen/src/Core/arch/SVE/MathFunctions.h +44 -0
  265. roboticstoolbox/core/Eigen/src/Core/arch/SVE/PacketMath.h +752 -0
  266. roboticstoolbox/core/Eigen/src/Core/arch/SVE/TypeCasting.h +49 -0
  267. roboticstoolbox/core/Eigen/src/Core/arch/SYCL/InteropHeaders.h +232 -0
  268. roboticstoolbox/core/Eigen/src/Core/arch/SYCL/MathFunctions.h +301 -0
  269. roboticstoolbox/core/Eigen/src/Core/arch/SYCL/PacketMath.h +670 -0
  270. roboticstoolbox/core/Eigen/src/Core/arch/SYCL/SyclMemoryModel.h +694 -0
  271. roboticstoolbox/core/Eigen/src/Core/arch/SYCL/TypeCasting.h +85 -0
  272. roboticstoolbox/core/Eigen/src/Core/arch/ZVector/Complex.h +426 -0
  273. roboticstoolbox/core/Eigen/src/Core/arch/ZVector/MathFunctions.h +233 -0
  274. roboticstoolbox/core/Eigen/src/Core/arch/ZVector/PacketMath.h +1060 -0
  275. roboticstoolbox/core/Eigen/src/Core/functors/AssignmentFunctors.h +177 -0
  276. roboticstoolbox/core/Eigen/src/Core/functors/BinaryFunctors.h +541 -0
  277. roboticstoolbox/core/Eigen/src/Core/functors/NullaryFunctors.h +189 -0
  278. roboticstoolbox/core/Eigen/src/Core/functors/StlFunctors.h +166 -0
  279. roboticstoolbox/core/Eigen/src/Core/functors/TernaryFunctors.h +25 -0
  280. roboticstoolbox/core/Eigen/src/Core/functors/UnaryFunctors.h +1131 -0
  281. roboticstoolbox/core/Eigen/src/Core/products/GeneralBlockPanelKernel.h +2645 -0
  282. roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixMatrix.h +517 -0
  283. roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h +317 -0
  284. roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h +145 -0
  285. roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h +124 -0
  286. roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixVector.h +518 -0
  287. roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h +136 -0
  288. roboticstoolbox/core/Eigen/src/Core/products/Parallelizer.h +180 -0
  289. roboticstoolbox/core/Eigen/src/Core/products/SelfadjointMatrixMatrix.h +544 -0
  290. roboticstoolbox/core/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h +295 -0
  291. roboticstoolbox/core/Eigen/src/Core/products/SelfadjointMatrixVector.h +262 -0
  292. roboticstoolbox/core/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h +118 -0
  293. roboticstoolbox/core/Eigen/src/Core/products/SelfadjointProduct.h +133 -0
  294. roboticstoolbox/core/Eigen/src/Core/products/SelfadjointRank2Update.h +94 -0
  295. roboticstoolbox/core/Eigen/src/Core/products/TriangularMatrixMatrix.h +472 -0
  296. roboticstoolbox/core/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h +317 -0
  297. roboticstoolbox/core/Eigen/src/Core/products/TriangularMatrixVector.h +350 -0
  298. roboticstoolbox/core/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h +255 -0
  299. roboticstoolbox/core/Eigen/src/Core/products/TriangularSolverMatrix.h +337 -0
  300. roboticstoolbox/core/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h +167 -0
  301. roboticstoolbox/core/Eigen/src/Core/products/TriangularSolverVector.h +148 -0
  302. roboticstoolbox/core/Eigen/src/Core/util/BlasUtil.h +583 -0
  303. roboticstoolbox/core/Eigen/src/Core/util/ConfigureVectorization.h +512 -0
  304. roboticstoolbox/core/Eigen/src/Core/util/Constants.h +563 -0
  305. roboticstoolbox/core/Eigen/src/Core/util/DisableStupidWarnings.h +106 -0
  306. roboticstoolbox/core/Eigen/src/Core/util/ForwardDeclarations.h +322 -0
  307. roboticstoolbox/core/Eigen/src/Core/util/IndexedViewHelper.h +186 -0
  308. roboticstoolbox/core/Eigen/src/Core/util/IntegralConstant.h +272 -0
  309. roboticstoolbox/core/Eigen/src/Core/util/MKL_support.h +137 -0
  310. roboticstoolbox/core/Eigen/src/Core/util/Macros.h +1464 -0
  311. roboticstoolbox/core/Eigen/src/Core/util/Memory.h +1163 -0
  312. roboticstoolbox/core/Eigen/src/Core/util/Meta.h +812 -0
  313. roboticstoolbox/core/Eigen/src/Core/util/NonMPL2.h +3 -0
  314. roboticstoolbox/core/Eigen/src/Core/util/ReenableStupidWarnings.h +31 -0
  315. roboticstoolbox/core/Eigen/src/Core/util/ReshapedHelper.h +51 -0
  316. roboticstoolbox/core/Eigen/src/Core/util/StaticAssert.h +221 -0
  317. roboticstoolbox/core/Eigen/src/Core/util/SymbolicIndex.h +293 -0
  318. roboticstoolbox/core/Eigen/src/Core/util/XprHelper.h +856 -0
  319. roboticstoolbox/core/Eigen/src/Eigenvalues/ComplexEigenSolver.h +346 -0
  320. roboticstoolbox/core/Eigen/src/Eigenvalues/ComplexSchur.h +462 -0
  321. roboticstoolbox/core/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h +91 -0
  322. roboticstoolbox/core/Eigen/src/Eigenvalues/EigenSolver.h +622 -0
  323. roboticstoolbox/core/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h +418 -0
  324. roboticstoolbox/core/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h +226 -0
  325. roboticstoolbox/core/Eigen/src/Eigenvalues/HessenbergDecomposition.h +374 -0
  326. roboticstoolbox/core/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h +158 -0
  327. roboticstoolbox/core/Eigen/src/Eigenvalues/RealQZ.h +657 -0
  328. roboticstoolbox/core/Eigen/src/Eigenvalues/RealSchur.h +558 -0
  329. roboticstoolbox/core/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h +77 -0
  330. roboticstoolbox/core/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h +904 -0
  331. roboticstoolbox/core/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h +87 -0
  332. roboticstoolbox/core/Eigen/src/Eigenvalues/Tridiagonalization.h +561 -0
  333. roboticstoolbox/core/Eigen/src/Geometry/AlignedBox.h +486 -0
  334. roboticstoolbox/core/Eigen/src/Geometry/AngleAxis.h +247 -0
  335. roboticstoolbox/core/Eigen/src/Geometry/EulerAngles.h +114 -0
  336. roboticstoolbox/core/Eigen/src/Geometry/Homogeneous.h +501 -0
  337. roboticstoolbox/core/Eigen/src/Geometry/Hyperplane.h +282 -0
  338. roboticstoolbox/core/Eigen/src/Geometry/OrthoMethods.h +235 -0
  339. roboticstoolbox/core/Eigen/src/Geometry/ParametrizedLine.h +232 -0
  340. roboticstoolbox/core/Eigen/src/Geometry/Quaternion.h +870 -0
  341. roboticstoolbox/core/Eigen/src/Geometry/Rotation2D.h +199 -0
  342. roboticstoolbox/core/Eigen/src/Geometry/RotationBase.h +206 -0
  343. roboticstoolbox/core/Eigen/src/Geometry/Scaling.h +188 -0
  344. roboticstoolbox/core/Eigen/src/Geometry/Transform.h +1563 -0
  345. roboticstoolbox/core/Eigen/src/Geometry/Translation.h +202 -0
  346. roboticstoolbox/core/Eigen/src/Geometry/Umeyama.h +166 -0
  347. roboticstoolbox/core/Eigen/src/Geometry/arch/Geometry_SIMD.h +168 -0
  348. roboticstoolbox/core/Eigen/src/Householder/BlockHouseholder.h +110 -0
  349. roboticstoolbox/core/Eigen/src/Householder/Householder.h +176 -0
  350. roboticstoolbox/core/Eigen/src/Householder/HouseholderSequence.h +545 -0
  351. roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h +226 -0
  352. roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h +212 -0
  353. roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h +229 -0
  354. roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h +394 -0
  355. roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h +453 -0
  356. roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h +444 -0
  357. roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h +198 -0
  358. roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h +117 -0
  359. roboticstoolbox/core/Eigen/src/Jacobi/Jacobi.h +483 -0
  360. roboticstoolbox/core/Eigen/src/KLUSupport/KLUSupport.h +358 -0
  361. roboticstoolbox/core/Eigen/src/LU/Determinant.h +117 -0
  362. roboticstoolbox/core/Eigen/src/LU/FullPivLU.h +877 -0
  363. roboticstoolbox/core/Eigen/src/LU/InverseImpl.h +432 -0
  364. roboticstoolbox/core/Eigen/src/LU/PartialPivLU.h +624 -0
  365. roboticstoolbox/core/Eigen/src/LU/PartialPivLU_LAPACKE.h +83 -0
  366. roboticstoolbox/core/Eigen/src/LU/arch/InverseSize4.h +351 -0
  367. roboticstoolbox/core/Eigen/src/MetisSupport/MetisSupport.h +137 -0
  368. roboticstoolbox/core/Eigen/src/OrderingMethods/Amd.h +435 -0
  369. roboticstoolbox/core/Eigen/src/OrderingMethods/Eigen_Colamd.h +1863 -0
  370. roboticstoolbox/core/Eigen/src/OrderingMethods/Ordering.h +153 -0
  371. roboticstoolbox/core/Eigen/src/PaStiXSupport/PaStiXSupport.h +678 -0
  372. roboticstoolbox/core/Eigen/src/PardisoSupport/PardisoSupport.h +545 -0
  373. roboticstoolbox/core/Eigen/src/QR/ColPivHouseholderQR.h +674 -0
  374. roboticstoolbox/core/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h +97 -0
  375. roboticstoolbox/core/Eigen/src/QR/CompleteOrthogonalDecomposition.h +635 -0
  376. roboticstoolbox/core/Eigen/src/QR/FullPivHouseholderQR.h +713 -0
  377. roboticstoolbox/core/Eigen/src/QR/HouseholderQR.h +434 -0
  378. roboticstoolbox/core/Eigen/src/QR/HouseholderQR_LAPACKE.h +68 -0
  379. roboticstoolbox/core/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h +335 -0
  380. roboticstoolbox/core/Eigen/src/SVD/BDCSVD.h +1366 -0
  381. roboticstoolbox/core/Eigen/src/SVD/JacobiSVD.h +812 -0
  382. roboticstoolbox/core/Eigen/src/SVD/JacobiSVD_LAPACKE.h +91 -0
  383. roboticstoolbox/core/Eigen/src/SVD/SVDBase.h +376 -0
  384. roboticstoolbox/core/Eigen/src/SVD/UpperBidiagonalization.h +414 -0
  385. roboticstoolbox/core/Eigen/src/SparseCholesky/SimplicialCholesky.h +697 -0
  386. roboticstoolbox/core/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h +174 -0
  387. roboticstoolbox/core/Eigen/src/SparseCore/AmbiVector.h +378 -0
  388. roboticstoolbox/core/Eigen/src/SparseCore/CompressedStorage.h +274 -0
  389. roboticstoolbox/core/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h +352 -0
  390. roboticstoolbox/core/Eigen/src/SparseCore/MappedSparseMatrix.h +67 -0
  391. roboticstoolbox/core/Eigen/src/SparseCore/SparseAssign.h +270 -0
  392. roboticstoolbox/core/Eigen/src/SparseCore/SparseBlock.h +571 -0
  393. roboticstoolbox/core/Eigen/src/SparseCore/SparseColEtree.h +206 -0
  394. roboticstoolbox/core/Eigen/src/SparseCore/SparseCompressedBase.h +370 -0
  395. roboticstoolbox/core/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +722 -0
  396. roboticstoolbox/core/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +150 -0
  397. roboticstoolbox/core/Eigen/src/SparseCore/SparseDenseProduct.h +342 -0
  398. roboticstoolbox/core/Eigen/src/SparseCore/SparseDiagonalProduct.h +138 -0
  399. roboticstoolbox/core/Eigen/src/SparseCore/SparseDot.h +98 -0
  400. roboticstoolbox/core/Eigen/src/SparseCore/SparseFuzzy.h +29 -0
  401. roboticstoolbox/core/Eigen/src/SparseCore/SparseMap.h +305 -0
  402. roboticstoolbox/core/Eigen/src/SparseCore/SparseMatrix.h +1518 -0
  403. roboticstoolbox/core/Eigen/src/SparseCore/SparseMatrixBase.h +398 -0
  404. roboticstoolbox/core/Eigen/src/SparseCore/SparsePermutation.h +178 -0
  405. roboticstoolbox/core/Eigen/src/SparseCore/SparseProduct.h +181 -0
  406. roboticstoolbox/core/Eigen/src/SparseCore/SparseRedux.h +49 -0
  407. roboticstoolbox/core/Eigen/src/SparseCore/SparseRef.h +397 -0
  408. roboticstoolbox/core/Eigen/src/SparseCore/SparseSelfAdjointView.h +659 -0
  409. roboticstoolbox/core/Eigen/src/SparseCore/SparseSolverBase.h +124 -0
  410. roboticstoolbox/core/Eigen/src/SparseCore/SparseSparseProductWithPruning.h +198 -0
  411. roboticstoolbox/core/Eigen/src/SparseCore/SparseTranspose.h +92 -0
  412. roboticstoolbox/core/Eigen/src/SparseCore/SparseTriangularView.h +189 -0
  413. roboticstoolbox/core/Eigen/src/SparseCore/SparseUtil.h +186 -0
  414. roboticstoolbox/core/Eigen/src/SparseCore/SparseVector.h +478 -0
  415. roboticstoolbox/core/Eigen/src/SparseCore/SparseView.h +254 -0
  416. roboticstoolbox/core/Eigen/src/SparseCore/TriangularSolver.h +315 -0
  417. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU.h +923 -0
  418. roboticstoolbox/core/Eigen/src/SparseLU/SparseLUImpl.h +66 -0
  419. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_Memory.h +226 -0
  420. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_Structs.h +110 -0
  421. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h +375 -0
  422. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_Utils.h +80 -0
  423. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_column_bmod.h +181 -0
  424. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_column_dfs.h +179 -0
  425. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h +107 -0
  426. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_gemm_kernel.h +280 -0
  427. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h +126 -0
  428. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_kernel_bmod.h +130 -0
  429. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_panel_bmod.h +223 -0
  430. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_panel_dfs.h +258 -0
  431. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_pivotL.h +137 -0
  432. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_pruneL.h +136 -0
  433. roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_relax_snode.h +83 -0
  434. roboticstoolbox/core/Eigen/src/SparseQR/SparseQR.h +758 -0
  435. roboticstoolbox/core/Eigen/src/StlSupport/StdDeque.h +116 -0
  436. roboticstoolbox/core/Eigen/src/StlSupport/StdList.h +106 -0
  437. roboticstoolbox/core/Eigen/src/StlSupport/StdVector.h +131 -0
  438. roboticstoolbox/core/Eigen/src/StlSupport/details.h +84 -0
  439. roboticstoolbox/core/Eigen/src/SuperLUSupport/SuperLUSupport.h +1025 -0
  440. roboticstoolbox/core/Eigen/src/UmfPackSupport/UmfPackSupport.h +642 -0
  441. roboticstoolbox/core/Eigen/src/misc/Image.h +82 -0
  442. roboticstoolbox/core/Eigen/src/misc/Kernel.h +79 -0
  443. roboticstoolbox/core/Eigen/src/misc/RealSvd2x2.h +55 -0
  444. roboticstoolbox/core/Eigen/src/misc/blas.h +440 -0
  445. roboticstoolbox/core/Eigen/src/misc/lapack.h +152 -0
  446. roboticstoolbox/core/Eigen/src/misc/lapacke.h +16292 -0
  447. roboticstoolbox/core/Eigen/src/misc/lapacke_mangling.h +17 -0
  448. roboticstoolbox/core/Eigen/src/plugins/ArrayCwiseBinaryOps.h +358 -0
  449. roboticstoolbox/core/Eigen/src/plugins/ArrayCwiseUnaryOps.h +696 -0
  450. roboticstoolbox/core/Eigen/src/plugins/BlockMethods.h +1442 -0
  451. roboticstoolbox/core/Eigen/src/plugins/CommonCwiseBinaryOps.h +115 -0
  452. roboticstoolbox/core/Eigen/src/plugins/CommonCwiseUnaryOps.h +177 -0
  453. roboticstoolbox/core/Eigen/src/plugins/IndexedViewMethods.h +262 -0
  454. roboticstoolbox/core/Eigen/src/plugins/MatrixCwiseBinaryOps.h +152 -0
  455. roboticstoolbox/core/Eigen/src/plugins/MatrixCwiseUnaryOps.h +95 -0
  456. roboticstoolbox/core/Eigen/src/plugins/ReshapedMethods.h +149 -0
  457. roboticstoolbox/core/fknm.cpp +1557 -0
  458. roboticstoolbox/core/fknm.h +55 -0
  459. roboticstoolbox/core/frne.c +351 -0
  460. roboticstoolbox/core/frne.h +96 -0
  461. roboticstoolbox/core/ik.cpp +301 -0
  462. roboticstoolbox/core/ik.h +59 -0
  463. roboticstoolbox/core/linalg.cpp +316 -0
  464. roboticstoolbox/core/linalg.h +64 -0
  465. roboticstoolbox/core/methods.cpp +372 -0
  466. roboticstoolbox/core/methods.h +32 -0
  467. roboticstoolbox/core/ne.c +493 -0
  468. roboticstoolbox/core/structs.cpp +24 -0
  469. roboticstoolbox/core/structs.h +62 -0
  470. roboticstoolbox/core/vmath.c +163 -0
  471. roboticstoolbox/core/vmath.h +32 -0
  472. roboticstoolbox/fknm.cp313-win_amd64.pyd +0 -0
  473. roboticstoolbox/frne.cp313-win_amd64.pyd +0 -0
  474. roboticstoolbox/mobile/Animations.py +485 -0
  475. roboticstoolbox/mobile/Bug2.py +455 -0
  476. roboticstoolbox/mobile/CurvaturePolyPlanner.py +179 -0
  477. roboticstoolbox/mobile/DistanceTransformPlanner.py +395 -0
  478. roboticstoolbox/mobile/DstarPlanner.py +591 -0
  479. roboticstoolbox/mobile/DubinsPlanner.py +474 -0
  480. roboticstoolbox/mobile/EKF.py +1617 -0
  481. roboticstoolbox/mobile/LatticePlanner.py +419 -0
  482. roboticstoolbox/mobile/OccGrid.py +613 -0
  483. roboticstoolbox/mobile/PRMPlanner.py +348 -0
  484. roboticstoolbox/mobile/ParticleFilter.py +706 -0
  485. roboticstoolbox/mobile/PlannerBase.py +1009 -0
  486. roboticstoolbox/mobile/PoseGraph.py +544 -0
  487. roboticstoolbox/mobile/QuinticPolyPlanner.py +349 -0
  488. roboticstoolbox/mobile/RRTPlanner.py +359 -0
  489. roboticstoolbox/mobile/ReedsSheppPlanner.py +545 -0
  490. roboticstoolbox/mobile/Vehicle.py +1909 -0
  491. roboticstoolbox/mobile/__init__.py +193 -0
  492. roboticstoolbox/mobile/drivers.py +390 -0
  493. roboticstoolbox/mobile/landmarkmap.py +181 -0
  494. roboticstoolbox/mobile/sensors.py +771 -0
  495. roboticstoolbox/models/DH/AL5D.py +121 -0
  496. roboticstoolbox/models/DH/Ball.py +87 -0
  497. roboticstoolbox/models/DH/Baxter.py +91 -0
  498. roboticstoolbox/models/DH/Cobra600.py +63 -0
  499. roboticstoolbox/models/DH/Coil.py +80 -0
  500. roboticstoolbox/models/DH/Hyper.py +83 -0
  501. roboticstoolbox/models/DH/Hyper3d.py +85 -0
  502. roboticstoolbox/models/DH/IRB140.py +159 -0
  503. roboticstoolbox/models/DH/Jaco.py +102 -0
  504. roboticstoolbox/models/DH/KR5.py +112 -0
  505. roboticstoolbox/models/DH/LWR4.py +85 -0
  506. roboticstoolbox/models/DH/Mico.py +102 -0
  507. roboticstoolbox/models/DH/Orion5.py +91 -0
  508. roboticstoolbox/models/DH/P8.py +80 -0
  509. roboticstoolbox/models/DH/Panda.py +178 -0
  510. roboticstoolbox/models/DH/Planar2.py +69 -0
  511. roboticstoolbox/models/DH/Planar3.py +51 -0
  512. roboticstoolbox/models/DH/Puma560.py +326 -0
  513. roboticstoolbox/models/DH/README.md +216 -0
  514. roboticstoolbox/models/DH/Sawyer.py +85 -0
  515. roboticstoolbox/models/DH/Stanford.py +147 -0
  516. roboticstoolbox/models/DH/TwoLink.py +109 -0
  517. roboticstoolbox/models/DH/UR10.py +124 -0
  518. roboticstoolbox/models/DH/UR3.py +98 -0
  519. roboticstoolbox/models/DH/UR5.py +98 -0
  520. roboticstoolbox/models/DH/Uprighttl.py +24 -0
  521. roboticstoolbox/models/DH/__init__.py +52 -0
  522. roboticstoolbox/models/ETS/Frankie.py +90 -0
  523. roboticstoolbox/models/ETS/GenericSeven.py +54 -0
  524. roboticstoolbox/models/ETS/Omni.py +74 -0
  525. roboticstoolbox/models/ETS/Panda.py +69 -0
  526. roboticstoolbox/models/ETS/Planar2.py +49 -0
  527. roboticstoolbox/models/ETS/Planar_Y.py +65 -0
  528. roboticstoolbox/models/ETS/Puma560.py +69 -0
  529. roboticstoolbox/models/ETS/XYPanda.py +84 -0
  530. roboticstoolbox/models/ETS/__init__.py +20 -0
  531. roboticstoolbox/models/README.md +9 -0
  532. roboticstoolbox/models/URDF/AL5D.py +54 -0
  533. roboticstoolbox/models/URDF/Fetch.py +70 -0
  534. roboticstoolbox/models/URDF/FetchCamera.py +71 -0
  535. roboticstoolbox/models/URDF/Frankie.py +75 -0
  536. roboticstoolbox/models/URDF/FrankieOmni.py +94 -0
  537. roboticstoolbox/models/URDF/KinovaGen3.py +71 -0
  538. roboticstoolbox/models/URDF/LBR.py +59 -0
  539. roboticstoolbox/models/URDF/Mico.py +68 -0
  540. roboticstoolbox/models/URDF/PR2.py +64 -0
  541. roboticstoolbox/models/URDF/Panda.py +67 -0
  542. roboticstoolbox/models/URDF/Puma560.py +97 -0
  543. roboticstoolbox/models/URDF/UR10.py +53 -0
  544. roboticstoolbox/models/URDF/UR3.py +53 -0
  545. roboticstoolbox/models/URDF/UR5.py +74 -0
  546. roboticstoolbox/models/URDF/Valkyrie.py +84 -0
  547. roboticstoolbox/models/URDF/YuMi.py +109 -0
  548. roboticstoolbox/models/URDF/__init__.py +53 -0
  549. roboticstoolbox/models/URDF/px100.py +56 -0
  550. roboticstoolbox/models/URDF/px150.py +56 -0
  551. roboticstoolbox/models/URDF/rx150.py +56 -0
  552. roboticstoolbox/models/URDF/rx200.py +56 -0
  553. roboticstoolbox/models/URDF/vx300.py +56 -0
  554. roboticstoolbox/models/URDF/vx300s.py +56 -0
  555. roboticstoolbox/models/URDF/wx200.py +56 -0
  556. roboticstoolbox/models/URDF/wx250.py +56 -0
  557. roboticstoolbox/models/URDF/wx250s.py +56 -0
  558. roboticstoolbox/models/__init__.py +7 -0
  559. roboticstoolbox/models/list.py +119 -0
  560. roboticstoolbox/robot/BaseRobot.py +3133 -0
  561. roboticstoolbox/robot/DHFactor.py +522 -0
  562. roboticstoolbox/robot/DHLink.py +981 -0
  563. roboticstoolbox/robot/DHRobot.py +2520 -0
  564. roboticstoolbox/robot/Dynamics.py +1620 -0
  565. roboticstoolbox/robot/ELink.py +23 -0
  566. roboticstoolbox/robot/ERobot.py +25 -0
  567. roboticstoolbox/robot/ET.py +1097 -0
  568. roboticstoolbox/robot/ETS.py +3542 -0
  569. roboticstoolbox/robot/Gripper.py +282 -0
  570. roboticstoolbox/robot/IK.py +1522 -0
  571. roboticstoolbox/robot/Link.py +1698 -0
  572. roboticstoolbox/robot/PoERobot.py +348 -0
  573. roboticstoolbox/robot/Robot.py +2100 -0
  574. roboticstoolbox/robot/RobotKinematics.py +1725 -0
  575. roboticstoolbox/robot/RobotProto.py +92 -0
  576. roboticstoolbox/robot/__init__.py +54 -0
  577. roboticstoolbox/tools/DHFactor.py +375 -0
  578. roboticstoolbox/tools/Ticker.py +53 -0
  579. roboticstoolbox/tools/__init__.py +54 -0
  580. roboticstoolbox/tools/data.py +187 -0
  581. roboticstoolbox/tools/jsingu.py +51 -0
  582. roboticstoolbox/tools/null.py +48 -0
  583. roboticstoolbox/tools/numerical.py +96 -0
  584. roboticstoolbox/tools/p_servo.py +106 -0
  585. roboticstoolbox/tools/params.py +11 -0
  586. roboticstoolbox/tools/plot.py +109 -0
  587. roboticstoolbox/tools/trajectory.py +1152 -0
  588. roboticstoolbox/tools/types.py +13 -0
  589. roboticstoolbox/tools/urdf/__init__.py +45 -0
  590. roboticstoolbox/tools/urdf/tests/data/ur5.urdf +341 -0
  591. roboticstoolbox/tools/urdf/tests/test_urdf.py +116 -0
  592. roboticstoolbox/tools/urdf/urdf.py +1976 -0
  593. roboticstoolbox/tools/urdf/utils.py +50 -0
  594. roboticstoolbox/tools/xacro/__init__.py +1148 -0
  595. roboticstoolbox/tools/xacro/cli.py +128 -0
  596. roboticstoolbox/tools/xacro/color.py +66 -0
  597. roboticstoolbox/tools/xacro/tests/CMakeLists.txt +4 -0
  598. roboticstoolbox/tools/xacro/tests/broken.xacro +1 -0
  599. roboticstoolbox/tools/xacro/tests/emoji.xacro +5 -0
  600. roboticstoolbox/tools/xacro/tests/include1.xacro +4 -0
  601. roboticstoolbox/tools/xacro/tests/include1.xml +1 -0
  602. roboticstoolbox/tools/xacro/tests/include2.xacro +4 -0
  603. roboticstoolbox/tools/xacro/tests/include2.xml +1 -0
  604. roboticstoolbox/tools/xacro/tests/robots/README +4 -0
  605. roboticstoolbox/tools/xacro/tests/robots/pr2/base_v0/base.gazebo.xacro +59 -0
  606. roboticstoolbox/tools/xacro/tests/robots/pr2/base_v0/base.transmission.xacro +24 -0
  607. roboticstoolbox/tools/xacro/tests/robots/pr2/base_v0/base.urdf.xacro +264 -0
  608. roboticstoolbox/tools/xacro/tests/robots/pr2/common.xacro +71 -0
  609. roboticstoolbox/tools/xacro/tests/robots/pr2/forearm_v0/forearm.gazebo.xacro +36 -0
  610. roboticstoolbox/tools/xacro/tests/robots/pr2/forearm_v0/forearm.transmission.xacro +20 -0
  611. roboticstoolbox/tools/xacro/tests/robots/pr2/forearm_v0/forearm.urdf.xacro +130 -0
  612. roboticstoolbox/tools/xacro/tests/robots/pr2/gazebo/gazebo.urdf.xacro +24 -0
  613. roboticstoolbox/tools/xacro/tests/robots/pr2/gripper_v0/gripper.gazebo.xacro +288 -0
  614. roboticstoolbox/tools/xacro/tests/robots/pr2/gripper_v0/gripper.transmission.xacro +50 -0
  615. roboticstoolbox/tools/xacro/tests/robots/pr2/gripper_v0/gripper.urdf.xacro +374 -0
  616. roboticstoolbox/tools/xacro/tests/robots/pr2/head_v0/head.gazebo.xacro +16 -0
  617. roboticstoolbox/tools/xacro/tests/robots/pr2/head_v0/head.transmission.xacro +34 -0
  618. roboticstoolbox/tools/xacro/tests/robots/pr2/head_v0/head.urdf.xacro +147 -0
  619. roboticstoolbox/tools/xacro/tests/robots/pr2/materials.urdf.xacro +52 -0
  620. roboticstoolbox/tools/xacro/tests/robots/pr2/pr2.urdf.xacro +157 -0
  621. roboticstoolbox/tools/xacro/tests/robots/pr2/pr2_1.11.4.xml +3781 -0
  622. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/double_stereo_camera.gazebo.xacro +16 -0
  623. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/double_stereo_camera.urdf.xacro +61 -0
  624. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/head_sensor_package.gazebo.xacro +20 -0
  625. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/head_sensor_package.urdf.xacro +63 -0
  626. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/hokuyo_lx30_laser.gazebo.xacro +39 -0
  627. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/hokuyo_lx30_laser.urdf.xacro +27 -0
  628. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/kinect_camera.gazebo.xacro +87 -0
  629. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/kinect_camera.urdf.xacro +55 -0
  630. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/kinect_prosilica_camera.gazebo.xacro +193 -0
  631. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/kinect_prosilica_camera.urdf.xacro +181 -0
  632. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/microstrain_3dmgx2_imu.gazebo.xacro +20 -0
  633. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/microstrain_3dmgx2_imu.urdf.xacro +25 -0
  634. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/projector_wg6802418.gazebo.xacro +31 -0
  635. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/projector_wg6802418.urdf.xacro +42 -0
  636. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/prosilica_gc2450_camera.gazebo.xacro +43 -0
  637. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/prosilica_gc2450_camera.urdf.xacro +49 -0
  638. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/stereo_camera.gazebo.xacro +23 -0
  639. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/stereo_camera.urdf.xacro +71 -0
  640. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/wge100_camera.gazebo.xacro +46 -0
  641. roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/wge100_camera.urdf.xacro +47 -0
  642. roboticstoolbox/tools/xacro/tests/robots/pr2/shoulder_v0/shoulder.gazebo.xacro +40 -0
  643. roboticstoolbox/tools/xacro/tests/robots/pr2/shoulder_v0/shoulder.transmission.xacro +35 -0
  644. roboticstoolbox/tools/xacro/tests/robots/pr2/shoulder_v0/shoulder.urdf.xacro +167 -0
  645. roboticstoolbox/tools/xacro/tests/robots/pr2/tilting_laser_v0/tilting_laser.gazebo.xacro +11 -0
  646. roboticstoolbox/tools/xacro/tests/robots/pr2/tilting_laser_v0/tilting_laser.transmission.xacro +14 -0
  647. roboticstoolbox/tools/xacro/tests/robots/pr2/tilting_laser_v0/tilting_laser.urdf.xacro +60 -0
  648. roboticstoolbox/tools/xacro/tests/robots/pr2/torso_v0/torso.gazebo.xacro +37 -0
  649. roboticstoolbox/tools/xacro/tests/robots/pr2/torso_v0/torso.transmission.xacro +22 -0
  650. roboticstoolbox/tools/xacro/tests/robots/pr2/torso_v0/torso.urdf.xacro +122 -0
  651. roboticstoolbox/tools/xacro/tests/robots/pr2/upper_arm_v0/upper_arm.gazebo.xacro +39 -0
  652. roboticstoolbox/tools/xacro/tests/robots/pr2/upper_arm_v0/upper_arm.transmission.xacro +28 -0
  653. roboticstoolbox/tools/xacro/tests/robots/pr2/upper_arm_v0/upper_arm.urdf.xacro +173 -0
  654. roboticstoolbox/tools/xacro/tests/settings.yaml +9 -0
  655. roboticstoolbox/tools/xacro/tests/subdir/foo.xacro +3 -0
  656. roboticstoolbox/tools/xacro/tests/subdir/include-recursive.xacro +5 -0
  657. roboticstoolbox/tools/xacro/tests/subdir/include1.xml +1 -0
  658. roboticstoolbox/tools/xacro/tests/test_xacro.py +1418 -0
  659. roboticstoolbox/tools/xacro/xmlutils.py +152 -0
  660. roboticstoolbox_python-1.3.0.dist-info/METADATA +552 -0
  661. roboticstoolbox_python-1.3.0.dist-info/RECORD +673 -0
  662. roboticstoolbox_python-1.3.0.dist-info/WHEEL +5 -0
  663. roboticstoolbox_python-1.3.0.dist-info/entry_points.txt +6 -0
  664. roboticstoolbox_python-1.3.0.dist-info/licenses/LICENSE +21 -0
  665. spatialgeometry/__init__.py +32 -0
  666. spatialgeometry/geom/CollisionShape.py +419 -0
  667. spatialgeometry/geom/SceneGroup.py +26 -0
  668. spatialgeometry/geom/SceneNode.py +315 -0
  669. spatialgeometry/geom/Shape.py +420 -0
  670. spatialgeometry/geom/__init__.py +26 -0
  671. spatialgeometry/scene.py +107 -0
  672. spatialgeometry/tools/__init__.py +0 -0
  673. spatialgeometry/tools/stdout_supress.py +302 -0
@@ -0,0 +1,3133 @@
1
+ #!/usr/bin/env python
2
+
3
+ """
4
+ @author: Jesse Haviland
5
+ @author: Peter Corke
6
+ """
7
+
8
+ # import sys
9
+ from abc import ABC
10
+ from copy import deepcopy
11
+ from functools import lru_cache
12
+ from typing import (
13
+ IO,
14
+ TYPE_CHECKING,
15
+ Any,
16
+ Callable,
17
+ Generic,
18
+ List,
19
+ TypeVar,
20
+ Union,
21
+ Dict,
22
+ Tuple,
23
+ Set,
24
+ )
25
+
26
+ from typing_extensions import Literal as L
27
+
28
+ import numpy as np
29
+
30
+ from spatialmath import SE3
31
+ from spatialmath.base.argcheck import (
32
+ getvector,
33
+ getmatrix,
34
+ getunit,
35
+ )
36
+
37
+ from ansitable import ANSITable, Column
38
+ from spatialgeometry import SceneNode
39
+ from roboticstoolbox.backends.Connector import Connector
40
+
41
+ from roboticstoolbox.fknm import Robot_link_T
42
+ import roboticstoolbox as rtb
43
+ from roboticstoolbox.robot.Gripper import Gripper
44
+ from roboticstoolbox.robot.Link import BaseLink, Link
45
+ from roboticstoolbox.robot.ETS import ETS
46
+ from roboticstoolbox.robot.ET import ET
47
+ from roboticstoolbox.robot.Dynamics import DynamicsMixin
48
+ from roboticstoolbox.tools.types import ArrayLike, NDArray
49
+ from roboticstoolbox.tools.params import rtb_get_param
50
+ from roboticstoolbox.backends.PyPlot import PyPlot, PyPlot2
51
+ from roboticstoolbox.backends.PyPlot.EllipsePlot import EllipsePlot
52
+
53
+ if TYPE_CHECKING:
54
+ from matplotlib.cm import Color # pragma nocover
55
+ else:
56
+ Color = None
57
+
58
+ try:
59
+ from matplotlib import colors
60
+ from matplotlib import cm
61
+
62
+ _mpl = True
63
+ except ImportError: # pragma nocover
64
+ cm = str
65
+ pass
66
+
67
+ # _default_backend = None
68
+
69
+ # A generic type variable representing any subclass of BaseLink
70
+ LinkType = TypeVar("LinkType", bound=BaseLink)
71
+
72
+
73
+ class BaseRobot(SceneNode, DynamicsMixin, ABC, Generic[LinkType]):
74
+ def __init__(
75
+ self,
76
+ links: List[LinkType],
77
+ gripper_links: Union[LinkType, List[LinkType], None] = None,
78
+ name: str = "",
79
+ manufacturer: str = "",
80
+ comment: str = "",
81
+ base: Union[NDArray, SE3, None] = None,
82
+ tool: Union[NDArray, SE3, None] = None,
83
+ gravity: ArrayLike = [0, 0, -9.81],
84
+ keywords: Union[List[str], Tuple[str]] = [],
85
+ symbolic: bool = False,
86
+ configs: Union[Dict[str, NDArray], None] = None,
87
+ check_jindex: bool = True,
88
+ ):
89
+ # Initialise the scene node
90
+ SceneNode.__init__(self)
91
+
92
+ # Lets sort out links now
93
+ self._linkdict: Dict[str, LinkType] = {}
94
+
95
+ # Sort links and set self.link, self.n, self.base_link,
96
+ # self.ee_links
97
+ self._sort_links(links, gripper_links, check_jindex)
98
+
99
+ # Fix number of links for gripper links
100
+ self._nlinks = len(links)
101
+
102
+ for gripper in self.grippers:
103
+ self._nlinks += len(gripper.links)
104
+
105
+ # Set the pose of the robot in the world frame
106
+ # in the scenenode object to a numpy array
107
+ if isinstance(base, SE3):
108
+ self._T = base.A
109
+ elif isinstance(base, np.ndarray):
110
+ self._T = base
111
+
112
+ # Set the robot tool transform
113
+ if isinstance(tool, SE3):
114
+ self._tool = tool.A
115
+ elif isinstance(tool, np.ndarray):
116
+ self._tool = tool
117
+ else:
118
+ self._tool = np.eye(4)
119
+
120
+ # Set the keywords
121
+ if keywords is not None and not isinstance(keywords, (tuple, list)):
122
+ raise TypeError("keywords must be a list or tuple")
123
+ else:
124
+ self._keywords = list(keywords)
125
+
126
+ # Gravity is in the negative-z direction.
127
+ self.gravity = np.array(gravity)
128
+
129
+ # Basic arguments
130
+ self.name = name
131
+ self.manufacturer = manufacturer
132
+ self.comment = comment
133
+ self._symbolic = symbolic
134
+ self._reach = None
135
+ self._hasdynamics = False
136
+ self._hasgeometry = False
137
+ self._hascollision = False
138
+ self._urdf_string = ""
139
+ self._urdf_filepath = ""
140
+
141
+ # Time to checkout the links for geometry information
142
+ for link in self.links:
143
+ # Add link back to robot object
144
+ link._robot = self
145
+
146
+ if link.hasdynamics:
147
+ self._hasdynamics = True
148
+ if link.geometry:
149
+ self._hasgeometry = []
150
+ if link.collision:
151
+ self._hascollision = True
152
+
153
+ if isinstance(link, Link):
154
+ if len(link.geometry) > 0:
155
+ self._hasgeometry = True
156
+
157
+ # Current joint configuraiton, velocity, acceleration
158
+ self.q = np.zeros(self.n)
159
+ self.qd = np.zeros(self.n)
160
+ self.qdd = np.zeros(self.n)
161
+
162
+ # The current control mode of the robot
163
+ self.control_mode = "v"
164
+
165
+ # Set up named configuration property
166
+ if configs is None:
167
+ configs = dict()
168
+ self._configs = configs
169
+
170
+ # A flag for watching dynamics properties
171
+ self._dynchanged = False
172
+
173
+ # Set up qlim
174
+ qlim = np.zeros((2, self.n))
175
+ j = 0
176
+
177
+ for i in range(len(self.links)):
178
+ if self.links[i].isjoint:
179
+ qlim[:, j] = self.links[i].qlim
180
+ j += 1
181
+ self._qlim = qlim
182
+
183
+ self._valid_qlim = False
184
+ for i in range(self.n):
185
+ if any(qlim[:, i] != 0) and not any(np.isnan(qlim[:, i])):
186
+ self._valid_qlim = True
187
+
188
+ # SceneNode, set a reference to the first link
189
+ self.scene_children = [self.links[0]] # type: ignore
190
+
191
+ self._default_backend = None
192
+ self._active_plot_env = None
193
+
194
+ # --------------------------------------------------------------------- #
195
+ # --------- Private Methods ------------------------------------------- #
196
+ # --------------------------------------------------------------------- #
197
+
198
+ def _sort_links(
199
+ self,
200
+ links: List[LinkType],
201
+ gripper_links: Union[LinkType, List[LinkType], None],
202
+ check_jindex: bool,
203
+ ):
204
+ """
205
+ This method does several things for setting up the links of a robot
206
+
207
+ - Gives each link a unique name if it doesn't have one
208
+ - Assigns each link a parent if it doesn't have one
209
+ - Finds and sets the base link
210
+ - Finds and sets the ee links
211
+ - sets the jindices
212
+ - sets n
213
+ - sets links
214
+
215
+ """
216
+
217
+ # The ordered links
218
+ orlinks: List[LinkType] = []
219
+
220
+ # The end-effector links
221
+ self._ee_links: List[LinkType] = []
222
+
223
+ # Check all the incoming Link objects
224
+ n: int = 0
225
+
226
+ # Make sure each link has a name
227
+ # ------------------------------
228
+ for k, link in enumerate(links):
229
+ if not isinstance(link, BaseLink):
230
+ raise TypeError("links should all be Link subclass")
231
+
232
+ # If link has no name, give it one
233
+ if link.name is None or link.name == "":
234
+ link.name = f"link-{k}"
235
+
236
+ link.number = k + 1
237
+
238
+ # Put it in the link dictionary, check for duplicates
239
+ if link.name in self._linkdict:
240
+ raise ValueError(f"link name {link.name} is not unique")
241
+
242
+ self._linkdict[link.name] = link
243
+
244
+ if link.isjoint:
245
+ n += 1
246
+
247
+ # Resolve parents given by name, within the context of
248
+ # this set of links
249
+ # ----------------------------------------------------
250
+ for link in links:
251
+ if link.parent is None and link.parent_name is not None:
252
+ link.parent = self._linkdict[link.parent_name]
253
+
254
+ if all([link.parent is None for link in links]):
255
+ # No parent links were given, assume they are sequential
256
+ for i in range(len(links) - 1):
257
+ # li = links[i]
258
+ links[i + 1].parent = links[i]
259
+
260
+ # Set the base link
261
+ # -----------------
262
+ for link in links:
263
+ # Is this a base link?
264
+
265
+ if isinstance(link.parent, BaseLink):
266
+ # Update children of this link's parent
267
+ link.parent._children.append(link)
268
+ else:
269
+ try:
270
+ if self._base_link is not None:
271
+ raise ValueError("Multiple base links")
272
+ except AttributeError:
273
+ pass
274
+
275
+ self._base_link = link
276
+
277
+ if not hasattr(self, "_base_link"):
278
+ raise ValueError(
279
+ "Invalid link configuration provided, must have a base link"
280
+ )
281
+
282
+ # Scene node, set links between the links
283
+ # ---------------------------------------
284
+ for link in links:
285
+ if isinstance(link.parent, BaseLink):
286
+ link.scene_parent = link.parent
287
+
288
+ # Set up the gripper, make a list containing the root of all
289
+ # grippers
290
+ # ----------------------------------------------------------
291
+ if gripper_links is None:
292
+ gripper_links = []
293
+
294
+ if not isinstance(gripper_links, list):
295
+ gripper_links = [gripper_links]
296
+
297
+ # An empty list to hold all grippers
298
+ self._grippers = []
299
+
300
+ # Make a gripper object for each gripper
301
+ for link in gripper_links:
302
+ g_links = self.dfs_links(link)
303
+
304
+ # Remove gripper links from the robot
305
+ for g_link in g_links:
306
+ # print(g_link)
307
+ links.remove(g_link)
308
+
309
+ # Save the gripper object
310
+ self._grippers.append(Gripper(g_links, name=link.name))
311
+
312
+ # Subtract the n of the grippers from the n of the robot
313
+ for gripper in self._grippers:
314
+ n -= gripper.n
315
+
316
+ # Set the ee links
317
+ # ----------------
318
+ ee_links: List[LinkType] = []
319
+
320
+ if len(gripper_links) == 0:
321
+ for link in links:
322
+ # Is this a leaf node? and do we not have any grippers
323
+ if link.children is None or len(link.children) == 0:
324
+ # No children, must be an end-effector
325
+ ee_links.append(link)
326
+ else:
327
+ for link in gripper_links:
328
+ # Use the passed in value
329
+ if link.parent is not None:
330
+ ee_links.append(link.parent)
331
+
332
+ self._ee_links = ee_links
333
+
334
+ # Assign the joint indices and sort the links
335
+ # -------------------------------------------
336
+ if all([link.jindex is None or link.ets._auto_jindex for link in links]):
337
+ # No joints have an index
338
+ jindex = [0] # "mutable integer" hack
339
+
340
+ def visit_link(link, jindex):
341
+ # if it's a joint, assign it a jindex and increment it
342
+ if link.isjoint and link in links:
343
+ link.jindex = jindex[0]
344
+ jindex[0] += 1
345
+
346
+ if link in links:
347
+ orlinks.append(link)
348
+
349
+ # visit all links in DFS order
350
+ self.dfs_links(self.base_link, lambda link: visit_link(link, jindex))
351
+
352
+ elif all(
353
+ [
354
+ link.jindex is not None and not link.ets._auto_jindex
355
+ for link in links
356
+ if link.isjoint
357
+ ]
358
+ ):
359
+ # Jindex set on all, check they are unique and contiguous
360
+ if check_jindex:
361
+ jset = set(range(n))
362
+ for link in links:
363
+ if link.isjoint and link.jindex not in jset:
364
+ raise ValueError(
365
+ f"joint index {link.jindex} was repeated or out of range"
366
+ )
367
+ jset -= set([link.jindex])
368
+ if len(jset) > 0: # pragma nocover # is impossible
369
+ raise ValueError(f"joints {jset} were not assigned")
370
+ orlinks = links
371
+ else:
372
+ # must be a mixture of Links with/without jindex
373
+ raise ValueError("all links must have a jindex, or none have a jindex")
374
+
375
+ # Set n
376
+ # -----
377
+ self._n = n
378
+
379
+ # Set links
380
+ # ---------
381
+ self._links = orlinks
382
+
383
+ def dynchanged(self, what: Union[str, None] = None):
384
+ """
385
+ Dynamic parameters have changed
386
+
387
+ Called from a property setter to inform the robot that the cache of
388
+ dynamic parameters is invalid.
389
+
390
+ See Also
391
+ --------
392
+ :func:`roboticstoolbox.Link._listen_dyn`
393
+
394
+ """
395
+
396
+ self._dynchanged = True
397
+ if what != "gravity":
398
+ self._hasdynamics = True
399
+
400
+ # --------------------------------------------------------------------- #
401
+ # --------- Magic Methods --------------------------------------------- #
402
+ # --------------------------------------------------------------------- #
403
+
404
+ def __iter__(self):
405
+ self._iter = 0
406
+ return self
407
+
408
+ def __next__(self) -> LinkType:
409
+ if self._iter < len(self.links):
410
+ link = self[self._iter]
411
+ self._iter += 1
412
+ return link
413
+ else:
414
+ raise StopIteration
415
+
416
+ def __getitem__(self, i: Union[int, str]) -> LinkType:
417
+ """
418
+ Get link
419
+
420
+ This also supports iterating over each link in the robot object,
421
+ from the base to the tool.
422
+
423
+ Parameters
424
+ ----------
425
+ i
426
+ link number or name
427
+
428
+ Returns
429
+ -------
430
+ link
431
+ i'th link or named link
432
+
433
+ Examples
434
+ --------
435
+ .. runblock:: pycon
436
+ >>> import roboticstoolbox as rtb
437
+ >>> robot = rtb.models.DH.Puma560()
438
+ >>> print(robot[1]) # print the 2nd link
439
+ >>> print([link.a for link in robot]) # print all the a_j values
440
+
441
+ Notes
442
+ -----
443
+ ``Robot`` supports link lookup by name,
444
+ eg. ``robot['link1']``
445
+
446
+ """
447
+
448
+ if isinstance(i, int):
449
+ return self._links[i]
450
+ else:
451
+ return self._linkdict[i]
452
+
453
+ def __str__(self) -> str:
454
+ """
455
+ Pretty prints the ETS Model of the robot.
456
+
457
+ Returns
458
+ -------
459
+ str
460
+ Pretty print of the robot model
461
+
462
+ Notes
463
+ -----
464
+ - Constant links are shown in blue.
465
+ - End-effector links are prefixed with an @
466
+ - Angles in degrees
467
+ - The robot base frame is denoted as ``BASE`` and is equal to the
468
+ robot's ``base`` attribute.
469
+
470
+ """
471
+
472
+ unicode = rtb_get_param("unicode")
473
+ border = "thin" if unicode else "ascii"
474
+
475
+ table = ANSITable(
476
+ Column("link", headalign="^", colalign=">"),
477
+ Column("link", headalign="^", colalign="<"),
478
+ Column("joint", headalign="^", colalign=">"),
479
+ Column("parent", headalign="^", colalign="<"),
480
+ Column("ETS: parent to link", headalign="^", colalign="<"),
481
+ border=border,
482
+ )
483
+
484
+ for k, link in enumerate(self.links):
485
+ color = "" if link.isjoint else "<<blue>>"
486
+ ee = "@" if link in self.ee_links else ""
487
+ ets = link.ets
488
+ if link.parent is None:
489
+ parent_name = "BASE"
490
+ else:
491
+ parent_name = link.parent.name
492
+ s = ets.__str__(f"q{link.jindex}")
493
+ # if len(s) > 0:
494
+ # op = " \u2295 " if unicode else " * " # \oplus
495
+ # s = op + s
496
+
497
+ if link.isjoint:
498
+ jname = link.jindex
499
+ else:
500
+ jname = ""
501
+ table.row(
502
+ # link.jindex,
503
+ k,
504
+ color + ee + link.name,
505
+ jname,
506
+ parent_name,
507
+ f"{s}",
508
+ )
509
+
510
+ classname = "ERobot"
511
+
512
+ s = f"{classname}: {self.name}"
513
+ if self.manufacturer is not None and len(self.manufacturer) > 0:
514
+ s += f" (by {self.manufacturer})"
515
+ s += f", {self.n} joints ({self.structure})"
516
+ if len(self.grippers) > 0:
517
+ s += (
518
+ f", {len(self.grippers)} gripper{'s' if len(self.grippers) > 1 else ''}"
519
+ )
520
+ if self.nbranches > 1:
521
+ s += f", {self.nbranches} branches"
522
+ if self._hasdynamics:
523
+ s += ", dynamics"
524
+ if any([len(link.geometry) > 0 for link in self.links]):
525
+ s += ", geometry"
526
+ if any([len(link.collision) > 0 for link in self.links]):
527
+ s += ", collision"
528
+ s += "\n"
529
+
530
+ s += str(table)
531
+ s += self.configurations_str(border=border)
532
+
533
+ return s
534
+
535
+ def __repr__(self) -> str:
536
+ return str(self)
537
+
538
+ # --------------------------------------------------------------------- #
539
+ # --------- Properties ------------------------------------------------ #
540
+ # --------------------------------------------------------------------- #
541
+
542
+ @property
543
+ def links(self) -> List[LinkType]:
544
+ """
545
+ Robot links
546
+
547
+ Returns
548
+ -------
549
+ links
550
+ A list of link objects
551
+
552
+ Notes
553
+ -----
554
+ It is probably more concise to index the robot object rather
555
+ than the list of links, ie. the following are equivalent:
556
+ - ``robot.links[i]``
557
+ - ``robot[i]``
558
+
559
+ """
560
+
561
+ return self._links
562
+
563
+ @property
564
+ def link_dict(self) -> Dict[str, LinkType]:
565
+ return self._linkdict
566
+
567
+ @property
568
+ def grippers(self) -> List[Gripper]:
569
+ """
570
+ Grippers attached to the robot
571
+
572
+ Returns
573
+ -------
574
+ grippers
575
+ A list of grippers
576
+
577
+ """
578
+
579
+ return self._grippers
580
+
581
+ @property
582
+ def base_link(self) -> LinkType:
583
+ """
584
+ Get the robot base link
585
+
586
+ - ``robot.base_link`` is the robot base link
587
+
588
+ Returns
589
+ -------
590
+ base_link
591
+ the first link in the robot tree
592
+
593
+ """
594
+
595
+ return self._base_link
596
+
597
+ @property
598
+ def ee_links(self) -> List[LinkType]:
599
+ return self._ee_links
600
+
601
+ @property
602
+ def n(self) -> int:
603
+ """
604
+ Number of joints
605
+
606
+ Returns
607
+ -------
608
+ n
609
+ Number of joints
610
+
611
+ Examples
612
+ --------
613
+ .. runblock:: pycon
614
+ >>> import roboticstoolbox as rtb
615
+ >>> robot = rtb.models.DH.Puma560()
616
+ >>> robot.n
617
+
618
+ See Also
619
+ --------
620
+ :func:`nlinks`
621
+ :func:`nbranches`
622
+
623
+ """
624
+
625
+ return self._n
626
+
627
+ @property
628
+ def nlinks(self):
629
+ """
630
+ Number of links
631
+
632
+ The returned number is the total of both variable joints and
633
+ static links
634
+
635
+ Returns
636
+ -------
637
+ nlinks
638
+ Number of links
639
+
640
+ Examples
641
+ --------
642
+
643
+ .. runblock:: pycon
644
+ >>> import roboticstoolbox as rtb
645
+ >>> robot = rtb.models.DH.Puma560()
646
+ >>> robot.nlinks
647
+
648
+ See Also
649
+ --------
650
+ :func:`n`
651
+ :func:`nbranches`
652
+
653
+ """
654
+
655
+ return self._nlinks
656
+
657
+ @property
658
+ def nbranches(self) -> int:
659
+ """
660
+ Number of branches
661
+
662
+ Number of branches in this robot. Computed as the number of links with
663
+ zero children
664
+
665
+ Returns
666
+ -------
667
+ nbranches
668
+ number of branches in the robot's kinematic tree
669
+
670
+ Examples
671
+ --------
672
+
673
+ .. runblock:: pycon
674
+ >>> import roboticstoolbox as rtb
675
+ >>> robot = rtb.models.ETS.Panda()
676
+ >>> robot.nbranches
677
+
678
+ See Also
679
+ --------
680
+ :func:`n`
681
+ :func:`nlinks`
682
+ """
683
+
684
+ return sum([link.nchildren == 0 for link in self.links]) + len(self.grippers)
685
+
686
+ # --------------------------------------------------------------------- #
687
+
688
+ @property
689
+ def name(self) -> str:
690
+ """
691
+ Get/set robot name
692
+
693
+ - ``robot.name`` is the robot name
694
+ - ``robot.name = ...`` checks and sets the robot name
695
+
696
+ Parameters
697
+ ----------
698
+ name
699
+ the new robot name
700
+
701
+ Returns
702
+ -------
703
+ name
704
+ the current robot name
705
+
706
+ """
707
+ return self._name
708
+
709
+ @name.setter
710
+ def name(self, name_new: str):
711
+ self._name = name_new
712
+
713
+ @property
714
+ def comment(self) -> str:
715
+ """
716
+ Get/set robot comment
717
+
718
+ - ``robot.comment`` is the robot comment
719
+ - ``robot.comment = ...`` checks and sets the robot comment
720
+
721
+ Parameters
722
+ ----------
723
+ name
724
+ the new robot comment
725
+
726
+ Returns
727
+ -------
728
+ comment
729
+ robot comment
730
+
731
+ """
732
+ return self._comment
733
+
734
+ @comment.setter
735
+ def comment(self, comment_new: str):
736
+ self._comment = comment_new
737
+
738
+ @property
739
+ def manufacturer(self):
740
+ """
741
+ Get/set robot manufacturer's name
742
+
743
+ - ``robot.manufacturer`` is the robot manufacturer's name
744
+ - ``robot.manufacturer = ...`` checks and sets the manufacturer's name
745
+
746
+ Returns
747
+ -------
748
+ manufacturer
749
+ robot manufacturer's name
750
+
751
+ """
752
+ return self._manufacturer
753
+
754
+ @manufacturer.setter
755
+ def manufacturer(self, manufacturer_new):
756
+ self._manufacturer = manufacturer_new
757
+
758
+ @property
759
+ def configs(self) -> Dict[str, NDArray]:
760
+ return self._configs
761
+
762
+ @property
763
+ def keywords(self) -> List[str]:
764
+ return self._keywords
765
+
766
+ @property
767
+ def symbolic(self) -> bool:
768
+ return self._symbolic
769
+
770
+ @property
771
+ def hasdynamics(self):
772
+ """
773
+ Robot has dynamic parameters
774
+
775
+ Returns
776
+ -------
777
+ hasdynamics
778
+ Robot has dynamic parameters
779
+
780
+ At least one link has associated dynamic parameters.
781
+
782
+ Examples
783
+ --------
784
+
785
+ .. runblock:: pycon
786
+ >>> import roboticstoolbox as rtb
787
+ >>> robot = rtb.models.DH.Puma560()
788
+ >>> robot.hasdynamics:
789
+
790
+ """
791
+
792
+ return self._hasdynamics
793
+
794
+ @property
795
+ def hasgeometry(self):
796
+ """
797
+ Robot has geometry model
798
+
799
+ At least one link has associated mesh to describe its shape.
800
+
801
+ Returns
802
+ -------
803
+ hasgeometry
804
+ Robot has geometry model
805
+
806
+ Examples
807
+ --------
808
+
809
+ .. runblock:: pycon
810
+ >>> import roboticstoolbox as rtb
811
+ >>> robot = rtb.models.DH.Puma560()
812
+ >>> robot.hasgeometry
813
+
814
+ See Also
815
+ --------
816
+ :func:`hascollision`
817
+
818
+ """
819
+
820
+ return self._hasgeometry
821
+
822
+ @property
823
+ def hascollision(self):
824
+ """
825
+ Robot has collision model
826
+
827
+ Returns
828
+ -------
829
+ hascollision
830
+ Robot has collision model
831
+
832
+ At least one link has associated collision model.
833
+
834
+ Examples
835
+ --------
836
+
837
+ .. runblock:: pycon
838
+ >>> import roboticstoolbox as rtb
839
+ >>> robot = rtb.models.DH.Puma560()
840
+ >>> robot.hascollision
841
+
842
+ See Also
843
+ --------
844
+ :func:`hasgeometry`
845
+
846
+ """
847
+
848
+ return self._hascollision
849
+
850
+ @property
851
+ def default_backend(self):
852
+ """
853
+ Get default graphical backend
854
+
855
+ - ``robot.default_backend`` Get the default graphical backend, used when
856
+ no explicit backend is passed to ``Robot.plot``.
857
+ - ``robot.default_backend = ...`` Set the default graphical backend, used when
858
+ no explicit backend is passed to ``Robot.plot``. The default set here will
859
+ be overridden if the particular ``Robot`` subclass cannot support it.
860
+
861
+ Returns
862
+ -------
863
+ default_backend
864
+ backend name
865
+
866
+
867
+ """
868
+ return self._default_backend
869
+
870
+ @default_backend.setter
871
+ def default_backend(self, be):
872
+ self._default_backend = be
873
+
874
+ @property
875
+ def gravity(self) -> NDArray:
876
+ """
877
+ Get/set default gravitational acceleration (Robot superclass)
878
+
879
+ - ``robot.name`` is the default gravitational acceleration
880
+ - ``robot.name = ...`` checks and sets default gravitational
881
+ acceleration
882
+
883
+
884
+ Parameters
885
+ ----------
886
+ gravity
887
+ the new gravitational acceleration for this robot
888
+
889
+ Returns
890
+ -------
891
+ gravity
892
+ gravitational acceleration
893
+
894
+ Notes
895
+ -----
896
+ If the z-axis is upward, out of the Earth, this should be
897
+ a positive number.
898
+
899
+ """
900
+
901
+ return self._gravity
902
+
903
+ @gravity.setter
904
+ def gravity(self, gravity_new: ArrayLike):
905
+ self._gravity = np.array(getvector(gravity_new, 3))
906
+ self.dynchanged()
907
+
908
+ # --------------------------------------------------------------------- #
909
+
910
+ @property
911
+ def q(self) -> NDArray:
912
+ """
913
+ Get/set robot joint configuration
914
+
915
+ - ``robot.q`` is the robot joint configuration
916
+ - ``robot.q = ...`` checks and sets the joint configuration
917
+
918
+ Parameters
919
+ ----------
920
+ q
921
+ the new robot joint configuration
922
+
923
+ Returns
924
+ -------
925
+ q
926
+ robot joint configuration
927
+
928
+ """
929
+
930
+ return self._q
931
+
932
+ @q.setter
933
+ def q(self, q_new: ArrayLike):
934
+ self._q = np.array(getvector(q_new, self.n))
935
+
936
+ @property
937
+ def qd(self) -> NDArray:
938
+ """
939
+ Get/set robot joint velocity
940
+
941
+ - ``robot.qd`` is the robot joint velocity
942
+ - ``robot.qd = ...`` checks and sets the joint velocity
943
+
944
+ Returns
945
+ -------
946
+ qd
947
+ robot joint velocity
948
+
949
+ """
950
+
951
+ return self._qd
952
+
953
+ @qd.setter
954
+ def qd(self, qd_new: ArrayLike):
955
+ self._qd = np.array(getvector(qd_new, self.n))
956
+
957
+ @property
958
+ def qdd(self) -> NDArray:
959
+ """
960
+ Get/set robot joint acceleration
961
+
962
+ - ``robot.qdd`` is the robot joint acceleration
963
+ - ``robot.qdd = ...`` checks and sets the robot joint acceleration
964
+
965
+ Returns
966
+ -------
967
+ qdd
968
+ robot joint acceleration
969
+
970
+
971
+ """
972
+ return self._qdd
973
+
974
+ @qdd.setter
975
+ def qdd(self, qdd_new: ArrayLike):
976
+ self._qdd = np.array(getvector(qdd_new, self.n))
977
+
978
+ @property
979
+ def qlim(self) -> NDArray:
980
+ r"""
981
+ Joint limits
982
+
983
+ Limits are extracted from the link objects. If joints limits are
984
+ not set for:
985
+
986
+ - a revolute joint [-𝜋. 𝜋] is returned
987
+ - a prismatic joint an exception is raised
988
+
989
+ Attributes
990
+ ----------
991
+ qlim
992
+ An array of joints limits (2, n)
993
+
994
+ Raises
995
+ ------
996
+ ValueError
997
+ unset limits for a prismatic joint
998
+
999
+ Returns
1000
+ -------
1001
+ qlim
1002
+ Array of joint limit values
1003
+
1004
+ Examples
1005
+ --------
1006
+ .. runblock:: pycon
1007
+ >>> import roboticstoolbox as rtb
1008
+ >>> robot = rtb.models.DH.Puma560()
1009
+ >>> robot.qlim
1010
+
1011
+ """
1012
+
1013
+ limits = np.zeros((2, self.n))
1014
+ j = 0
1015
+
1016
+ for link in self.links:
1017
+ if link.isrevolute:
1018
+ if (
1019
+ link.qlim is None
1020
+ or link.qlim[0] is None
1021
+ or np.any(np.isnan(link.qlim))
1022
+ ):
1023
+ v = [-np.pi, np.pi]
1024
+ else:
1025
+ v = link.qlim
1026
+ elif link.isprismatic:
1027
+ if link.qlim is None:
1028
+ raise ValueError("Undefined prismatic joint limit")
1029
+ else:
1030
+ v = link.qlim
1031
+ else:
1032
+ # Fixed link
1033
+ continue # pragma nocover
1034
+
1035
+ limits[:, j] = v
1036
+ j += 1
1037
+
1038
+ return limits
1039
+
1040
+ @qlim.setter
1041
+ def qlim(self, new_qlim: ArrayLike):
1042
+ new_qlim = np.array(new_qlim)
1043
+
1044
+ if new_qlim.shape != (2, self.n):
1045
+ raise ValueError("new_qlim must be of shape (2, n)")
1046
+
1047
+ j = 0
1048
+ for link in self.links:
1049
+ if link.isjoint:
1050
+ link.qlim = new_qlim[:, j]
1051
+ j += 1
1052
+
1053
+ @property
1054
+ def structure(self) -> str:
1055
+ """
1056
+ Return the joint structure string
1057
+
1058
+ A string with one letter per joint: ``R`` for a revolute
1059
+ joint, and ``P`` for a prismatic joint.
1060
+
1061
+ Returns
1062
+ -------
1063
+ structure
1064
+ joint configuration string
1065
+
1066
+ Examples
1067
+ --------
1068
+ .. runblock:: pycon
1069
+ >>> import roboticstoolbox as rtb
1070
+ >>> puma = rtb.models.DH.Puma560()
1071
+ >>> puma.structure
1072
+ >>> stanford = rtb.models.DH.Stanford()
1073
+ >>> stanford.structure
1074
+
1075
+ Notes
1076
+ -----
1077
+ Fixed joints, that maintain a constant link relative pose,
1078
+ are not included.
1079
+ ``len(self.structure) == self.n``.
1080
+
1081
+ """
1082
+
1083
+ structure = []
1084
+
1085
+ for link in self.links:
1086
+ if link.isrevolute:
1087
+ structure.append("R")
1088
+ elif link.isprismatic:
1089
+ structure.append("P")
1090
+
1091
+ return "".join(structure)
1092
+
1093
+ @property
1094
+ def prismaticjoints(self) -> List[bool]:
1095
+ """
1096
+ Revolute joints as bool array
1097
+
1098
+ Returns
1099
+ -------
1100
+ prismaticjoints
1101
+ array of joint type, True if prismatic
1102
+
1103
+ Examples
1104
+ --------
1105
+ .. runblock:: pycon
1106
+ >>> import roboticstoolbox as rtb
1107
+ >>> puma = rtb.models.DH.Puma560()
1108
+ >>> puma.prismaticjoints
1109
+ >>> stanford = rtb.models.DH.Stanford()
1110
+ >>> stanford.prismaticjoints
1111
+
1112
+ Notes
1113
+ -----
1114
+ Fixed joints, that maintain a constant link relative pose,
1115
+ are not included.
1116
+
1117
+ See Also
1118
+ --------
1119
+ :func:`Link.isprismatic`
1120
+ :func:`revolutejoints`
1121
+
1122
+ """
1123
+
1124
+ return [link.isprismatic for link in self.links if link.isjoint]
1125
+
1126
+ @property
1127
+ def revolutejoints(self) -> List[bool]:
1128
+ """
1129
+ Revolute joints as bool array
1130
+
1131
+ Returns
1132
+ -------
1133
+ revolutejoints
1134
+ array of joint type, True if revolute
1135
+
1136
+ Examples
1137
+ --------
1138
+ .. runblock:: pycon
1139
+ >>> import roboticstoolbox as rtb
1140
+ >>> puma = rtb.models.DH.Puma560()
1141
+ >>> puma.revolutejoints
1142
+ >>> stanford = rtb.models.DH.Stanford()
1143
+ >>> stanford.revolutejoints
1144
+
1145
+ Notes
1146
+ -----
1147
+ Fixed joints, that maintain a constant link relative pose,
1148
+ are not included.
1149
+
1150
+ See Also
1151
+ --------
1152
+ :func:`Link.isrevolute`
1153
+ :func:`prismaticjoints`
1154
+
1155
+ """
1156
+
1157
+ return [link.isrevolute for link in self.links if link.isjoint]
1158
+
1159
+ @property
1160
+ def control_mode(self) -> str:
1161
+ """
1162
+ Get/set robot control mode
1163
+
1164
+ - ``robot.control_type`` is the robot control mode
1165
+ - ``robot.control_type = ...`` checks and sets the robot control mode
1166
+
1167
+ Parameters
1168
+ ----------
1169
+ control_mode
1170
+ the new robot control mode
1171
+
1172
+ Returns
1173
+ -------
1174
+ control_mode
1175
+ the current robot control mode
1176
+
1177
+ """
1178
+
1179
+ return self._control_mode
1180
+
1181
+ @control_mode.setter
1182
+ def control_mode(self, cn: str):
1183
+ if cn == "p" or cn == "v" or cn == "a":
1184
+ self._control_mode = cn
1185
+ else:
1186
+ raise ValueError("Control type must be one of 'p', 'v', or 'a'")
1187
+
1188
+ # --------------------------------------------------------------------- #
1189
+
1190
+ @property
1191
+ def urdf_string(self) -> str:
1192
+ return self._urdf_string
1193
+
1194
+ @property
1195
+ def urdf_filepath(self) -> str:
1196
+ return self._urdf_filepath
1197
+
1198
+ # --------------------------------------------------------------------- #
1199
+
1200
+ @property
1201
+ def tool(self) -> SE3:
1202
+ """
1203
+ Get/set robot tool transform
1204
+
1205
+ - ``robot.tool`` is the robot tool transform as an SE3 object
1206
+ - ``robot._tool`` is the robot tool transform as a numpy array
1207
+ - ``robot.tool = ...`` checks and sets the robot tool transform
1208
+
1209
+ Parameters
1210
+ ----------
1211
+ tool
1212
+ the new robot tool transform (as an SE(3))
1213
+
1214
+ Returns
1215
+ -------
1216
+ tool
1217
+ robot tool transform
1218
+
1219
+
1220
+
1221
+ """
1222
+ return SE3(self._tool, check=False)
1223
+
1224
+ @tool.setter
1225
+ def tool(self, T: Union[SE3, NDArray]):
1226
+ if isinstance(T, SE3):
1227
+ self._tool = T.A
1228
+ else:
1229
+ self._tool = T
1230
+
1231
+ @property
1232
+ def base(self) -> SE3:
1233
+ """
1234
+ Get/set robot base transform
1235
+
1236
+ - ``robot.base`` is the robot base transform
1237
+ - ``robot.base = ...`` checks and sets the robot base transform
1238
+
1239
+ Parameters
1240
+ ----------
1241
+ base
1242
+ the new robot base transform
1243
+
1244
+ Returns
1245
+ -------
1246
+ base
1247
+ the current robot base transform
1248
+
1249
+ """
1250
+
1251
+ # return a copy, otherwise somebody with
1252
+ # reference to the base can change it
1253
+
1254
+ # This now returns the Scene Node transform
1255
+ # self._T is a copy of SceneNode.__T
1256
+ return SE3(self._T, check=False)
1257
+
1258
+ @base.setter
1259
+ def base(self, T: Union[NDArray, SE3]):
1260
+ if isinstance(self, rtb.Robot):
1261
+ # All 3D robots
1262
+ # Set the SceneNode T
1263
+ if isinstance(T, SE3):
1264
+ self._T = T.A
1265
+ else:
1266
+ self._T = T
1267
+
1268
+ # --------------------------------------------------------------------- #
1269
+
1270
+ @lru_cache(maxsize=32)
1271
+ def get_path(
1272
+ self,
1273
+ end: Union[Gripper, LinkType, str, None] = None,
1274
+ start: Union[Gripper, LinkType, str, None] = None,
1275
+ ) -> Tuple[List[LinkType], int, SE3]:
1276
+ """
1277
+ Find a path from start to end
1278
+
1279
+ Parameters
1280
+ ----------
1281
+ end
1282
+ end-effector or gripper to compute forward kinematics to
1283
+ start
1284
+ name or reference to a base link, defaults to None
1285
+
1286
+ Raises
1287
+ ------
1288
+ ValueError
1289
+ link not known or ambiguous
1290
+
1291
+ Returns
1292
+ -------
1293
+ path
1294
+ the path from start to end
1295
+ n
1296
+ the number of joints in the path
1297
+ T
1298
+ the tool transform present after end
1299
+
1300
+ """
1301
+
1302
+ def search(
1303
+ start,
1304
+ end,
1305
+ explored: Set[Union[LinkType, Link]],
1306
+ path: List[Union[LinkType, Link]],
1307
+ ) -> Union[List[Union[LinkType, Link]], None]:
1308
+ link = self._getlink(start, self.base_link)
1309
+ end = self._getlink(end, self.ee_links[0])
1310
+
1311
+ toplevel = len(path) == 0
1312
+ explored.add(link)
1313
+
1314
+ if link == end:
1315
+ return path
1316
+
1317
+ # unlike regular DFS, the neighbours of the node are its children
1318
+ # and its parent.
1319
+
1320
+ # visit child nodes below start
1321
+ if toplevel:
1322
+ path = [link]
1323
+
1324
+ if link.children is not None:
1325
+ for child in link.children:
1326
+ if child not in explored:
1327
+ path.append(child)
1328
+ p = search(child, end, explored, path)
1329
+ if p is not None:
1330
+ return p
1331
+
1332
+ # We didn't find the node below, keep going up a level, and recursing
1333
+ # down again
1334
+ if toplevel:
1335
+ path = []
1336
+
1337
+ if link.parent is not None:
1338
+ parent = link.parent # go up one level toward the root
1339
+ if parent not in explored:
1340
+ if len(path) == 0:
1341
+ p = search(parent, end, explored, [link])
1342
+ else:
1343
+ path.append(link)
1344
+ p = search(parent, end, explored, path)
1345
+
1346
+ if p is not None and len(p) > 0:
1347
+ return p
1348
+
1349
+ end, start, tool = self._get_limit_links(end=end, start=start)
1350
+
1351
+ path = search(start, end, set(), [])
1352
+
1353
+ if path is None or len(path) == 0:
1354
+ raise ValueError("No path found") # pragma nocover
1355
+ elif path[-1] != end:
1356
+ path.append(end)
1357
+
1358
+ if tool is None:
1359
+ tool = SE3()
1360
+
1361
+ return path, len(path), tool # type: ignore
1362
+
1363
+ @lru_cache(maxsize=32)
1364
+ def _getlink(
1365
+ self,
1366
+ link: Union[LinkType, Gripper, str, None],
1367
+ default: Union[LinkType, Gripper, str, None] = None,
1368
+ ) -> Union[LinkType, Link]:
1369
+ """
1370
+ Validate reference to Link
1371
+
1372
+ ``robot._getlink(link)`` is a validated reference to a Link within
1373
+ the ERobot ``robot``. If ``link`` is:
1374
+
1375
+ - an ``Link`` reference it is validated as belonging to
1376
+ ``robot``.
1377
+ - a string, then it looked up in the robot's link name dictionary, and
1378
+ a Link reference returned.
1379
+
1380
+ Parameters
1381
+ ----------
1382
+ link
1383
+ link
1384
+
1385
+ Raises
1386
+ ------
1387
+ ValueError
1388
+ link does not belong to this ERobot
1389
+ TypeError
1390
+ bad argument
1391
+
1392
+ Returns
1393
+ -------
1394
+ link
1395
+ link reference
1396
+
1397
+ """
1398
+
1399
+ if link is None:
1400
+ link = default
1401
+
1402
+ if isinstance(link, str):
1403
+ if link in self.link_dict:
1404
+ return self.link_dict[link]
1405
+
1406
+ raise ValueError(f"no link named {link}")
1407
+
1408
+ elif isinstance(link, BaseLink):
1409
+ if link in self.links:
1410
+ return link
1411
+ else:
1412
+ for gripper in self.grippers:
1413
+ if link in gripper.links:
1414
+ return link
1415
+
1416
+ raise ValueError("link not in robot links")
1417
+ elif isinstance(link, Gripper):
1418
+ for gripper in self.grippers:
1419
+ if link is gripper:
1420
+ return gripper.links[0]
1421
+
1422
+ raise ValueError("Gripper not in robot")
1423
+ else:
1424
+ raise TypeError("unknown argument")
1425
+
1426
+ def _find_ets(self, start, end, explored, path) -> Union[ETS, None]:
1427
+ """
1428
+ Privade method which will recursively find the ETS of a path
1429
+ see ets()
1430
+ """
1431
+
1432
+ link = self._getlink(start, self.base_link)
1433
+ end = self._getlink(end, self.ee_links[0])
1434
+
1435
+ toplevel = path is None
1436
+ explored.add(link)
1437
+
1438
+ if link == end:
1439
+ return path
1440
+
1441
+ # unlike regular DFS, the neighbours of the node are its children
1442
+ # and its parent.
1443
+
1444
+ # visit child nodes below start
1445
+ if toplevel:
1446
+ path = link.ets
1447
+
1448
+ if link.children is not None:
1449
+ for child in link.children:
1450
+ if child not in explored:
1451
+ p = self._find_ets(child, end, explored, path * child.ets)
1452
+ if p is not None:
1453
+ return p
1454
+
1455
+ # we didn't find the node below, keep going up a level, and recursing
1456
+ # down again
1457
+ if toplevel:
1458
+ path = None
1459
+ if link.parent is not None:
1460
+ parent = link.parent # go up one level toward the root
1461
+ if parent not in explored:
1462
+ if path is None:
1463
+ p = self._find_ets(parent, end, explored, link.ets.inv())
1464
+ else:
1465
+ p = self._find_ets(parent, end, explored, path * link.ets.inv())
1466
+ if p is not None:
1467
+ return p
1468
+
1469
+ def _gripper_ets(self, gripper: Gripper) -> ETS:
1470
+ """
1471
+ Privade method which will find the ETS of a gripper
1472
+
1473
+ """
1474
+
1475
+ return ETS(ET.SE3(gripper.tool))
1476
+
1477
+ @lru_cache(maxsize=32)
1478
+ def _get_limit_links(
1479
+ self,
1480
+ end: Union[Gripper, LinkType, str, None] = None,
1481
+ start: Union[Gripper, LinkType, str, None] = None,
1482
+ ) -> Tuple[LinkType, LinkType, Union[None, SE3]]:
1483
+ """
1484
+ Get and validate an end-effector, and a base link
1485
+
1486
+ Helper method to find or validate an end-effector and base link
1487
+
1488
+ end
1489
+ end-effector or gripper to compute forward kinematics to
1490
+ start
1491
+ name or reference to a base link, defaults to None
1492
+
1493
+ ValueError
1494
+ link not known or ambiguous
1495
+ ValueError
1496
+ [description]
1497
+ TypeError
1498
+ unknown type provided
1499
+
1500
+ Returns
1501
+ -------
1502
+ end
1503
+ end-effector link
1504
+ start
1505
+ base link
1506
+ tool
1507
+ tool transform of gripper if applicable
1508
+
1509
+ """
1510
+
1511
+ tool = None
1512
+ if end is None:
1513
+ if len(self.grippers) > 1:
1514
+ end_ret = self.grippers[0].links[0]
1515
+ tool = self.grippers[0].tool
1516
+ if len(self.grippers) > 1:
1517
+ # Warn user: more than one gripper
1518
+ print("More than one gripper present, using robot.grippers[0]")
1519
+ elif len(self.grippers) == 1:
1520
+ end_ret = self.grippers[0].links[0]
1521
+ tool = self.grippers[0].tool
1522
+
1523
+ # no grippers, use ee link if just one
1524
+ elif len(self.ee_links) > 1:
1525
+ end_ret = self.ee_links[0]
1526
+ if len(self.ee_links) > 1:
1527
+ # Warn user: more than one EE
1528
+ print("More than one end-effector present, using robot.ee_links[0]")
1529
+ else:
1530
+ end_ret = self.ee_links[0]
1531
+
1532
+ else:
1533
+ # Check if end corresponds to gripper
1534
+ for gripper in self.grippers:
1535
+ if end == gripper or end == gripper.name:
1536
+ tool = gripper.tool
1537
+ # end_ret = gripper.links[0]
1538
+
1539
+ # otherwise check for end in the links
1540
+ end_ret = self._getlink(end)
1541
+
1542
+ if start is None:
1543
+ start_ret = self.base_link
1544
+
1545
+ # Cache result
1546
+ self._cache_start = start
1547
+ else:
1548
+ # start effector is specified
1549
+ start_ret = self._getlink(start)
1550
+
1551
+ # because Gripper returns Link not LinkType
1552
+ return end_ret, start_ret, tool # type: ignore
1553
+
1554
+ @lru_cache(maxsize=32)
1555
+ def ets(
1556
+ self,
1557
+ start: Union[LinkType, Gripper, str, None] = None,
1558
+ end: Union[LinkType, Gripper, str, None] = None,
1559
+ ) -> ETS:
1560
+ """
1561
+ Robot to ETS
1562
+
1563
+ ``robot.ets()`` is an ETS representing the kinematics from base to
1564
+ end-effector.
1565
+
1566
+ ``robot.ets(end=link)`` is an ETS representing the kinematics from
1567
+ base to the link ``link`` specified as a Link reference or a name.
1568
+
1569
+ ``robot.ets(start=l1, end=l2)`` is an ETS representing the kinematics
1570
+ from link ``l1`` to link ``l2``.
1571
+
1572
+ Parameters
1573
+ ----------
1574
+ :param start: start of path, defaults to ``base_link``
1575
+ :param end: end of path, defaults to end-effector
1576
+
1577
+ Raises
1578
+ ------
1579
+ ValueError
1580
+ a link does not belong to this ERobot
1581
+ TypeError
1582
+ a bad link argument
1583
+
1584
+ Returns
1585
+ -------
1586
+ ets
1587
+ elementary transform sequence
1588
+
1589
+ Examples
1590
+ --------
1591
+ .. runblock:: pycon
1592
+ >>> import roboticstoolbox as rtb
1593
+ >>> panda = rtb.models.ETS.Panda()
1594
+ >>> panda.ets()
1595
+
1596
+ """
1597
+
1598
+ # ets to stand and end incase of grippers
1599
+ ets_init = None
1600
+ ets_end = None
1601
+
1602
+ if isinstance(start, Gripper):
1603
+ ets_init = self._gripper_ets(start).inv()
1604
+ link = start.links[0].parent
1605
+ if link is None: # pragma nocover
1606
+ raise ValueError("Invalid robot link configuration")
1607
+ else:
1608
+ link = self._getlink(start, self.base_link)
1609
+
1610
+ if end is None:
1611
+ if len(self.grippers) > 1:
1612
+ end_link = self.grippers[0].links[0]
1613
+ ets_end = self._gripper_ets(self.grippers[0])
1614
+ print("multiple grippers present, ambiguous, using self.grippers[0]")
1615
+ elif len(self.grippers) == 1:
1616
+ end_link = self.grippers[0].links[0]
1617
+ ets_end = self._gripper_ets(self.grippers[0])
1618
+ elif len(self.ee_links) > 1:
1619
+ end_link = self._getlink(end, self.ee_links[0])
1620
+ print(
1621
+ "multiple end-effectors present, ambiguous, using self.ee_links[0]"
1622
+ )
1623
+ else:
1624
+ end_link = self._getlink(end, self.ee_links[0])
1625
+ else:
1626
+ if isinstance(end, Gripper):
1627
+ ets_end = self._gripper_ets(end)
1628
+ end_link = end.links[0].parent # type: ignore
1629
+ if end_link is None: # pragma nocover
1630
+ raise ValueError("Invalid robot link configuration")
1631
+ else:
1632
+ end_link = self._getlink(end, self.ee_links[0])
1633
+
1634
+ explored = set()
1635
+
1636
+ if link is end_link:
1637
+ ets = link.ets
1638
+ else:
1639
+ ets = self._find_ets(link, end_link, explored, path=None)
1640
+
1641
+ if ets is None:
1642
+ raise ValueError(
1643
+ "Could not find the requested ETS in this robot"
1644
+ ) # pragma nocover
1645
+
1646
+ if ets_init is not None:
1647
+ ets = ets_init * ets
1648
+
1649
+ if ets_end is not None:
1650
+ ets = ets * ets_end
1651
+
1652
+ return ets
1653
+
1654
+ def copy(self):
1655
+ return deepcopy(self)
1656
+
1657
+ def __deepcopy__(self, memo):
1658
+ links = []
1659
+
1660
+ # if isinstance(self, rtb.DHRobot):
1661
+ # cls = rtb.DHRobot
1662
+ if isinstance(self, rtb.Robot2):
1663
+ cls = rtb.Robot2
1664
+ else:
1665
+ cls = rtb.Robot
1666
+
1667
+ for link in self.links:
1668
+ links.append(deepcopy(link))
1669
+
1670
+ name = deepcopy(self.name)
1671
+ manufacturer = deepcopy(self.manufacturer)
1672
+ comment = deepcopy(self.comment)
1673
+ base = deepcopy(self.base)
1674
+ tool = deepcopy(self.tool)
1675
+ gravity = deepcopy(self.gravity)
1676
+ keywords = deepcopy(self.keywords)
1677
+ symbolic = deepcopy(self.symbolic)
1678
+ configs = deepcopy(self.configs)
1679
+
1680
+ result = cls(
1681
+ links,
1682
+ name=name,
1683
+ manufacturer=manufacturer,
1684
+ comment=comment,
1685
+ base=base, # type: ignore
1686
+ tool=tool,
1687
+ gravity=gravity,
1688
+ keywords=keywords,
1689
+ symbolic=symbolic,
1690
+ configs=configs,
1691
+ )
1692
+
1693
+ # if a configuration was an attribute of original robot, make it an
1694
+ # attribute of the deep copy
1695
+ for config in configs:
1696
+ if hasattr(self, config):
1697
+ setattr(result, config, configs[config])
1698
+
1699
+ memo[id(self)] = result
1700
+ return result
1701
+
1702
+ # --------------------------------------------------------------------- #
1703
+
1704
+ def todegrees(self, q) -> NDArray:
1705
+ """
1706
+ Convert joint angles to degrees
1707
+
1708
+ Parameters
1709
+ ----------
1710
+ q
1711
+ The joint configuration of the robot
1712
+
1713
+ Returns
1714
+ -------
1715
+ q
1716
+ a vector of joint coordinates in degrees and metres
1717
+
1718
+ ``robot.todegrees(q)`` converts joint coordinates ``q`` to degrees
1719
+ taking into account whether elements of ``q`` correspond to revolute
1720
+ or prismatic joints, ie. prismatic joint values are not converted.
1721
+
1722
+ If ``q`` is a matrix, with one column per joint, the conversion is
1723
+ performed columnwise.
1724
+
1725
+ Examples
1726
+ --------
1727
+ .. runblock:: pycon
1728
+ >>> import roboticstoolbox as rtb
1729
+ >>> from math import pi
1730
+ >>> stanford = rtb.models.DH.Stanford()
1731
+ >>> stanford.todegrees([pi/4, pi/8, 2, -pi/4, pi/6, pi/3])
1732
+
1733
+ """
1734
+
1735
+ q = getmatrix(q, (None, self.n))
1736
+
1737
+ for j, revolute in enumerate(self.revolutejoints):
1738
+ if revolute:
1739
+ q[:, j] *= 180.0 / np.pi
1740
+
1741
+ if q.shape[0] == 1:
1742
+ return q[0]
1743
+ else:
1744
+ return q
1745
+
1746
+ def toradians(self, q) -> NDArray:
1747
+ """
1748
+ Convert joint angles to radians
1749
+
1750
+ ``robot.toradians(q)`` converts joint coordinates ``q`` to radians
1751
+ taking into account whether elements of ``q`` correspond to revolute
1752
+ or prismatic joints, ie. prismatic joint values are not converted.
1753
+
1754
+ If ``q`` is a matrix, with one column per joint, the conversion is
1755
+ performed columnwise.
1756
+
1757
+ Parameters
1758
+ ----------
1759
+ q
1760
+ The joint configuration of the robot
1761
+
1762
+ Returns
1763
+ -------
1764
+ q
1765
+ a vector of joint coordinates in radians and metres
1766
+
1767
+ Examples
1768
+ --------
1769
+ .. runblock:: pycon
1770
+ >>> import roboticstoolbox as rtb
1771
+ >>> stanford = rtb.models.DH.Stanford()
1772
+ >>> stanford.toradians([10, 20, 2, 30, 40, 50])
1773
+
1774
+ """
1775
+
1776
+ q = getmatrix(q, (None, self.n))
1777
+
1778
+ for j, revolute in enumerate(self.revolutejoints):
1779
+ if revolute:
1780
+ q[:, j] *= np.pi / 180.0
1781
+
1782
+ if q.shape[0] == 1:
1783
+ return q[0]
1784
+ else:
1785
+ return q
1786
+
1787
+ def isrevolute(self, j) -> bool:
1788
+ """
1789
+ Check if joint is revolute
1790
+
1791
+ Returns
1792
+ -------
1793
+ j
1794
+ True if revolute
1795
+
1796
+ Examples
1797
+ --------
1798
+ .. runblock:: pycon
1799
+ >>> import roboticstoolbox as rtb
1800
+ >>> puma = rtb.models.DH.Puma560()
1801
+ >>> puma.revolutejoints
1802
+ >>> stanford = rtb.models.DH.Stanford()
1803
+ >>> stanford.isrevolute(1)
1804
+
1805
+ See Also
1806
+ --------
1807
+ :func:`Link.isrevolute`
1808
+ :func:`revolutejoints`
1809
+
1810
+ """
1811
+ return self.revolutejoints[j]
1812
+
1813
+ def isprismatic(self, j) -> bool:
1814
+ """
1815
+ Check if joint is prismatic
1816
+
1817
+ Returns
1818
+ -------
1819
+ j
1820
+ True if prismatic
1821
+
1822
+ Examples
1823
+ --------
1824
+ .. runblock:: pycon
1825
+ >>> import roboticstoolbox as rtb
1826
+ >>> puma = rtb.models.DH.Puma560()
1827
+ >>> puma.prismaticjoints
1828
+ >>> stanford = rtb.models.DH.Stanford()
1829
+ >>> stanford.isprismatic(1)
1830
+
1831
+ See Also
1832
+ --------
1833
+ :func:`Link.isprismatic`
1834
+ :func:`prismaticjoints`
1835
+
1836
+ """
1837
+
1838
+ return self.prismaticjoints[j]
1839
+
1840
+ # --------------------------------------------------------------------- #
1841
+
1842
+ def dfs_links(
1843
+ self,
1844
+ start: LinkType,
1845
+ func: Union[None, Callable[[LinkType], Any]] = None,
1846
+ ) -> List[LinkType]:
1847
+ """
1848
+ A link search method
1849
+
1850
+ Visit all links from start in depth-first order and will apply
1851
+ func to each visited link
1852
+
1853
+ Parameters
1854
+ ----------
1855
+ start
1856
+ The link to start at
1857
+ func
1858
+ An optional function to apply to each link as it is found
1859
+
1860
+ Returns
1861
+ -------
1862
+ links
1863
+ A list of links
1864
+
1865
+ """
1866
+
1867
+ visited = []
1868
+
1869
+ def vis_children(link):
1870
+ visited.append(link)
1871
+ if func is not None:
1872
+ func(link)
1873
+
1874
+ for li in link.children:
1875
+ if li not in visited:
1876
+ vis_children(li)
1877
+
1878
+ vis_children(start)
1879
+
1880
+ return visited
1881
+
1882
+ def addconfiguration_attr(self, name: str, q: ArrayLike, unit: str = "rad"):
1883
+ """
1884
+ Add a named joint configuration as an attribute
1885
+
1886
+ Parameters
1887
+ ----------
1888
+ name
1889
+ Name of the joint configuration
1890
+ q
1891
+ Joint configuration
1892
+
1893
+ Examples
1894
+ --------
1895
+ .. runblock:: pycon
1896
+ >>> import roboticstoolbox as rtb
1897
+ >>> robot = rtb.models.DH.Puma560()
1898
+ >>> robot.addconfiguration_attr("mypos", [0.1, 0.2, 0.3, 0.4, 0.5, 0.6])
1899
+ >>> robot.mypos
1900
+ >>> robot.configs["mypos"]
1901
+
1902
+ Notes
1903
+ -----
1904
+ - Used in robot model init method to store the ``qr`` configuration
1905
+ - Dynamically adding attributes to objects can cause issues with
1906
+ Python type checking.
1907
+ - Configuration is also added to the robot instance's dictionary of
1908
+ named configurations.
1909
+
1910
+ See Also
1911
+ --------
1912
+ :meth:`addconfiguration`
1913
+
1914
+ """
1915
+
1916
+ v = getunit(q, unit, dim=self.n)
1917
+ self._configs[name] = v
1918
+ setattr(self, name, v)
1919
+
1920
+ def addconfiguration(self, name: str, q: NDArray):
1921
+ """
1922
+ Add a named joint configuration
1923
+
1924
+ Add a named configuration to the robot instance's dictionary of named
1925
+ configurations.
1926
+
1927
+ Parameters
1928
+ ----------
1929
+ name
1930
+ Name of the joint configuration
1931
+ q
1932
+ Joint configuration
1933
+
1934
+
1935
+
1936
+ Examples
1937
+ --------
1938
+ .. runblock:: pycon
1939
+ >>> import roboticstoolbox as rtb
1940
+ >>> robot = rtb.models.DH.Puma560()
1941
+ >>> robot.addconfiguration_attr("mypos", [0.1, 0.2, 0.3, 0.4, 0.5, 0.6])
1942
+ >>> robot.configs["mypos"]
1943
+
1944
+ See Also
1945
+ --------
1946
+ :meth:`addconfiguration`
1947
+
1948
+ """
1949
+
1950
+ self._configs[name] = q
1951
+
1952
+ def configurations_str(self, border="thin"):
1953
+ deg = 180 / np.pi
1954
+
1955
+ # TODO: factor this out of DHRobot
1956
+ def angle(theta, fmt=None):
1957
+ if fmt is not None:
1958
+ try:
1959
+ return fmt.format(theta * deg) + "\u00b0"
1960
+ except TypeError: # pragma nocover
1961
+ pass
1962
+
1963
+ return str(theta * deg) + "\u00b0" # pragma nocover
1964
+
1965
+ # show named configurations
1966
+ if len(self._configs) > 0:
1967
+ table = ANSITable(
1968
+ Column("name", colalign=">"),
1969
+ *[
1970
+ Column(f"q{j:d}", colalign="<", headalign="<")
1971
+ for j in range(self.n)
1972
+ ],
1973
+ border=border,
1974
+ )
1975
+
1976
+ for name, q in self._configs.items():
1977
+ qlist = []
1978
+ for j, c in enumerate(self.structure):
1979
+ if c == "P":
1980
+ qlist.append(f"{q[j]: .3g}")
1981
+ else:
1982
+ qlist.append(angle(q[j], "{: .3g}"))
1983
+ table.row(name, *qlist)
1984
+
1985
+ return "\n" + str(table)
1986
+ else: # pragma nocover
1987
+ return ""
1988
+
1989
+ def random_q(self):
1990
+ """
1991
+ Return a random joint configuration
1992
+
1993
+ The value for each joint is uniform randomly distributed between the
1994
+ limits set for the robot.
1995
+
1996
+ Note
1997
+ ----
1998
+ The joint limit for all joints must be set.
1999
+
2000
+ Returns
2001
+ -------
2002
+ q
2003
+ Random joint configuration :rtype: ndarray(n)
2004
+
2005
+ See Also
2006
+ --------
2007
+ :func:`Robot.qlim`
2008
+ :func:`Link.qlim`
2009
+
2010
+ """
2011
+
2012
+ qlim = self.qlim
2013
+ if np.any(np.isnan(qlim)):
2014
+ raise ValueError("some joint limits not defined") # pragma nocover
2015
+ return np.random.uniform(low=qlim[0, :], high=qlim[1, :], size=(self.n,))
2016
+
2017
+ def linkcolormap(self, linkcolors: Union[List[Any], str] = "viridis"):
2018
+ """
2019
+ Create a colormap for robot joints
2020
+
2021
+ - ``cm = robot.linkcolormap()`` is an n-element colormap that gives a
2022
+ unique color for every link. The RGBA colors for link ``j`` are
2023
+ ``cm(j)``.
2024
+ - ``cm = robot.linkcolormap(cmap)`` as above but ``cmap`` is the name
2025
+ of a valid matplotlib colormap. The default, example above, is the
2026
+ ``viridis`` colormap.
2027
+ - ``cm = robot.linkcolormap(list of colors)`` as above but a
2028
+ colormap is created from a list of n color names given as strings,
2029
+ tuples or hexstrings.
2030
+
2031
+ Parameters
2032
+ ----------
2033
+ linkcolors
2034
+ list of colors or colormap, defaults to "viridis"
2035
+
2036
+ Returns
2037
+ -------
2038
+ color map
2039
+ the color map
2040
+
2041
+
2042
+ Examples
2043
+ --------
2044
+ .. runblock:: pycon
2045
+ >>> import roboticstoolbox as rtb
2046
+ >>> robot = rtb.models.DH.Puma560()
2047
+ >>> cm = robot.linkcolormap("inferno")
2048
+ >>> print(cm(range(6))) # cm(i) is 3rd color in colormap
2049
+ >>> cm = robot.linkcolormap(
2050
+ ... ['red', 'g', (0,0.5,0), '#0f8040', 'yellow', 'cyan'])
2051
+ >>> print(cm(range(6)))
2052
+
2053
+ Notes
2054
+ -----
2055
+ - Colormaps have 4-elements: red, green, blue, alpha (RGBA)
2056
+ - Names of supported colors and colormaps are defined in the
2057
+ matplotlib documentation.
2058
+
2059
+ - `Specifying colors <https://matplotlib.org/3.1.0/tutorials/colors/colors.html>`_
2060
+ - `Colormaps <https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html>`_
2061
+
2062
+ """ # noqa
2063
+
2064
+ if isinstance(linkcolors, list) and len(linkcolors) == self.n: # pragma nocover
2065
+ # provided a list of color names
2066
+ return colors.ListedColormap(linkcolors) # type: ignore
2067
+ else: # pragma nocover
2068
+ # assume it is a colormap name
2069
+ return cm.get_cmap(linkcolors, 6) # type: ignore
2070
+
2071
+ def hierarchy(self) -> None:
2072
+ """
2073
+ Pretty print the robot link hierachy
2074
+
2075
+ Returns
2076
+ -------
2077
+ Pretty print of the robot model
2078
+
2079
+ Examples
2080
+ --------
2081
+ Makes a robot and prints the heirachy
2082
+
2083
+ .. runblock:: pycon
2084
+ >>> import roboticstoolbox as rtb
2085
+ >>> robot = rtb.models.URDF.Panda()
2086
+ >>> robot.hierarchy()
2087
+
2088
+ """
2089
+
2090
+ def recurse(link, indent=0):
2091
+ print(" " * indent * 2, link.name)
2092
+ if link.children is not None:
2093
+ for child in link.children:
2094
+ recurse(child, indent + 1)
2095
+
2096
+ recurse(self.base_link)
2097
+
2098
+ def segments(self) -> List[List[Union[LinkType, None]]]:
2099
+ """
2100
+ Segments of branched robot
2101
+
2102
+ For a single-chain robot with structure::
2103
+
2104
+ L1 - L2 - L3
2105
+
2106
+ the return is ``[[None, L1, L2, L3]]``
2107
+
2108
+ For a robot with structure::
2109
+
2110
+ L1 - L2 +- L3 - L4
2111
+ +- L5 - L6
2112
+
2113
+ the return is ``[[None, L1, L2], [L2, L3, L4], [L2, L5, L6]]``
2114
+
2115
+ Returns
2116
+ -------
2117
+ segments
2118
+ Segment list
2119
+
2120
+ Notes
2121
+ -----
2122
+ - the length of the list is the number of segments in the robot
2123
+ - the first segment always starts with ``None`` which represents
2124
+ the base transform (since there is no base link)
2125
+ - the last link of one segment is also the first link of subsequent
2126
+ segments
2127
+ """
2128
+
2129
+ def recurse(link: Link):
2130
+ segs = [link.parent]
2131
+ while True:
2132
+ segs.append(link)
2133
+ if link.nchildren == 0:
2134
+ return [segs]
2135
+ elif link.nchildren == 1:
2136
+ link = link.children[0] # type: ignore
2137
+ continue
2138
+ elif link.nchildren > 1:
2139
+ segs = [segs]
2140
+
2141
+ for child in link.children: # type: ignore
2142
+ segs.extend(recurse(child))
2143
+
2144
+ return segs
2145
+
2146
+ return recurse(self.links[0]) # type: ignore
2147
+
2148
+ # --------------------------------------------------------------------- #
2149
+ # Scene Graph section
2150
+ # --------------------------------------------------------------------- #
2151
+
2152
+ def _update_link_tf(self, q: Union[ArrayLike, None] = None):
2153
+ """
2154
+ This private method updates the local transform of each link within
2155
+ this robot according to q (or self.q if q is none)
2156
+ """
2157
+
2158
+ @lru_cache(maxsize=2)
2159
+ def get_link_ets():
2160
+ return [link.ets._fknm for link in self.links]
2161
+
2162
+ @lru_cache(maxsize=2)
2163
+ def get_link_scene_node():
2164
+ return [link._T_reference for link in self.links]
2165
+
2166
+ Robot_link_T(get_link_ets(), get_link_scene_node(), self._q, q)
2167
+
2168
+ [gripper._update_link_tf() for gripper in self.grippers]
2169
+
2170
+ # --------------------------------------------------------------------- #
2171
+ # --------- PyPlot Methods -------------------------------------------- #
2172
+ # --------------------------------------------------------------------- #
2173
+
2174
+ def _get_graphical_backend(
2175
+ self,
2176
+ backend: Union[L["swift", "pyplot", "pyplot2"], None] = None, # noqa
2177
+ ) -> Connector:
2178
+ import sys
2179
+ from roboticstoolbox.backends import load_backend
2180
+
2181
+ # Resolve which backend name to use
2182
+ if backend is not None:
2183
+ using_backend = backend.lower()
2184
+ else:
2185
+ # In JupyterLite/Pyodide, only pyplot/pyplot2 are available
2186
+ if sys.platform == "emscripten":
2187
+ if isinstance(self, rtb.Robot2):
2188
+ using_backend = "pyplot2"
2189
+ else:
2190
+ using_backend = "pyplot"
2191
+ else:
2192
+ # Infer from robot type and robot-level default override
2193
+ using_backend = self.default_backend
2194
+ if using_backend is None:
2195
+ if isinstance(self, rtb.DHRobot):
2196
+ using_backend = "pyplot"
2197
+ elif isinstance(self, rtb.Robot2):
2198
+ using_backend = "pyplot2"
2199
+ elif isinstance(self, rtb.Robot):
2200
+ using_backend = "swift" if self.hasgeometry else "pyplot"
2201
+ else:
2202
+ using_backend = "pyplot"
2203
+
2204
+ # swift is optional; fall back to pyplot with a helpful message
2205
+ if using_backend == "swift": # pragma nocover
2206
+ if isinstance(self, rtb.DHRobot):
2207
+ raise NotImplementedError(
2208
+ "Plotting in Swift is not implemented for DHRobots yet"
2209
+ )
2210
+ try:
2211
+ return load_backend("swift")
2212
+ except ModuleNotFoundError:
2213
+ if backend is not None:
2214
+ # user explicitly asked for swift
2215
+ print(
2216
+ "Swift is not installed. "
2217
+ "Install it with: pip install swift-sim"
2218
+ )
2219
+ using_backend = "pyplot"
2220
+
2221
+ return load_backend(using_backend)
2222
+
2223
+ def plot(
2224
+ self,
2225
+ q: ArrayLike,
2226
+ backend: Union[L["swift", "pyplot", "pyplot2"], None] = None, # noqa
2227
+ block: bool = False,
2228
+ dt: float = 0.050,
2229
+ limits: Union[ArrayLike, None] = None,
2230
+ vellipse: bool = False,
2231
+ fellipse: bool = False,
2232
+ fig: Union[str, None] = None,
2233
+ movie: Union[str, None] = None,
2234
+ loop: bool = False,
2235
+ **kwargs,
2236
+ ) -> Connector:
2237
+ """
2238
+ Graphical display and animation
2239
+
2240
+ ``robot.plot(q, 'pyplot')`` displays a graphical view of a robot
2241
+ based on the kinematic model and the joint configuration ``q``.
2242
+ This is a stick figure polyline which joins the origins of the
2243
+ link coordinate frames. The plot will autoscale with an aspect
2244
+ ratio of 1.
2245
+
2246
+ If ``q`` (m,n) representing a joint-space trajectory it will create an
2247
+ animation with a pause of ``dt`` seconds between each frame.
2248
+
2249
+ Parameters
2250
+ ----------
2251
+ q
2252
+ The joint configuration of the robot.
2253
+ backend
2254
+ The graphical backend to use, currently 'swift'
2255
+ and 'pyplot' are implemented. Defaults to 'swift' of a ``Robot``
2256
+ and 'pyplot` for a ``DHRobot``
2257
+ block
2258
+ Block operation of the code and keep the figure open
2259
+ dt
2260
+ if q is a trajectory, this describes the delay in
2261
+ seconds between frames
2262
+ limits
2263
+ Custom view limits for the plot. If not supplied will
2264
+ autoscale, [x1, x2, y1, y2, z1, z2]
2265
+ (this option is for 'pyplot' only)
2266
+ vellipse
2267
+ (Plot Option) Plot the velocity ellipse at the
2268
+ end-effector (this option is for 'pyplot' only)
2269
+ fellipse
2270
+ (Plot Option) Plot the force ellipse at the
2271
+ end-effector (this option is for 'pyplot' only)
2272
+ fig
2273
+ (Plot Option) The figure label to plot in (this option is for
2274
+ 'pyplot' only)
2275
+ movie
2276
+ (Plot Option) The filename to save the movie to (this option is for
2277
+ 'pyplot' only)
2278
+ loop
2279
+ (Plot Option) Loop the movie (this option is for
2280
+ 'pyplot' only)
2281
+ jointaxes
2282
+ (Plot Option) Plot an arrow indicating the axes in
2283
+ which the joint revolves around(revolute joint) or translates
2284
+ along (prosmatic joint) (this option is for 'pyplot' only)
2285
+ eeframe
2286
+ (Plot Option) Plot the end-effector coordinate frame
2287
+ at the location of the end-effector. Uses three arrows, red,
2288
+ green and blue to indicate the x, y, and z-axes.
2289
+ (this option is for 'pyplot' only)
2290
+ shadow
2291
+ (Plot Option) Plot a shadow of the robot in the x-y
2292
+ plane. (this option is for 'pyplot' only)
2293
+ name
2294
+ (Plot Option) Plot the name of the robot near its base
2295
+ (this option is for 'pyplot' only)
2296
+ render_mode
2297
+ (Plot Option) Rendering mode for matplotlib backends:
2298
+ ``'window'``, ``'notebook-widget'``, or ``'notebook-inline'``.
2299
+ If omitted, an environment-appropriate mode is selected.
2300
+ inline_every_n
2301
+ (Plot Option) In notebook-inline mode, push one rendered frame
2302
+ every N simulation steps. Larger N reduces output load.
2303
+ inline_format
2304
+ (Plot Option) In notebook-inline mode, frame format:
2305
+ ``'svg'`` (default) or ``'png'``.
2306
+ inline_dpi
2307
+ (Plot Option) DPI for PNG inline frames only; ignored when
2308
+ ``inline_format='svg'``.
2309
+
2310
+ Returns
2311
+ -------
2312
+ env
2313
+ A reference to the environment object which controls the
2314
+ figure
2315
+
2316
+ Notes
2317
+ -----
2318
+ - By default this method will block until the figure is dismissed.
2319
+ To avoid this set ``block=False``.
2320
+ - For PyPlot, the polyline joins the origins of the link frames,
2321
+ but for some Denavit-Hartenberg models those frames may not
2322
+ actually be on the robot, ie. the lines to not neccessarily
2323
+ represent the links of the robot.
2324
+
2325
+ See Also
2326
+ --------
2327
+ :func:`teach`
2328
+
2329
+ """ # noqa
2330
+
2331
+ env = None
2332
+
2333
+ env = self._get_graphical_backend(backend)
2334
+
2335
+ launch_kwargs = {}
2336
+ for key in ("render_mode", "inline_every_n", "inline_format", "inline_dpi"):
2337
+ if key in kwargs:
2338
+ launch_kwargs[key] = kwargs.pop(key)
2339
+
2340
+ q = np.array(getmatrix(q, (None, self.n)))
2341
+ self.q = q[0, :]
2342
+
2343
+ # Add the self to the figure in readonly mode
2344
+ if q.shape[0] == 1:
2345
+ env.launch(
2346
+ name=self.name + " Plot", limits=limits, fig=fig, **launch_kwargs
2347
+ )
2348
+ else:
2349
+ env.launch(
2350
+ name=self.name + " Trajectory Plot",
2351
+ limits=limits,
2352
+ fig=fig,
2353
+ **launch_kwargs,
2354
+ )
2355
+
2356
+ env.add(self, readonly=True, **kwargs)
2357
+ self._active_plot_env = env
2358
+
2359
+ if vellipse:
2360
+ vell = self.vellipse(q[0], centre="ee", add=False)
2361
+ env.add(vell)
2362
+ else:
2363
+ vell = None
2364
+
2365
+ if fellipse:
2366
+ fell = self.fellipse(q[0], centre="ee", add=False)
2367
+ env.add(fell)
2368
+ else:
2369
+ fell = None
2370
+
2371
+ # List of images saved from each plot
2372
+ images = []
2373
+
2374
+ if movie is not None: # pragma: nocover
2375
+ loop = False
2376
+
2377
+ while True:
2378
+ for qk in q:
2379
+ self.q = qk
2380
+ if vell is not None:
2381
+ vell.q = qk
2382
+ if fell is not None:
2383
+ fell.q = qk
2384
+ env.step(dt)
2385
+
2386
+ if movie is not None and isinstance(env, PyPlot): # pragma nocover
2387
+ images.append(env.getframe())
2388
+
2389
+ if movie is not None: # pragma nocover
2390
+ # save it as an animated GIF
2391
+ images[0].save(
2392
+ movie,
2393
+ save_all=True,
2394
+ append_images=images[1:],
2395
+ optimize=False,
2396
+ duration=dt,
2397
+ loop=0,
2398
+ )
2399
+ if not loop:
2400
+ break
2401
+
2402
+ # Keep the plot open
2403
+ if block: # pragma nocover
2404
+ env.hold()
2405
+
2406
+ return env
2407
+
2408
+ def fellipse(
2409
+ self,
2410
+ q: ArrayLike,
2411
+ opt: L["trans", "rot"] = "trans", # noqa
2412
+ unit: L["rad", "deg"] = "rad", # noqa
2413
+ centre: Union[L["ee"], ArrayLike] = "ee", # noqa
2414
+ add: bool = True,
2415
+ ) -> EllipsePlot:
2416
+ """
2417
+ Create a force ellipsoid object for plotting with PyPlot
2418
+
2419
+ ``robot.fellipse(q)`` creates a force ellipsoid for the robot at
2420
+ pose ``q``. By default the ellipsoid is centered at the end-effector.
2421
+
2422
+ Parameters
2423
+ ----------
2424
+ q
2425
+ The joint configuration of the robot.
2426
+ opt
2427
+ 'trans' or 'rot' will plot either the translational or
2428
+ rotational force ellipsoid
2429
+ unit
2430
+ 'rad' or 'deg' will plot the ellipsoid in radians or
2431
+ degrees
2432
+ centre
2433
+ The centre of the ellipsoid, either 'ee' for the end-effector
2434
+ or a 3-vector [x, y, z] in the world frame
2435
+
2436
+ Returns
2437
+ -------
2438
+ env
2439
+ An EllipsePlot object
2440
+
2441
+ Notes
2442
+ -----
2443
+ - By default the ellipsoid related to translational motion is
2444
+ drawn. Use ``opt='rot'`` to draw the rotational velocity
2445
+ ellipsoid.
2446
+ - By default the ellipsoid is drawn at the end-effector. The option
2447
+ ``centre`` allows its origin to set to set to the specified
2448
+ 3-vector, or the string "ee" ensures it is drawn at the
2449
+ end-effector position.
2450
+
2451
+ """
2452
+
2453
+ if isinstance(self, rtb.ERobot): # pragma nocover
2454
+ raise NotImplementedError("ERobot fellipse not implemented yet")
2455
+
2456
+ q = getunit(q, unit)
2457
+ ell = EllipsePlot(self, q, "f", opt, centre=centre)
2458
+
2459
+ if add:
2460
+ self._maybe_add_ellipse_to_active_env(ell)
2461
+
2462
+ return ell
2463
+
2464
+ def vellipse(
2465
+ self,
2466
+ q: ArrayLike,
2467
+ opt: L["trans", "rot"] = "trans", # noqa
2468
+ unit: L["rad", "deg"] = "rad", # noqa
2469
+ centre: Union[L["ee"], ArrayLike] = "ee", # noqa
2470
+ scale: float = 0.1,
2471
+ add: bool = True,
2472
+ ) -> EllipsePlot:
2473
+ """
2474
+ Create a velocity ellipsoid object for plotting with PyPlot
2475
+
2476
+ ``robot.vellipse(q)`` creates a force ellipsoid for the robot at
2477
+ pose ``q``. By default the ellipsoid is centered at the end-effector.
2478
+
2479
+ Parameters
2480
+ ----------
2481
+ q
2482
+ The joint configuration of the robot.
2483
+ opt
2484
+ 'trans' or 'rot' will plot either the translational or
2485
+ rotational force ellipsoid
2486
+ unit
2487
+ 'rad' or 'deg' will plot the ellipsoid in radians or
2488
+ degrees
2489
+ centre
2490
+ The centre of the ellipsoid, either 'ee' for the end-effector
2491
+ or a 3-vector [x, y, z] in the world frame
2492
+ scale
2493
+ The scale factor for the ellipsoid
2494
+
2495
+ Returns
2496
+ -------
2497
+ env
2498
+ An EllipsePlot object
2499
+
2500
+ Notes
2501
+ -----
2502
+ - By default the ellipsoid related to translational motion is
2503
+ drawn. Use ``opt='rot'`` to draw the rotational velocity
2504
+ ellipsoid.
2505
+ - By default the ellipsoid is drawn at the end-effector. The option
2506
+ ``centre`` allows its origin to set to set to the specified
2507
+ 3-vector, or the string "ee" ensures it is drawn at the
2508
+ end-effector position.
2509
+
2510
+ """
2511
+
2512
+ if isinstance(self, rtb.ERobot): # pragma nocover
2513
+ raise NotImplementedError("ERobot vellipse not implemented yet")
2514
+
2515
+ q = getunit(q, unit)
2516
+ ell = EllipsePlot(self, q, "v", opt, centre=centre, scale=scale)
2517
+
2518
+ if add:
2519
+ self._maybe_add_ellipse_to_active_env(ell)
2520
+
2521
+ return ell
2522
+
2523
+ def _maybe_add_ellipse_to_active_env(self, ellipse: EllipsePlot) -> None:
2524
+ """
2525
+ Add ellipse to the most recently active PyPlot environment, if available.
2526
+ """
2527
+ env = self._active_plot_env
2528
+ if env is None:
2529
+ return
2530
+
2531
+ if type(env).__name__ not in ("PyPlot", "PyPlot2"):
2532
+ return
2533
+
2534
+ try:
2535
+ env.add(ellipse)
2536
+ except Exception:
2537
+ # Environment may be stale/closed; ignore in this convenience path.
2538
+ pass
2539
+
2540
+ def plot_ellipse(
2541
+ self,
2542
+ ellipse: EllipsePlot,
2543
+ block: bool = True,
2544
+ limits: Union[ArrayLike, None] = None,
2545
+ jointaxes: bool = True,
2546
+ eeframe: bool = True,
2547
+ shadow: bool = True,
2548
+ name: bool = True,
2549
+ ) -> PyPlot:
2550
+ """
2551
+ Plot the an ellipsoid
2552
+
2553
+ ``robot.plot_ellipse(ellipsoid)`` displays the ellipsoid.
2554
+
2555
+ Parameters
2556
+ ----------
2557
+ ellipse
2558
+ the ellipsoid to plot
2559
+ block
2560
+ Block operation of the code and keep the figure open
2561
+ limits
2562
+ Custom view limits for the plot. If not supplied will
2563
+ autoscale, [x1, x2, y1, y2, z1, z2]
2564
+ jointaxes
2565
+ (Plot Option) Plot an arrow indicating the axes in
2566
+ which the joint revolves around(revolute joint) or translates
2567
+ along (prosmatic joint)
2568
+ eeframe
2569
+ (Plot Option) Plot the end-effector coordinate frame
2570
+ at the location of the end-effector. Uses three arrows, red,
2571
+ green and blue to indicate the x, y, and z-axes.
2572
+ shadow
2573
+ (Plot Option) Plot a shadow of the robot in the x-y
2574
+ plane
2575
+ name
2576
+ (Plot Option) Plot the name of the robot near its base
2577
+
2578
+ Returns
2579
+ -------
2580
+ env
2581
+ A reference to the PyPlot object which controls the
2582
+ matplotlib figure
2583
+
2584
+ """
2585
+
2586
+ if not isinstance(ellipse, EllipsePlot): # pragma nocover
2587
+ raise TypeError(
2588
+ "ellipse must be of type roboticstoolbox.backend.PyPlot.EllipsePlot"
2589
+ )
2590
+
2591
+ env = PyPlot()
2592
+
2593
+ # Add the robot to the figure in readonly mode
2594
+ env.launch(ellipse.robot.name + " " + ellipse.name, limits=limits)
2595
+
2596
+ env.add(ellipse, jointaxes=jointaxes, eeframe=eeframe, shadow=shadow, name=name)
2597
+
2598
+ # Keep the plot open
2599
+ if block: # pragma nocover
2600
+ env.hold()
2601
+
2602
+ return env
2603
+
2604
+ def plot_fellipse(
2605
+ self,
2606
+ q: Union[ArrayLike, None],
2607
+ block: bool = True,
2608
+ fellipse: Union[EllipsePlot, None] = None,
2609
+ limits: Union[ArrayLike, None] = None,
2610
+ opt: L["trans", "rot"] = "trans", # noqa
2611
+ centre: Union[L["ee"], ArrayLike] = "ee", # noqa
2612
+ jointaxes: bool = True,
2613
+ eeframe: bool = True,
2614
+ shadow: bool = True,
2615
+ name: bool = True,
2616
+ ) -> PyPlot:
2617
+ """
2618
+ Plot the force ellipsoid for manipulator
2619
+
2620
+ ``robot.plot_fellipse(q)`` displays the velocity ellipsoid for the
2621
+ robot at pose ``q``. The plot will autoscale with an aspect ratio
2622
+ of 1.
2623
+
2624
+ ``robot.plot_fellipse(vellipse)`` specifies a custon ellipse to plot.
2625
+
2626
+ Parameters
2627
+ ----------
2628
+ q
2629
+ The joint configuration of the robot
2630
+ block
2631
+ Block operation of the code and keep the figure open
2632
+ fellipse
2633
+ the vellocity ellipsoid to plot
2634
+ limits
2635
+ Custom view limits for the plot. If not supplied will
2636
+ autoscale, [x1, x2, y1, y2, z1, z2]
2637
+ opt
2638
+ 'trans' or 'rot' will plot either the translational or
2639
+ rotational force ellipsoid
2640
+ centre
2641
+ The coordinates to plot the fellipse [x, y, z] or "ee"
2642
+ to plot at the end-effector location
2643
+ jointaxes
2644
+ (Plot Option) Plot an arrow indicating the axes in
2645
+ which the joint revolves around(revolute joint) or translates
2646
+ along (prosmatic joint)
2647
+ eeframe
2648
+ (Plot Option) Plot the end-effector coordinate frame
2649
+ at the location of the end-effector. Uses three arrows, red,
2650
+ green and blue to indicate the x, y, and z-axes.
2651
+ shadow
2652
+ (Plot Option) Plot a shadow of the robot in the x-y
2653
+ plane
2654
+ name
2655
+ (Plot Option) Plot the name of the robot near its base
2656
+
2657
+ Raises
2658
+ ------
2659
+ ValueError
2660
+ q or fellipse must be supplied
2661
+
2662
+ Returns
2663
+ -------
2664
+ env
2665
+ A reference to the PyPlot object which controls the
2666
+ matplotlib figure
2667
+
2668
+ Notes
2669
+ -----
2670
+ - By default the ellipsoid related to translational motion is
2671
+ drawn. Use ``opt='rot'`` to draw the rotational velocity
2672
+ ellipsoid.
2673
+ - By default the ellipsoid is drawn at the origin. The option
2674
+ ``centre`` allows its origin to set to set to the specified
2675
+ 3-vector, or the string "ee" ensures it is drawn at the
2676
+ end-effector position.
2677
+
2678
+ """
2679
+
2680
+ if isinstance(self, rtb.ERobot): # pragma nocover
2681
+ raise NotImplementedError(
2682
+ "Ellipse Plotting of ERobot's not implemented yet"
2683
+ )
2684
+
2685
+ if fellipse is None and q is not None:
2686
+ fellipse = self.fellipse(q, opt=opt, centre=centre, add=False)
2687
+ elif fellipse is None:
2688
+ raise ValueError("Must specify either q or fellipse") # pragma: nocover
2689
+
2690
+ return self.plot_ellipse(
2691
+ fellipse,
2692
+ block=block,
2693
+ limits=limits,
2694
+ jointaxes=jointaxes,
2695
+ eeframe=eeframe,
2696
+ shadow=shadow,
2697
+ name=name,
2698
+ )
2699
+
2700
+ def plot_vellipse(
2701
+ self,
2702
+ q: Union[ArrayLike, None],
2703
+ block: bool = True,
2704
+ vellipse: Union[EllipsePlot, None] = None,
2705
+ limits: Union[ArrayLike, None] = None,
2706
+ opt: L["trans", "rot"] = "trans", # noqa
2707
+ centre: Union[L["ee"], ArrayLike] = "ee", # noqa
2708
+ jointaxes: bool = True,
2709
+ eeframe: bool = True,
2710
+ shadow: bool = True,
2711
+ name: bool = True,
2712
+ ) -> PyPlot:
2713
+ """
2714
+ Plot the velocity ellipsoid for manipulator
2715
+
2716
+ ``robot.plot_vellipse(q)`` displays the velocity ellipsoid for the
2717
+ robot at pose ``q``. The plot will autoscale with an aspect ratio
2718
+ of 1.
2719
+
2720
+ ``robot.plot_vellipse(vellipse)`` specifies a custon ellipse to plot.
2721
+
2722
+ block
2723
+ Block operation of the code and keep the figure open
2724
+ q
2725
+ The joint configuration of the robot
2726
+ vellipse
2727
+ the vellocity ellipsoid to plot
2728
+ limits
2729
+ Custom view limits for the plot. If not supplied will
2730
+ autoscale, [x1, x2, y1, y2, z1, z2]
2731
+ opt
2732
+ 'trans' or 'rot' will plot either the translational or
2733
+ rotational velocity ellipsoid
2734
+ centre
2735
+ The coordinates to plot the vellipse [x, y, z] or "ee"
2736
+ to plot at the end-effector location
2737
+ jointaxes
2738
+ (Plot Option) Plot an arrow indicating the axes in
2739
+ which the joint revolves around(revolute joint) or translates
2740
+ along (prosmatic joint)
2741
+ eeframe
2742
+ (Plot Option) Plot the end-effector coordinate frame
2743
+ at the location of the end-effector. Uses three arrows, red,
2744
+ green and blue to indicate the x, y, and z-axes.
2745
+ shadow
2746
+ (Plot Option) Plot a shadow of the robot in the x-y
2747
+ plane
2748
+ name
2749
+ (Plot Option) Plot the name of the robot near its base
2750
+
2751
+ Raises
2752
+ ------
2753
+ ValueError
2754
+ q or fellipse must be supplied
2755
+
2756
+ Returns
2757
+ -------
2758
+ env
2759
+ A reference to the PyPlot object which controls the
2760
+ matplotlib figure
2761
+
2762
+ Notes
2763
+ -----
2764
+ - By default the ellipsoid related to translational motion is
2765
+ drawn. Use ``opt='rot'`` to draw the rotational velocity
2766
+ ellipsoid.
2767
+ - By default the ellipsoid is drawn at the origin. The option
2768
+ ``centre`` allows its origin to set to set to the specified
2769
+ 3-vector, or the string "ee" ensures it is drawn at the
2770
+ end-effector position.
2771
+
2772
+ """
2773
+
2774
+ if isinstance(self, rtb.ERobot): # pragma nocover
2775
+ raise NotImplementedError(
2776
+ "Ellipse Plotting of ERobot's not implemented yet"
2777
+ )
2778
+
2779
+ if vellipse is None and q is not None:
2780
+ vellipse = self.vellipse(q=q, opt=opt, centre=centre, add=False)
2781
+ elif vellipse is None:
2782
+ raise ValueError("Must specify either q or vellipse") # pragma: nocover
2783
+
2784
+ return self.plot_ellipse(
2785
+ vellipse,
2786
+ block=block,
2787
+ limits=limits,
2788
+ jointaxes=jointaxes,
2789
+ eeframe=eeframe,
2790
+ shadow=shadow,
2791
+ name=name,
2792
+ )
2793
+
2794
+ def teach(
2795
+ self,
2796
+ q: Union[ArrayLike, None],
2797
+ block: bool = True,
2798
+ limits: Union[ArrayLike, None] = None,
2799
+ vellipse: bool = False,
2800
+ fellipse: bool = False,
2801
+ backend: Union[L["pyplot", "pyplot2"], None] = None, # noqa
2802
+ ) -> Connector:
2803
+ """
2804
+ Graphical teach pendant
2805
+
2806
+ ``robot.teach(q)`` creates a matplotlib plot which allows the user to
2807
+ "drive" a graphical robot using a graphical slider panel. The robot's
2808
+ inital joint configuration is ``q``. The plot will autoscale with an
2809
+ aspect ratio of 1.
2810
+
2811
+ ``robot.teach()`` as above except the robot's stored value of ``q``
2812
+ is used.
2813
+
2814
+ q
2815
+ The joint configuration of the robot (Optional,
2816
+ if not supplied will use the stored q values).
2817
+ block
2818
+ Block operation of the code and keep the figure open
2819
+ limits
2820
+ Custom view limits for the plot. If not supplied will
2821
+ autoscale, [x1, x2, y1, y2, z1, z2]
2822
+ vellipse
2823
+ (Plot Option) Plot the velocity ellipse at the
2824
+ end-effector (this option is for 'pyplot' only)
2825
+ fellipse
2826
+ (Plot Option) Plot the force ellipse at the
2827
+ end-effector (this option is for 'pyplot' only)
2828
+
2829
+ Returns
2830
+ -------
2831
+ env
2832
+ A reference to the PyPlot object which controls the
2833
+ matplotlib figure
2834
+
2835
+ Notes
2836
+ -----
2837
+ - Program execution is blocked until the teach window is
2838
+ dismissed. If ``block=False`` the method is non-blocking but
2839
+ you need to poll the window manager to ensure that the window
2840
+ remains responsive.
2841
+ - The slider limits are derived from the joint limit properties.
2842
+ If not set then:
2843
+ - For revolute joints they are assumed to be [-pi, +pi]
2844
+ - For prismatic joint they are assumed unknown and an error
2845
+ occurs.
2846
+
2847
+ """
2848
+
2849
+ if q is None:
2850
+ q = np.zeros((self.n,))
2851
+ else:
2852
+ q = getvector(q, self.n)
2853
+
2854
+ # Make an empty 3D figure
2855
+ env = self._get_graphical_backend(backend)
2856
+
2857
+ if type(env).__name__ == "Swift": # pragma: nocover
2858
+ raise TypeError("teach() not supported for Swift backend")
2859
+
2860
+ # Add the self to the figure in readonly mode
2861
+ env.launch("Teach " + self.name, limits=limits)
2862
+ env.add(
2863
+ self,
2864
+ readonly=True,
2865
+ # jointaxes=jointaxes,
2866
+ # jointlabels=jointlabels,
2867
+ # eeframe=eeframe,
2868
+ # shadow=shadow,
2869
+ # name=name,
2870
+ )
2871
+ self._active_plot_env = env
2872
+
2873
+ env._add_teach_panel(self, q)
2874
+
2875
+ if vellipse:
2876
+ vell = self.vellipse(q, centre="ee", scale=0.5, add=False)
2877
+ env.add(vell)
2878
+
2879
+ if fellipse:
2880
+ fell = self.fellipse(q, centre="ee", add=False)
2881
+ env.add(fell)
2882
+
2883
+ # Keep the plot open
2884
+ if block: # pragma nocover
2885
+ env.hold()
2886
+
2887
+ return env
2888
+
2889
+ # --------------------------------------------------------------------- #
2890
+
2891
+ # --------------------------------------------------------------------- #
2892
+ # --------- Utility Methods ------------------------------------------- #
2893
+ # --------------------------------------------------------------------- #
2894
+
2895
+ def showgraph(self, display_graph: bool = True, **kwargs) -> Union[None, str]:
2896
+ """
2897
+ Display a link transform graph in browser
2898
+
2899
+ ``robot.showgraph()`` displays a graph of the robot's link frames
2900
+ and the ETS between them. It uses GraphViz dot.
2901
+
2902
+ The nodes are:
2903
+ - Base is shown as a grey square. This is the world frame origin,
2904
+ but can be changed using the ``base`` attribute of the robot.
2905
+ - Link frames are indicated by circles
2906
+ - ETS transforms are indicated by rounded boxes
2907
+
2908
+ The edges are:
2909
+ - an arrow if `jtype` is False or the joint is fixed
2910
+ - an arrow with a round head if `jtype` is True and the joint is
2911
+ revolute
2912
+ - an arrow with a box head if `jtype` is True and the joint is
2913
+ prismatic
2914
+
2915
+ Edge labels or nodes in blue have a fixed transformation to the
2916
+ preceding link.
2917
+
2918
+ Parameters
2919
+ ----------
2920
+ display_graph
2921
+ Open the graph in a browser if True. Otherwise will return the
2922
+ file path
2923
+ etsbox
2924
+ Put the link ETS in a box, otherwise an edge label
2925
+ jtype
2926
+ Arrowhead to node indicates revolute or prismatic type
2927
+ static
2928
+ Show static joints in blue and bold
2929
+
2930
+ Examples
2931
+ --------
2932
+ >>> import roboticstoolbox as rtb
2933
+ >>> panda = rtb.models.URDF.Panda()
2934
+ >>> panda.showgraph()
2935
+
2936
+ .. image:: ../figs/panda-graph.svg
2937
+ :width: 600
2938
+
2939
+ See Also
2940
+ --------
2941
+ :func:`dotfile`
2942
+
2943
+ """
2944
+
2945
+ # Lazy import
2946
+ import tempfile
2947
+ import subprocess
2948
+ import webbrowser
2949
+
2950
+ # create the temporary dotfile
2951
+ dotfile = tempfile.TemporaryFile(mode="w")
2952
+ self.dotfile(dotfile, **kwargs)
2953
+
2954
+ # rewind the dot file, create PDF file in the filesystem, run dot
2955
+ dotfile.seek(0)
2956
+ pdffile = tempfile.NamedTemporaryFile(suffix=".pdf", delete=False)
2957
+ subprocess.run("dot -Tpdf", shell=True, stdin=dotfile, stdout=pdffile)
2958
+
2959
+ # open the PDF file in browser (hopefully portable), then cleanup
2960
+ if display_graph: # pragma nocover
2961
+ webbrowser.open(f"file://{pdffile.name}")
2962
+ else:
2963
+ return pdffile.name
2964
+
2965
+ def dotfile(
2966
+ self,
2967
+ filename: Union[str, IO[str]],
2968
+ etsbox: bool = False,
2969
+ ets: L["full", "brief"] = "full", # noqa
2970
+ jtype: bool = False,
2971
+ static: bool = True,
2972
+ ):
2973
+ """
2974
+ Write a link transform graph as a GraphViz dot file
2975
+
2976
+ The file can be processed using dot:
2977
+ % dot -Tpng -o out.png dotfile.dot
2978
+
2979
+ The nodes are:
2980
+ - Base is shown as a grey square. This is the world frame origin,
2981
+ but can be changed using the ``base`` attribute of the robot.
2982
+ - Link frames are indicated by circles
2983
+ - ETS transforms are indicated by rounded boxes
2984
+
2985
+ The edges are:
2986
+ - an arrow if `jtype` is False or the joint is fixed
2987
+ - an arrow with a round head if `jtype` is True and the joint is
2988
+ revolute
2989
+ - an arrow with a box head if `jtype` is True and the joint is
2990
+ prismatic
2991
+
2992
+ Edge labels or nodes in blue have a fixed transformation to the
2993
+ preceding link.
2994
+
2995
+ Note
2996
+ ----
2997
+ If ``filename`` is a file object then the file will *not*
2998
+ be closed after the GraphViz model is written.
2999
+
3000
+ Parameters
3001
+ ----------
3002
+ file
3003
+ Name of file to write to
3004
+ etsbox
3005
+ Put the link ETS in a box, otherwise an edge label
3006
+ ets
3007
+ Display the full ets with "full" or a brief version with "brief"
3008
+ jtype
3009
+ Arrowhead to node indicates revolute or prismatic type
3010
+ static
3011
+ Show static joints in blue and bold
3012
+
3013
+ See Also
3014
+ --------
3015
+ :func:`showgraph`
3016
+
3017
+ """
3018
+
3019
+ if isinstance(filename, str):
3020
+ file = open(filename, "w")
3021
+ else:
3022
+ file = filename
3023
+
3024
+ header = r"""digraph G {
3025
+ graph [rankdir=LR];
3026
+ """
3027
+
3028
+ def draw_edge(link, etsbox, jtype, static):
3029
+ # draw the edge
3030
+ if jtype:
3031
+ if link.isprismatic:
3032
+ edge_options = 'arrowhead="box", arrowtail="inv", dir="both"'
3033
+ elif link.isrevolute:
3034
+ edge_options = 'arrowhead="dot", arrowtail="inv", dir="both"'
3035
+ else:
3036
+ edge_options = 'arrowhead="normal"'
3037
+ else:
3038
+ edge_options = 'arrowhead="normal"'
3039
+
3040
+ if link.parent is None:
3041
+ parent = "BASE"
3042
+ else:
3043
+ parent = link.parent.name
3044
+
3045
+ if etsbox:
3046
+ # put the ets fragment in a box
3047
+ if not link.isjoint and static:
3048
+ node_options = ', fontcolor="blue"'
3049
+ else:
3050
+ node_options = ""
3051
+
3052
+ try:
3053
+ file.write(
3054
+ ' {}_ets [shape=box, style=rounded, label="{}"{}];\n'.format(
3055
+ link.name,
3056
+ link.ets.__str__(q=f"q{link.jindex}"),
3057
+ node_options,
3058
+ )
3059
+ )
3060
+ except UnicodeEncodeError: # pragma nocover
3061
+ file.write(
3062
+ ' {}_ets [shape=box, style=rounded, label="{}"{}];\n'.format(
3063
+ link.name,
3064
+ link.ets.__str__(q=f"q{link.jindex}")
3065
+ .encode("ascii", "ignore")
3066
+ .decode("ascii"),
3067
+ node_options,
3068
+ )
3069
+ )
3070
+
3071
+ file.write(" {} -> {}_ets;\n".format(parent, link.name))
3072
+ file.write(
3073
+ " {}_ets -> {} [{}];\n".format(link.name, link.name, edge_options)
3074
+ )
3075
+ else:
3076
+ # put the ets fragment as an edge label
3077
+ if not link.isjoint and static:
3078
+ edge_options += 'fontcolor="blue"'
3079
+ if ets == "full":
3080
+ estr = link.ets.__str__(q=f"q{link.jindex}")
3081
+ elif ets == "brief":
3082
+ if link.jindex is None:
3083
+ estr = ""
3084
+ else:
3085
+ estr = f"...q{link.jindex}"
3086
+ else:
3087
+ return
3088
+ try:
3089
+ file.write(
3090
+ ' {} -> {} [label="{}", {}];\n'.format(
3091
+ parent,
3092
+ link.name,
3093
+ estr,
3094
+ edge_options,
3095
+ )
3096
+ )
3097
+ except UnicodeEncodeError: # pragma nocover
3098
+ file.write(
3099
+ ' {} -> {} [label="{}", {}];\n'.format(
3100
+ parent,
3101
+ link.name,
3102
+ estr.encode("ascii", "ignore").decode("ascii"),
3103
+ edge_options,
3104
+ )
3105
+ )
3106
+
3107
+ file.write(header)
3108
+
3109
+ # add the base link
3110
+ file.write(" BASE [shape=square, style=filled, fillcolor=gray]\n")
3111
+
3112
+ # add the links
3113
+ for link in self:
3114
+ # draw the link frame node (circle) or ee node (doublecircle)
3115
+ if link in self.ee_links:
3116
+ # end-effector
3117
+ node_options = 'shape="doublecircle", color="blue", fontcolor="blue"'
3118
+ else:
3119
+ node_options = 'shape="circle"'
3120
+
3121
+ file.write(" {} [{}];\n".format(link.name, node_options))
3122
+
3123
+ draw_edge(link, etsbox, jtype, static)
3124
+
3125
+ for gripper in self.grippers:
3126
+ for link in gripper.links:
3127
+ file.write(" {} [shape=cds];\n".format(link.name))
3128
+ draw_edge(link, etsbox, jtype, static)
3129
+
3130
+ file.write("}\n")
3131
+
3132
+ if isinstance(filename, str):
3133
+ file.close() # noqa