roboticstoolbox-python 1.3.0__cp312-cp312-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.cp312-win_amd64.pyd +0 -0
- roboticstoolbox/frne.cp312-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,1976 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
@author (Original) Matthew Matl, Github: mmatl
|
|
4
|
+
@author (Adapted by) Jesse Haviland
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import roboticstoolbox as rtb
|
|
9
|
+
import spatialgeometry as gm
|
|
10
|
+
import copy
|
|
11
|
+
import os
|
|
12
|
+
import xml.etree.ElementTree as ETT
|
|
13
|
+
from spatialmath import SE3
|
|
14
|
+
from spatialmath.base import unitvec_norm, angvec2r, tr2rpy
|
|
15
|
+
|
|
16
|
+
from io import BytesIO
|
|
17
|
+
from roboticstoolbox.tools.data import rtb_path_to_datafile
|
|
18
|
+
from pathlib import PurePosixPath
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
from .utils import parse_origin, configure_origin
|
|
22
|
+
|
|
23
|
+
# Global variable for the base path of the robot meshes
|
|
24
|
+
_base_path = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class URDFType(object):
|
|
28
|
+
"""Abstract base class for all URDF types.
|
|
29
|
+
This has useful class methods for automatic parsing/unparsing
|
|
30
|
+
of XML trees.
|
|
31
|
+
There are three overridable class variables:
|
|
32
|
+
- ``_ATTRIBS`` - This is a dictionary mapping attribute names to a tuple,
|
|
33
|
+
``(type, required)`` where ``type`` is the Python type for the
|
|
34
|
+
attribute and ``required`` is a boolean stating whether the attribute
|
|
35
|
+
is required to be present.
|
|
36
|
+
- ``_ELEMENTS`` - This is a dictionary mapping element names to a tuple,
|
|
37
|
+
``(type, required, multiple)`` where ``type`` is the Python type for the
|
|
38
|
+
element, ``required`` is a boolean stating whether the element
|
|
39
|
+
is required to be present, and ``multiple`` is a boolean indicating
|
|
40
|
+
whether multiple elements of this type could be present.
|
|
41
|
+
Elements are child nodes in the XML tree, and their type must be a
|
|
42
|
+
subclass of :class:`.URDFType`.
|
|
43
|
+
- ``_TAG`` - This is a string that represents the XML tag for the node
|
|
44
|
+
containing this type of object.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
_ATTRIBS = {} # Map from attrib name to (type, required)
|
|
48
|
+
_ELEMENTS = {} # Map from element name to (type, required, multiple)
|
|
49
|
+
_TAG = "" # XML tag for this element
|
|
50
|
+
|
|
51
|
+
def __init__(self): # pragma nocover
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def _parse_attrib(cls, val_type, val):
|
|
56
|
+
"""Parse an XML attribute into a python value.
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
val_type : :class:`type`
|
|
60
|
+
The type of value to create.
|
|
61
|
+
val : :class:`object`
|
|
62
|
+
The value to parse.
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
val : :class:`object`
|
|
66
|
+
The parsed attribute.
|
|
67
|
+
"""
|
|
68
|
+
if val_type == np.ndarray:
|
|
69
|
+
val = np.fromstring(val, sep=" ")
|
|
70
|
+
else:
|
|
71
|
+
val = val_type(val)
|
|
72
|
+
return val
|
|
73
|
+
|
|
74
|
+
@classmethod
|
|
75
|
+
def _parse_simple_attribs(cls, node):
|
|
76
|
+
"""Parse all attributes in the _ATTRIBS array for this class.
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
node : :class:`lxml.etree.Element`
|
|
80
|
+
The node to parse attributes for.
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
kwargs : dict
|
|
84
|
+
Map from attribute name to value. If the attribute is not
|
|
85
|
+
required and is not present, that attribute's name will map to
|
|
86
|
+
``None``.
|
|
87
|
+
"""
|
|
88
|
+
kwargs = {}
|
|
89
|
+
for a in cls._ATTRIBS:
|
|
90
|
+
t, r = cls._ATTRIBS[a] # t = type, r = required (bool)
|
|
91
|
+
if r:
|
|
92
|
+
try:
|
|
93
|
+
v = cls._parse_attrib(t, node.attrib[a])
|
|
94
|
+
except Exception: # pragma nocover
|
|
95
|
+
raise ValueError(
|
|
96
|
+
"Missing required attribute {} when parsing an object "
|
|
97
|
+
"of type {}".format(a, cls.__name__)
|
|
98
|
+
)
|
|
99
|
+
else:
|
|
100
|
+
v = None
|
|
101
|
+
if a in node.attrib:
|
|
102
|
+
v = cls._parse_attrib(t, node.attrib[a])
|
|
103
|
+
kwargs[a] = v
|
|
104
|
+
return kwargs
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def _parse_simple_elements(cls, node, path):
|
|
108
|
+
"""Parse all elements in the _ELEMENTS array from the children of
|
|
109
|
+
this node.
|
|
110
|
+
Parameters
|
|
111
|
+
----------
|
|
112
|
+
node : :class:`lxml.etree.Element`
|
|
113
|
+
The node to parse children for.
|
|
114
|
+
path : str
|
|
115
|
+
The string path where the XML file is located (used for resolving
|
|
116
|
+
the location of mesh or image files).
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
kwargs : dict
|
|
120
|
+
Map from element names to the :class:`URDFType` subclass (or list,
|
|
121
|
+
if ``multiple`` was set) created for that element.
|
|
122
|
+
"""
|
|
123
|
+
kwargs = {}
|
|
124
|
+
for a in cls._ELEMENTS:
|
|
125
|
+
t, r, m = cls._ELEMENTS[a]
|
|
126
|
+
if not m:
|
|
127
|
+
v = node.find(t._TAG)
|
|
128
|
+
if r or v is not None:
|
|
129
|
+
v = t._from_xml(v, path)
|
|
130
|
+
else:
|
|
131
|
+
vs = node.findall(t._TAG)
|
|
132
|
+
if len(vs) == 0 and r: # pragma nocover
|
|
133
|
+
raise ValueError(
|
|
134
|
+
"Missing required subelement(s) of type {} when "
|
|
135
|
+
"parsing an object of type {}".format(t.__name__, cls.__name__)
|
|
136
|
+
)
|
|
137
|
+
v = [t._from_xml(n, path) for n in vs]
|
|
138
|
+
kwargs[a] = v
|
|
139
|
+
return kwargs
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def _parse(cls, node, path):
|
|
143
|
+
"""Parse all elements and attributes in the _ELEMENTS and _ATTRIBS
|
|
144
|
+
arrays for a node.
|
|
145
|
+
Parameters
|
|
146
|
+
----------
|
|
147
|
+
node : :class:`lxml.etree.Element`
|
|
148
|
+
The node to parse.
|
|
149
|
+
path : str
|
|
150
|
+
The string path where the XML file is located (used for resolving
|
|
151
|
+
the location of mesh or image files).
|
|
152
|
+
Returns
|
|
153
|
+
-------
|
|
154
|
+
kwargs : dict
|
|
155
|
+
Map from names to Python classes created from the attributes
|
|
156
|
+
and elements in the class arrays.
|
|
157
|
+
"""
|
|
158
|
+
kwargs = cls._parse_simple_attribs(node)
|
|
159
|
+
kwargs.update(cls._parse_simple_elements(node, path))
|
|
160
|
+
return kwargs
|
|
161
|
+
|
|
162
|
+
@classmethod
|
|
163
|
+
def _from_xml(cls, node, path):
|
|
164
|
+
"""Create an instance of this class from an XML node.
|
|
165
|
+
Parameters
|
|
166
|
+
----------
|
|
167
|
+
node : :class:`lxml.etree.Element`
|
|
168
|
+
The node to parse.
|
|
169
|
+
path : str
|
|
170
|
+
The string path where the XML file is located (used for resolving
|
|
171
|
+
the location of mesh or image files).
|
|
172
|
+
Returns
|
|
173
|
+
-------
|
|
174
|
+
obj : :class:`URDFType`
|
|
175
|
+
An instance of this class parsed from the node.
|
|
176
|
+
"""
|
|
177
|
+
return cls(**cls._parse(node, path))
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
###############################################################################
|
|
181
|
+
# Link types
|
|
182
|
+
###############################################################################
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class Box(URDFType):
|
|
186
|
+
"""A rectangular prism whose center is at the local origin.
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
size : (3,) float
|
|
190
|
+
The length, width, and height of the box in meters.
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
_ATTRIBS = {"size": (np.ndarray, True)}
|
|
194
|
+
_TAG = "box"
|
|
195
|
+
|
|
196
|
+
def __init__(self, size):
|
|
197
|
+
self.size = size
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def size(self):
|
|
201
|
+
"""(3,) float : The length, width, and height of the box in meters."""
|
|
202
|
+
return self._size
|
|
203
|
+
|
|
204
|
+
@size.setter
|
|
205
|
+
def size(self, value):
|
|
206
|
+
self._size = np.asanyarray(value).astype(np.float64)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class Cylinder(URDFType):
|
|
210
|
+
"""A cylinder whose center is at the local origin.
|
|
211
|
+
Parameters
|
|
212
|
+
----------
|
|
213
|
+
radius : float
|
|
214
|
+
The radius of the cylinder in meters.
|
|
215
|
+
length : float
|
|
216
|
+
The length of the cylinder in meters.
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
_ATTRIBS = {
|
|
220
|
+
"radius": (float, True),
|
|
221
|
+
"length": (float, True),
|
|
222
|
+
}
|
|
223
|
+
_TAG = "cylinder"
|
|
224
|
+
|
|
225
|
+
def __init__(self, radius, length):
|
|
226
|
+
self.radius = radius
|
|
227
|
+
self.length = length
|
|
228
|
+
|
|
229
|
+
@property
|
|
230
|
+
def radius(self):
|
|
231
|
+
"""float : The radius of the cylinder in meters."""
|
|
232
|
+
return self._radius
|
|
233
|
+
|
|
234
|
+
@radius.setter
|
|
235
|
+
def radius(self, value):
|
|
236
|
+
self._radius = float(value)
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def length(self):
|
|
240
|
+
"""float : The length of the cylinder in meters."""
|
|
241
|
+
return self._length
|
|
242
|
+
|
|
243
|
+
@length.setter
|
|
244
|
+
def length(self, value):
|
|
245
|
+
self._length = float(value)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class Sphere(URDFType):
|
|
249
|
+
"""A sphere whose center is at the local origin.
|
|
250
|
+
Parameters
|
|
251
|
+
----------
|
|
252
|
+
radius : float
|
|
253
|
+
The radius of the sphere in meters.
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
_ATTRIBS = {
|
|
257
|
+
"radius": (float, True),
|
|
258
|
+
}
|
|
259
|
+
_TAG = "sphere"
|
|
260
|
+
|
|
261
|
+
def __init__(self, radius):
|
|
262
|
+
self.radius = radius
|
|
263
|
+
|
|
264
|
+
@property
|
|
265
|
+
def radius(self):
|
|
266
|
+
"""float : The radius of the sphere in meters."""
|
|
267
|
+
return self._radius
|
|
268
|
+
|
|
269
|
+
@radius.setter
|
|
270
|
+
def radius(self, value):
|
|
271
|
+
self._radius = float(value)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
class Mesh(URDFType):
|
|
275
|
+
"""A triangular mesh object.
|
|
276
|
+
Parameters
|
|
277
|
+
----------
|
|
278
|
+
filename : str
|
|
279
|
+
The path to the mesh that contains this object. This can be
|
|
280
|
+
relative to the top-level URDF or an absolute path.
|
|
281
|
+
scale : (3,) float, optional
|
|
282
|
+
The scaling value for the mesh along the XYZ axes.
|
|
283
|
+
If ``None``, assumes no scale is applied.
|
|
284
|
+
"""
|
|
285
|
+
|
|
286
|
+
_ATTRIBS = {"filename": (str, True), "scale": (np.ndarray, False)}
|
|
287
|
+
_TAG = "mesh"
|
|
288
|
+
|
|
289
|
+
def __init__(self, filename, scale=None):
|
|
290
|
+
self.filename = filename
|
|
291
|
+
self.scale = scale
|
|
292
|
+
|
|
293
|
+
@property
|
|
294
|
+
def filename(self):
|
|
295
|
+
"""str : The path to the mesh file for this object."""
|
|
296
|
+
return self._filename
|
|
297
|
+
|
|
298
|
+
@filename.setter
|
|
299
|
+
def filename(self, value):
|
|
300
|
+
|
|
301
|
+
global _base_path
|
|
302
|
+
|
|
303
|
+
if value.startswith("package://"):
|
|
304
|
+
value = value.replace("package://", "")
|
|
305
|
+
elif value.startswith("file://"):
|
|
306
|
+
value = value.replace("file://", "")
|
|
307
|
+
|
|
308
|
+
if _base_path is None:
|
|
309
|
+
value = rtb_path_to_datafile("xacro", value)
|
|
310
|
+
else:
|
|
311
|
+
value = _base_path / PurePosixPath(value)
|
|
312
|
+
|
|
313
|
+
self._filename = str(value)
|
|
314
|
+
|
|
315
|
+
@property
|
|
316
|
+
def scale(self):
|
|
317
|
+
"""(3,) float : A scaling for the mesh along its local XYZ axes."""
|
|
318
|
+
return self._scale
|
|
319
|
+
|
|
320
|
+
@scale.setter
|
|
321
|
+
def scale(self, value):
|
|
322
|
+
if value is not None:
|
|
323
|
+
value = np.asanyarray(value).astype(np.float64)
|
|
324
|
+
self._scale = value
|
|
325
|
+
|
|
326
|
+
@classmethod
|
|
327
|
+
def _from_xml(cls, node, path):
|
|
328
|
+
kwargs = cls._parse(node, path)
|
|
329
|
+
return Mesh(**kwargs)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
class Material(URDFType):
|
|
333
|
+
"""A material for some geometry.
|
|
334
|
+
Parameters
|
|
335
|
+
----------
|
|
336
|
+
name : str
|
|
337
|
+
The name of the material.
|
|
338
|
+
color : (4,) float, optional
|
|
339
|
+
The RGBA color of the material in the range [0,1].
|
|
340
|
+
texture : :class:`.Texture`, optional
|
|
341
|
+
A texture for the material.
|
|
342
|
+
"""
|
|
343
|
+
|
|
344
|
+
_ATTRIBS = {"name": (str, True)}
|
|
345
|
+
_ELEMENTS = {}
|
|
346
|
+
_TAG = "material"
|
|
347
|
+
|
|
348
|
+
def __init__(self, name, color=None, texture=None):
|
|
349
|
+
# if color is None:
|
|
350
|
+
# color = name
|
|
351
|
+
|
|
352
|
+
self.name = name
|
|
353
|
+
self.color = color
|
|
354
|
+
self.texture = texture
|
|
355
|
+
|
|
356
|
+
@classmethod
|
|
357
|
+
def _from_xml(cls, node, path): # pragma nocover
|
|
358
|
+
kwargs = cls._parse(node, path)
|
|
359
|
+
|
|
360
|
+
# Extract the color -- it's weirdly an attribute of a subelement
|
|
361
|
+
color = node.find("color")
|
|
362
|
+
if color is not None:
|
|
363
|
+
color = np.fromstring(color.attrib["rgba"], sep=" ", dtype=np.float64)
|
|
364
|
+
kwargs["color"] = color
|
|
365
|
+
|
|
366
|
+
return Material(**kwargs)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
class Geometry(URDFType):
|
|
370
|
+
"""A wrapper for all geometry types.
|
|
371
|
+
Only one of the following values can be set, all others should be set
|
|
372
|
+
to ``None``.
|
|
373
|
+
Parameters
|
|
374
|
+
----------
|
|
375
|
+
box : :class:`.Box`, optional
|
|
376
|
+
Box geometry.
|
|
377
|
+
cylinder : :class:`.Cylinder`
|
|
378
|
+
Cylindrical geometry.
|
|
379
|
+
sphere : :class:`.Sphere`
|
|
380
|
+
Spherical geometry.
|
|
381
|
+
mesh : :class:`.Mesh`
|
|
382
|
+
Mesh geometry.
|
|
383
|
+
"""
|
|
384
|
+
|
|
385
|
+
_ELEMENTS = {
|
|
386
|
+
"box": (Box, False, False),
|
|
387
|
+
"cylinder": (Cylinder, False, False),
|
|
388
|
+
"sphere": (Sphere, False, False),
|
|
389
|
+
"mesh": (Mesh, False, False),
|
|
390
|
+
}
|
|
391
|
+
_TAG = "geometry"
|
|
392
|
+
|
|
393
|
+
def __init__(self, box=None, cylinder=None, sphere=None, mesh=None):
|
|
394
|
+
if (
|
|
395
|
+
box is None and cylinder is None and sphere is None and mesh is None
|
|
396
|
+
): # pragma nocover
|
|
397
|
+
raise ValueError("At least one geometry element must be set")
|
|
398
|
+
|
|
399
|
+
if box is not None:
|
|
400
|
+
self.box = box
|
|
401
|
+
self.ob = gm.Cuboid(box.size)
|
|
402
|
+
|
|
403
|
+
if cylinder is not None:
|
|
404
|
+
self.cylinder = cylinder
|
|
405
|
+
self.ob = gm.Cylinder(cylinder.radius, cylinder.length)
|
|
406
|
+
|
|
407
|
+
if sphere is not None:
|
|
408
|
+
self.sphere = sphere
|
|
409
|
+
self.ob = gm.Sphere(sphere.radius)
|
|
410
|
+
|
|
411
|
+
if mesh is not None:
|
|
412
|
+
self.mesh = mesh
|
|
413
|
+
self.ob = gm.Mesh(mesh.filename, scale=mesh.scale)
|
|
414
|
+
|
|
415
|
+
@property
|
|
416
|
+
def box(self):
|
|
417
|
+
""":class:`.Box` : Box geometry."""
|
|
418
|
+
return self._box
|
|
419
|
+
|
|
420
|
+
@box.setter
|
|
421
|
+
def box(self, value):
|
|
422
|
+
if value is not None and not isinstance(value, Box): # pragma nocover
|
|
423
|
+
raise TypeError("Expected Box type")
|
|
424
|
+
self._box = value
|
|
425
|
+
|
|
426
|
+
@property
|
|
427
|
+
def cylinder(self):
|
|
428
|
+
""":class:`.Cylinder` : Cylinder geometry."""
|
|
429
|
+
return self._cylinder
|
|
430
|
+
|
|
431
|
+
@cylinder.setter
|
|
432
|
+
def cylinder(self, value):
|
|
433
|
+
if value is not None and not isinstance(value, Cylinder):
|
|
434
|
+
raise TypeError("Expected Cylinder type") # pragma nocover
|
|
435
|
+
self._cylinder = value
|
|
436
|
+
|
|
437
|
+
@property
|
|
438
|
+
def sphere(self):
|
|
439
|
+
""":class:`.Sphere` : Spherical geometry."""
|
|
440
|
+
return self._sphere
|
|
441
|
+
|
|
442
|
+
@sphere.setter
|
|
443
|
+
def sphere(self, value):
|
|
444
|
+
if value is not None and not isinstance(value, Sphere):
|
|
445
|
+
raise TypeError("Expected Sphere type") # pragma nocover
|
|
446
|
+
self._sphere = value
|
|
447
|
+
|
|
448
|
+
@property
|
|
449
|
+
def mesh(self):
|
|
450
|
+
""":class:`.Mesh` : Mesh geometry."""
|
|
451
|
+
return self._mesh
|
|
452
|
+
|
|
453
|
+
@mesh.setter
|
|
454
|
+
def mesh(self, value):
|
|
455
|
+
if value is not None and not isinstance(value, Mesh):
|
|
456
|
+
raise TypeError("Expected Mesh type") # pragma nocover
|
|
457
|
+
self._mesh = value
|
|
458
|
+
|
|
459
|
+
@property
|
|
460
|
+
def geometry(self): # pragma nocover
|
|
461
|
+
""":class:`.Box`, :class:`.Cylinder`, :class:`.Sphere`, or
|
|
462
|
+
:class:`.Mesh` : The valid geometry element.
|
|
463
|
+
"""
|
|
464
|
+
if self.box is not None:
|
|
465
|
+
return self.box
|
|
466
|
+
if self.cylinder is not None:
|
|
467
|
+
return self.cylinder
|
|
468
|
+
if self.sphere is not None:
|
|
469
|
+
return self.sphere
|
|
470
|
+
if self.mesh is not None:
|
|
471
|
+
return self.mesh
|
|
472
|
+
return None
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
class Collision(URDFType):
|
|
476
|
+
"""Collision properties of a link.
|
|
477
|
+
Parameters
|
|
478
|
+
----------
|
|
479
|
+
geometry : :class:`.Geometry`
|
|
480
|
+
The geometry of the element
|
|
481
|
+
name : str, optional
|
|
482
|
+
The name of the collision geometry.
|
|
483
|
+
origin : (4,4) float, optional
|
|
484
|
+
The pose of the collision element relative to the link frame.
|
|
485
|
+
Defaults to identity.
|
|
486
|
+
"""
|
|
487
|
+
|
|
488
|
+
_ATTRIBS = {"name": (str, False)}
|
|
489
|
+
_ELEMENTS = {
|
|
490
|
+
"geometry": (Geometry, True, False),
|
|
491
|
+
}
|
|
492
|
+
_TAG = "collision"
|
|
493
|
+
|
|
494
|
+
def __init__(self, name, origin, geometry):
|
|
495
|
+
self.geometry = geometry
|
|
496
|
+
self.name = name
|
|
497
|
+
self.origin = origin
|
|
498
|
+
self.geometry.ob.T = origin
|
|
499
|
+
|
|
500
|
+
@property
|
|
501
|
+
def geometry(self):
|
|
502
|
+
""":class:`.Geometry` : The geometry of this element."""
|
|
503
|
+
return self._geometry
|
|
504
|
+
|
|
505
|
+
@geometry.setter
|
|
506
|
+
def geometry(self, value):
|
|
507
|
+
if not isinstance(value, Geometry): # pragma nocover
|
|
508
|
+
raise TypeError("Must set geometry with Geometry object")
|
|
509
|
+
self._geometry = value
|
|
510
|
+
|
|
511
|
+
@property
|
|
512
|
+
def name(self):
|
|
513
|
+
"""str : The name of this collision element."""
|
|
514
|
+
return self._name
|
|
515
|
+
|
|
516
|
+
@name.setter
|
|
517
|
+
def name(self, value):
|
|
518
|
+
if value is not None:
|
|
519
|
+
value = str(value)
|
|
520
|
+
self._name = value
|
|
521
|
+
|
|
522
|
+
@property
|
|
523
|
+
def origin(self):
|
|
524
|
+
"""(4,4) float : The pose of this element relative to the link frame."""
|
|
525
|
+
return self._origin
|
|
526
|
+
|
|
527
|
+
@origin.setter
|
|
528
|
+
def origin(self, value):
|
|
529
|
+
self._origin = configure_origin(value)
|
|
530
|
+
|
|
531
|
+
@classmethod
|
|
532
|
+
def _from_xml(cls, node, path):
|
|
533
|
+
kwargs = cls._parse(node, path)
|
|
534
|
+
kwargs["origin"], _ = parse_origin(node)
|
|
535
|
+
return Collision(**kwargs)
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
class Visual(URDFType):
|
|
539
|
+
"""Visual properties of a link.
|
|
540
|
+
Parameters
|
|
541
|
+
----------
|
|
542
|
+
geometry : :class:`.Geometry`
|
|
543
|
+
The geometry of the element
|
|
544
|
+
name : str, optional
|
|
545
|
+
The name of the visual geometry.
|
|
546
|
+
origin : (4,4) float, optional
|
|
547
|
+
The pose of the visual element relative to the link frame.
|
|
548
|
+
Defaults to identity.
|
|
549
|
+
material : :class:`.Material`, optional
|
|
550
|
+
The material of the element.
|
|
551
|
+
"""
|
|
552
|
+
|
|
553
|
+
_ATTRIBS = {"name": (str, False)}
|
|
554
|
+
_ELEMENTS = {
|
|
555
|
+
"geometry": (Geometry, True, False),
|
|
556
|
+
"material": (Material, False, False),
|
|
557
|
+
}
|
|
558
|
+
_TAG = "visual"
|
|
559
|
+
|
|
560
|
+
def __init__(self, geometry, name=None, origin=None, material=None):
|
|
561
|
+
self.geometry = geometry
|
|
562
|
+
geometry.ob.T = origin
|
|
563
|
+
self.name = name
|
|
564
|
+
self.origin = origin
|
|
565
|
+
self.material = material
|
|
566
|
+
|
|
567
|
+
# Do not set material color yet. The top level URDF colors have not
|
|
568
|
+
# been parsed/defined yet so we do not know what 'Grey' or 'Blue2'
|
|
569
|
+
# mean yet. We set colors after these top level definitions come in
|
|
570
|
+
|
|
571
|
+
# Do set it if the color was defined in line by the URDF
|
|
572
|
+
if material is not None and material.color is not None:
|
|
573
|
+
self.geometry.ob.color = material.color
|
|
574
|
+
|
|
575
|
+
@property
|
|
576
|
+
def geometry(self):
|
|
577
|
+
""":class:`.Geometry` : The geometry of this element."""
|
|
578
|
+
return self._geometry
|
|
579
|
+
|
|
580
|
+
@geometry.setter
|
|
581
|
+
def geometry(self, value):
|
|
582
|
+
if not isinstance(value, Geometry): # pragma nocover
|
|
583
|
+
raise TypeError("Must set geometry with Geometry object")
|
|
584
|
+
self._geometry = value
|
|
585
|
+
|
|
586
|
+
@property
|
|
587
|
+
def name(self):
|
|
588
|
+
"""str : The name of this visual element."""
|
|
589
|
+
return self._name
|
|
590
|
+
|
|
591
|
+
@name.setter
|
|
592
|
+
def name(self, value):
|
|
593
|
+
if value is not None:
|
|
594
|
+
value = str(value)
|
|
595
|
+
self._name = value
|
|
596
|
+
|
|
597
|
+
@property
|
|
598
|
+
def origin(self):
|
|
599
|
+
"""(4,4) float : The pose of this element relative to the link frame."""
|
|
600
|
+
return self._origin
|
|
601
|
+
|
|
602
|
+
@origin.setter
|
|
603
|
+
def origin(self, value):
|
|
604
|
+
self._origin = configure_origin(value)
|
|
605
|
+
|
|
606
|
+
@classmethod
|
|
607
|
+
def _from_xml(cls, node, path):
|
|
608
|
+
kwargs = cls._parse(node, path)
|
|
609
|
+
kwargs["origin"], _ = parse_origin(node)
|
|
610
|
+
return Visual(**kwargs)
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
class Inertial(URDFType):
|
|
614
|
+
"""The inertial properties of a link.
|
|
615
|
+
Parameters
|
|
616
|
+
----------
|
|
617
|
+
mass : float
|
|
618
|
+
The mass of the link in kilograms.
|
|
619
|
+
inertia : (3,3) float
|
|
620
|
+
The 3x3 symmetric rotational inertia matrix.
|
|
621
|
+
origin : (4,4) float, optional
|
|
622
|
+
The pose of the inertials relative to the link frame.
|
|
623
|
+
Defaults to identity if not specified.
|
|
624
|
+
"""
|
|
625
|
+
|
|
626
|
+
_TAG = "inertial"
|
|
627
|
+
|
|
628
|
+
def __init__(self, mass=None, inertia=None, origin=None):
|
|
629
|
+
self._mass = mass
|
|
630
|
+
self._inertia = inertia
|
|
631
|
+
self._origin = origin
|
|
632
|
+
|
|
633
|
+
@property
|
|
634
|
+
def mass(self):
|
|
635
|
+
"""float : The mass of the link in kilograms."""
|
|
636
|
+
return self._mass
|
|
637
|
+
|
|
638
|
+
@mass.setter
|
|
639
|
+
def mass(self, value):
|
|
640
|
+
self._mass = float(value)
|
|
641
|
+
|
|
642
|
+
@property
|
|
643
|
+
def inertia(self):
|
|
644
|
+
"""(3,3) float : The 3x3 symmetric rotational inertia matrix."""
|
|
645
|
+
return self._inertia
|
|
646
|
+
|
|
647
|
+
@inertia.setter
|
|
648
|
+
def inertia(self, value):
|
|
649
|
+
value = np.asanyarray(value).astype(np.float64)
|
|
650
|
+
if not np.allclose(value, value.T): # pragma nocover
|
|
651
|
+
raise ValueError("Inertia must be a symmetric matrix")
|
|
652
|
+
self._inertia = value
|
|
653
|
+
|
|
654
|
+
@property
|
|
655
|
+
def origin(self):
|
|
656
|
+
"""(4,4) float : The pose of the inertials relative to the link frame."""
|
|
657
|
+
return self._origin
|
|
658
|
+
|
|
659
|
+
@origin.setter
|
|
660
|
+
def origin(self, value):
|
|
661
|
+
self._origin = configure_origin(value)
|
|
662
|
+
|
|
663
|
+
@classmethod
|
|
664
|
+
def _from_xml(cls, node, path):
|
|
665
|
+
origin, _ = parse_origin(node)
|
|
666
|
+
mass = float(node.find("mass").attrib["value"])
|
|
667
|
+
n = node.find("inertia")
|
|
668
|
+
xx = float(n.attrib["ixx"])
|
|
669
|
+
xy = float(n.attrib["ixy"])
|
|
670
|
+
xz = float(n.attrib["ixz"])
|
|
671
|
+
yy = float(n.attrib["iyy"])
|
|
672
|
+
yz = float(n.attrib["iyz"])
|
|
673
|
+
zz = float(n.attrib["izz"])
|
|
674
|
+
inertia = np.array([[xx, xy, xz], [xy, yy, yz], [xz, yz, zz]], dtype=np.float64)
|
|
675
|
+
return Inertial(mass=mass, inertia=inertia, origin=origin)
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
###############################################################################
|
|
679
|
+
# Joint types
|
|
680
|
+
###############################################################################
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
class JointCalibration(URDFType): # pragma nocover
|
|
684
|
+
"""The reference positions of the joint.
|
|
685
|
+
Parameters
|
|
686
|
+
----------
|
|
687
|
+
rising : float, optional
|
|
688
|
+
When the joint moves in a positive direction, this position will
|
|
689
|
+
trigger a rising edge.
|
|
690
|
+
falling :
|
|
691
|
+
When the joint moves in a positive direction, this position will
|
|
692
|
+
trigger a falling edge.
|
|
693
|
+
"""
|
|
694
|
+
|
|
695
|
+
_ATTRIBS = {"rising": (float, False), "falling": (float, False)}
|
|
696
|
+
_TAG = "calibration"
|
|
697
|
+
|
|
698
|
+
def __init__(self, rising=None, falling=None):
|
|
699
|
+
self.rising = rising
|
|
700
|
+
self.falling = falling
|
|
701
|
+
|
|
702
|
+
@property
|
|
703
|
+
def rising(self):
|
|
704
|
+
"""float : description."""
|
|
705
|
+
return self._rising
|
|
706
|
+
|
|
707
|
+
@rising.setter
|
|
708
|
+
def rising(self, value):
|
|
709
|
+
if value is not None:
|
|
710
|
+
value = float(value)
|
|
711
|
+
self._rising = value
|
|
712
|
+
|
|
713
|
+
@property
|
|
714
|
+
def falling(self):
|
|
715
|
+
"""float : description."""
|
|
716
|
+
return self._falling
|
|
717
|
+
|
|
718
|
+
@falling.setter
|
|
719
|
+
def falling(self, value):
|
|
720
|
+
if value is not None:
|
|
721
|
+
value = float(value)
|
|
722
|
+
self._falling = value
|
|
723
|
+
|
|
724
|
+
def copy(self, prefix="", scale=None):
|
|
725
|
+
"""Create a deep copy of the visual with the prefix applied to all names.
|
|
726
|
+
Parameters
|
|
727
|
+
----------
|
|
728
|
+
prefix : str
|
|
729
|
+
A prefix to apply to all joint and link names.
|
|
730
|
+
Returns
|
|
731
|
+
-------
|
|
732
|
+
:class:`.JointCalibration`
|
|
733
|
+
A deep copy of the visual.
|
|
734
|
+
"""
|
|
735
|
+
return JointCalibration(
|
|
736
|
+
rising=self.rising,
|
|
737
|
+
falling=self.falling,
|
|
738
|
+
)
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
class JointDynamics(URDFType):
|
|
742
|
+
"""The dynamic properties of the joint.
|
|
743
|
+
Parameters
|
|
744
|
+
----------
|
|
745
|
+
damping : float
|
|
746
|
+
The damping value of the joint (Ns/m for prismatic joints,
|
|
747
|
+
Nms/rad for revolute).
|
|
748
|
+
friction : float
|
|
749
|
+
The static friction value of the joint (N for prismatic joints,
|
|
750
|
+
Nm for revolute).
|
|
751
|
+
"""
|
|
752
|
+
|
|
753
|
+
_ATTRIBS = {
|
|
754
|
+
"damping": (float, False),
|
|
755
|
+
"friction": (float, False),
|
|
756
|
+
}
|
|
757
|
+
_TAG = "dynamics"
|
|
758
|
+
|
|
759
|
+
def __init__(self, damping, friction):
|
|
760
|
+
self.damping = damping
|
|
761
|
+
self.friction = friction
|
|
762
|
+
|
|
763
|
+
@property
|
|
764
|
+
def damping(self): # pragma nocover
|
|
765
|
+
"""float : The damping value of the joint."""
|
|
766
|
+
return self._damping
|
|
767
|
+
|
|
768
|
+
@damping.setter
|
|
769
|
+
def damping(self, value):
|
|
770
|
+
if value is not None:
|
|
771
|
+
value = float(value)
|
|
772
|
+
self._damping = value
|
|
773
|
+
|
|
774
|
+
@property
|
|
775
|
+
def friction(self):
|
|
776
|
+
"""float : The static friction value of the joint."""
|
|
777
|
+
return self._friction
|
|
778
|
+
|
|
779
|
+
@friction.setter
|
|
780
|
+
def friction(self, value):
|
|
781
|
+
if value is not None:
|
|
782
|
+
value = float(value)
|
|
783
|
+
self._friction = value
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
class JointLimit(URDFType):
|
|
787
|
+
"""The limits of the joint.
|
|
788
|
+
Parameters
|
|
789
|
+
----------
|
|
790
|
+
effort : float
|
|
791
|
+
The maximum joint effort (N for prismatic joints, Nm for revolute).
|
|
792
|
+
velocity : float
|
|
793
|
+
The maximum joint velocity (m/s for prismatic joints, rad/s for
|
|
794
|
+
revolute).
|
|
795
|
+
lower : float, optional
|
|
796
|
+
The lower joint limit (m for prismatic joints, rad for revolute).
|
|
797
|
+
upper : float, optional
|
|
798
|
+
The upper joint limit (m for prismatic joints, rad for revolute).
|
|
799
|
+
"""
|
|
800
|
+
|
|
801
|
+
_ATTRIBS = {
|
|
802
|
+
"effort": (float, True),
|
|
803
|
+
"velocity": (float, True),
|
|
804
|
+
"lower": (float, False),
|
|
805
|
+
"upper": (float, False),
|
|
806
|
+
}
|
|
807
|
+
_TAG = "limit"
|
|
808
|
+
|
|
809
|
+
def __init__(self, effort, velocity, lower=None, upper=None):
|
|
810
|
+
self.effort = effort
|
|
811
|
+
self.velocity = velocity
|
|
812
|
+
self.lower = lower
|
|
813
|
+
self.upper = upper
|
|
814
|
+
|
|
815
|
+
@property
|
|
816
|
+
def effort(self):
|
|
817
|
+
"""float : The maximum joint effort."""
|
|
818
|
+
return self._effort
|
|
819
|
+
|
|
820
|
+
@effort.setter
|
|
821
|
+
def effort(self, value):
|
|
822
|
+
self._effort = float(value)
|
|
823
|
+
|
|
824
|
+
@property
|
|
825
|
+
def velocity(self):
|
|
826
|
+
"""float : The maximum joint velocity."""
|
|
827
|
+
return self._velocity
|
|
828
|
+
|
|
829
|
+
@velocity.setter
|
|
830
|
+
def velocity(self, value):
|
|
831
|
+
self._velocity = float(value)
|
|
832
|
+
|
|
833
|
+
@property
|
|
834
|
+
def lower(self):
|
|
835
|
+
"""float : The lower joint limit."""
|
|
836
|
+
return self._lower
|
|
837
|
+
|
|
838
|
+
@lower.setter
|
|
839
|
+
def lower(self, value):
|
|
840
|
+
if value is not None:
|
|
841
|
+
value = float(value)
|
|
842
|
+
self._lower = value
|
|
843
|
+
|
|
844
|
+
@property
|
|
845
|
+
def upper(self):
|
|
846
|
+
"""float : The upper joint limit."""
|
|
847
|
+
return self._upper
|
|
848
|
+
|
|
849
|
+
@upper.setter
|
|
850
|
+
def upper(self, value):
|
|
851
|
+
if value is not None:
|
|
852
|
+
value = float(value)
|
|
853
|
+
self._upper = value
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
class JointMimic(URDFType): # pragma nocover
|
|
857
|
+
"""A mimicry tag for a joint, which forces its configuration to
|
|
858
|
+
mimic another joint's.
|
|
859
|
+
This joint's configuration value is set equal to
|
|
860
|
+
``multiplier * other_joint_cfg + offset``.
|
|
861
|
+
Parameters
|
|
862
|
+
----------
|
|
863
|
+
joint : str
|
|
864
|
+
The name of the joint to mimic.
|
|
865
|
+
multiplier : float
|
|
866
|
+
The joint configuration multiplier. Defaults to 1.0.
|
|
867
|
+
offset : float, optional
|
|
868
|
+
The joint configuration offset. Defaults to 0.0.
|
|
869
|
+
"""
|
|
870
|
+
|
|
871
|
+
_ATTRIBS = {
|
|
872
|
+
"joint": (str, True),
|
|
873
|
+
"multiplier": (float, False),
|
|
874
|
+
"offset": (float, False),
|
|
875
|
+
}
|
|
876
|
+
_TAG = "mimic"
|
|
877
|
+
|
|
878
|
+
def __init__(self, joint, multiplier=None, offset=None):
|
|
879
|
+
self.joint = joint
|
|
880
|
+
self.multiplier = multiplier
|
|
881
|
+
self.offset = offset
|
|
882
|
+
|
|
883
|
+
@property
|
|
884
|
+
def joint(self):
|
|
885
|
+
"""float : The name of the joint to mimic."""
|
|
886
|
+
return self._joint
|
|
887
|
+
|
|
888
|
+
@joint.setter
|
|
889
|
+
def joint(self, value):
|
|
890
|
+
self._joint = str(value)
|
|
891
|
+
|
|
892
|
+
@property
|
|
893
|
+
def multiplier(self):
|
|
894
|
+
"""float : The multiplier for the joint configuration."""
|
|
895
|
+
return self._multiplier
|
|
896
|
+
|
|
897
|
+
@multiplier.setter
|
|
898
|
+
def multiplier(self, value):
|
|
899
|
+
if value is not None:
|
|
900
|
+
value = float(value)
|
|
901
|
+
else:
|
|
902
|
+
value = 1.0
|
|
903
|
+
self._multiplier = value
|
|
904
|
+
|
|
905
|
+
@property
|
|
906
|
+
def offset(self):
|
|
907
|
+
"""float : The offset for the joint configuration"""
|
|
908
|
+
return self._offset
|
|
909
|
+
|
|
910
|
+
@offset.setter
|
|
911
|
+
def offset(self, value):
|
|
912
|
+
if value is not None:
|
|
913
|
+
value = float(value)
|
|
914
|
+
else:
|
|
915
|
+
value = 0.0
|
|
916
|
+
self._offset = value
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
class SafetyController(URDFType): # pragma nocover
|
|
920
|
+
"""A controller for joint movement safety.
|
|
921
|
+
Parameters
|
|
922
|
+
----------
|
|
923
|
+
k_velocity : float
|
|
924
|
+
An attribute specifying the relation between the effort and velocity
|
|
925
|
+
limits.
|
|
926
|
+
k_position : float, optional
|
|
927
|
+
An attribute specifying the relation between the position and velocity
|
|
928
|
+
limits. Defaults to 0.0.
|
|
929
|
+
soft_lower_limit : float, optional
|
|
930
|
+
The lower joint boundary where the safety controller kicks in.
|
|
931
|
+
Defaults to 0.0.
|
|
932
|
+
soft_upper_limit : float, optional
|
|
933
|
+
The upper joint boundary where the safety controller kicks in.
|
|
934
|
+
Defaults to 0.0.
|
|
935
|
+
"""
|
|
936
|
+
|
|
937
|
+
_ATTRIBS = {
|
|
938
|
+
"k_velocity": (float, True),
|
|
939
|
+
"k_position": (float, False),
|
|
940
|
+
"soft_lower_limit": (float, False),
|
|
941
|
+
"soft_upper_limit": (float, False),
|
|
942
|
+
}
|
|
943
|
+
_TAG = "safety_controller"
|
|
944
|
+
|
|
945
|
+
def __init__(
|
|
946
|
+
self, k_velocity, k_position=None, soft_lower_limit=None, soft_upper_limit=None
|
|
947
|
+
):
|
|
948
|
+
self.k_velocity = k_velocity
|
|
949
|
+
self.k_position = k_position
|
|
950
|
+
self.soft_lower_limit = soft_lower_limit
|
|
951
|
+
self.soft_upper_limit = soft_upper_limit
|
|
952
|
+
|
|
953
|
+
@property
|
|
954
|
+
def soft_lower_limit(self):
|
|
955
|
+
"""float : The soft lower limit where the safety controller kicks in."""
|
|
956
|
+
return self._soft_lower_limit
|
|
957
|
+
|
|
958
|
+
@soft_lower_limit.setter
|
|
959
|
+
def soft_lower_limit(self, value):
|
|
960
|
+
if value is not None:
|
|
961
|
+
value = float(value)
|
|
962
|
+
else:
|
|
963
|
+
value = 0.0
|
|
964
|
+
self._soft_lower_limit = value
|
|
965
|
+
|
|
966
|
+
@property
|
|
967
|
+
def soft_upper_limit(self):
|
|
968
|
+
"""float : The soft upper limit where the safety controller kicks in."""
|
|
969
|
+
return self._soft_upper_limit
|
|
970
|
+
|
|
971
|
+
@soft_upper_limit.setter
|
|
972
|
+
def soft_upper_limit(self, value):
|
|
973
|
+
if value is not None:
|
|
974
|
+
value = float(value)
|
|
975
|
+
else:
|
|
976
|
+
value = 0.0
|
|
977
|
+
self._soft_upper_limit = value
|
|
978
|
+
|
|
979
|
+
@property
|
|
980
|
+
def k_position(self):
|
|
981
|
+
"""float : A relation between the position and velocity limits."""
|
|
982
|
+
return self._k_position
|
|
983
|
+
|
|
984
|
+
@k_position.setter
|
|
985
|
+
def k_position(self, value):
|
|
986
|
+
if value is not None:
|
|
987
|
+
value = float(value)
|
|
988
|
+
else:
|
|
989
|
+
value = 0.0
|
|
990
|
+
self._k_position = value
|
|
991
|
+
|
|
992
|
+
@property
|
|
993
|
+
def k_velocity(self):
|
|
994
|
+
"""float : A relation between the effort and velocity limits."""
|
|
995
|
+
return self._k_velocity
|
|
996
|
+
|
|
997
|
+
@k_velocity.setter
|
|
998
|
+
def k_velocity(self, value):
|
|
999
|
+
self._k_velocity = float(value)
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
###############################################################################
|
|
1003
|
+
# Transmission types
|
|
1004
|
+
###############################################################################
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
class Actuator(URDFType):
|
|
1008
|
+
"""An actuator.
|
|
1009
|
+
Parameters
|
|
1010
|
+
----------
|
|
1011
|
+
name : str
|
|
1012
|
+
The name of this actuator.
|
|
1013
|
+
mechanicalReduction : str, optional
|
|
1014
|
+
A specifier for the mechanical reduction at the joint/actuator
|
|
1015
|
+
transmission.
|
|
1016
|
+
hardwareInterfaces : list of str, optional
|
|
1017
|
+
The supported hardware interfaces to the actuator.
|
|
1018
|
+
"""
|
|
1019
|
+
|
|
1020
|
+
_ATTRIBS = {
|
|
1021
|
+
"name": (str, True),
|
|
1022
|
+
}
|
|
1023
|
+
_TAG = "actuator"
|
|
1024
|
+
|
|
1025
|
+
def __init__(self, name, mechanicalReduction=None, hardwareInterfaces=None):
|
|
1026
|
+
self.name = name
|
|
1027
|
+
self.mechanicalReduction = mechanicalReduction
|
|
1028
|
+
self.hardwareInterfaces = hardwareInterfaces
|
|
1029
|
+
|
|
1030
|
+
@property
|
|
1031
|
+
def name(self): # pragma nocover
|
|
1032
|
+
"""str : The name of this actuator."""
|
|
1033
|
+
return self._name
|
|
1034
|
+
|
|
1035
|
+
@name.setter
|
|
1036
|
+
def name(self, value):
|
|
1037
|
+
self._name = str(value)
|
|
1038
|
+
|
|
1039
|
+
@property
|
|
1040
|
+
def mechanicalReduction(self): # pragma nocover
|
|
1041
|
+
"""str : A specifier for the type of mechanical reduction."""
|
|
1042
|
+
return self._mechanicalReduction
|
|
1043
|
+
|
|
1044
|
+
@mechanicalReduction.setter
|
|
1045
|
+
def mechanicalReduction(self, value):
|
|
1046
|
+
if value is not None:
|
|
1047
|
+
value = str(value)
|
|
1048
|
+
self._mechanicalReduction = value
|
|
1049
|
+
|
|
1050
|
+
@property
|
|
1051
|
+
def hardwareInterfaces(self): # pragma nocover
|
|
1052
|
+
"""list of str : The supported hardware interfaces."""
|
|
1053
|
+
return self._hardwareInterfaces
|
|
1054
|
+
|
|
1055
|
+
@hardwareInterfaces.setter
|
|
1056
|
+
def hardwareInterfaces(self, value): # pragma nocover
|
|
1057
|
+
if value is None:
|
|
1058
|
+
value = []
|
|
1059
|
+
else:
|
|
1060
|
+
value = list(value)
|
|
1061
|
+
for i, v in enumerate(value):
|
|
1062
|
+
value[i] = str(v)
|
|
1063
|
+
self._hardwareInterfaces = value
|
|
1064
|
+
|
|
1065
|
+
@classmethod
|
|
1066
|
+
def _from_xml(cls, node, path): # pragma nocover
|
|
1067
|
+
kwargs = cls._parse(node, path)
|
|
1068
|
+
mr = node.find("mechanicalReduction")
|
|
1069
|
+
if mr is not None:
|
|
1070
|
+
mr = float(mr.text)
|
|
1071
|
+
kwargs["mechanicalReduction"] = mr
|
|
1072
|
+
hi = node.findall("hardwareInterface")
|
|
1073
|
+
if len(hi) > 0:
|
|
1074
|
+
hi = [h.text for h in hi]
|
|
1075
|
+
kwargs["hardwareInterfaces"] = hi
|
|
1076
|
+
return Actuator(**kwargs)
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
class TransmissionJoint(URDFType):
|
|
1080
|
+
"""A transmission joint specification.
|
|
1081
|
+
Parameters
|
|
1082
|
+
----------
|
|
1083
|
+
name : str
|
|
1084
|
+
The name of this actuator.
|
|
1085
|
+
hardwareInterfaces : list of str, optional
|
|
1086
|
+
The supported hardware interfaces to the actuator.
|
|
1087
|
+
"""
|
|
1088
|
+
|
|
1089
|
+
_ATTRIBS = {
|
|
1090
|
+
"name": (str, True),
|
|
1091
|
+
}
|
|
1092
|
+
_TAG = "joint"
|
|
1093
|
+
|
|
1094
|
+
def __init__(self, name, hardwareInterfaces):
|
|
1095
|
+
self.name = name
|
|
1096
|
+
self.hardwareInterfaces = hardwareInterfaces
|
|
1097
|
+
|
|
1098
|
+
@property
|
|
1099
|
+
def name(self): # pragma nocover
|
|
1100
|
+
"""str : The name of this transmission joint."""
|
|
1101
|
+
return self._name
|
|
1102
|
+
|
|
1103
|
+
@name.setter
|
|
1104
|
+
def name(self, value):
|
|
1105
|
+
self._name = str(value)
|
|
1106
|
+
|
|
1107
|
+
@property
|
|
1108
|
+
def hardwareInterfaces(self): # pragma nocover
|
|
1109
|
+
"""list of str : The supported hardware interfaces."""
|
|
1110
|
+
return self._hardwareInterfaces
|
|
1111
|
+
|
|
1112
|
+
@hardwareInterfaces.setter
|
|
1113
|
+
def hardwareInterfaces(self, value): # pragma nocover
|
|
1114
|
+
if value is None:
|
|
1115
|
+
value = []
|
|
1116
|
+
else:
|
|
1117
|
+
value = list(value)
|
|
1118
|
+
for i, v in enumerate(value):
|
|
1119
|
+
value[i] = str(v)
|
|
1120
|
+
self._hardwareInterfaces = value
|
|
1121
|
+
|
|
1122
|
+
@classmethod
|
|
1123
|
+
def _from_xml(cls, node, path):
|
|
1124
|
+
kwargs = cls._parse(node, path)
|
|
1125
|
+
hi = node.findall("hardwareInterface")
|
|
1126
|
+
if len(hi) > 0:
|
|
1127
|
+
hi = [h.text for h in hi]
|
|
1128
|
+
kwargs["hardwareInterfaces"] = hi
|
|
1129
|
+
return TransmissionJoint(**kwargs)
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
###############################################################################
|
|
1133
|
+
# Top-level types
|
|
1134
|
+
###############################################################################
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
class Transmission(URDFType):
|
|
1138
|
+
"""An element that describes the relationship between an actuator and a
|
|
1139
|
+
joint.
|
|
1140
|
+
Parameters
|
|
1141
|
+
----------
|
|
1142
|
+
name : str
|
|
1143
|
+
The name of this transmission.
|
|
1144
|
+
trans_type : str
|
|
1145
|
+
The type of this transmission.
|
|
1146
|
+
joints : list of :class:`.TransmissionJoint`
|
|
1147
|
+
The joints connected to this transmission.
|
|
1148
|
+
actuators : list of :class:`.Actuator`
|
|
1149
|
+
The actuators connected to this transmission.
|
|
1150
|
+
"""
|
|
1151
|
+
|
|
1152
|
+
_ATTRIBS = {
|
|
1153
|
+
"name": (str, True),
|
|
1154
|
+
}
|
|
1155
|
+
_ELEMENTS = {
|
|
1156
|
+
"joints": (TransmissionJoint, True, True),
|
|
1157
|
+
"actuators": (Actuator, True, True),
|
|
1158
|
+
}
|
|
1159
|
+
_TAG = "transmission"
|
|
1160
|
+
|
|
1161
|
+
def __init__(self, name, trans_type, joints=None, actuators=None):
|
|
1162
|
+
self.name = name
|
|
1163
|
+
self.trans_type = trans_type
|
|
1164
|
+
self.joints = joints
|
|
1165
|
+
self.actuators = actuators
|
|
1166
|
+
|
|
1167
|
+
@property
|
|
1168
|
+
def name(self):
|
|
1169
|
+
"""str : The name of this transmission."""
|
|
1170
|
+
return self._name
|
|
1171
|
+
|
|
1172
|
+
@name.setter
|
|
1173
|
+
def name(self, value):
|
|
1174
|
+
self._name = str(value)
|
|
1175
|
+
|
|
1176
|
+
@property
|
|
1177
|
+
def trans_type(self): # pragma nocover
|
|
1178
|
+
"""str : The type of this transmission."""
|
|
1179
|
+
return self._trans_type
|
|
1180
|
+
|
|
1181
|
+
@trans_type.setter
|
|
1182
|
+
def trans_type(self, value):
|
|
1183
|
+
self._trans_type = str(value)
|
|
1184
|
+
|
|
1185
|
+
@property
|
|
1186
|
+
def joints(self): # pragma nocover
|
|
1187
|
+
""":class:`.TransmissionJoint` : The joints the transmission is
|
|
1188
|
+
connected to.
|
|
1189
|
+
"""
|
|
1190
|
+
return self._joints
|
|
1191
|
+
|
|
1192
|
+
@joints.setter
|
|
1193
|
+
def joints(self, value): # pragma nocover
|
|
1194
|
+
if value is None:
|
|
1195
|
+
value = []
|
|
1196
|
+
else:
|
|
1197
|
+
value = list(value)
|
|
1198
|
+
for v in value:
|
|
1199
|
+
if not isinstance(v, TransmissionJoint):
|
|
1200
|
+
raise TypeError("Joints expects a list of TransmissionJoint")
|
|
1201
|
+
self._joints = value
|
|
1202
|
+
|
|
1203
|
+
@property
|
|
1204
|
+
def actuators(self): # pragma nocover
|
|
1205
|
+
""":class:`.Actuator` : The actuators the transmission is connected to."""
|
|
1206
|
+
return self._actuators
|
|
1207
|
+
|
|
1208
|
+
@actuators.setter
|
|
1209
|
+
def actuators(self, value): # pragma nocover
|
|
1210
|
+
if value is None:
|
|
1211
|
+
value = []
|
|
1212
|
+
else:
|
|
1213
|
+
value = list(value)
|
|
1214
|
+
for v in value:
|
|
1215
|
+
if not isinstance(v, Actuator):
|
|
1216
|
+
raise TypeError("Actuators expects a list of Actuator")
|
|
1217
|
+
self._actuators = value
|
|
1218
|
+
|
|
1219
|
+
@classmethod
|
|
1220
|
+
def _from_xml(cls, node, path):
|
|
1221
|
+
kwargs = cls._parse(node, path)
|
|
1222
|
+
if node.find("type") is not None:
|
|
1223
|
+
kwargs["trans_type"] = node.find("type").text
|
|
1224
|
+
else:
|
|
1225
|
+
kwargs["trans_type"] = " " # pragma nocover
|
|
1226
|
+
|
|
1227
|
+
return Transmission(**kwargs)
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
class Joint(URDFType):
|
|
1231
|
+
"""A connection between two links.
|
|
1232
|
+
There are several types of joints, including:
|
|
1233
|
+
- ``fixed`` - a joint that cannot move.
|
|
1234
|
+
- ``prismatic`` - a joint that slides along the joint axis.
|
|
1235
|
+
- ``revolute`` - a hinge joint that rotates about the axis with a limited
|
|
1236
|
+
range of motion.
|
|
1237
|
+
- ``continuous`` - a hinge joint that rotates about the axis with an
|
|
1238
|
+
unlimited range of motion.
|
|
1239
|
+
- ``planar`` - a joint that moves in the plane orthogonal to the axis.
|
|
1240
|
+
- ``floating`` - a joint that can move in 6DoF.
|
|
1241
|
+
Parameters
|
|
1242
|
+
----------
|
|
1243
|
+
name : str
|
|
1244
|
+
The name of this joint.
|
|
1245
|
+
parent : str
|
|
1246
|
+
The name of the parent link of this joint.
|
|
1247
|
+
child : str
|
|
1248
|
+
The name of the child link of this joint.
|
|
1249
|
+
joint_type : str
|
|
1250
|
+
The type of the joint. Must be one of :obj:`.Joint.TYPES`.
|
|
1251
|
+
axis : (3,) float, optional
|
|
1252
|
+
The axis of the joint specified in joint frame. Defaults to
|
|
1253
|
+
``[1,0,0]``.
|
|
1254
|
+
origin : (4,4) float, optional
|
|
1255
|
+
The pose of the child link with respect to the parent link's frame.
|
|
1256
|
+
The joint frame is defined to be coincident with the child link's
|
|
1257
|
+
frame, so this is also the pose of the joint frame with respect to
|
|
1258
|
+
the parent link's frame.
|
|
1259
|
+
limit : :class:`.JointLimit`, optional
|
|
1260
|
+
Limit for the joint. Only required for revolute and prismatic
|
|
1261
|
+
joints.
|
|
1262
|
+
dynamics : :class:`.JointDynamics`, optional
|
|
1263
|
+
Dynamics for the joint.
|
|
1264
|
+
safety_controller : :class`.SafetyController`, optional
|
|
1265
|
+
The safety controller for this joint.
|
|
1266
|
+
calibration : :class:`.JointCalibration`, optional
|
|
1267
|
+
Calibration information for the joint.
|
|
1268
|
+
mimic : :class:`JointMimic`, optional
|
|
1269
|
+
Joint mimicry information.
|
|
1270
|
+
"""
|
|
1271
|
+
|
|
1272
|
+
TYPES = ["fixed", "prismatic", "revolute", "continuous", "floating", "planar"]
|
|
1273
|
+
_ATTRIBS = {
|
|
1274
|
+
"name": (str, True),
|
|
1275
|
+
}
|
|
1276
|
+
_ELEMENTS = {
|
|
1277
|
+
"dynamics": (JointDynamics, False, False),
|
|
1278
|
+
"limit": (JointLimit, False, False),
|
|
1279
|
+
"mimic": (JointMimic, False, False),
|
|
1280
|
+
"safety_controller": (SafetyController, False, False),
|
|
1281
|
+
"calibration": (JointCalibration, False, False),
|
|
1282
|
+
}
|
|
1283
|
+
_TAG = "joint"
|
|
1284
|
+
|
|
1285
|
+
def __init__(
|
|
1286
|
+
self,
|
|
1287
|
+
name,
|
|
1288
|
+
joint_type,
|
|
1289
|
+
parent,
|
|
1290
|
+
child,
|
|
1291
|
+
axis=None,
|
|
1292
|
+
origin=None,
|
|
1293
|
+
limit=None,
|
|
1294
|
+
dynamics=None,
|
|
1295
|
+
safety_controller=None,
|
|
1296
|
+
calibration=None,
|
|
1297
|
+
mimic=None,
|
|
1298
|
+
rpy=None,
|
|
1299
|
+
):
|
|
1300
|
+
self.name = name
|
|
1301
|
+
self.parent = parent
|
|
1302
|
+
self.child = child
|
|
1303
|
+
self.joint_type = joint_type
|
|
1304
|
+
self.axis = axis
|
|
1305
|
+
self.origin = origin
|
|
1306
|
+
self.rpy = rpy
|
|
1307
|
+
self.limit = limit
|
|
1308
|
+
self.dynamics = dynamics
|
|
1309
|
+
self.safety_controller = safety_controller
|
|
1310
|
+
self.calibration = calibration
|
|
1311
|
+
self.mimic = mimic
|
|
1312
|
+
|
|
1313
|
+
@property
|
|
1314
|
+
def name(self):
|
|
1315
|
+
"""str : Name for this joint."""
|
|
1316
|
+
return self._name
|
|
1317
|
+
|
|
1318
|
+
@name.setter
|
|
1319
|
+
def name(self, value):
|
|
1320
|
+
self._name = str(value)
|
|
1321
|
+
|
|
1322
|
+
@property
|
|
1323
|
+
def joint_type(self):
|
|
1324
|
+
"""str : The type of this joint."""
|
|
1325
|
+
return self._joint_type
|
|
1326
|
+
|
|
1327
|
+
@joint_type.setter
|
|
1328
|
+
def joint_type(self, value):
|
|
1329
|
+
value = str(value)
|
|
1330
|
+
if value not in Joint.TYPES: # pragma nocover
|
|
1331
|
+
raise ValueError("Unsupported joint type {}".format(value))
|
|
1332
|
+
self._joint_type = value
|
|
1333
|
+
|
|
1334
|
+
@property
|
|
1335
|
+
def parent(self):
|
|
1336
|
+
"""str : The name of the parent link."""
|
|
1337
|
+
return self._parent
|
|
1338
|
+
|
|
1339
|
+
@parent.setter
|
|
1340
|
+
def parent(self, value):
|
|
1341
|
+
self._parent = str(value)
|
|
1342
|
+
|
|
1343
|
+
@property
|
|
1344
|
+
def child(self):
|
|
1345
|
+
"""str : The name of the child link."""
|
|
1346
|
+
return self._child
|
|
1347
|
+
|
|
1348
|
+
@child.setter
|
|
1349
|
+
def child(self, value):
|
|
1350
|
+
self._child = str(value)
|
|
1351
|
+
|
|
1352
|
+
@property
|
|
1353
|
+
def axis(self):
|
|
1354
|
+
"""(3,) float : The joint axis in the joint frame."""
|
|
1355
|
+
return self._axis
|
|
1356
|
+
|
|
1357
|
+
@axis.setter
|
|
1358
|
+
def axis(self, value):
|
|
1359
|
+
if value is None:
|
|
1360
|
+
value = np.array([1.0, 0.0, 0.0], dtype=np.float64)
|
|
1361
|
+
else:
|
|
1362
|
+
value = np.asanyarray(value, dtype=np.float64)
|
|
1363
|
+
if value.shape != (3,): # pragma nocover
|
|
1364
|
+
raise ValueError("Invalid shape for axis, should be (3,)")
|
|
1365
|
+
norm = np.linalg.norm(value)
|
|
1366
|
+
|
|
1367
|
+
if norm != 0:
|
|
1368
|
+
value = value / norm
|
|
1369
|
+
self._axis = value
|
|
1370
|
+
|
|
1371
|
+
@property
|
|
1372
|
+
def origin(self):
|
|
1373
|
+
"""(4,4) float : The pose of child and joint frames relative to the
|
|
1374
|
+
parent link's frame.
|
|
1375
|
+
"""
|
|
1376
|
+
return self._origin
|
|
1377
|
+
|
|
1378
|
+
@origin.setter
|
|
1379
|
+
def origin(self, value):
|
|
1380
|
+
self._origin = configure_origin(value)
|
|
1381
|
+
|
|
1382
|
+
@property
|
|
1383
|
+
def rpy(self):
|
|
1384
|
+
return self._rpy
|
|
1385
|
+
|
|
1386
|
+
@rpy.setter
|
|
1387
|
+
def rpy(self, value):
|
|
1388
|
+
self._rpy = value
|
|
1389
|
+
|
|
1390
|
+
@property
|
|
1391
|
+
def limit(self):
|
|
1392
|
+
""":class:`.JointLimit` : The limits for this joint."""
|
|
1393
|
+
return self._limit
|
|
1394
|
+
|
|
1395
|
+
@limit.setter
|
|
1396
|
+
def limit(self, value):
|
|
1397
|
+
if value is None:
|
|
1398
|
+
if self.joint_type in ["prismatic", "revolute"]: # pragma nocover
|
|
1399
|
+
raise ValueError(
|
|
1400
|
+
"Require joint limit for prismatic and revolute joints"
|
|
1401
|
+
)
|
|
1402
|
+
elif not isinstance(value, JointLimit): # pragma nocover
|
|
1403
|
+
raise TypeError("Expected JointLimit type")
|
|
1404
|
+
self._limit = value
|
|
1405
|
+
|
|
1406
|
+
@property
|
|
1407
|
+
def dynamics(self):
|
|
1408
|
+
""":class:`.JointDynamics` : The dynamics for this joint."""
|
|
1409
|
+
return self._dynamics
|
|
1410
|
+
|
|
1411
|
+
@dynamics.setter
|
|
1412
|
+
def dynamics(self, value):
|
|
1413
|
+
if value is not None:
|
|
1414
|
+
if not isinstance(value, JointDynamics): # pragma nocover
|
|
1415
|
+
raise TypeError("Expected JointDynamics type")
|
|
1416
|
+
self._dynamics = value
|
|
1417
|
+
|
|
1418
|
+
@property
|
|
1419
|
+
def safety_controller(self): # pragma nocover
|
|
1420
|
+
""":class:`.SafetyController` : The safety controller for this joint."""
|
|
1421
|
+
return self._safety_controller
|
|
1422
|
+
|
|
1423
|
+
@safety_controller.setter
|
|
1424
|
+
def safety_controller(self, value):
|
|
1425
|
+
if value is not None:
|
|
1426
|
+
if not isinstance(value, SafetyController): # pragma nocover
|
|
1427
|
+
raise TypeError("Expected SafetyController type")
|
|
1428
|
+
self._safety_controller = value
|
|
1429
|
+
|
|
1430
|
+
@property
|
|
1431
|
+
def calibration(self): # pragma nocover
|
|
1432
|
+
""":class:`.JointCalibration` : The calibration for this joint."""
|
|
1433
|
+
return self._calibration
|
|
1434
|
+
|
|
1435
|
+
@calibration.setter
|
|
1436
|
+
def calibration(self, value):
|
|
1437
|
+
if value is not None:
|
|
1438
|
+
if not isinstance(value, JointCalibration): # pragma nocover
|
|
1439
|
+
raise TypeError("Expected JointCalibration type")
|
|
1440
|
+
self._calibration = value
|
|
1441
|
+
|
|
1442
|
+
@property
|
|
1443
|
+
def mimic(self): # pragma nocover
|
|
1444
|
+
""":class:`.JointMimic` : The mimic for this joint."""
|
|
1445
|
+
return self._mimic
|
|
1446
|
+
|
|
1447
|
+
@mimic.setter
|
|
1448
|
+
def mimic(self, value):
|
|
1449
|
+
if value is not None:
|
|
1450
|
+
if not isinstance(value, JointMimic): # pragma nocover
|
|
1451
|
+
raise TypeError("Expected JointMimic type")
|
|
1452
|
+
self._mimic = value
|
|
1453
|
+
|
|
1454
|
+
def is_valid(self, cfg): # pragma nocover
|
|
1455
|
+
"""Check if the provided configuration value is valid for this joint.
|
|
1456
|
+
Parameters
|
|
1457
|
+
----------
|
|
1458
|
+
cfg : float, (2,) float, (6,) float, or (4,4) float
|
|
1459
|
+
The configuration of the joint.
|
|
1460
|
+
Returns
|
|
1461
|
+
-------
|
|
1462
|
+
is_valid : bool
|
|
1463
|
+
True if the configuration is valid, and False otherwise.
|
|
1464
|
+
"""
|
|
1465
|
+
if self.joint_type not in ["fixed", "revolute"]:
|
|
1466
|
+
return True
|
|
1467
|
+
if self.joint_limit is None:
|
|
1468
|
+
return True
|
|
1469
|
+
cfg = float(cfg)
|
|
1470
|
+
lower = -np.infty
|
|
1471
|
+
upper = np.infty
|
|
1472
|
+
if self.limit.lower is not None:
|
|
1473
|
+
lower = self.limit.lower
|
|
1474
|
+
if self.limit.upper is not None:
|
|
1475
|
+
upper = self.limit.upper
|
|
1476
|
+
return cfg >= lower and cfg <= upper
|
|
1477
|
+
|
|
1478
|
+
@classmethod
|
|
1479
|
+
def _from_xml(cls, node, path):
|
|
1480
|
+
kwargs = cls._parse(node, path)
|
|
1481
|
+
kwargs["joint_type"] = str(node.attrib["type"])
|
|
1482
|
+
kwargs["parent"] = node.find("parent").attrib["link"]
|
|
1483
|
+
kwargs["child"] = node.find("child").attrib["link"]
|
|
1484
|
+
axis = node.find("axis")
|
|
1485
|
+
if axis is not None:
|
|
1486
|
+
axis = np.fromstring(axis.attrib["xyz"], sep=" ")
|
|
1487
|
+
kwargs["axis"] = axis
|
|
1488
|
+
kwargs["origin"], kwargs["rpy"] = parse_origin(node)
|
|
1489
|
+
return Joint(**kwargs)
|
|
1490
|
+
|
|
1491
|
+
|
|
1492
|
+
class Link(URDFType):
|
|
1493
|
+
"""A link of a rigid object.
|
|
1494
|
+
Parameters
|
|
1495
|
+
----------
|
|
1496
|
+
name : str
|
|
1497
|
+
The name of the link.
|
|
1498
|
+
inertial : :class:`.Inertial`, optional
|
|
1499
|
+
The inertial properties of the link.
|
|
1500
|
+
visuals : list of :class:`.Visual`, optional
|
|
1501
|
+
The visual properties of the link.
|
|
1502
|
+
collsions : list of :class:`.Collision`, optional
|
|
1503
|
+
The collision properties of the link.
|
|
1504
|
+
"""
|
|
1505
|
+
|
|
1506
|
+
_ATTRIBS = {
|
|
1507
|
+
"name": (str, True),
|
|
1508
|
+
}
|
|
1509
|
+
_ELEMENTS = {
|
|
1510
|
+
"inertial": (Inertial, False, False),
|
|
1511
|
+
"visuals": (Visual, False, True),
|
|
1512
|
+
"collisions": (Collision, False, True),
|
|
1513
|
+
}
|
|
1514
|
+
_TAG = "link"
|
|
1515
|
+
|
|
1516
|
+
def __init__(self, name, inertial, visuals, collisions):
|
|
1517
|
+
self.name = name
|
|
1518
|
+
self.inertial = inertial
|
|
1519
|
+
self.visuals = visuals
|
|
1520
|
+
self.collisions = collisions
|
|
1521
|
+
|
|
1522
|
+
@property
|
|
1523
|
+
def name(self):
|
|
1524
|
+
"""str : The name of this link."""
|
|
1525
|
+
return self._name
|
|
1526
|
+
|
|
1527
|
+
@name.setter
|
|
1528
|
+
def name(self, value):
|
|
1529
|
+
self._name = str(value)
|
|
1530
|
+
|
|
1531
|
+
@property
|
|
1532
|
+
def inertial(self):
|
|
1533
|
+
""":class:`.Inertial` : Inertial properties of the link."""
|
|
1534
|
+
return self._inertial
|
|
1535
|
+
|
|
1536
|
+
@inertial.setter
|
|
1537
|
+
def inertial(self, value):
|
|
1538
|
+
if value is not None and not isinstance(value, Inertial):
|
|
1539
|
+
raise TypeError("Expected Inertial object") # pragma nocover
|
|
1540
|
+
# Set default inertial
|
|
1541
|
+
if value is None:
|
|
1542
|
+
value = Inertial()
|
|
1543
|
+
self._inertial = value
|
|
1544
|
+
|
|
1545
|
+
@property
|
|
1546
|
+
def visuals(self):
|
|
1547
|
+
"""list of :class:`.Visual` : The visual properties of this link."""
|
|
1548
|
+
return self._visuals
|
|
1549
|
+
|
|
1550
|
+
@visuals.setter
|
|
1551
|
+
def visuals(self, value):
|
|
1552
|
+
if value is None: # pragma nocover
|
|
1553
|
+
value = []
|
|
1554
|
+
else:
|
|
1555
|
+
value = list(value)
|
|
1556
|
+
for v in value:
|
|
1557
|
+
if not isinstance(v, Visual): # pragma nocover
|
|
1558
|
+
raise ValueError("Expected list of Visual objects")
|
|
1559
|
+
self._visuals = value
|
|
1560
|
+
|
|
1561
|
+
@property
|
|
1562
|
+
def collisions(self):
|
|
1563
|
+
"""list of :class:`.Collision` : The collision properties of this link."""
|
|
1564
|
+
return self._collisions
|
|
1565
|
+
|
|
1566
|
+
@collisions.setter
|
|
1567
|
+
def collisions(self, value):
|
|
1568
|
+
if value is None: # pragma nocover
|
|
1569
|
+
value = []
|
|
1570
|
+
else:
|
|
1571
|
+
value = list(value)
|
|
1572
|
+
for v in value:
|
|
1573
|
+
if not isinstance(v, Collision): # pragma nocover
|
|
1574
|
+
raise ValueError("Expected list of Collision objects")
|
|
1575
|
+
self._collisions = value
|
|
1576
|
+
|
|
1577
|
+
|
|
1578
|
+
class URDF(URDFType):
|
|
1579
|
+
"""The top-level URDF specification.
|
|
1580
|
+
The URDF encapsulates an articulated object, such as a robot or a gripper.
|
|
1581
|
+
It is made of links and joints that tie them together and define their
|
|
1582
|
+
relative motions.
|
|
1583
|
+
Parameters
|
|
1584
|
+
----------
|
|
1585
|
+
name : str
|
|
1586
|
+
The name of the URDF.
|
|
1587
|
+
links : list of :class:`.Link`
|
|
1588
|
+
The links of the URDF.
|
|
1589
|
+
joints : list of :class:`.Joint`, optional
|
|
1590
|
+
The joints of the URDF.
|
|
1591
|
+
transmissions : list of :class:`.Transmission`, optional
|
|
1592
|
+
The transmissions of the URDF.
|
|
1593
|
+
materials : list of :class:`.Material`, optional
|
|
1594
|
+
The materials for the URDF.
|
|
1595
|
+
other_xml : str, optional
|
|
1596
|
+
A string containing any extra XML for extensions.
|
|
1597
|
+
"""
|
|
1598
|
+
|
|
1599
|
+
_ATTRIBS = {
|
|
1600
|
+
"name": (str, True),
|
|
1601
|
+
}
|
|
1602
|
+
_ELEMENTS = {
|
|
1603
|
+
"links": (Link, True, True),
|
|
1604
|
+
"joints": (Joint, False, True),
|
|
1605
|
+
"transmissions": (Transmission, False, True),
|
|
1606
|
+
"materials": (Material, False, True),
|
|
1607
|
+
}
|
|
1608
|
+
_TAG = "robot"
|
|
1609
|
+
|
|
1610
|
+
def __init__(
|
|
1611
|
+
self,
|
|
1612
|
+
name,
|
|
1613
|
+
links,
|
|
1614
|
+
joints=None,
|
|
1615
|
+
transmissions=None,
|
|
1616
|
+
materials=None,
|
|
1617
|
+
other_xml=None,
|
|
1618
|
+
):
|
|
1619
|
+
if joints is None: # pragma nocover
|
|
1620
|
+
joints = []
|
|
1621
|
+
if transmissions is None: # pragma nocover
|
|
1622
|
+
transmissions = []
|
|
1623
|
+
if materials is None:
|
|
1624
|
+
materials = []
|
|
1625
|
+
|
|
1626
|
+
# TODO, what does this next line do?
|
|
1627
|
+
# why arent the other things validated
|
|
1628
|
+
try:
|
|
1629
|
+
self._validate_transmissions()
|
|
1630
|
+
except Exception:
|
|
1631
|
+
pass
|
|
1632
|
+
|
|
1633
|
+
self.name = name
|
|
1634
|
+
self.other_xml = other_xml
|
|
1635
|
+
|
|
1636
|
+
# No setters for these
|
|
1637
|
+
self._links = list(links)
|
|
1638
|
+
self._joints = list(joints)
|
|
1639
|
+
self._transmissions = list(transmissions)
|
|
1640
|
+
self._materials = list(materials)
|
|
1641
|
+
self._material_map = {}
|
|
1642
|
+
|
|
1643
|
+
for x in self._materials:
|
|
1644
|
+
if x.name in self._material_map:
|
|
1645
|
+
raise ValueError("Two materials with name {} found".format(x.name))
|
|
1646
|
+
self._material_map[x.name] = x
|
|
1647
|
+
|
|
1648
|
+
# check for duplicate names
|
|
1649
|
+
if len(self._links) > len(
|
|
1650
|
+
set([x.name for x in self._links])
|
|
1651
|
+
): # pragma nocover # noqa
|
|
1652
|
+
raise ValueError("Duplicate link names")
|
|
1653
|
+
if len(self._joints) > len(
|
|
1654
|
+
set([x.name for x in self._joints])
|
|
1655
|
+
): # pragma nocover # noqa
|
|
1656
|
+
raise ValueError("Duplicate joint names")
|
|
1657
|
+
if len(self._transmissions) > len(
|
|
1658
|
+
set([x.name for x in self._transmissions])
|
|
1659
|
+
): # pragma nocover # noqa
|
|
1660
|
+
raise ValueError("Duplicate transmission names")
|
|
1661
|
+
|
|
1662
|
+
elinks = []
|
|
1663
|
+
elinkdict = {}
|
|
1664
|
+
# jointdict = {}
|
|
1665
|
+
|
|
1666
|
+
# build the list of links in URDF file order
|
|
1667
|
+
for link in self._links:
|
|
1668
|
+
elink = rtb.Link(
|
|
1669
|
+
name=link.name,
|
|
1670
|
+
m=link.inertial.mass,
|
|
1671
|
+
r=link.inertial.origin[:3, 3]
|
|
1672
|
+
if link.inertial.origin is not None
|
|
1673
|
+
else None,
|
|
1674
|
+
I=link.inertial.inertia,
|
|
1675
|
+
)
|
|
1676
|
+
elinks.append(elink)
|
|
1677
|
+
elinkdict[link.name] = elink
|
|
1678
|
+
|
|
1679
|
+
# add the inertial parameters
|
|
1680
|
+
|
|
1681
|
+
# add the visuals to visual list
|
|
1682
|
+
try:
|
|
1683
|
+
elink.geometry = [v.geometry.ob for v in link.visuals]
|
|
1684
|
+
except AttributeError: # pragma nocover
|
|
1685
|
+
pass
|
|
1686
|
+
|
|
1687
|
+
# add collision objects to collision object list
|
|
1688
|
+
try:
|
|
1689
|
+
elink.collision = [col.geometry.ob for col in link.collisions]
|
|
1690
|
+
except AttributeError: # pragma nocover
|
|
1691
|
+
pass
|
|
1692
|
+
|
|
1693
|
+
# connect the links using joint info
|
|
1694
|
+
for joint in self._joints:
|
|
1695
|
+
# get references to joint's parent and child
|
|
1696
|
+
childlink = elinkdict[joint.child]
|
|
1697
|
+
parentlink = elinkdict[joint.parent]
|
|
1698
|
+
|
|
1699
|
+
childlink._parent = parentlink # connect child link to parent
|
|
1700
|
+
childlink._joint_name = joint.name
|
|
1701
|
+
|
|
1702
|
+
# constant part of link transform
|
|
1703
|
+
trans = SE3(joint.origin).t
|
|
1704
|
+
rot = joint.rpy
|
|
1705
|
+
|
|
1706
|
+
# Check if axis of rotation/tanslation is not 1
|
|
1707
|
+
if np.count_nonzero(joint.axis) < 2:
|
|
1708
|
+
ets = rtb.ET.SE3(SE3(trans) * SE3.RPY(rot))
|
|
1709
|
+
else:
|
|
1710
|
+
# Normalise the joint axis to be along or about z axis
|
|
1711
|
+
# Convert rest to static ETS
|
|
1712
|
+
v = joint.axis
|
|
1713
|
+
u, n = unitvec_norm(v)
|
|
1714
|
+
R = angvec2r(n, u)
|
|
1715
|
+
|
|
1716
|
+
R_total = SE3.RPY(joint.rpy) * R
|
|
1717
|
+
rpy = tr2rpy(R_total)
|
|
1718
|
+
|
|
1719
|
+
ets = rtb.ET.SE3(SE3(trans) * SE3.RPY(rpy))
|
|
1720
|
+
|
|
1721
|
+
joint.axis = [0, 0, 1]
|
|
1722
|
+
|
|
1723
|
+
# variable part of link transform
|
|
1724
|
+
var = None
|
|
1725
|
+
if joint.joint_type in ("revolute", "continuous"): # pragma nocover # noqa
|
|
1726
|
+
if joint.axis[0] == 1:
|
|
1727
|
+
var = rtb.ET.Rx()
|
|
1728
|
+
elif joint.axis[0] == -1:
|
|
1729
|
+
var = rtb.ET.Rx(flip=True)
|
|
1730
|
+
elif joint.axis[1] == 1:
|
|
1731
|
+
var = rtb.ET.Ry()
|
|
1732
|
+
elif joint.axis[1] == -1:
|
|
1733
|
+
var = rtb.ET.Ry(flip=True)
|
|
1734
|
+
elif joint.axis[2] == 1:
|
|
1735
|
+
var = rtb.ET.Rz()
|
|
1736
|
+
elif joint.axis[2] == -1:
|
|
1737
|
+
var = rtb.ET.Rz(flip=True)
|
|
1738
|
+
elif joint.joint_type == "prismatic": # pragma nocover
|
|
1739
|
+
if joint.axis[0] == 1:
|
|
1740
|
+
var = rtb.ET.tx()
|
|
1741
|
+
elif joint.axis[0] == -1:
|
|
1742
|
+
var = rtb.ET.tx(flip=True)
|
|
1743
|
+
elif joint.axis[1] == 1:
|
|
1744
|
+
var = rtb.ET.ty()
|
|
1745
|
+
elif joint.axis[1] == -1:
|
|
1746
|
+
var = rtb.ET.ty(flip=True)
|
|
1747
|
+
elif joint.axis[2] == 1:
|
|
1748
|
+
var = rtb.ET.tz()
|
|
1749
|
+
elif joint.axis[2] == -1:
|
|
1750
|
+
var = rtb.ET.tz(flip=True)
|
|
1751
|
+
elif joint.joint_type == "fixed":
|
|
1752
|
+
var = None
|
|
1753
|
+
|
|
1754
|
+
if var is not None:
|
|
1755
|
+
ets = ets * var
|
|
1756
|
+
|
|
1757
|
+
if isinstance(ets, rtb.ET):
|
|
1758
|
+
ets = rtb.ETS(ets)
|
|
1759
|
+
|
|
1760
|
+
childlink.ets = ets
|
|
1761
|
+
|
|
1762
|
+
# joint limit
|
|
1763
|
+
try:
|
|
1764
|
+
if childlink.isjoint:
|
|
1765
|
+
childlink.qlim = [joint.limit.lower, joint.limit.upper]
|
|
1766
|
+
except AttributeError:
|
|
1767
|
+
# no joint limits provided
|
|
1768
|
+
pass
|
|
1769
|
+
|
|
1770
|
+
# joint friction
|
|
1771
|
+
try:
|
|
1772
|
+
if joint.dynamics.friction is not None:
|
|
1773
|
+
childlink.B = joint.dynamics.friction
|
|
1774
|
+
|
|
1775
|
+
# TODO Add damping
|
|
1776
|
+
# joint.dynamics.damping
|
|
1777
|
+
except AttributeError:
|
|
1778
|
+
pass
|
|
1779
|
+
|
|
1780
|
+
# joint gear ratio
|
|
1781
|
+
# TODO, not sure if t.joint.name is a thing
|
|
1782
|
+
for t in self.transmissions: # pragma nocover
|
|
1783
|
+
if t.name == joint.name:
|
|
1784
|
+
childlink.G = t.actuators[0].mechanicalReduction
|
|
1785
|
+
|
|
1786
|
+
self.elinks = elinks
|
|
1787
|
+
|
|
1788
|
+
# TODO, why did you put the base_link on the end?
|
|
1789
|
+
# easy to do it here
|
|
1790
|
+
|
|
1791
|
+
@property
|
|
1792
|
+
def name(self):
|
|
1793
|
+
"""str : The name of the URDF."""
|
|
1794
|
+
return self._name
|
|
1795
|
+
|
|
1796
|
+
@name.setter
|
|
1797
|
+
def name(self, value):
|
|
1798
|
+
self._name = str(value)
|
|
1799
|
+
|
|
1800
|
+
@property
|
|
1801
|
+
def links(self):
|
|
1802
|
+
"""list of :class:`.Link` : The links of the URDF.
|
|
1803
|
+
This returns a copy of the links array which cannot be edited
|
|
1804
|
+
directly. If you want to add or remove links, use
|
|
1805
|
+
the appropriate functions.
|
|
1806
|
+
"""
|
|
1807
|
+
return copy.copy(self._links)
|
|
1808
|
+
|
|
1809
|
+
@property
|
|
1810
|
+
def link_map(self): # pragma nocover
|
|
1811
|
+
"""dict : Map from link names to the links themselves.
|
|
1812
|
+
This returns a copy of the link map which cannot be edited
|
|
1813
|
+
directly. If you want to add or remove links, use
|
|
1814
|
+
the appropriate functions.
|
|
1815
|
+
"""
|
|
1816
|
+
return copy.copy(self._link_map)
|
|
1817
|
+
|
|
1818
|
+
@property
|
|
1819
|
+
def joints(self):
|
|
1820
|
+
"""list of :class:`.Joint` : The links of the URDF.
|
|
1821
|
+
This returns a copy of the joints array which cannot be edited
|
|
1822
|
+
directly. If you want to add or remove joints, use
|
|
1823
|
+
the appropriate functions.
|
|
1824
|
+
"""
|
|
1825
|
+
return copy.copy(self._joints)
|
|
1826
|
+
|
|
1827
|
+
@property
|
|
1828
|
+
def joint_map(self): # pragma nocover
|
|
1829
|
+
"""dict : Map from joint names to the joints themselves.
|
|
1830
|
+
This returns a copy of the joint map which cannot be edited
|
|
1831
|
+
directly. If you want to add or remove joints, use
|
|
1832
|
+
the appropriate functions.
|
|
1833
|
+
"""
|
|
1834
|
+
return copy.copy(self._joint_map)
|
|
1835
|
+
|
|
1836
|
+
@property
|
|
1837
|
+
def transmissions(self):
|
|
1838
|
+
"""list of :class:`.Transmission` : The transmissions of the URDF.
|
|
1839
|
+
This returns a copy of the transmissions array which cannot be edited
|
|
1840
|
+
directly. If you want to add or remove transmissions, use
|
|
1841
|
+
the appropriate functions.
|
|
1842
|
+
"""
|
|
1843
|
+
return copy.copy(self._transmissions)
|
|
1844
|
+
|
|
1845
|
+
@property
|
|
1846
|
+
def transmission_map(self): # pragma nocover
|
|
1847
|
+
"""dict : Map from transmission names to the transmissions themselves.
|
|
1848
|
+
This returns a copy of the transmission map which cannot be edited
|
|
1849
|
+
directly. If you want to add or remove transmissions, use
|
|
1850
|
+
the appropriate functions.
|
|
1851
|
+
"""
|
|
1852
|
+
return copy.copy(self._transmission_map)
|
|
1853
|
+
|
|
1854
|
+
@property
|
|
1855
|
+
def other_xml(self): # pragma nocover
|
|
1856
|
+
"""str : Any extra XML that belongs with the URDF."""
|
|
1857
|
+
return self._other_xml
|
|
1858
|
+
|
|
1859
|
+
@other_xml.setter
|
|
1860
|
+
def other_xml(self, value):
|
|
1861
|
+
self._other_xml = value
|
|
1862
|
+
|
|
1863
|
+
@property
|
|
1864
|
+
def actuated_joints(self): # pragma nocover
|
|
1865
|
+
"""list of :class:`.Joint` : The joints that are independently
|
|
1866
|
+
actuated.
|
|
1867
|
+
This excludes mimic joints and fixed joints. The joints are listed
|
|
1868
|
+
in topological order, starting from the base-most joint.
|
|
1869
|
+
"""
|
|
1870
|
+
return self._actuated_joints
|
|
1871
|
+
|
|
1872
|
+
def _merge_materials(self):
|
|
1873
|
+
"""Merge the top-level material set with the link materials."""
|
|
1874
|
+
for link in self.links:
|
|
1875
|
+
for v in link.visuals:
|
|
1876
|
+
if v.material is None:
|
|
1877
|
+
continue
|
|
1878
|
+
if v.material.name in self.material_map:
|
|
1879
|
+
v.material = self._material_map[v.material.name]
|
|
1880
|
+
v.geometry.ob.color = v.material.color
|
|
1881
|
+
else:
|
|
1882
|
+
self._materials.append(v.material)
|
|
1883
|
+
self._material_map[v.material.name] = v.material
|
|
1884
|
+
|
|
1885
|
+
@staticmethod
|
|
1886
|
+
def load(file_obj): # pragma nocover
|
|
1887
|
+
"""Load a URDF from a file.
|
|
1888
|
+
Parameters
|
|
1889
|
+
----------
|
|
1890
|
+
file_obj : str or file-like object
|
|
1891
|
+
The file to load the URDF from. Should be the path to the
|
|
1892
|
+
``.urdf`` XML file. Any paths in the URDF should be specified
|
|
1893
|
+
as relative paths to the ``.urdf`` file instead of as ROS
|
|
1894
|
+
resources.
|
|
1895
|
+
Returns
|
|
1896
|
+
-------
|
|
1897
|
+
urdf : :class:`.URDF`
|
|
1898
|
+
The parsed URDF.
|
|
1899
|
+
"""
|
|
1900
|
+
if isinstance(file_obj, str):
|
|
1901
|
+
if os.path.isfile(file_obj):
|
|
1902
|
+
parser = ETT.XMLParser()
|
|
1903
|
+
tree = ETT.parse(file_obj, parser=parser)
|
|
1904
|
+
path, _ = os.path.split(file_obj)
|
|
1905
|
+
else:
|
|
1906
|
+
raise ValueError("{} is not a file".format(file_obj))
|
|
1907
|
+
else:
|
|
1908
|
+
parser = ETT.XMLParser()
|
|
1909
|
+
tree = ETT.parse(file_obj, parser=parser)
|
|
1910
|
+
path, _ = os.path.split(file_obj.name)
|
|
1911
|
+
|
|
1912
|
+
node = tree.getroot()
|
|
1913
|
+
return URDF._from_xml(node, path)
|
|
1914
|
+
|
|
1915
|
+
@staticmethod
|
|
1916
|
+
def loadstr(str_obj, file_obj, base_path=None):
|
|
1917
|
+
"""Load a URDF from a file.
|
|
1918
|
+
Parameters
|
|
1919
|
+
----------
|
|
1920
|
+
file_obj : str or file-like object
|
|
1921
|
+
The file to load the URDF from. Should be the path to the
|
|
1922
|
+
``.urdf`` XML file. Any paths in the URDF should be specified
|
|
1923
|
+
as relative paths to the ``.urdf`` file instead of as ROS
|
|
1924
|
+
resources.
|
|
1925
|
+
Returns
|
|
1926
|
+
-------
|
|
1927
|
+
urdf : :class:`.URDF`
|
|
1928
|
+
The parsed URDF.
|
|
1929
|
+
"""
|
|
1930
|
+
global _base_path
|
|
1931
|
+
|
|
1932
|
+
if base_path is not None:
|
|
1933
|
+
_base_path = base_path
|
|
1934
|
+
|
|
1935
|
+
if isinstance(str_obj, str):
|
|
1936
|
+
if os.path.isfile(file_obj):
|
|
1937
|
+
parser = ETT.XMLParser()
|
|
1938
|
+
bytes_obj = BytesIO(bytes(str_obj, "utf-8"))
|
|
1939
|
+
tree = ETT.parse(bytes_obj, parser=parser)
|
|
1940
|
+
path, _ = os.path.split(file_obj)
|
|
1941
|
+
|
|
1942
|
+
else: # pragma nocover
|
|
1943
|
+
parser = ETT.XMLParser()
|
|
1944
|
+
tree = ETT.parse(file_obj, parser=parser)
|
|
1945
|
+
path, _ = os.path.split(file_obj.name)
|
|
1946
|
+
|
|
1947
|
+
node = tree.getroot()
|
|
1948
|
+
return URDF._from_xml(node, path)
|
|
1949
|
+
|
|
1950
|
+
def _validate_transmissions(self):
|
|
1951
|
+
"""Raise an exception of any transmissions are invalidly specified.
|
|
1952
|
+
Checks for the following:
|
|
1953
|
+
- Transmission joints have valid joint names.
|
|
1954
|
+
"""
|
|
1955
|
+
for t in self.transmissions: # pragma nocover
|
|
1956
|
+
for joint in t.joints:
|
|
1957
|
+
if joint.name not in self._joint_map:
|
|
1958
|
+
raise ValueError(
|
|
1959
|
+
"Transmission {} has invalid joint name {}".format(
|
|
1960
|
+
t.name, joint.name
|
|
1961
|
+
)
|
|
1962
|
+
)
|
|
1963
|
+
|
|
1964
|
+
@classmethod
|
|
1965
|
+
def _from_xml(cls, node, path):
|
|
1966
|
+
valid_tags = set(["joint", "link", "transmission", "material"])
|
|
1967
|
+
kwargs = cls._parse(node, path)
|
|
1968
|
+
|
|
1969
|
+
extra_xml_node = ETT.Element("extra")
|
|
1970
|
+
for child in node:
|
|
1971
|
+
if child.tag not in valid_tags:
|
|
1972
|
+
extra_xml_node.append(child)
|
|
1973
|
+
|
|
1974
|
+
# data = ETT.ostring(extra_xml_node)
|
|
1975
|
+
# kwargs['other_xml'] = data
|
|
1976
|
+
return URDF(**kwargs)
|