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,3542 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
@author: Jesse Haviland
|
|
5
|
+
@author: Peter Corke
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
from collections import UserList
|
|
10
|
+
import numpy as np
|
|
11
|
+
from numpy.random import uniform
|
|
12
|
+
from numpy.linalg import inv, det, cond, svd
|
|
13
|
+
from spatialmath import SE3, SE2
|
|
14
|
+
from spatialmath.base import (
|
|
15
|
+
getvector,
|
|
16
|
+
issymbol,
|
|
17
|
+
tr2jac,
|
|
18
|
+
verifymatrix,
|
|
19
|
+
tr2jac2,
|
|
20
|
+
t2r,
|
|
21
|
+
rotvelxform,
|
|
22
|
+
simplify,
|
|
23
|
+
getmatrix,
|
|
24
|
+
)
|
|
25
|
+
from roboticstoolbox import rtb_get_param
|
|
26
|
+
from roboticstoolbox.robot.IK import IK_GN, IK_LM, IK_NR, IK_QP
|
|
27
|
+
|
|
28
|
+
from roboticstoolbox.fknm import (
|
|
29
|
+
ETS_init,
|
|
30
|
+
ETS_fkine,
|
|
31
|
+
ETS_jacob0,
|
|
32
|
+
ETS_jacobe,
|
|
33
|
+
ETS_hessian0,
|
|
34
|
+
ETS_hessiane,
|
|
35
|
+
IK_NR_c,
|
|
36
|
+
IK_GN_c,
|
|
37
|
+
IK_LM_c,
|
|
38
|
+
)
|
|
39
|
+
from copy import deepcopy
|
|
40
|
+
from roboticstoolbox.robot.ET import ET, ET2, BaseET
|
|
41
|
+
from typing import Union, overload, List, Set, Tuple, TypeVar
|
|
42
|
+
from typing_extensions import Literal as L
|
|
43
|
+
from sys import version_info
|
|
44
|
+
from roboticstoolbox.tools.types import ArrayLike, NDArray
|
|
45
|
+
|
|
46
|
+
py_ver = version_info
|
|
47
|
+
|
|
48
|
+
if version_info >= (3, 9):
|
|
49
|
+
from functools import cached_property
|
|
50
|
+
|
|
51
|
+
c_property = cached_property
|
|
52
|
+
else: # pragma: nocover
|
|
53
|
+
c_property = property
|
|
54
|
+
|
|
55
|
+
T = TypeVar("T", bound="BaseETS")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class BaseETS(UserList):
|
|
59
|
+
def __init__(self, *args):
|
|
60
|
+
super().__init__(*args)
|
|
61
|
+
|
|
62
|
+
def _update_internals(self):
|
|
63
|
+
self._m = len(self.data)
|
|
64
|
+
self._n = len([True for et in self.data if et.isjoint])
|
|
65
|
+
self._fknm = ETS_init(
|
|
66
|
+
[et.fknm for et in self.data],
|
|
67
|
+
self._n,
|
|
68
|
+
self._m,
|
|
69
|
+
)
|
|
70
|
+
# self._fknm = [et.fknm for et in self.data]
|
|
71
|
+
|
|
72
|
+
def __str__(self, q: Union[str, None] = None):
|
|
73
|
+
"""
|
|
74
|
+
Pretty prints the ETS
|
|
75
|
+
|
|
76
|
+
``q`` controls how the joint variables are displayed:
|
|
77
|
+
|
|
78
|
+
- None, format depends on number of joint variables
|
|
79
|
+
- one, display joint variable as q
|
|
80
|
+
- more, display joint variables as q0, q1, ...
|
|
81
|
+
- if a joint index was provided, use this value
|
|
82
|
+
- "", display all joint variables as empty parentheses ``()``
|
|
83
|
+
- "θ", display all joint variables as ``(θ)``
|
|
84
|
+
- format string with passed joint variables ``(j, j+1)``, so "θ{0}"
|
|
85
|
+
would display joint variables as θ0, θ1, ... while "θ{1}" would
|
|
86
|
+
display joint variables as θ1, θ2, ... ``j`` is either the joint
|
|
87
|
+
index, if provided, otherwise a sequential value.
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
q
|
|
92
|
+
control how joint variables are displayed
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
str
|
|
97
|
+
Pretty printed ETS
|
|
98
|
+
|
|
99
|
+
Examples
|
|
100
|
+
--------
|
|
101
|
+
.. runblock:: pycon
|
|
102
|
+
>>> from roboticstoolbox import ET
|
|
103
|
+
>>> e = ET.Rz() * ET.tx(1) * ET.Rz()
|
|
104
|
+
>>> print(e[:2])
|
|
105
|
+
>>> print(e)
|
|
106
|
+
>>> print(e.__str__(""))
|
|
107
|
+
>>> print(e.__str__("θ{0}")) # numbering from 0
|
|
108
|
+
>>> print(e.__str__("θ{1}")) # numbering from 1
|
|
109
|
+
>>> # explicit joint indices
|
|
110
|
+
>>> e = ET.Rz(jindex=3) * ET.tx(1) * ET.Rz(jindex=4)
|
|
111
|
+
>>> print(e)
|
|
112
|
+
>>> print(e.__str__("θ{0}"))
|
|
113
|
+
|
|
114
|
+
Angular parameters are converted to degrees, except if they
|
|
115
|
+
are symbolic.
|
|
116
|
+
|
|
117
|
+
.. runblock:: pycon
|
|
118
|
+
>>> from roboticstoolbox import ET
|
|
119
|
+
>>> from spatialmath.base import symbol
|
|
120
|
+
>>> theta, d = symbol('theta, d')
|
|
121
|
+
>>> e = ET.Rx(theta) * ET.tx(2) * ET.Rx(45, 'deg') * ET.Ry(0.2) * ET.ty(d)
|
|
122
|
+
>>> str(e)
|
|
123
|
+
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
es = []
|
|
127
|
+
j = 0
|
|
128
|
+
c = 0
|
|
129
|
+
s = None
|
|
130
|
+
unicode = rtb_get_param("unicode")
|
|
131
|
+
|
|
132
|
+
# An empty SE3
|
|
133
|
+
if len(self.data) == 0:
|
|
134
|
+
return "SE3()"
|
|
135
|
+
|
|
136
|
+
if q is None:
|
|
137
|
+
if len(self.joints()) > 1:
|
|
138
|
+
q = "q{0}"
|
|
139
|
+
else:
|
|
140
|
+
q = "q"
|
|
141
|
+
|
|
142
|
+
# For et in the object, display it, data comes from properties
|
|
143
|
+
# which come from the named tuple
|
|
144
|
+
for et in self.data:
|
|
145
|
+
if et.isjoint:
|
|
146
|
+
if q is not None:
|
|
147
|
+
if et.jindex is None: # pragma: nocover this is no longer possible
|
|
148
|
+
_j = j
|
|
149
|
+
else:
|
|
150
|
+
_j = et.jindex
|
|
151
|
+
qvar = q.format( # lgtm [py/str-format/surplus-argument] # noqa
|
|
152
|
+
_j, _j + 1
|
|
153
|
+
)
|
|
154
|
+
# else:
|
|
155
|
+
# qvar = ""
|
|
156
|
+
|
|
157
|
+
if et.isflip:
|
|
158
|
+
s = f"{et.axis}(-{qvar})"
|
|
159
|
+
else:
|
|
160
|
+
s = f"{et.axis}({qvar})"
|
|
161
|
+
j += 1
|
|
162
|
+
|
|
163
|
+
elif et.isrotation:
|
|
164
|
+
if issymbol(et.eta):
|
|
165
|
+
s = f"{et.axis}({et.eta})"
|
|
166
|
+
else:
|
|
167
|
+
s = f"{et.axis}({et.eta * 180 / np.pi:.4g}°)"
|
|
168
|
+
|
|
169
|
+
elif et.istranslation:
|
|
170
|
+
try:
|
|
171
|
+
s = f"{et.axis}({et.eta:.4g})"
|
|
172
|
+
except TypeError: # pragma: nocover
|
|
173
|
+
s = f"{et.axis}({et.eta})"
|
|
174
|
+
|
|
175
|
+
elif not et.iselementary:
|
|
176
|
+
s = str(et)
|
|
177
|
+
c += 1
|
|
178
|
+
|
|
179
|
+
es.append(s)
|
|
180
|
+
|
|
181
|
+
if unicode:
|
|
182
|
+
return " \u2295 ".join(es)
|
|
183
|
+
else: # pragma: nocover
|
|
184
|
+
return " * ".join(es)
|
|
185
|
+
|
|
186
|
+
def _repr_pretty_(self, p, cycle):
|
|
187
|
+
"""
|
|
188
|
+
Pretty string for IPython
|
|
189
|
+
|
|
190
|
+
Print stringified version when variable is displayed in IPython, ie. on
|
|
191
|
+
a line by itself.
|
|
192
|
+
|
|
193
|
+
Parameters
|
|
194
|
+
----------
|
|
195
|
+
p
|
|
196
|
+
pretty printer handle (ignored)
|
|
197
|
+
cycle
|
|
198
|
+
pretty printer flag (ignored)
|
|
199
|
+
|
|
200
|
+
Examples
|
|
201
|
+
--------
|
|
202
|
+
In [1]: e
|
|
203
|
+
Out [1]: R(q0) ⊕ tx(1) ⊕ R(q1) ⊕ tx(1)
|
|
204
|
+
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
print(self.__str__()) # pragma: nocover
|
|
208
|
+
|
|
209
|
+
def joint_idx(self) -> List[int]:
|
|
210
|
+
"""
|
|
211
|
+
Get index of joint transforms
|
|
212
|
+
|
|
213
|
+
Returns
|
|
214
|
+
-------
|
|
215
|
+
joint_idx
|
|
216
|
+
indices of transforms that are joints
|
|
217
|
+
|
|
218
|
+
Examples
|
|
219
|
+
--------
|
|
220
|
+
.. runblock:: pycon
|
|
221
|
+
>>> from roboticstoolbox import ET
|
|
222
|
+
>>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1)
|
|
223
|
+
>>> e.joint_idx()
|
|
224
|
+
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
return np.where([e.isjoint for e in self])[0] # type: ignore
|
|
228
|
+
|
|
229
|
+
def joints(self) -> List[ET]:
|
|
230
|
+
"""
|
|
231
|
+
Get a list of the variable ETs with this ETS
|
|
232
|
+
|
|
233
|
+
Returns
|
|
234
|
+
-------
|
|
235
|
+
joints
|
|
236
|
+
list of ETs that are joints
|
|
237
|
+
|
|
238
|
+
Examples
|
|
239
|
+
--------
|
|
240
|
+
.. runblock:: pycon
|
|
241
|
+
>>> from roboticstoolbox import ET
|
|
242
|
+
>>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1)
|
|
243
|
+
>>> e.joints()
|
|
244
|
+
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
return [e for e in self if e.isjoint]
|
|
248
|
+
|
|
249
|
+
def jindex_set(self) -> Set[int]: #
|
|
250
|
+
"""
|
|
251
|
+
Get set of joint indices
|
|
252
|
+
|
|
253
|
+
Returns
|
|
254
|
+
-------
|
|
255
|
+
jindex_set
|
|
256
|
+
set of unique joint indices
|
|
257
|
+
|
|
258
|
+
Examples
|
|
259
|
+
--------
|
|
260
|
+
.. runblock:: pycon
|
|
261
|
+
>>> from roboticstoolbox import ET
|
|
262
|
+
>>> e = ET.Rz(jindex=1) * ET.tx(jindex=2) * ET.Rz(jindex=1) * ET.tx(1)
|
|
263
|
+
>>> e.jointset()
|
|
264
|
+
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
return set([self[j].jindex for j in self.joint_idx()]) # type: ignore
|
|
268
|
+
|
|
269
|
+
@c_property
|
|
270
|
+
def jindices(self) -> NDArray:
|
|
271
|
+
"""
|
|
272
|
+
Get an array of joint indices
|
|
273
|
+
|
|
274
|
+
Returns
|
|
275
|
+
-------
|
|
276
|
+
jindices
|
|
277
|
+
array of unique joint indices
|
|
278
|
+
|
|
279
|
+
Examples
|
|
280
|
+
--------
|
|
281
|
+
.. runblock:: pycon
|
|
282
|
+
>>> from roboticstoolbox import ET
|
|
283
|
+
>>> e = ET.Rz(jindex=1) * ET.tx(jindex=2) * ET.Rz(jindex=1) * ET.tx(1)
|
|
284
|
+
>>> e.jointset()
|
|
285
|
+
|
|
286
|
+
"""
|
|
287
|
+
|
|
288
|
+
return np.array([j.jindex for j in self.joints()]) # type: ignore
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def qlim(self):
|
|
292
|
+
r"""
|
|
293
|
+
Get/Set Joint limits
|
|
294
|
+
|
|
295
|
+
Limits are extracted from the link objects. If joints limits are
|
|
296
|
+
not set for:
|
|
297
|
+
|
|
298
|
+
- a revolute joint [-𝜋. 𝜋] is returned
|
|
299
|
+
- a prismatic joint an exception is raised
|
|
300
|
+
|
|
301
|
+
Parameters
|
|
302
|
+
----------
|
|
303
|
+
new_qlim
|
|
304
|
+
An ndarray(2, n) of the new joint limits to set
|
|
305
|
+
|
|
306
|
+
Returns
|
|
307
|
+
-------
|
|
308
|
+
:return: Array of joint limit values
|
|
309
|
+
:rtype: ndarray(2,n)
|
|
310
|
+
|
|
311
|
+
Raises
|
|
312
|
+
------
|
|
313
|
+
ValueError
|
|
314
|
+
unset limits for a prismatic joint
|
|
315
|
+
|
|
316
|
+
Examples
|
|
317
|
+
--------
|
|
318
|
+
.. runblock:: pycon
|
|
319
|
+
>>> import roboticstoolbox as rtb
|
|
320
|
+
>>> robot = rtb.models.DH.Puma560()
|
|
321
|
+
>>> robot.qlim
|
|
322
|
+
|
|
323
|
+
"""
|
|
324
|
+
|
|
325
|
+
limits = np.zeros((2, self.n))
|
|
326
|
+
|
|
327
|
+
for i, et in enumerate(self.joints()):
|
|
328
|
+
if et.isrotation:
|
|
329
|
+
if et.qlim is None:
|
|
330
|
+
v = [-np.pi, np.pi]
|
|
331
|
+
else:
|
|
332
|
+
v = et.qlim
|
|
333
|
+
elif et.istranslation:
|
|
334
|
+
if et.qlim is None:
|
|
335
|
+
raise ValueError("undefined prismatic joint limit")
|
|
336
|
+
else:
|
|
337
|
+
v = et.qlim
|
|
338
|
+
else:
|
|
339
|
+
raise ValueError("Undefined Joint Type") # pragma: nocover
|
|
340
|
+
limits[:, i] = v
|
|
341
|
+
|
|
342
|
+
return limits
|
|
343
|
+
|
|
344
|
+
@qlim.setter
|
|
345
|
+
def qlim(self, new_qlim: ArrayLike):
|
|
346
|
+
new_qlim = np.array(new_qlim)
|
|
347
|
+
|
|
348
|
+
if new_qlim.shape == (2,) and self.n == 1:
|
|
349
|
+
new_qlim = new_qlim.reshape(2, 1)
|
|
350
|
+
|
|
351
|
+
if new_qlim.shape != (2, self.n):
|
|
352
|
+
raise ValueError("new_qlim must be of shape (2, n)")
|
|
353
|
+
|
|
354
|
+
for j, i in enumerate(self.joint_idx()):
|
|
355
|
+
et = self[i]
|
|
356
|
+
et.qlim = new_qlim[:, j]
|
|
357
|
+
|
|
358
|
+
self[i] = et
|
|
359
|
+
|
|
360
|
+
self._update_internals()
|
|
361
|
+
|
|
362
|
+
@property
|
|
363
|
+
def structure(self) -> str:
|
|
364
|
+
"""
|
|
365
|
+
Joint structure string
|
|
366
|
+
|
|
367
|
+
A string comprising the characters 'R' or 'P' which indicate the types
|
|
368
|
+
of joints in order from left to right.
|
|
369
|
+
|
|
370
|
+
Returns
|
|
371
|
+
-------
|
|
372
|
+
structure
|
|
373
|
+
A string indicating the joint types
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
Examples
|
|
378
|
+
--------
|
|
379
|
+
.. runblock:: pycon
|
|
380
|
+
>>> from roboticstoolbox import ET
|
|
381
|
+
>>> e = ET.tz() * ET.tx(1) * ET.Rz() * ET.tx(1)
|
|
382
|
+
>>> e.structure
|
|
383
|
+
|
|
384
|
+
"""
|
|
385
|
+
|
|
386
|
+
return "".join(
|
|
387
|
+
["R" if self.data[i].isrotation else "P" for i in self.joint_idx()]
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
@property
|
|
391
|
+
def n(self) -> int:
|
|
392
|
+
"""
|
|
393
|
+
Number of joints
|
|
394
|
+
|
|
395
|
+
Counts the number of joints in the ETS.
|
|
396
|
+
|
|
397
|
+
Returns
|
|
398
|
+
-------
|
|
399
|
+
n
|
|
400
|
+
the number of joints in the ETS
|
|
401
|
+
|
|
402
|
+
Examples
|
|
403
|
+
--------
|
|
404
|
+
.. runblock:: pycon
|
|
405
|
+
>>> from roboticstoolbox import ET
|
|
406
|
+
>>> e = ET.Rx() * ET.tx(1) * ET.tz()
|
|
407
|
+
>>> e.n
|
|
408
|
+
|
|
409
|
+
See Also
|
|
410
|
+
--------
|
|
411
|
+
:func:`joints`
|
|
412
|
+
|
|
413
|
+
"""
|
|
414
|
+
|
|
415
|
+
return self._n
|
|
416
|
+
|
|
417
|
+
@property
|
|
418
|
+
def m(self) -> int:
|
|
419
|
+
"""
|
|
420
|
+
Number of transforms
|
|
421
|
+
|
|
422
|
+
Counts the number of transforms in the ETS.
|
|
423
|
+
|
|
424
|
+
Returns
|
|
425
|
+
-------
|
|
426
|
+
m
|
|
427
|
+
the number of transforms in the ETS
|
|
428
|
+
|
|
429
|
+
Examples
|
|
430
|
+
--------
|
|
431
|
+
.. runblock:: pycon
|
|
432
|
+
>>> from roboticstoolbox import ET
|
|
433
|
+
>>> e = ET.Rx() * ET.tx(1) * ET.tz()
|
|
434
|
+
>>> e.m
|
|
435
|
+
|
|
436
|
+
"""
|
|
437
|
+
|
|
438
|
+
return self._m
|
|
439
|
+
|
|
440
|
+
@overload
|
|
441
|
+
def data(self: "ETS") -> List[ET]: ... # pragma: nocover
|
|
442
|
+
|
|
443
|
+
@overload
|
|
444
|
+
def data(self: "ETS2") -> List[ET2]: ... # pragma: nocover
|
|
445
|
+
|
|
446
|
+
@property
|
|
447
|
+
def data(self):
|
|
448
|
+
return self._data
|
|
449
|
+
|
|
450
|
+
@data.setter
|
|
451
|
+
@overload
|
|
452
|
+
def data(self: "ETS", new_data: List[ET]): ... # pragma: nocover
|
|
453
|
+
|
|
454
|
+
@data.setter
|
|
455
|
+
@overload
|
|
456
|
+
def data(self: "ETS", new_data: List[ET2]): ... # pragma: nocover
|
|
457
|
+
|
|
458
|
+
@data.setter
|
|
459
|
+
def data(self, new_data):
|
|
460
|
+
self._data = new_data
|
|
461
|
+
|
|
462
|
+
@overload
|
|
463
|
+
def pop(self: "ETS", i: int = -1) -> ET: ... # pragma: nocover
|
|
464
|
+
|
|
465
|
+
@overload
|
|
466
|
+
def pop(self: "ETS2", i: int = -1) -> ET2: ... # pragma: nocover
|
|
467
|
+
|
|
468
|
+
def pop(self, i=-1):
|
|
469
|
+
"""
|
|
470
|
+
Pop value
|
|
471
|
+
|
|
472
|
+
Removes a value from the value list and returns it. The original
|
|
473
|
+
instance is modified.
|
|
474
|
+
|
|
475
|
+
Parameters
|
|
476
|
+
----------
|
|
477
|
+
i
|
|
478
|
+
item in the list to pop, default is last
|
|
479
|
+
|
|
480
|
+
Returns
|
|
481
|
+
-------
|
|
482
|
+
pop
|
|
483
|
+
the popped value
|
|
484
|
+
|
|
485
|
+
Raises
|
|
486
|
+
------
|
|
487
|
+
IndexError
|
|
488
|
+
if there are no values to pop
|
|
489
|
+
|
|
490
|
+
Examples
|
|
491
|
+
--------
|
|
492
|
+
.. runblock:: pycon
|
|
493
|
+
>>> from roboticstoolbox import ET
|
|
494
|
+
>>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1)
|
|
495
|
+
>>> tail = e.pop()
|
|
496
|
+
>>> tail
|
|
497
|
+
>>> e
|
|
498
|
+
|
|
499
|
+
"""
|
|
500
|
+
|
|
501
|
+
item = super().pop(i)
|
|
502
|
+
self._update_internals()
|
|
503
|
+
return item
|
|
504
|
+
|
|
505
|
+
@overload
|
|
506
|
+
def split(self: "ETS") -> List["ETS"]: ... # pragma: nocover
|
|
507
|
+
|
|
508
|
+
@overload
|
|
509
|
+
def split(self: "ETS2") -> List["ETS2"]: ... # pragma: nocover
|
|
510
|
+
|
|
511
|
+
def split(self):
|
|
512
|
+
"""
|
|
513
|
+
Split ETS into link segments
|
|
514
|
+
|
|
515
|
+
Returns
|
|
516
|
+
-------
|
|
517
|
+
split
|
|
518
|
+
a list of ETS, each one, apart from the last,
|
|
519
|
+
ends with a variable ET.
|
|
520
|
+
|
|
521
|
+
"""
|
|
522
|
+
|
|
523
|
+
segments = []
|
|
524
|
+
start = 0
|
|
525
|
+
|
|
526
|
+
for j, k in enumerate(self.joint_idx()):
|
|
527
|
+
ets_j = self.data[start : k + 1]
|
|
528
|
+
start = k + 1
|
|
529
|
+
segments.append(ets_j)
|
|
530
|
+
|
|
531
|
+
tail = self.data[start:]
|
|
532
|
+
|
|
533
|
+
if isinstance(tail, list):
|
|
534
|
+
tail_len = len(tail)
|
|
535
|
+
elif tail is not None: # pragma: nocover
|
|
536
|
+
tail_len = 1
|
|
537
|
+
else: # pragma: nocover
|
|
538
|
+
tail_len = 0
|
|
539
|
+
|
|
540
|
+
if tail_len > 0:
|
|
541
|
+
segments.append(tail)
|
|
542
|
+
|
|
543
|
+
return segments
|
|
544
|
+
|
|
545
|
+
def inv(self: T) -> T:
|
|
546
|
+
r"""
|
|
547
|
+
Inverse of ETS
|
|
548
|
+
|
|
549
|
+
The inverse of a given ETS. It is computed as the inverse of the
|
|
550
|
+
individual ETs in the reverse order.
|
|
551
|
+
|
|
552
|
+
.. math::
|
|
553
|
+
|
|
554
|
+
(\mathbf{E}_0, \mathbf{E}_1 \cdots \mathbf{E}_{n-1} )^{-1} = (\mathbf{E}_{n-1}^{-1}, \mathbf{E}_{n-2}^{-1} \cdots \mathbf{E}_0^{-1}{n-1} )
|
|
555
|
+
|
|
556
|
+
Returns
|
|
557
|
+
-------
|
|
558
|
+
inv
|
|
559
|
+
Inverse of the ETS
|
|
560
|
+
|
|
561
|
+
Examples
|
|
562
|
+
--------
|
|
563
|
+
.. runblock:: pycon
|
|
564
|
+
>>> from roboticstoolbox import ET
|
|
565
|
+
>>> e = ET.Rz(jindex=2) * ET.tx(1) * ET.Rx(jindex=3,flip=True) * ET.tx(1)
|
|
566
|
+
>>> print(e)
|
|
567
|
+
>>> print(e.inv())
|
|
568
|
+
|
|
569
|
+
Notes
|
|
570
|
+
-----
|
|
571
|
+
- It is essential to use explicit joint indices to account for
|
|
572
|
+
the reversed order of the transforms.
|
|
573
|
+
|
|
574
|
+
""" # noqa
|
|
575
|
+
|
|
576
|
+
return self.__class__([et.inv() for et in reversed(self.data)])
|
|
577
|
+
|
|
578
|
+
@overload
|
|
579
|
+
def __getitem__(self: "BaseETS", i: int) -> BaseET: ...
|
|
580
|
+
|
|
581
|
+
@overload
|
|
582
|
+
def __getitem__(self: "ETS", i: int) -> ET: ...
|
|
583
|
+
|
|
584
|
+
@overload
|
|
585
|
+
def __getitem__(self: "ETS", i: slice) -> List[ET]: ...
|
|
586
|
+
|
|
587
|
+
@overload
|
|
588
|
+
def __getitem__(self: "ETS2", i: int) -> ET2: ...
|
|
589
|
+
|
|
590
|
+
@overload
|
|
591
|
+
def __getitem__(self: "ETS2", i: slice) -> List[ET2]: ...
|
|
592
|
+
|
|
593
|
+
def __getitem__(self, i):
|
|
594
|
+
"""
|
|
595
|
+
Index or slice an ETS
|
|
596
|
+
|
|
597
|
+
Parameters
|
|
598
|
+
----------
|
|
599
|
+
i
|
|
600
|
+
the index or slince
|
|
601
|
+
|
|
602
|
+
Returns
|
|
603
|
+
-------
|
|
604
|
+
et
|
|
605
|
+
Elementary transform
|
|
606
|
+
|
|
607
|
+
Examples
|
|
608
|
+
--------
|
|
609
|
+
.. runblock:: pycon
|
|
610
|
+
>>> from roboticstoolbox import ET
|
|
611
|
+
>>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1)
|
|
612
|
+
>>> e[0]
|
|
613
|
+
>>> e[1]
|
|
614
|
+
>>> e[1:3]
|
|
615
|
+
|
|
616
|
+
"""
|
|
617
|
+
return self.data[i] # can be [2] or slice, eg. [3:5]
|
|
618
|
+
|
|
619
|
+
@overload
|
|
620
|
+
def __setitem__(self: "BaseETS", i: int, value: BaseET): ...
|
|
621
|
+
|
|
622
|
+
@overload
|
|
623
|
+
def __setitem__(self: "ETS", i: int, value: ET): ...
|
|
624
|
+
|
|
625
|
+
@overload
|
|
626
|
+
def __setitem__(self: "ETS", i: slice, value: List[ET]): ...
|
|
627
|
+
|
|
628
|
+
@overload
|
|
629
|
+
def __setitem__(self: "ETS2", i: int, value: ET2): ...
|
|
630
|
+
|
|
631
|
+
@overload
|
|
632
|
+
def __setitem__(self: "ETS2", i: slice, value: List[ET2]): ...
|
|
633
|
+
|
|
634
|
+
def __setitem__(self, i, value):
|
|
635
|
+
"""
|
|
636
|
+
Set an item in the ETS
|
|
637
|
+
|
|
638
|
+
Parameters
|
|
639
|
+
----------
|
|
640
|
+
i
|
|
641
|
+
the index
|
|
642
|
+
value
|
|
643
|
+
the value to set
|
|
644
|
+
|
|
645
|
+
Examples
|
|
646
|
+
--------
|
|
647
|
+
.. runblock:: pycon
|
|
648
|
+
>>> from roboticstoolbox import ET
|
|
649
|
+
>>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1)
|
|
650
|
+
>>> e[1] = ET.tx(2)
|
|
651
|
+
>>> e
|
|
652
|
+
|
|
653
|
+
"""
|
|
654
|
+
self.data[i] = value
|
|
655
|
+
self._update_internals()
|
|
656
|
+
|
|
657
|
+
def __deepcopy__(self, memo):
|
|
658
|
+
new_data = []
|
|
659
|
+
|
|
660
|
+
for data in self:
|
|
661
|
+
new_data.append(deepcopy(data))
|
|
662
|
+
|
|
663
|
+
cls = self.__class__
|
|
664
|
+
result = cls(new_data)
|
|
665
|
+
memo[id(self)] = result
|
|
666
|
+
return result
|
|
667
|
+
|
|
668
|
+
def plot(self, *args, **kwargs):
|
|
669
|
+
from roboticstoolbox.robot.Robot import Robot, Robot2
|
|
670
|
+
|
|
671
|
+
if isinstance(self, ETS):
|
|
672
|
+
robot = Robot(self)
|
|
673
|
+
else:
|
|
674
|
+
robot = Robot2(self)
|
|
675
|
+
|
|
676
|
+
robot.plot(*args, **kwargs)
|
|
677
|
+
|
|
678
|
+
def teach(self, *args, **kwargs):
|
|
679
|
+
from roboticstoolbox.robot.Robot import Robot, Robot2
|
|
680
|
+
|
|
681
|
+
if isinstance(self, ETS):
|
|
682
|
+
robot = Robot(self)
|
|
683
|
+
else:
|
|
684
|
+
robot = Robot2(self)
|
|
685
|
+
|
|
686
|
+
robot.teach(*args, **kwargs)
|
|
687
|
+
|
|
688
|
+
def random_q(self, i: int = 1) -> NDArray:
|
|
689
|
+
"""
|
|
690
|
+
Generate a random valid joint configuration
|
|
691
|
+
|
|
692
|
+
Generates a random q vector within the joint limits defined by
|
|
693
|
+
`self.qlim`.
|
|
694
|
+
|
|
695
|
+
Parameters
|
|
696
|
+
----------
|
|
697
|
+
i
|
|
698
|
+
number of configurations to generate
|
|
699
|
+
|
|
700
|
+
Examples
|
|
701
|
+
--------
|
|
702
|
+
.. runblock:: pycon
|
|
703
|
+
>>> import roboticstoolbox as rtb
|
|
704
|
+
>>> robot = rtb.models.Panda()
|
|
705
|
+
>>> ets = robot.ets()
|
|
706
|
+
>>> q = ets.random_q()
|
|
707
|
+
>>> q
|
|
708
|
+
|
|
709
|
+
"""
|
|
710
|
+
|
|
711
|
+
if i == 1:
|
|
712
|
+
q = np.zeros(self.n)
|
|
713
|
+
|
|
714
|
+
for i in range(self.n):
|
|
715
|
+
q[i] = uniform(self.qlim[0, i], self.qlim[1, i])
|
|
716
|
+
|
|
717
|
+
else:
|
|
718
|
+
q = np.zeros((i, self.n))
|
|
719
|
+
|
|
720
|
+
for j in range(i):
|
|
721
|
+
for i in range(self.n):
|
|
722
|
+
q[j, i] = uniform(self.qlim[0, i], self.qlim[1, i])
|
|
723
|
+
|
|
724
|
+
return q
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
class ETS(BaseETS):
|
|
728
|
+
"""
|
|
729
|
+
This class implements an elementary transform sequence (ETS) for 3D
|
|
730
|
+
|
|
731
|
+
An instance can contain an elementary transform (ET) or an elementary
|
|
732
|
+
transform sequence (ETS). It has list-like properties by subclassing
|
|
733
|
+
UserList, which means we can perform indexing, slicing pop, insert, as well
|
|
734
|
+
as using it as an iterator over its values.
|
|
735
|
+
|
|
736
|
+
- ``ETS()`` an empty ETS list
|
|
737
|
+
- ``ETS(et)`` an ETS containing a single ET
|
|
738
|
+
- ``ETS([et0, et1, et2])`` an ETS consisting of three ET's
|
|
739
|
+
|
|
740
|
+
Parameters
|
|
741
|
+
----------
|
|
742
|
+
arg
|
|
743
|
+
Function to compute ET value
|
|
744
|
+
|
|
745
|
+
Examples
|
|
746
|
+
--------
|
|
747
|
+
.. runblock:: pycon
|
|
748
|
+
>>> from roboticstoolbox import ETS, ET
|
|
749
|
+
>>> e = ET.Rz(0.3) # a single ET, rotation about z
|
|
750
|
+
>>> ets1 = ETS(e)
|
|
751
|
+
>>> len(ets1)
|
|
752
|
+
>>> ets2 = ET.Rz(0.3) * ET.tx(2) # an ETS
|
|
753
|
+
>>> len(ets2) # of length 2
|
|
754
|
+
>>> ets2[1] # an ET sliced from the ETS
|
|
755
|
+
|
|
756
|
+
References
|
|
757
|
+
----------
|
|
758
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
759
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
760
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
761
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
See Also
|
|
765
|
+
--------
|
|
766
|
+
:func:`rx`
|
|
767
|
+
:func:`ry`
|
|
768
|
+
:func:`rz`
|
|
769
|
+
:func:`tx`
|
|
770
|
+
:func:`ty`
|
|
771
|
+
:func:`tz`
|
|
772
|
+
|
|
773
|
+
"""
|
|
774
|
+
|
|
775
|
+
def __init__(
|
|
776
|
+
self,
|
|
777
|
+
arg: Union[
|
|
778
|
+
List[Union["ETS", ET]], List[ET], List["ETS"], ET, "ETS", None
|
|
779
|
+
] = None,
|
|
780
|
+
):
|
|
781
|
+
super().__init__()
|
|
782
|
+
if isinstance(arg, list):
|
|
783
|
+
for item in arg:
|
|
784
|
+
if isinstance(item, ET):
|
|
785
|
+
self.data.append(deepcopy(item))
|
|
786
|
+
elif isinstance(item, ETS):
|
|
787
|
+
for ets_item in item:
|
|
788
|
+
self.data.append(deepcopy(ets_item))
|
|
789
|
+
else:
|
|
790
|
+
raise TypeError("Invalid arg")
|
|
791
|
+
elif isinstance(arg, ET):
|
|
792
|
+
self.data.append(deepcopy(arg))
|
|
793
|
+
elif isinstance(arg, ETS):
|
|
794
|
+
for ets_item in arg:
|
|
795
|
+
self.data.append(deepcopy(ets_item))
|
|
796
|
+
elif arg is None:
|
|
797
|
+
self.data = []
|
|
798
|
+
else:
|
|
799
|
+
raise TypeError("Invalid arg")
|
|
800
|
+
|
|
801
|
+
super()._update_internals()
|
|
802
|
+
|
|
803
|
+
self._auto_jindex = False
|
|
804
|
+
|
|
805
|
+
# Check if jindices are set
|
|
806
|
+
joints = self.joints()
|
|
807
|
+
|
|
808
|
+
# Number of joints with a jindex
|
|
809
|
+
jindices = 0
|
|
810
|
+
|
|
811
|
+
# Number of joints with a sequential jindex (j[2] -> jindex = 2)
|
|
812
|
+
seq_jindex = 0
|
|
813
|
+
|
|
814
|
+
# Count them up
|
|
815
|
+
for j, joint in enumerate(joints):
|
|
816
|
+
if joint.jindex is not None:
|
|
817
|
+
jindices += 1
|
|
818
|
+
if joint.jindex == j:
|
|
819
|
+
seq_jindex += 1
|
|
820
|
+
|
|
821
|
+
if (
|
|
822
|
+
jindices == self.n - 1
|
|
823
|
+
and seq_jindex == self.n - 1
|
|
824
|
+
and joints[-1].jindex is None
|
|
825
|
+
):
|
|
826
|
+
# ets has sequential jindicies, except for the last.
|
|
827
|
+
joints[-1].jindex = self.n - 1
|
|
828
|
+
self._auto_jindex = True
|
|
829
|
+
|
|
830
|
+
elif jindices > 0 and not jindices == self.n:
|
|
831
|
+
raise ValueError(
|
|
832
|
+
"You can not have some jindices set for the ET's in arg. It must be all"
|
|
833
|
+
" or none"
|
|
834
|
+
) # pragma: nocover
|
|
835
|
+
elif jindices == 0 and self.n > 0:
|
|
836
|
+
# Set them ourself
|
|
837
|
+
for j, joint in enumerate(joints):
|
|
838
|
+
joint.jindex = j
|
|
839
|
+
|
|
840
|
+
self._auto_jindex = True
|
|
841
|
+
|
|
842
|
+
def __mul__(self, other: Union["ET", "ETS"]) -> "ETS":
|
|
843
|
+
if isinstance(other, ET):
|
|
844
|
+
return ETS([*self.data, other])
|
|
845
|
+
else:
|
|
846
|
+
return ETS([*self.data, *other.data]) # pragma: nocover
|
|
847
|
+
|
|
848
|
+
def __rmul__(self, other: Union["ET", "ETS"]) -> "ETS":
|
|
849
|
+
return ETS([other, *self.data]) # pragma: nocover
|
|
850
|
+
|
|
851
|
+
def __imul__(self, rest: "ETS"):
|
|
852
|
+
return self + rest # pragma: nocover
|
|
853
|
+
|
|
854
|
+
def __add__(self, rest) -> "ETS":
|
|
855
|
+
return self.__mul__(rest) # pragma: nocover
|
|
856
|
+
|
|
857
|
+
def compile(self) -> "ETS":
|
|
858
|
+
"""
|
|
859
|
+
Compile an ETS
|
|
860
|
+
|
|
861
|
+
Perform constant folding for faster evaluation. Consecutive constant
|
|
862
|
+
ETs are compounded, leading to a constant ET which is denoted by
|
|
863
|
+
``SE3`` when displayed.
|
|
864
|
+
|
|
865
|
+
Returns
|
|
866
|
+
-------
|
|
867
|
+
compile
|
|
868
|
+
optimised ETS
|
|
869
|
+
|
|
870
|
+
Examples
|
|
871
|
+
--------
|
|
872
|
+
.. runblock:: pycon
|
|
873
|
+
>>> import roboticstoolbox as rtb
|
|
874
|
+
>>> robot = rtb.models.ETS.Panda()
|
|
875
|
+
>>> ets = robot.ets()
|
|
876
|
+
>>> ets
|
|
877
|
+
>>> ets.compile()
|
|
878
|
+
|
|
879
|
+
See Also
|
|
880
|
+
--------
|
|
881
|
+
:func:`isconstant`
|
|
882
|
+
"""
|
|
883
|
+
const = None
|
|
884
|
+
ets = ETS()
|
|
885
|
+
|
|
886
|
+
for et in self:
|
|
887
|
+
if et.isjoint:
|
|
888
|
+
# a joint
|
|
889
|
+
if const is not None:
|
|
890
|
+
# flush the constant
|
|
891
|
+
if not np.array_equal(const, np.eye(4)):
|
|
892
|
+
ets *= ET.SE3(const)
|
|
893
|
+
const = None
|
|
894
|
+
ets *= et # emit the joint ET
|
|
895
|
+
else:
|
|
896
|
+
# not a joint
|
|
897
|
+
if const is None:
|
|
898
|
+
const = et.A()
|
|
899
|
+
else:
|
|
900
|
+
const = const @ et.A()
|
|
901
|
+
|
|
902
|
+
if const is not None:
|
|
903
|
+
# flush the constant, tool transform
|
|
904
|
+
if not np.array_equal(const, np.eye(4)):
|
|
905
|
+
ets *= ET.SE3(const)
|
|
906
|
+
return ets
|
|
907
|
+
|
|
908
|
+
def insert(
|
|
909
|
+
self,
|
|
910
|
+
arg: Union[ET, "ETS"],
|
|
911
|
+
i: int = -1,
|
|
912
|
+
) -> None:
|
|
913
|
+
"""
|
|
914
|
+
Insert value
|
|
915
|
+
|
|
916
|
+
Inserts an ET or ETS into the ET sequence. The inserted value is at position
|
|
917
|
+
``i``.
|
|
918
|
+
|
|
919
|
+
Parameters
|
|
920
|
+
----------
|
|
921
|
+
i
|
|
922
|
+
insert an ET or ETS into the ETS, default is at the end
|
|
923
|
+
arg
|
|
924
|
+
the elementary transform or sequence to insert
|
|
925
|
+
|
|
926
|
+
Examples
|
|
927
|
+
--------
|
|
928
|
+
.. runblock:: pycon
|
|
929
|
+
>>> from roboticstoolbox import ET
|
|
930
|
+
>>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1)
|
|
931
|
+
>>> f = ET.Ry()
|
|
932
|
+
>>> e.insert(f, 2)
|
|
933
|
+
>>> e
|
|
934
|
+
|
|
935
|
+
"""
|
|
936
|
+
|
|
937
|
+
if isinstance(arg, ET):
|
|
938
|
+
if i == -1:
|
|
939
|
+
self.data.append(arg)
|
|
940
|
+
else:
|
|
941
|
+
self.data.insert(i, arg)
|
|
942
|
+
elif isinstance(arg, ETS):
|
|
943
|
+
if i == -1:
|
|
944
|
+
for et in arg:
|
|
945
|
+
self.data.append(et)
|
|
946
|
+
else:
|
|
947
|
+
for j, et in enumerate(arg):
|
|
948
|
+
self.data.insert(i + j, et)
|
|
949
|
+
self._update_internals()
|
|
950
|
+
|
|
951
|
+
def fkine(
|
|
952
|
+
self,
|
|
953
|
+
q: ArrayLike,
|
|
954
|
+
base: Union[NDArray, SE3, None] = None,
|
|
955
|
+
tool: Union[NDArray, SE3, None] = None,
|
|
956
|
+
include_base: bool = True,
|
|
957
|
+
) -> SE3:
|
|
958
|
+
"""
|
|
959
|
+
Forward kinematics
|
|
960
|
+
|
|
961
|
+
``T = ets.fkine(q)`` evaluates forward kinematics for the ets at
|
|
962
|
+
joint configuration ``q``.
|
|
963
|
+
|
|
964
|
+
**Trajectory operation**:
|
|
965
|
+
If ``q`` has multiple rows (mxn), it is considered a trajectory and the
|
|
966
|
+
result is an ``SE3`` instance with ``m`` values.
|
|
967
|
+
|
|
968
|
+
Parameters
|
|
969
|
+
----------
|
|
970
|
+
q
|
|
971
|
+
Joint coordinates
|
|
972
|
+
base
|
|
973
|
+
A base transform applied before the ETS
|
|
974
|
+
tool
|
|
975
|
+
tool transform, optional
|
|
976
|
+
include_base
|
|
977
|
+
set to True if the base transform should be considered
|
|
978
|
+
|
|
979
|
+
Returns
|
|
980
|
+
-------
|
|
981
|
+
The transformation matrix representing the pose of the
|
|
982
|
+
end-effector
|
|
983
|
+
|
|
984
|
+
Examples
|
|
985
|
+
--------
|
|
986
|
+
The following example makes a ``panda`` robot object, gets the ets, and
|
|
987
|
+
solves for the forward kinematics at the listed configuration.
|
|
988
|
+
|
|
989
|
+
.. runblock:: pycon
|
|
990
|
+
>>> import roboticstoolbox as rtb
|
|
991
|
+
>>> panda = rtb.models.Panda().ets()
|
|
992
|
+
>>> panda.fkine([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
993
|
+
|
|
994
|
+
Notes
|
|
995
|
+
-----
|
|
996
|
+
- A tool transform, if provided, is incorporated into the result.
|
|
997
|
+
- Works from the end-effector link to the base
|
|
998
|
+
|
|
999
|
+
References
|
|
1000
|
+
----------
|
|
1001
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
1002
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
1003
|
+
|
|
1004
|
+
""" # noqa
|
|
1005
|
+
|
|
1006
|
+
ret = SE3.Empty()
|
|
1007
|
+
fk = self.eval(q, base, tool, include_base)
|
|
1008
|
+
|
|
1009
|
+
if fk.dtype == "O":
|
|
1010
|
+
# symbolic
|
|
1011
|
+
fk = np.array(simplify(fk))
|
|
1012
|
+
|
|
1013
|
+
if fk.ndim == 3:
|
|
1014
|
+
for T in fk:
|
|
1015
|
+
ret.append(SE3(T, check=False)) # type: ignore
|
|
1016
|
+
else:
|
|
1017
|
+
ret = SE3(fk, check=False)
|
|
1018
|
+
|
|
1019
|
+
return ret
|
|
1020
|
+
|
|
1021
|
+
def eval(
|
|
1022
|
+
self,
|
|
1023
|
+
q: ArrayLike,
|
|
1024
|
+
base: Union[NDArray, SE3, None] = None,
|
|
1025
|
+
tool: Union[NDArray, SE3, None] = None,
|
|
1026
|
+
include_base: bool = True,
|
|
1027
|
+
) -> NDArray:
|
|
1028
|
+
"""
|
|
1029
|
+
Forward kinematics
|
|
1030
|
+
|
|
1031
|
+
``T = ets.fkine(q)`` evaluates forward kinematics for the ets at
|
|
1032
|
+
joint configuration ``q``.
|
|
1033
|
+
|
|
1034
|
+
**Trajectory operation**:
|
|
1035
|
+
If ``q`` has multiple rows (mxn), it is considered a trajectory and the
|
|
1036
|
+
result is an ``SE3`` instance with ``m`` values.
|
|
1037
|
+
|
|
1038
|
+
Parameters
|
|
1039
|
+
----------
|
|
1040
|
+
q
|
|
1041
|
+
Joint coordinates
|
|
1042
|
+
base
|
|
1043
|
+
A base transform applied before the ETS
|
|
1044
|
+
tool
|
|
1045
|
+
tool transform, optional
|
|
1046
|
+
include_base
|
|
1047
|
+
set to True if the base transform should be considered
|
|
1048
|
+
Returns
|
|
1049
|
+
-------
|
|
1050
|
+
The transformation matrix representing the pose of the
|
|
1051
|
+
end-effector
|
|
1052
|
+
|
|
1053
|
+
Examples
|
|
1054
|
+
--------
|
|
1055
|
+
The following example makes a ``panda`` robot object, gets the ets, and
|
|
1056
|
+
solves for the forward kinematics at the listed configuration.
|
|
1057
|
+
|
|
1058
|
+
.. runblock:: pycon
|
|
1059
|
+
>>> import roboticstoolbox as rtb
|
|
1060
|
+
>>> panda = rtb.models.Panda().ets()
|
|
1061
|
+
>>> panda.fkine([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
1062
|
+
|
|
1063
|
+
Notes
|
|
1064
|
+
-----
|
|
1065
|
+
- A tool transform, if provided, is incorporated into the result.
|
|
1066
|
+
- Works from the end-effector link to the base
|
|
1067
|
+
|
|
1068
|
+
References
|
|
1069
|
+
----------
|
|
1070
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
1071
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
1072
|
+
|
|
1073
|
+
""" # noqa
|
|
1074
|
+
|
|
1075
|
+
try:
|
|
1076
|
+
return ETS_fkine(self._fknm, q, base, tool, include_base)
|
|
1077
|
+
except BaseException:
|
|
1078
|
+
pass
|
|
1079
|
+
|
|
1080
|
+
q = getmatrix(q, (None, None))
|
|
1081
|
+
l, _ = q.shape # type: ignore
|
|
1082
|
+
end = self.data[-1]
|
|
1083
|
+
|
|
1084
|
+
if isinstance(tool, SE3):
|
|
1085
|
+
tool = np.array(tool.A)
|
|
1086
|
+
|
|
1087
|
+
if isinstance(base, SE3):
|
|
1088
|
+
base = np.array(base.A)
|
|
1089
|
+
|
|
1090
|
+
if base is None:
|
|
1091
|
+
bases = None
|
|
1092
|
+
elif np.array_equal(base, np.eye(3)): # pragma: nocover
|
|
1093
|
+
bases = None
|
|
1094
|
+
else: # pragma: nocover
|
|
1095
|
+
bases = base
|
|
1096
|
+
|
|
1097
|
+
if tool is None:
|
|
1098
|
+
tools = None
|
|
1099
|
+
elif np.array_equal(tool, np.eye(3)): # pragma: nocover
|
|
1100
|
+
tools = None
|
|
1101
|
+
else: # pragma: nocover
|
|
1102
|
+
tools = tool
|
|
1103
|
+
|
|
1104
|
+
if l > 1:
|
|
1105
|
+
T = np.zeros((l, 4, 4), dtype=object)
|
|
1106
|
+
else:
|
|
1107
|
+
T = np.zeros((4, 4), dtype=object)
|
|
1108
|
+
|
|
1109
|
+
# Tk = None
|
|
1110
|
+
|
|
1111
|
+
for k, qk in enumerate(q): # type: ignore
|
|
1112
|
+
link = end # start with last link
|
|
1113
|
+
|
|
1114
|
+
jindex = 0 if link.jindex is None and link.isjoint else link.jindex
|
|
1115
|
+
|
|
1116
|
+
Tk = link.A(qk[jindex])
|
|
1117
|
+
|
|
1118
|
+
if tools is not None:
|
|
1119
|
+
Tk = Tk @ tools
|
|
1120
|
+
|
|
1121
|
+
# add remaining links, back toward the base
|
|
1122
|
+
for i in range(self.m - 2, -1, -1):
|
|
1123
|
+
link = self.data[i]
|
|
1124
|
+
|
|
1125
|
+
jindex = 0 if link.jindex is None and link.isjoint else link.jindex
|
|
1126
|
+
A = link.A(qk[jindex])
|
|
1127
|
+
|
|
1128
|
+
if A is not None:
|
|
1129
|
+
Tk = A @ Tk
|
|
1130
|
+
|
|
1131
|
+
# add base transform if it is set
|
|
1132
|
+
if include_base is True and bases is not None:
|
|
1133
|
+
Tk = bases @ Tk
|
|
1134
|
+
|
|
1135
|
+
# append
|
|
1136
|
+
if l > 1:
|
|
1137
|
+
T[k, :, :] = Tk
|
|
1138
|
+
else:
|
|
1139
|
+
T = Tk
|
|
1140
|
+
|
|
1141
|
+
return T
|
|
1142
|
+
|
|
1143
|
+
def jacob0(
|
|
1144
|
+
self,
|
|
1145
|
+
q: ArrayLike,
|
|
1146
|
+
tool: Union[NDArray, SE3, None] = None,
|
|
1147
|
+
) -> NDArray:
|
|
1148
|
+
r"""
|
|
1149
|
+
Manipulator geometric Jacobian in the base frame
|
|
1150
|
+
|
|
1151
|
+
``robot.jacobo(q)`` is the manipulator Jacobian matrix which maps
|
|
1152
|
+
joint velocity to end-effector spatial velocity expressed in the
|
|
1153
|
+
base frame.
|
|
1154
|
+
|
|
1155
|
+
End-effector spatial velocity :math:`\nu = (v_x, v_y, v_z, \omega_x, \omega_y, \omega_z)^T`
|
|
1156
|
+
is related to joint velocity by :math:`{}^{E}\!\nu = \mathbf{J}_m(q) \dot{q}`.
|
|
1157
|
+
|
|
1158
|
+
Parameters
|
|
1159
|
+
----------
|
|
1160
|
+
q
|
|
1161
|
+
Joint coordinate vector
|
|
1162
|
+
tool
|
|
1163
|
+
a static tool transformation matrix to apply to the
|
|
1164
|
+
end of end, defaults to None
|
|
1165
|
+
|
|
1166
|
+
Returns
|
|
1167
|
+
-------
|
|
1168
|
+
J0
|
|
1169
|
+
Manipulator Jacobian in the base frame
|
|
1170
|
+
|
|
1171
|
+
Examples
|
|
1172
|
+
--------
|
|
1173
|
+
The following example makes a ``Puma560`` robot object, and solves for the
|
|
1174
|
+
base-frame Jacobian at the zero joint angle configuration
|
|
1175
|
+
|
|
1176
|
+
.. runblock:: pycon
|
|
1177
|
+
>>> import roboticstoolbox as rtb
|
|
1178
|
+
>>> puma = rtb.models.Puma560().ets()
|
|
1179
|
+
>>> puma.jacob0([0, 0, 0, 0, 0, 0])
|
|
1180
|
+
|
|
1181
|
+
Notes
|
|
1182
|
+
-----
|
|
1183
|
+
- This is the geometric Jacobian as described in texts by
|
|
1184
|
+
Corke, Spong etal., Siciliano etal. The end-effector velocity is
|
|
1185
|
+
described in terms of translational and angular velocity, not a
|
|
1186
|
+
velocity twist as per the text by Lynch & Park.
|
|
1187
|
+
|
|
1188
|
+
References
|
|
1189
|
+
----------
|
|
1190
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
1191
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
1192
|
+
|
|
1193
|
+
""" # noqa
|
|
1194
|
+
|
|
1195
|
+
# Use c extension
|
|
1196
|
+
try:
|
|
1197
|
+
return ETS_jacob0(self._fknm, q, tool)
|
|
1198
|
+
except TypeError:
|
|
1199
|
+
pass
|
|
1200
|
+
|
|
1201
|
+
# Otherwise use Python
|
|
1202
|
+
if tool is None:
|
|
1203
|
+
tools = np.eye(4)
|
|
1204
|
+
elif isinstance(tool, SE3):
|
|
1205
|
+
tools = np.array(tool.A)
|
|
1206
|
+
else: # pragma: nocover
|
|
1207
|
+
tools = np.eye(4)
|
|
1208
|
+
|
|
1209
|
+
q = getvector(q, None)
|
|
1210
|
+
|
|
1211
|
+
T = self.eval(q, include_base=False) @ tools
|
|
1212
|
+
|
|
1213
|
+
U = np.eye(4)
|
|
1214
|
+
j = 0
|
|
1215
|
+
J = np.zeros((6, self.n), dtype="object")
|
|
1216
|
+
zero = np.array([0, 0, 0])
|
|
1217
|
+
end = self.data[-1]
|
|
1218
|
+
|
|
1219
|
+
for link in self.data:
|
|
1220
|
+
jindex = 0 if link.jindex is None and link.isjoint else link.jindex
|
|
1221
|
+
|
|
1222
|
+
if link.isjoint:
|
|
1223
|
+
U = U @ link.A(q[jindex]) # type: ignore
|
|
1224
|
+
|
|
1225
|
+
if link == end:
|
|
1226
|
+
U = U @ tools
|
|
1227
|
+
|
|
1228
|
+
Tu = SE3(U, check=False).inv().A @ T
|
|
1229
|
+
n = U[:3, 0]
|
|
1230
|
+
o = U[:3, 1]
|
|
1231
|
+
a = U[:3, 2]
|
|
1232
|
+
x = Tu[0, 3]
|
|
1233
|
+
y = Tu[1, 3]
|
|
1234
|
+
z = Tu[2, 3]
|
|
1235
|
+
|
|
1236
|
+
if link.axis == "Rz":
|
|
1237
|
+
J[:3, j] = (o * x) - (n * y)
|
|
1238
|
+
J[3:, j] = a
|
|
1239
|
+
|
|
1240
|
+
elif link.axis == "Ry":
|
|
1241
|
+
J[:3, j] = (n * z) - (a * x)
|
|
1242
|
+
J[3:, j] = o
|
|
1243
|
+
|
|
1244
|
+
elif link.axis == "Rx":
|
|
1245
|
+
J[:3, j] = (a * y) - (o * z)
|
|
1246
|
+
J[3:, j] = n
|
|
1247
|
+
|
|
1248
|
+
elif link.axis == "tx":
|
|
1249
|
+
J[:3, j] = n
|
|
1250
|
+
J[3:, j] = zero
|
|
1251
|
+
|
|
1252
|
+
elif link.axis == "ty":
|
|
1253
|
+
J[:3, j] = o
|
|
1254
|
+
J[3:, j] = zero
|
|
1255
|
+
|
|
1256
|
+
elif link.axis == "tz":
|
|
1257
|
+
J[:3, j] = a
|
|
1258
|
+
J[3:, j] = zero
|
|
1259
|
+
|
|
1260
|
+
j += 1
|
|
1261
|
+
else:
|
|
1262
|
+
A = link.A()
|
|
1263
|
+
if A is not None:
|
|
1264
|
+
U = U @ A
|
|
1265
|
+
|
|
1266
|
+
return J
|
|
1267
|
+
|
|
1268
|
+
def jacobe(
|
|
1269
|
+
self,
|
|
1270
|
+
q: ArrayLike,
|
|
1271
|
+
tool: Union[NDArray, SE3, None] = None,
|
|
1272
|
+
) -> NDArray:
|
|
1273
|
+
r"""
|
|
1274
|
+
Manipulator geometric Jacobian in the end-effector frame
|
|
1275
|
+
|
|
1276
|
+
``robot.jacobe(q)`` is the manipulator Jacobian matrix which maps
|
|
1277
|
+
joint velocity to end-effector spatial velocity expressed in the
|
|
1278
|
+
``end`` frame.
|
|
1279
|
+
|
|
1280
|
+
End-effector spatial velocity :math:`\nu = (v_x, v_y, v_z, \omega_x, \omega_y, \omega_z)^T`
|
|
1281
|
+
is related to joint velocity by :math:`{}^{E}\!\nu = \mathbf{J}_m(q) \dot{q}`.
|
|
1282
|
+
|
|
1283
|
+
Parameters
|
|
1284
|
+
----------
|
|
1285
|
+
q
|
|
1286
|
+
Joint coordinate vector
|
|
1287
|
+
end
|
|
1288
|
+
the particular link or gripper whose velocity the Jacobian
|
|
1289
|
+
describes, defaults to the end-effector if only one is present
|
|
1290
|
+
start
|
|
1291
|
+
the link considered as the base frame, defaults to the robots's base frame
|
|
1292
|
+
tool
|
|
1293
|
+
a static tool transformation matrix to apply to the
|
|
1294
|
+
end of end, defaults to None
|
|
1295
|
+
|
|
1296
|
+
Returns
|
|
1297
|
+
-------
|
|
1298
|
+
Je
|
|
1299
|
+
Manipulator Jacobian in the ``end`` frame
|
|
1300
|
+
|
|
1301
|
+
Examples
|
|
1302
|
+
--------
|
|
1303
|
+
The following example makes a ``Puma560`` robot object, and solves for the
|
|
1304
|
+
end-effector frame Jacobian at the zero joint angle configuration
|
|
1305
|
+
|
|
1306
|
+
.. runblock:: pycon
|
|
1307
|
+
>>> import roboticstoolbox as rtb
|
|
1308
|
+
>>> puma = rtb.models.Puma560().ets()
|
|
1309
|
+
>>> puma.jacobe([0, 0, 0, 0, 0, 0])
|
|
1310
|
+
|
|
1311
|
+
Notes
|
|
1312
|
+
-----
|
|
1313
|
+
- This is the geometric Jacobian as described in texts by
|
|
1314
|
+
Corke, Spong etal., Siciliano etal. The end-effector velocity is
|
|
1315
|
+
described in terms of translational and angular velocity, not a
|
|
1316
|
+
velocity twist as per the text by Lynch & Park.
|
|
1317
|
+
|
|
1318
|
+
References
|
|
1319
|
+
----------
|
|
1320
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
1321
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
1322
|
+
|
|
1323
|
+
""" # noqa
|
|
1324
|
+
|
|
1325
|
+
# Use c extension
|
|
1326
|
+
try:
|
|
1327
|
+
return ETS_jacobe(self._fknm, q, tool)
|
|
1328
|
+
except TypeError:
|
|
1329
|
+
pass
|
|
1330
|
+
|
|
1331
|
+
T = self.eval(q, tool=tool, include_base=False)
|
|
1332
|
+
return tr2jac(T.T) @ self.jacob0(q, tool=tool)
|
|
1333
|
+
|
|
1334
|
+
def hessian0(
|
|
1335
|
+
self,
|
|
1336
|
+
q: Union[ArrayLike, None] = None,
|
|
1337
|
+
J0: Union[NDArray, None] = None,
|
|
1338
|
+
tool: Union[NDArray, SE3, None] = None,
|
|
1339
|
+
) -> NDArray:
|
|
1340
|
+
r"""
|
|
1341
|
+
Manipulator Hessian
|
|
1342
|
+
|
|
1343
|
+
The manipulator Hessian tensor maps joint acceleration to end-effector
|
|
1344
|
+
spatial acceleration, expressed in the base frame. This
|
|
1345
|
+
function calulcates this based on the ETS of the robot. One of J0 or q
|
|
1346
|
+
is required. Supply J0 if already calculated to save computation time
|
|
1347
|
+
|
|
1348
|
+
Parameters
|
|
1349
|
+
----------
|
|
1350
|
+
q
|
|
1351
|
+
The joint angles/configuration of the robot (Optional,
|
|
1352
|
+
if not supplied will use the stored q values).
|
|
1353
|
+
J0
|
|
1354
|
+
The manipulator Jacobian in the base frame
|
|
1355
|
+
tool
|
|
1356
|
+
a static tool transformation matrix to apply to the
|
|
1357
|
+
end of end, defaults to None
|
|
1358
|
+
|
|
1359
|
+
Returns
|
|
1360
|
+
-------
|
|
1361
|
+
h0
|
|
1362
|
+
The manipulator Hessian in the base frame
|
|
1363
|
+
|
|
1364
|
+
Synopsis
|
|
1365
|
+
--------
|
|
1366
|
+
This method computes the manipulator Hessian in the base frame. If
|
|
1367
|
+
we take the time derivative of the differential kinematic relationship
|
|
1368
|
+
|
|
1369
|
+
.. math::
|
|
1370
|
+
|
|
1371
|
+
\nu &= \mat{J}(\vec{q}) \dvec{q} \\
|
|
1372
|
+
\alpha &= \dmat{J} \dvec{q} + \mat{J} \ddvec{q}
|
|
1373
|
+
|
|
1374
|
+
where
|
|
1375
|
+
|
|
1376
|
+
.. math::
|
|
1377
|
+
|
|
1378
|
+
\dmat{J} = \mat{H} \dvec{q}
|
|
1379
|
+
|
|
1380
|
+
and :math:`\mat{H} \in \mathbb{R}^{6\times n \times n}` is the
|
|
1381
|
+
Hessian tensor.
|
|
1382
|
+
|
|
1383
|
+
The elements of the Hessian are
|
|
1384
|
+
|
|
1385
|
+
.. math::
|
|
1386
|
+
|
|
1387
|
+
\mat{H}_{i,j,k} = \frac{d^2 u_i}{d q_j d q_k}
|
|
1388
|
+
|
|
1389
|
+
where :math:`u = \{t_x, t_y, t_z, r_x, r_y, r_z\}` are the elements
|
|
1390
|
+
of the spatial velocity vector.
|
|
1391
|
+
|
|
1392
|
+
Similarly, we can write
|
|
1393
|
+
|
|
1394
|
+
.. math::
|
|
1395
|
+
|
|
1396
|
+
\mat{J}_{i,j} = \frac{d u_i}{d q_j}
|
|
1397
|
+
|
|
1398
|
+
Examples
|
|
1399
|
+
--------
|
|
1400
|
+
The following example makes a ``Panda`` robot object, and solves for the
|
|
1401
|
+
base frame Hessian at the given joint angle configuration
|
|
1402
|
+
|
|
1403
|
+
.. runblock:: pycon
|
|
1404
|
+
>>> import roboticstoolbox as rtb
|
|
1405
|
+
>>> panda = rtb.models.Panda().ets()
|
|
1406
|
+
>>> panda.hessian0([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
1407
|
+
|
|
1408
|
+
References
|
|
1409
|
+
----------
|
|
1410
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
1411
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
1412
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
1413
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
1414
|
+
|
|
1415
|
+
""" # noqa
|
|
1416
|
+
|
|
1417
|
+
# Use c extension
|
|
1418
|
+
try:
|
|
1419
|
+
return ETS_hessian0(self._fknm, q, J0, tool)
|
|
1420
|
+
except TypeError:
|
|
1421
|
+
pass
|
|
1422
|
+
|
|
1423
|
+
def cross(a, b):
|
|
1424
|
+
x = a[1] * b[2] - a[2] * b[1]
|
|
1425
|
+
y = a[2] * b[0] - a[0] * b[2]
|
|
1426
|
+
z = a[0] * b[1] - a[1] * b[0]
|
|
1427
|
+
return np.array([x, y, z])
|
|
1428
|
+
|
|
1429
|
+
n = self.n
|
|
1430
|
+
|
|
1431
|
+
if J0 is None:
|
|
1432
|
+
if q is None:
|
|
1433
|
+
raise ValueError("Either J0 or q must be provided")
|
|
1434
|
+
|
|
1435
|
+
q = getvector(q, None)
|
|
1436
|
+
J0 = self.jacob0(q, tool=tool)
|
|
1437
|
+
else:
|
|
1438
|
+
verifymatrix(J0, (6, self.n))
|
|
1439
|
+
|
|
1440
|
+
H = np.zeros((n, 6, n))
|
|
1441
|
+
|
|
1442
|
+
for j in range(n):
|
|
1443
|
+
for i in range(j, n):
|
|
1444
|
+
H[j, :3, i] = cross(J0[3:, j], J0[:3, i])
|
|
1445
|
+
H[j, 3:, i] = cross(J0[3:, j], J0[3:, i])
|
|
1446
|
+
|
|
1447
|
+
if i != j:
|
|
1448
|
+
H[i, :3, j] = H[j, :3, i]
|
|
1449
|
+
|
|
1450
|
+
return H
|
|
1451
|
+
|
|
1452
|
+
def hessiane(
|
|
1453
|
+
self,
|
|
1454
|
+
q: Union[ArrayLike, None] = None,
|
|
1455
|
+
Je: Union[NDArray, None] = None,
|
|
1456
|
+
tool: Union[NDArray, SE3, None] = None,
|
|
1457
|
+
) -> NDArray:
|
|
1458
|
+
r"""
|
|
1459
|
+
Manipulator Hessian
|
|
1460
|
+
|
|
1461
|
+
The manipulator Hessian tensor maps joint acceleration to end-effector
|
|
1462
|
+
spatial acceleration, expressed in the end-effector coordinate frame. This
|
|
1463
|
+
function calulcates this based on the ETS of the robot. One of J0 or q
|
|
1464
|
+
is required. Supply J0 if already calculated to save computation time
|
|
1465
|
+
|
|
1466
|
+
Parameters
|
|
1467
|
+
----------
|
|
1468
|
+
q
|
|
1469
|
+
The joint angles/configuration of the robot (Optional,
|
|
1470
|
+
if not supplied will use the stored q values).
|
|
1471
|
+
J0
|
|
1472
|
+
The manipulator Jacobian in the end-effector frame
|
|
1473
|
+
tool
|
|
1474
|
+
a static tool transformation matrix to apply to the
|
|
1475
|
+
end of end, defaults to None
|
|
1476
|
+
|
|
1477
|
+
Returns
|
|
1478
|
+
-------
|
|
1479
|
+
he
|
|
1480
|
+
The manipulator Hessian in end-effector frame
|
|
1481
|
+
|
|
1482
|
+
Synopsis
|
|
1483
|
+
--------
|
|
1484
|
+
This method computes the manipulator Hessian in the end-effector frame. If
|
|
1485
|
+
we take the time derivative of the differential kinematic relationship
|
|
1486
|
+
|
|
1487
|
+
.. math::
|
|
1488
|
+
|
|
1489
|
+
\nu &= \mat{J}(\vec{q}) \dvec{q} \\
|
|
1490
|
+
\alpha &= \dmat{J} \dvec{q} + \mat{J} \ddvec{q}
|
|
1491
|
+
|
|
1492
|
+
where
|
|
1493
|
+
|
|
1494
|
+
.. math::
|
|
1495
|
+
|
|
1496
|
+
\dmat{J} = \mat{H} \dvec{q}
|
|
1497
|
+
|
|
1498
|
+
and :math:`\mat{H} \in \mathbb{R}^{6\times n \times n}` is the
|
|
1499
|
+
Hessian tensor.
|
|
1500
|
+
|
|
1501
|
+
The elements of the Hessian are
|
|
1502
|
+
|
|
1503
|
+
.. math::
|
|
1504
|
+
|
|
1505
|
+
\mat{H}_{i,j,k} = \frac{d^2 u_i}{d q_j d q_k}
|
|
1506
|
+
|
|
1507
|
+
where :math:`u = \{t_x, t_y, t_z, r_x, r_y, r_z\}` are the elements
|
|
1508
|
+
of the spatial velocity vector.
|
|
1509
|
+
|
|
1510
|
+
Similarly, we can write
|
|
1511
|
+
|
|
1512
|
+
.. math::
|
|
1513
|
+
|
|
1514
|
+
\mat{J}_{i,j} = \frac{d u_i}{d q_j}
|
|
1515
|
+
|
|
1516
|
+
Examples
|
|
1517
|
+
--------
|
|
1518
|
+
The following example makes a ``Panda`` robot object, and solves for the
|
|
1519
|
+
end-effector frame Hessian at the given joint angle configuration
|
|
1520
|
+
|
|
1521
|
+
.. runblock:: pycon
|
|
1522
|
+
>>> import roboticstoolbox as rtb
|
|
1523
|
+
>>> panda = rtb.models.Panda().ets()
|
|
1524
|
+
>>> panda.hessiane([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
1525
|
+
|
|
1526
|
+
References
|
|
1527
|
+
----------
|
|
1528
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
1529
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
1530
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
1531
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
1532
|
+
|
|
1533
|
+
""" # noqa
|
|
1534
|
+
|
|
1535
|
+
# Use c extension
|
|
1536
|
+
try:
|
|
1537
|
+
return ETS_hessiane(self._fknm, q, Je, tool)
|
|
1538
|
+
except TypeError:
|
|
1539
|
+
pass
|
|
1540
|
+
|
|
1541
|
+
def cross(a, b):
|
|
1542
|
+
x = a[1] * b[2] - a[2] * b[1]
|
|
1543
|
+
y = a[2] * b[0] - a[0] * b[2]
|
|
1544
|
+
z = a[0] * b[1] - a[1] * b[0]
|
|
1545
|
+
return np.array([x, y, z])
|
|
1546
|
+
|
|
1547
|
+
n = self.n
|
|
1548
|
+
|
|
1549
|
+
if Je is None:
|
|
1550
|
+
if q is None:
|
|
1551
|
+
raise ValueError("Either Je or q must be provided")
|
|
1552
|
+
|
|
1553
|
+
q = getvector(q, None)
|
|
1554
|
+
Je = self.jacobe(q, tool=tool)
|
|
1555
|
+
else:
|
|
1556
|
+
verifymatrix(Je, (6, self.n))
|
|
1557
|
+
|
|
1558
|
+
H = np.zeros((n, 6, n))
|
|
1559
|
+
|
|
1560
|
+
for j in range(n):
|
|
1561
|
+
for i in range(j, n):
|
|
1562
|
+
H[j, :3, i] = cross(Je[3:, j], Je[:3, i])
|
|
1563
|
+
H[j, 3:, i] = cross(Je[3:, j], Je[3:, i])
|
|
1564
|
+
|
|
1565
|
+
if i != j:
|
|
1566
|
+
H[i, :3, j] = H[j, :3, i]
|
|
1567
|
+
|
|
1568
|
+
return H
|
|
1569
|
+
|
|
1570
|
+
def jacob0_analytical(
|
|
1571
|
+
self,
|
|
1572
|
+
q: ArrayLike,
|
|
1573
|
+
representation: str = "rpy/xyz",
|
|
1574
|
+
tool: Union[NDArray, SE3, None] = None,
|
|
1575
|
+
):
|
|
1576
|
+
r"""
|
|
1577
|
+
Manipulator analytical Jacobian in the base frame
|
|
1578
|
+
|
|
1579
|
+
``robot.jacob0_analytical(q)`` is the manipulator Jacobian matrix which maps
|
|
1580
|
+
joint velocity to end-effector spatial velocity expressed in the
|
|
1581
|
+
base frame.
|
|
1582
|
+
|
|
1583
|
+
Parameters
|
|
1584
|
+
----------
|
|
1585
|
+
q
|
|
1586
|
+
Joint coordinate vector
|
|
1587
|
+
representation
|
|
1588
|
+
angular representation
|
|
1589
|
+
tool
|
|
1590
|
+
a static tool transformation matrix to apply to the
|
|
1591
|
+
end of end, defaults to None
|
|
1592
|
+
|
|
1593
|
+
Returns
|
|
1594
|
+
-------
|
|
1595
|
+
jacob0
|
|
1596
|
+
Manipulator Jacobian in the base frame
|
|
1597
|
+
|
|
1598
|
+
Synopsis
|
|
1599
|
+
--------
|
|
1600
|
+
End-effector spatial velocity :math:`\nu = (v_x, v_y, v_z, \omega_x, \omega_y, \omega_z)^T`
|
|
1601
|
+
is related to joint velocity by :math:`{}^{E}\!\nu = \mathbf{J}_m(q) \dot{q}`.
|
|
1602
|
+
|
|
1603
|
+
|``representation`` | Rotational representation |
|
|
1604
|
+
|---------------------|-------------------------------------|
|
|
1605
|
+
|``'rpy/xyz'`` | RPY angular rates in XYZ order |
|
|
1606
|
+
|``'rpy/zyx'`` | RPY angular rates in XYZ order |
|
|
1607
|
+
|``'eul'`` | Euler angular rates in ZYZ order |
|
|
1608
|
+
|``'exp'`` | exponential coordinate rates |
|
|
1609
|
+
|
|
1610
|
+
Examples
|
|
1611
|
+
--------
|
|
1612
|
+
Makes a robot object and computes the analytic Jacobian for the given
|
|
1613
|
+
joint configuration
|
|
1614
|
+
|
|
1615
|
+
.. runblock:: pycon
|
|
1616
|
+
>>> import roboticstoolbox as rtb
|
|
1617
|
+
>>> puma = rtb.models.ETS.Puma560().ets()
|
|
1618
|
+
>>> puma.jacob0_analytical([0, 0, 0, 0, 0, 0])
|
|
1619
|
+
|
|
1620
|
+
""" # noqa
|
|
1621
|
+
|
|
1622
|
+
T = self.eval(q, tool=tool)
|
|
1623
|
+
J = self.jacob0(q, tool=tool)
|
|
1624
|
+
gamma = t2r(T)[:3, :3]
|
|
1625
|
+
A = rotvelxform(gamma, full=True, inverse=True, representation=representation)
|
|
1626
|
+
return A @ J
|
|
1627
|
+
|
|
1628
|
+
def jacobm(self, q: ArrayLike) -> NDArray:
|
|
1629
|
+
r"""
|
|
1630
|
+
The manipulability Jacobian
|
|
1631
|
+
|
|
1632
|
+
This measure relates the rate of change of the manipulability to the
|
|
1633
|
+
joint velocities of the robot. One of J or q is required. Supply J
|
|
1634
|
+
and H if already calculated to save computation time
|
|
1635
|
+
|
|
1636
|
+
Parameters
|
|
1637
|
+
----------
|
|
1638
|
+
q
|
|
1639
|
+
The joint angles/configuration of the robot (Optional,
|
|
1640
|
+
if not supplied will use the stored q values).
|
|
1641
|
+
|
|
1642
|
+
Returns
|
|
1643
|
+
-------
|
|
1644
|
+
jacobm
|
|
1645
|
+
The manipulability Jacobian
|
|
1646
|
+
|
|
1647
|
+
Synopsis
|
|
1648
|
+
--------
|
|
1649
|
+
Yoshikawa's manipulability measure
|
|
1650
|
+
|
|
1651
|
+
.. math::
|
|
1652
|
+
|
|
1653
|
+
m(\vec{q}) = \sqrt{\mat{J}(\vec{q}) \mat{J}(\vec{q})^T}
|
|
1654
|
+
|
|
1655
|
+
This method returns its Jacobian with respect to configuration
|
|
1656
|
+
|
|
1657
|
+
.. math::
|
|
1658
|
+
|
|
1659
|
+
\frac{\partial m(\vec{q})}{\partial \vec{q}}
|
|
1660
|
+
|
|
1661
|
+
References
|
|
1662
|
+
----------
|
|
1663
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
1664
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
1665
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
1666
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
1667
|
+
|
|
1668
|
+
""" # noqa
|
|
1669
|
+
|
|
1670
|
+
J = self.jacob0(q)
|
|
1671
|
+
H = self.hessian0(q)
|
|
1672
|
+
|
|
1673
|
+
manipulability = self.manipulability(q)
|
|
1674
|
+
|
|
1675
|
+
# J = J[axes, :]
|
|
1676
|
+
# H = H[:, axes, :]
|
|
1677
|
+
|
|
1678
|
+
b = inv(J @ J.T)
|
|
1679
|
+
Jm = np.zeros((self.n, 1))
|
|
1680
|
+
|
|
1681
|
+
for i in range(self.n):
|
|
1682
|
+
c = J @ H[i, :, :].T
|
|
1683
|
+
Jm[i, 0] = manipulability * (c.flatten("F")).T @ b.flatten("F")
|
|
1684
|
+
|
|
1685
|
+
return Jm
|
|
1686
|
+
|
|
1687
|
+
def manipulability(
|
|
1688
|
+
self,
|
|
1689
|
+
q,
|
|
1690
|
+
method: L["yoshikawa", "minsingular", "invcondition"] = "yoshikawa", # noqa
|
|
1691
|
+
axes: Union[L["all", "trans", "rot"], List[bool]] = "all", # noqa
|
|
1692
|
+
):
|
|
1693
|
+
"""
|
|
1694
|
+
Manipulability measure
|
|
1695
|
+
|
|
1696
|
+
``manipulability(q)`` is the scalar manipulability index
|
|
1697
|
+
for the ets at the joint configuration ``q``. It indicates
|
|
1698
|
+
dexterity, that is, how well conditioned the ets is for motion
|
|
1699
|
+
with respect to the 6 degrees of Cartesian motion. The values is
|
|
1700
|
+
zero if the ets is at a singularity.
|
|
1701
|
+
|
|
1702
|
+
Parameters
|
|
1703
|
+
----------
|
|
1704
|
+
q
|
|
1705
|
+
Joint coordinates, one of J or q required
|
|
1706
|
+
method
|
|
1707
|
+
method to use, "yoshikawa" (default), "invcondition",
|
|
1708
|
+
"minsingular"
|
|
1709
|
+
axes
|
|
1710
|
+
Task space axes to consider: "all" [default],
|
|
1711
|
+
"trans", or "rot"
|
|
1712
|
+
|
|
1713
|
+
Returns
|
|
1714
|
+
-------
|
|
1715
|
+
manipulability
|
|
1716
|
+
the manipulability metric
|
|
1717
|
+
|
|
1718
|
+
Synopsis
|
|
1719
|
+
--------
|
|
1720
|
+
|
|
1721
|
+
Various measures are supported:
|
|
1722
|
+
|
|
1723
|
+
| Measure | Description |
|
|
1724
|
+
|-------------------|-------------------------------------------------|
|
|
1725
|
+
| ``"yoshikawa"`` | Volume of the velocity ellipsoid, *distance* |
|
|
1726
|
+
| | from singularity [Yoshikawa85]_ |
|
|
1727
|
+
| ``"invcondition"``| Inverse condition number of Jacobian, isotropy |
|
|
1728
|
+
| | of the velocity ellipsoid [Klein87]_ |
|
|
1729
|
+
| ``"minsingular"`` | Minimum singular value of the Jacobian, |
|
|
1730
|
+
| | *distance* from singularity [Klein87]_ |
|
|
1731
|
+
|
|
1732
|
+
**Trajectory operation**:
|
|
1733
|
+
|
|
1734
|
+
If ``q`` is a matrix (m,n) then the result (m,) is a vector of
|
|
1735
|
+
manipulability indices for each joint configuration specified by a row
|
|
1736
|
+
of ``q``.
|
|
1737
|
+
|
|
1738
|
+
Notes
|
|
1739
|
+
-----
|
|
1740
|
+
- Invokes the ``jacob0`` method of the robot if ``J`` is not passed
|
|
1741
|
+
- The "all" option includes rotational and translational
|
|
1742
|
+
dexterity, but this involves adding different units. It can be
|
|
1743
|
+
more useful to look at the translational and rotational
|
|
1744
|
+
manipulability separately.
|
|
1745
|
+
- Examples in the RVC book (1st edition) can be replicated by
|
|
1746
|
+
using the "all" option
|
|
1747
|
+
- Asada's measure requires inertial a robot model with inertial
|
|
1748
|
+
parameters.
|
|
1749
|
+
|
|
1750
|
+
References
|
|
1751
|
+
----------
|
|
1752
|
+
.. [Yoshikawa85] Manipulability of Robotic Mechanisms. Yoshikawa T.,
|
|
1753
|
+
The International Journal of Robotics Research.
|
|
1754
|
+
1985;4(2):3-9. doi:10.1177/027836498500400201
|
|
1755
|
+
.. [Klein87] Dexterity Measures for the Design and Control of
|
|
1756
|
+
Kinematically Redundant Manipulators. Klein CA, Blaho BE.
|
|
1757
|
+
The International Journal of Robotics Research.
|
|
1758
|
+
1987;6(2):72-83. doi:10.1177/027836498700600206
|
|
1759
|
+
- Robotics, Vision & Control in Python, 3e, P. Corke, Springer 2023, Chap 7.
|
|
1760
|
+
|
|
1761
|
+
|
|
1762
|
+
.. versionchanged:: 1.0.4
|
|
1763
|
+
Removed 'both' option for axes, added a custom list option.
|
|
1764
|
+
|
|
1765
|
+
"""
|
|
1766
|
+
|
|
1767
|
+
axes_list: List[bool] = []
|
|
1768
|
+
|
|
1769
|
+
if isinstance(axes, list):
|
|
1770
|
+
axes_list = axes
|
|
1771
|
+
elif axes == "all":
|
|
1772
|
+
axes_list = [True, True, True, True, True, True]
|
|
1773
|
+
elif axes.startswith("trans"):
|
|
1774
|
+
axes_list = [True, True, True, False, False, False]
|
|
1775
|
+
elif axes.startswith("rot"):
|
|
1776
|
+
axes_list = [False, False, False, True, True, True]
|
|
1777
|
+
else:
|
|
1778
|
+
raise ValueError("axes must be all, trans, rot or both")
|
|
1779
|
+
|
|
1780
|
+
def yoshikawa(robot, J, q, axes, **kwargs):
|
|
1781
|
+
J = J[axes, :]
|
|
1782
|
+
if J.shape[0] == J.shape[1]:
|
|
1783
|
+
# simplified case for square matrix
|
|
1784
|
+
return abs(det(J))
|
|
1785
|
+
else:
|
|
1786
|
+
m2 = det(J @ J.T)
|
|
1787
|
+
return np.sqrt(abs(m2))
|
|
1788
|
+
|
|
1789
|
+
def condition(robot, J, q, axes, **kwargs):
|
|
1790
|
+
J = J[axes, :]
|
|
1791
|
+
return 1 / cond(J)
|
|
1792
|
+
|
|
1793
|
+
def minsingular(robot, J, q, axes, **kwargs):
|
|
1794
|
+
J = J[axes, :]
|
|
1795
|
+
s = svd(J, compute_uv=False)
|
|
1796
|
+
return s[-1] # return last/smallest singular value of J
|
|
1797
|
+
|
|
1798
|
+
# choose the handler function
|
|
1799
|
+
if method == "yoshikawa":
|
|
1800
|
+
mfunc = yoshikawa
|
|
1801
|
+
elif method == "invcondition":
|
|
1802
|
+
mfunc = condition
|
|
1803
|
+
elif method == "minsingular":
|
|
1804
|
+
mfunc = minsingular
|
|
1805
|
+
else:
|
|
1806
|
+
raise ValueError("Invalid method chosen")
|
|
1807
|
+
|
|
1808
|
+
# Otherwise use the q vector/matrix
|
|
1809
|
+
q = np.array(getmatrix(q, (None, self.n)))
|
|
1810
|
+
w = np.zeros(q.shape[0])
|
|
1811
|
+
|
|
1812
|
+
for k, qk in enumerate(q):
|
|
1813
|
+
Jk = self.jacob0(qk)
|
|
1814
|
+
w[k] = mfunc(self, Jk, qk, axes_list)
|
|
1815
|
+
|
|
1816
|
+
if len(w) == 1:
|
|
1817
|
+
return w[0]
|
|
1818
|
+
else:
|
|
1819
|
+
return w
|
|
1820
|
+
|
|
1821
|
+
def partial_fkine0(self, q: ArrayLike, n: int) -> NDArray:
|
|
1822
|
+
r"""
|
|
1823
|
+
Manipulator Forward Kinematics nth Partial Derivative
|
|
1824
|
+
|
|
1825
|
+
This method computes the nth derivative of the forward kinematics where ``n`` is
|
|
1826
|
+
greater than or equal to 3. This is an extension of the differential kinematics
|
|
1827
|
+
where the Jacobian is the first partial derivative and the Hessian is the
|
|
1828
|
+
second.
|
|
1829
|
+
|
|
1830
|
+
Parameters
|
|
1831
|
+
----------
|
|
1832
|
+
q
|
|
1833
|
+
The joint angles/configuration of the robot (Optional,
|
|
1834
|
+
if not supplied will use the stored q values).
|
|
1835
|
+
end
|
|
1836
|
+
the final link/Gripper which the Hessian represents
|
|
1837
|
+
start
|
|
1838
|
+
the first link which the Hessian represents
|
|
1839
|
+
tool
|
|
1840
|
+
a static tool transformation matrix to apply to the
|
|
1841
|
+
end of end, defaults to None
|
|
1842
|
+
|
|
1843
|
+
Returns
|
|
1844
|
+
-------
|
|
1845
|
+
A
|
|
1846
|
+
The nth Partial Derivative of the forward kinematics
|
|
1847
|
+
|
|
1848
|
+
Examples
|
|
1849
|
+
--------
|
|
1850
|
+
The following example makes a ``Panda`` robot object, and solves for the
|
|
1851
|
+
base-effector frame 4th defivative of the forward kinematics at the given
|
|
1852
|
+
joint angle configuration
|
|
1853
|
+
|
|
1854
|
+
.. runblock:: pycon
|
|
1855
|
+
>>> import roboticstoolbox as rtb
|
|
1856
|
+
>>> panda = rtb.models.Panda().ets()
|
|
1857
|
+
>>> panda.partial_fkine0([0, -0.3, 0, -2.2, 0, 2, 0.7854], n=4)
|
|
1858
|
+
|
|
1859
|
+
References
|
|
1860
|
+
----------
|
|
1861
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
1862
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
1863
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
1864
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
1865
|
+
|
|
1866
|
+
""" # noqa
|
|
1867
|
+
|
|
1868
|
+
# Calculate the Jacobian and Hessian
|
|
1869
|
+
J = self.jacob0(q)
|
|
1870
|
+
H = self.hessian0(q)
|
|
1871
|
+
|
|
1872
|
+
# A list of derivatives, starting with the jacobian and hessian
|
|
1873
|
+
dT = [J, H]
|
|
1874
|
+
|
|
1875
|
+
# The tensor dimensions of the latest derivative
|
|
1876
|
+
# Set to the current size of the Hessian
|
|
1877
|
+
size = [self.n, 6, self.n]
|
|
1878
|
+
|
|
1879
|
+
# An array which keeps track of the index of the partial derivative
|
|
1880
|
+
# we are calculating
|
|
1881
|
+
# It stores the indices in the order: "j, k, l. m, n, o, ..."
|
|
1882
|
+
# where count is extended to match oder of the partial derivative
|
|
1883
|
+
count = np.array([0, 0])
|
|
1884
|
+
|
|
1885
|
+
# The order of derivative for which we are calculating
|
|
1886
|
+
# The Hessian is the 2nd-order so we start with c = 2
|
|
1887
|
+
c = 2
|
|
1888
|
+
|
|
1889
|
+
def add_indices(indices, c):
|
|
1890
|
+
total = len(indices * 2)
|
|
1891
|
+
new_indices = []
|
|
1892
|
+
|
|
1893
|
+
for i in range(total):
|
|
1894
|
+
j = i // 2
|
|
1895
|
+
new_indices.append([])
|
|
1896
|
+
new_indices[i].append(indices[j][0].copy())
|
|
1897
|
+
new_indices[i].append(indices[j][1].copy())
|
|
1898
|
+
|
|
1899
|
+
if i % 2 == 0:
|
|
1900
|
+
# if even number
|
|
1901
|
+
new_indices[i][0].append(c)
|
|
1902
|
+
else:
|
|
1903
|
+
# if odd number
|
|
1904
|
+
new_indices[i][1].append(c)
|
|
1905
|
+
|
|
1906
|
+
return new_indices
|
|
1907
|
+
|
|
1908
|
+
def add_pdi(pdi):
|
|
1909
|
+
total = len(pdi * 2)
|
|
1910
|
+
new_pdi = []
|
|
1911
|
+
|
|
1912
|
+
for i in range(total):
|
|
1913
|
+
j = i // 2
|
|
1914
|
+
new_pdi.append([])
|
|
1915
|
+
new_pdi[i].append(pdi[j][0])
|
|
1916
|
+
new_pdi[i].append(pdi[j][1])
|
|
1917
|
+
|
|
1918
|
+
# if even number
|
|
1919
|
+
if i % 2 == 0:
|
|
1920
|
+
new_pdi[i][0] += 1
|
|
1921
|
+
# if odd number
|
|
1922
|
+
else:
|
|
1923
|
+
new_pdi[i][1] += 1
|
|
1924
|
+
|
|
1925
|
+
return new_pdi
|
|
1926
|
+
|
|
1927
|
+
# these are the indices used for the hessian
|
|
1928
|
+
indices = [[[1], [0]]]
|
|
1929
|
+
|
|
1930
|
+
# The partial derivative indices (pdi)
|
|
1931
|
+
# the are the pd indices used in the cross products
|
|
1932
|
+
pdi = [[0, 0]]
|
|
1933
|
+
|
|
1934
|
+
# The length of dT correspods to the number of derivatives we have calculated
|
|
1935
|
+
while len(dT) != n:
|
|
1936
|
+
# Add to the start of the tensor size list
|
|
1937
|
+
size.insert(0, self.n)
|
|
1938
|
+
|
|
1939
|
+
# Add an axis to the count array
|
|
1940
|
+
count = np.concatenate(([0], count))
|
|
1941
|
+
|
|
1942
|
+
# This variables corresponds to indices within the previous
|
|
1943
|
+
# partial derivatives
|
|
1944
|
+
# to be cross prodded
|
|
1945
|
+
# The order is: "[j, k, l, m, n, o, ...]"
|
|
1946
|
+
# Although, our partial derivatives have the order:
|
|
1947
|
+
# pd[..., o, n, m, l, k, cartesian DoF, j]
|
|
1948
|
+
# For example, consider the Hessian Tensor H[n, 6, n],
|
|
1949
|
+
# the index H[k, :, j]. This corrsponds
|
|
1950
|
+
# to the second partial derivative of the kinematics of joint j with
|
|
1951
|
+
# respect to joint k.
|
|
1952
|
+
indices = add_indices(indices, c)
|
|
1953
|
+
|
|
1954
|
+
# This variable corresponds to the indices in Td which corresponds to the
|
|
1955
|
+
# partial derivatives we need to use
|
|
1956
|
+
pdi = add_pdi(pdi)
|
|
1957
|
+
|
|
1958
|
+
c += 1
|
|
1959
|
+
|
|
1960
|
+
# Allocate our new partial derivative tensor
|
|
1961
|
+
pd = np.zeros(size)
|
|
1962
|
+
|
|
1963
|
+
# We need to loop n^c times
|
|
1964
|
+
# There are n^c columns to calculate
|
|
1965
|
+
for _ in range(self.n**c):
|
|
1966
|
+
# Allocate the rotation and translation components
|
|
1967
|
+
rot = np.zeros(3)
|
|
1968
|
+
trn = np.zeros(3)
|
|
1969
|
+
|
|
1970
|
+
# This loop calculates a single column ([trn, rot])
|
|
1971
|
+
# of the tensor for dT(x)
|
|
1972
|
+
for j in range(len(indices)):
|
|
1973
|
+
pdr0 = dT[pdi[j][0]]
|
|
1974
|
+
pdr1 = dT[pdi[j][1]]
|
|
1975
|
+
|
|
1976
|
+
idx0 = count[indices[j][0]]
|
|
1977
|
+
idx1 = count[indices[j][1]]
|
|
1978
|
+
|
|
1979
|
+
# This is a list of indices selecting the slices of the
|
|
1980
|
+
# previous tensor
|
|
1981
|
+
idx0_slices = np.flip(idx0[1:])
|
|
1982
|
+
idx1_slices = np.flip(idx1[1:])
|
|
1983
|
+
|
|
1984
|
+
# This index selecting the column within the 2d slice of the
|
|
1985
|
+
# previous tensor
|
|
1986
|
+
idx0_n = idx0[0]
|
|
1987
|
+
idx1_n = idx1[0]
|
|
1988
|
+
|
|
1989
|
+
# Use our indices to select the rotational column from pdr0 and pdr1
|
|
1990
|
+
col0_rot = pdr0[(*idx0_slices, slice(3, 6), idx0_n)]
|
|
1991
|
+
col1_rot = pdr1[(*idx1_slices, slice(3, 6), idx1_n)]
|
|
1992
|
+
|
|
1993
|
+
# Use our indices to select the translational column from pdr1
|
|
1994
|
+
col1_trn = pdr1[(*idx1_slices, slice(0, 3), idx1_n)]
|
|
1995
|
+
|
|
1996
|
+
# Perform the cross product as described in the maths above
|
|
1997
|
+
rot += np.cross(col0_rot, col1_rot)
|
|
1998
|
+
trn += np.cross(col0_rot, col1_trn)
|
|
1999
|
+
|
|
2000
|
+
pd[(*np.flip(count[1:]), slice(0, 3), count[0])] = trn
|
|
2001
|
+
pd[(*np.flip(count[1:]), slice(3, 6), count[0])] = rot
|
|
2002
|
+
|
|
2003
|
+
count[0] += 1
|
|
2004
|
+
for j in range(len(count)):
|
|
2005
|
+
if count[j] == self.n:
|
|
2006
|
+
count[j] = 0
|
|
2007
|
+
if j != len(count) - 1:
|
|
2008
|
+
count[j + 1] += 1
|
|
2009
|
+
|
|
2010
|
+
dT.append(pd)
|
|
2011
|
+
|
|
2012
|
+
return dT[-1]
|
|
2013
|
+
|
|
2014
|
+
def ik_LM(
|
|
2015
|
+
self,
|
|
2016
|
+
Tep: Union[NDArray, SE3],
|
|
2017
|
+
q0: Union[NDArray, None] = None,
|
|
2018
|
+
ilimit: int = 30,
|
|
2019
|
+
slimit: int = 100,
|
|
2020
|
+
tol: float = 1e-6,
|
|
2021
|
+
mask: Union[NDArray, None] = None,
|
|
2022
|
+
joint_limits: bool = True,
|
|
2023
|
+
k: float = 1.0,
|
|
2024
|
+
method: L["chan", "wampler", "sugihara"] = "chan", # noqa
|
|
2025
|
+
) -> Tuple[NDArray, int, int, int, float]:
|
|
2026
|
+
r"""
|
|
2027
|
+
Fast levenberg-Marquadt Numerical Inverse Kinematics Solver
|
|
2028
|
+
|
|
2029
|
+
A method which provides functionality to perform numerical inverse kinematics (IK)
|
|
2030
|
+
using the Levemberg-Marquadt method. This
|
|
2031
|
+
is a fast solver implemented in C++.
|
|
2032
|
+
|
|
2033
|
+
See the :ref:`Inverse Kinematics Docs Page <IK>` for more details and for a
|
|
2034
|
+
**tutorial** on numerical IK, see `here <https://bit.ly/3ak5GDi>`_.
|
|
2035
|
+
|
|
2036
|
+
Parameters
|
|
2037
|
+
----------
|
|
2038
|
+
Tep
|
|
2039
|
+
The desired end-effector pose
|
|
2040
|
+
q0
|
|
2041
|
+
The initial joint coordinate vector
|
|
2042
|
+
ilimit
|
|
2043
|
+
How many iterations are allowed within a search before a new search
|
|
2044
|
+
is started
|
|
2045
|
+
slimit
|
|
2046
|
+
How many searches are allowed before being deemed unsuccessful
|
|
2047
|
+
tol
|
|
2048
|
+
Maximum allowed residual error E
|
|
2049
|
+
mask
|
|
2050
|
+
A 6 vector which assigns weights to Cartesian degrees-of-freedom
|
|
2051
|
+
error priority
|
|
2052
|
+
joint_limits
|
|
2053
|
+
Reject solutions with joint limit violations
|
|
2054
|
+
seed
|
|
2055
|
+
A seed for the private RNG used to generate random joint coordinate
|
|
2056
|
+
vectors
|
|
2057
|
+
k
|
|
2058
|
+
Sets the gain value for the damping matrix Wn in the next iteration. See
|
|
2059
|
+
synopsis
|
|
2060
|
+
method
|
|
2061
|
+
One of "chan", "sugihara" or "wampler". Defines which method is used
|
|
2062
|
+
to calculate the damping matrix Wn in the ``step`` method
|
|
2063
|
+
|
|
2064
|
+
Synopsis
|
|
2065
|
+
--------
|
|
2066
|
+
The operation is defined by the choice of the ``method`` kwarg.
|
|
2067
|
+
|
|
2068
|
+
The step is deined as
|
|
2069
|
+
|
|
2070
|
+
.. math::
|
|
2071
|
+
|
|
2072
|
+
\vec{q}_{k+1}
|
|
2073
|
+
&=
|
|
2074
|
+
\vec{q}_k +
|
|
2075
|
+
\left(
|
|
2076
|
+
\mat{A}_k
|
|
2077
|
+
\right)^{-1}
|
|
2078
|
+
\bf{g}_k \\
|
|
2079
|
+
%
|
|
2080
|
+
\mat{A}_k
|
|
2081
|
+
&=
|
|
2082
|
+
{\mat{J}(\vec{q}_k)}^\top
|
|
2083
|
+
\mat{W}_e \
|
|
2084
|
+
{\mat{J}(\vec{q}_k)}
|
|
2085
|
+
+
|
|
2086
|
+
\mat{W}_n
|
|
2087
|
+
|
|
2088
|
+
where :math:`\mat{W}_n = \text{diag}(\vec{w_n})(\vec{w_n} \in \mathbb{R}^n_{>0})` is a
|
|
2089
|
+
diagonal damping matrix. The damping matrix ensures that :math:`\mat{A}_k` is
|
|
2090
|
+
non-singular and positive definite. The performance of the LM method largely depends
|
|
2091
|
+
on the choice of :math:`\mat{W}_n`.
|
|
2092
|
+
|
|
2093
|
+
*Chan's Method*
|
|
2094
|
+
|
|
2095
|
+
Chan proposed
|
|
2096
|
+
|
|
2097
|
+
.. math::
|
|
2098
|
+
|
|
2099
|
+
\mat{W}_n
|
|
2100
|
+
=
|
|
2101
|
+
λ E_k \mat{1}_n
|
|
2102
|
+
|
|
2103
|
+
where λ is a constant which reportedly does not have much influence on performance.
|
|
2104
|
+
Use the kwarg `k` to adjust the weighting term λ.
|
|
2105
|
+
|
|
2106
|
+
*Sugihara's Method*
|
|
2107
|
+
|
|
2108
|
+
Sugihara proposed
|
|
2109
|
+
|
|
2110
|
+
.. math::
|
|
2111
|
+
|
|
2112
|
+
\mat{W}_n
|
|
2113
|
+
=
|
|
2114
|
+
E_k \mat{1}_n + \text{diag}(\hat{\vec{w}}_n)
|
|
2115
|
+
|
|
2116
|
+
where :math:`\hat{\vec{w}}_n \in \mathbb{R}^n`, :math:`\hat{w}_{n_i} = l^2 \sim 0.01 l^2`,
|
|
2117
|
+
and :math:`l` is the length of a typical link within the manipulator. We provide the
|
|
2118
|
+
variable `k` as a kwarg to adjust the value of :math:`w_n`.
|
|
2119
|
+
|
|
2120
|
+
*Wampler's Method*
|
|
2121
|
+
|
|
2122
|
+
Wampler proposed :math:`\vec{w_n}` to be a constant. This is set through the `k` kwarg.
|
|
2123
|
+
|
|
2124
|
+
Examples
|
|
2125
|
+
--------
|
|
2126
|
+
The following example gets the ``ets`` of a ``panda`` robot object, makes a goal
|
|
2127
|
+
pose ``Tep``, and then solves for the joint coordinates which result in the pose
|
|
2128
|
+
``Tep`` using the `ikine_LM` method.
|
|
2129
|
+
|
|
2130
|
+
.. runblock:: pycon
|
|
2131
|
+
>>> import roboticstoolbox as rtb
|
|
2132
|
+
>>> panda = rtb.models.Panda().ets()
|
|
2133
|
+
>>> Tep = panda.fkine([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
2134
|
+
>>> panda.ikine_LM(Tep)
|
|
2135
|
+
|
|
2136
|
+
Notes
|
|
2137
|
+
-----
|
|
2138
|
+
The value for the ``k`` kwarg will depend on the ``method`` chosen and the arm you are
|
|
2139
|
+
using. Use the following as a rough guide ``chan, k = 1.0 - 0.01``,
|
|
2140
|
+
``wampler, k = 0.01 - 0.0001``, and ``sugihara, k = 0.1 - 0.0001``
|
|
2141
|
+
|
|
2142
|
+
When using the this method, the initial joint coordinates :math:`q_0`, should correspond
|
|
2143
|
+
to a non-singular manipulator pose, since it uses the manipulator Jacobian.
|
|
2144
|
+
|
|
2145
|
+
This class supports null-space motion to assist with maximising manipulability and
|
|
2146
|
+
avoiding joint limits. These are enabled by setting kq and km to non-zero values.
|
|
2147
|
+
|
|
2148
|
+
References
|
|
2149
|
+
----------
|
|
2150
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
2151
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
2152
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
2153
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
2154
|
+
|
|
2155
|
+
See Also
|
|
2156
|
+
--------
|
|
2157
|
+
ik_NR
|
|
2158
|
+
A fast numerical inverse kinematics solver using Newton-Raphson optimisation
|
|
2159
|
+
ik_GN
|
|
2160
|
+
A fast numerical inverse kinematics solver using Gauss-Newton optimisation
|
|
2161
|
+
|
|
2162
|
+
|
|
2163
|
+
.. versionchanged:: 1.0.4
|
|
2164
|
+
Merged the Levemberg-Marquadt IK solvers into the ik_LM method
|
|
2165
|
+
|
|
2166
|
+
""" # noqa
|
|
2167
|
+
|
|
2168
|
+
return IK_LM_c(
|
|
2169
|
+
self._fknm, Tep, q0, ilimit, slimit, tol, joint_limits, mask, k, method
|
|
2170
|
+
)
|
|
2171
|
+
|
|
2172
|
+
def ik_NR(
|
|
2173
|
+
self,
|
|
2174
|
+
Tep: Union[NDArray, SE3],
|
|
2175
|
+
q0: Union[NDArray, None] = None,
|
|
2176
|
+
ilimit: int = 30,
|
|
2177
|
+
slimit: int = 100,
|
|
2178
|
+
tol: float = 1e-6,
|
|
2179
|
+
mask: Union[NDArray, None] = None,
|
|
2180
|
+
joint_limits: bool = True,
|
|
2181
|
+
pinv: int = True,
|
|
2182
|
+
pinv_damping: float = 0.0,
|
|
2183
|
+
) -> Tuple[NDArray, int, int, int, float]:
|
|
2184
|
+
r"""
|
|
2185
|
+
Fast numerical inverse kinematics using Newton-Raphson optimization
|
|
2186
|
+
|
|
2187
|
+
``sol = ets.ik_NR(Tep)`` are the joint coordinates (n) corresponding
|
|
2188
|
+
to the robot end-effector pose ``Tep`` which is an ``SE3`` or ``ndarray`` object.
|
|
2189
|
+
This method can be used for robots with any number of degrees of freedom. This
|
|
2190
|
+
is a fast solver implemented in C++.
|
|
2191
|
+
|
|
2192
|
+
See the :ref:`Inverse Kinematics Docs Page <IK>` for more details and for a
|
|
2193
|
+
**tutorial** on numerical IK, see `here <https://bit.ly/3ak5GDi>`_.
|
|
2194
|
+
|
|
2195
|
+
Note
|
|
2196
|
+
----
|
|
2197
|
+
When using this method with redundant robots (>6 DoF), ``pinv`` must be set to ``True``
|
|
2198
|
+
|
|
2199
|
+
Parameters
|
|
2200
|
+
----------
|
|
2201
|
+
Tep
|
|
2202
|
+
The desired end-effector pose or pose trajectory
|
|
2203
|
+
q0
|
|
2204
|
+
initial joint configuration (default to random valid joint
|
|
2205
|
+
configuration contrained by the joint limits of the robot)
|
|
2206
|
+
ilimit
|
|
2207
|
+
maximum number of iterations per search
|
|
2208
|
+
slimit
|
|
2209
|
+
maximum number of search attempts
|
|
2210
|
+
tol
|
|
2211
|
+
final error tolerance
|
|
2212
|
+
mask
|
|
2213
|
+
a mask vector which weights the end-effector error priority.
|
|
2214
|
+
Corresponds to translation in X, Y and Z and rotation about X, Y and Z
|
|
2215
|
+
respectively
|
|
2216
|
+
joint_limits
|
|
2217
|
+
constrain the solution to being within the joint limits of
|
|
2218
|
+
the robot (reject solution with invalid joint configurations and perfrom
|
|
2219
|
+
another search up to the slimit)
|
|
2220
|
+
pinv
|
|
2221
|
+
Use the psuedo-inverse instad of the normal matrix inverse
|
|
2222
|
+
pinv_damping
|
|
2223
|
+
Damping factor for the psuedo-inverse
|
|
2224
|
+
|
|
2225
|
+
Returns
|
|
2226
|
+
-------
|
|
2227
|
+
sol
|
|
2228
|
+
tuple (q, success, iterations, searches, residual)
|
|
2229
|
+
|
|
2230
|
+
The return value ``sol`` is a tuple with elements:
|
|
2231
|
+
|
|
2232
|
+
============ ========== ===============================================
|
|
2233
|
+
Element Type Description
|
|
2234
|
+
============ ========== ===============================================
|
|
2235
|
+
``q`` ndarray(n) joint coordinates in units of radians or metres
|
|
2236
|
+
``success`` int whether a solution was found
|
|
2237
|
+
``iterations`` int total number of iterations
|
|
2238
|
+
``searches`` int total number of searches
|
|
2239
|
+
``residual`` float final value of cost function
|
|
2240
|
+
============ ========== ===============================================
|
|
2241
|
+
|
|
2242
|
+
If ``success == 0`` the ``q`` values will be valid numbers, but the
|
|
2243
|
+
solution will be in error. The amount of error is indicated by
|
|
2244
|
+
the ``residual``.
|
|
2245
|
+
|
|
2246
|
+
Synopsis
|
|
2247
|
+
--------
|
|
2248
|
+
Each iteration uses the Newton-Raphson optimisation method
|
|
2249
|
+
|
|
2250
|
+
.. math::
|
|
2251
|
+
|
|
2252
|
+
\vec{q}_{k+1} = \vec{q}_k + {^0\mat{J}(\vec{q}_k)}^{-1} \vec{e}_k
|
|
2253
|
+
|
|
2254
|
+
Examples
|
|
2255
|
+
--------
|
|
2256
|
+
The following example gets the ``ets`` of a ``panda`` robot object, makes a goal
|
|
2257
|
+
pose ``Tep``, and then solves for the joint coordinates which result in the pose
|
|
2258
|
+
``Tep`` using the `ikine_GN` method.
|
|
2259
|
+
|
|
2260
|
+
.. runblock:: pycon
|
|
2261
|
+
>>> import roboticstoolbox as rtb
|
|
2262
|
+
>>> panda = rtb.models.Panda().ets()
|
|
2263
|
+
>>> Tep = panda.fkine([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
2264
|
+
>>> panda.ik_NR(Tep)
|
|
2265
|
+
|
|
2266
|
+
Notes
|
|
2267
|
+
-----
|
|
2268
|
+
When using the this method, the initial joint coordinates :math:`q_0`, should correspond
|
|
2269
|
+
to a non-singular manipulator pose, since it uses the manipulator Jacobian.
|
|
2270
|
+
|
|
2271
|
+
References
|
|
2272
|
+
----------
|
|
2273
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
2274
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
2275
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
2276
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
2277
|
+
|
|
2278
|
+
See Also
|
|
2279
|
+
--------
|
|
2280
|
+
ik_LM
|
|
2281
|
+
A fast numerical inverse kinematics solver using Levenberg-Marquadt optimisation
|
|
2282
|
+
ik_GN
|
|
2283
|
+
A fast numerical inverse kinematics solver using Gauss-Newton optimisation
|
|
2284
|
+
|
|
2285
|
+
""" # noqa
|
|
2286
|
+
|
|
2287
|
+
return IK_NR_c(
|
|
2288
|
+
self._fknm,
|
|
2289
|
+
Tep,
|
|
2290
|
+
q0,
|
|
2291
|
+
ilimit,
|
|
2292
|
+
slimit,
|
|
2293
|
+
tol,
|
|
2294
|
+
joint_limits,
|
|
2295
|
+
mask,
|
|
2296
|
+
pinv,
|
|
2297
|
+
pinv_damping,
|
|
2298
|
+
)
|
|
2299
|
+
|
|
2300
|
+
def ik_GN(
|
|
2301
|
+
self,
|
|
2302
|
+
Tep: Union[NDArray, SE3],
|
|
2303
|
+
q0: Union[NDArray, None] = None,
|
|
2304
|
+
ilimit: int = 30,
|
|
2305
|
+
slimit: int = 100,
|
|
2306
|
+
tol: float = 1e-6,
|
|
2307
|
+
mask: Union[NDArray, None] = None,
|
|
2308
|
+
joint_limits: bool = True,
|
|
2309
|
+
pinv: int = True,
|
|
2310
|
+
pinv_damping: float = 0.0,
|
|
2311
|
+
) -> Tuple[NDArray, int, int, int, float]:
|
|
2312
|
+
r"""
|
|
2313
|
+
Fast numerical inverse kinematics by Gauss-Newton optimization
|
|
2314
|
+
|
|
2315
|
+
``sol = ets.ik_GN(Tep)`` are the joint coordinates (n) corresponding
|
|
2316
|
+
to the robot end-effector pose ``Tep`` which is an ``SE3`` or ``ndarray`` object.
|
|
2317
|
+
This method can be used for robots with any number of degrees of freedom. This
|
|
2318
|
+
is a fast solver implemented in C++.
|
|
2319
|
+
|
|
2320
|
+
See the :ref:`Inverse Kinematics Docs Page <IK>` for more details and for a
|
|
2321
|
+
**tutorial** on numerical IK, see `here <https://bit.ly/3ak5GDi>`_.
|
|
2322
|
+
|
|
2323
|
+
Note
|
|
2324
|
+
----
|
|
2325
|
+
When using this method with redundant robots (>6 DoF), ``pinv`` must be set to ``True``
|
|
2326
|
+
|
|
2327
|
+
Parameters
|
|
2328
|
+
----------
|
|
2329
|
+
Tep
|
|
2330
|
+
The desired end-effector pose or pose trajectory
|
|
2331
|
+
q0
|
|
2332
|
+
initial joint configuration (default to random valid joint
|
|
2333
|
+
configuration contrained by the joint limits of the robot)
|
|
2334
|
+
ilimit
|
|
2335
|
+
maximum number of iterations per search
|
|
2336
|
+
slimit
|
|
2337
|
+
maximum number of search attempts
|
|
2338
|
+
tol
|
|
2339
|
+
final error tolerance
|
|
2340
|
+
mask
|
|
2341
|
+
a mask vector which weights the end-effector error priority.
|
|
2342
|
+
Corresponds to translation in X, Y and Z and rotation about X, Y and Z
|
|
2343
|
+
respectively
|
|
2344
|
+
joint_limits
|
|
2345
|
+
constrain the solution to being within the joint limits of
|
|
2346
|
+
the robot (reject solution with invalid joint configurations and perfrom
|
|
2347
|
+
another search up to the slimit)
|
|
2348
|
+
pinv
|
|
2349
|
+
Use the psuedo-inverse instad of the normal matrix inverse
|
|
2350
|
+
pinv_damping
|
|
2351
|
+
Damping factor for the psuedo-inverse
|
|
2352
|
+
|
|
2353
|
+
Returns
|
|
2354
|
+
-------
|
|
2355
|
+
sol
|
|
2356
|
+
tuple (q, success, iterations, searches, residual)
|
|
2357
|
+
|
|
2358
|
+
The return value ``sol`` is a tuple with elements:
|
|
2359
|
+
|
|
2360
|
+
============ ========== ===============================================
|
|
2361
|
+
Element Type Description
|
|
2362
|
+
============ ========== ===============================================
|
|
2363
|
+
``q`` ndarray(n) joint coordinates in units of radians or metres
|
|
2364
|
+
``success`` int whether a solution was found
|
|
2365
|
+
``iterations`` int total number of iterations
|
|
2366
|
+
``searches`` int total number of searches
|
|
2367
|
+
``residual`` float final value of cost function
|
|
2368
|
+
============ ========== ===============================================
|
|
2369
|
+
|
|
2370
|
+
If ``success == 0`` the ``q`` values will be valid numbers, but the
|
|
2371
|
+
solution will be in error. The amount of error is indicated by
|
|
2372
|
+
the ``residual``.
|
|
2373
|
+
|
|
2374
|
+
Synopsis
|
|
2375
|
+
--------
|
|
2376
|
+
Each iteration uses the Gauss-Newton optimisation method
|
|
2377
|
+
|
|
2378
|
+
.. math::
|
|
2379
|
+
|
|
2380
|
+
\vec{q}_{k+1} &= \vec{q}_k +
|
|
2381
|
+
\left(
|
|
2382
|
+
{\mat{J}(\vec{q}_k)}^\top
|
|
2383
|
+
\mat{W}_e \
|
|
2384
|
+
{\mat{J}(\vec{q}_k)}
|
|
2385
|
+
\right)^{-1}
|
|
2386
|
+
\bf{g}_k \\
|
|
2387
|
+
\bf{g}_k &=
|
|
2388
|
+
{\mat{J}(\vec{q}_k)}^\top
|
|
2389
|
+
\mat{W}_e
|
|
2390
|
+
\vec{e}_k
|
|
2391
|
+
|
|
2392
|
+
where :math:`\mat{J} = {^0\mat{J}}` is the base-frame manipulator Jacobian. If
|
|
2393
|
+
:math:`\mat{J}(\vec{q}_k)` is non-singular, and :math:`\mat{W}_e = \mat{1}_n`, then
|
|
2394
|
+
the above provides the pseudoinverse solution. However, if :math:`\mat{J}(\vec{q}_k)`
|
|
2395
|
+
is singular, the above can not be computed and the GN solution is infeasible.
|
|
2396
|
+
|
|
2397
|
+
Examples
|
|
2398
|
+
--------
|
|
2399
|
+
The following example gets the ``ets`` of a ``panda`` robot object, makes a goal
|
|
2400
|
+
pose ``Tep``, and then solves for the joint coordinates which result in the pose
|
|
2401
|
+
``Tep`` using the `ikine_GN` method.
|
|
2402
|
+
|
|
2403
|
+
.. runblock:: pycon
|
|
2404
|
+
>>> import roboticstoolbox as rtb
|
|
2405
|
+
>>> panda = rtb.models.Panda().ets()
|
|
2406
|
+
>>> Tep = panda.fkine([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
2407
|
+
>>> panda.ik_GN(Tep)
|
|
2408
|
+
|
|
2409
|
+
Notes
|
|
2410
|
+
-----
|
|
2411
|
+
When using the this method, the initial joint coordinates :math:`q_0`, should correspond
|
|
2412
|
+
to a non-singular manipulator pose, since it uses the manipulator Jacobian.
|
|
2413
|
+
|
|
2414
|
+
References
|
|
2415
|
+
----------
|
|
2416
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
2417
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
2418
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
2419
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
2420
|
+
|
|
2421
|
+
See Also
|
|
2422
|
+
--------
|
|
2423
|
+
ik_NR
|
|
2424
|
+
A fast numerical inverse kinematics solver using Newton-Raphson optimisation
|
|
2425
|
+
ik_GN
|
|
2426
|
+
A fast numerical inverse kinematics solver using Gauss-Newton optimisation
|
|
2427
|
+
|
|
2428
|
+
""" # noqa
|
|
2429
|
+
|
|
2430
|
+
return IK_GN_c(
|
|
2431
|
+
self._fknm,
|
|
2432
|
+
Tep,
|
|
2433
|
+
q0,
|
|
2434
|
+
ilimit,
|
|
2435
|
+
slimit,
|
|
2436
|
+
tol,
|
|
2437
|
+
joint_limits,
|
|
2438
|
+
mask,
|
|
2439
|
+
pinv,
|
|
2440
|
+
pinv_damping,
|
|
2441
|
+
)
|
|
2442
|
+
|
|
2443
|
+
def ikine_LM(
|
|
2444
|
+
self,
|
|
2445
|
+
Tep: Union[NDArray, SE3],
|
|
2446
|
+
q0: Union[ArrayLike, None] = None,
|
|
2447
|
+
ilimit: int = 30,
|
|
2448
|
+
slimit: int = 100,
|
|
2449
|
+
tol: float = 1e-6,
|
|
2450
|
+
mask: Union[ArrayLike, None] = None,
|
|
2451
|
+
joint_limits: bool = True,
|
|
2452
|
+
seed: Union[int, None] = None,
|
|
2453
|
+
k: float = 1.0,
|
|
2454
|
+
method: L["chan", "wampler", "sugihara"] = "chan", # noqa
|
|
2455
|
+
kq: float = 0.0,
|
|
2456
|
+
km: float = 0.0,
|
|
2457
|
+
ps: float = 0.0,
|
|
2458
|
+
pi: Union[NDArray, float] = 0.3,
|
|
2459
|
+
**kwargs,
|
|
2460
|
+
):
|
|
2461
|
+
r"""
|
|
2462
|
+
Levemberg-Marquadt Numerical Inverse Kinematics Solver
|
|
2463
|
+
|
|
2464
|
+
A method which provides functionality to perform numerical inverse kinematics (IK)
|
|
2465
|
+
using the Levemberg-Marquadt method.
|
|
2466
|
+
|
|
2467
|
+
See the :ref:`Inverse Kinematics Docs Page <IK>` for more details and for a
|
|
2468
|
+
**tutorial** on numerical IK, see `here <https://bit.ly/3ak5GDi>`_.
|
|
2469
|
+
|
|
2470
|
+
Parameters
|
|
2471
|
+
----------
|
|
2472
|
+
Tep
|
|
2473
|
+
The desired end-effector pose
|
|
2474
|
+
q0
|
|
2475
|
+
The initial joint coordinate vector
|
|
2476
|
+
ilimit
|
|
2477
|
+
How many iterations are allowed within a search before a new search
|
|
2478
|
+
is started
|
|
2479
|
+
slimit
|
|
2480
|
+
How many searches are allowed before being deemed unsuccessful
|
|
2481
|
+
tol
|
|
2482
|
+
Maximum allowed residual error E
|
|
2483
|
+
mask
|
|
2484
|
+
A 6 vector which assigns weights to Cartesian degrees-of-freedom
|
|
2485
|
+
error priority
|
|
2486
|
+
joint_limits
|
|
2487
|
+
Reject solutions with joint limit violations
|
|
2488
|
+
seed
|
|
2489
|
+
A seed for the private RNG used to generate random joint coordinate
|
|
2490
|
+
vectors
|
|
2491
|
+
k
|
|
2492
|
+
Sets the gain value for the damping matrix Wn in the next iteration. See
|
|
2493
|
+
synopsis
|
|
2494
|
+
method
|
|
2495
|
+
One of "chan", "sugihara" or "wampler". Defines which method is used
|
|
2496
|
+
to calculate the damping matrix Wn in the ``step`` method
|
|
2497
|
+
kq
|
|
2498
|
+
The gain for joint limit avoidance. Setting to 0.0 will remove this
|
|
2499
|
+
completely from the solution
|
|
2500
|
+
km
|
|
2501
|
+
The gain for maximisation. Setting to 0.0 will remove this completely
|
|
2502
|
+
from the solution
|
|
2503
|
+
ps
|
|
2504
|
+
The minimum angle/distance (in radians or metres) in which the joint is
|
|
2505
|
+
allowed to approach to its limit
|
|
2506
|
+
pi
|
|
2507
|
+
The influence angle/distance (in radians or metres) in null space motion
|
|
2508
|
+
becomes active
|
|
2509
|
+
|
|
2510
|
+
Synopsis
|
|
2511
|
+
--------
|
|
2512
|
+
The operation is defined by the choice of the ``method`` kwarg.
|
|
2513
|
+
|
|
2514
|
+
The step is deined as
|
|
2515
|
+
|
|
2516
|
+
.. math::
|
|
2517
|
+
|
|
2518
|
+
\vec{q}_{k+1}
|
|
2519
|
+
&=
|
|
2520
|
+
\vec{q}_k +
|
|
2521
|
+
\left(
|
|
2522
|
+
\mat{A}_k
|
|
2523
|
+
\right)^{-1}
|
|
2524
|
+
\bf{g}_k \\
|
|
2525
|
+
%
|
|
2526
|
+
\mat{A}_k
|
|
2527
|
+
&=
|
|
2528
|
+
{\mat{J}(\vec{q}_k)}^\top
|
|
2529
|
+
\mat{W}_e \
|
|
2530
|
+
{\mat{J}(\vec{q}_k)}
|
|
2531
|
+
+
|
|
2532
|
+
\mat{W}_n
|
|
2533
|
+
|
|
2534
|
+
where :math:`\mat{W}_n = \text{diag}(\vec{w_n})(\vec{w_n} \in \mathbb{R}^n_{>0})` is a
|
|
2535
|
+
diagonal damping matrix. The damping matrix ensures that :math:`\mat{A}_k` is
|
|
2536
|
+
non-singular and positive definite. The performance of the LM method largely depends
|
|
2537
|
+
on the choice of :math:`\mat{W}_n`.
|
|
2538
|
+
|
|
2539
|
+
*Chan's Method*
|
|
2540
|
+
|
|
2541
|
+
Chan proposed
|
|
2542
|
+
|
|
2543
|
+
.. math::
|
|
2544
|
+
|
|
2545
|
+
\mat{W}_n
|
|
2546
|
+
=
|
|
2547
|
+
λ E_k \mat{1}_n
|
|
2548
|
+
|
|
2549
|
+
where λ is a constant which reportedly does not have much influence on performance.
|
|
2550
|
+
Use the kwarg `k` to adjust the weighting term λ.
|
|
2551
|
+
|
|
2552
|
+
*Sugihara's Method*
|
|
2553
|
+
|
|
2554
|
+
Sugihara proposed
|
|
2555
|
+
|
|
2556
|
+
.. math::
|
|
2557
|
+
|
|
2558
|
+
\mat{W}_n
|
|
2559
|
+
=
|
|
2560
|
+
E_k \mat{1}_n + \text{diag}(\hat{\vec{w}}_n)
|
|
2561
|
+
|
|
2562
|
+
where :math:`\hat{\vec{w}}_n \in \mathbb{R}^n`, :math:`\hat{w}_{n_i} = l^2 \sim 0.01 l^2`,
|
|
2563
|
+
and :math:`l` is the length of a typical link within the manipulator. We provide the
|
|
2564
|
+
variable `k` as a kwarg to adjust the value of :math:`w_n`.
|
|
2565
|
+
|
|
2566
|
+
*Wampler's Method*
|
|
2567
|
+
|
|
2568
|
+
Wampler proposed :math:`\vec{w_n}` to be a constant. This is set through the `k` kwarg.
|
|
2569
|
+
|
|
2570
|
+
Examples
|
|
2571
|
+
--------
|
|
2572
|
+
The following example gets the ``ets`` of a ``panda`` robot object, makes a goal
|
|
2573
|
+
pose ``Tep``, and then solves for the joint coordinates which result in the pose
|
|
2574
|
+
``Tep`` using the `ikine_LM` method.
|
|
2575
|
+
|
|
2576
|
+
.. runblock:: pycon
|
|
2577
|
+
>>> import roboticstoolbox as rtb
|
|
2578
|
+
>>> panda = rtb.models.Panda().ets()
|
|
2579
|
+
>>> Tep = panda.fkine([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
2580
|
+
>>> panda.ikine_LM(Tep)
|
|
2581
|
+
|
|
2582
|
+
Notes
|
|
2583
|
+
-----
|
|
2584
|
+
The value for the ``k`` kwarg will depend on the ``method`` chosen and the arm you are
|
|
2585
|
+
using. Use the following as a rough guide ``chan, k = 1.0 - 0.01``,
|
|
2586
|
+
``wampler, k = 0.01 - 0.0001``, and ``sugihara, k = 0.1 - 0.0001``
|
|
2587
|
+
|
|
2588
|
+
When using the this method, the initial joint coordinates :math:`q_0`, should correspond
|
|
2589
|
+
to a non-singular manipulator pose, since it uses the manipulator Jacobian.
|
|
2590
|
+
|
|
2591
|
+
This class supports null-space motion to assist with maximising manipulability and
|
|
2592
|
+
avoiding joint limits. These are enabled by setting kq and km to non-zero values.
|
|
2593
|
+
|
|
2594
|
+
References
|
|
2595
|
+
----------
|
|
2596
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
2597
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
2598
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
2599
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
2600
|
+
|
|
2601
|
+
See Also
|
|
2602
|
+
--------
|
|
2603
|
+
:py:class:`~roboticstoolbox.robot.IK.IK_LM`
|
|
2604
|
+
An IK Solver class which implements the Levemberg Marquadt optimisation technique
|
|
2605
|
+
ikine_NR
|
|
2606
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_NR` class as a method within the :py:class:`ETS` class
|
|
2607
|
+
ikine_GN
|
|
2608
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_GN` class as a method within the :py:class:`ETS` class
|
|
2609
|
+
ikine_QP
|
|
2610
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_QP` class as a method within the :py:class:`ETS` class
|
|
2611
|
+
|
|
2612
|
+
|
|
2613
|
+
.. versionchanged:: 1.0.4
|
|
2614
|
+
Added the Levemberg-Marquadt IK solver method on the `ETS` class
|
|
2615
|
+
|
|
2616
|
+
""" # noqa
|
|
2617
|
+
|
|
2618
|
+
solver = IK_LM(
|
|
2619
|
+
ilimit=ilimit,
|
|
2620
|
+
slimit=slimit,
|
|
2621
|
+
tol=tol,
|
|
2622
|
+
joint_limits=joint_limits,
|
|
2623
|
+
mask=mask,
|
|
2624
|
+
seed=seed,
|
|
2625
|
+
k=k,
|
|
2626
|
+
method=method,
|
|
2627
|
+
kq=kq,
|
|
2628
|
+
km=km,
|
|
2629
|
+
ps=ps,
|
|
2630
|
+
pi=pi,
|
|
2631
|
+
**kwargs,
|
|
2632
|
+
)
|
|
2633
|
+
|
|
2634
|
+
# if isinstance(Tep, SE3):
|
|
2635
|
+
# Tep = Tep.A
|
|
2636
|
+
|
|
2637
|
+
return solver.solve(ets=self, Tep=Tep, q0=q0)
|
|
2638
|
+
|
|
2639
|
+
def ikine_NR(
|
|
2640
|
+
self,
|
|
2641
|
+
Tep: Union[NDArray, SE3],
|
|
2642
|
+
q0: Union[ArrayLike, None] = None,
|
|
2643
|
+
ilimit: int = 30,
|
|
2644
|
+
slimit: int = 100,
|
|
2645
|
+
tol: float = 1e-6,
|
|
2646
|
+
mask: Union[ArrayLike, None] = None,
|
|
2647
|
+
joint_limits: bool = True,
|
|
2648
|
+
seed: Union[int, None] = None,
|
|
2649
|
+
pinv: bool = False,
|
|
2650
|
+
kq: float = 0.0,
|
|
2651
|
+
km: float = 0.0,
|
|
2652
|
+
ps: float = 0.0,
|
|
2653
|
+
pi: Union[NDArray, float] = 0.3,
|
|
2654
|
+
**kwargs,
|
|
2655
|
+
):
|
|
2656
|
+
r"""
|
|
2657
|
+
Newton-Raphson Numerical Inverse Kinematics Solver
|
|
2658
|
+
|
|
2659
|
+
A method which provides functionality to perform numerical inverse kinematics (IK)
|
|
2660
|
+
using the Newton-Raphson method.
|
|
2661
|
+
|
|
2662
|
+
See the :ref:`Inverse Kinematics Docs Page <IK>` for more details and for a
|
|
2663
|
+
**tutorial** on numerical IK, see `here <https://bit.ly/3ak5GDi>`_.
|
|
2664
|
+
|
|
2665
|
+
Note
|
|
2666
|
+
----
|
|
2667
|
+
When using this method with redundant robots (>6 DoF), ``pinv`` must be set to ``True``
|
|
2668
|
+
|
|
2669
|
+
Parameters
|
|
2670
|
+
----------
|
|
2671
|
+
Tep
|
|
2672
|
+
The desired end-effector pose
|
|
2673
|
+
q0
|
|
2674
|
+
The initial joint coordinate vector
|
|
2675
|
+
ilimit
|
|
2676
|
+
How many iterations are allowed within a search before a new search
|
|
2677
|
+
is started
|
|
2678
|
+
slimit
|
|
2679
|
+
How many searches are allowed before being deemed unsuccessful
|
|
2680
|
+
tol
|
|
2681
|
+
Maximum allowed residual error E
|
|
2682
|
+
mask
|
|
2683
|
+
A 6 vector which assigns weights to Cartesian degrees-of-freedom
|
|
2684
|
+
error priority
|
|
2685
|
+
joint_limits
|
|
2686
|
+
Reject solutions with joint limit violations
|
|
2687
|
+
seed
|
|
2688
|
+
A seed for the private RNG used to generate random joint coordinate
|
|
2689
|
+
vectors
|
|
2690
|
+
pinv
|
|
2691
|
+
If True, will use the psuedoinverse in the `step` method instead of
|
|
2692
|
+
the normal inverse
|
|
2693
|
+
kq
|
|
2694
|
+
The gain for joint limit avoidance. Setting to 0.0 will remove this
|
|
2695
|
+
completely from the solution
|
|
2696
|
+
km
|
|
2697
|
+
The gain for maximisation. Setting to 0.0 will remove this completely
|
|
2698
|
+
from the solution
|
|
2699
|
+
ps
|
|
2700
|
+
The minimum angle/distance (in radians or metres) in which the joint is
|
|
2701
|
+
allowed to approach to its limit
|
|
2702
|
+
pi
|
|
2703
|
+
The influence angle/distance (in radians or metres) in null space motion
|
|
2704
|
+
becomes active
|
|
2705
|
+
|
|
2706
|
+
Synopsis
|
|
2707
|
+
--------
|
|
2708
|
+
Each iteration uses the Newton-Raphson optimisation method
|
|
2709
|
+
|
|
2710
|
+
.. math::
|
|
2711
|
+
|
|
2712
|
+
\vec{q}_{k+1} = \vec{q}_k + {^0\mat{J}(\vec{q}_k)}^{-1} \vec{e}_k
|
|
2713
|
+
|
|
2714
|
+
Examples
|
|
2715
|
+
--------
|
|
2716
|
+
The following example gets the ``ets`` of a ``panda`` robot object, makes a goal
|
|
2717
|
+
pose ``Tep``, and then solves for the joint coordinates which result in the pose
|
|
2718
|
+
``Tep`` using the `ikine_NR` method.
|
|
2719
|
+
|
|
2720
|
+
.. runblock:: pycon
|
|
2721
|
+
>>> import roboticstoolbox as rtb
|
|
2722
|
+
>>> panda = rtb.models.Panda().ets()
|
|
2723
|
+
>>> Tep = panda.fkine([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
2724
|
+
>>> panda.ikine_NR(Tep)
|
|
2725
|
+
|
|
2726
|
+
Notes
|
|
2727
|
+
-----
|
|
2728
|
+
When using the this method, the initial joint coordinates :math:`q_0`, should correspond
|
|
2729
|
+
to a non-singular manipulator pose, since it uses the manipulator Jacobian.
|
|
2730
|
+
|
|
2731
|
+
This class supports null-space motion to assist with maximising manipulability and
|
|
2732
|
+
avoiding joint limits. These are enabled by setting kq and km to non-zero values.
|
|
2733
|
+
|
|
2734
|
+
References
|
|
2735
|
+
----------
|
|
2736
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
2737
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
2738
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
2739
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
2740
|
+
|
|
2741
|
+
See Also
|
|
2742
|
+
--------
|
|
2743
|
+
:py:class:`~roboticstoolbox.robot.IK.IK_NR`
|
|
2744
|
+
An IK Solver class which implements the Newton-Raphson optimisation technique
|
|
2745
|
+
ikine_LM
|
|
2746
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_LM` class as a method within the :py:class:`ETS` class
|
|
2747
|
+
ikine_GN
|
|
2748
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_GN` class as a method within the :py:class:`ETS` class
|
|
2749
|
+
ikine_QP
|
|
2750
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_QP` class as a method within the :py:class:`ETS` class
|
|
2751
|
+
|
|
2752
|
+
|
|
2753
|
+
.. versionchanged:: 1.0.4
|
|
2754
|
+
Added the Newton-Raphson IK solver method on the `ETS` class
|
|
2755
|
+
|
|
2756
|
+
""" # noqa
|
|
2757
|
+
|
|
2758
|
+
solver = IK_NR(
|
|
2759
|
+
ilimit=ilimit,
|
|
2760
|
+
slimit=slimit,
|
|
2761
|
+
tol=tol,
|
|
2762
|
+
joint_limits=joint_limits,
|
|
2763
|
+
mask=mask,
|
|
2764
|
+
seed=seed,
|
|
2765
|
+
pinv=pinv,
|
|
2766
|
+
kq=kq,
|
|
2767
|
+
km=km,
|
|
2768
|
+
ps=ps,
|
|
2769
|
+
pi=pi,
|
|
2770
|
+
**kwargs,
|
|
2771
|
+
)
|
|
2772
|
+
|
|
2773
|
+
# if isinstance(Tep, SE3):
|
|
2774
|
+
# Tep = Tep.A
|
|
2775
|
+
|
|
2776
|
+
return solver.solve(ets=self, Tep=Tep, q0=q0)
|
|
2777
|
+
|
|
2778
|
+
def ikine_GN(
|
|
2779
|
+
self,
|
|
2780
|
+
Tep: Union[NDArray, SE3],
|
|
2781
|
+
q0: Union[ArrayLike, None] = None,
|
|
2782
|
+
ilimit: int = 30,
|
|
2783
|
+
slimit: int = 100,
|
|
2784
|
+
tol: float = 1e-6,
|
|
2785
|
+
mask: Union[ArrayLike, None] = None,
|
|
2786
|
+
joint_limits: bool = True,
|
|
2787
|
+
seed: Union[int, None] = None,
|
|
2788
|
+
pinv: bool = False,
|
|
2789
|
+
kq: float = 0.0,
|
|
2790
|
+
km: float = 0.0,
|
|
2791
|
+
ps: float = 0.0,
|
|
2792
|
+
pi: Union[NDArray, float] = 0.3,
|
|
2793
|
+
**kwargs,
|
|
2794
|
+
):
|
|
2795
|
+
r"""
|
|
2796
|
+
Gauss-Newton Numerical Inverse Kinematics Solver
|
|
2797
|
+
|
|
2798
|
+
A method which provides functionality to perform numerical inverse kinematics (IK)
|
|
2799
|
+
using the Gauss-Newton method.
|
|
2800
|
+
|
|
2801
|
+
See the :ref:`Inverse Kinematics Docs Page <IK>` for more details and for a
|
|
2802
|
+
**tutorial** on numerical IK, see `here <https://bit.ly/3ak5GDi>`_.
|
|
2803
|
+
|
|
2804
|
+
Note
|
|
2805
|
+
----
|
|
2806
|
+
When using this method with redundant robots (>6 DoF), ``pinv`` must be set to ``True``
|
|
2807
|
+
|
|
2808
|
+
Parameters
|
|
2809
|
+
----------
|
|
2810
|
+
Tep
|
|
2811
|
+
The desired end-effector pose
|
|
2812
|
+
q0
|
|
2813
|
+
The initial joint coordinate vector
|
|
2814
|
+
ilimit
|
|
2815
|
+
How many iterations are allowed within a search before a new search
|
|
2816
|
+
is started
|
|
2817
|
+
slimit
|
|
2818
|
+
How many searches are allowed before being deemed unsuccessful
|
|
2819
|
+
tol
|
|
2820
|
+
Maximum allowed residual error E
|
|
2821
|
+
mask
|
|
2822
|
+
A 6 vector which assigns weights to Cartesian degrees-of-freedom
|
|
2823
|
+
error priority
|
|
2824
|
+
joint_limits
|
|
2825
|
+
Reject solutions with joint limit violations
|
|
2826
|
+
seed
|
|
2827
|
+
A seed for the private RNG used to generate random joint coordinate
|
|
2828
|
+
vectors
|
|
2829
|
+
pinv
|
|
2830
|
+
If True, will use the psuedoinverse in the `step` method instead of
|
|
2831
|
+
the normal inverse
|
|
2832
|
+
kq
|
|
2833
|
+
The gain for joint limit avoidance. Setting to 0.0 will remove this
|
|
2834
|
+
completely from the solution
|
|
2835
|
+
km
|
|
2836
|
+
The gain for maximisation. Setting to 0.0 will remove this completely
|
|
2837
|
+
from the solution
|
|
2838
|
+
ps
|
|
2839
|
+
The minimum angle/distance (in radians or metres) in which the joint is
|
|
2840
|
+
allowed to approach to its limit
|
|
2841
|
+
pi
|
|
2842
|
+
The influence angle/distance (in radians or metres) in null space motion
|
|
2843
|
+
becomes active
|
|
2844
|
+
|
|
2845
|
+
Synopsis
|
|
2846
|
+
--------
|
|
2847
|
+
Each iteration uses the Gauss-Newton optimisation method
|
|
2848
|
+
|
|
2849
|
+
.. math::
|
|
2850
|
+
|
|
2851
|
+
\vec{q}_{k+1} &= \vec{q}_k +
|
|
2852
|
+
\left(
|
|
2853
|
+
{\mat{J}(\vec{q}_k)}^\top
|
|
2854
|
+
\mat{W}_e \
|
|
2855
|
+
{\mat{J}(\vec{q}_k)}
|
|
2856
|
+
\right)^{-1}
|
|
2857
|
+
\bf{g}_k \\
|
|
2858
|
+
\bf{g}_k &=
|
|
2859
|
+
{\mat{J}(\vec{q}_k)}^\top
|
|
2860
|
+
\mat{W}_e
|
|
2861
|
+
\vec{e}_k
|
|
2862
|
+
|
|
2863
|
+
where :math:`\mat{J} = {^0\mat{J}}` is the base-frame manipulator Jacobian. If
|
|
2864
|
+
:math:`\mat{J}(\vec{q}_k)` is non-singular, and :math:`\mat{W}_e = \mat{1}_n`, then
|
|
2865
|
+
the above provides the pseudoinverse solution. However, if :math:`\mat{J}(\vec{q}_k)`
|
|
2866
|
+
is singular, the above can not be computed and the GN solution is infeasible.
|
|
2867
|
+
|
|
2868
|
+
Examples
|
|
2869
|
+
--------
|
|
2870
|
+
The following example gets the ``ets`` of a ``panda`` robot object, makes a goal
|
|
2871
|
+
pose ``Tep``, and then solves for the joint coordinates which result in the pose
|
|
2872
|
+
``Tep`` using the `ikine_GN` method.
|
|
2873
|
+
|
|
2874
|
+
.. runblock:: pycon
|
|
2875
|
+
>>> import roboticstoolbox as rtb
|
|
2876
|
+
>>> panda = rtb.models.Panda().ets()
|
|
2877
|
+
>>> Tep = panda.fkine([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
2878
|
+
>>> panda.ikine_GN(Tep)
|
|
2879
|
+
|
|
2880
|
+
Notes
|
|
2881
|
+
-----
|
|
2882
|
+
When using the this method, the initial joint coordinates :math:`q_0`, should correspond
|
|
2883
|
+
to a non-singular manipulator pose, since it uses the manipulator Jacobian.
|
|
2884
|
+
|
|
2885
|
+
This class supports null-space motion to assist with maximising manipulability and
|
|
2886
|
+
avoiding joint limits. These are enabled by setting kq and km to non-zero values.
|
|
2887
|
+
|
|
2888
|
+
References
|
|
2889
|
+
----------
|
|
2890
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
2891
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
2892
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
2893
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
2894
|
+
|
|
2895
|
+
See Also
|
|
2896
|
+
--------
|
|
2897
|
+
:py:class:`~roboticstoolbox.robot.IK.IK_NR`
|
|
2898
|
+
An IK Solver class which implements the Newton-Raphson optimisation technique
|
|
2899
|
+
ikine_LM
|
|
2900
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_LM` class as a method within the :py:class:`ETS` class
|
|
2901
|
+
ikine_NR
|
|
2902
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_NR` class as a method within the :py:class:`ETS` class
|
|
2903
|
+
ikine_QP
|
|
2904
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_QP` class as a method within the :py:class:`ETS` class
|
|
2905
|
+
|
|
2906
|
+
|
|
2907
|
+
.. versionchanged:: 1.0.4
|
|
2908
|
+
Added the Gauss-Newton IK solver method on the `ETS` class
|
|
2909
|
+
|
|
2910
|
+
""" # noqa
|
|
2911
|
+
|
|
2912
|
+
solver = IK_GN(
|
|
2913
|
+
ilimit=ilimit,
|
|
2914
|
+
slimit=slimit,
|
|
2915
|
+
tol=tol,
|
|
2916
|
+
joint_limits=joint_limits,
|
|
2917
|
+
mask=mask,
|
|
2918
|
+
seed=seed,
|
|
2919
|
+
pinv=pinv,
|
|
2920
|
+
kq=kq,
|
|
2921
|
+
km=km,
|
|
2922
|
+
ps=ps,
|
|
2923
|
+
pi=pi,
|
|
2924
|
+
**kwargs,
|
|
2925
|
+
)
|
|
2926
|
+
|
|
2927
|
+
# if isinstance(Tep, SE3):
|
|
2928
|
+
# Tep = Tep.A
|
|
2929
|
+
|
|
2930
|
+
return solver.solve(ets=self, Tep=Tep, q0=q0)
|
|
2931
|
+
|
|
2932
|
+
def ikine_QP(
|
|
2933
|
+
self,
|
|
2934
|
+
Tep: Union[NDArray, SE3],
|
|
2935
|
+
q0: Union[ArrayLike, None] = None,
|
|
2936
|
+
ilimit: int = 30,
|
|
2937
|
+
slimit: int = 100,
|
|
2938
|
+
tol: float = 1e-6,
|
|
2939
|
+
mask: Union[ArrayLike, None] = None,
|
|
2940
|
+
joint_limits: bool = True,
|
|
2941
|
+
seed: Union[int, None] = None,
|
|
2942
|
+
kj=1.0,
|
|
2943
|
+
ks=1.0,
|
|
2944
|
+
kq: float = 0.0,
|
|
2945
|
+
km: float = 0.0,
|
|
2946
|
+
ps: float = 0.0,
|
|
2947
|
+
pi: Union[NDArray, float] = 0.3,
|
|
2948
|
+
**kwargs,
|
|
2949
|
+
):
|
|
2950
|
+
r"""
|
|
2951
|
+
Quadratic Programming Numerical Inverse Kinematics Solver
|
|
2952
|
+
|
|
2953
|
+
A method that provides functionality to perform numerical inverse kinematics
|
|
2954
|
+
(IK) using a quadratic progamming approach.
|
|
2955
|
+
|
|
2956
|
+
See the :ref:`Inverse Kinematics Docs Page <IK>` for more details and for a
|
|
2957
|
+
**tutorial** on numerical IK, see `here <https://bit.ly/3ak5GDi>`_.
|
|
2958
|
+
|
|
2959
|
+
Parameters
|
|
2960
|
+
----------
|
|
2961
|
+
Tep
|
|
2962
|
+
The desired end-effector pose
|
|
2963
|
+
q0
|
|
2964
|
+
The initial joint coordinate vector
|
|
2965
|
+
ilimit
|
|
2966
|
+
How many iterations are allowed within a search before a new search
|
|
2967
|
+
is started
|
|
2968
|
+
slimit
|
|
2969
|
+
How many searches are allowed before being deemed unsuccessful
|
|
2970
|
+
tol
|
|
2971
|
+
Maximum allowed residual error E
|
|
2972
|
+
mask
|
|
2973
|
+
A 6 vector which assigns weights to Cartesian degrees-of-freedom
|
|
2974
|
+
error priority
|
|
2975
|
+
joint_limits
|
|
2976
|
+
Reject solutions with joint limit violations
|
|
2977
|
+
seed
|
|
2978
|
+
A seed for the private RNG used to generate random joint coordinate
|
|
2979
|
+
vectors
|
|
2980
|
+
kj
|
|
2981
|
+
A gain for joint velocity norm minimisation
|
|
2982
|
+
ks
|
|
2983
|
+
A gain which adjusts the cost of slack (intentional error)
|
|
2984
|
+
kq
|
|
2985
|
+
The gain for joint limit avoidance. Setting to 0.0 will remove this
|
|
2986
|
+
completely from the solution
|
|
2987
|
+
km
|
|
2988
|
+
The gain for maximisation. Setting to 0.0 will remove this completely
|
|
2989
|
+
from the solution
|
|
2990
|
+
ps
|
|
2991
|
+
The minimum angle/distance (in radians or metres) in which the joint is
|
|
2992
|
+
allowed to approach to its limit
|
|
2993
|
+
pi
|
|
2994
|
+
The influence angle/distance (in radians or metres) in null space motion
|
|
2995
|
+
becomes active
|
|
2996
|
+
|
|
2997
|
+
Raises
|
|
2998
|
+
------
|
|
2999
|
+
ImportError
|
|
3000
|
+
If the package ``qpsolvers`` is not installed
|
|
3001
|
+
|
|
3002
|
+
Synopsis
|
|
3003
|
+
--------
|
|
3004
|
+
Each iteration uses the following approach
|
|
3005
|
+
|
|
3006
|
+
.. math::
|
|
3007
|
+
|
|
3008
|
+
\vec{q}_{k+1} = \vec{q}_{k} + \dot{\vec{q}}.
|
|
3009
|
+
|
|
3010
|
+
where the QP is defined as
|
|
3011
|
+
|
|
3012
|
+
.. math::
|
|
3013
|
+
|
|
3014
|
+
\min_x \quad f_o(\vec{x}) &= \frac{1}{2} \vec{x}^\top \mathcal{Q} \vec{x}+ \mathcal{C}^\top \vec{x}, \\
|
|
3015
|
+
\text{subject to} \quad \mathcal{J} \vec{x} &= \vec{\nu}, \\
|
|
3016
|
+
\mathcal{A} \vec{x} &\leq \mathcal{B}, \\
|
|
3017
|
+
\vec{x}^- &\leq \vec{x} \leq \vec{x}^+
|
|
3018
|
+
|
|
3019
|
+
with
|
|
3020
|
+
|
|
3021
|
+
.. math::
|
|
3022
|
+
|
|
3023
|
+
\vec{x} &=
|
|
3024
|
+
\begin{pmatrix}
|
|
3025
|
+
\dvec{q} \\ \vec{\delta}
|
|
3026
|
+
\end{pmatrix} \in \mathbb{R}^{(n+6)} \\
|
|
3027
|
+
\mathcal{Q} &=
|
|
3028
|
+
\begin{pmatrix}
|
|
3029
|
+
\lambda_q \mat{1}_{n} & \mathbf{0}_{6 \times 6} \\ \mathbf{0}_{n \times n} & \lambda_\delta \mat{1}_{6}
|
|
3030
|
+
\end{pmatrix} \in \mathbb{R}^{(n+6) \times (n+6)} \\
|
|
3031
|
+
\mathcal{J} &=
|
|
3032
|
+
\begin{pmatrix}
|
|
3033
|
+
\mat{J}(\vec{q}) & \mat{1}_{6}
|
|
3034
|
+
\end{pmatrix} \in \mathbb{R}^{6 \times (n+6)} \\
|
|
3035
|
+
\mathcal{C} &=
|
|
3036
|
+
\begin{pmatrix}
|
|
3037
|
+
\mat{J}_m \\ \bf{0}_{6 \times 1}
|
|
3038
|
+
\end{pmatrix} \in \mathbb{R}^{(n + 6)} \\
|
|
3039
|
+
\mathcal{A} &=
|
|
3040
|
+
\begin{pmatrix}
|
|
3041
|
+
\mat{1}_{n \times n + 6} \\
|
|
3042
|
+
\end{pmatrix} \in \mathbb{R}^{(l + n) \times (n + 6)} \\
|
|
3043
|
+
\mathcal{B} &=
|
|
3044
|
+
\eta
|
|
3045
|
+
\begin{pmatrix}
|
|
3046
|
+
\frac{\rho_0 - \rho_s}
|
|
3047
|
+
{\rho_i - \rho_s} \\
|
|
3048
|
+
\vdots \\
|
|
3049
|
+
\frac{\rho_n - \rho_s}
|
|
3050
|
+
{\rho_i - \rho_s}
|
|
3051
|
+
\end{pmatrix} \in \mathbb{R}^{n} \\
|
|
3052
|
+
\vec{x}^{-, +} &=
|
|
3053
|
+
\begin{pmatrix}
|
|
3054
|
+
\dvec{q}^{-, +} \\
|
|
3055
|
+
\vec{\delta}^{-, +}
|
|
3056
|
+
\end{pmatrix} \in \mathbb{R}^{(n+6)},
|
|
3057
|
+
|
|
3058
|
+
where :math:`\vec{\delta} \in \mathbb{R}^6` is the slack vector,
|
|
3059
|
+
:math:`\lambda_\delta \in \mathbb{R}^+` is a gain term which adjusts the
|
|
3060
|
+
cost of the norm of the slack vector in the optimiser,
|
|
3061
|
+
:math:`\dvec{q}^{-,+}` are the minimum and maximum joint velocities, and
|
|
3062
|
+
:math:`\dvec{\delta}^{-,+}` are the minimum and maximum slack velocities.
|
|
3063
|
+
|
|
3064
|
+
Examples
|
|
3065
|
+
--------
|
|
3066
|
+
The following example gets the ``ets`` of a ``panda`` robot object, makes a goal
|
|
3067
|
+
pose ``Tep``, and then solves for the joint coordinates which result in the pose
|
|
3068
|
+
``Tep`` using the `ikine_QP` method.
|
|
3069
|
+
|
|
3070
|
+
.. runblock:: pycon
|
|
3071
|
+
>>> import roboticstoolbox as rtb
|
|
3072
|
+
>>> panda = rtb.models.Panda().ets()
|
|
3073
|
+
>>> Tep = panda.fkine([0, -0.3, 0, -2.2, 0, 2, 0.7854])
|
|
3074
|
+
>>> panda.ikine_QP(Tep)
|
|
3075
|
+
|
|
3076
|
+
Notes
|
|
3077
|
+
-----
|
|
3078
|
+
When using the this method, the initial joint coordinates :math:`q_0`, should correspond
|
|
3079
|
+
to a non-singular manipulator pose, since it uses the manipulator Jacobian.
|
|
3080
|
+
|
|
3081
|
+
This class supports null-space motion to assist with maximising manipulability and
|
|
3082
|
+
avoiding joint limits. These are enabled by setting kq and km to non-zero values.
|
|
3083
|
+
|
|
3084
|
+
References
|
|
3085
|
+
----------
|
|
3086
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I:
|
|
3087
|
+
Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022).
|
|
3088
|
+
- J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II:
|
|
3089
|
+
Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022).
|
|
3090
|
+
|
|
3091
|
+
See Also
|
|
3092
|
+
--------
|
|
3093
|
+
:py:class:`~roboticstoolbox.robot.IK.IK_NR`
|
|
3094
|
+
An IK Solver class which implements the Newton-Raphson optimisation technique
|
|
3095
|
+
ikine_LM
|
|
3096
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_LM` class as a method within the :py:class:`ETS` class
|
|
3097
|
+
ikine_GN
|
|
3098
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_GN` class as a method within the :py:class:`ETS` class
|
|
3099
|
+
ikine_NR
|
|
3100
|
+
Implements the :py:class:`~roboticstoolbox.robot.IK.IK_NR` class as a method within the :py:class:`ETS` class
|
|
3101
|
+
|
|
3102
|
+
|
|
3103
|
+
.. versionchanged:: 1.0.4
|
|
3104
|
+
Added the Quadratic Programming IK solver method on the `ETS` class
|
|
3105
|
+
|
|
3106
|
+
""" # noqa: E501
|
|
3107
|
+
|
|
3108
|
+
solver = IK_QP(
|
|
3109
|
+
ilimit=ilimit,
|
|
3110
|
+
slimit=slimit,
|
|
3111
|
+
tol=tol,
|
|
3112
|
+
joint_limits=joint_limits,
|
|
3113
|
+
mask=mask,
|
|
3114
|
+
seed=seed,
|
|
3115
|
+
kj=kj,
|
|
3116
|
+
ks=ks,
|
|
3117
|
+
kq=kq,
|
|
3118
|
+
km=km,
|
|
3119
|
+
ps=ps,
|
|
3120
|
+
pi=pi,
|
|
3121
|
+
**kwargs,
|
|
3122
|
+
)
|
|
3123
|
+
|
|
3124
|
+
# if isinstance(Tep, SE3):
|
|
3125
|
+
# Tep = Tep.A
|
|
3126
|
+
|
|
3127
|
+
return solver.solve(ets=self, Tep=Tep, q0=q0)
|
|
3128
|
+
|
|
3129
|
+
|
|
3130
|
+
class ETS2(BaseETS):
|
|
3131
|
+
"""
|
|
3132
|
+
This class implements an elementary transform sequence (ETS) for 2D
|
|
3133
|
+
|
|
3134
|
+
:param arg: Function to compute ET value
|
|
3135
|
+
|
|
3136
|
+
An instance can contain an elementary transform (ET) or an elementary
|
|
3137
|
+
transform sequence (ETS). It has list-like properties by subclassing
|
|
3138
|
+
UserList, which means we can perform indexing, slicing pop, insert, as well
|
|
3139
|
+
as using it as an iterator over its values.
|
|
3140
|
+
|
|
3141
|
+
- ``ETS()`` an empty ETS list
|
|
3142
|
+
- ``ET2.XY(η)`` is a constant elementary transform
|
|
3143
|
+
- ``ET2.XY(η, 'deg')`` as above but the angle is expressed in degrees
|
|
3144
|
+
- ``ET2.XY()`` is a joint variable, the value is left free until evaluation
|
|
3145
|
+
time
|
|
3146
|
+
- ``ET2.XY(j=J)`` as above but the joint index is explicitly given, this
|
|
3147
|
+
might correspond to the joint number of a multi-joint robot.
|
|
3148
|
+
- ``ET2.XY(flip=True)`` as above but the joint moves in the opposite sense
|
|
3149
|
+
|
|
3150
|
+
where ``XY`` is one of ``R``, ``tx``, ``ty``.
|
|
3151
|
+
|
|
3152
|
+
Example:
|
|
3153
|
+
|
|
3154
|
+
.. runblock:: pycon
|
|
3155
|
+
|
|
3156
|
+
>>> from roboticstoolbox import ETS2 as ET2
|
|
3157
|
+
>>> e = ET2.R(0.3) # a single ET, rotation about z
|
|
3158
|
+
>>> len(e)
|
|
3159
|
+
>>> e = ET2.R(0.3) * ET2.tx(2) # an ETS
|
|
3160
|
+
>>> len(e) # of length 2
|
|
3161
|
+
>>> e[1] # an ET sliced from the ETS
|
|
3162
|
+
|
|
3163
|
+
:references:
|
|
3164
|
+
- Kinematic Derivatives using the Elementary Transform Sequence,
|
|
3165
|
+
J. Haviland and P. Corke
|
|
3166
|
+
|
|
3167
|
+
:seealso: :func:`r`, :func:`tx`, :func:`ty`
|
|
3168
|
+
"""
|
|
3169
|
+
|
|
3170
|
+
def __init__(
|
|
3171
|
+
self,
|
|
3172
|
+
arg: Union[
|
|
3173
|
+
List[Union["ETS2", ET2]], List[ET2], List["ETS2"], ET2, "ETS2", None
|
|
3174
|
+
] = None,
|
|
3175
|
+
):
|
|
3176
|
+
super().__init__()
|
|
3177
|
+
if isinstance(arg, list):
|
|
3178
|
+
for item in arg:
|
|
3179
|
+
if isinstance(item, ET2):
|
|
3180
|
+
self.data.append(deepcopy(item))
|
|
3181
|
+
elif isinstance(item, ETS2):
|
|
3182
|
+
for ets_item in item:
|
|
3183
|
+
self.data.append(deepcopy(ets_item))
|
|
3184
|
+
else:
|
|
3185
|
+
raise TypeError("bad arg")
|
|
3186
|
+
elif isinstance(arg, ET2):
|
|
3187
|
+
self.data.append(deepcopy(arg))
|
|
3188
|
+
elif isinstance(arg, ETS2):
|
|
3189
|
+
for ets_item in arg:
|
|
3190
|
+
self.data.append(deepcopy(ets_item))
|
|
3191
|
+
elif arg is None:
|
|
3192
|
+
self.data = []
|
|
3193
|
+
else:
|
|
3194
|
+
raise TypeError("Invalid arg")
|
|
3195
|
+
|
|
3196
|
+
self._update_internals()
|
|
3197
|
+
self._ndims = 2
|
|
3198
|
+
self._auto_jindex = False
|
|
3199
|
+
|
|
3200
|
+
# Check if jindices are set
|
|
3201
|
+
joints = self.joints()
|
|
3202
|
+
|
|
3203
|
+
# Number of joints with a jindex
|
|
3204
|
+
jindices = 0
|
|
3205
|
+
|
|
3206
|
+
# Number of joints with a sequential jindex (j[2] -> jindex = 2)
|
|
3207
|
+
seq_jindex = 0
|
|
3208
|
+
|
|
3209
|
+
# Count them up
|
|
3210
|
+
for j, joint in enumerate(joints):
|
|
3211
|
+
if joint.jindex is not None:
|
|
3212
|
+
jindices += 1
|
|
3213
|
+
if joint.jindex == j:
|
|
3214
|
+
seq_jindex += 1
|
|
3215
|
+
|
|
3216
|
+
if (
|
|
3217
|
+
jindices == self.n - 1
|
|
3218
|
+
and seq_jindex == self.n - 1
|
|
3219
|
+
and joints[-1].jindex is None
|
|
3220
|
+
):
|
|
3221
|
+
# ets has sequential jindicies, except for the last.
|
|
3222
|
+
joints[-1].jindex = self.n - 1
|
|
3223
|
+
self._auto_jindex = True
|
|
3224
|
+
elif jindices > 0 and not jindices == self.n:
|
|
3225
|
+
raise ValueError(
|
|
3226
|
+
"You can not have some jindices set for the ET's in arg. It must be all"
|
|
3227
|
+
" or none"
|
|
3228
|
+
) # pragma: nocover
|
|
3229
|
+
elif jindices == 0 and self.n > 0:
|
|
3230
|
+
# Set them ourself
|
|
3231
|
+
for j, joint in enumerate(joints):
|
|
3232
|
+
joint.jindex = j
|
|
3233
|
+
self._auto_jindex = True
|
|
3234
|
+
|
|
3235
|
+
def __mul__(self, other: Union[ET2, "ETS2"]) -> "ETS2":
|
|
3236
|
+
if isinstance(other, ET2):
|
|
3237
|
+
return ETS2([*self.data, other])
|
|
3238
|
+
else:
|
|
3239
|
+
return ETS2([*self.data, *other.data]) # pragma: nocover
|
|
3240
|
+
|
|
3241
|
+
def __rmul__(self, other: Union[ET2, "ETS2"]) -> "ETS2":
|
|
3242
|
+
return ETS2([other, self.data]) # pragma: nocover
|
|
3243
|
+
|
|
3244
|
+
def __imul__(self, rest: "ETS2"):
|
|
3245
|
+
return self + rest # pragma: nocover
|
|
3246
|
+
|
|
3247
|
+
def __add__(self, rest) -> "ETS2":
|
|
3248
|
+
return self.__mul__(rest) # pragma: nocover
|
|
3249
|
+
|
|
3250
|
+
def compile(self) -> "ETS2":
|
|
3251
|
+
"""
|
|
3252
|
+
Compile an ETS2
|
|
3253
|
+
|
|
3254
|
+
:return: optimised ETS2
|
|
3255
|
+
|
|
3256
|
+
Perform constant folding for faster evaluation. Consecutive constant
|
|
3257
|
+
ETs are compounded, leading to a constant ET which is denoted by
|
|
3258
|
+
``SE3`` when displayed.
|
|
3259
|
+
|
|
3260
|
+
:seealso: :func:`isconstant`
|
|
3261
|
+
"""
|
|
3262
|
+
const = None
|
|
3263
|
+
ets = ETS2()
|
|
3264
|
+
|
|
3265
|
+
for et in self:
|
|
3266
|
+
if et.isjoint:
|
|
3267
|
+
# a joint
|
|
3268
|
+
if const is not None:
|
|
3269
|
+
# flush the constant
|
|
3270
|
+
if not np.array_equal(const, np.eye(3)):
|
|
3271
|
+
ets *= ET2.SE2(const)
|
|
3272
|
+
const = None
|
|
3273
|
+
ets *= et # emit the joint ET
|
|
3274
|
+
else:
|
|
3275
|
+
# not a joint
|
|
3276
|
+
if const is None:
|
|
3277
|
+
const = et.A()
|
|
3278
|
+
else:
|
|
3279
|
+
const = const @ et.A()
|
|
3280
|
+
|
|
3281
|
+
if const is not None:
|
|
3282
|
+
# flush the constant, tool transform
|
|
3283
|
+
if not np.array_equal(const, np.eye(3)):
|
|
3284
|
+
ets *= ET2.SE2(const)
|
|
3285
|
+
return ets
|
|
3286
|
+
|
|
3287
|
+
def insert(
|
|
3288
|
+
self,
|
|
3289
|
+
arg: Union[ET2, "ETS2"],
|
|
3290
|
+
i: int = -1,
|
|
3291
|
+
) -> None:
|
|
3292
|
+
"""
|
|
3293
|
+
Insert value
|
|
3294
|
+
|
|
3295
|
+
:param i: insert an ET or ETS into the ETS, default is at the end
|
|
3296
|
+
:param arg: the elementary transform or sequence to insert
|
|
3297
|
+
|
|
3298
|
+
Inserts an ET or ETS into the ET sequence. The inserted value is at position
|
|
3299
|
+
``i``.
|
|
3300
|
+
|
|
3301
|
+
Example:
|
|
3302
|
+
|
|
3303
|
+
.. runblock:: pycon
|
|
3304
|
+
|
|
3305
|
+
>>> from roboticstoolbox import ET2
|
|
3306
|
+
>>> e = ET2.R() * ET2.tx(1) * ET2.R() * ET2.tx(1)
|
|
3307
|
+
>>> f = ET2.R()
|
|
3308
|
+
>>> e.insert(f, 2)
|
|
3309
|
+
>>> e
|
|
3310
|
+
"""
|
|
3311
|
+
|
|
3312
|
+
if isinstance(arg, ET2):
|
|
3313
|
+
if i == -1:
|
|
3314
|
+
self.data.append(arg)
|
|
3315
|
+
else:
|
|
3316
|
+
self.data.insert(i, arg)
|
|
3317
|
+
elif isinstance(arg, ETS2):
|
|
3318
|
+
if i == -1:
|
|
3319
|
+
for et in arg:
|
|
3320
|
+
self.data.append(et)
|
|
3321
|
+
else:
|
|
3322
|
+
for j, et in enumerate(arg):
|
|
3323
|
+
self.data.insert(i + j, et)
|
|
3324
|
+
self._update_internals()
|
|
3325
|
+
|
|
3326
|
+
def fkine(
|
|
3327
|
+
self,
|
|
3328
|
+
q: ArrayLike,
|
|
3329
|
+
base: Union[NDArray, SE2, None] = None,
|
|
3330
|
+
tool: Union[NDArray, SE2, None] = None,
|
|
3331
|
+
include_base: bool = True,
|
|
3332
|
+
) -> SE2:
|
|
3333
|
+
"""
|
|
3334
|
+
Forward kinematics
|
|
3335
|
+
:param q: Joint coordinates
|
|
3336
|
+
:type q: ArrayLike
|
|
3337
|
+
:param base: base transform, optional
|
|
3338
|
+
:param tool: tool transform, optional
|
|
3339
|
+
|
|
3340
|
+
:return: The transformation matrix representing the pose of the
|
|
3341
|
+
end-effector
|
|
3342
|
+
|
|
3343
|
+
- ``T = ets.fkine(q)`` evaluates forward kinematics for the robot at
|
|
3344
|
+
joint configuration ``q``.
|
|
3345
|
+
**Trajectory operation**:
|
|
3346
|
+
If ``q`` has multiple rows (mxn), it is considered a trajectory and the
|
|
3347
|
+
result is an ``SE2`` instance with ``m`` values.
|
|
3348
|
+
.. note::
|
|
3349
|
+
- The robot's base tool transform, if set, is incorporated
|
|
3350
|
+
into the result.
|
|
3351
|
+
- A tool transform, if provided, is incorporated into the result.
|
|
3352
|
+
- Works from the end-effector link to the base
|
|
3353
|
+
:references:
|
|
3354
|
+
- Kinematic Derivatives using the Elementary Transform
|
|
3355
|
+
Sequence, J. Haviland and P. Corke
|
|
3356
|
+
"""
|
|
3357
|
+
|
|
3358
|
+
ret = SE2.Empty()
|
|
3359
|
+
fk = self.eval(q, base, tool, include_base)
|
|
3360
|
+
|
|
3361
|
+
if fk.dtype == "O":
|
|
3362
|
+
# symbolic
|
|
3363
|
+
fk = np.array(simplify(fk))
|
|
3364
|
+
|
|
3365
|
+
if fk.ndim == 3:
|
|
3366
|
+
for T in fk:
|
|
3367
|
+
ret.append(SE2(T, check=False)) # type: ignore
|
|
3368
|
+
else:
|
|
3369
|
+
ret = SE2(fk, check=False)
|
|
3370
|
+
|
|
3371
|
+
return ret
|
|
3372
|
+
|
|
3373
|
+
def eval(
|
|
3374
|
+
self,
|
|
3375
|
+
q: ArrayLike,
|
|
3376
|
+
base: Union[NDArray, SE2, None] = None,
|
|
3377
|
+
tool: Union[NDArray, SE2, None] = None,
|
|
3378
|
+
include_base: bool = True,
|
|
3379
|
+
) -> NDArray:
|
|
3380
|
+
"""
|
|
3381
|
+
Forward kinematics
|
|
3382
|
+
:param q: Joint coordinates
|
|
3383
|
+
:type q: ArrayLike
|
|
3384
|
+
:param base: base transform, optional
|
|
3385
|
+
:param tool: tool transform, optional
|
|
3386
|
+
|
|
3387
|
+
:return: The transformation matrix representing the pose of the
|
|
3388
|
+
end-effector
|
|
3389
|
+
|
|
3390
|
+
- ``T = ets.fkine(q)`` evaluates forward kinematics for the robot at
|
|
3391
|
+
joint configuration ``q``.
|
|
3392
|
+
**Trajectory operation**:
|
|
3393
|
+
If ``q`` has multiple rows (mxn), it is considered a trajectory and the
|
|
3394
|
+
result is an ``SE2`` instance with ``m`` values.
|
|
3395
|
+
.. note::
|
|
3396
|
+
- The robot's base tool transform, if set, is incorporated
|
|
3397
|
+
into the result.
|
|
3398
|
+
- A tool transform, if provided, is incorporated into the result.
|
|
3399
|
+
- Works from the end-effector link to the base
|
|
3400
|
+
:references:
|
|
3401
|
+
- Kinematic Derivatives using the Elementary Transform
|
|
3402
|
+
Sequence, J. Haviland and P. Corke
|
|
3403
|
+
"""
|
|
3404
|
+
|
|
3405
|
+
q = getmatrix(q, (None, None))
|
|
3406
|
+
l, _ = q.shape # type: ignore
|
|
3407
|
+
end = self[-1]
|
|
3408
|
+
|
|
3409
|
+
if base is None:
|
|
3410
|
+
bases = None
|
|
3411
|
+
elif isinstance(base, SE2):
|
|
3412
|
+
bases = np.array(base.A)
|
|
3413
|
+
elif np.array_equal(base, np.eye(3)): # pragma: nocover
|
|
3414
|
+
bases = None
|
|
3415
|
+
else: # pragma: nocover
|
|
3416
|
+
bases = base
|
|
3417
|
+
|
|
3418
|
+
if tool is None:
|
|
3419
|
+
tools = None
|
|
3420
|
+
elif isinstance(tool, SE2):
|
|
3421
|
+
tools = np.array(tool.A)
|
|
3422
|
+
elif np.array_equal(tool, np.eye(3)): # pragma: nocover
|
|
3423
|
+
tools = None
|
|
3424
|
+
else: # pragma: nocover
|
|
3425
|
+
tools = tool
|
|
3426
|
+
|
|
3427
|
+
if l > 1:
|
|
3428
|
+
T = np.zeros((l, 3, 3), dtype=object)
|
|
3429
|
+
else:
|
|
3430
|
+
T = np.zeros((3, 3), dtype=object)
|
|
3431
|
+
|
|
3432
|
+
for k, qk in enumerate(q): # type: ignore
|
|
3433
|
+
link = end # start with last link
|
|
3434
|
+
|
|
3435
|
+
jindex = 0 if link.jindex is None and link.isjoint else link.jindex
|
|
3436
|
+
Tk = link.A(qk[jindex])
|
|
3437
|
+
|
|
3438
|
+
if tools is not None:
|
|
3439
|
+
Tk = Tk @ tools
|
|
3440
|
+
|
|
3441
|
+
# add remaining links, back toward the base
|
|
3442
|
+
for i in range(self.m - 2, -1, -1):
|
|
3443
|
+
link = self.data[i]
|
|
3444
|
+
|
|
3445
|
+
jindex = 0 if link.jindex is None and link.isjoint else link.jindex
|
|
3446
|
+
A = link.A(qk[jindex])
|
|
3447
|
+
|
|
3448
|
+
if A is not None:
|
|
3449
|
+
Tk = A @ Tk
|
|
3450
|
+
|
|
3451
|
+
# add base transform if it is set
|
|
3452
|
+
if include_base is True and bases is not None:
|
|
3453
|
+
Tk = bases @ Tk
|
|
3454
|
+
|
|
3455
|
+
# append
|
|
3456
|
+
if l > 1:
|
|
3457
|
+
T[k, :, :] = Tk
|
|
3458
|
+
# ret.append(SE2(Tk, check=False)) # type: ignore
|
|
3459
|
+
else:
|
|
3460
|
+
T = Tk
|
|
3461
|
+
# ret = SE2(Tk, check=False)
|
|
3462
|
+
|
|
3463
|
+
return T
|
|
3464
|
+
|
|
3465
|
+
def jacob0(
|
|
3466
|
+
self,
|
|
3467
|
+
q: ArrayLike,
|
|
3468
|
+
) -> NDArray:
|
|
3469
|
+
# very inefficient implementation, just put a 1 in last row
|
|
3470
|
+
# if its a rotation joint
|
|
3471
|
+
q = getvector(q)
|
|
3472
|
+
|
|
3473
|
+
j = 0
|
|
3474
|
+
J = np.zeros((3, self.n))
|
|
3475
|
+
etjoints = self.joint_idx()
|
|
3476
|
+
|
|
3477
|
+
if not np.all(np.array([self[i].jindex for i in etjoints])):
|
|
3478
|
+
# not all joints have a jindex it is required, set them
|
|
3479
|
+
for j in range(self.n):
|
|
3480
|
+
i = etjoints[j]
|
|
3481
|
+
self[i].jindex = j
|
|
3482
|
+
|
|
3483
|
+
for j in range(self.n):
|
|
3484
|
+
i = etjoints[j]
|
|
3485
|
+
|
|
3486
|
+
if self[i].jindex is not None:
|
|
3487
|
+
jindex = self[i].jindex
|
|
3488
|
+
else:
|
|
3489
|
+
jindex = 0 # pragma: nocover
|
|
3490
|
+
|
|
3491
|
+
# jindex = 0 if self[i].jindex is None else self[i].jindex
|
|
3492
|
+
|
|
3493
|
+
axis = self[i].axis
|
|
3494
|
+
if axis == "R":
|
|
3495
|
+
dTdq = np.array([[0, -1, 0], [1, 0, 0], [0, 0, 0]]) @ self[i].A(
|
|
3496
|
+
q[jindex] # type: ignore
|
|
3497
|
+
)
|
|
3498
|
+
elif axis == "tx":
|
|
3499
|
+
dTdq = np.array([[0, 0, 1], [0, 0, 0], [0, 0, 0]])
|
|
3500
|
+
elif axis == "ty":
|
|
3501
|
+
dTdq = np.array([[0, 0, 0], [0, 0, 1], [0, 0, 0]])
|
|
3502
|
+
else: # pragma: nocover
|
|
3503
|
+
raise TypeError("Invalid axes")
|
|
3504
|
+
|
|
3505
|
+
E0 = ETS2(self[:i])
|
|
3506
|
+
if len(E0) > 0:
|
|
3507
|
+
dTdq = E0.fkine(q).A @ dTdq
|
|
3508
|
+
|
|
3509
|
+
Ef = ETS2(self[i + 1 :])
|
|
3510
|
+
if len(Ef) > 0:
|
|
3511
|
+
dTdq = dTdq @ Ef.fkine(q).A
|
|
3512
|
+
|
|
3513
|
+
T = self.fkine(q).A
|
|
3514
|
+
dRdt = dTdq[:2, :2] @ T[:2, :2].T
|
|
3515
|
+
|
|
3516
|
+
J[:2, j] = dTdq[:2, 2]
|
|
3517
|
+
J[2, j] = dRdt[1, 0]
|
|
3518
|
+
|
|
3519
|
+
return J
|
|
3520
|
+
|
|
3521
|
+
def jacobe(
|
|
3522
|
+
self,
|
|
3523
|
+
q: ArrayLike,
|
|
3524
|
+
):
|
|
3525
|
+
r"""
|
|
3526
|
+
Jacobian in base frame
|
|
3527
|
+
|
|
3528
|
+
:param q: joint coordinates
|
|
3529
|
+
:type q: ArrayLike
|
|
3530
|
+
:return: Jacobian matrix
|
|
3531
|
+
|
|
3532
|
+
``jacobe(q)`` is the manipulator Jacobian matrix which maps joint
|
|
3533
|
+
velocity to end-effector spatial velocity.
|
|
3534
|
+
|
|
3535
|
+
End-effector spatial velocity :math:`\nu = (v_x, v_y, v_z, \omega_x, \omega_y, \omega_z)^T`
|
|
3536
|
+
is related to joint velocity by :math:`{}^{e}\nu = {}^{e}\mathbf{J}_0(q) \dot{q}`.
|
|
3537
|
+
|
|
3538
|
+
:seealso: :func:`jacob`, :func:`hessian0`
|
|
3539
|
+
""" # noqa
|
|
3540
|
+
|
|
3541
|
+
T = self.fkine(q, include_base=False).A
|
|
3542
|
+
return tr2jac2(T.T) @ self.jacob0(q)
|