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.
- roboticstoolbox/__init__.py +104 -0
- roboticstoolbox/backends/Connector.py +107 -0
- roboticstoolbox/backends/Dynamixel/README.md +9 -0
- roboticstoolbox/backends/Dynamixel/dynamixel.json +581 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_io.py +450 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/LICENSE +201 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/README.md +28 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/ReleaseNote.md +181 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/__init__.py +27 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/group_bulk_read.py +163 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/group_bulk_write.py +109 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/group_sync_read.py +166 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/group_sync_write.py +99 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/packet_handler.py +33 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/port_handler.py +155 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/protocol1_packet_handler.py +548 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/protocol2_packet_handler.py +1080 -0
- roboticstoolbox/backends/Dynamixel/dynamixel_sdk/robotis_def.py +75 -0
- roboticstoolbox/backends/Dynamixel/dyndata.py +121 -0
- roboticstoolbox/backends/PyPlot/EllipsePlot.py +253 -0
- roboticstoolbox/backends/PyPlot/PyPlot.py +769 -0
- roboticstoolbox/backends/PyPlot/PyPlot2.py +526 -0
- roboticstoolbox/backends/PyPlot/README.md +67 -0
- roboticstoolbox/backends/PyPlot/RobotPlot.py +247 -0
- roboticstoolbox/backends/PyPlot/RobotPlot2.py +123 -0
- roboticstoolbox/backends/PyPlot/__init__.py +4 -0
- roboticstoolbox/backends/ROS/ROS.py +129 -0
- roboticstoolbox/backends/ROS/__init__.py +3 -0
- roboticstoolbox/backends/__init__.py +39 -0
- roboticstoolbox/backends/swift/__init__.py +26 -0
- roboticstoolbox/bin/__init__.py +0 -0
- roboticstoolbox/bin/rtbtool.py +307 -0
- roboticstoolbox/blocks/Icons/250x250/armplot.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/bicycle.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/camera.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/circlepath.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/coriolis.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/ctraj.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/delta2tr.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/diffsteer.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/fdyn.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/fdynx.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/fkine.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/gravload.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/idyn.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/idynx.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/ikine.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/inertia.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/jacobian.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/jtraj.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/lspb.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/multirotor.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/multirotormixer.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/multirotorplot.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/point2tr.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/tr2delta.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/tr2t.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/unicycle.png +0 -0
- roboticstoolbox/blocks/Icons/250x250/vehicleplot.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/armplot.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/bicycle.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/camera.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/circlepath.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/coriolis.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/delta2tr.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/diffsteer.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/fdyn.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/fdynx.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/fkine.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/gravload.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/idyn.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/idynx.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/ikine.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/inertia.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/jacobian.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/jtraj.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/lspb.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/multirotor.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/multirotormixer.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/multirotorplot.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/point2tr.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/tr2delta.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/tr2t.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/unicycle.png +0 -0
- roboticstoolbox/blocks/Icons/50x50/vehicleplot.png +0 -0
- roboticstoolbox/blocks/Icons/armplot.png +0 -0
- roboticstoolbox/blocks/Icons/bicycle.png +0 -0
- roboticstoolbox/blocks/Icons/camera.png +0 -0
- roboticstoolbox/blocks/Icons/circlepath.png +0 -0
- roboticstoolbox/blocks/Icons/coriolis.png +0 -0
- roboticstoolbox/blocks/Icons/ctraj.png +0 -0
- roboticstoolbox/blocks/Icons/delta2tr.png +0 -0
- roboticstoolbox/blocks/Icons/diffsteer.png +0 -0
- roboticstoolbox/blocks/Icons/fdyn.png +0 -0
- roboticstoolbox/blocks/Icons/fdynx.png +0 -0
- roboticstoolbox/blocks/Icons/fkine.png +0 -0
- roboticstoolbox/blocks/Icons/gravload.png +0 -0
- roboticstoolbox/blocks/Icons/idyn.png +0 -0
- roboticstoolbox/blocks/Icons/idynx.png +0 -0
- roboticstoolbox/blocks/Icons/ikine.png +0 -0
- roboticstoolbox/blocks/Icons/inertia.png +0 -0
- roboticstoolbox/blocks/Icons/jacobian.png +0 -0
- roboticstoolbox/blocks/Icons/jtraj.png +0 -0
- roboticstoolbox/blocks/Icons/lspb.png +0 -0
- roboticstoolbox/blocks/Icons/multirotor.png +0 -0
- roboticstoolbox/blocks/Icons/multirotormixer.png +0 -0
- roboticstoolbox/blocks/Icons/multirotorplot.png +0 -0
- roboticstoolbox/blocks/Icons/point2tr.png +0 -0
- roboticstoolbox/blocks/Icons/tr2delta.png +0 -0
- roboticstoolbox/blocks/Icons/tr2t.png +0 -0
- roboticstoolbox/blocks/Icons/unicycle.png +0 -0
- roboticstoolbox/blocks/Icons/vehicleplot.png +0 -0
- roboticstoolbox/blocks/README.md +43 -0
- roboticstoolbox/blocks/__init__.py +6 -0
- roboticstoolbox/blocks/arm.py +1587 -0
- roboticstoolbox/blocks/mobile.py +500 -0
- roboticstoolbox/blocks/quad_model.py +132 -0
- roboticstoolbox/blocks/spatial.py +245 -0
- roboticstoolbox/blocks/uav.py +949 -0
- roboticstoolbox/core/Eigen/Cholesky +45 -0
- roboticstoolbox/core/Eigen/CholmodSupport +48 -0
- roboticstoolbox/core/Eigen/Core +384 -0
- roboticstoolbox/core/Eigen/Dense +7 -0
- roboticstoolbox/core/Eigen/Eigen +2 -0
- roboticstoolbox/core/Eigen/Eigenvalues +60 -0
- roboticstoolbox/core/Eigen/Geometry +59 -0
- roboticstoolbox/core/Eigen/Householder +29 -0
- roboticstoolbox/core/Eigen/IterativeLinearSolvers +48 -0
- roboticstoolbox/core/Eigen/Jacobi +32 -0
- roboticstoolbox/core/Eigen/KLUSupport +41 -0
- roboticstoolbox/core/Eigen/LU +47 -0
- roboticstoolbox/core/Eigen/MetisSupport +35 -0
- roboticstoolbox/core/Eigen/OrderingMethods +70 -0
- roboticstoolbox/core/Eigen/PaStiXSupport +49 -0
- roboticstoolbox/core/Eigen/PardisoSupport +35 -0
- roboticstoolbox/core/Eigen/QR +50 -0
- roboticstoolbox/core/Eigen/QtAlignedMalloc +39 -0
- roboticstoolbox/core/Eigen/SPQRSupport +34 -0
- roboticstoolbox/core/Eigen/SVD +50 -0
- roboticstoolbox/core/Eigen/Sparse +34 -0
- roboticstoolbox/core/Eigen/SparseCholesky +37 -0
- roboticstoolbox/core/Eigen/SparseCore +69 -0
- roboticstoolbox/core/Eigen/SparseLU +50 -0
- roboticstoolbox/core/Eigen/SparseQR +36 -0
- roboticstoolbox/core/Eigen/StdDeque +27 -0
- roboticstoolbox/core/Eigen/StdList +26 -0
- roboticstoolbox/core/Eigen/StdVector +27 -0
- roboticstoolbox/core/Eigen/SuperLUSupport +64 -0
- roboticstoolbox/core/Eigen/UmfPackSupport +40 -0
- roboticstoolbox/core/Eigen/src/Cholesky/LDLT.h +688 -0
- roboticstoolbox/core/Eigen/src/Cholesky/LLT.h +558 -0
- roboticstoolbox/core/Eigen/src/Cholesky/LLT_LAPACKE.h +99 -0
- roboticstoolbox/core/Eigen/src/CholmodSupport/CholmodSupport.h +682 -0
- roboticstoolbox/core/Eigen/src/Core/ArithmeticSequence.h +413 -0
- roboticstoolbox/core/Eigen/src/Core/Array.h +417 -0
- roboticstoolbox/core/Eigen/src/Core/ArrayBase.h +226 -0
- roboticstoolbox/core/Eigen/src/Core/ArrayWrapper.h +209 -0
- roboticstoolbox/core/Eigen/src/Core/Assign.h +90 -0
- roboticstoolbox/core/Eigen/src/Core/AssignEvaluator.h +1010 -0
- roboticstoolbox/core/Eigen/src/Core/Assign_MKL.h +178 -0
- roboticstoolbox/core/Eigen/src/Core/BandMatrix.h +353 -0
- roboticstoolbox/core/Eigen/src/Core/Block.h +448 -0
- roboticstoolbox/core/Eigen/src/Core/BooleanRedux.h +162 -0
- roboticstoolbox/core/Eigen/src/Core/CommaInitializer.h +164 -0
- roboticstoolbox/core/Eigen/src/Core/ConditionEstimator.h +175 -0
- roboticstoolbox/core/Eigen/src/Core/CoreEvaluators.h +1741 -0
- roboticstoolbox/core/Eigen/src/Core/CoreIterators.h +132 -0
- roboticstoolbox/core/Eigen/src/Core/CwiseBinaryOp.h +183 -0
- roboticstoolbox/core/Eigen/src/Core/CwiseNullaryOp.h +1001 -0
- roboticstoolbox/core/Eigen/src/Core/CwiseTernaryOp.h +197 -0
- roboticstoolbox/core/Eigen/src/Core/CwiseUnaryOp.h +103 -0
- roboticstoolbox/core/Eigen/src/Core/CwiseUnaryView.h +132 -0
- roboticstoolbox/core/Eigen/src/Core/DenseBase.h +701 -0
- roboticstoolbox/core/Eigen/src/Core/DenseCoeffsBase.h +685 -0
- roboticstoolbox/core/Eigen/src/Core/DenseStorage.h +652 -0
- roboticstoolbox/core/Eigen/src/Core/Diagonal.h +258 -0
- roboticstoolbox/core/Eigen/src/Core/DiagonalMatrix.h +391 -0
- roboticstoolbox/core/Eigen/src/Core/DiagonalProduct.h +28 -0
- roboticstoolbox/core/Eigen/src/Core/Dot.h +318 -0
- roboticstoolbox/core/Eigen/src/Core/EigenBase.h +160 -0
- roboticstoolbox/core/Eigen/src/Core/ForceAlignedAccess.h +150 -0
- roboticstoolbox/core/Eigen/src/Core/Fuzzy.h +155 -0
- roboticstoolbox/core/Eigen/src/Core/GeneralProduct.h +465 -0
- roboticstoolbox/core/Eigen/src/Core/GenericPacketMath.h +1040 -0
- roboticstoolbox/core/Eigen/src/Core/GlobalFunctions.h +194 -0
- roboticstoolbox/core/Eigen/src/Core/IO.h +258 -0
- roboticstoolbox/core/Eigen/src/Core/IndexedView.h +237 -0
- roboticstoolbox/core/Eigen/src/Core/Inverse.h +117 -0
- roboticstoolbox/core/Eigen/src/Core/Map.h +171 -0
- roboticstoolbox/core/Eigen/src/Core/MapBase.h +310 -0
- roboticstoolbox/core/Eigen/src/Core/MathFunctions.h +2057 -0
- roboticstoolbox/core/Eigen/src/Core/MathFunctionsImpl.h +200 -0
- roboticstoolbox/core/Eigen/src/Core/Matrix.h +565 -0
- roboticstoolbox/core/Eigen/src/Core/MatrixBase.h +547 -0
- roboticstoolbox/core/Eigen/src/Core/NestByValue.h +85 -0
- roboticstoolbox/core/Eigen/src/Core/NoAlias.h +109 -0
- roboticstoolbox/core/Eigen/src/Core/NumTraits.h +335 -0
- roboticstoolbox/core/Eigen/src/Core/PartialReduxEvaluator.h +232 -0
- roboticstoolbox/core/Eigen/src/Core/PermutationMatrix.h +605 -0
- roboticstoolbox/core/Eigen/src/Core/PlainObjectBase.h +1128 -0
- roboticstoolbox/core/Eigen/src/Core/Product.h +191 -0
- roboticstoolbox/core/Eigen/src/Core/ProductEvaluators.h +1179 -0
- roboticstoolbox/core/Eigen/src/Core/Random.h +218 -0
- roboticstoolbox/core/Eigen/src/Core/Redux.h +515 -0
- roboticstoolbox/core/Eigen/src/Core/Ref.h +381 -0
- roboticstoolbox/core/Eigen/src/Core/Replicate.h +142 -0
- roboticstoolbox/core/Eigen/src/Core/Reshaped.h +454 -0
- roboticstoolbox/core/Eigen/src/Core/ReturnByValue.h +119 -0
- roboticstoolbox/core/Eigen/src/Core/Reverse.h +217 -0
- roboticstoolbox/core/Eigen/src/Core/Select.h +164 -0
- roboticstoolbox/core/Eigen/src/Core/SelfAdjointView.h +365 -0
- roboticstoolbox/core/Eigen/src/Core/SelfCwiseBinaryOp.h +47 -0
- roboticstoolbox/core/Eigen/src/Core/Solve.h +188 -0
- roboticstoolbox/core/Eigen/src/Core/SolveTriangular.h +235 -0
- roboticstoolbox/core/Eigen/src/Core/SolverBase.h +168 -0
- roboticstoolbox/core/Eigen/src/Core/StableNorm.h +251 -0
- roboticstoolbox/core/Eigen/src/Core/StlIterators.h +463 -0
- roboticstoolbox/core/Eigen/src/Core/Stride.h +116 -0
- roboticstoolbox/core/Eigen/src/Core/Swap.h +68 -0
- roboticstoolbox/core/Eigen/src/Core/Transpose.h +464 -0
- roboticstoolbox/core/Eigen/src/Core/Transpositions.h +386 -0
- roboticstoolbox/core/Eigen/src/Core/TriangularMatrix.h +1001 -0
- roboticstoolbox/core/Eigen/src/Core/VectorBlock.h +96 -0
- roboticstoolbox/core/Eigen/src/Core/VectorwiseOp.h +784 -0
- roboticstoolbox/core/Eigen/src/Core/Visitor.h +381 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AVX/Complex.h +372 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AVX/MathFunctions.h +228 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AVX/PacketMath.h +1574 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AVX/TypeCasting.h +115 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AVX512/Complex.h +422 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AVX512/MathFunctions.h +362 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AVX512/PacketMath.h +2303 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AVX512/TypeCasting.h +89 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/Complex.h +417 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/MathFunctions.h +90 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/MatrixProduct.h +2937 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/MatrixProductCommon.h +221 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h +629 -0
- roboticstoolbox/core/Eigen/src/Core/arch/AltiVec/PacketMath.h +2711 -0
- roboticstoolbox/core/Eigen/src/Core/arch/CUDA/Complex.h +258 -0
- roboticstoolbox/core/Eigen/src/Core/arch/Default/BFloat16.h +700 -0
- roboticstoolbox/core/Eigen/src/Core/arch/Default/ConjHelper.h +117 -0
- roboticstoolbox/core/Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h +1649 -0
- roboticstoolbox/core/Eigen/src/Core/arch/Default/GenericPacketMathFunctionsFwd.h +110 -0
- roboticstoolbox/core/Eigen/src/Core/arch/Default/Half.h +942 -0
- roboticstoolbox/core/Eigen/src/Core/arch/Default/Settings.h +49 -0
- roboticstoolbox/core/Eigen/src/Core/arch/Default/TypeCasting.h +120 -0
- roboticstoolbox/core/Eigen/src/Core/arch/GPU/MathFunctions.h +103 -0
- roboticstoolbox/core/Eigen/src/Core/arch/GPU/PacketMath.h +1685 -0
- roboticstoolbox/core/Eigen/src/Core/arch/GPU/TypeCasting.h +80 -0
- roboticstoolbox/core/Eigen/src/Core/arch/HIP/hcc/math_constants.h +23 -0
- roboticstoolbox/core/Eigen/src/Core/arch/MSA/Complex.h +648 -0
- roboticstoolbox/core/Eigen/src/Core/arch/MSA/MathFunctions.h +387 -0
- roboticstoolbox/core/Eigen/src/Core/arch/MSA/PacketMath.h +1233 -0
- roboticstoolbox/core/Eigen/src/Core/arch/NEON/Complex.h +584 -0
- roboticstoolbox/core/Eigen/src/Core/arch/NEON/GeneralBlockPanelKernel.h +183 -0
- roboticstoolbox/core/Eigen/src/Core/arch/NEON/MathFunctions.h +75 -0
- roboticstoolbox/core/Eigen/src/Core/arch/NEON/PacketMath.h +4587 -0
- roboticstoolbox/core/Eigen/src/Core/arch/NEON/TypeCasting.h +1419 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SSE/Complex.h +351 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SSE/MathFunctions.h +199 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SSE/PacketMath.h +1505 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SSE/TypeCasting.h +142 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SVE/MathFunctions.h +44 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SVE/PacketMath.h +752 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SVE/TypeCasting.h +49 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SYCL/InteropHeaders.h +232 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SYCL/MathFunctions.h +301 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SYCL/PacketMath.h +670 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SYCL/SyclMemoryModel.h +694 -0
- roboticstoolbox/core/Eigen/src/Core/arch/SYCL/TypeCasting.h +85 -0
- roboticstoolbox/core/Eigen/src/Core/arch/ZVector/Complex.h +426 -0
- roboticstoolbox/core/Eigen/src/Core/arch/ZVector/MathFunctions.h +233 -0
- roboticstoolbox/core/Eigen/src/Core/arch/ZVector/PacketMath.h +1060 -0
- roboticstoolbox/core/Eigen/src/Core/functors/AssignmentFunctors.h +177 -0
- roboticstoolbox/core/Eigen/src/Core/functors/BinaryFunctors.h +541 -0
- roboticstoolbox/core/Eigen/src/Core/functors/NullaryFunctors.h +189 -0
- roboticstoolbox/core/Eigen/src/Core/functors/StlFunctors.h +166 -0
- roboticstoolbox/core/Eigen/src/Core/functors/TernaryFunctors.h +25 -0
- roboticstoolbox/core/Eigen/src/Core/functors/UnaryFunctors.h +1131 -0
- roboticstoolbox/core/Eigen/src/Core/products/GeneralBlockPanelKernel.h +2645 -0
- roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixMatrix.h +517 -0
- roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h +317 -0
- roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h +145 -0
- roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h +124 -0
- roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixVector.h +518 -0
- roboticstoolbox/core/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h +136 -0
- roboticstoolbox/core/Eigen/src/Core/products/Parallelizer.h +180 -0
- roboticstoolbox/core/Eigen/src/Core/products/SelfadjointMatrixMatrix.h +544 -0
- roboticstoolbox/core/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h +295 -0
- roboticstoolbox/core/Eigen/src/Core/products/SelfadjointMatrixVector.h +262 -0
- roboticstoolbox/core/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h +118 -0
- roboticstoolbox/core/Eigen/src/Core/products/SelfadjointProduct.h +133 -0
- roboticstoolbox/core/Eigen/src/Core/products/SelfadjointRank2Update.h +94 -0
- roboticstoolbox/core/Eigen/src/Core/products/TriangularMatrixMatrix.h +472 -0
- roboticstoolbox/core/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h +317 -0
- roboticstoolbox/core/Eigen/src/Core/products/TriangularMatrixVector.h +350 -0
- roboticstoolbox/core/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h +255 -0
- roboticstoolbox/core/Eigen/src/Core/products/TriangularSolverMatrix.h +337 -0
- roboticstoolbox/core/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h +167 -0
- roboticstoolbox/core/Eigen/src/Core/products/TriangularSolverVector.h +148 -0
- roboticstoolbox/core/Eigen/src/Core/util/BlasUtil.h +583 -0
- roboticstoolbox/core/Eigen/src/Core/util/ConfigureVectorization.h +512 -0
- roboticstoolbox/core/Eigen/src/Core/util/Constants.h +563 -0
- roboticstoolbox/core/Eigen/src/Core/util/DisableStupidWarnings.h +106 -0
- roboticstoolbox/core/Eigen/src/Core/util/ForwardDeclarations.h +322 -0
- roboticstoolbox/core/Eigen/src/Core/util/IndexedViewHelper.h +186 -0
- roboticstoolbox/core/Eigen/src/Core/util/IntegralConstant.h +272 -0
- roboticstoolbox/core/Eigen/src/Core/util/MKL_support.h +137 -0
- roboticstoolbox/core/Eigen/src/Core/util/Macros.h +1464 -0
- roboticstoolbox/core/Eigen/src/Core/util/Memory.h +1163 -0
- roboticstoolbox/core/Eigen/src/Core/util/Meta.h +812 -0
- roboticstoolbox/core/Eigen/src/Core/util/NonMPL2.h +3 -0
- roboticstoolbox/core/Eigen/src/Core/util/ReenableStupidWarnings.h +31 -0
- roboticstoolbox/core/Eigen/src/Core/util/ReshapedHelper.h +51 -0
- roboticstoolbox/core/Eigen/src/Core/util/StaticAssert.h +221 -0
- roboticstoolbox/core/Eigen/src/Core/util/SymbolicIndex.h +293 -0
- roboticstoolbox/core/Eigen/src/Core/util/XprHelper.h +856 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/ComplexEigenSolver.h +346 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/ComplexSchur.h +462 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h +91 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/EigenSolver.h +622 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h +418 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h +226 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/HessenbergDecomposition.h +374 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h +158 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/RealQZ.h +657 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/RealSchur.h +558 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h +77 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h +904 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h +87 -0
- roboticstoolbox/core/Eigen/src/Eigenvalues/Tridiagonalization.h +561 -0
- roboticstoolbox/core/Eigen/src/Geometry/AlignedBox.h +486 -0
- roboticstoolbox/core/Eigen/src/Geometry/AngleAxis.h +247 -0
- roboticstoolbox/core/Eigen/src/Geometry/EulerAngles.h +114 -0
- roboticstoolbox/core/Eigen/src/Geometry/Homogeneous.h +501 -0
- roboticstoolbox/core/Eigen/src/Geometry/Hyperplane.h +282 -0
- roboticstoolbox/core/Eigen/src/Geometry/OrthoMethods.h +235 -0
- roboticstoolbox/core/Eigen/src/Geometry/ParametrizedLine.h +232 -0
- roboticstoolbox/core/Eigen/src/Geometry/Quaternion.h +870 -0
- roboticstoolbox/core/Eigen/src/Geometry/Rotation2D.h +199 -0
- roboticstoolbox/core/Eigen/src/Geometry/RotationBase.h +206 -0
- roboticstoolbox/core/Eigen/src/Geometry/Scaling.h +188 -0
- roboticstoolbox/core/Eigen/src/Geometry/Transform.h +1563 -0
- roboticstoolbox/core/Eigen/src/Geometry/Translation.h +202 -0
- roboticstoolbox/core/Eigen/src/Geometry/Umeyama.h +166 -0
- roboticstoolbox/core/Eigen/src/Geometry/arch/Geometry_SIMD.h +168 -0
- roboticstoolbox/core/Eigen/src/Householder/BlockHouseholder.h +110 -0
- roboticstoolbox/core/Eigen/src/Householder/Householder.h +176 -0
- roboticstoolbox/core/Eigen/src/Householder/HouseholderSequence.h +545 -0
- roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h +226 -0
- roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h +212 -0
- roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h +229 -0
- roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h +394 -0
- roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h +453 -0
- roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h +444 -0
- roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h +198 -0
- roboticstoolbox/core/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h +117 -0
- roboticstoolbox/core/Eigen/src/Jacobi/Jacobi.h +483 -0
- roboticstoolbox/core/Eigen/src/KLUSupport/KLUSupport.h +358 -0
- roboticstoolbox/core/Eigen/src/LU/Determinant.h +117 -0
- roboticstoolbox/core/Eigen/src/LU/FullPivLU.h +877 -0
- roboticstoolbox/core/Eigen/src/LU/InverseImpl.h +432 -0
- roboticstoolbox/core/Eigen/src/LU/PartialPivLU.h +624 -0
- roboticstoolbox/core/Eigen/src/LU/PartialPivLU_LAPACKE.h +83 -0
- roboticstoolbox/core/Eigen/src/LU/arch/InverseSize4.h +351 -0
- roboticstoolbox/core/Eigen/src/MetisSupport/MetisSupport.h +137 -0
- roboticstoolbox/core/Eigen/src/OrderingMethods/Amd.h +435 -0
- roboticstoolbox/core/Eigen/src/OrderingMethods/Eigen_Colamd.h +1863 -0
- roboticstoolbox/core/Eigen/src/OrderingMethods/Ordering.h +153 -0
- roboticstoolbox/core/Eigen/src/PaStiXSupport/PaStiXSupport.h +678 -0
- roboticstoolbox/core/Eigen/src/PardisoSupport/PardisoSupport.h +545 -0
- roboticstoolbox/core/Eigen/src/QR/ColPivHouseholderQR.h +674 -0
- roboticstoolbox/core/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h +97 -0
- roboticstoolbox/core/Eigen/src/QR/CompleteOrthogonalDecomposition.h +635 -0
- roboticstoolbox/core/Eigen/src/QR/FullPivHouseholderQR.h +713 -0
- roboticstoolbox/core/Eigen/src/QR/HouseholderQR.h +434 -0
- roboticstoolbox/core/Eigen/src/QR/HouseholderQR_LAPACKE.h +68 -0
- roboticstoolbox/core/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h +335 -0
- roboticstoolbox/core/Eigen/src/SVD/BDCSVD.h +1366 -0
- roboticstoolbox/core/Eigen/src/SVD/JacobiSVD.h +812 -0
- roboticstoolbox/core/Eigen/src/SVD/JacobiSVD_LAPACKE.h +91 -0
- roboticstoolbox/core/Eigen/src/SVD/SVDBase.h +376 -0
- roboticstoolbox/core/Eigen/src/SVD/UpperBidiagonalization.h +414 -0
- roboticstoolbox/core/Eigen/src/SparseCholesky/SimplicialCholesky.h +697 -0
- roboticstoolbox/core/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h +174 -0
- roboticstoolbox/core/Eigen/src/SparseCore/AmbiVector.h +378 -0
- roboticstoolbox/core/Eigen/src/SparseCore/CompressedStorage.h +274 -0
- roboticstoolbox/core/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h +352 -0
- roboticstoolbox/core/Eigen/src/SparseCore/MappedSparseMatrix.h +67 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseAssign.h +270 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseBlock.h +571 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseColEtree.h +206 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseCompressedBase.h +370 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +722 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +150 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseDenseProduct.h +342 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseDiagonalProduct.h +138 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseDot.h +98 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseFuzzy.h +29 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseMap.h +305 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseMatrix.h +1518 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseMatrixBase.h +398 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparsePermutation.h +178 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseProduct.h +181 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseRedux.h +49 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseRef.h +397 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseSelfAdjointView.h +659 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseSolverBase.h +124 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseSparseProductWithPruning.h +198 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseTranspose.h +92 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseTriangularView.h +189 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseUtil.h +186 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseVector.h +478 -0
- roboticstoolbox/core/Eigen/src/SparseCore/SparseView.h +254 -0
- roboticstoolbox/core/Eigen/src/SparseCore/TriangularSolver.h +315 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU.h +923 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLUImpl.h +66 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_Memory.h +226 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_Structs.h +110 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h +375 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_Utils.h +80 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_column_bmod.h +181 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_column_dfs.h +179 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h +107 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_gemm_kernel.h +280 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h +126 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_kernel_bmod.h +130 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_panel_bmod.h +223 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_panel_dfs.h +258 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_pivotL.h +137 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_pruneL.h +136 -0
- roboticstoolbox/core/Eigen/src/SparseLU/SparseLU_relax_snode.h +83 -0
- roboticstoolbox/core/Eigen/src/SparseQR/SparseQR.h +758 -0
- roboticstoolbox/core/Eigen/src/StlSupport/StdDeque.h +116 -0
- roboticstoolbox/core/Eigen/src/StlSupport/StdList.h +106 -0
- roboticstoolbox/core/Eigen/src/StlSupport/StdVector.h +131 -0
- roboticstoolbox/core/Eigen/src/StlSupport/details.h +84 -0
- roboticstoolbox/core/Eigen/src/SuperLUSupport/SuperLUSupport.h +1025 -0
- roboticstoolbox/core/Eigen/src/UmfPackSupport/UmfPackSupport.h +642 -0
- roboticstoolbox/core/Eigen/src/misc/Image.h +82 -0
- roboticstoolbox/core/Eigen/src/misc/Kernel.h +79 -0
- roboticstoolbox/core/Eigen/src/misc/RealSvd2x2.h +55 -0
- roboticstoolbox/core/Eigen/src/misc/blas.h +440 -0
- roboticstoolbox/core/Eigen/src/misc/lapack.h +152 -0
- roboticstoolbox/core/Eigen/src/misc/lapacke.h +16292 -0
- roboticstoolbox/core/Eigen/src/misc/lapacke_mangling.h +17 -0
- roboticstoolbox/core/Eigen/src/plugins/ArrayCwiseBinaryOps.h +358 -0
- roboticstoolbox/core/Eigen/src/plugins/ArrayCwiseUnaryOps.h +696 -0
- roboticstoolbox/core/Eigen/src/plugins/BlockMethods.h +1442 -0
- roboticstoolbox/core/Eigen/src/plugins/CommonCwiseBinaryOps.h +115 -0
- roboticstoolbox/core/Eigen/src/plugins/CommonCwiseUnaryOps.h +177 -0
- roboticstoolbox/core/Eigen/src/plugins/IndexedViewMethods.h +262 -0
- roboticstoolbox/core/Eigen/src/plugins/MatrixCwiseBinaryOps.h +152 -0
- roboticstoolbox/core/Eigen/src/plugins/MatrixCwiseUnaryOps.h +95 -0
- roboticstoolbox/core/Eigen/src/plugins/ReshapedMethods.h +149 -0
- roboticstoolbox/core/fknm.cpp +1557 -0
- roboticstoolbox/core/fknm.h +55 -0
- roboticstoolbox/core/frne.c +351 -0
- roboticstoolbox/core/frne.h +96 -0
- roboticstoolbox/core/ik.cpp +301 -0
- roboticstoolbox/core/ik.h +59 -0
- roboticstoolbox/core/linalg.cpp +316 -0
- roboticstoolbox/core/linalg.h +64 -0
- roboticstoolbox/core/methods.cpp +372 -0
- roboticstoolbox/core/methods.h +32 -0
- roboticstoolbox/core/ne.c +493 -0
- roboticstoolbox/core/structs.cpp +24 -0
- roboticstoolbox/core/structs.h +62 -0
- roboticstoolbox/core/vmath.c +163 -0
- roboticstoolbox/core/vmath.h +32 -0
- roboticstoolbox/fknm.cp313-win_amd64.pyd +0 -0
- roboticstoolbox/frne.cp313-win_amd64.pyd +0 -0
- roboticstoolbox/mobile/Animations.py +485 -0
- roboticstoolbox/mobile/Bug2.py +455 -0
- roboticstoolbox/mobile/CurvaturePolyPlanner.py +179 -0
- roboticstoolbox/mobile/DistanceTransformPlanner.py +395 -0
- roboticstoolbox/mobile/DstarPlanner.py +591 -0
- roboticstoolbox/mobile/DubinsPlanner.py +474 -0
- roboticstoolbox/mobile/EKF.py +1617 -0
- roboticstoolbox/mobile/LatticePlanner.py +419 -0
- roboticstoolbox/mobile/OccGrid.py +613 -0
- roboticstoolbox/mobile/PRMPlanner.py +348 -0
- roboticstoolbox/mobile/ParticleFilter.py +706 -0
- roboticstoolbox/mobile/PlannerBase.py +1009 -0
- roboticstoolbox/mobile/PoseGraph.py +544 -0
- roboticstoolbox/mobile/QuinticPolyPlanner.py +349 -0
- roboticstoolbox/mobile/RRTPlanner.py +359 -0
- roboticstoolbox/mobile/ReedsSheppPlanner.py +545 -0
- roboticstoolbox/mobile/Vehicle.py +1909 -0
- roboticstoolbox/mobile/__init__.py +193 -0
- roboticstoolbox/mobile/drivers.py +390 -0
- roboticstoolbox/mobile/landmarkmap.py +181 -0
- roboticstoolbox/mobile/sensors.py +771 -0
- roboticstoolbox/models/DH/AL5D.py +121 -0
- roboticstoolbox/models/DH/Ball.py +87 -0
- roboticstoolbox/models/DH/Baxter.py +91 -0
- roboticstoolbox/models/DH/Cobra600.py +63 -0
- roboticstoolbox/models/DH/Coil.py +80 -0
- roboticstoolbox/models/DH/Hyper.py +83 -0
- roboticstoolbox/models/DH/Hyper3d.py +85 -0
- roboticstoolbox/models/DH/IRB140.py +159 -0
- roboticstoolbox/models/DH/Jaco.py +102 -0
- roboticstoolbox/models/DH/KR5.py +112 -0
- roboticstoolbox/models/DH/LWR4.py +85 -0
- roboticstoolbox/models/DH/Mico.py +102 -0
- roboticstoolbox/models/DH/Orion5.py +91 -0
- roboticstoolbox/models/DH/P8.py +80 -0
- roboticstoolbox/models/DH/Panda.py +178 -0
- roboticstoolbox/models/DH/Planar2.py +69 -0
- roboticstoolbox/models/DH/Planar3.py +51 -0
- roboticstoolbox/models/DH/Puma560.py +326 -0
- roboticstoolbox/models/DH/README.md +216 -0
- roboticstoolbox/models/DH/Sawyer.py +85 -0
- roboticstoolbox/models/DH/Stanford.py +147 -0
- roboticstoolbox/models/DH/TwoLink.py +109 -0
- roboticstoolbox/models/DH/UR10.py +124 -0
- roboticstoolbox/models/DH/UR3.py +98 -0
- roboticstoolbox/models/DH/UR5.py +98 -0
- roboticstoolbox/models/DH/Uprighttl.py +24 -0
- roboticstoolbox/models/DH/__init__.py +52 -0
- roboticstoolbox/models/ETS/Frankie.py +90 -0
- roboticstoolbox/models/ETS/GenericSeven.py +54 -0
- roboticstoolbox/models/ETS/Omni.py +74 -0
- roboticstoolbox/models/ETS/Panda.py +69 -0
- roboticstoolbox/models/ETS/Planar2.py +49 -0
- roboticstoolbox/models/ETS/Planar_Y.py +65 -0
- roboticstoolbox/models/ETS/Puma560.py +69 -0
- roboticstoolbox/models/ETS/XYPanda.py +84 -0
- roboticstoolbox/models/ETS/__init__.py +20 -0
- roboticstoolbox/models/README.md +9 -0
- roboticstoolbox/models/URDF/AL5D.py +54 -0
- roboticstoolbox/models/URDF/Fetch.py +70 -0
- roboticstoolbox/models/URDF/FetchCamera.py +71 -0
- roboticstoolbox/models/URDF/Frankie.py +75 -0
- roboticstoolbox/models/URDF/FrankieOmni.py +94 -0
- roboticstoolbox/models/URDF/KinovaGen3.py +71 -0
- roboticstoolbox/models/URDF/LBR.py +59 -0
- roboticstoolbox/models/URDF/Mico.py +68 -0
- roboticstoolbox/models/URDF/PR2.py +64 -0
- roboticstoolbox/models/URDF/Panda.py +67 -0
- roboticstoolbox/models/URDF/Puma560.py +97 -0
- roboticstoolbox/models/URDF/UR10.py +53 -0
- roboticstoolbox/models/URDF/UR3.py +53 -0
- roboticstoolbox/models/URDF/UR5.py +74 -0
- roboticstoolbox/models/URDF/Valkyrie.py +84 -0
- roboticstoolbox/models/URDF/YuMi.py +109 -0
- roboticstoolbox/models/URDF/__init__.py +53 -0
- roboticstoolbox/models/URDF/px100.py +56 -0
- roboticstoolbox/models/URDF/px150.py +56 -0
- roboticstoolbox/models/URDF/rx150.py +56 -0
- roboticstoolbox/models/URDF/rx200.py +56 -0
- roboticstoolbox/models/URDF/vx300.py +56 -0
- roboticstoolbox/models/URDF/vx300s.py +56 -0
- roboticstoolbox/models/URDF/wx200.py +56 -0
- roboticstoolbox/models/URDF/wx250.py +56 -0
- roboticstoolbox/models/URDF/wx250s.py +56 -0
- roboticstoolbox/models/__init__.py +7 -0
- roboticstoolbox/models/list.py +119 -0
- roboticstoolbox/robot/BaseRobot.py +3133 -0
- roboticstoolbox/robot/DHFactor.py +522 -0
- roboticstoolbox/robot/DHLink.py +981 -0
- roboticstoolbox/robot/DHRobot.py +2520 -0
- roboticstoolbox/robot/Dynamics.py +1620 -0
- roboticstoolbox/robot/ELink.py +23 -0
- roboticstoolbox/robot/ERobot.py +25 -0
- roboticstoolbox/robot/ET.py +1097 -0
- roboticstoolbox/robot/ETS.py +3542 -0
- roboticstoolbox/robot/Gripper.py +282 -0
- roboticstoolbox/robot/IK.py +1522 -0
- roboticstoolbox/robot/Link.py +1698 -0
- roboticstoolbox/robot/PoERobot.py +348 -0
- roboticstoolbox/robot/Robot.py +2100 -0
- roboticstoolbox/robot/RobotKinematics.py +1725 -0
- roboticstoolbox/robot/RobotProto.py +92 -0
- roboticstoolbox/robot/__init__.py +54 -0
- roboticstoolbox/tools/DHFactor.py +375 -0
- roboticstoolbox/tools/Ticker.py +53 -0
- roboticstoolbox/tools/__init__.py +54 -0
- roboticstoolbox/tools/data.py +187 -0
- roboticstoolbox/tools/jsingu.py +51 -0
- roboticstoolbox/tools/null.py +48 -0
- roboticstoolbox/tools/numerical.py +96 -0
- roboticstoolbox/tools/p_servo.py +106 -0
- roboticstoolbox/tools/params.py +11 -0
- roboticstoolbox/tools/plot.py +109 -0
- roboticstoolbox/tools/trajectory.py +1152 -0
- roboticstoolbox/tools/types.py +13 -0
- roboticstoolbox/tools/urdf/__init__.py +45 -0
- roboticstoolbox/tools/urdf/tests/data/ur5.urdf +341 -0
- roboticstoolbox/tools/urdf/tests/test_urdf.py +116 -0
- roboticstoolbox/tools/urdf/urdf.py +1976 -0
- roboticstoolbox/tools/urdf/utils.py +50 -0
- roboticstoolbox/tools/xacro/__init__.py +1148 -0
- roboticstoolbox/tools/xacro/cli.py +128 -0
- roboticstoolbox/tools/xacro/color.py +66 -0
- roboticstoolbox/tools/xacro/tests/CMakeLists.txt +4 -0
- roboticstoolbox/tools/xacro/tests/broken.xacro +1 -0
- roboticstoolbox/tools/xacro/tests/emoji.xacro +5 -0
- roboticstoolbox/tools/xacro/tests/include1.xacro +4 -0
- roboticstoolbox/tools/xacro/tests/include1.xml +1 -0
- roboticstoolbox/tools/xacro/tests/include2.xacro +4 -0
- roboticstoolbox/tools/xacro/tests/include2.xml +1 -0
- roboticstoolbox/tools/xacro/tests/robots/README +4 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/base_v0/base.gazebo.xacro +59 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/base_v0/base.transmission.xacro +24 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/base_v0/base.urdf.xacro +264 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/common.xacro +71 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/forearm_v0/forearm.gazebo.xacro +36 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/forearm_v0/forearm.transmission.xacro +20 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/forearm_v0/forearm.urdf.xacro +130 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/gazebo/gazebo.urdf.xacro +24 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/gripper_v0/gripper.gazebo.xacro +288 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/gripper_v0/gripper.transmission.xacro +50 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/gripper_v0/gripper.urdf.xacro +374 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/head_v0/head.gazebo.xacro +16 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/head_v0/head.transmission.xacro +34 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/head_v0/head.urdf.xacro +147 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/materials.urdf.xacro +52 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/pr2.urdf.xacro +157 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/pr2_1.11.4.xml +3781 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/double_stereo_camera.gazebo.xacro +16 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/double_stereo_camera.urdf.xacro +61 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/head_sensor_package.gazebo.xacro +20 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/head_sensor_package.urdf.xacro +63 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/hokuyo_lx30_laser.gazebo.xacro +39 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/hokuyo_lx30_laser.urdf.xacro +27 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/kinect_camera.gazebo.xacro +87 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/kinect_camera.urdf.xacro +55 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/kinect_prosilica_camera.gazebo.xacro +193 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/kinect_prosilica_camera.urdf.xacro +181 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/microstrain_3dmgx2_imu.gazebo.xacro +20 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/microstrain_3dmgx2_imu.urdf.xacro +25 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/projector_wg6802418.gazebo.xacro +31 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/projector_wg6802418.urdf.xacro +42 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/prosilica_gc2450_camera.gazebo.xacro +43 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/prosilica_gc2450_camera.urdf.xacro +49 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/stereo_camera.gazebo.xacro +23 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/stereo_camera.urdf.xacro +71 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/wge100_camera.gazebo.xacro +46 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/sensors/wge100_camera.urdf.xacro +47 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/shoulder_v0/shoulder.gazebo.xacro +40 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/shoulder_v0/shoulder.transmission.xacro +35 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/shoulder_v0/shoulder.urdf.xacro +167 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/tilting_laser_v0/tilting_laser.gazebo.xacro +11 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/tilting_laser_v0/tilting_laser.transmission.xacro +14 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/tilting_laser_v0/tilting_laser.urdf.xacro +60 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/torso_v0/torso.gazebo.xacro +37 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/torso_v0/torso.transmission.xacro +22 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/torso_v0/torso.urdf.xacro +122 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/upper_arm_v0/upper_arm.gazebo.xacro +39 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/upper_arm_v0/upper_arm.transmission.xacro +28 -0
- roboticstoolbox/tools/xacro/tests/robots/pr2/upper_arm_v0/upper_arm.urdf.xacro +173 -0
- roboticstoolbox/tools/xacro/tests/settings.yaml +9 -0
- roboticstoolbox/tools/xacro/tests/subdir/foo.xacro +3 -0
- roboticstoolbox/tools/xacro/tests/subdir/include-recursive.xacro +5 -0
- roboticstoolbox/tools/xacro/tests/subdir/include1.xml +1 -0
- roboticstoolbox/tools/xacro/tests/test_xacro.py +1418 -0
- roboticstoolbox/tools/xacro/xmlutils.py +152 -0
- roboticstoolbox_python-1.3.0.dist-info/METADATA +552 -0
- roboticstoolbox_python-1.3.0.dist-info/RECORD +673 -0
- roboticstoolbox_python-1.3.0.dist-info/WHEEL +5 -0
- roboticstoolbox_python-1.3.0.dist-info/entry_points.txt +6 -0
- roboticstoolbox_python-1.3.0.dist-info/licenses/LICENSE +21 -0
- spatialgeometry/__init__.py +32 -0
- spatialgeometry/geom/CollisionShape.py +419 -0
- spatialgeometry/geom/SceneGroup.py +26 -0
- spatialgeometry/geom/SceneNode.py +315 -0
- spatialgeometry/geom/Shape.py +420 -0
- spatialgeometry/geom/__init__.py +26 -0
- spatialgeometry/scene.py +107 -0
- spatialgeometry/tools/__init__.py +0 -0
- spatialgeometry/tools/stdout_supress.py +302 -0
|
@@ -0,0 +1,2100 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
@author: Jesse Haviland
|
|
5
|
+
@author: Peter Corke
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# import sys
|
|
9
|
+
from os.path import splitext
|
|
10
|
+
from copy import deepcopy
|
|
11
|
+
from warnings import warn
|
|
12
|
+
from pathlib import PurePosixPath, Path
|
|
13
|
+
from typing import (
|
|
14
|
+
List,
|
|
15
|
+
TypeVar,
|
|
16
|
+
Union,
|
|
17
|
+
Dict,
|
|
18
|
+
Tuple,
|
|
19
|
+
overload,
|
|
20
|
+
)
|
|
21
|
+
from typing_extensions import Literal as L
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
import numpy as np
|
|
25
|
+
|
|
26
|
+
import spatialmath.base as smb
|
|
27
|
+
from spatialmath.base.argcheck import (
|
|
28
|
+
getvector,
|
|
29
|
+
getmatrix,
|
|
30
|
+
verifymatrix,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
from spatialgeometry import Shape, CollisionShape, Cylinder
|
|
34
|
+
|
|
35
|
+
from spatialmath import (
|
|
36
|
+
SE3,
|
|
37
|
+
SE2,
|
|
38
|
+
SpatialAcceleration,
|
|
39
|
+
SpatialVelocity,
|
|
40
|
+
SpatialInertia,
|
|
41
|
+
SpatialForce,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
import roboticstoolbox as rtb
|
|
45
|
+
from roboticstoolbox.robot.BaseRobot import BaseRobot
|
|
46
|
+
from roboticstoolbox.robot.RobotKinematics import RobotKinematicsMixin
|
|
47
|
+
from roboticstoolbox.robot.Gripper import Gripper
|
|
48
|
+
from roboticstoolbox.robot.Link import BaseLink, Link, Link2
|
|
49
|
+
from roboticstoolbox.robot.ETS import ETS, ETS2
|
|
50
|
+
from roboticstoolbox.tools import xacro
|
|
51
|
+
from roboticstoolbox.tools import URDF
|
|
52
|
+
from roboticstoolbox.tools.types import ArrayLike, NDArray
|
|
53
|
+
from roboticstoolbox.tools.data import rtb_path_to_datafile
|
|
54
|
+
|
|
55
|
+
# A generic type variable representing any subclass of BaseLink
|
|
56
|
+
LinkType = TypeVar("LinkType", bound=BaseLink)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# ==================================================================================== #
|
|
60
|
+
# ================= Robot Class ====================================================== #
|
|
61
|
+
# ==================================================================================== #
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Robot(BaseRobot[Link], RobotKinematicsMixin):
|
|
65
|
+
_color = True
|
|
66
|
+
|
|
67
|
+
def __init__(
|
|
68
|
+
self,
|
|
69
|
+
arg: Union[List[Link], ETS, "Robot"],
|
|
70
|
+
gripper_links: Union[Link, List[Link], None] = None,
|
|
71
|
+
name: str = "",
|
|
72
|
+
manufacturer: str = "",
|
|
73
|
+
comment: str = "",
|
|
74
|
+
base: Union[NDArray, SE3, None] = None,
|
|
75
|
+
tool: Union[NDArray, SE3, None] = None,
|
|
76
|
+
gravity: ArrayLike = [0, 0, -9.81],
|
|
77
|
+
keywords: Union[List[str], Tuple[str]] = [],
|
|
78
|
+
symbolic: bool = False,
|
|
79
|
+
configs: Union[Dict[str, NDArray], None] = None,
|
|
80
|
+
check_jindex: bool = True,
|
|
81
|
+
urdf_string: Union[str, None] = None,
|
|
82
|
+
urdf_filepath: Union[Path, PurePosixPath, None] = None,
|
|
83
|
+
):
|
|
84
|
+
# Process links
|
|
85
|
+
if isinstance(arg, Robot):
|
|
86
|
+
# We're passed a Robot, clone it
|
|
87
|
+
# We need to preserve the parent link as we copy
|
|
88
|
+
|
|
89
|
+
# Copy each link within the robot
|
|
90
|
+
links = [deepcopy(link) for link in arg.links]
|
|
91
|
+
gripper_links = []
|
|
92
|
+
|
|
93
|
+
for gripper in arg.grippers:
|
|
94
|
+
glinks = []
|
|
95
|
+
for link in gripper.links:
|
|
96
|
+
glinks.append(deepcopy(link))
|
|
97
|
+
|
|
98
|
+
gripper_links.append(glinks[0])
|
|
99
|
+
links = links + glinks
|
|
100
|
+
|
|
101
|
+
# Sever parent connection, but save the string
|
|
102
|
+
# The constructor will piece this together for us
|
|
103
|
+
for link in links:
|
|
104
|
+
link._children = []
|
|
105
|
+
if link.parent is not None:
|
|
106
|
+
link._parent_name = link.parent.name
|
|
107
|
+
link._parent = None
|
|
108
|
+
|
|
109
|
+
super().__init__(links, gripper_links=gripper_links)
|
|
110
|
+
|
|
111
|
+
for i, gripper in enumerate(self.grippers):
|
|
112
|
+
gripper.tool = arg.grippers[i].tool.copy()
|
|
113
|
+
|
|
114
|
+
self._urdf_string = arg.urdf_string
|
|
115
|
+
self._urdf_filepath = arg.urdf_filepath
|
|
116
|
+
else:
|
|
117
|
+
if isinstance(arg, ETS):
|
|
118
|
+
# We're passed an ETS string
|
|
119
|
+
links = []
|
|
120
|
+
# chop it up into segments, a link frame after every joint
|
|
121
|
+
parent = None
|
|
122
|
+
for j, ets_j in enumerate(arg.split()):
|
|
123
|
+
elink = Link(ETS(ets_j), parent=parent, name=f"link{j:d}")
|
|
124
|
+
if (
|
|
125
|
+
elink.qlim is None
|
|
126
|
+
and elink.v is not None
|
|
127
|
+
and elink.v.qlim is not None
|
|
128
|
+
):
|
|
129
|
+
elink.qlim = elink.v.qlim # pragma nocover
|
|
130
|
+
parent = elink
|
|
131
|
+
links.append(elink)
|
|
132
|
+
|
|
133
|
+
elif smb.islistof(arg, Link):
|
|
134
|
+
links = arg
|
|
135
|
+
|
|
136
|
+
else:
|
|
137
|
+
raise TypeError("arg was invalid, must be List[Link], ETS, or Robot")
|
|
138
|
+
|
|
139
|
+
# Initialise Base Robot object
|
|
140
|
+
super().__init__(
|
|
141
|
+
links=links,
|
|
142
|
+
gripper_links=gripper_links,
|
|
143
|
+
name=name,
|
|
144
|
+
manufacturer=manufacturer,
|
|
145
|
+
comment=comment,
|
|
146
|
+
base=base,
|
|
147
|
+
tool=tool,
|
|
148
|
+
gravity=gravity,
|
|
149
|
+
keywords=keywords,
|
|
150
|
+
symbolic=symbolic,
|
|
151
|
+
configs=configs,
|
|
152
|
+
check_jindex=check_jindex,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# --------------------------------------------------------------------- #
|
|
156
|
+
# --------- Swift Methods --------------------------------------------- #
|
|
157
|
+
# --------------------------------------------------------------------- #
|
|
158
|
+
|
|
159
|
+
def _to_dict(self, robot_alpha=1.0, collision_alpha=0.0):
|
|
160
|
+
ob = []
|
|
161
|
+
|
|
162
|
+
for link in self.links:
|
|
163
|
+
if robot_alpha > 0:
|
|
164
|
+
for gi in link.geometry:
|
|
165
|
+
gi.set_alpha(robot_alpha)
|
|
166
|
+
ob.append(gi.to_dict())
|
|
167
|
+
if collision_alpha > 0:
|
|
168
|
+
for gi in link.collision:
|
|
169
|
+
gi.set_alpha(collision_alpha)
|
|
170
|
+
ob.append(gi.to_dict())
|
|
171
|
+
|
|
172
|
+
# Do the grippers now
|
|
173
|
+
for gripper in self.grippers:
|
|
174
|
+
for link in gripper.links:
|
|
175
|
+
if robot_alpha > 0:
|
|
176
|
+
for gi in link.geometry:
|
|
177
|
+
gi.set_alpha(robot_alpha)
|
|
178
|
+
ob.append(gi.to_dict())
|
|
179
|
+
if collision_alpha > 0:
|
|
180
|
+
for gi in link.collision:
|
|
181
|
+
gi.set_alpha(collision_alpha)
|
|
182
|
+
ob.append(gi.to_dict())
|
|
183
|
+
|
|
184
|
+
# for o in ob:
|
|
185
|
+
# print(o)
|
|
186
|
+
|
|
187
|
+
return ob
|
|
188
|
+
|
|
189
|
+
def _fk_dict(self, robot_alpha=1.0, collision_alpha=0.0):
|
|
190
|
+
ob = []
|
|
191
|
+
|
|
192
|
+
# Do the robot
|
|
193
|
+
for link in self.links:
|
|
194
|
+
if robot_alpha > 0:
|
|
195
|
+
for gi in link.geometry:
|
|
196
|
+
ob.append(gi.fk_dict())
|
|
197
|
+
if collision_alpha > 0:
|
|
198
|
+
for gi in link.collision:
|
|
199
|
+
ob.append(gi.fk_dict())
|
|
200
|
+
|
|
201
|
+
# Do the grippers now
|
|
202
|
+
for gripper in self.grippers:
|
|
203
|
+
for link in gripper.links:
|
|
204
|
+
if robot_alpha > 0:
|
|
205
|
+
for gi in link.geometry:
|
|
206
|
+
ob.append(gi.fk_dict())
|
|
207
|
+
if collision_alpha > 0:
|
|
208
|
+
for gi in link.collision:
|
|
209
|
+
ob.append(gi.fk_dict())
|
|
210
|
+
|
|
211
|
+
return ob
|
|
212
|
+
|
|
213
|
+
# --------------------------------------------------------------------- #
|
|
214
|
+
# --------- URDF Methods ---------------------------------------------- #
|
|
215
|
+
# --------------------------------------------------------------------- #
|
|
216
|
+
|
|
217
|
+
@staticmethod
|
|
218
|
+
def URDF_read(
|
|
219
|
+
file_path, tld=None, xacro_tld=None
|
|
220
|
+
) -> Tuple[List[Link], str, str, Union[Path, PurePosixPath]]:
|
|
221
|
+
"""
|
|
222
|
+
Read a URDF file as Links
|
|
223
|
+
|
|
224
|
+
File should be specified relative to ``RTBDATA/URDF/xacro``
|
|
225
|
+
|
|
226
|
+
Parameters
|
|
227
|
+
----------
|
|
228
|
+
file_path
|
|
229
|
+
File path relative to the xacro folder
|
|
230
|
+
tld
|
|
231
|
+
A custom top-level directory which holds the xacro data,
|
|
232
|
+
defaults to None
|
|
233
|
+
xacro_tld
|
|
234
|
+
A custom top-level within the xacro data,
|
|
235
|
+
defaults to None
|
|
236
|
+
|
|
237
|
+
Returns
|
|
238
|
+
-------
|
|
239
|
+
links
|
|
240
|
+
a list of links
|
|
241
|
+
name
|
|
242
|
+
the name of the robot
|
|
243
|
+
urdf
|
|
244
|
+
a string representing the URDF
|
|
245
|
+
file_path
|
|
246
|
+
a path to the original file
|
|
247
|
+
|
|
248
|
+
Notes
|
|
249
|
+
-----
|
|
250
|
+
If ``tld`` is not supplied, filepath pointing to xacro data should
|
|
251
|
+
be directly under ``RTBDATA/URDF/xacro`` OR under ``./xacro`` relative
|
|
252
|
+
to the model file calling this method. If ``tld`` is supplied, then
|
|
253
|
+
```file_path``` needs to be relative to ``tld``
|
|
254
|
+
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
# Get the path to the class that defines the robot
|
|
258
|
+
if tld is None:
|
|
259
|
+
base_path = rtb_path_to_datafile("xacro")
|
|
260
|
+
else:
|
|
261
|
+
base_path = PurePosixPath(tld)
|
|
262
|
+
|
|
263
|
+
# Add on relative path to get to the URDF or xacro file
|
|
264
|
+
# base_path = PurePath(classpath).parent.parent / 'URDF' / 'xacro'
|
|
265
|
+
file_path = base_path / PurePosixPath(file_path)
|
|
266
|
+
_, ext = splitext(file_path)
|
|
267
|
+
|
|
268
|
+
if ext == ".xacro":
|
|
269
|
+
# it's a xacro file, preprocess it
|
|
270
|
+
if xacro_tld is not None:
|
|
271
|
+
xacro_tld = base_path / PurePosixPath(xacro_tld)
|
|
272
|
+
urdf_string = xacro.main(file_path, xacro_tld)
|
|
273
|
+
try:
|
|
274
|
+
urdf = URDF.loadstr(urdf_string, file_path, base_path)
|
|
275
|
+
except BaseException as e: # pragma nocover
|
|
276
|
+
print("error parsing URDF file", file_path)
|
|
277
|
+
raise e
|
|
278
|
+
else: # pragma nocover
|
|
279
|
+
urdf_string = open(file_path).read()
|
|
280
|
+
urdf = URDF.loadstr(urdf_string, file_path, base_path)
|
|
281
|
+
|
|
282
|
+
if not isinstance(urdf_string, str): # pragma nocover
|
|
283
|
+
raise ValueError("Parsing failed, did not get valid URDF string back")
|
|
284
|
+
|
|
285
|
+
return urdf.elinks, urdf.name, urdf_string, file_path
|
|
286
|
+
|
|
287
|
+
@classmethod
|
|
288
|
+
def URDF(cls, file_path: str, gripper: Union[int, str, None] = None):
|
|
289
|
+
"""
|
|
290
|
+
Construct a Robot object from URDF file
|
|
291
|
+
|
|
292
|
+
Parameters
|
|
293
|
+
----------
|
|
294
|
+
file_path
|
|
295
|
+
the path to the URDF
|
|
296
|
+
gripper
|
|
297
|
+
index or name of the gripper link(s)
|
|
298
|
+
|
|
299
|
+
Returns
|
|
300
|
+
-------
|
|
301
|
+
If ``gripper`` is specified, links from that link outward are removed
|
|
302
|
+
from the rigid-body tree and folded into a ``Gripper`` object.
|
|
303
|
+
|
|
304
|
+
"""
|
|
305
|
+
|
|
306
|
+
links, name, urdf_string, urdf_filepath = Robot.URDF_read(file_path)
|
|
307
|
+
|
|
308
|
+
gripperLink: Union[Link, None] = None
|
|
309
|
+
|
|
310
|
+
if gripper is not None:
|
|
311
|
+
if isinstance(gripper, int):
|
|
312
|
+
gripperLink = links[gripper]
|
|
313
|
+
elif isinstance(gripper, str):
|
|
314
|
+
for link in links:
|
|
315
|
+
if link.name == gripper:
|
|
316
|
+
gripperLink = link
|
|
317
|
+
break
|
|
318
|
+
else: # pragma nocover
|
|
319
|
+
raise ValueError(f"no link named {gripper}")
|
|
320
|
+
else: # pragma nocover
|
|
321
|
+
raise TypeError("bad argument passed as gripper")
|
|
322
|
+
|
|
323
|
+
# links, name, urdf_string, urdf_filepath = Robot.URDF_read(file_path)
|
|
324
|
+
|
|
325
|
+
return cls(
|
|
326
|
+
links,
|
|
327
|
+
name=name,
|
|
328
|
+
gripper_links=gripperLink,
|
|
329
|
+
urdf_string=urdf_string,
|
|
330
|
+
urdf_filepath=urdf_filepath,
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
# # --------------------------------------------------------------------- #
|
|
334
|
+
# # --------- Utility Methods ------------------------------------------- #
|
|
335
|
+
# # --------------------------------------------------------------------- #
|
|
336
|
+
|
|
337
|
+
# def showgraph(self, display_graph: bool = True, **kwargs) -> Union[None, str]:
|
|
338
|
+
# """
|
|
339
|
+
# Display a link transform graph in browser
|
|
340
|
+
|
|
341
|
+
# ``robot.showgraph()`` displays a graph of the robot's link frames
|
|
342
|
+
# and the ETS between them. It uses GraphViz dot.
|
|
343
|
+
|
|
344
|
+
# The nodes are:
|
|
345
|
+
# - Base is shown as a grey square. This is the world frame origin,
|
|
346
|
+
# but can be changed using the ``base`` attribute of the robot.
|
|
347
|
+
# - Link frames are indicated by circles
|
|
348
|
+
# - ETS transforms are indicated by rounded boxes
|
|
349
|
+
|
|
350
|
+
# The edges are:
|
|
351
|
+
# - an arrow if `jtype` is False or the joint is fixed
|
|
352
|
+
# - an arrow with a round head if `jtype` is True and the joint is
|
|
353
|
+
# revolute
|
|
354
|
+
# - an arrow with a box head if `jtype` is True and the joint is
|
|
355
|
+
# prismatic
|
|
356
|
+
|
|
357
|
+
# Edge labels or nodes in blue have a fixed transformation to the
|
|
358
|
+
# preceding link.
|
|
359
|
+
|
|
360
|
+
# Parameters
|
|
361
|
+
# ----------
|
|
362
|
+
# display_graph
|
|
363
|
+
# Open the graph in a browser if True. Otherwise will return the
|
|
364
|
+
# file path
|
|
365
|
+
# etsbox
|
|
366
|
+
# Put the link ETS in a box, otherwise an edge label
|
|
367
|
+
# jtype
|
|
368
|
+
# Arrowhead to node indicates revolute or prismatic type
|
|
369
|
+
# static
|
|
370
|
+
# Show static joints in blue and bold
|
|
371
|
+
|
|
372
|
+
# Examples
|
|
373
|
+
# --------
|
|
374
|
+
# >>> import roboticstoolbox as rtb
|
|
375
|
+
# >>> panda = rtb.models.URDF.Panda()
|
|
376
|
+
# >>> panda.showgraph()
|
|
377
|
+
|
|
378
|
+
# .. image:: ../figs/panda-graph.svg
|
|
379
|
+
# :width: 600
|
|
380
|
+
|
|
381
|
+
# See Also
|
|
382
|
+
# --------
|
|
383
|
+
# :func:`dotfile`
|
|
384
|
+
|
|
385
|
+
# """
|
|
386
|
+
|
|
387
|
+
# # Lazy import
|
|
388
|
+
# import tempfile
|
|
389
|
+
# import subprocess
|
|
390
|
+
# import webbrowser
|
|
391
|
+
|
|
392
|
+
# # create the temporary dotfile
|
|
393
|
+
# dotfile = tempfile.TemporaryFile(mode="w")
|
|
394
|
+
# self.dotfile(dotfile, **kwargs)
|
|
395
|
+
|
|
396
|
+
# # rewind the dot file, create PDF file in the filesystem, run dot
|
|
397
|
+
# dotfile.seek(0)
|
|
398
|
+
# pdffile = tempfile.NamedTemporaryFile(suffix=".pdf", delete=False)
|
|
399
|
+
# subprocess.run("dot -Tpdf", shell=True, stdin=dotfile, stdout=pdffile)
|
|
400
|
+
|
|
401
|
+
# # open the PDF file in browser (hopefully portable), then cleanup
|
|
402
|
+
# if display_graph: # pragma nocover
|
|
403
|
+
# webbrowser.open(f"file://{pdffile.name}")
|
|
404
|
+
# else:
|
|
405
|
+
# return pdffile.name
|
|
406
|
+
|
|
407
|
+
# def dotfile(
|
|
408
|
+
# self,
|
|
409
|
+
# filename: Union[str, IO[str]],
|
|
410
|
+
# etsbox: bool = False,
|
|
411
|
+
# ets: L["full", "brief"] = "full",
|
|
412
|
+
# jtype: bool = False,
|
|
413
|
+
# static: bool = True,
|
|
414
|
+
# ):
|
|
415
|
+
# """
|
|
416
|
+
# Write a link transform graph as a GraphViz dot file
|
|
417
|
+
|
|
418
|
+
# The file can be processed using dot:
|
|
419
|
+
# % dot -Tpng -o out.png dotfile.dot
|
|
420
|
+
|
|
421
|
+
# The nodes are:
|
|
422
|
+
# - Base is shown as a grey square. This is the world frame origin,
|
|
423
|
+
# but can be changed using the ``base`` attribute of the robot.
|
|
424
|
+
# - Link frames are indicated by circles
|
|
425
|
+
# - ETS transforms are indicated by rounded boxes
|
|
426
|
+
|
|
427
|
+
# The edges are:
|
|
428
|
+
# - an arrow if `jtype` is False or the joint is fixed
|
|
429
|
+
# - an arrow with a round head if `jtype` is True and the joint is
|
|
430
|
+
# revolute
|
|
431
|
+
# - an arrow with a box head if `jtype` is True and the joint is
|
|
432
|
+
# prismatic
|
|
433
|
+
|
|
434
|
+
# Edge labels or nodes in blue have a fixed transformation to the
|
|
435
|
+
# preceding link.
|
|
436
|
+
|
|
437
|
+
# Note
|
|
438
|
+
# ----
|
|
439
|
+
# If ``filename`` is a file object then the file will *not*
|
|
440
|
+
# be closed after the GraphViz model is written.
|
|
441
|
+
|
|
442
|
+
# Parameters
|
|
443
|
+
# ----------
|
|
444
|
+
# file
|
|
445
|
+
# Name of file to write to
|
|
446
|
+
# etsbox
|
|
447
|
+
# Put the link ETS in a box, otherwise an edge label
|
|
448
|
+
# ets
|
|
449
|
+
# Display the full ets with "full" or a brief version with "brief"
|
|
450
|
+
# jtype
|
|
451
|
+
# Arrowhead to node indicates revolute or prismatic type
|
|
452
|
+
# static
|
|
453
|
+
# Show static joints in blue and bold
|
|
454
|
+
|
|
455
|
+
# See Also
|
|
456
|
+
# --------
|
|
457
|
+
# :func:`showgraph`
|
|
458
|
+
|
|
459
|
+
# """
|
|
460
|
+
|
|
461
|
+
# if isinstance(filename, str):
|
|
462
|
+
# file = open(filename, "w")
|
|
463
|
+
# else:
|
|
464
|
+
# file = filename
|
|
465
|
+
|
|
466
|
+
# header = r"""digraph G {
|
|
467
|
+
# graph [rankdir=LR];
|
|
468
|
+
# """
|
|
469
|
+
|
|
470
|
+
# def draw_edge(link, etsbox, jtype, static):
|
|
471
|
+
# # draw the edge
|
|
472
|
+
# if jtype:
|
|
473
|
+
# if link.isprismatic:
|
|
474
|
+
# edge_options = 'arrowhead="box", arrowtail="inv", dir="both"'
|
|
475
|
+
# elif link.isrevolute:
|
|
476
|
+
# edge_options = 'arrowhead="dot", arrowtail="inv", dir="both"'
|
|
477
|
+
# else:
|
|
478
|
+
# edge_options = 'arrowhead="normal"'
|
|
479
|
+
# else:
|
|
480
|
+
# edge_options = 'arrowhead="normal"'
|
|
481
|
+
|
|
482
|
+
# if link.parent is None:
|
|
483
|
+
# parent = "BASE"
|
|
484
|
+
# else:
|
|
485
|
+
# parent = link.parent.name
|
|
486
|
+
|
|
487
|
+
# if etsbox:
|
|
488
|
+
# # put the ets fragment in a box
|
|
489
|
+
# if not link.isjoint and static:
|
|
490
|
+
# node_options = ', fontcolor="blue"'
|
|
491
|
+
# else:
|
|
492
|
+
# node_options = ""
|
|
493
|
+
|
|
494
|
+
# try:
|
|
495
|
+
# file.write(
|
|
496
|
+
# ' {}_ets [shape=box, style=rounded, label="{}"{}];\n'.format(
|
|
497
|
+
# link.name,
|
|
498
|
+
# link.ets.__str__(q=f"q{link.jindex}"),
|
|
499
|
+
# node_options,
|
|
500
|
+
# )
|
|
501
|
+
# )
|
|
502
|
+
# except UnicodeEncodeError: # pragma nocover
|
|
503
|
+
# file.write(
|
|
504
|
+
# ' {}_ets [shape=box, style=rounded, label="{}"{}];\n'.format(
|
|
505
|
+
# link.name,
|
|
506
|
+
# link.ets.__str__(q=f"q{link.jindex}")
|
|
507
|
+
# .encode("ascii", "ignore")
|
|
508
|
+
# .decode("ascii"),
|
|
509
|
+
# node_options,
|
|
510
|
+
# )
|
|
511
|
+
# )
|
|
512
|
+
|
|
513
|
+
# file.write(" {} -> {}_ets;\n".format(parent, link.name))
|
|
514
|
+
# file.write(
|
|
515
|
+
# " {}_ets -> {} [{}];\n".format(link.name, link.name, edge_options)
|
|
516
|
+
# )
|
|
517
|
+
# else:
|
|
518
|
+
# # put the ets fragment as an edge label
|
|
519
|
+
# if not link.isjoint and static:
|
|
520
|
+
# edge_options += 'fontcolor="blue"'
|
|
521
|
+
# if ets == "full":
|
|
522
|
+
# estr = link.ets.__str__(q=f"q{link.jindex}")
|
|
523
|
+
# elif ets == "brief":
|
|
524
|
+
# if link.jindex is None:
|
|
525
|
+
# estr = ""
|
|
526
|
+
# else:
|
|
527
|
+
# estr = f"...q{link.jindex}"
|
|
528
|
+
# else:
|
|
529
|
+
# return
|
|
530
|
+
# try:
|
|
531
|
+
# file.write(
|
|
532
|
+
# ' {} -> {} [label="{}", {}];\n'.format(
|
|
533
|
+
# parent,
|
|
534
|
+
# link.name,
|
|
535
|
+
# estr,
|
|
536
|
+
# edge_options,
|
|
537
|
+
# )
|
|
538
|
+
# )
|
|
539
|
+
# except UnicodeEncodeError: # pragma nocover
|
|
540
|
+
# file.write(
|
|
541
|
+
# ' {} -> {} [label="{}", {}];\n'.format(
|
|
542
|
+
# parent,
|
|
543
|
+
# link.name,
|
|
544
|
+
# estr.encode("ascii", "ignore").decode("ascii"),
|
|
545
|
+
# edge_options,
|
|
546
|
+
# )
|
|
547
|
+
# )
|
|
548
|
+
|
|
549
|
+
# file.write(header)
|
|
550
|
+
|
|
551
|
+
# # add the base link
|
|
552
|
+
# file.write(" BASE [shape=square, style=filled, fillcolor=gray]\n")
|
|
553
|
+
|
|
554
|
+
# # add the links
|
|
555
|
+
# for link in self:
|
|
556
|
+
# # draw the link frame node (circle) or ee node (doublecircle)
|
|
557
|
+
# if link in self.ee_links:
|
|
558
|
+
# # end-effector
|
|
559
|
+
# node_options = 'shape="doublecircle", color="blue", fontcolor="blue"'
|
|
560
|
+
# else:
|
|
561
|
+
# node_options = 'shape="circle"'
|
|
562
|
+
|
|
563
|
+
# file.write(" {} [{}];\n".format(link.name, node_options))
|
|
564
|
+
|
|
565
|
+
# draw_edge(link, etsbox, jtype, static)
|
|
566
|
+
|
|
567
|
+
# for gripper in self.grippers:
|
|
568
|
+
# for link in gripper.links:
|
|
569
|
+
# file.write(" {} [shape=cds];\n".format(link.name))
|
|
570
|
+
# draw_edge(link, etsbox, jtype, static)
|
|
571
|
+
|
|
572
|
+
# file.write("}\n")
|
|
573
|
+
|
|
574
|
+
# if isinstance(filename, str):
|
|
575
|
+
# file.close() # noqa
|
|
576
|
+
|
|
577
|
+
# --------------------------------------------------------------------- #
|
|
578
|
+
# --------- Kinematic Methods ----------------------------------------- #
|
|
579
|
+
# --------------------------------------------------------------------- #
|
|
580
|
+
|
|
581
|
+
@property
|
|
582
|
+
def reach(self) -> float:
|
|
583
|
+
r"""
|
|
584
|
+
Reach of the robot
|
|
585
|
+
|
|
586
|
+
A conservative estimate of the reach of the robot. It is computed as
|
|
587
|
+
the sum of the translational ETs that define the link transform.
|
|
588
|
+
|
|
589
|
+
Note
|
|
590
|
+
----
|
|
591
|
+
Computed on the first access. If kinematic parameters
|
|
592
|
+
subsequently change this will not be reflected.
|
|
593
|
+
|
|
594
|
+
Returns
|
|
595
|
+
-------
|
|
596
|
+
reach
|
|
597
|
+
Maximum reach of the robot
|
|
598
|
+
|
|
599
|
+
Notes
|
|
600
|
+
-----
|
|
601
|
+
- Probably an overestimate of reach
|
|
602
|
+
- Used by numerical inverse kinematics to scale translational
|
|
603
|
+
error.
|
|
604
|
+
- For a prismatic joint, uses ``qlim`` if it is set
|
|
605
|
+
|
|
606
|
+
"""
|
|
607
|
+
|
|
608
|
+
# TODO
|
|
609
|
+
# This should be a start, end method and compute the reach based on the
|
|
610
|
+
# given ets. Then use an lru_cache to speed up return
|
|
611
|
+
|
|
612
|
+
if self._reach is None:
|
|
613
|
+
d_all = []
|
|
614
|
+
for link in self.ee_links:
|
|
615
|
+
d = 0
|
|
616
|
+
while True:
|
|
617
|
+
for et in link.ets:
|
|
618
|
+
if et.istranslation:
|
|
619
|
+
if et.isjoint:
|
|
620
|
+
# the length of a prismatic joint depends on the
|
|
621
|
+
# joint limits. They might be set in the ET
|
|
622
|
+
# or in the Link depending on how the robot
|
|
623
|
+
# was constructed
|
|
624
|
+
if link.qlim is not None:
|
|
625
|
+
d += max(link.qlim)
|
|
626
|
+
elif et.qlim is not None: # pragma nocover
|
|
627
|
+
d += max(et.qlim)
|
|
628
|
+
else:
|
|
629
|
+
d += abs(et.eta)
|
|
630
|
+
link = link.parent
|
|
631
|
+
if link is None or isinstance(link, str):
|
|
632
|
+
d_all.append(d)
|
|
633
|
+
break
|
|
634
|
+
|
|
635
|
+
self._reach = max(d_all)
|
|
636
|
+
return self._reach
|
|
637
|
+
|
|
638
|
+
def fkine_all(self, q: ArrayLike) -> SE3:
|
|
639
|
+
"""
|
|
640
|
+
Compute the pose of every link frame
|
|
641
|
+
|
|
642
|
+
``T = robot.fkine_all(q)`` is an SE3 instance with ``robot.nlinks +
|
|
643
|
+
1`` values:
|
|
644
|
+
|
|
645
|
+
- ``T[0]`` is the base transform
|
|
646
|
+
- ``T[i]`` is the pose of link whose ``number`` is ``i``
|
|
647
|
+
|
|
648
|
+
Parameters
|
|
649
|
+
----------
|
|
650
|
+
q
|
|
651
|
+
The joint configuration
|
|
652
|
+
|
|
653
|
+
Returns
|
|
654
|
+
-------
|
|
655
|
+
fkine_all
|
|
656
|
+
Pose of all links
|
|
657
|
+
|
|
658
|
+
References
|
|
659
|
+
----------
|
|
660
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
661
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
662
|
+
|
|
663
|
+
""" # noqa
|
|
664
|
+
|
|
665
|
+
q = getvector(q)
|
|
666
|
+
|
|
667
|
+
Tbase = SE3(self.base) # add base, also sets the type
|
|
668
|
+
|
|
669
|
+
linkframes = Tbase.__class__.Alloc(self.nlinks + 1)
|
|
670
|
+
linkframes[0] = Tbase
|
|
671
|
+
|
|
672
|
+
def recurse(Tall, Tparent, q, link):
|
|
673
|
+
# if joint??
|
|
674
|
+
T = Tparent
|
|
675
|
+
while True:
|
|
676
|
+
T *= SE3(link.A(q[link.jindex]))
|
|
677
|
+
|
|
678
|
+
Tall[link.number] = T
|
|
679
|
+
|
|
680
|
+
if link.nchildren == 0:
|
|
681
|
+
# no children
|
|
682
|
+
return
|
|
683
|
+
elif link.nchildren == 1:
|
|
684
|
+
# one child
|
|
685
|
+
if link in self.ee_links: # pragma nocover
|
|
686
|
+
# this link is an end-effector, go no further
|
|
687
|
+
return
|
|
688
|
+
link = link.children[0]
|
|
689
|
+
continue
|
|
690
|
+
else:
|
|
691
|
+
# multiple children
|
|
692
|
+
for child in link.children:
|
|
693
|
+
recurse(Tall, T, q, child)
|
|
694
|
+
return
|
|
695
|
+
|
|
696
|
+
recurse(linkframes, Tbase, q, self.links[0])
|
|
697
|
+
|
|
698
|
+
return linkframes
|
|
699
|
+
|
|
700
|
+
@overload
|
|
701
|
+
def manipulability(
|
|
702
|
+
self,
|
|
703
|
+
q: ArrayLike = ...,
|
|
704
|
+
J: None = None,
|
|
705
|
+
end: Union[str, Link, Gripper, None] = None,
|
|
706
|
+
start: Union[str, Link, Gripper, None] = None,
|
|
707
|
+
method: L[
|
|
708
|
+
"yoshikawa", "asada", "minsingular", "invcondition" # noqa
|
|
709
|
+
] = "yoshikawa",
|
|
710
|
+
axes: Union[L["all", "trans", "rot"], List[bool]] = "all", # noqa
|
|
711
|
+
**kwargs,
|
|
712
|
+
) -> Union[float, NDArray]: # pragma nocover
|
|
713
|
+
...
|
|
714
|
+
|
|
715
|
+
@overload
|
|
716
|
+
def manipulability(
|
|
717
|
+
self,
|
|
718
|
+
q: None = None,
|
|
719
|
+
J: NDArray = ...,
|
|
720
|
+
end: Union[str, Link, Gripper, None] = None,
|
|
721
|
+
start: Union[str, Link, Gripper, None] = None,
|
|
722
|
+
method: L[
|
|
723
|
+
"yoshikawa", "asada", "minsingular", "invcondition" # noqa
|
|
724
|
+
] = "yoshikawa",
|
|
725
|
+
axes: Union[L["all", "trans", "rot"], List[bool]] = "all", # noqa
|
|
726
|
+
**kwargs,
|
|
727
|
+
) -> Union[float, NDArray]: # pragma nocover
|
|
728
|
+
...
|
|
729
|
+
|
|
730
|
+
def manipulability(
|
|
731
|
+
self,
|
|
732
|
+
q=None,
|
|
733
|
+
J=None,
|
|
734
|
+
end: Union[str, Link, Gripper, None] = None,
|
|
735
|
+
start: Union[str, Link, Gripper, None] = None,
|
|
736
|
+
method: L[
|
|
737
|
+
"yoshikawa", "asada", "minsingular", "invcondition" # noqa
|
|
738
|
+
] = "yoshikawa",
|
|
739
|
+
axes: Union[L["all", "trans", "rot"], List[bool]] = "all", # noqa
|
|
740
|
+
**kwargs,
|
|
741
|
+
):
|
|
742
|
+
"""
|
|
743
|
+
Manipulability measure
|
|
744
|
+
|
|
745
|
+
``manipulability(q)`` is the scalar manipulability index
|
|
746
|
+
for the robot at the joint configuration ``q``. It indicates
|
|
747
|
+
dexterity, that is, how well conditioned the robot is for motion
|
|
748
|
+
with respect to the 6 degrees of Cartesian motion. The values is
|
|
749
|
+
zero if the robot is at a singularity.
|
|
750
|
+
|
|
751
|
+
Parameters
|
|
752
|
+
----------
|
|
753
|
+
q
|
|
754
|
+
Joint coordinates, one of J or q required
|
|
755
|
+
J
|
|
756
|
+
Jacobian in base frame if already computed, one of J or
|
|
757
|
+
q required
|
|
758
|
+
method
|
|
759
|
+
method to use, "yoshikawa" (default), "invcondition",
|
|
760
|
+
"minsingular" or "asada"
|
|
761
|
+
axes
|
|
762
|
+
Task space axes to consider: "all" [default],
|
|
763
|
+
"trans", or "rot"
|
|
764
|
+
|
|
765
|
+
Returns
|
|
766
|
+
-------
|
|
767
|
+
manipulability
|
|
768
|
+
|
|
769
|
+
Synopsis
|
|
770
|
+
--------
|
|
771
|
+
|
|
772
|
+
Various measures are supported:
|
|
773
|
+
|
|
774
|
+
| Measure | Description |
|
|
775
|
+
| ``"yoshikawa"`` | Volume of the velocity ellipsoid, *distance* |
|
|
776
|
+
| | from singularity [Yoshikawa85]_ |
|
|
777
|
+
| ``"invcondition"``| Inverse condition number of Jacobian, isotropy |
|
|
778
|
+
| | of the velocity ellipsoid [Klein87]_ |
|
|
779
|
+
| ``"minsingular"`` | Minimum singular value of the Jacobian, |
|
|
780
|
+
| | *distance* from singularity [Klein87]_ |
|
|
781
|
+
| ``"asada"`` | Isotropy of the task-space acceleration |
|
|
782
|
+
| | ellipsoid which is a function of the Cartesian |
|
|
783
|
+
| | inertia matrix which depends on the inertial |
|
|
784
|
+
| | parameters [Asada83]_ |
|
|
785
|
+
|
|
786
|
+
**Trajectory operation**:
|
|
787
|
+
|
|
788
|
+
If ``q`` is a matrix (m,n) then the result (m,) is a vector of
|
|
789
|
+
manipulability indices for each joint configuration specified by a row
|
|
790
|
+
of ``q``.
|
|
791
|
+
|
|
792
|
+
Notes
|
|
793
|
+
-----
|
|
794
|
+
- Invokes the ``jacob0`` method of the robot if ``J`` is not passed
|
|
795
|
+
- The "all" option includes rotational and translational
|
|
796
|
+
dexterity, but this involves adding different units. It can be
|
|
797
|
+
more useful to look at the translational and rotational
|
|
798
|
+
manipulability separately.
|
|
799
|
+
- Examples in the RVC book (1st edition) can be replicated by
|
|
800
|
+
using the "all" option
|
|
801
|
+
- Asada's measure requires inertial a robot model with inertial
|
|
802
|
+
parameters.
|
|
803
|
+
|
|
804
|
+
References
|
|
805
|
+
----------
|
|
806
|
+
.. [Yoshikawa85] Manipulability of Robotic Mechanisms. Yoshikawa T.,
|
|
807
|
+
The International Journal of Robotics Research.
|
|
808
|
+
1985;4(2):3-9. doi:10.1177/027836498500400201
|
|
809
|
+
.. [Asada83] A geometrical representation of manipulator dynamics and
|
|
810
|
+
its application to arm design, H. Asada,
|
|
811
|
+
Journal of Dynamic Systems, Measurement, and Control,
|
|
812
|
+
vol. 105, p. 131, 1983.
|
|
813
|
+
.. [Klein87] Dexterity Measures for the Design and Control of
|
|
814
|
+
Kinematically Redundant Manipulators. Klein CA, Blaho BE.
|
|
815
|
+
The International Journal of Robotics Research.
|
|
816
|
+
1987;6(2):72-83. doi:10.1177/027836498700600206
|
|
817
|
+
- Robotics, Vision & Control, Chap 8, P. Corke, Springer 2011.
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
.. versionchanged:: 1.0.3
|
|
821
|
+
Removed 'both' option for axes, added a custom list option.
|
|
822
|
+
|
|
823
|
+
"""
|
|
824
|
+
|
|
825
|
+
ets = self.ets(end, start)
|
|
826
|
+
|
|
827
|
+
axes_list: List[bool] = []
|
|
828
|
+
|
|
829
|
+
if isinstance(axes, list):
|
|
830
|
+
axes_list = axes
|
|
831
|
+
elif axes == "all":
|
|
832
|
+
axes_list = [True, True, True, True, True, True]
|
|
833
|
+
elif axes.startswith("trans"):
|
|
834
|
+
axes_list = [True, True, True, False, False, False]
|
|
835
|
+
elif axes.startswith("rot"):
|
|
836
|
+
axes_list = [False, False, False, True, True, True]
|
|
837
|
+
elif axes == "both":
|
|
838
|
+
return (
|
|
839
|
+
self.manipulability(
|
|
840
|
+
q=q, J=J, end=end, start=start, method=method, axes="trans"
|
|
841
|
+
),
|
|
842
|
+
self.manipulability(
|
|
843
|
+
q=q, J=J, end=end, start=start, method=method, axes="rot"
|
|
844
|
+
),
|
|
845
|
+
)
|
|
846
|
+
else:
|
|
847
|
+
raise ValueError("axes must be all, trans, rot or both")
|
|
848
|
+
|
|
849
|
+
def yoshikawa(robot, J, q, axes_list):
|
|
850
|
+
J = J[axes_list, :]
|
|
851
|
+
if J.shape[0] == J.shape[1]:
|
|
852
|
+
# simplified case for square matrix
|
|
853
|
+
return abs(np.linalg.det(J))
|
|
854
|
+
else:
|
|
855
|
+
m2 = np.linalg.det(J @ J.T)
|
|
856
|
+
return np.sqrt(abs(m2))
|
|
857
|
+
|
|
858
|
+
def condition(robot, J, q, axes_list):
|
|
859
|
+
J = J[axes_list, :]
|
|
860
|
+
|
|
861
|
+
# return 1/cond(J)
|
|
862
|
+
return 1 / np.linalg.cond(J)
|
|
863
|
+
|
|
864
|
+
def minsingular(robot, J, q, axes_list):
|
|
865
|
+
J = J[axes_list, :]
|
|
866
|
+
s = np.linalg.svd(J, compute_uv=False)
|
|
867
|
+
|
|
868
|
+
# return last/smallest singular value of J
|
|
869
|
+
return s[-1]
|
|
870
|
+
|
|
871
|
+
def asada(robot, J, q, axes_list):
|
|
872
|
+
# dof = np.sum(axes_list)
|
|
873
|
+
if np.linalg.matrix_rank(J) < 6:
|
|
874
|
+
return 0
|
|
875
|
+
Ji = np.linalg.pinv(J)
|
|
876
|
+
Mx = Ji.T @ robot.inertia(q) @ Ji
|
|
877
|
+
d = np.where(axes_list)[0]
|
|
878
|
+
Mx = Mx[d]
|
|
879
|
+
Mx = Mx[:, d.tolist()]
|
|
880
|
+
e, _ = np.linalg.eig(Mx)
|
|
881
|
+
return np.min(e) / np.max(e)
|
|
882
|
+
|
|
883
|
+
# choose the handler function
|
|
884
|
+
if method.lower().startswith("yoshi"):
|
|
885
|
+
mfunc = yoshikawa
|
|
886
|
+
elif method.lower().startswith("invc"):
|
|
887
|
+
mfunc = condition
|
|
888
|
+
elif method.lower().startswith("mins"):
|
|
889
|
+
mfunc = minsingular
|
|
890
|
+
elif method.lower().startswith("asa"):
|
|
891
|
+
mfunc = asada
|
|
892
|
+
else:
|
|
893
|
+
raise ValueError("Invalid method chosen")
|
|
894
|
+
|
|
895
|
+
# Calculate manipulability based on supplied Jacobian
|
|
896
|
+
if J is not None:
|
|
897
|
+
w = [mfunc(self, J, q, axes_list)]
|
|
898
|
+
|
|
899
|
+
# Otherwise use the q vector/matrix
|
|
900
|
+
else:
|
|
901
|
+
if q is None:
|
|
902
|
+
raise ValueError("Either J or q must be supplied")
|
|
903
|
+
|
|
904
|
+
q = getmatrix(q, (None, self.n))
|
|
905
|
+
q = np.array(getmatrix(q, (None, self.n)))
|
|
906
|
+
w = np.zeros(q.shape[0])
|
|
907
|
+
|
|
908
|
+
for k, qk in enumerate(q):
|
|
909
|
+
Jk = ets.jacob0(qk)
|
|
910
|
+
w[k] = mfunc(self, Jk, qk, axes_list)
|
|
911
|
+
|
|
912
|
+
if len(w) == 1:
|
|
913
|
+
return w[0]
|
|
914
|
+
else:
|
|
915
|
+
return w
|
|
916
|
+
|
|
917
|
+
def jtraj(
|
|
918
|
+
self,
|
|
919
|
+
T1: Union[NDArray, SE3],
|
|
920
|
+
T2: Union[NDArray, SE3],
|
|
921
|
+
t: Union[NDArray, int],
|
|
922
|
+
**kwargs,
|
|
923
|
+
):
|
|
924
|
+
"""
|
|
925
|
+
Joint-space trajectory between SE(3) poses
|
|
926
|
+
|
|
927
|
+
The initial and final poses are mapped to joint space using inverse
|
|
928
|
+
kinematics:
|
|
929
|
+
|
|
930
|
+
- if the object has an analytic solution ``ikine_a`` that will be used,
|
|
931
|
+
- otherwise the general numerical algorithm ``ikine_lm`` will be used.
|
|
932
|
+
|
|
933
|
+
``traj = obot.jtraj(T1, T2, t)`` is a trajectory object whose
|
|
934
|
+
attribute ``traj.q`` is a row-wise joint-space trajectory.
|
|
935
|
+
|
|
936
|
+
Parameters
|
|
937
|
+
----------
|
|
938
|
+
T1
|
|
939
|
+
initial end-effector pose
|
|
940
|
+
T2
|
|
941
|
+
final end-effector pose
|
|
942
|
+
t
|
|
943
|
+
time vector or number of steps
|
|
944
|
+
kwargs
|
|
945
|
+
arguments passed to the IK solver
|
|
946
|
+
|
|
947
|
+
Returns
|
|
948
|
+
-------
|
|
949
|
+
trajectory
|
|
950
|
+
|
|
951
|
+
""" # noqa
|
|
952
|
+
|
|
953
|
+
if hasattr(self, "ikine_a"):
|
|
954
|
+
ik = self.ikine_a # type: ignore
|
|
955
|
+
else:
|
|
956
|
+
ik = self.ikine_LM
|
|
957
|
+
|
|
958
|
+
q1 = ik(T1, **kwargs)
|
|
959
|
+
q2 = ik(T2, **kwargs)
|
|
960
|
+
|
|
961
|
+
return rtb.jtraj(q1.q, q2.q, t)
|
|
962
|
+
|
|
963
|
+
@overload
|
|
964
|
+
def jacob0_dot(
|
|
965
|
+
self,
|
|
966
|
+
q: ArrayLike,
|
|
967
|
+
qd: ArrayLike,
|
|
968
|
+
J0: None = None,
|
|
969
|
+
representation: Union[
|
|
970
|
+
L["rpy/xyz", "rpy/zyx", "eul", "exp"], None # noqa
|
|
971
|
+
] = None,
|
|
972
|
+
) -> NDArray: # pragma no cover
|
|
973
|
+
...
|
|
974
|
+
|
|
975
|
+
@overload
|
|
976
|
+
def jacob0_dot(
|
|
977
|
+
self,
|
|
978
|
+
q: None,
|
|
979
|
+
qd: ArrayLike,
|
|
980
|
+
J0: NDArray = ...,
|
|
981
|
+
representation: Union[
|
|
982
|
+
L["rpy/xyz", "rpy/zyx", "eul", "exp"], None # noqa
|
|
983
|
+
] = None,
|
|
984
|
+
) -> NDArray: # pragma no cover
|
|
985
|
+
...
|
|
986
|
+
|
|
987
|
+
def jacob0_dot(
|
|
988
|
+
self,
|
|
989
|
+
q,
|
|
990
|
+
qd: ArrayLike,
|
|
991
|
+
J0=None,
|
|
992
|
+
representation: Union[
|
|
993
|
+
L["rpy/xyz", "rpy/zyx", "eul", "exp"], None # noqa
|
|
994
|
+
] = None,
|
|
995
|
+
):
|
|
996
|
+
r"""
|
|
997
|
+
Derivative of Jacobian
|
|
998
|
+
|
|
999
|
+
``robot.jacob_dot(q, qd)`` computes the rate of change of the
|
|
1000
|
+
Jacobian elements
|
|
1001
|
+
|
|
1002
|
+
.. math::
|
|
1003
|
+
|
|
1004
|
+
\dmat{J} = \frac{d \mat{J}}{d \vec{q}} \frac{d \vec{q}}{dt}
|
|
1005
|
+
|
|
1006
|
+
where the first term is the rank-3 Hessian.
|
|
1007
|
+
|
|
1008
|
+
Parameters
|
|
1009
|
+
----------
|
|
1010
|
+
q
|
|
1011
|
+
The joint configuration of the robot
|
|
1012
|
+
qd
|
|
1013
|
+
The joint velocity of the robot
|
|
1014
|
+
J0
|
|
1015
|
+
Jacobian in {0} frame
|
|
1016
|
+
representation
|
|
1017
|
+
angular representation
|
|
1018
|
+
|
|
1019
|
+
Returns
|
|
1020
|
+
-------
|
|
1021
|
+
jdot
|
|
1022
|
+
The derivative of the manipulator Jacobian
|
|
1023
|
+
|
|
1024
|
+
Synopsis
|
|
1025
|
+
--------
|
|
1026
|
+
|
|
1027
|
+
If ``J0`` is already calculated for the joint
|
|
1028
|
+
coordinates ``q`` it can be passed in to to save computation time.
|
|
1029
|
+
|
|
1030
|
+
It is computed as the mode-3 product of the Hessian tensor and the
|
|
1031
|
+
velocity vector.
|
|
1032
|
+
|
|
1033
|
+
The derivative of an analytical Jacobian can be obtained by setting
|
|
1034
|
+
``representation`` as
|
|
1035
|
+
|
|
1036
|
+
.. list-table::
|
|
1037
|
+
:header-rows: 1
|
|
1038
|
+
|
|
1039
|
+
* - ``representation``
|
|
1040
|
+
- Rotational representation
|
|
1041
|
+
* - ``'rpy/xyz'``
|
|
1042
|
+
- RPY angular rates in XYZ order
|
|
1043
|
+
* - ``'rpy/zyx'``
|
|
1044
|
+
- RPY angular rates in ZYX order
|
|
1045
|
+
* - ``'eul'``
|
|
1046
|
+
- Euler angular rates in ZYZ order
|
|
1047
|
+
* - ``'exp'``
|
|
1048
|
+
- exponential coordinate rates
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
References
|
|
1052
|
+
----------
|
|
1053
|
+
- Kinematic Derivatives using the Elementary Transform
|
|
1054
|
+
Sequence, J. Haviland and P. Corke
|
|
1055
|
+
|
|
1056
|
+
See Also
|
|
1057
|
+
--------
|
|
1058
|
+
:func:`jacob0`
|
|
1059
|
+
:func:`hessian0`
|
|
1060
|
+
|
|
1061
|
+
"""
|
|
1062
|
+
|
|
1063
|
+
qd = np.array(qd)
|
|
1064
|
+
|
|
1065
|
+
if representation is None:
|
|
1066
|
+
if J0 is None:
|
|
1067
|
+
J0 = self.jacob0(q)
|
|
1068
|
+
H = self.hessian0(q, J0=J0)
|
|
1069
|
+
|
|
1070
|
+
else:
|
|
1071
|
+
# # determine analytic rotation
|
|
1072
|
+
# T = self.fkine(q).A
|
|
1073
|
+
# gamma = smb.r2x(smb.t2r(T), representation=representation)
|
|
1074
|
+
|
|
1075
|
+
# # get transformation angular velocity to analytic velocity
|
|
1076
|
+
# Ai = smb.rotvelxform(
|
|
1077
|
+
# gamma, representation=representation, inverse=True, full=True
|
|
1078
|
+
# )
|
|
1079
|
+
|
|
1080
|
+
# # get analytic rate from joint rates
|
|
1081
|
+
# omega = J0[3:, :] @ qd
|
|
1082
|
+
# gamma_dot = Ai[3:, 3:] @ omega
|
|
1083
|
+
# Ai_dot = smb.rotvelxform_inv_dot(gamma, gamma_dot, full=True)
|
|
1084
|
+
# Ai_dot = sp.linalg.block_diag(np.zeros((3, 3)), Ai_dot)
|
|
1085
|
+
|
|
1086
|
+
# Jd = Ai_dot @ J0 + Ai @ Jd
|
|
1087
|
+
|
|
1088
|
+
# not actually sure this can be written in closed form
|
|
1089
|
+
|
|
1090
|
+
H = smb.numhess(
|
|
1091
|
+
lambda q: self.jacob0_analytical(q, representation=representation), q
|
|
1092
|
+
)
|
|
1093
|
+
|
|
1094
|
+
# Jd = Ai @ Jd
|
|
1095
|
+
|
|
1096
|
+
# return Jd
|
|
1097
|
+
|
|
1098
|
+
return np.tensordot(H, qd, (0, 0))
|
|
1099
|
+
|
|
1100
|
+
@overload
|
|
1101
|
+
def jacobm(
|
|
1102
|
+
self,
|
|
1103
|
+
q: ArrayLike = ...,
|
|
1104
|
+
J: None = None,
|
|
1105
|
+
H: None = None,
|
|
1106
|
+
end: Union[str, Link, Gripper, None] = None,
|
|
1107
|
+
start: Union[str, Link, Gripper, None] = None,
|
|
1108
|
+
axes: Union[L["all", "trans", "rot"], List[bool]] = "all", # noqa
|
|
1109
|
+
) -> NDArray: # pragma no cover
|
|
1110
|
+
...
|
|
1111
|
+
|
|
1112
|
+
@overload
|
|
1113
|
+
def jacobm(
|
|
1114
|
+
self,
|
|
1115
|
+
q: None = None,
|
|
1116
|
+
J: NDArray = ...,
|
|
1117
|
+
H: NDArray = ...,
|
|
1118
|
+
end: Union[str, Link, Gripper, None] = None,
|
|
1119
|
+
start: Union[str, Link, Gripper, None] = None,
|
|
1120
|
+
axes: Union[L["all", "trans", "rot"], List[bool]] = "all", # noqa
|
|
1121
|
+
) -> NDArray: # pragma no cover
|
|
1122
|
+
...
|
|
1123
|
+
|
|
1124
|
+
def jacobm(
|
|
1125
|
+
self,
|
|
1126
|
+
q=None,
|
|
1127
|
+
J=None,
|
|
1128
|
+
H=None,
|
|
1129
|
+
end: Union[str, Link, Gripper, None] = None,
|
|
1130
|
+
start: Union[str, Link, Gripper, None] = None,
|
|
1131
|
+
axes: Union[L["all", "trans", "rot"], List[bool]] = "all", # noqa
|
|
1132
|
+
) -> NDArray:
|
|
1133
|
+
r"""
|
|
1134
|
+
The manipulability Jacobian
|
|
1135
|
+
|
|
1136
|
+
This measure relates the rate of change of the manipulability to the
|
|
1137
|
+
joint velocities of the robot. One of J or q is required. Supply J
|
|
1138
|
+
and H if already calculated to save computation time
|
|
1139
|
+
|
|
1140
|
+
Parameters
|
|
1141
|
+
----------
|
|
1142
|
+
q
|
|
1143
|
+
The joint angles/configuration of the robot (Optional,
|
|
1144
|
+
if not supplied will use the stored q values).
|
|
1145
|
+
J
|
|
1146
|
+
The manipulator Jacobian in any frame
|
|
1147
|
+
H
|
|
1148
|
+
The manipulator Hessian in any frame
|
|
1149
|
+
end
|
|
1150
|
+
the final link or Gripper which the Hessian represents
|
|
1151
|
+
start
|
|
1152
|
+
the first link which the Hessian represents
|
|
1153
|
+
|
|
1154
|
+
Returns
|
|
1155
|
+
-------
|
|
1156
|
+
jacobm
|
|
1157
|
+
The manipulability Jacobian
|
|
1158
|
+
|
|
1159
|
+
Synopsis
|
|
1160
|
+
--------
|
|
1161
|
+
Yoshikawa's manipulability measure
|
|
1162
|
+
|
|
1163
|
+
.. math::
|
|
1164
|
+
|
|
1165
|
+
m(\vec{q}) = \sqrt{\mat{J}(\vec{q}) \mat{J}(\vec{q})^T}
|
|
1166
|
+
|
|
1167
|
+
This method returns its Jacobian with respect to configuration
|
|
1168
|
+
|
|
1169
|
+
.. math::
|
|
1170
|
+
|
|
1171
|
+
\frac{\partial m(\vec{q})}{\partial \vec{q}}
|
|
1172
|
+
|
|
1173
|
+
References
|
|
1174
|
+
----------
|
|
1175
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
1176
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
1177
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
1178
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
1179
|
+
|
|
1180
|
+
""" # noqa
|
|
1181
|
+
|
|
1182
|
+
end, start, _ = self._get_limit_links(end, start)
|
|
1183
|
+
|
|
1184
|
+
#
|
|
1185
|
+
if not isinstance(axes, list):
|
|
1186
|
+
if axes.startswith("all"):
|
|
1187
|
+
axes = [True, True, True, True, True, True]
|
|
1188
|
+
elif axes.startswith("trans"):
|
|
1189
|
+
axes = [True, True, True, False, False, False]
|
|
1190
|
+
elif axes.startswith("rot"):
|
|
1191
|
+
axes = [False, False, False, True, True, True]
|
|
1192
|
+
else:
|
|
1193
|
+
raise ValueError("axes must be all, trans or rot")
|
|
1194
|
+
|
|
1195
|
+
if J is None:
|
|
1196
|
+
if q is None:
|
|
1197
|
+
q = np.copy(self.q)
|
|
1198
|
+
else:
|
|
1199
|
+
q = getvector(q, self.n)
|
|
1200
|
+
|
|
1201
|
+
J = self.jacob0(q, start=start, end=end)
|
|
1202
|
+
else:
|
|
1203
|
+
verifymatrix(J, (6, self.n))
|
|
1204
|
+
|
|
1205
|
+
n = J.shape[1]
|
|
1206
|
+
|
|
1207
|
+
if H is None:
|
|
1208
|
+
H = self.hessian0(J0=J, start=start, end=end)
|
|
1209
|
+
# else:
|
|
1210
|
+
# verifymatrix(H, (6, self.n, self.n))
|
|
1211
|
+
elif not isinstance(H, np.ndarray):
|
|
1212
|
+
raise TypeError("Hessian must be numpy array of shape 6xnxn")
|
|
1213
|
+
elif H.shape != (6, self.n, self.n):
|
|
1214
|
+
raise ValueError("Hessian must be numpy array of shape 6xnxn")
|
|
1215
|
+
|
|
1216
|
+
manipulability = self.manipulability(
|
|
1217
|
+
q,
|
|
1218
|
+
J=J,
|
|
1219
|
+
start=start,
|
|
1220
|
+
end=end,
|
|
1221
|
+
axes=axes, # type: ignore
|
|
1222
|
+
)
|
|
1223
|
+
|
|
1224
|
+
J = J[axes, :] # type: ignore
|
|
1225
|
+
H = H[:, axes, :] # type: ignore
|
|
1226
|
+
|
|
1227
|
+
b = np.linalg.inv(J @ np.transpose(J))
|
|
1228
|
+
Jm = np.zeros((n, 1))
|
|
1229
|
+
|
|
1230
|
+
for i in range(n):
|
|
1231
|
+
c = J @ np.transpose(H[i, :, :])
|
|
1232
|
+
Jm[i, 0] = manipulability * np.transpose(c.flatten("F")) @ b.flatten("F")
|
|
1233
|
+
|
|
1234
|
+
return Jm
|
|
1235
|
+
|
|
1236
|
+
# --------------------------------------------------------------------- #
|
|
1237
|
+
# --------- Collision Methods ----------------------------------------- #
|
|
1238
|
+
# --------------------------------------------------------------------- #
|
|
1239
|
+
|
|
1240
|
+
def closest_point(
|
|
1241
|
+
self, q: ArrayLike, shape: Shape, inf_dist: float = 1.0, skip: bool = False
|
|
1242
|
+
) -> Tuple[
|
|
1243
|
+
Union[int, None],
|
|
1244
|
+
Union[NDArray, None],
|
|
1245
|
+
Union[NDArray, None],
|
|
1246
|
+
]:
|
|
1247
|
+
"""
|
|
1248
|
+
Find the closest point between robot and shape
|
|
1249
|
+
|
|
1250
|
+
``closest_point(shape, inf_dist)`` returns the minimum euclidean
|
|
1251
|
+
distance between this robot and shape, provided it is less than
|
|
1252
|
+
inf_dist. It will also return the points on self and shape in the
|
|
1253
|
+
world frame which connect the line of length distance between the
|
|
1254
|
+
shapes. If the distance is negative then the shapes are collided.
|
|
1255
|
+
|
|
1256
|
+
Parameters
|
|
1257
|
+
----------
|
|
1258
|
+
shape
|
|
1259
|
+
The shape to compare distance to
|
|
1260
|
+
inf_dist
|
|
1261
|
+
The minimum distance within which to consider
|
|
1262
|
+
the shape
|
|
1263
|
+
skip
|
|
1264
|
+
Skip setting all shape transforms based on q, use this
|
|
1265
|
+
option if using this method in conjuction with Swift to save time
|
|
1266
|
+
|
|
1267
|
+
Returns
|
|
1268
|
+
-------
|
|
1269
|
+
d
|
|
1270
|
+
distance between the robot and shape
|
|
1271
|
+
p1
|
|
1272
|
+
[x, y, z] point on the robot (in the world frame)
|
|
1273
|
+
p2
|
|
1274
|
+
[x, y, z] point on the shape (in the world frame)
|
|
1275
|
+
|
|
1276
|
+
"""
|
|
1277
|
+
|
|
1278
|
+
if not skip:
|
|
1279
|
+
self._update_link_tf(q)
|
|
1280
|
+
self._propogate_scene_tree()
|
|
1281
|
+
shape._propogate_scene_tree()
|
|
1282
|
+
|
|
1283
|
+
d = 10000
|
|
1284
|
+
p1 = None
|
|
1285
|
+
p2 = None
|
|
1286
|
+
|
|
1287
|
+
for link in self.links:
|
|
1288
|
+
td, tp1, tp2 = link.closest_point(shape, inf_dist, skip=True)
|
|
1289
|
+
|
|
1290
|
+
if td is not None and td < d:
|
|
1291
|
+
d = td
|
|
1292
|
+
p1 = tp1
|
|
1293
|
+
p2 = tp2
|
|
1294
|
+
|
|
1295
|
+
if d == 10000:
|
|
1296
|
+
d = None
|
|
1297
|
+
|
|
1298
|
+
return d, p1, p2
|
|
1299
|
+
|
|
1300
|
+
def iscollided(self, q, shape: Shape, skip: bool = False) -> bool:
|
|
1301
|
+
"""
|
|
1302
|
+
Check if the robot is in collision with a shape
|
|
1303
|
+
|
|
1304
|
+
``iscollided(shape)`` checks if this robot and shape have collided
|
|
1305
|
+
|
|
1306
|
+
Parameters
|
|
1307
|
+
----------
|
|
1308
|
+
shape
|
|
1309
|
+
The shape to compare distance to
|
|
1310
|
+
skip
|
|
1311
|
+
Skip setting all shape transforms based on q, use this
|
|
1312
|
+
option if using this method in conjuction with Swift to save time
|
|
1313
|
+
|
|
1314
|
+
Returns
|
|
1315
|
+
-------
|
|
1316
|
+
iscollided
|
|
1317
|
+
True if shapes have collided
|
|
1318
|
+
|
|
1319
|
+
"""
|
|
1320
|
+
|
|
1321
|
+
if not skip:
|
|
1322
|
+
self._update_link_tf(q)
|
|
1323
|
+
self._propogate_scene_tree()
|
|
1324
|
+
shape._propogate_scene_tree()
|
|
1325
|
+
|
|
1326
|
+
for link in self.links:
|
|
1327
|
+
if link.iscollided(shape, skip=True):
|
|
1328
|
+
return True
|
|
1329
|
+
|
|
1330
|
+
if isinstance(self, rtb.Robot):
|
|
1331
|
+
for gripper in self.grippers:
|
|
1332
|
+
for link in gripper.links:
|
|
1333
|
+
if link.iscollided(shape, skip=True):
|
|
1334
|
+
return True
|
|
1335
|
+
|
|
1336
|
+
return False
|
|
1337
|
+
|
|
1338
|
+
def collided(self, q, shape: Shape, skip: bool = False) -> bool:
|
|
1339
|
+
"""
|
|
1340
|
+
Check if the robot is in collision with a shape
|
|
1341
|
+
|
|
1342
|
+
``collided(shape)`` checks if this robot and shape have collided
|
|
1343
|
+
|
|
1344
|
+
Parameters
|
|
1345
|
+
----------
|
|
1346
|
+
shape
|
|
1347
|
+
The shape to compare distance to
|
|
1348
|
+
skip
|
|
1349
|
+
Skip setting all shape transforms based on q, use this
|
|
1350
|
+
option if using this method in conjuction with Swift to save time
|
|
1351
|
+
|
|
1352
|
+
Returns
|
|
1353
|
+
-------
|
|
1354
|
+
collided
|
|
1355
|
+
True if shapes have collided
|
|
1356
|
+
|
|
1357
|
+
"""
|
|
1358
|
+
|
|
1359
|
+
warn("method collided is deprecated, use iscollided instead", FutureWarning)
|
|
1360
|
+
return self.iscollided(q, shape, skip=skip)
|
|
1361
|
+
|
|
1362
|
+
# --------------------------------------------------------------------- #
|
|
1363
|
+
# --------- Constraint Methods ---------------------------------------- #
|
|
1364
|
+
# --------------------------------------------------------------------- #
|
|
1365
|
+
|
|
1366
|
+
def joint_velocity_damper(
|
|
1367
|
+
self,
|
|
1368
|
+
q=None,
|
|
1369
|
+
ps: float = 0.05,
|
|
1370
|
+
pi: float = 0.1,
|
|
1371
|
+
n: Union[int, None] = None,
|
|
1372
|
+
gain: float = 1.0,
|
|
1373
|
+
) -> Tuple[NDArray, NDArray]:
|
|
1374
|
+
"""
|
|
1375
|
+
Compute the joint velocity damper for QP motion control
|
|
1376
|
+
|
|
1377
|
+
Formulates an inequality contraint which, when optimised for will
|
|
1378
|
+
make it impossible for the robot to run into joint limits. Requires
|
|
1379
|
+
the joint limits of the robot to be specified. See examples/mmc.py
|
|
1380
|
+
for use case
|
|
1381
|
+
|
|
1382
|
+
Parameters
|
|
1383
|
+
----------
|
|
1384
|
+
ps
|
|
1385
|
+
The minimum angle (in radians) in which the joint is
|
|
1386
|
+
allowed to approach to its limit
|
|
1387
|
+
pi
|
|
1388
|
+
The influence angle (in radians) in which the velocity
|
|
1389
|
+
damper becomes active
|
|
1390
|
+
n
|
|
1391
|
+
The number of joints to consider. Defaults to all joints
|
|
1392
|
+
gain
|
|
1393
|
+
The gain for the velocity damper
|
|
1394
|
+
|
|
1395
|
+
Returns
|
|
1396
|
+
-------
|
|
1397
|
+
Ain
|
|
1398
|
+
A (6,) vector inequality contraint for an optisator
|
|
1399
|
+
Bin
|
|
1400
|
+
b (6,) vector inequality contraint for an optisator
|
|
1401
|
+
|
|
1402
|
+
"""
|
|
1403
|
+
|
|
1404
|
+
if n is None:
|
|
1405
|
+
n = self.n
|
|
1406
|
+
|
|
1407
|
+
if q is None:
|
|
1408
|
+
q = np.copy(self.q)
|
|
1409
|
+
|
|
1410
|
+
Ain = np.zeros((n, n))
|
|
1411
|
+
Bin = np.zeros(n)
|
|
1412
|
+
|
|
1413
|
+
for i in range(n):
|
|
1414
|
+
if self.q[i] - self.qlim[0, i] <= pi:
|
|
1415
|
+
Bin[i] = -gain * (((self.qlim[0, i] - q[i]) + ps) / (pi - ps))
|
|
1416
|
+
Ain[i, i] = -1
|
|
1417
|
+
if self.qlim[1, i] - self.q[i] <= pi:
|
|
1418
|
+
Bin[i] = gain * ((self.qlim[1, i] - q[i]) - ps) / (pi - ps)
|
|
1419
|
+
Ain[i, i] = 1
|
|
1420
|
+
|
|
1421
|
+
return Ain, Bin
|
|
1422
|
+
|
|
1423
|
+
def link_collision_damper(
|
|
1424
|
+
self,
|
|
1425
|
+
shape: CollisionShape,
|
|
1426
|
+
q: ArrayLike,
|
|
1427
|
+
di: float = 0.3,
|
|
1428
|
+
ds: float = 0.05,
|
|
1429
|
+
xi: float = 1.0,
|
|
1430
|
+
end: Union[Link, None] = None,
|
|
1431
|
+
start: Union[Link, None] = None,
|
|
1432
|
+
collision_list: Union[List[Shape], None] = None,
|
|
1433
|
+
):
|
|
1434
|
+
"""
|
|
1435
|
+
Compute a collision constrain for QP motion control
|
|
1436
|
+
|
|
1437
|
+
Formulates an inequality contraint which, when optimised for will
|
|
1438
|
+
make it impossible for the robot to run into a collision. Requires
|
|
1439
|
+
See examples/neo.py for use case
|
|
1440
|
+
|
|
1441
|
+
Parameters
|
|
1442
|
+
----------
|
|
1443
|
+
ds
|
|
1444
|
+
The minimum distance in which a joint is allowed to
|
|
1445
|
+
approach the collision object shape
|
|
1446
|
+
di
|
|
1447
|
+
The influence distance in which the velocity
|
|
1448
|
+
damper becomes active
|
|
1449
|
+
xi
|
|
1450
|
+
The gain for the velocity damper
|
|
1451
|
+
end
|
|
1452
|
+
The end link of the robot to consider
|
|
1453
|
+
start
|
|
1454
|
+
The start link of the robot to consider
|
|
1455
|
+
collision_list
|
|
1456
|
+
A list of shapes to consider for collision
|
|
1457
|
+
|
|
1458
|
+
Returns
|
|
1459
|
+
-------
|
|
1460
|
+
Ain
|
|
1461
|
+
A (6,) vector inequality contraint for an optisator
|
|
1462
|
+
Bin
|
|
1463
|
+
b (6,) vector inequality contraint for an optisator
|
|
1464
|
+
|
|
1465
|
+
"""
|
|
1466
|
+
|
|
1467
|
+
end, start, _ = self._get_limit_links(start=start, end=end)
|
|
1468
|
+
|
|
1469
|
+
links, n, _ = self.get_path(start=start, end=end)
|
|
1470
|
+
|
|
1471
|
+
q = np.array(q)
|
|
1472
|
+
j = 0
|
|
1473
|
+
Ain = None
|
|
1474
|
+
bin = None
|
|
1475
|
+
|
|
1476
|
+
def indiv_calculation(link: Link, link_col: CollisionShape, q: NDArray):
|
|
1477
|
+
d, wTlp, wTcp = link_col.closest_point(shape, di)
|
|
1478
|
+
|
|
1479
|
+
if d is not None and wTlp is not None and wTcp is not None:
|
|
1480
|
+
lpTcp = -wTlp + wTcp
|
|
1481
|
+
|
|
1482
|
+
norm = lpTcp / d
|
|
1483
|
+
norm_h = np.expand_dims(
|
|
1484
|
+
np.concatenate((norm, [0.0, 0.0, 0.0])),
|
|
1485
|
+
axis=0, # type: ignore
|
|
1486
|
+
)
|
|
1487
|
+
|
|
1488
|
+
# tool = (self.fkine(q, end=link).inv() * SE3(wTlp)).A[:3, 3]
|
|
1489
|
+
|
|
1490
|
+
# Je = self.jacob0(q, end=link, tool=tool)
|
|
1491
|
+
# Je[:3, :] = self._T[:3, :3] @ Je[:3, :]
|
|
1492
|
+
|
|
1493
|
+
# n_dim = Je.shape[1]
|
|
1494
|
+
# dp = norm_h @ shape.v
|
|
1495
|
+
# l_Ain = zeros((1, self.n))
|
|
1496
|
+
|
|
1497
|
+
Je = self.jacobe(q, start=start, end=link, tool=link_col.T)
|
|
1498
|
+
n_dim = Je.shape[1]
|
|
1499
|
+
dp = norm_h @ shape.v
|
|
1500
|
+
l_Ain = np.zeros((1, n))
|
|
1501
|
+
|
|
1502
|
+
l_Ain[0, :n_dim] = 1 * norm_h @ Je
|
|
1503
|
+
l_bin = (xi * (d - ds) / (di - ds)) + dp
|
|
1504
|
+
else: # pragma nocover
|
|
1505
|
+
l_Ain = None
|
|
1506
|
+
l_bin = None
|
|
1507
|
+
|
|
1508
|
+
return l_Ain, l_bin
|
|
1509
|
+
|
|
1510
|
+
for link in links:
|
|
1511
|
+
if link.isjoint:
|
|
1512
|
+
j += 1
|
|
1513
|
+
|
|
1514
|
+
if collision_list is None:
|
|
1515
|
+
col_list = link.collision
|
|
1516
|
+
|
|
1517
|
+
for c in col_list:
|
|
1518
|
+
pass
|
|
1519
|
+
else:
|
|
1520
|
+
col_list = [collision_list[j - 1]] # pragma nocover
|
|
1521
|
+
|
|
1522
|
+
for link_col in col_list:
|
|
1523
|
+
l_Ain, l_bin = indiv_calculation(link, link_col, q) # type: ignore
|
|
1524
|
+
|
|
1525
|
+
if l_Ain is not None and l_bin is not None:
|
|
1526
|
+
if Ain is None:
|
|
1527
|
+
Ain = l_Ain
|
|
1528
|
+
else:
|
|
1529
|
+
Ain = np.concatenate((Ain, l_Ain))
|
|
1530
|
+
|
|
1531
|
+
if bin is None:
|
|
1532
|
+
bin = np.array(l_bin)
|
|
1533
|
+
else:
|
|
1534
|
+
bin = np.concatenate((bin, l_bin))
|
|
1535
|
+
|
|
1536
|
+
return Ain, bin
|
|
1537
|
+
|
|
1538
|
+
def vision_collision_damper(
|
|
1539
|
+
self,
|
|
1540
|
+
shape: CollisionShape,
|
|
1541
|
+
camera: Union["Robot", SE3, None] = None,
|
|
1542
|
+
camera_n: int = 0,
|
|
1543
|
+
q=None,
|
|
1544
|
+
di=0.3,
|
|
1545
|
+
ds=0.05,
|
|
1546
|
+
xi=1.0,
|
|
1547
|
+
end=None,
|
|
1548
|
+
start=None,
|
|
1549
|
+
collision_list=None,
|
|
1550
|
+
): # pragma nocover
|
|
1551
|
+
"""
|
|
1552
|
+
Compute a vision collision constrain for QP motion control
|
|
1553
|
+
|
|
1554
|
+
Formulates an inequality contraint which, when optimised for will
|
|
1555
|
+
make it impossible for the robot to run into a line of sight.
|
|
1556
|
+
See examples/fetch_vision.py for use case
|
|
1557
|
+
|
|
1558
|
+
Parameters
|
|
1559
|
+
----------
|
|
1560
|
+
camera
|
|
1561
|
+
The camera link, either as a robotic link or SE3
|
|
1562
|
+
pose
|
|
1563
|
+
camera_n
|
|
1564
|
+
Degrees of freedom of the camera link
|
|
1565
|
+
ds
|
|
1566
|
+
The minimum distance in which a joint is allowed to
|
|
1567
|
+
approach the collision object shape
|
|
1568
|
+
di
|
|
1569
|
+
The influence distance in which the velocity
|
|
1570
|
+
damper becomes active
|
|
1571
|
+
xi
|
|
1572
|
+
The gain for the velocity damper
|
|
1573
|
+
end
|
|
1574
|
+
The end link of the robot to consider
|
|
1575
|
+
start
|
|
1576
|
+
The start link of the robot to consider
|
|
1577
|
+
collision_list
|
|
1578
|
+
A list of shapes to consider for collision
|
|
1579
|
+
|
|
1580
|
+
Returns
|
|
1581
|
+
-------
|
|
1582
|
+
Ain
|
|
1583
|
+
A (6,) vector inequality contraint for an optisator
|
|
1584
|
+
Bin
|
|
1585
|
+
b (6,) vector inequality contraint for an optisator
|
|
1586
|
+
"""
|
|
1587
|
+
|
|
1588
|
+
end, start, _ = self._get_limit_links(start=start, end=end)
|
|
1589
|
+
|
|
1590
|
+
links, n, _ = self.get_path(start=start, end=end)
|
|
1591
|
+
|
|
1592
|
+
q = np.array(q)
|
|
1593
|
+
j = 0
|
|
1594
|
+
Ain = None
|
|
1595
|
+
bin = None
|
|
1596
|
+
|
|
1597
|
+
def rotation_between_vectors(a, b):
|
|
1598
|
+
a = a / np.linalg.norm(a)
|
|
1599
|
+
b = b / np.linalg.norm(b)
|
|
1600
|
+
|
|
1601
|
+
angle = np.arccos(np.dot(a, b))
|
|
1602
|
+
axis = np.cross(a, b)
|
|
1603
|
+
|
|
1604
|
+
return SE3.AngleAxis(angle, axis)
|
|
1605
|
+
|
|
1606
|
+
if isinstance(camera, rtb.BaseRobot):
|
|
1607
|
+
wTcp = camera.fkine(camera.q).A[:3, 3]
|
|
1608
|
+
elif isinstance(camera, SE3):
|
|
1609
|
+
wTcp = camera.t
|
|
1610
|
+
else:
|
|
1611
|
+
raise TypeError("Camera must be a robotic link or SE3 pose")
|
|
1612
|
+
|
|
1613
|
+
wTtp = shape.T[:3, -1]
|
|
1614
|
+
|
|
1615
|
+
# Create line of sight object
|
|
1616
|
+
los_mid = SE3((wTcp + wTtp) / 2)
|
|
1617
|
+
los_orientation = rotation_between_vectors(
|
|
1618
|
+
np.array([0.0, 0.0, 1.0]),
|
|
1619
|
+
wTcp - wTtp, # type: ignore
|
|
1620
|
+
)
|
|
1621
|
+
|
|
1622
|
+
los = Cylinder(
|
|
1623
|
+
radius=0.001,
|
|
1624
|
+
length=np.linalg.norm(wTcp - wTtp), # type: ignore
|
|
1625
|
+
base=(los_mid * los_orientation),
|
|
1626
|
+
)
|
|
1627
|
+
|
|
1628
|
+
def indiv_calculation(link: Link, link_col: CollisionShape, q: NDArray):
|
|
1629
|
+
d, wTlp, wTvp = link_col.closest_point(los, di)
|
|
1630
|
+
|
|
1631
|
+
if d is not None and wTlp is not None and wTvp is not None:
|
|
1632
|
+
lpTvp = -wTlp + wTvp
|
|
1633
|
+
|
|
1634
|
+
norm = lpTvp / d
|
|
1635
|
+
norm_h = np.expand_dims(np.concatenate((norm, [0.0, 0.0, 0.0])), axis=0) # type: ignore
|
|
1636
|
+
|
|
1637
|
+
tool = SE3(
|
|
1638
|
+
(np.linalg.inv(self.fkine(q, end=link).A) @ SE3(wTlp).A)[:3, 3]
|
|
1639
|
+
)
|
|
1640
|
+
|
|
1641
|
+
Je = self.jacob0(q, end=link, tool=tool.A)
|
|
1642
|
+
Je[:3, :] = self._T[:3, :3] @ Je[:3, :]
|
|
1643
|
+
n_dim = Je.shape[1]
|
|
1644
|
+
|
|
1645
|
+
if isinstance(camera, "Robot"):
|
|
1646
|
+
Jv = camera.jacob0(camera.q)
|
|
1647
|
+
Jv[:3, :] = self._T[:3, :3] @ Jv[:3, :]
|
|
1648
|
+
|
|
1649
|
+
Jv *= np.linalg.norm(wTvp - shape.T[:3, -1]) / los.length # type: ignore
|
|
1650
|
+
|
|
1651
|
+
dpc = norm_h @ Jv
|
|
1652
|
+
dpc = np.concatenate(
|
|
1653
|
+
(
|
|
1654
|
+
dpc[0, :-camera_n],
|
|
1655
|
+
np.zeros(self.n - (camera.n - camera_n)),
|
|
1656
|
+
dpc[0, -camera_n:],
|
|
1657
|
+
)
|
|
1658
|
+
)
|
|
1659
|
+
else:
|
|
1660
|
+
dpc = np.zeros((1, self.n + camera_n))
|
|
1661
|
+
|
|
1662
|
+
dpt = norm_h @ shape.v
|
|
1663
|
+
dpt *= np.linalg.norm(wTvp - wTcp) / los.length # type: ignore
|
|
1664
|
+
|
|
1665
|
+
l_Ain = np.zeros((1, self.n + camera_n))
|
|
1666
|
+
l_Ain[0, :n_dim] = norm_h @ Je
|
|
1667
|
+
l_Ain -= dpc
|
|
1668
|
+
l_bin = (xi * (d - ds) / (di - ds)) + dpt
|
|
1669
|
+
else:
|
|
1670
|
+
l_Ain = None
|
|
1671
|
+
l_bin = None
|
|
1672
|
+
|
|
1673
|
+
return l_Ain, l_bin
|
|
1674
|
+
|
|
1675
|
+
for link in links:
|
|
1676
|
+
if link.isjoint:
|
|
1677
|
+
j += 1
|
|
1678
|
+
|
|
1679
|
+
if collision_list is None:
|
|
1680
|
+
col_list = link.collision
|
|
1681
|
+
else:
|
|
1682
|
+
col_list = collision_list[j - 1]
|
|
1683
|
+
|
|
1684
|
+
for link_col in col_list:
|
|
1685
|
+
l_Ain, l_bin = indiv_calculation(link, link_col, q)
|
|
1686
|
+
|
|
1687
|
+
if l_Ain is not None and l_bin is not None:
|
|
1688
|
+
if Ain is None:
|
|
1689
|
+
Ain = l_Ain
|
|
1690
|
+
else:
|
|
1691
|
+
Ain = np.concatenate((Ain, l_Ain))
|
|
1692
|
+
|
|
1693
|
+
if bin is None:
|
|
1694
|
+
bin = np.array(l_bin)
|
|
1695
|
+
else:
|
|
1696
|
+
bin = np.concatenate((bin, l_bin))
|
|
1697
|
+
|
|
1698
|
+
return Ain, bin
|
|
1699
|
+
|
|
1700
|
+
# --------------------------------------------------------------------- #
|
|
1701
|
+
# --------- Dynamics Methods ------------------------------------------ #
|
|
1702
|
+
# --------------------------------------------------------------------- #
|
|
1703
|
+
|
|
1704
|
+
def rne(
|
|
1705
|
+
self,
|
|
1706
|
+
q: NDArray,
|
|
1707
|
+
qd: NDArray,
|
|
1708
|
+
qdd: NDArray,
|
|
1709
|
+
symbolic: bool = False,
|
|
1710
|
+
gravity: Union[ArrayLike, None] = None,
|
|
1711
|
+
):
|
|
1712
|
+
"""
|
|
1713
|
+
Compute inverse dynamics via recursive Newton-Euler formulation
|
|
1714
|
+
|
|
1715
|
+
``rne_dh(q, qd, qdd)`` where the arguments have shape (n,) where n is
|
|
1716
|
+
the number of robot joints. The result has shape (n,).
|
|
1717
|
+
|
|
1718
|
+
``rne_dh(q, qd, qdd)`` where the arguments have shape (m,n) where n
|
|
1719
|
+
is the number of robot joints and where m is the number of steps in
|
|
1720
|
+
the joint trajectory. The result has shape (m,n).
|
|
1721
|
+
|
|
1722
|
+
``rne_dh(p)`` where the input is a 1D array ``p`` = [q, qd, qdd] with
|
|
1723
|
+
shape (3n,), and the result has shape (n,).
|
|
1724
|
+
|
|
1725
|
+
``rne_dh(p)`` where the input is a 2D array ``p`` = [q, qd, qdd] with
|
|
1726
|
+
shape (m,3n) and the result has shape (m,n).
|
|
1727
|
+
|
|
1728
|
+
Parameters
|
|
1729
|
+
----------
|
|
1730
|
+
q
|
|
1731
|
+
Joint coordinates
|
|
1732
|
+
qd
|
|
1733
|
+
Joint velocity
|
|
1734
|
+
qdd
|
|
1735
|
+
Joint acceleration
|
|
1736
|
+
symbolic
|
|
1737
|
+
If True, supports symbolic expressions
|
|
1738
|
+
gravity
|
|
1739
|
+
Gravitational acceleration, defaults to attribute
|
|
1740
|
+
of self
|
|
1741
|
+
|
|
1742
|
+
Returns
|
|
1743
|
+
-------
|
|
1744
|
+
tau
|
|
1745
|
+
Joint force/torques
|
|
1746
|
+
|
|
1747
|
+
Notes
|
|
1748
|
+
-----
|
|
1749
|
+
- This version supports symbolic model parameters
|
|
1750
|
+
- Verified against MATLAB code
|
|
1751
|
+
|
|
1752
|
+
"""
|
|
1753
|
+
|
|
1754
|
+
n = self.n
|
|
1755
|
+
# n = len(self.links)
|
|
1756
|
+
|
|
1757
|
+
# allocate intermediate variables
|
|
1758
|
+
Xup = SE3.Alloc(n)
|
|
1759
|
+
|
|
1760
|
+
v = SpatialVelocity.Alloc(n)
|
|
1761
|
+
a = SpatialAcceleration.Alloc(n)
|
|
1762
|
+
f = SpatialForce.Alloc(n)
|
|
1763
|
+
I = SpatialInertia.Alloc(n) # noqa
|
|
1764
|
+
s = [] # joint motion subspace
|
|
1765
|
+
|
|
1766
|
+
# Handle trajectory case
|
|
1767
|
+
q = getmatrix(q, (None, None))
|
|
1768
|
+
qd = getmatrix(qd, (None, None))
|
|
1769
|
+
qdd = getmatrix(qdd, (None, None))
|
|
1770
|
+
l, _ = q.shape
|
|
1771
|
+
|
|
1772
|
+
if symbolic: # pragma: nocover
|
|
1773
|
+
Q = np.empty((l, n), dtype="O") # joint torque/force
|
|
1774
|
+
else:
|
|
1775
|
+
Q = np.empty((l, n)) # joint torque/force
|
|
1776
|
+
|
|
1777
|
+
link_groups: List[List[int]] = []
|
|
1778
|
+
|
|
1779
|
+
# Group links together based on whether they are joints or not
|
|
1780
|
+
# Static links are grouped with the first joint encountered
|
|
1781
|
+
current_group = []
|
|
1782
|
+
for i, link in enumerate(self.links):
|
|
1783
|
+
current_group.append(i)
|
|
1784
|
+
|
|
1785
|
+
# Break after adding the first link
|
|
1786
|
+
if link.isjoint:
|
|
1787
|
+
link_groups.append(current_group)
|
|
1788
|
+
current_group = []
|
|
1789
|
+
|
|
1790
|
+
# Make some intermediate variables
|
|
1791
|
+
for i, group in enumerate(link_groups):
|
|
1792
|
+
I_int = SpatialInertia()
|
|
1793
|
+
|
|
1794
|
+
for idx in group:
|
|
1795
|
+
link = self.links[idx]
|
|
1796
|
+
|
|
1797
|
+
I_int = I_int + SpatialInertia(m=link.m, r=link.r)
|
|
1798
|
+
|
|
1799
|
+
if link.v is not None:
|
|
1800
|
+
s.append(link.v.s)
|
|
1801
|
+
|
|
1802
|
+
I[i] = I_int
|
|
1803
|
+
|
|
1804
|
+
if gravity is None:
|
|
1805
|
+
a_grav = -SpatialAcceleration(self.gravity)
|
|
1806
|
+
else: # pragma nocover
|
|
1807
|
+
a_grav = -SpatialAcceleration(gravity)
|
|
1808
|
+
|
|
1809
|
+
# For the following, v, a, f, I, s, Xup are all lists of length n
|
|
1810
|
+
# where the indices correspond to the index of the group within
|
|
1811
|
+
# link_groups
|
|
1812
|
+
# As always, q, qd, qdd are lists of length n, where indices correspond
|
|
1813
|
+
# to the jindex of the joint, which will be the last link in the group
|
|
1814
|
+
# within link_groups
|
|
1815
|
+
|
|
1816
|
+
for k in range(l):
|
|
1817
|
+
qk = q[k, :]
|
|
1818
|
+
qdk = qd[k, :]
|
|
1819
|
+
qddk = qdd[k, :]
|
|
1820
|
+
|
|
1821
|
+
# forward recursion
|
|
1822
|
+
for j, group in enumerate(link_groups):
|
|
1823
|
+
# The joint is the last link in the group
|
|
1824
|
+
joint = self.links[group[-1]]
|
|
1825
|
+
jindex = joint.jindex
|
|
1826
|
+
|
|
1827
|
+
vJ = SpatialVelocity(s[j] * qdk[jindex])
|
|
1828
|
+
|
|
1829
|
+
# transform from parent(j) to j
|
|
1830
|
+
# Xup_int = SE3()
|
|
1831
|
+
first_element = True
|
|
1832
|
+
for idx in group:
|
|
1833
|
+
link = self.links[idx]
|
|
1834
|
+
|
|
1835
|
+
if link.isjoint and link.jindex is not None:
|
|
1836
|
+
if first_element:
|
|
1837
|
+
Xup_int = SE3(link.A(qk[link.jindex]))
|
|
1838
|
+
first_element = False
|
|
1839
|
+
else:
|
|
1840
|
+
Xup_int = Xup_int * SE3(link.A(qk[link.jindex]))
|
|
1841
|
+
else:
|
|
1842
|
+
if first_element:
|
|
1843
|
+
Xup_int = SE3(link.A())
|
|
1844
|
+
first_element = False
|
|
1845
|
+
else:
|
|
1846
|
+
Xup_int = Xup_int * SE3(link.A())
|
|
1847
|
+
|
|
1848
|
+
Xup[j] = Xup_int.inv()
|
|
1849
|
+
|
|
1850
|
+
# The first link in the group
|
|
1851
|
+
first_link = self.links[group[0]]
|
|
1852
|
+
|
|
1853
|
+
if first_link.parent is None:
|
|
1854
|
+
v[j] = vJ
|
|
1855
|
+
a[j] = Xup[j] * a_grav + SpatialAcceleration(s[j] * qddk[jindex])
|
|
1856
|
+
else:
|
|
1857
|
+
# The index of `link`s parent within self.links
|
|
1858
|
+
parent_idx = self.links.index(first_link.parent)
|
|
1859
|
+
|
|
1860
|
+
# The index of the group that the parent link is in
|
|
1861
|
+
group_idx = [
|
|
1862
|
+
i for i, group in enumerate(link_groups) if parent_idx in group
|
|
1863
|
+
][0]
|
|
1864
|
+
|
|
1865
|
+
v[j] = Xup[j] * v[group_idx] + vJ
|
|
1866
|
+
a[j] = (
|
|
1867
|
+
Xup[j] * a[group_idx]
|
|
1868
|
+
+ SpatialAcceleration(s[j] * qddk[jindex])
|
|
1869
|
+
+ v[j] @ vJ
|
|
1870
|
+
)
|
|
1871
|
+
|
|
1872
|
+
f[j] = I[j] * a[j] + v[j] @ (I[j] * v[j])
|
|
1873
|
+
|
|
1874
|
+
# Backward recursion
|
|
1875
|
+
for j in reversed(range(n)):
|
|
1876
|
+
group = link_groups[j]
|
|
1877
|
+
joint = self.links[group[-1]]
|
|
1878
|
+
first_link = self.links[group[0]]
|
|
1879
|
+
# link = self.links[j]
|
|
1880
|
+
|
|
1881
|
+
# next line could be dot(), but fails for symbolic arguments
|
|
1882
|
+
Q[k, j] = sum(f[j].A * s[j])
|
|
1883
|
+
|
|
1884
|
+
if first_link.parent is not None:
|
|
1885
|
+
# The index of `link`s parent within self.links
|
|
1886
|
+
parent_idx = self.links.index(first_link.parent)
|
|
1887
|
+
|
|
1888
|
+
# The index of the group that the parent link is in
|
|
1889
|
+
group_idx = [
|
|
1890
|
+
i for i, group in enumerate(link_groups) if parent_idx in group
|
|
1891
|
+
][0]
|
|
1892
|
+
|
|
1893
|
+
f[group_idx] = f[group_idx] + Xup[j] * f[j]
|
|
1894
|
+
|
|
1895
|
+
# The current Q has the length equal to the number of links within the robot
|
|
1896
|
+
# rather than the number of joints. We need to remove the static links
|
|
1897
|
+
# from the Q array
|
|
1898
|
+
# joint_idx = [i for i, link in enumerate(self.links) if link.isjoint]
|
|
1899
|
+
|
|
1900
|
+
if l == 1:
|
|
1901
|
+
return Q[0]
|
|
1902
|
+
else: # pragma nocover
|
|
1903
|
+
return Q
|
|
1904
|
+
|
|
1905
|
+
|
|
1906
|
+
# ============================================================================= #
|
|
1907
|
+
# ================= Robot2 Class ============================================== #
|
|
1908
|
+
# ============================================================================= #
|
|
1909
|
+
|
|
1910
|
+
|
|
1911
|
+
class Robot2(BaseRobot[Link2]):
|
|
1912
|
+
def __init__(self, arg, **kwargs):
|
|
1913
|
+
if isinstance(arg, ETS2):
|
|
1914
|
+
# we're passed an ETS string
|
|
1915
|
+
links = []
|
|
1916
|
+
# chop it up into segments, a link frame after every joint
|
|
1917
|
+
parent = None
|
|
1918
|
+
for j, ets_j in enumerate(arg.split()):
|
|
1919
|
+
elink = Link2(ETS2(ets_j), parent=parent, name=f"link{j:d}")
|
|
1920
|
+
parent = elink
|
|
1921
|
+
if (
|
|
1922
|
+
elink.qlim is None
|
|
1923
|
+
and elink.v is not None
|
|
1924
|
+
and elink.v.qlim is not None
|
|
1925
|
+
): # pragma nocover
|
|
1926
|
+
elink.qlim = elink.v.qlim
|
|
1927
|
+
links.append(elink)
|
|
1928
|
+
|
|
1929
|
+
elif smb.islistof(arg, Link2):
|
|
1930
|
+
links = arg
|
|
1931
|
+
|
|
1932
|
+
else: # pragma nocover
|
|
1933
|
+
raise TypeError("constructor argument must be ETS2 or list of Link2")
|
|
1934
|
+
|
|
1935
|
+
super().__init__(links, **kwargs)
|
|
1936
|
+
|
|
1937
|
+
# Should just set it to None
|
|
1938
|
+
self.base = SE2() # override superclass
|
|
1939
|
+
|
|
1940
|
+
@property
|
|
1941
|
+
def base(self) -> SE2:
|
|
1942
|
+
"""
|
|
1943
|
+
Get/set robot base transform (Robot superclass)
|
|
1944
|
+
|
|
1945
|
+
``robot.base`` is the robot base transform
|
|
1946
|
+
|
|
1947
|
+
Returns
|
|
1948
|
+
-------
|
|
1949
|
+
base
|
|
1950
|
+
robot tool transform
|
|
1951
|
+
|
|
1952
|
+
- ``robot.base = ...`` checks and sets the robot base transform
|
|
1953
|
+
|
|
1954
|
+
Notes
|
|
1955
|
+
-----
|
|
1956
|
+
- The private attribute ``_base`` will be None in the case of
|
|
1957
|
+
no base transform, but this property will return ``SE3()`` which
|
|
1958
|
+
is an identity matrix.
|
|
1959
|
+
"""
|
|
1960
|
+
if self._base is None: # pragma nocover
|
|
1961
|
+
self._base = SE2()
|
|
1962
|
+
|
|
1963
|
+
# return a copy, otherwise somebody with
|
|
1964
|
+
# reference to the base can change it
|
|
1965
|
+
return self._base.copy()
|
|
1966
|
+
|
|
1967
|
+
@base.setter
|
|
1968
|
+
def base(self, T):
|
|
1969
|
+
if isinstance(T, SE2):
|
|
1970
|
+
self._base = T
|
|
1971
|
+
elif SE2.isvalid(T): # pragma nocover
|
|
1972
|
+
self._tool = SE2(T, check=True)
|
|
1973
|
+
|
|
1974
|
+
def jacob0(self, q, start=None, end=None):
|
|
1975
|
+
return self.ets(start, end).jacob0(q)
|
|
1976
|
+
|
|
1977
|
+
def jacobe(self, q, start=None, end=None):
|
|
1978
|
+
return self.ets(start, end).jacobe(q)
|
|
1979
|
+
|
|
1980
|
+
def fkine(self, q, end=None, start=None):
|
|
1981
|
+
return self.ets(start, end).fkine(q)
|
|
1982
|
+
|
|
1983
|
+
@property
|
|
1984
|
+
def reach(self) -> float:
|
|
1985
|
+
r"""
|
|
1986
|
+
Reach of the robot
|
|
1987
|
+
|
|
1988
|
+
A conservative estimate of the reach of the robot. It is computed as
|
|
1989
|
+
the sum of the translational ETs that define the link transform.
|
|
1990
|
+
|
|
1991
|
+
Note
|
|
1992
|
+
----
|
|
1993
|
+
Computed on the first access. If kinematic parameters
|
|
1994
|
+
subsequently change this will not be reflected.
|
|
1995
|
+
|
|
1996
|
+
Returns
|
|
1997
|
+
-------
|
|
1998
|
+
reach
|
|
1999
|
+
Maximum reach of the robot
|
|
2000
|
+
|
|
2001
|
+
Notes
|
|
2002
|
+
-----
|
|
2003
|
+
- Probably an overestimate of reach
|
|
2004
|
+
- Used by numerical inverse kinematics to scale translational
|
|
2005
|
+
error.
|
|
2006
|
+
- For a prismatic joint, uses ``qlim`` if it is set
|
|
2007
|
+
|
|
2008
|
+
"""
|
|
2009
|
+
|
|
2010
|
+
# TODO
|
|
2011
|
+
# This should be a start, end method and compute the reach based on the
|
|
2012
|
+
# given ets. Then use an lru_cache to speed up return
|
|
2013
|
+
|
|
2014
|
+
if self._reach is None:
|
|
2015
|
+
d_all = []
|
|
2016
|
+
for link in self.ee_links:
|
|
2017
|
+
d = 0
|
|
2018
|
+
while True:
|
|
2019
|
+
for et in link.ets:
|
|
2020
|
+
if et.istranslation:
|
|
2021
|
+
if et.isjoint:
|
|
2022
|
+
# the length of a prismatic joint depends on the
|
|
2023
|
+
# joint limits. They might be set in the ET
|
|
2024
|
+
# or in the Link depending on how the robot
|
|
2025
|
+
# was constructed
|
|
2026
|
+
if link.qlim is not None:
|
|
2027
|
+
d += max(link.qlim)
|
|
2028
|
+
elif et.qlim is not None: # pragma nocover
|
|
2029
|
+
d += max(et.qlim)
|
|
2030
|
+
else:
|
|
2031
|
+
d += abs(et.eta)
|
|
2032
|
+
link = link.parent
|
|
2033
|
+
if link is None or isinstance(link, str):
|
|
2034
|
+
d_all.append(d)
|
|
2035
|
+
break
|
|
2036
|
+
|
|
2037
|
+
self._reach = max(d_all)
|
|
2038
|
+
return self._reach
|
|
2039
|
+
|
|
2040
|
+
def fkine_all(self, q: ArrayLike) -> SE2:
|
|
2041
|
+
"""
|
|
2042
|
+
Compute the pose of every link frame
|
|
2043
|
+
|
|
2044
|
+
``T = robot.fkine_all(q)`` is an SE3 instance with ``robot.nlinks +
|
|
2045
|
+
1`` values:
|
|
2046
|
+
|
|
2047
|
+
- ``T[0]`` is the base transform
|
|
2048
|
+
- ``T[i]`` is the pose of link whose ``number`` is ``i``
|
|
2049
|
+
|
|
2050
|
+
Parameters
|
|
2051
|
+
----------
|
|
2052
|
+
q
|
|
2053
|
+
The joint configuration
|
|
2054
|
+
|
|
2055
|
+
Returns
|
|
2056
|
+
-------
|
|
2057
|
+
fkine_all
|
|
2058
|
+
Pose of all links
|
|
2059
|
+
|
|
2060
|
+
References
|
|
2061
|
+
----------
|
|
2062
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
2063
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
2064
|
+
|
|
2065
|
+
""" # noqa
|
|
2066
|
+
|
|
2067
|
+
q = getvector(q)
|
|
2068
|
+
|
|
2069
|
+
Tbase = SE2(self.base) # add base, also sets the type
|
|
2070
|
+
|
|
2071
|
+
linkframes = Tbase.__class__.Alloc(self.nlinks + 1)
|
|
2072
|
+
linkframes[0] = Tbase
|
|
2073
|
+
|
|
2074
|
+
def recurse(Tall, Tparent, q, link):
|
|
2075
|
+
# if joint??
|
|
2076
|
+
T = Tparent
|
|
2077
|
+
while True:
|
|
2078
|
+
T *= SE2(link.A(q[link.jindex]))
|
|
2079
|
+
|
|
2080
|
+
Tall[link.number] = T
|
|
2081
|
+
|
|
2082
|
+
if link.nchildren == 0:
|
|
2083
|
+
# no children
|
|
2084
|
+
return
|
|
2085
|
+
elif link.nchildren == 1:
|
|
2086
|
+
# one child
|
|
2087
|
+
if link in self.ee_links: # pragma nocover
|
|
2088
|
+
# this link is an end-effector, go no further
|
|
2089
|
+
return
|
|
2090
|
+
link = link.children[0]
|
|
2091
|
+
continue
|
|
2092
|
+
else:
|
|
2093
|
+
# multiple children
|
|
2094
|
+
for child in link.children:
|
|
2095
|
+
recurse(Tall, T, q, child)
|
|
2096
|
+
return
|
|
2097
|
+
|
|
2098
|
+
recurse(linkframes, Tbase, q, self.links[0])
|
|
2099
|
+
|
|
2100
|
+
return linkframes
|