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,1909 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python Vehicle
|
|
3
|
+
@Author: Peter Corke, original MATLAB code and Python version
|
|
4
|
+
@Author: Kristian Gibson, initial MATLAB port
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
import warnings
|
|
9
|
+
import sys
|
|
10
|
+
from math import pi, sin, cos, tan
|
|
11
|
+
import numpy as np
|
|
12
|
+
from scipy import interpolate
|
|
13
|
+
|
|
14
|
+
import matplotlib.pyplot as plt
|
|
15
|
+
from matplotlib import animation
|
|
16
|
+
|
|
17
|
+
# from matplotlib import patches
|
|
18
|
+
# import matplotlib.transforms as mtransforms
|
|
19
|
+
|
|
20
|
+
from spatialmath import SE2, base
|
|
21
|
+
from roboticstoolbox.mobile.drivers import VehicleDriverBase
|
|
22
|
+
from roboticstoolbox.mobile.Animations import VehiclePolygon
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _isnotebook():
|
|
26
|
+
"""
|
|
27
|
+
Determine if code is being run from a Jupyter notebook or JupyterLite.
|
|
28
|
+
"""
|
|
29
|
+
if sys.platform == "emscripten":
|
|
30
|
+
return True
|
|
31
|
+
|
|
32
|
+
if "ipykernel" in sys.modules or "google.colab" in sys.modules:
|
|
33
|
+
return True
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
get_ipython_fn = globals().get("get_ipython", None)
|
|
37
|
+
if callable(get_ipython_fn):
|
|
38
|
+
shell = get_ipython_fn().__class__.__name__
|
|
39
|
+
if shell == "ZMQInteractiveShell":
|
|
40
|
+
return True
|
|
41
|
+
return False
|
|
42
|
+
except Exception:
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _refresh_animation_frame(fig, dt, pause):
|
|
47
|
+
"""
|
|
48
|
+
Refresh animation for desktop and notebook backends.
|
|
49
|
+
|
|
50
|
+
Notebook inline backends do not always animate with ``plt.pause`` alone,
|
|
51
|
+
so we explicitly draw and re-display the figure there.
|
|
52
|
+
"""
|
|
53
|
+
if fig is None:
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
if not pause:
|
|
57
|
+
try:
|
|
58
|
+
fig.canvas.draw_idle()
|
|
59
|
+
fig.canvas.flush_events()
|
|
60
|
+
except Exception:
|
|
61
|
+
pass
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
if _isnotebook():
|
|
65
|
+
try:
|
|
66
|
+
fig.canvas.draw_idle()
|
|
67
|
+
fig.canvas.flush_events()
|
|
68
|
+
except Exception:
|
|
69
|
+
pass
|
|
70
|
+
|
|
71
|
+
backend = plt.get_backend().lower()
|
|
72
|
+
if (
|
|
73
|
+
"inline" in backend
|
|
74
|
+
or "matplotlib_inline" in backend
|
|
75
|
+
or sys.platform == "emscripten"
|
|
76
|
+
):
|
|
77
|
+
try:
|
|
78
|
+
import importlib
|
|
79
|
+
|
|
80
|
+
ipdisplay = importlib.import_module("IPython.display")
|
|
81
|
+
ipdisplay.clear_output(wait=True)
|
|
82
|
+
ipdisplay.display(fig)
|
|
83
|
+
return
|
|
84
|
+
except Exception:
|
|
85
|
+
pass
|
|
86
|
+
|
|
87
|
+
plt.pause(dt)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class Trailer:
|
|
91
|
+
def __init__(self, L1=1, L2=1, animation=None, polygon=None, **kwargs):
|
|
92
|
+
"""
|
|
93
|
+
_summary_
|
|
94
|
+
|
|
95
|
+
:param L1: _description_, defaults to 1
|
|
96
|
+
:type L1: int, optional
|
|
97
|
+
:param L2: _description_, defaults to 1
|
|
98
|
+
:type L2: int, optional
|
|
99
|
+
:param animation: _description_, defaults to None
|
|
100
|
+
:type animation: _type_, optional
|
|
101
|
+
:param polygon: bounding polygon of vehicle
|
|
102
|
+
:type polygon: :class:`~spatialmath.geom2d.Polygon2`
|
|
103
|
+
"""
|
|
104
|
+
self._L1 = L1
|
|
105
|
+
self._L2 = L2
|
|
106
|
+
|
|
107
|
+
self._polygon = polygon
|
|
108
|
+
if animation is not None:
|
|
109
|
+
if isinstance(animation, str):
|
|
110
|
+
animation = VehiclePolygon(animation)
|
|
111
|
+
self._animation = animation
|
|
112
|
+
elif polygon is not None:
|
|
113
|
+
self._animation = VehiclePolygon(polygon)
|
|
114
|
+
|
|
115
|
+
self._kwargs = kwargs
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class VehicleBase(ABC):
|
|
119
|
+
def __init__(
|
|
120
|
+
self,
|
|
121
|
+
covar=None,
|
|
122
|
+
speed_max=np.inf,
|
|
123
|
+
accel_max=np.inf,
|
|
124
|
+
x0=[0, 0, 0],
|
|
125
|
+
dt=0.1,
|
|
126
|
+
control=None,
|
|
127
|
+
seed=0,
|
|
128
|
+
animation=None,
|
|
129
|
+
verbose=False,
|
|
130
|
+
plot=False,
|
|
131
|
+
workspace=None,
|
|
132
|
+
polygon=None,
|
|
133
|
+
trailers=None,
|
|
134
|
+
):
|
|
135
|
+
r"""
|
|
136
|
+
Superclass for vehicle kinematic models
|
|
137
|
+
|
|
138
|
+
:param covar: odometry covariance, defaults to zero
|
|
139
|
+
:type covar: ndarray(2,2), optional
|
|
140
|
+
:param speed_max: maximum speed, defaults to :math:`\infty`
|
|
141
|
+
:type speed_max: float, optional
|
|
142
|
+
:param accel_max: maximum acceleration, defaults to :math:`\infty`
|
|
143
|
+
:type accel_max: float, optional
|
|
144
|
+
:param x0: Initial state, defaults to (0,0,0)
|
|
145
|
+
:type x0: array_like(3), optional
|
|
146
|
+
:param dt: sample update interval, defaults to 0.1
|
|
147
|
+
:type dt: float, optional
|
|
148
|
+
:param control: vehicle control inputs, defaults to None
|
|
149
|
+
:type control: array_like(2), interp1d, VehicleDriverBase
|
|
150
|
+
:param animation: Graphical animation of vehicle, defaults to None
|
|
151
|
+
:type animation: :class:`VehicleAnimationBase` subclass, optional
|
|
152
|
+
:param verbose: print lots of info, defaults to False
|
|
153
|
+
:type verbose: bool, optional
|
|
154
|
+
:param workspace: dimensions of 2D plot area, defaults to (-10:10) x (-10:10),
|
|
155
|
+
see :func:`~spatialmath.base.graphics.plotvol2`
|
|
156
|
+
:type workspace: float, array_like(2), array_like(4)
|
|
157
|
+
:param polygon: bounding polygon of vehicle
|
|
158
|
+
:type polygon: :class:`~spatialmath.geom2d.Polygon2`
|
|
159
|
+
|
|
160
|
+
This is an abstract superclass that simulates the motion of a mobile
|
|
161
|
+
robot under the action of a controller. The controller provides
|
|
162
|
+
control inputs to the vehicle, and the output odometry is returned.
|
|
163
|
+
The true state, effectively unknowable in practice, is computed
|
|
164
|
+
and accessible.
|
|
165
|
+
|
|
166
|
+
The workspace can be specified in several ways:
|
|
167
|
+
|
|
168
|
+
============== ======= =======
|
|
169
|
+
``workspace`` x-range y-range
|
|
170
|
+
============== ======= =======
|
|
171
|
+
A (scalar) -A:A -A:A
|
|
172
|
+
[A, B] A:B A:B
|
|
173
|
+
[A, B, C, D] A:B C:D
|
|
174
|
+
============== ======= =======
|
|
175
|
+
|
|
176
|
+
:note: Set ``seed=None`` to have it randomly initialized from the
|
|
177
|
+
operating system.
|
|
178
|
+
|
|
179
|
+
:seealso: :class:`Bicycle` :class:`Unicycle` :class:`VehicleAnimationBase`
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
self._V = covar
|
|
183
|
+
self._dt = dt
|
|
184
|
+
if x0 is None:
|
|
185
|
+
x0 = np.zeros((3,), dtype=float)
|
|
186
|
+
else:
|
|
187
|
+
x0 = base.getvector(x0)
|
|
188
|
+
if len(x0) not in (2, 3):
|
|
189
|
+
raise ValueError("x0 must be length 2 or 3")
|
|
190
|
+
self._x0 = x0
|
|
191
|
+
self._x = x0.copy()
|
|
192
|
+
|
|
193
|
+
self._random = np.random.default_rng(seed)
|
|
194
|
+
self._seed = seed
|
|
195
|
+
self._speed_max = speed_max
|
|
196
|
+
self._accel_max = accel_max
|
|
197
|
+
self._v_prev = [0]
|
|
198
|
+
|
|
199
|
+
self._polygon = polygon
|
|
200
|
+
if isinstance(animation, str):
|
|
201
|
+
animation = VehiclePolygon(animation)
|
|
202
|
+
self._animation = animation
|
|
203
|
+
self._ax = None
|
|
204
|
+
|
|
205
|
+
if control is not None:
|
|
206
|
+
self.add_driver(control)
|
|
207
|
+
|
|
208
|
+
self._dt = dt
|
|
209
|
+
self._t = 0
|
|
210
|
+
self._stopsim = False
|
|
211
|
+
|
|
212
|
+
self._verbose = verbose
|
|
213
|
+
self._plot = False
|
|
214
|
+
|
|
215
|
+
self._control = control
|
|
216
|
+
self._x_hist = []
|
|
217
|
+
|
|
218
|
+
if workspace:
|
|
219
|
+
try:
|
|
220
|
+
self._workspace = workspace.workspace
|
|
221
|
+
except AttributeError:
|
|
222
|
+
self._workspace = base.expand_dims(workspace)
|
|
223
|
+
else:
|
|
224
|
+
self._workspace = None
|
|
225
|
+
|
|
226
|
+
def __str__(self):
|
|
227
|
+
"""
|
|
228
|
+
String representation of vehicle (superclass)
|
|
229
|
+
|
|
230
|
+
:return: String representation of vehicle object
|
|
231
|
+
:rtype: str
|
|
232
|
+
"""
|
|
233
|
+
s = f"{self.__class__.__name__}: "
|
|
234
|
+
s += f"x = {base.array2str(self._x)}"
|
|
235
|
+
return s
|
|
236
|
+
|
|
237
|
+
def __repr__(self):
|
|
238
|
+
return str(self)
|
|
239
|
+
|
|
240
|
+
def f(self, x, odo, v=None):
|
|
241
|
+
r"""
|
|
242
|
+
State transition function
|
|
243
|
+
|
|
244
|
+
:param x: vehicle state :math:`(x, y, \theta)`
|
|
245
|
+
:type x: array_like(3), ndarray(n,3)
|
|
246
|
+
:param odo: vehicle odometry :math:`(\delta_d, \delta_\theta)`
|
|
247
|
+
:type odo: array_like(2)
|
|
248
|
+
:param v: additive odometry noise, defaults to (0,0)
|
|
249
|
+
:type v: array_like(2), optional
|
|
250
|
+
:return: predicted vehicle state
|
|
251
|
+
:rtype: ndarray(3)
|
|
252
|
+
|
|
253
|
+
Predict the next state based on current state and odometry
|
|
254
|
+
value. ``v`` is a random variable that represents additive
|
|
255
|
+
odometry noise for simulation purposes.
|
|
256
|
+
|
|
257
|
+
.. math::
|
|
258
|
+
|
|
259
|
+
f: \vec{x}_k, \delta_d, \delta_\theta \mapsto \vec{x}_{k+1}
|
|
260
|
+
|
|
261
|
+
For particle filters it is useful to apply the odometry to the
|
|
262
|
+
states of all particles and this can be achieved if ``x`` is a 2D
|
|
263
|
+
array with one state per row. ``v`` is ignored in this case.
|
|
264
|
+
|
|
265
|
+
.. note:: This is the state update equation used for EKF localization.
|
|
266
|
+
|
|
267
|
+
:seealso: :meth:`deriv` :meth:`Fx` :meth:`Fv`
|
|
268
|
+
"""
|
|
269
|
+
odo = base.getvector(odo, 2)
|
|
270
|
+
|
|
271
|
+
if isinstance(x, np.ndarray) and x.ndim == 2:
|
|
272
|
+
# x is Nx3 set of vehicle states, do vectorized form
|
|
273
|
+
# used by particle filter
|
|
274
|
+
dd, dth = odo
|
|
275
|
+
theta = x[:, 2]
|
|
276
|
+
return (
|
|
277
|
+
np.array(x)
|
|
278
|
+
+ np.c_[
|
|
279
|
+
dd * np.cos(theta), dd * np.sin(theta), np.full(theta.shape, dth)
|
|
280
|
+
]
|
|
281
|
+
)
|
|
282
|
+
else:
|
|
283
|
+
# x is a vector
|
|
284
|
+
x = base.getvector(x, 3)
|
|
285
|
+
dd, dth = odo
|
|
286
|
+
theta = x[2]
|
|
287
|
+
|
|
288
|
+
if v is not None:
|
|
289
|
+
v = base.getvector(v, 2)
|
|
290
|
+
dd += v[0]
|
|
291
|
+
dth += v[1]
|
|
292
|
+
|
|
293
|
+
return x + np.r_[dd * np.cos(theta), dd * np.sin(theta), dth]
|
|
294
|
+
|
|
295
|
+
def Fx(self, x, odo):
|
|
296
|
+
r"""
|
|
297
|
+
Jacobian of state transition function df/dx
|
|
298
|
+
|
|
299
|
+
:param x: vehicle state :math:`(x, y, \theta)`
|
|
300
|
+
:type x: array_like(3)
|
|
301
|
+
:param odo: vehicle odometry :math:`(\delta_d, \delta_\theta)`
|
|
302
|
+
:type odo: array_like(2)
|
|
303
|
+
:return: Jacobian matrix
|
|
304
|
+
:rtype: ndarray(3,3)
|
|
305
|
+
|
|
306
|
+
Returns the Jacobian matrix :math:`\frac{\partial \vec{f}}{\partial \vec{x}}` for
|
|
307
|
+
the given state and odometry.
|
|
308
|
+
|
|
309
|
+
:seealso: :meth:`f` :meth:`deriv` :meth:`Fv`
|
|
310
|
+
"""
|
|
311
|
+
dd, dth = odo
|
|
312
|
+
theta = x[2]
|
|
313
|
+
|
|
314
|
+
# fmt: off
|
|
315
|
+
J = np.array([
|
|
316
|
+
[1, 0, -dd * sin(theta)],
|
|
317
|
+
[0, 1, dd * cos(theta)],
|
|
318
|
+
[0, 0, 1],
|
|
319
|
+
])
|
|
320
|
+
# fmt: on
|
|
321
|
+
return J
|
|
322
|
+
|
|
323
|
+
def Fv(self, x, odo):
|
|
324
|
+
r"""
|
|
325
|
+
Jacobian of state transition function df/dv
|
|
326
|
+
|
|
327
|
+
:param x: vehicle state :math:`(x, y, \theta)`
|
|
328
|
+
:type x: array_like(3)
|
|
329
|
+
:param odo: vehicle odometry :math:`(\delta_d, \delta_\theta)`
|
|
330
|
+
:type odo: array_like(2)
|
|
331
|
+
:return: Jacobian matrix
|
|
332
|
+
:rtype: ndarray(3,2)
|
|
333
|
+
|
|
334
|
+
Returns the Jacobian matrix :math:`\frac{\partial \vec{f}}{\partial \vec{v}}` for
|
|
335
|
+
the given state and odometry.
|
|
336
|
+
|
|
337
|
+
:seealso: :meth:`f` :meth:`deriv` :meth:`Fx`
|
|
338
|
+
"""
|
|
339
|
+
dd, dth = odo
|
|
340
|
+
theta = x[2]
|
|
341
|
+
|
|
342
|
+
# fmt: off
|
|
343
|
+
J = np.array([
|
|
344
|
+
[cos(theta), 0],
|
|
345
|
+
[sin(theta), 0],
|
|
346
|
+
[0, 1],
|
|
347
|
+
])
|
|
348
|
+
# fmt: on
|
|
349
|
+
return J
|
|
350
|
+
|
|
351
|
+
@property
|
|
352
|
+
def control(self):
|
|
353
|
+
"""
|
|
354
|
+
Get/set vehicle control (superclass)
|
|
355
|
+
|
|
356
|
+
:getter: Returns vehicle's control
|
|
357
|
+
:setter: Sets the vehicle's control
|
|
358
|
+
:type: 2-tuple, callable, interp1d or VehicleDriver
|
|
359
|
+
|
|
360
|
+
This is the input to the vehicle during a simulation performed
|
|
361
|
+
by :meth:`run`. The control input can be:
|
|
362
|
+
|
|
363
|
+
* a constant tuple as the control inputs to the vehicle
|
|
364
|
+
* a function called as ``f(vehicle, t, x)`` that returns a tuple
|
|
365
|
+
* an interpolator called as ``f(t)`` that returns a tuple
|
|
366
|
+
* a driver agent, subclass of :class:`~roboticstoolbox.mobile.driversVehicleDriverBase`
|
|
367
|
+
|
|
368
|
+
Example:
|
|
369
|
+
|
|
370
|
+
.. runblock:: pycon
|
|
371
|
+
|
|
372
|
+
>>> from roboticstoolbox import Bicycle, RandomPath
|
|
373
|
+
>>> bike = Bicycle()
|
|
374
|
+
>>> bike.control = RandomPath(10)
|
|
375
|
+
>>> print(bike)
|
|
376
|
+
|
|
377
|
+
:seealso: :meth:`run` :meth:`eval_control` :obj:`scipy.interpolate.interp1d` :class:`~roboticstoolbox.mobile.drivers.VehicleDriverBase`
|
|
378
|
+
"""
|
|
379
|
+
return self._control
|
|
380
|
+
|
|
381
|
+
@control.setter
|
|
382
|
+
def control(self, control):
|
|
383
|
+
|
|
384
|
+
# * a function called as ``f(vehicle, t, x)`` that returns a tuple
|
|
385
|
+
# * an interpolator called as f(t) that returns a tuple, see
|
|
386
|
+
# SciPy interp1d
|
|
387
|
+
|
|
388
|
+
self._control = control
|
|
389
|
+
if isinstance(control, VehicleDriverBase):
|
|
390
|
+
# if this is a driver agent, connect it to the vehicle
|
|
391
|
+
control.vehicle = self
|
|
392
|
+
|
|
393
|
+
def eval_control(self, control, x):
|
|
394
|
+
"""
|
|
395
|
+
Evaluate vehicle control input (superclass method)
|
|
396
|
+
|
|
397
|
+
:param control: vehicle control
|
|
398
|
+
:type control: [type]
|
|
399
|
+
:param x: vehicle state :math:`(x, y, \theta)`
|
|
400
|
+
:type x: array_like(3)
|
|
401
|
+
:raises ValueError: bad control
|
|
402
|
+
:return: vehicle control inputs
|
|
403
|
+
:rtype: ndarray(2)
|
|
404
|
+
|
|
405
|
+
Evaluates the control for this time step and state. Control is set
|
|
406
|
+
by the :meth:`control` property to:
|
|
407
|
+
|
|
408
|
+
* a constant tuple as the control inputs to the vehicle
|
|
409
|
+
* a function called as ``f(vehicle, t, x)`` that returns a tuple
|
|
410
|
+
* an interpolator called as f(t) that returns a tuple
|
|
411
|
+
* a driver agent, subclass of :class:`VehicleDriverBase`
|
|
412
|
+
|
|
413
|
+
Vehicle steering, speed and acceleration limits are applied to the
|
|
414
|
+
result before being input to the vehicle model.
|
|
415
|
+
|
|
416
|
+
:seealso: :meth:`run` :meth:`control` :func:`scipy.interpolate.interp1d`
|
|
417
|
+
"""
|
|
418
|
+
# was called control() in the MATLAB version
|
|
419
|
+
|
|
420
|
+
if base.isvector(control, 2):
|
|
421
|
+
# control is a constant
|
|
422
|
+
u = base.getvector(control, 2)
|
|
423
|
+
|
|
424
|
+
elif isinstance(control, VehicleDriverBase):
|
|
425
|
+
# vehicle has a driver object
|
|
426
|
+
u = control.demand()
|
|
427
|
+
|
|
428
|
+
elif isinstance(control, interpolate.interpolate.interp1d):
|
|
429
|
+
# control is an interp1d object
|
|
430
|
+
u = control(self._t)
|
|
431
|
+
|
|
432
|
+
elif callable(control):
|
|
433
|
+
# control is a user function of time and state
|
|
434
|
+
u = control(self, self._t, x)
|
|
435
|
+
|
|
436
|
+
else:
|
|
437
|
+
raise ValueError("bad control specified")
|
|
438
|
+
|
|
439
|
+
# apply limits
|
|
440
|
+
ulim = self.u_limited(u)
|
|
441
|
+
return ulim
|
|
442
|
+
|
|
443
|
+
def limits_va(self, v, v_prev):
|
|
444
|
+
"""
|
|
445
|
+
Apply velocity and acceleration limits (superclass)
|
|
446
|
+
|
|
447
|
+
:param v: desired velocity
|
|
448
|
+
:type v: float
|
|
449
|
+
:param v_prev: previous velocity, reference to list
|
|
450
|
+
:type v_prev: list with single element
|
|
451
|
+
:return: allowed velocity
|
|
452
|
+
:rtype: float
|
|
453
|
+
|
|
454
|
+
Determine allowable velocity given desired velocity, speed and
|
|
455
|
+
acceleration limits.
|
|
456
|
+
|
|
457
|
+
.. note:: This function requires previous velocity, ``v_prev`` to enable
|
|
458
|
+
acceleration limiting. This is passed as a reference to a mutable value,
|
|
459
|
+
a single-element list. This is reset to zero at the start of each simulation.
|
|
460
|
+
"""
|
|
461
|
+
# acceleration limit
|
|
462
|
+
vp = v_prev[0]
|
|
463
|
+
if self._accel_max is not None:
|
|
464
|
+
if (v - vp) / self._dt > self._accel_max:
|
|
465
|
+
v = vp + self._accel_max * self._dt
|
|
466
|
+
elif (v - vp) / self._dt < -self._accel_max:
|
|
467
|
+
v = vp - self._accel_max * self._dt
|
|
468
|
+
v_prev[0] = v
|
|
469
|
+
|
|
470
|
+
# speed limit
|
|
471
|
+
if self._speed_max is not None:
|
|
472
|
+
v = np.clip(v, -self._speed_max, self._speed_max)
|
|
473
|
+
return v
|
|
474
|
+
|
|
475
|
+
def polygon(self, q):
|
|
476
|
+
"""
|
|
477
|
+
Bounding polygon at vehicle configuration
|
|
478
|
+
|
|
479
|
+
:param q: vehicle configuration :math:`(x, y, \theta)`
|
|
480
|
+
:type q: array_like(3)
|
|
481
|
+
:return: bounding polygon of vehicle at configuration ``q``
|
|
482
|
+
:rtype: :class:`~spatialmath.geom2d.Polygon2`
|
|
483
|
+
|
|
484
|
+
The bounding polygon of the vehicle is returned for the configuration
|
|
485
|
+
``q``. Can be used for collision checking using the :meth:`~spatialmath.geom2d.Polygon2.intersects`
|
|
486
|
+
method.
|
|
487
|
+
|
|
488
|
+
:seealso: :class:`~spatialmath.geom2d.Polygon2`
|
|
489
|
+
"""
|
|
490
|
+
return self._polygon.transformed(SE2(q))
|
|
491
|
+
|
|
492
|
+
# This function is overridden by the child class
|
|
493
|
+
@abstractmethod
|
|
494
|
+
def deriv(self, x, u):
|
|
495
|
+
pass
|
|
496
|
+
|
|
497
|
+
def add_driver(self, driver):
|
|
498
|
+
"""
|
|
499
|
+
Add a driver agent (superclass)
|
|
500
|
+
|
|
501
|
+
:param driver: a driver agent object
|
|
502
|
+
:type driver: VehicleDriverBase subclass
|
|
503
|
+
|
|
504
|
+
.. warning:: Deprecated. Use ``vehicle.control = driver`` instead.
|
|
505
|
+
|
|
506
|
+
:seealso: :class:`VehicleDriverBase` :meth:`control`
|
|
507
|
+
"""
|
|
508
|
+
|
|
509
|
+
warnings.warn("add_driver is deprecated, use veh.control=driver instead")
|
|
510
|
+
self._control = driver
|
|
511
|
+
driver._veh = self
|
|
512
|
+
|
|
513
|
+
def run(self, T=10, x0=None, control=None, animate=True):
|
|
514
|
+
r"""
|
|
515
|
+
Simulate motion of vehicle (superclass)
|
|
516
|
+
|
|
517
|
+
:param T: Simulation time in seconds, defaults to 10
|
|
518
|
+
:type T: float, optional
|
|
519
|
+
:param x0: Initial state, defaults to value given to Vehicle constructor
|
|
520
|
+
:type x0: array_like(3) or array_like(2)
|
|
521
|
+
:param control: vehicle control inputs, defaults to None
|
|
522
|
+
:type control: array_like(2), callable, driving agent
|
|
523
|
+
:param animate: Enable graphical animation of vehicle, defaults to False
|
|
524
|
+
:type animate: bool, optional
|
|
525
|
+
:return: State trajectory, each row is :math:`(x,y,\theta)`.
|
|
526
|
+
:rtype: ndarray(n,3)
|
|
527
|
+
|
|
528
|
+
Runs the vehicle simulation for ``T`` seconds and optionally plots
|
|
529
|
+
an animation. The method :meth:`step` performs each time step.
|
|
530
|
+
|
|
531
|
+
The control inputs are provided by ``control`` which can be:
|
|
532
|
+
|
|
533
|
+
* a constant tuple as the control inputs to the vehicle
|
|
534
|
+
* a function called as ``f(vehicle, t, x)`` that returns a tuple
|
|
535
|
+
* an interpolator called as ``f(t)`` that returns a tuple, see
|
|
536
|
+
SciPy interp1d
|
|
537
|
+
* a driver agent, subclass of :class:`VehicleDriverBase`
|
|
538
|
+
|
|
539
|
+
This is evaluated by :meth:`eval_control` which applies velocity,
|
|
540
|
+
acceleration and steering limits.
|
|
541
|
+
|
|
542
|
+
The simulation can be stopped prematurely by the control function
|
|
543
|
+
calling :meth:`stopsim`.
|
|
544
|
+
|
|
545
|
+
.. note::
|
|
546
|
+
* the simulation is fixed-time step with the step given by the ``dt``
|
|
547
|
+
attribute set by the constructor.
|
|
548
|
+
* integration uses rectangular integration.
|
|
549
|
+
|
|
550
|
+
:seealso: :meth:`init` :meth:`step` :meth:`control` :meth:`run_animation`
|
|
551
|
+
"""
|
|
552
|
+
|
|
553
|
+
self.init(control=control, animate=animate, x0=x0)
|
|
554
|
+
|
|
555
|
+
for i in range(round(T / self.dt)):
|
|
556
|
+
self.step(animate=animate)
|
|
557
|
+
|
|
558
|
+
# check for user requested stop
|
|
559
|
+
if self._stopsim:
|
|
560
|
+
print("USER REEQUESTED STOP AT time", self._t)
|
|
561
|
+
break
|
|
562
|
+
|
|
563
|
+
return self.x_hist
|
|
564
|
+
|
|
565
|
+
def run_animation(self, T=10, x0=None, control=None, format=None, file=None):
|
|
566
|
+
r"""
|
|
567
|
+
Simulate motion of vehicle (superclass)
|
|
568
|
+
|
|
569
|
+
:param T: Simulation time in seconds, defaults to 10
|
|
570
|
+
:type T: float, optional
|
|
571
|
+
:param x0: Initial state, defaults to value given to Vehicle constructor
|
|
572
|
+
:type x0: array_like(3) or array_like(2)
|
|
573
|
+
:param control: vehicle control inputs, defaults to None
|
|
574
|
+
:type control: array_like(2), callable, driving agent
|
|
575
|
+
:param format: Output format
|
|
576
|
+
:type format: str, optional
|
|
577
|
+
:param file: File name
|
|
578
|
+
:type file: str, optional
|
|
579
|
+
:return: Matplotlib animation object
|
|
580
|
+
:rtype: :meth:`matplotlib.animation.FuncAnimation`
|
|
581
|
+
|
|
582
|
+
Runs the vehicle simulation for ``T`` seconds and returns an animation
|
|
583
|
+
in various formats::
|
|
584
|
+
|
|
585
|
+
``format`` ``file`` description
|
|
586
|
+
============ ========= ============================
|
|
587
|
+
``"html"`` str, None return HTML5 video
|
|
588
|
+
``"jshtml"`` str, None return JS+HTML video
|
|
589
|
+
``"gif"`` str return animated GIF
|
|
590
|
+
``"mp4"`` str return MP4/H264 video
|
|
591
|
+
``None`` return a ``FuncAnimation`` object
|
|
592
|
+
|
|
593
|
+
The allowables types for ``file`` are given in the second column. A str
|
|
594
|
+
value is the file name. If ``None`` is an option then return the video as a string.
|
|
595
|
+
|
|
596
|
+
For the last case, a reference to the animation object must be held if used for
|
|
597
|
+
animation in a Jupyter cell::
|
|
598
|
+
|
|
599
|
+
anim = robot.run_animation(T=20)
|
|
600
|
+
|
|
601
|
+
The control inputs are provided by ``control`` which can be:
|
|
602
|
+
|
|
603
|
+
* a constant tuple as the control inputs to the vehicle
|
|
604
|
+
* a function called as ``f(vehicle, t, x)`` that returns a tuple
|
|
605
|
+
* an interpolator called as ``f(t)`` that returns a tuple, see
|
|
606
|
+
SciPy interp1d
|
|
607
|
+
* a driver agent, subclass of :class:`VehicleDriverBase`
|
|
608
|
+
|
|
609
|
+
This is evaluated by :meth:`eval_control` which applies velocity,
|
|
610
|
+
acceleration and steering limits.
|
|
611
|
+
|
|
612
|
+
The simulation can be stopped prematurely by the control function
|
|
613
|
+
calling :meth:`stopsim`.
|
|
614
|
+
|
|
615
|
+
.. note::
|
|
616
|
+
* the simulation is fixed-time step with the step given by the ``dt``
|
|
617
|
+
attribute set by the constructor.
|
|
618
|
+
* integration uses rectangular integration.
|
|
619
|
+
|
|
620
|
+
:seealso: :meth:`init` :meth:`step` :meth:`control` :meth:`run_animation`
|
|
621
|
+
"""
|
|
622
|
+
|
|
623
|
+
fig, ax = plt.subplots()
|
|
624
|
+
|
|
625
|
+
nframes = round(T / self.dt)
|
|
626
|
+
anim = animation.FuncAnimation(
|
|
627
|
+
fig=fig,
|
|
628
|
+
func=lambda i: self.step(animate=True, pause=False),
|
|
629
|
+
init_func=lambda: self.init(animate=True),
|
|
630
|
+
frames=nframes,
|
|
631
|
+
interval=self.dt * 1000,
|
|
632
|
+
blit=False,
|
|
633
|
+
repeat=False,
|
|
634
|
+
)
|
|
635
|
+
# anim._interval = self.dt*1000/2
|
|
636
|
+
# anim._repeat = True
|
|
637
|
+
ret = None
|
|
638
|
+
if format == "html":
|
|
639
|
+
ret = anim.to_html5_video() # convert to embeddable HTML5 animation
|
|
640
|
+
elif format == "jshtml":
|
|
641
|
+
ret = anim.to_jshtml() # convert to embeddable Javascript/HTML animation
|
|
642
|
+
elif format == "gif":
|
|
643
|
+
anim.save(
|
|
644
|
+
file, writer=animation.PillowWriter(fps=1 / self.dt)
|
|
645
|
+
) # convert to GIF
|
|
646
|
+
ret = None
|
|
647
|
+
elif format == "mp4":
|
|
648
|
+
anim.save(
|
|
649
|
+
file, writer=animation.FFMpegWriter(fps=1 / self.dt)
|
|
650
|
+
) # convert to mp4/H264
|
|
651
|
+
ret = None
|
|
652
|
+
elif format == None:
|
|
653
|
+
# return the anim object
|
|
654
|
+
return anim
|
|
655
|
+
else:
|
|
656
|
+
raise ValueError("unknown format")
|
|
657
|
+
|
|
658
|
+
if ret is not None and file is not None:
|
|
659
|
+
with open(file, "w") as f:
|
|
660
|
+
f.write(ret)
|
|
661
|
+
ret = None
|
|
662
|
+
plt.close(fig)
|
|
663
|
+
return ret
|
|
664
|
+
|
|
665
|
+
def init(self, x0=None, control=None, animate=True):
|
|
666
|
+
"""
|
|
667
|
+
Initialize for simulation (superclass)
|
|
668
|
+
|
|
669
|
+
:param x0: Initial state, defaults to value given to Vehicle constructor
|
|
670
|
+
:type x0: array_like(3) or array_like(2)
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
Performs the following initializations:
|
|
674
|
+
|
|
675
|
+
#. Clears the state history
|
|
676
|
+
#. Set the private random number generator to initial value
|
|
677
|
+
#. Sets state :math:`x = x_0`
|
|
678
|
+
#. Sets previous velocity to zero
|
|
679
|
+
#. If a driver is attached, initialize it
|
|
680
|
+
#. If animation is enabled, initialize that
|
|
681
|
+
|
|
682
|
+
If animation is enabled by constructor and no animation object is given,
|
|
683
|
+
use a default ``VehiclePolygon("car")``
|
|
684
|
+
|
|
685
|
+
:seealso: :class:`VehicleAnimationBase` :meth:`run`
|
|
686
|
+
"""
|
|
687
|
+
if x0 is not None:
|
|
688
|
+
self._x = base.getvector(x0, 3)
|
|
689
|
+
else:
|
|
690
|
+
self._x = self._x0.copy()
|
|
691
|
+
|
|
692
|
+
self._x_hist = []
|
|
693
|
+
|
|
694
|
+
if self._seed is not None:
|
|
695
|
+
self._random = np.random.default_rng(self._seed)
|
|
696
|
+
|
|
697
|
+
if control is not None:
|
|
698
|
+
# override control
|
|
699
|
+
self._control = control
|
|
700
|
+
|
|
701
|
+
if isinstance(self._control, VehicleDriverBase):
|
|
702
|
+
self._control.init()
|
|
703
|
+
|
|
704
|
+
self._t = 0
|
|
705
|
+
self._v_prev = [0]
|
|
706
|
+
|
|
707
|
+
# initialize the graphics
|
|
708
|
+
if animate and self._animation is not None:
|
|
709
|
+
# setup the plot
|
|
710
|
+
self._ax = base.plotvol2(self.workspace)
|
|
711
|
+
|
|
712
|
+
self._ax.set_xlabel("x")
|
|
713
|
+
self._ax.set_ylabel("y")
|
|
714
|
+
self._ax.set_aspect("equal")
|
|
715
|
+
try:
|
|
716
|
+
self._ax.figure.canvas.manager.set_window_title(
|
|
717
|
+
f"Robotics Toolbox for Python (Figure {self._ax.figure.number})"
|
|
718
|
+
)
|
|
719
|
+
except AttributeError:
|
|
720
|
+
pass
|
|
721
|
+
|
|
722
|
+
self._animation.add(ax=self._ax) # add vehicle animation to axis
|
|
723
|
+
self._timer = plt.figtext(0.85, 0.95, "") # display time counter
|
|
724
|
+
|
|
725
|
+
# initialize the driver
|
|
726
|
+
if isinstance(self._control, VehicleDriverBase):
|
|
727
|
+
self._control.init(ax=self._ax)
|
|
728
|
+
|
|
729
|
+
def plot(self, x):
|
|
730
|
+
self._animation.update(x)
|
|
731
|
+
|
|
732
|
+
def step(self, u=None, animate=True, pause=True):
|
|
733
|
+
r"""
|
|
734
|
+
Step simulator by one time step (superclass)
|
|
735
|
+
|
|
736
|
+
:return: odometry :math:`(\delta_d, \delta_\theta)`
|
|
737
|
+
:rtype: ndarray(2)
|
|
738
|
+
|
|
739
|
+
#. Obtain the vehicle control inputs
|
|
740
|
+
#. Integrate the vehicle state forward one timestep
|
|
741
|
+
#. Updates the stored state and state history
|
|
742
|
+
#. Update animation if enabled.
|
|
743
|
+
#. Returns the odometry
|
|
744
|
+
|
|
745
|
+
- ``veh.step((vel, steer))`` for a Bicycle vehicle model
|
|
746
|
+
- ``veh.step((vel, vel_diff))`` for a Unicycle vehicle model
|
|
747
|
+
- ``veh.step()`` as above but control is taken from the ``control``
|
|
748
|
+
attribute which might be a function or driver agent.
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
Example:
|
|
752
|
+
|
|
753
|
+
.. runblock:: pycon
|
|
754
|
+
|
|
755
|
+
>>> from roboticstoolbox import Bicycle
|
|
756
|
+
>>> bike = Bicycle() # default bicycle model
|
|
757
|
+
>>> bike.step((1, 0.2)) # one step: v=1, γ=0.2
|
|
758
|
+
>>> bike.x
|
|
759
|
+
>>> bike.step((1, 0.2)) # another step: v=1, γ=0.2
|
|
760
|
+
>>> bike.x
|
|
761
|
+
|
|
762
|
+
.. note:: Vehicle control input limits are applied.
|
|
763
|
+
|
|
764
|
+
:seealso: :func:`control`, :func:`update`, :func:`run`
|
|
765
|
+
"""
|
|
766
|
+
# determine vehicle control
|
|
767
|
+
if u is not None:
|
|
768
|
+
u = self.eval_control(u, self._x)
|
|
769
|
+
else:
|
|
770
|
+
u = self.eval_control(self._control, self._x)
|
|
771
|
+
|
|
772
|
+
# update state (used to be function control() in MATLAB version)
|
|
773
|
+
xd = self._dt * self.deriv(self._x, u) # delta state
|
|
774
|
+
|
|
775
|
+
# update state vector
|
|
776
|
+
self._x += xd
|
|
777
|
+
self._x_hist.append(tuple(self._x))
|
|
778
|
+
|
|
779
|
+
# print('VEH', u, self.x)
|
|
780
|
+
|
|
781
|
+
# odometry comes from change in state vector
|
|
782
|
+
odo = np.r_[np.linalg.norm(xd[0:2]), xd[2]]
|
|
783
|
+
|
|
784
|
+
if self._V is not None:
|
|
785
|
+
odo += self.random.multivariate_normal((0, 0), self._V)
|
|
786
|
+
|
|
787
|
+
# do the graphics
|
|
788
|
+
if animate and self._animation:
|
|
789
|
+
self.plot(self._x)
|
|
790
|
+
# if self._timer is not None:
|
|
791
|
+
# self._timer.set_text(f"t = {self._t:.2f}")
|
|
792
|
+
_refresh_animation_frame(
|
|
793
|
+
self._ax.figure if self._ax else None, self._dt, pause
|
|
794
|
+
)
|
|
795
|
+
# plt.show(block=False)
|
|
796
|
+
# pass
|
|
797
|
+
|
|
798
|
+
self._t += self._dt
|
|
799
|
+
|
|
800
|
+
# be verbose
|
|
801
|
+
if self._verbose:
|
|
802
|
+
print(
|
|
803
|
+
f"{self._t:8.2f}: u=({u[0]:8.2f}, {u[1]:8.2f}), x=({self._x[0]:8.2f},"
|
|
804
|
+
f" {self._x[1]:8.2f}, {self._x[2]:8.2f})"
|
|
805
|
+
)
|
|
806
|
+
|
|
807
|
+
return odo
|
|
808
|
+
|
|
809
|
+
@property
|
|
810
|
+
def workspace(self):
|
|
811
|
+
"""
|
|
812
|
+
Size of robot workspace (superclass)
|
|
813
|
+
|
|
814
|
+
:return: workspace bounds [xmin, xmax, ymin, ymax]
|
|
815
|
+
:rtype: ndarray(4)
|
|
816
|
+
|
|
817
|
+
Returns the bounds of the workspace as specified by constructor
|
|
818
|
+
option ``workspace``
|
|
819
|
+
"""
|
|
820
|
+
|
|
821
|
+
# get workspace specified for Vehicle or from its driver
|
|
822
|
+
if self._workspace is not None:
|
|
823
|
+
return self._workspace
|
|
824
|
+
if self._control is not None and hasattr(self._control, "_workspace"):
|
|
825
|
+
return self._control._workspace
|
|
826
|
+
|
|
827
|
+
@property
|
|
828
|
+
def x(self):
|
|
829
|
+
r"""
|
|
830
|
+
Get vehicle state/configuration (superclass)
|
|
831
|
+
|
|
832
|
+
:return: Vehicle state :math:`(x, y, \theta)`
|
|
833
|
+
:rtype: ndarray(3)
|
|
834
|
+
|
|
835
|
+
:seealso: :meth:`q`
|
|
836
|
+
"""
|
|
837
|
+
return self._x
|
|
838
|
+
|
|
839
|
+
@property
|
|
840
|
+
def q(self):
|
|
841
|
+
r"""
|
|
842
|
+
Get vehicle state/configuration (superclass)
|
|
843
|
+
|
|
844
|
+
:return: Vehicle state :math:`(x, y, \theta)`
|
|
845
|
+
:rtype: ndarray(3)
|
|
846
|
+
|
|
847
|
+
:seealso: :meth:`x`
|
|
848
|
+
"""
|
|
849
|
+
return self._x
|
|
850
|
+
|
|
851
|
+
@property
|
|
852
|
+
def x0(self):
|
|
853
|
+
r"""
|
|
854
|
+
Get vehicle initial state/configuration (superclass)
|
|
855
|
+
|
|
856
|
+
:return: Vehicle state :math:`(x, y, \theta)`
|
|
857
|
+
:rtype: ndarray(3)
|
|
858
|
+
|
|
859
|
+
Set by :class:`VehicleBase` subclass constructor. The state is set to this value
|
|
860
|
+
at the beginning of each simulation run.
|
|
861
|
+
|
|
862
|
+
:seealso: :meth:`run`
|
|
863
|
+
"""
|
|
864
|
+
return self._x0
|
|
865
|
+
|
|
866
|
+
@x0.setter
|
|
867
|
+
def x0(self, x0):
|
|
868
|
+
r"""
|
|
869
|
+
Set vehicle initial state/configuration (superclass)
|
|
870
|
+
|
|
871
|
+
:param x0: Vehicle state :math:`(x, y, \theta)`
|
|
872
|
+
:type x0: array_like(3)
|
|
873
|
+
|
|
874
|
+
The state is set to this value at the beginning of each simulation
|
|
875
|
+
run. Overrides the value set by :class:`VehicleBase` subclass constructor.
|
|
876
|
+
|
|
877
|
+
:seealso: :func:`run`
|
|
878
|
+
"""
|
|
879
|
+
self._x0 = base.getvector(x0, 3)
|
|
880
|
+
|
|
881
|
+
@property
|
|
882
|
+
def random(self):
|
|
883
|
+
"""
|
|
884
|
+
Get private random number generator
|
|
885
|
+
|
|
886
|
+
:return: NumPy random number generator
|
|
887
|
+
:rtype: :class:`numpy.random.Generator`
|
|
888
|
+
|
|
889
|
+
Has methods including:
|
|
890
|
+
|
|
891
|
+
- :meth:`integers(low, high, size, endpoint) <numpy.random.Generator.integers>`
|
|
892
|
+
- :meth:`random(size) <numpy.random.Generator.random>`
|
|
893
|
+
- :meth:`uniform(low, high, size) <numpy.random.Generator.uniform>`
|
|
894
|
+
- :meth:`normal(mean, std, size) <numpy.random.Generator.normal>`
|
|
895
|
+
- :meth:`multivariate_normal(mean, covar, size) <numpy.random.Generator.multivariate_normal>`
|
|
896
|
+
|
|
897
|
+
The generator is initialized with the seed provided at constructor
|
|
898
|
+
time every time :meth:`init` is called.
|
|
899
|
+
|
|
900
|
+
:seealso: :meth:`init` :func:`numpy.random.default_rng`
|
|
901
|
+
"""
|
|
902
|
+
return self._random
|
|
903
|
+
|
|
904
|
+
@property
|
|
905
|
+
def x_hist(self):
|
|
906
|
+
"""
|
|
907
|
+
Get vehicle state/configuration history (superclass)
|
|
908
|
+
|
|
909
|
+
:return: Vehicle state history
|
|
910
|
+
:rtype: ndarray(n,3)
|
|
911
|
+
|
|
912
|
+
The state :math:`(x, y, \theta)` at each time step resulting from a
|
|
913
|
+
simulation run, one row per timestep.
|
|
914
|
+
|
|
915
|
+
:seealso: :meth:`run`
|
|
916
|
+
"""
|
|
917
|
+
return np.array(self._x_hist)
|
|
918
|
+
|
|
919
|
+
@property
|
|
920
|
+
def speed_max(self):
|
|
921
|
+
"""
|
|
922
|
+
Get maximum speed of vehicle (superclass)
|
|
923
|
+
|
|
924
|
+
:return: maximum speed
|
|
925
|
+
:rtype: float
|
|
926
|
+
|
|
927
|
+
Set by :meth:`VehicleBase` subclass constructor.
|
|
928
|
+
|
|
929
|
+
:seealso: :meth:`accel_max` :meth:`steer_max` :meth:`u_limited`
|
|
930
|
+
"""
|
|
931
|
+
return self._speed_max
|
|
932
|
+
|
|
933
|
+
@property
|
|
934
|
+
def accel_max(self):
|
|
935
|
+
"""
|
|
936
|
+
Get maximum acceleration of vehicle (superclass)
|
|
937
|
+
|
|
938
|
+
:return: maximum acceleration
|
|
939
|
+
:rtype: float
|
|
940
|
+
|
|
941
|
+
Set by :meth:`VehicleBase` subclass constructor.
|
|
942
|
+
|
|
943
|
+
:seealso: :meth:`speed_max` :meth:`steer_max` :meth:`u_limited`
|
|
944
|
+
"""
|
|
945
|
+
return self._accel_max
|
|
946
|
+
|
|
947
|
+
@property
|
|
948
|
+
def dt(self):
|
|
949
|
+
"""
|
|
950
|
+
Get sample time (superclass)
|
|
951
|
+
|
|
952
|
+
:return: discrete time step for simulation
|
|
953
|
+
:rtype: float
|
|
954
|
+
|
|
955
|
+
Set by :meth:`VehicleBase` subclass constructor. Used by
|
|
956
|
+
:meth:`step` to update state.
|
|
957
|
+
|
|
958
|
+
:seealso: :meth:`run`
|
|
959
|
+
"""
|
|
960
|
+
return self._dt
|
|
961
|
+
|
|
962
|
+
@property
|
|
963
|
+
def verbose(self):
|
|
964
|
+
"""
|
|
965
|
+
Get verbosity (superclass)
|
|
966
|
+
|
|
967
|
+
:return: verbosity level
|
|
968
|
+
:rtype: bool
|
|
969
|
+
|
|
970
|
+
Set by :class:`VehicleBase` subclass constructor.
|
|
971
|
+
"""
|
|
972
|
+
return self._verbose
|
|
973
|
+
|
|
974
|
+
@verbose.setter
|
|
975
|
+
def verbose(self, verbose):
|
|
976
|
+
"""
|
|
977
|
+
Set verbosity (superclass)
|
|
978
|
+
|
|
979
|
+
:return: verbosity level
|
|
980
|
+
:rtype: bool
|
|
981
|
+
|
|
982
|
+
Set by :class:`VehicleBase` subclass constructor.
|
|
983
|
+
"""
|
|
984
|
+
self._verbose = verbose
|
|
985
|
+
|
|
986
|
+
def stopsim(self):
|
|
987
|
+
"""
|
|
988
|
+
Stop the simulation (superclass)
|
|
989
|
+
|
|
990
|
+
A control function can stop the simulation initated by the ``run``
|
|
991
|
+
method.
|
|
992
|
+
|
|
993
|
+
:seealso: :meth:`run`
|
|
994
|
+
"""
|
|
995
|
+
self._stopsim = True
|
|
996
|
+
|
|
997
|
+
def plot_xy(self, *args, block=None, **kwargs):
|
|
998
|
+
"""
|
|
999
|
+
Plot xy-path from history
|
|
1000
|
+
|
|
1001
|
+
:param block: block until plot dismissed, defaults to None
|
|
1002
|
+
:type block: bool, optional
|
|
1003
|
+
:param args: positional arguments passed to :meth:`~matplotlib.axes.Axes.plot`
|
|
1004
|
+
:param kwargs: keyword arguments passed to :meth:`~matplotlib.axes.Axes.plot`
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
The :math:`(x,y)` trajectory from the simulation history is plotted as
|
|
1008
|
+
:math:`x` vs :math:`y`.
|
|
1009
|
+
|
|
1010
|
+
:seealso: :meth:`run` :meth:`plot_xyt`
|
|
1011
|
+
"""
|
|
1012
|
+
if args is None and "color" not in kwargs:
|
|
1013
|
+
kwargs["color"] = "b"
|
|
1014
|
+
xyt = self.x_hist
|
|
1015
|
+
plt.plot(xyt[:, 0], xyt[:, 1], *args, **kwargs)
|
|
1016
|
+
if block is not None:
|
|
1017
|
+
plt.show(block=block)
|
|
1018
|
+
|
|
1019
|
+
def plot_xyt(self, block=None, **kwargs):
|
|
1020
|
+
"""
|
|
1021
|
+
Plot configuration vs time from history
|
|
1022
|
+
|
|
1023
|
+
:param block: block until plot dismissed, defaults to False
|
|
1024
|
+
:type block: bool, optional
|
|
1025
|
+
:param args: positional arguments passed to :meth:`~matplotlib.axes.Axes.plot`
|
|
1026
|
+
:param kwargs: keyword arguments passed to :meth:`~matplotlib.axes.Axes.plot`
|
|
1027
|
+
|
|
1028
|
+
The :math:`(x,y, \theta)` trajectory from the simulation history is plotted
|
|
1029
|
+
against time.
|
|
1030
|
+
|
|
1031
|
+
:seealso: :meth:`run` :meth:`plot_xy`
|
|
1032
|
+
"""
|
|
1033
|
+
xyt = self.x_hist
|
|
1034
|
+
t = np.arange(0, xyt.shape[0] * self._dt, self._dt)
|
|
1035
|
+
plt.plot(xyt[:, 0], xyt[:, :], **kwargs)
|
|
1036
|
+
plt.legend(["x", "y", "$\\theta$"])
|
|
1037
|
+
if block is not None:
|
|
1038
|
+
plt.show(block=block)
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
# ========================================================================= #
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
class Bicycle(VehicleBase):
|
|
1045
|
+
def __init__(self, L=1, steer_max=0.45 * pi, **kwargs):
|
|
1046
|
+
r"""
|
|
1047
|
+
Create bicycle kinematic model
|
|
1048
|
+
|
|
1049
|
+
:param L: wheel base, defaults to 1
|
|
1050
|
+
:type L: float, optional
|
|
1051
|
+
:param steer_max: maximum steering angle, defaults to :math:`0.45\pi`
|
|
1052
|
+
:type steer_max: float, optional
|
|
1053
|
+
:param kwargs: additional arguments passed to :class:`VehicleBase`
|
|
1054
|
+
constructor
|
|
1055
|
+
|
|
1056
|
+
Model the motion of a bicycle model with equations of motion given by:
|
|
1057
|
+
|
|
1058
|
+
.. math::
|
|
1059
|
+
|
|
1060
|
+
\dot{x} &= v \cos \theta \\
|
|
1061
|
+
\dot{y} &= v \sin \theta \\
|
|
1062
|
+
\dot{\theta} &= \frac{v}{L} \tan \gamma
|
|
1063
|
+
|
|
1064
|
+
where :math:`v` is the velocity in body frame x-direction, and
|
|
1065
|
+
:math:`\gamma` is the angle of the steered wheel.
|
|
1066
|
+
|
|
1067
|
+
:seealso: :meth:`f` :meth:`deriv` :meth:`Fx` meth:`Fv` :class:`VehicleBase`
|
|
1068
|
+
"""
|
|
1069
|
+
super().__init__(**kwargs)
|
|
1070
|
+
|
|
1071
|
+
self._l = L
|
|
1072
|
+
self._steer_max = steer_max
|
|
1073
|
+
|
|
1074
|
+
def __str__(self):
|
|
1075
|
+
|
|
1076
|
+
s = super().__str__()
|
|
1077
|
+
s += (
|
|
1078
|
+
f"\n L={self._l}, steer_max={self._steer_max:g},"
|
|
1079
|
+
f" speed_max={self._speed_max:g}, accel_max={self._accel_max:g}"
|
|
1080
|
+
)
|
|
1081
|
+
return s
|
|
1082
|
+
|
|
1083
|
+
@property
|
|
1084
|
+
def l(self):
|
|
1085
|
+
"""
|
|
1086
|
+
Vehicle wheelbase
|
|
1087
|
+
|
|
1088
|
+
:return: vehicle wheelbase
|
|
1089
|
+
:rtype: float
|
|
1090
|
+
"""
|
|
1091
|
+
return self._l
|
|
1092
|
+
|
|
1093
|
+
@property
|
|
1094
|
+
def radius_min(self):
|
|
1095
|
+
r"""
|
|
1096
|
+
Vehicle turning radius
|
|
1097
|
+
|
|
1098
|
+
:return: radius of minimum possible turning circle
|
|
1099
|
+
:rtype: float
|
|
1100
|
+
|
|
1101
|
+
Minimum turning radius based on maximum steered wheel angle and wheelbase.
|
|
1102
|
+
|
|
1103
|
+
.. math::
|
|
1104
|
+
\frac{l}{\tan \gamma_{max}}
|
|
1105
|
+
|
|
1106
|
+
:seealso: :meth:`curvature_max`
|
|
1107
|
+
"""
|
|
1108
|
+
return self.l / np.tan(self.steer_max)
|
|
1109
|
+
|
|
1110
|
+
@property
|
|
1111
|
+
def curvature_max(self):
|
|
1112
|
+
r"""
|
|
1113
|
+
Vehicle maximum path curvature
|
|
1114
|
+
|
|
1115
|
+
:return: maximum curvature
|
|
1116
|
+
:rtype: float
|
|
1117
|
+
|
|
1118
|
+
Maximum path curvature based on maximum steered wheel angle and wheelbase.
|
|
1119
|
+
|
|
1120
|
+
.. math::
|
|
1121
|
+
\frac{\tan \gamma_{max}}{l}
|
|
1122
|
+
|
|
1123
|
+
:seealso: :meth:`radius_min`
|
|
1124
|
+
"""
|
|
1125
|
+
return 1.0 / self.radius_min
|
|
1126
|
+
|
|
1127
|
+
@property
|
|
1128
|
+
def steer_max(self):
|
|
1129
|
+
"""
|
|
1130
|
+
Vehicle maximum steered wheel angle
|
|
1131
|
+
|
|
1132
|
+
:return: maximum angle
|
|
1133
|
+
:rtype: float
|
|
1134
|
+
"""
|
|
1135
|
+
return self._steer_max
|
|
1136
|
+
|
|
1137
|
+
def deriv(self, x, u, limits=True):
|
|
1138
|
+
r"""
|
|
1139
|
+
Time derivative of state
|
|
1140
|
+
|
|
1141
|
+
:param x: vehicle state :math:`(x, y, \theta)`
|
|
1142
|
+
:type x: array_like(3)
|
|
1143
|
+
:param u: control input :math:`(v, \gamma)`
|
|
1144
|
+
:type u: array_like(2)
|
|
1145
|
+
:param limits: limits are applied to input, default True
|
|
1146
|
+
:type limits: bool
|
|
1147
|
+
:return: state derivative :math:`(\dot{x}, \dot{y}, \dot{\theta})`
|
|
1148
|
+
:rtype: ndarray(3)
|
|
1149
|
+
|
|
1150
|
+
Returns the time derivative of state (3x1) at the state ``x`` with velocity :math:`v`
|
|
1151
|
+
and steered wheel angle :math:`\gamma`
|
|
1152
|
+
|
|
1153
|
+
.. math::
|
|
1154
|
+
\dot{x} &= v \cos \theta \\
|
|
1155
|
+
\dot{y} &= v \sin \theta \\
|
|
1156
|
+
\dot{\theta} &= \frac{v}{L} \tan \gamma
|
|
1157
|
+
|
|
1158
|
+
If ``limits`` is True then speed, acceleration and steer-angle limits are
|
|
1159
|
+
applied to ``u``.
|
|
1160
|
+
|
|
1161
|
+
:seealso: :meth:`f`
|
|
1162
|
+
"""
|
|
1163
|
+
|
|
1164
|
+
# unpack some variables
|
|
1165
|
+
theta = x[2]
|
|
1166
|
+
|
|
1167
|
+
if limits:
|
|
1168
|
+
u = self.u_limited(u)
|
|
1169
|
+
v = u[0]
|
|
1170
|
+
gamma = u[1]
|
|
1171
|
+
|
|
1172
|
+
return v * np.r_[cos(theta), sin(theta), tan(gamma) / self.l]
|
|
1173
|
+
|
|
1174
|
+
def u_limited(self, u):
|
|
1175
|
+
r"""
|
|
1176
|
+
Apply vehicle velocity, acceleration and steering limits
|
|
1177
|
+
|
|
1178
|
+
:param u: Desired vehicle inputs :math:`(v, \gamma)`
|
|
1179
|
+
:type u: array_like(2)
|
|
1180
|
+
:return: Allowable vehicle inputs :math:`(v, \gamma)`
|
|
1181
|
+
:rtype: ndarray(2)
|
|
1182
|
+
|
|
1183
|
+
Velocity and acceleration limits are applied to :math:`v` and
|
|
1184
|
+
steered wheel angle limits are applied to :math:`\gamma`.
|
|
1185
|
+
"""
|
|
1186
|
+
# limit speed and steer angle
|
|
1187
|
+
ulim = np.array(u)
|
|
1188
|
+
ulim[0] = self.limits_va(u[0], self._v_prev)
|
|
1189
|
+
ulim[1] = np.clip(u[1], -self._steer_max, self._steer_max)
|
|
1190
|
+
|
|
1191
|
+
return ulim
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
# ========================================================================= #
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
class Unicycle(VehicleBase):
|
|
1198
|
+
def __init__(self, W=1, steer_max=np.inf, **kwargs):
|
|
1199
|
+
r"""
|
|
1200
|
+
Create unicycle kinematic model
|
|
1201
|
+
|
|
1202
|
+
:param W: vehicle width, defaults to 1
|
|
1203
|
+
:type W: float, optional
|
|
1204
|
+
:param steer_max: maximum turn rate
|
|
1205
|
+
:type steer_max: float
|
|
1206
|
+
:param kwargs: additional arguments passed to :class:`VehicleBase`
|
|
1207
|
+
constructor
|
|
1208
|
+
|
|
1209
|
+
Model the motion of a unicycle model with equations of motion given by:
|
|
1210
|
+
|
|
1211
|
+
.. math::
|
|
1212
|
+
|
|
1213
|
+
\dot{x} &= v \cos \theta \\
|
|
1214
|
+
\dot{y} &= v \sin \theta \\
|
|
1215
|
+
\dot{\theta} &= \omega
|
|
1216
|
+
|
|
1217
|
+
where :math:`v` is the velocity in body frame x-direction, and
|
|
1218
|
+
:math:`\omega` is the turn rate.
|
|
1219
|
+
|
|
1220
|
+
:seealso: :meth:`f` :meth:`deriv` :meth:`Fx` meth:`Fv` :class:`Vehicle`
|
|
1221
|
+
"""
|
|
1222
|
+
super().__init__(**kwargs)
|
|
1223
|
+
self._W = W
|
|
1224
|
+
self._steer_max = steer_max
|
|
1225
|
+
|
|
1226
|
+
def __str__(self):
|
|
1227
|
+
|
|
1228
|
+
s = super().__str__()
|
|
1229
|
+
s += (
|
|
1230
|
+
f"\n W={self._W}, steer_max={self._steer_max:g},"
|
|
1231
|
+
f" vel_max={self._speed_max}, accel_max={self._accel_max}"
|
|
1232
|
+
)
|
|
1233
|
+
return s
|
|
1234
|
+
|
|
1235
|
+
def deriv(self, x, u, limits=True):
|
|
1236
|
+
r"""
|
|
1237
|
+
Time derivative of state
|
|
1238
|
+
|
|
1239
|
+
:param x: vehicle state :math:`(x, y, \theta)`
|
|
1240
|
+
:type x: array_like(3)
|
|
1241
|
+
:param u: control input :math:`(v, \omega)`
|
|
1242
|
+
:type u: array_like(2)
|
|
1243
|
+
:param limits: limits are applied to input, default True
|
|
1244
|
+
:type limits: bool
|
|
1245
|
+
:return: state derivative :math:`(\dot{x}, \dot{y}, \dot{\theta})`
|
|
1246
|
+
:rtype: ndarray(3)
|
|
1247
|
+
|
|
1248
|
+
Returns the time derivative of state (3x1) at the state ``x`` with velocity :math:`v`
|
|
1249
|
+
and turn rate :math:`\omega`
|
|
1250
|
+
|
|
1251
|
+
.. math::
|
|
1252
|
+
\dot{x} &= v \cos \theta \\
|
|
1253
|
+
\dot{y} &= v \sin \theta \\
|
|
1254
|
+
\dot{\theta} &= \omega
|
|
1255
|
+
|
|
1256
|
+
If ``limits`` is True then speed, acceleration and steer-angle limits are
|
|
1257
|
+
applied to ``u``.
|
|
1258
|
+
|
|
1259
|
+
:seealso: :meth:`f`
|
|
1260
|
+
"""
|
|
1261
|
+
if limits:
|
|
1262
|
+
u = self.u_limited(u)
|
|
1263
|
+
# unpack some variables
|
|
1264
|
+
theta = x[2]
|
|
1265
|
+
v = u[0]
|
|
1266
|
+
vdiff = u[1]
|
|
1267
|
+
|
|
1268
|
+
return np.r_[v * cos(theta), v * sin(theta), vdiff / self._W]
|
|
1269
|
+
|
|
1270
|
+
def u_limited(self, u):
|
|
1271
|
+
r"""
|
|
1272
|
+
Apply vehicle velocity, acceleration and steering limits
|
|
1273
|
+
|
|
1274
|
+
:param u: Desired vehicle inputs :math:`(v, \omega)`
|
|
1275
|
+
:type u: array_like(2)
|
|
1276
|
+
:return: Allowable vehicle inputs :math:`(v, \omega)`
|
|
1277
|
+
:rtype: ndarray(2)
|
|
1278
|
+
|
|
1279
|
+
Velocity and acceleration limits are applied to :math:`v` and
|
|
1280
|
+
turn rate limits are applied to :math:`\omega`.
|
|
1281
|
+
"""
|
|
1282
|
+
|
|
1283
|
+
# limit speed and steer angle
|
|
1284
|
+
ulim = np.array(u)
|
|
1285
|
+
ulim[0] = self.limits_va(u[0], self._v_prev)
|
|
1286
|
+
ulim[1] = np.maximum(-self._steer_max, np.minimum(self._steer_max, u[1]))
|
|
1287
|
+
|
|
1288
|
+
return ulim
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
# ========================================================================= #
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
class DiffSteer(Unicycle):
|
|
1295
|
+
def __init__(self, W=1, **kwargs):
|
|
1296
|
+
r"""
|
|
1297
|
+
Create differential steering kinematic model
|
|
1298
|
+
|
|
1299
|
+
:param W: vehicle width, defaults to 1
|
|
1300
|
+
:type W: float, optional
|
|
1301
|
+
:param kwargs: additional arguments passed to :class:`VehicleBase`
|
|
1302
|
+
constructor
|
|
1303
|
+
|
|
1304
|
+
Model the motion of a unicycle model with equations of motion given by:
|
|
1305
|
+
|
|
1306
|
+
.. math::
|
|
1307
|
+
|
|
1308
|
+
\dot{x} &= v \cos \theta \\
|
|
1309
|
+
\dot{y} &= v \sin \theta \\
|
|
1310
|
+
\dot{\theta} &= \omega
|
|
1311
|
+
|
|
1312
|
+
where :math:`v = (v_R + v_L)/2` is the velocity in body frame x-direction, and
|
|
1313
|
+
:math:`\omega = (v_R - v_L)/W` is the turn rate.
|
|
1314
|
+
|
|
1315
|
+
:seealso: :meth:`f` :meth:`deriv` :meth:`Fx` meth:`Fv` :class:`Vehicle`
|
|
1316
|
+
"""
|
|
1317
|
+
super().__init__(**kwargs)
|
|
1318
|
+
self._W = W
|
|
1319
|
+
self._v_prev_L = [0]
|
|
1320
|
+
self._v_prev_R = [0]
|
|
1321
|
+
|
|
1322
|
+
def __str__(self):
|
|
1323
|
+
|
|
1324
|
+
s = super().__str__()
|
|
1325
|
+
return s
|
|
1326
|
+
|
|
1327
|
+
def init(self, **kwargs):
|
|
1328
|
+
super().init(**kwargs)
|
|
1329
|
+
self._v_prev_L = [0]
|
|
1330
|
+
self._v_prev_R = [0]
|
|
1331
|
+
|
|
1332
|
+
def u_limited(self, u):
|
|
1333
|
+
r"""
|
|
1334
|
+
Apply vehicle velocity and acceleration limits
|
|
1335
|
+
|
|
1336
|
+
:param u: Desired vehicle inputs :math:`(v_L, v_R)`
|
|
1337
|
+
:type u: array_like(2)
|
|
1338
|
+
:return: Allowable vehicle inputs :math:`(v_L, v_R)`
|
|
1339
|
+
:rtype: ndarray(2)
|
|
1340
|
+
|
|
1341
|
+
Velocity and acceleration limits are applied to :math:`v` and
|
|
1342
|
+
turn rate limits are applied to :math:`\omega`.
|
|
1343
|
+
"""
|
|
1344
|
+
|
|
1345
|
+
# limit speed and acceleration of each wheel/track
|
|
1346
|
+
ulim = np.array(u)
|
|
1347
|
+
ulim[0] = self.limits_va(u[0], self._v_prev_L)
|
|
1348
|
+
ulim[1] = self.limits_va(u[1], self._v_prev_R)
|
|
1349
|
+
|
|
1350
|
+
return ulim
|
|
1351
|
+
|
|
1352
|
+
def deriv(self, x, u, limits=True):
|
|
1353
|
+
r"""
|
|
1354
|
+
Time derivative of state
|
|
1355
|
+
|
|
1356
|
+
:param x: vehicle state :math:`(x, y, \theta)`
|
|
1357
|
+
:type x: array_like(3)
|
|
1358
|
+
:param u: Desired vehicle inputs :math:`(v_L, v_R)`
|
|
1359
|
+
:type u: array_like(2)
|
|
1360
|
+
:param limits: limits are applied to input, default True
|
|
1361
|
+
:type limits: bool
|
|
1362
|
+
:return: state derivative :math:`(\dot{x}, \dot{y}, \dot{\theta})`
|
|
1363
|
+
:rtype: ndarray(3)
|
|
1364
|
+
|
|
1365
|
+
Returns the time derivative of state (3x1) at the state ``x`` with left and
|
|
1366
|
+
right wheel speeds ``u``.
|
|
1367
|
+
|
|
1368
|
+
.. math::
|
|
1369
|
+
|
|
1370
|
+
\dot{x} &= v \cos \theta \\
|
|
1371
|
+
\dot{y} &= v \sin \theta \\
|
|
1372
|
+
\dot{\theta} &= \omega
|
|
1373
|
+
|
|
1374
|
+
where :math:`v = (v_R + v_L)/2` is the velocity in body frame x-direction, and
|
|
1375
|
+
:math:`\omega = (v_R - v_L)/W` is the turn rate.
|
|
1376
|
+
|
|
1377
|
+
If ``limits`` is True then speed and acceleration limits are applied to the
|
|
1378
|
+
wheel speeds ``u``.
|
|
1379
|
+
|
|
1380
|
+
:seealso: :meth:`f`
|
|
1381
|
+
"""
|
|
1382
|
+
if limits:
|
|
1383
|
+
u = self.u_limited(u)
|
|
1384
|
+
# unpack some variables
|
|
1385
|
+
theta = x[2]
|
|
1386
|
+
vleft = u[0]
|
|
1387
|
+
vright = u[1]
|
|
1388
|
+
|
|
1389
|
+
# convert wheel speeds to forward and differential velocity
|
|
1390
|
+
v = (vright + vleft) / 2.0
|
|
1391
|
+
vdiff = vright - vleft
|
|
1392
|
+
|
|
1393
|
+
return np.r_[v * cos(theta), v * sin(theta), vdiff / self._W]
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
# ========================================================================= #
|
|
1397
|
+
|
|
1398
|
+
|
|
1399
|
+
class DiffSteerTrailer(Unicycle):
|
|
1400
|
+
def __init__(self, W=1, L1=1, L2=1, x0=[0.0, 0, 0, 0], trailer=None, **kwargs):
|
|
1401
|
+
r"""
|
|
1402
|
+
Create differential steering kinematic model with trailer
|
|
1403
|
+
|
|
1404
|
+
:param W: vehicle width, defaults to 1
|
|
1405
|
+
:type W: float, optional
|
|
1406
|
+
:param L1: distance from rear axle to trailer hitch, defaults to 1
|
|
1407
|
+
:type L1: float, optional
|
|
1408
|
+
:param L2: distance from trailer hitch to trailer axle, defaults to 1
|
|
1409
|
+
:type L2: float, optional
|
|
1410
|
+
:param kwargs: additional arguments passed to :class:`VehicleBase`
|
|
1411
|
+
constructor
|
|
1412
|
+
|
|
1413
|
+
Model the motion of a unicycle model with equations of motion given by:
|
|
1414
|
+
|
|
1415
|
+
.. math::
|
|
1416
|
+
|
|
1417
|
+
\dot{x} &= v \cos \theta \\
|
|
1418
|
+
\dot{y} &= v \sin \theta \\
|
|
1419
|
+
\dot{\theta} &= \omega \\
|
|
1420
|
+
\dot{\delta} &= \frac{v}{L_1} \sin(\theta - \delta)
|
|
1421
|
+
|
|
1422
|
+
where :math:`v = (v_R + v_L)/2` is the velocity in body frame x-direction,
|
|
1423
|
+
:math:`\omega = (v_R - v_L)/W` is the turn rate, and :math:`\delta` is the
|
|
1424
|
+
hitch angle.
|
|
1425
|
+
|
|
1426
|
+
:seealso: :meth:`f` :meth:`deriv` :meth:`Fx` meth:`Fv` :class:`Vehicle`
|
|
1427
|
+
"""
|
|
1428
|
+
super().__init__(**kwargs)
|
|
1429
|
+
self._x0 = np.r_[x0]
|
|
1430
|
+
self._x = x0.copy()
|
|
1431
|
+
self._W = W
|
|
1432
|
+
self._L1 = L1
|
|
1433
|
+
self._L2 = L2
|
|
1434
|
+
self._animation_trailer = trailer
|
|
1435
|
+
self._v_prev_L = [0]
|
|
1436
|
+
self._v_prev_R = [0]
|
|
1437
|
+
|
|
1438
|
+
def __str__(self):
|
|
1439
|
+
|
|
1440
|
+
s = super().__str__()
|
|
1441
|
+
return s
|
|
1442
|
+
|
|
1443
|
+
def init(self, **kwargs):
|
|
1444
|
+
super().init(**kwargs)
|
|
1445
|
+
self._animation_trailer.add(ax=self._ax) # add trailer animation to axis
|
|
1446
|
+
|
|
1447
|
+
def plot(self, x):
|
|
1448
|
+
self._animation.update(x[:3]) # show robot
|
|
1449
|
+
|
|
1450
|
+
theta = x[2]
|
|
1451
|
+
eta = theta + x[3]
|
|
1452
|
+
Q = (
|
|
1453
|
+
x[:2]
|
|
1454
|
+
- self._L1 * np.r_[cos(theta), sin(theta)]
|
|
1455
|
+
- self._L2 * np.r_[cos(eta), sin(eta)]
|
|
1456
|
+
)
|
|
1457
|
+
self._animation_trailer.update(np.concatenate((Q, [eta]))) # show trailer
|
|
1458
|
+
|
|
1459
|
+
def deriv(self, x, u, limits=True):
|
|
1460
|
+
r"""
|
|
1461
|
+
Time derivative of state
|
|
1462
|
+
|
|
1463
|
+
:param x: vehicle state :math:`(x, y, \theta, \delta)`
|
|
1464
|
+
:type x: array_like(3)
|
|
1465
|
+
:param u: Desired vehicle inputs :math:`(v_L, v_R)`
|
|
1466
|
+
:type u: array_like(2)
|
|
1467
|
+
:param limits: limits are applied to input, default True
|
|
1468
|
+
:type limits: bool
|
|
1469
|
+
:return: state derivative :math:`(\dot{x}, \dot{y}, \dot{\theta})`
|
|
1470
|
+
:rtype: ndarray(3)
|
|
1471
|
+
|
|
1472
|
+
Returns the time derivative of state (4x1) at the state ``x`` with left and
|
|
1473
|
+
right wheel speeds ``u``.
|
|
1474
|
+
|
|
1475
|
+
.. math::
|
|
1476
|
+
|
|
1477
|
+
\dot{x} &= v \cos \theta \\
|
|
1478
|
+
\dot{y} &= v \sin \theta \\
|
|
1479
|
+
\dot{\theta} &= \omega \\
|
|
1480
|
+
\dot{\delta} &= \frac{v}{L_1} \sin(\theta - \delta)
|
|
1481
|
+
|
|
1482
|
+
where :math:`v = (v_R + v_L)/2` is the velocity in body frame x-direction, and
|
|
1483
|
+
:math:`\omega = (v_R - v_L)/W` is the turn rate.
|
|
1484
|
+
|
|
1485
|
+
If ``limits`` is True then speed and acceleration limits are applied to the
|
|
1486
|
+
wheel speeds ``u``.
|
|
1487
|
+
|
|
1488
|
+
:seealso: :meth:`f`
|
|
1489
|
+
"""
|
|
1490
|
+
if limits:
|
|
1491
|
+
u = self.u_limited(u)
|
|
1492
|
+
# unpack some variables
|
|
1493
|
+
theta = x[2]
|
|
1494
|
+
delta = x[3]
|
|
1495
|
+
vleft = u[0]
|
|
1496
|
+
vright = u[1]
|
|
1497
|
+
|
|
1498
|
+
# convert wheel speeds to forward and differential velocity
|
|
1499
|
+
v = (vright + vleft) / 2.0
|
|
1500
|
+
vdiff = vright - vleft
|
|
1501
|
+
|
|
1502
|
+
# xd yd thetad
|
|
1503
|
+
X = np.r_[v * cos(theta), v * sin(theta), vdiff / self._W, 0]
|
|
1504
|
+
|
|
1505
|
+
hx = X[0] + self._L1 * X[2] * sin(theta)
|
|
1506
|
+
hy = X[1] - self._L1 * X[2] * cos(theta)
|
|
1507
|
+
|
|
1508
|
+
# trailer kino-dynamics
|
|
1509
|
+
if X[2] > 0.01:
|
|
1510
|
+
pass
|
|
1511
|
+
eta = theta + delta
|
|
1512
|
+
etad = (hy * cos(eta) - hx * sin(eta)) / self._L2
|
|
1513
|
+
X[3] = etad - X[2] # deltad = etad - thetad
|
|
1514
|
+
print(X[2], eta, etad)
|
|
1515
|
+
|
|
1516
|
+
return X
|
|
1517
|
+
|
|
1518
|
+
|
|
1519
|
+
# composite of vehicle + trailers
|
|
1520
|
+
class VehicleTrailer(VehicleBase):
|
|
1521
|
+
def __init__(self, vehicle, trailers, x0=None, verbose=False):
|
|
1522
|
+
r"""
|
|
1523
|
+
Create a kinematic system with a vehicle with one or more trailers
|
|
1524
|
+
|
|
1525
|
+
:param vehicle: vehicle model
|
|
1526
|
+
:type vehicle: :class:`VehicleBase` such as `Bicycle`, `Unicycle` or `DiffSteer`
|
|
1527
|
+
:param trailers: trailer model or list of trailer models
|
|
1528
|
+
:type trailers: :class:`Trailer` or list of :class:`Trailer`
|
|
1529
|
+
:param x0: initial state, defaults to [0, 0, 0, 0, ...]
|
|
1530
|
+
:type x0: array_like(3+m) where `m` is the number of trailers
|
|
1531
|
+
:param kwargs: additional arguments passed to :class:`VehicleBase`
|
|
1532
|
+
constructor
|
|
1533
|
+
|
|
1534
|
+
The vehicle motion model is defined by `vehicle`. The trailers have car-like
|
|
1535
|
+
kinematics with a lateral non-sliding constraint. Each trailer is connected to
|
|
1536
|
+
the preceding one (vehicle or trailer) by a hitch defined by two lengths `L1` and `L2`.
|
|
1537
|
+
|
|
1538
|
+
The state of the system is :math:`(x, y, \theta, \delta_i, \cdots)` where
|
|
1539
|
+
:math:`(x,y)` is the position of the centre of vehicle, :math:`\theta` is the
|
|
1540
|
+
heading angle, and :math:`\delta_i` is the hitch angle for the `i`-th trailer.
|
|
1541
|
+
|
|
1542
|
+
:seealso: :class:`VehicleBase` :class:`Trailer`
|
|
1543
|
+
"""
|
|
1544
|
+
self.vehicle = vehicle
|
|
1545
|
+
if isinstance(trailers, Trailer):
|
|
1546
|
+
self.trailers = [trailers]
|
|
1547
|
+
else:
|
|
1548
|
+
self.trailers = trailers
|
|
1549
|
+
|
|
1550
|
+
if x0 is None:
|
|
1551
|
+
x0 = np.zeros((3 + len(self.trailers),))
|
|
1552
|
+
self._x0 = x0
|
|
1553
|
+
self._verbose = verbose
|
|
1554
|
+
|
|
1555
|
+
def __str__(self):
|
|
1556
|
+
"""
|
|
1557
|
+
Pretty print the vehicle and trailers
|
|
1558
|
+
"""
|
|
1559
|
+
|
|
1560
|
+
s = str(self.vehicle)
|
|
1561
|
+
for k, trailer in enumerate(self.trailers):
|
|
1562
|
+
s += f"\n + trailer {k}: L1={trailer._L1}, L2={trailer._L2}"
|
|
1563
|
+
return s
|
|
1564
|
+
|
|
1565
|
+
def polygon(self, q):
|
|
1566
|
+
r"""
|
|
1567
|
+
Bounding polygons at vehicle configuration
|
|
1568
|
+
|
|
1569
|
+
:param q: vehicle configuration :math:`(x, y, \theta, \delta_i, \cdots)`
|
|
1570
|
+
:type q: array_like(3+m) where `m` is the number of trailers
|
|
1571
|
+
:return: list of bounding polygons of vehicle at configuration ``q``
|
|
1572
|
+
:rtype: :class:`~spatialmath.geom2d.Polygon2`
|
|
1573
|
+
|
|
1574
|
+
The bounding polygon of the vehicle is returned for the configuration
|
|
1575
|
+
``q``. Can be used for collision checking using the :meth:`~spatialmath.geom2d.Polygon2.intersects`
|
|
1576
|
+
method.
|
|
1577
|
+
|
|
1578
|
+
:seealso: :class:`~spatialmath.geom2d.Polygon2`
|
|
1579
|
+
"""
|
|
1580
|
+
polygons = [self.vehicle._polygon.transformed(SE2(q))]
|
|
1581
|
+
|
|
1582
|
+
for trailer, delta in zip(self.trailers, q[3:]):
|
|
1583
|
+
polygons.append(trailer._polygon.transformed(SE2(delta)))
|
|
1584
|
+
|
|
1585
|
+
return polygons
|
|
1586
|
+
|
|
1587
|
+
def init(self, **kwargs):
|
|
1588
|
+
self.vehicle.init(**kwargs)
|
|
1589
|
+
self._x = self._x0
|
|
1590
|
+
self._t = 0
|
|
1591
|
+
self._x_hist = []
|
|
1592
|
+
|
|
1593
|
+
for trailer in self.trailers:
|
|
1594
|
+
if trailer._animation is not None:
|
|
1595
|
+
trailer._animation.add(
|
|
1596
|
+
ax=self.vehicle._ax
|
|
1597
|
+
) # add trailer animation to axis
|
|
1598
|
+
|
|
1599
|
+
@property
|
|
1600
|
+
def dt(self):
|
|
1601
|
+
return self.vehicle.dt
|
|
1602
|
+
|
|
1603
|
+
def run(self, T=10, x0=None, control=None, animate=True):
|
|
1604
|
+
r"""
|
|
1605
|
+
Simulate motion of vehicle and m trailers
|
|
1606
|
+
|
|
1607
|
+
:param T: Simulation time in seconds, defaults to 10
|
|
1608
|
+
:type T: float, optional
|
|
1609
|
+
:param x0: Initial state, defaults to value given to :class:`VehicleTrailer` constructor
|
|
1610
|
+
:type x0: array_like(3+m) where `m` is the number of trailers, optional
|
|
1611
|
+
:param control: vehicle control inputs, defaults to None
|
|
1612
|
+
:type control: array_like(2), callable, driving agent
|
|
1613
|
+
:param animate: Enable graphical animation of vehicle, defaults to False
|
|
1614
|
+
:type animate: bool, optional
|
|
1615
|
+
:return: State trajectory, each row is :math:`(x,y,\theta, \delta_i, \cdots)`.
|
|
1616
|
+
:rtype: ndarray(n,3)
|
|
1617
|
+
|
|
1618
|
+
Runs the vehicle and trailer simulation for ``T`` seconds and optionally plots
|
|
1619
|
+
an animation. The method :meth:`step` performs each time step.
|
|
1620
|
+
|
|
1621
|
+
The control inputs to the vehicle are provided by ``control`` which can be:
|
|
1622
|
+
|
|
1623
|
+
* a constant tuple as the control inputs to the vehicle
|
|
1624
|
+
* a function called as ``f(vehicle, t, x)`` that returns a tuple
|
|
1625
|
+
* an interpolator called as ``f(t)`` that returns a tuple, see
|
|
1626
|
+
SciPy interp1d
|
|
1627
|
+
* a driver agent, subclass of :class:`VehicleDriverBase`
|
|
1628
|
+
|
|
1629
|
+
This is evaluated by :meth:`eval_control` which applies velocity,
|
|
1630
|
+
acceleration and steering limits.
|
|
1631
|
+
|
|
1632
|
+
The simulation can be stopped prematurely by the control function
|
|
1633
|
+
calling :meth:`stopsim`.
|
|
1634
|
+
|
|
1635
|
+
.. note::
|
|
1636
|
+
* the simulation is fixed-time step with the step given by the ``dt``
|
|
1637
|
+
attribute set by the constructor.
|
|
1638
|
+
* integration uses rectangular integration.
|
|
1639
|
+
|
|
1640
|
+
:seealso: :meth:`init` :meth:`step` :meth:`control` :meth:`run_animation`
|
|
1641
|
+
"""
|
|
1642
|
+
|
|
1643
|
+
self.init(control=control, animate=animate, x0=x0)
|
|
1644
|
+
|
|
1645
|
+
for i in range(round(T / self.dt)):
|
|
1646
|
+
self.step(animate=animate)
|
|
1647
|
+
|
|
1648
|
+
# check for user requested stop
|
|
1649
|
+
if self.vehicle._stopsim:
|
|
1650
|
+
print("USER REEQUESTED STOP AT time", self._t)
|
|
1651
|
+
break
|
|
1652
|
+
|
|
1653
|
+
return self.x_hist
|
|
1654
|
+
|
|
1655
|
+
def step(self, u=None, animate=True, pause=True):
|
|
1656
|
+
r"""
|
|
1657
|
+
Step simulator by one time step
|
|
1658
|
+
|
|
1659
|
+
#. Obtain the vehicle control inputs
|
|
1660
|
+
#. Integrate the vehicle state forward one timestep
|
|
1661
|
+
#. Updates the stored state and state history
|
|
1662
|
+
#. Update animation if enabled.
|
|
1663
|
+
|
|
1664
|
+
Example:
|
|
1665
|
+
|
|
1666
|
+
.. runblock:: pycon
|
|
1667
|
+
|
|
1668
|
+
>>> from roboticstoolbox import Bicycle
|
|
1669
|
+
>>> vt = VehicleTrailer(Bicycle(), Trailer()) # default bicycle model
|
|
1670
|
+
>>> vt.step((1, 0.2)) # one step: v=1, γ=0.2
|
|
1671
|
+
>>> vt.x
|
|
1672
|
+
>>> vt.run(5) # run simulatin for 5 seconds
|
|
1673
|
+
|
|
1674
|
+
.. note:: Vehicle control input limits are applied.
|
|
1675
|
+
|
|
1676
|
+
:seealso: :func:`control`, :func:`update`, :func:`run`
|
|
1677
|
+
"""
|
|
1678
|
+
# determine vehicle control
|
|
1679
|
+
if u is not None:
|
|
1680
|
+
u = self.eval_control(u, self._x)
|
|
1681
|
+
else:
|
|
1682
|
+
u = self.vehicle.eval_control(self.vehicle._control, self._x)
|
|
1683
|
+
|
|
1684
|
+
# update state (used to be function control() in MATLAB version)
|
|
1685
|
+
xd = self.dt * self.deriv(self._x, u) # delta state
|
|
1686
|
+
|
|
1687
|
+
# update state vector
|
|
1688
|
+
self._x += xd
|
|
1689
|
+
self.vehicle._x = self._x[:3]
|
|
1690
|
+
self._x_hist.append(tuple(self._x))
|
|
1691
|
+
|
|
1692
|
+
# print('VEH', u, self.x)
|
|
1693
|
+
|
|
1694
|
+
# do the graphics
|
|
1695
|
+
if animate and self.vehicle._animation:
|
|
1696
|
+
x = self._x[:3].copy()
|
|
1697
|
+
self.vehicle._animation.update(x) # show robot
|
|
1698
|
+
|
|
1699
|
+
for trailer, delta in zip(self.trailers, self._x[3:]):
|
|
1700
|
+
x[:2] -= (
|
|
1701
|
+
trailer._L1 * np.r_[cos(x[2]), sin(x[2])]
|
|
1702
|
+
+ trailer._L2 * np.r_[cos(x[2] + delta), sin(x[2] + delta)]
|
|
1703
|
+
)
|
|
1704
|
+
x[2] += delta
|
|
1705
|
+
trailer._animation.update(x) # show trailer
|
|
1706
|
+
# if self._timer is not None:
|
|
1707
|
+
# self._timer.set_text(f"t = {self._t:.2f}")
|
|
1708
|
+
_refresh_animation_frame(
|
|
1709
|
+
self.vehicle._ax.figure if self.vehicle._ax else None, self.dt, pause
|
|
1710
|
+
)
|
|
1711
|
+
# plt.show(block=False)
|
|
1712
|
+
# pass
|
|
1713
|
+
|
|
1714
|
+
self._t += self.dt
|
|
1715
|
+
self.vehicle._t = self._t
|
|
1716
|
+
|
|
1717
|
+
# be verbose
|
|
1718
|
+
if self._verbose:
|
|
1719
|
+
print(
|
|
1720
|
+
f"{self._t:8.2f}: u=({u[0]:8.2f}, {u[1]:8.2f}), x=({self._x[0]:8.2f},"
|
|
1721
|
+
f" {self._x[1]:8.2f}, {self._x[2]:8.2f})"
|
|
1722
|
+
)
|
|
1723
|
+
|
|
1724
|
+
def plot(self, x):
|
|
1725
|
+
self._animation.update(x[:3]) # show robot
|
|
1726
|
+
|
|
1727
|
+
theta = x[2]
|
|
1728
|
+
eta = theta + x[3]
|
|
1729
|
+
Q = (
|
|
1730
|
+
x[:2]
|
|
1731
|
+
- self._L1 * (cos(theta), sin(theta))
|
|
1732
|
+
- self._L2 * (cos(eta), sin(eta))
|
|
1733
|
+
)
|
|
1734
|
+
self._animation_trailer.update(np.concatenate((Q, [eta]))) # show trailer
|
|
1735
|
+
|
|
1736
|
+
def deriv(self, x, u, limits=True):
|
|
1737
|
+
r"""
|
|
1738
|
+
Time derivative of state
|
|
1739
|
+
|
|
1740
|
+
:param x: vehicle + trailer state :math:`(x, y, \theta, \delta_i, \cdots)`
|
|
1741
|
+
:type x: array_like(3+m) where `m` is the number of trailers
|
|
1742
|
+
:param u: Desired vehicle inputs, meaning depends on vehicle type
|
|
1743
|
+
:type u: array_like()
|
|
1744
|
+
:param limits: limits are applied to input, default True
|
|
1745
|
+
:type limits: bool
|
|
1746
|
+
:return: state derivative :math:`(\dot{x}, \dot{y}, \dot{\theta}, \dot{\delta}_i, \cdots)`
|
|
1747
|
+
:rtype: ndarray(3)
|
|
1748
|
+
|
|
1749
|
+
Returns the time derivative of state (3+m) at the state ``x`` with left and
|
|
1750
|
+
right wheel speeds ``u``.
|
|
1751
|
+
|
|
1752
|
+
If the velocity of the lead vehicle is :math:`(\dot{x}_l, \dot{y}_l, \dot{\theta}_l)`
|
|
1753
|
+
then the velocity of the hitch point is:
|
|
1754
|
+
|
|
1755
|
+
.. math::
|
|
1756
|
+
|
|
1757
|
+
\dot{x}_h &= \dot{x}_l + \ell_1 \dot{theta}_l \sin \theta_l \\
|
|
1758
|
+
\dot{y}_h &= \dot{y}_l - \ell_1 \dot{theta}_l \cos \theta_l \\
|
|
1759
|
+
|
|
1760
|
+
and the change of heading angle of the follower is:
|
|
1761
|
+
|
|
1762
|
+
.. math::
|
|
1763
|
+
|
|
1764
|
+
\dot{theta}_f = \frac{\dot{y}_h \cos(\theta_f - \delta_f) - \dot{x}_h \sin(\theta_f - \delta_f)}{\ell_2}
|
|
1765
|
+
|
|
1766
|
+
and the change of the hitch angle is
|
|
1767
|
+
|
|
1768
|
+
.. math::
|
|
1769
|
+
|
|
1770
|
+
\dot{\delta} = \dot{theta}_f - \dot{theta}_l
|
|
1771
|
+
|
|
1772
|
+
If ``limits`` is True then speed and acceleration limits are applied to the
|
|
1773
|
+
wheel speeds ``u``.
|
|
1774
|
+
|
|
1775
|
+
:seealso: :meth:`VehicleBas.f`
|
|
1776
|
+
"""
|
|
1777
|
+
dx = self.vehicle.deriv(x[:3], u, limits)
|
|
1778
|
+
|
|
1779
|
+
# velocity and orientation of vehicle/trailer before
|
|
1780
|
+
xd = dx[0]
|
|
1781
|
+
yd = dx[1]
|
|
1782
|
+
thetad = dx[2]
|
|
1783
|
+
theta = x[2]
|
|
1784
|
+
|
|
1785
|
+
for trailer, delta in zip(self.trailers, x[3:]):
|
|
1786
|
+
# hitch point velocity
|
|
1787
|
+
hx = xd + trailer._L1 * thetad * sin(theta)
|
|
1788
|
+
hy = yd - trailer._L1 * thetad * cos(theta)
|
|
1789
|
+
|
|
1790
|
+
eta = theta + delta
|
|
1791
|
+
etad = (hy * cos(eta) - hx * sin(eta)) / trailer._L2
|
|
1792
|
+
deltad = etad - thetad # hitch angle velocity
|
|
1793
|
+
|
|
1794
|
+
# print(X[2], eta, etad)
|
|
1795
|
+
dx = np.concatenate((dx, [deltad])) # append to derivative vector
|
|
1796
|
+
|
|
1797
|
+
# compute velocity of trailer's rear axle midpoint
|
|
1798
|
+
xd = hx + etad * trailer._L2 * sin(eta)
|
|
1799
|
+
yd = hy - etad * trailer._L2 * cos(eta)
|
|
1800
|
+
thetad = etad
|
|
1801
|
+
|
|
1802
|
+
return dx
|
|
1803
|
+
|
|
1804
|
+
|
|
1805
|
+
if __name__ == "__main__":
|
|
1806
|
+
from roboticstoolbox import RandomPath
|
|
1807
|
+
|
|
1808
|
+
import roboticstoolbox as rtb
|
|
1809
|
+
import time
|
|
1810
|
+
|
|
1811
|
+
def steering(v, t, x):
|
|
1812
|
+
speed = (0.5, 0.5)
|
|
1813
|
+
if 3 <= t < 5:
|
|
1814
|
+
speed = (0.4, 0.6)
|
|
1815
|
+
elif 5 <= t < 7:
|
|
1816
|
+
speed = (0.6, 0.4)
|
|
1817
|
+
|
|
1818
|
+
return speed
|
|
1819
|
+
|
|
1820
|
+
a = rtb.VehiclePolygon(shape="car", color="blue")
|
|
1821
|
+
t = rtb.VehiclePolygon(shape="box", color="red")
|
|
1822
|
+
veh = DiffSteer(animation=a, control=steering, workspace=10)
|
|
1823
|
+
vt = VehicleTrailer(veh, Trailer(L1=1, L2=2, animation=t))
|
|
1824
|
+
print(vt)
|
|
1825
|
+
print(vt.deriv([0, 0, 0, 0], [1, 1]))
|
|
1826
|
+
vt.run(10)
|
|
1827
|
+
print(veh.x_hist)
|
|
1828
|
+
|
|
1829
|
+
# a = rtb.VehiclePolygon(shape="car", color="blue")
|
|
1830
|
+
# t = rtb.VehiclePolygon(shape="car", color="red")
|
|
1831
|
+
# veh = DiffSteerTrailer(animation=a, trailer=t, workspace=10)
|
|
1832
|
+
# veh.control = control
|
|
1833
|
+
# time.sleep(5)
|
|
1834
|
+
# veh.run(10)
|
|
1835
|
+
# print(veh.x_hist)
|
|
1836
|
+
|
|
1837
|
+
# a = rtb.VehicleMarker(marker="s", markerfacecolor="b")
|
|
1838
|
+
# veh = rtb.Bicycle(animation=a, workspace=10)
|
|
1839
|
+
# veh.control = (4, 0.5)
|
|
1840
|
+
# veh.run(20)
|
|
1841
|
+
|
|
1842
|
+
# V = np.eye(2) * 0.001
|
|
1843
|
+
# robot = Bicycle(covar=V, animation="car")
|
|
1844
|
+
# odo = robot.step((1, 0.3), animate=False)
|
|
1845
|
+
|
|
1846
|
+
# robot.control = RandomPath(workspace=10)
|
|
1847
|
+
|
|
1848
|
+
# # robot.run(T=10, animate=True)
|
|
1849
|
+
# # plt.show(block=True)
|
|
1850
|
+
|
|
1851
|
+
# anim = robot.run_animation(T=10, format="html", file="veh.html")
|
|
1852
|
+
|
|
1853
|
+
# anim.save("veh.mp4", writer=animation.FFMpegWriter(fps=1/robot.dt)) # convert to mp4/H264
|
|
1854
|
+
# with open("veh.html", "w") as f:
|
|
1855
|
+
# f.write(anim.to_html5_video())
|
|
1856
|
+
|
|
1857
|
+
# from math import pi
|
|
1858
|
+
|
|
1859
|
+
# V = np.diag(np.r_[0.02, 0.5 * pi / 180] ** 2)
|
|
1860
|
+
|
|
1861
|
+
# v = VehiclePolygon()
|
|
1862
|
+
# # v = VehicleIcon('greycar2', scale=2, rotation=90)
|
|
1863
|
+
|
|
1864
|
+
# veh = Bicycle(covar=V, animation=v, control=RandomPath(10), verbose=False)
|
|
1865
|
+
# print(veh)
|
|
1866
|
+
|
|
1867
|
+
# odo = veh.step(1, 0.3)
|
|
1868
|
+
# print(odo)
|
|
1869
|
+
|
|
1870
|
+
# print(veh.x)
|
|
1871
|
+
|
|
1872
|
+
# print(veh.f([0, 0, 0], odo))
|
|
1873
|
+
|
|
1874
|
+
# def control(v, t, x):
|
|
1875
|
+
# goal = (6,6)
|
|
1876
|
+
# goal_heading = atan2(goal[1]-x[1], goal[0]-x[0])
|
|
1877
|
+
# d_heading = base.angdiff(goal_heading, x[2])
|
|
1878
|
+
# v.stopif(base.norm(x[0:2] - goal) < 0.1)
|
|
1879
|
+
|
|
1880
|
+
# return (1, d_heading)
|
|
1881
|
+
|
|
1882
|
+
# veh.control=RandomPath(10)
|
|
1883
|
+
# p = veh.run(1000, plot=True)
|
|
1884
|
+
# # plt.show()
|
|
1885
|
+
# print(p)
|
|
1886
|
+
|
|
1887
|
+
# veh.plot_xyt_t()
|
|
1888
|
+
# veh.plot(p)
|
|
1889
|
+
|
|
1890
|
+
# t, x = veh.path(5, u=control)
|
|
1891
|
+
# print(t)
|
|
1892
|
+
|
|
1893
|
+
# fig, ax = plt.subplots()
|
|
1894
|
+
|
|
1895
|
+
# ax.set_xlim(-5, 5)
|
|
1896
|
+
# ax.set_ylim(-5, 5)
|
|
1897
|
+
|
|
1898
|
+
# v = VehicleAnimation.Polygon(shape='triangle', maxdim=0.1, color='r')
|
|
1899
|
+
# v = VehicleAnimation.Icon('car3.png', maxdim=2, centre=[0.3, 0.5])
|
|
1900
|
+
# v = VehicleAnimation.Icon('/Users/corkep/Dropbox/code/robotics-toolbox-python/roboticstoolbox/data/car1.png', maxdim=2, centre=[0.3, 0.5])
|
|
1901
|
+
# v = VehicleAnimation.icon('car3.png', maxdim=2, centre=[0.3, 0.5])
|
|
1902
|
+
# v = VehicleAnimation.marker()
|
|
1903
|
+
# v.start()
|
|
1904
|
+
# plt.grid(True)
|
|
1905
|
+
# # plt.axis('equal')
|
|
1906
|
+
|
|
1907
|
+
# for theta in np.linspace(0, 2 * np.pi, 100):
|
|
1908
|
+
# v.update([0, 0, theta])
|
|
1909
|
+
# plt.pause(0.1)
|