From f5598823dfc46e4c91b0cc9e714e66bd45080852 Mon Sep 17 00:00:00 2001 From: Simon Ottenhaus <simon.ottenhaus@kit.edu> Date: Thu, 23 Apr 2020 12:10:28 +0200 Subject: [PATCH] added joint costs to fix cla1 movement --- ...ointCartesianNaturalPositionController.cpp | 1 + ...uralPositionControllerWidgetController.cpp | 4 + ...rtesianNaturalPositionControllerConfig.ice | 5 +- .../CartesianNaturalPositionController.cpp | 4 + .../core/CartesianVelocityController.cpp | 131 ++++++++++-------- .../core/CartesianVelocityController.h | 19 ++- .../CartesianVelocityControllerWithRamp.cpp | 4 +- .../test/CartesianVelocityControllerTest.cpp | 6 +- 8 files changed, 106 insertions(+), 68 deletions(-) diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianNaturalPositionController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianNaturalPositionController.cpp index 6bbc17af4..106b2fbf9 100644 --- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianNaturalPositionController.cpp +++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianNaturalPositionController.cpp @@ -38,6 +38,7 @@ namespace armarx << "maxJointVelocity " << vec2str(cfg.maxJointVelocity) << '\n' << "maxNullspaceVelocity " << vec2str(cfg.maxNullspaceVelocity) << '\n' + << "jointCosts " << vec2str(cfg.jointCosts) << '\n' << "jointLimitAvoidanceKp " << cfg.jointLimitAvoidanceKp << '\n' << "elbowKp " << cfg.elbowKp << '\n' diff --git a/source/RobotAPI/gui-plugins/CartesianNaturalPositionController/CartesianNaturalPositionControllerWidgetController.cpp b/source/RobotAPI/gui-plugins/CartesianNaturalPositionController/CartesianNaturalPositionControllerWidgetController.cpp index 06d753341..f14d3a669 100644 --- a/source/RobotAPI/gui-plugins/CartesianNaturalPositionController/CartesianNaturalPositionControllerWidgetController.cpp +++ b/source/RobotAPI/gui-plugins/CartesianNaturalPositionController/CartesianNaturalPositionControllerWidgetController.cpp @@ -185,6 +185,9 @@ namespace armarx arm.elbow = elb; arm.tcp = tcp; + std::vector<float> jointCosts = std::vector<float>(rns->getSize(), 1); + jointCosts.at(0) = 4; + armarx::RemoteRobot::synchronizeLocalClone(_robot, _robotStateComponent); _tcpTarget = rns->getTCP()->getPoseInRootFrame(); @@ -196,6 +199,7 @@ namespace armarx ik.setUpperArmLength(upper_arm_length); ik.setLowerArmLength(lower_arm_length); NJointCartesianNaturalPositionControllerConfigPtr config = CartesianNaturalPositionControllerProxy::MakeConfig(rns->getName(), elb->getName()); + config->runCfg.jointCosts = jointCosts; CartesianNaturalPositionControllerConfig runCfg = config->runCfg; updateKpSliders(runCfg); //config->runCfg = runCfg; diff --git a/source/RobotAPI/interface/core/CartesianNaturalPositionControllerConfig.ice b/source/RobotAPI/interface/core/CartesianNaturalPositionControllerConfig.ice index efd0de988..a876489d1 100644 --- a/source/RobotAPI/interface/core/CartesianNaturalPositionControllerConfig.ice +++ b/source/RobotAPI/interface/core/CartesianNaturalPositionControllerConfig.ice @@ -35,10 +35,11 @@ module armarx Ice::FloatSeq maxJointVelocity; Ice::FloatSeq maxNullspaceVelocity; + Ice::FloatSeq jointCosts; float jointLimitAvoidanceKp = 0.1; - float elbowKp = 2; - float nullspaceTargetKp = 2; + float elbowKp = 1; + float nullspaceTargetKp = 1; float thresholdOrientationNear = 0.1; float thresholdOrientationReached = 0.05; diff --git a/source/RobotAPI/libraries/core/CartesianNaturalPositionController.cpp b/source/RobotAPI/libraries/core/CartesianNaturalPositionController.cpp index 4b0b4be7d..158aa743b 100644 --- a/source/RobotAPI/libraries/core/CartesianNaturalPositionController.cpp +++ b/source/RobotAPI/libraries/core/CartesianNaturalPositionController.cpp @@ -291,6 +291,10 @@ namespace armarx cfg.maxOrientationAcceleration, cfg.maxNullspaceAcceleration ); + if (cfg.jointCosts.size() > 0) + { + vcTcp.controller.setJointCosts(cfg.jointCosts); + } } Eigen::VectorXf CartesianNaturalPositionController::actualTcpVel(const Eigen::VectorXf& jointVel) diff --git a/source/RobotAPI/libraries/core/CartesianVelocityController.cpp b/source/RobotAPI/libraries/core/CartesianVelocityController.cpp index 228df7d26..f140f9512 100644 --- a/source/RobotAPI/libraries/core/CartesianVelocityController.cpp +++ b/source/RobotAPI/libraries/core/CartesianVelocityController.cpp @@ -29,40 +29,60 @@ #include <RobotAPI/libraries/core/math/MathUtils.h> #include <VirtualRobot/math/Helpers.h> +#include <ArmarXCore/core/exceptions/local/ExpressionException.h> using namespace armarx; CartesianVelocityController::CartesianVelocityController(const VirtualRobot::RobotNodeSetPtr& rns, const VirtualRobot::RobotNodePtr& tcp, const VirtualRobot::JacobiProvider::InverseJacobiMethod invJacMethod, bool considerJointLimits) : rns(rns), - considerJointLimits(considerJointLimits) + _considerJointLimits(considerJointLimits) { //ARMARX_IMPORTANT << VAROUT(rns->getRobot()->getRootNode()); ik.reset(new VirtualRobot::DifferentialIK(rns, rns->getRobot()->getRootNode(), invJacMethod)); - this->tcp = tcp ? tcp : rns->getTCP(); + _tcp = tcp ? tcp : rns->getTCP(); - this->cartesianMMRegularization = 100; - this->cartesianRadianRegularization = 1; + _cartesianMMRegularization = 100; + _cartesianRadianRegularization = 1; + _jointCosts = Eigen::VectorXf::Constant(rns->getSize(), 1); } -Eigen::VectorXf CartesianVelocityController::calculate(const Eigen::VectorXf& cartesianVel, VirtualRobot::IKSolver::CartesianSelection mode) +void CartesianVelocityController::calculateJacobis(VirtualRobot::IKSolver::CartesianSelection mode) { - jacobi = ik->getJacobianMatrix(tcp, mode); + jacobi = ik->getJacobianMatrix(_tcp, mode); + _jacobiWithCosts = Eigen::MatrixXf(jacobi.rows(), jacobi.cols()); + for (int r = 0; r < jacobi.rows(); r++) + { + for (int c = 0; c < jacobi.cols(); c++) + { + _jacobiWithCosts(r, c) = jacobi(r, c) / _jointCosts(c); + } + } + _inv = ik->computePseudoInverseJacobianMatrix(_jacobiWithCosts, ik->getJacobiRegularization(mode)); +} - inv = ik->computePseudoInverseJacobianMatrix(jacobi, ik->getJacobiRegularization(mode)); +Eigen::VectorXf CartesianVelocityController::calculate(const Eigen::VectorXf& cartesianVel, VirtualRobot::IKSolver::CartesianSelection mode) +{ + return calculate(cartesianVel, Eigen::VectorXf::Zero(0), mode); + /*calculateJacobis(mode); - if (considerJointLimits) + if (_considerJointLimits) { - adjustJacobiForJointsAtJointLimits(mode, cartesianVel); + clampJacobiAtJointLimits(mode, cartesianVel, _jacobiWithCosts, _inv); } - Eigen::VectorXf jointVel = inv * cartesianVel; + Eigen::VectorXf jointVel = _inv * cartesianVel; + jointVel += nsv; + for (int r = 0; r < jointVel.rows(); r++) + { + jointVel(r) = jointVel(r) / _jointCosts(r); + } if (maximumJointVelocities.rows() > 0) { jointVel = ::math::Helpers::LimitVectorLength(jointVel, maximumJointVelocities); } - return jointVel; + return jointVel;*/ } Eigen::VectorXf CartesianVelocityController::calculate(const Eigen::VectorXf& cartesianVel, float KpJointLimitAvoidanceScale, VirtualRobot::IKSolver::CartesianSelection mode) @@ -73,50 +93,44 @@ Eigen::VectorXf CartesianVelocityController::calculate(const Eigen::VectorXf& ca Eigen::VectorXf CartesianVelocityController::calculate(const Eigen::VectorXf& cartesianVel, const Eigen::VectorXf& nullspaceVel, VirtualRobot::IKSolver::CartesianSelection mode) { - //ARMARX_IMPORTANT << VAROUT(rns.get()); - //ARMARX_IMPORTANT << VAROUT(tcp.get()); - //ARMARX_IMPORTANT << VAROUT(ik.get()); - jacobi = ik->getJacobianMatrix(tcp, mode); - // ARMARX_IMPORTANT << "nullspaceVel " << nullspaceVel.transpose(); - Eigen::FullPivLU<Eigen::MatrixXf> lu_decomp(jacobi); - //ARMARX_IMPORTANT << "The rank of the jacobi is " << lu_decomp.rank(); - //ARMARX_IMPORTANT << "Null space: " << lu_decomp.kernel(); - Eigen::MatrixXf nullspace = lu_decomp.kernel(); + calculateJacobis(mode); - // Eigen::MatrixXf nullspace = Eigen::MatrixXf::Identity(jacobi.cols(), jacobi.cols()) - inv * jacobi; + Eigen::VectorXf nsv = Eigen::VectorXf::Zero(rns->getSize()); - Eigen::VectorXf nsv = Eigen::VectorXf::Zero(nullspace.rows()); - for (int i = 0; i < nullspace.cols(); i++) + if (nullspaceVel.rows() > 0) { - float squaredNorm = nullspace.col(i).squaredNorm(); - // Prevent division by zero - if (squaredNorm > 1.0e-32f) + // ARMARX_IMPORTANT << "nullspaceVel " << nullspaceVel.transpose(); + Eigen::FullPivLU<Eigen::MatrixXf> lu_decomp(_jacobiWithCosts); + //ARMARX_IMPORTANT << "The rank of the _jacobiWithCosts is " << lu_decomp.rank(); + //ARMARX_IMPORTANT << "Null space: " << lu_decomp.kernel(); + Eigen::MatrixXf nullspace = lu_decomp.kernel(); + + for (int i = 0; i < nullspace.cols(); i++) { - nsv += nullspace.col(i) * nullspace.col(i).dot(nullspaceVel) / nullspace.col(i).squaredNorm(); + float squaredNorm = nullspace.col(i).squaredNorm(); + // Prevent division by zero + if (squaredNorm > 1.0e-32f) + { + nsv += nullspace.col(i) * nullspace.col(i).dot(nullspaceVel) / nullspace.col(i).squaredNorm(); + } } } - // Eigen::VectorXf nsv = nullspace * nullspaceVel; - - //nsv /= kernel.cols(); - - - - inv = ik->computePseudoInverseJacobianMatrix(jacobi, ik->getJacobiRegularization(mode)); - - - if (considerJointLimits) + if (_considerJointLimits) { - adjustJacobiForJointsAtJointLimits(mode, cartesianVel); + clampJacobiAtJointLimits(mode, cartesianVel, _jacobiWithCosts, _inv); } - Eigen::VectorXf jointVel = inv * cartesianVel; + Eigen::VectorXf jointVel = _inv * cartesianVel; jointVel += nsv; - + for (int r = 0; r < jointVel.rows(); r++) + { + jointVel(r) = jointVel(r) / _jointCosts(r); + } if (maximumJointVelocities.rows() > 0) { @@ -189,8 +203,8 @@ Eigen::VectorXf CartesianVelocityController::calculateNullspaceVelocity(const Ei void CartesianVelocityController::setCartesianRegularization(float cartesianMMRegularization, float cartesianRadianRegularization) { - this->cartesianMMRegularization = cartesianMMRegularization; - this->cartesianRadianRegularization = cartesianRadianRegularization; + _cartesianMMRegularization = cartesianMMRegularization; + _cartesianRadianRegularization = cartesianRadianRegularization; } Eigen::VectorXf CartesianVelocityController::calculateRegularization(VirtualRobot::IKSolver::CartesianSelection mode) @@ -201,31 +215,30 @@ Eigen::VectorXf CartesianVelocityController::calculateRegularization(VirtualRobo if (mode & VirtualRobot::IKSolver::X) { - regularization(i++) = 1 / cartesianMMRegularization; + regularization(i++) = 1 / _cartesianMMRegularization; } if (mode & VirtualRobot::IKSolver::Y) { - regularization(i++) = 1 / cartesianMMRegularization; + regularization(i++) = 1 / _cartesianMMRegularization; } if (mode & VirtualRobot::IKSolver::Z) { - regularization(i++) = 1 / cartesianMMRegularization; + regularization(i++) = 1 / _cartesianMMRegularization; } if (mode & VirtualRobot::IKSolver::Orientation) { - regularization(i++) = 1 / cartesianRadianRegularization; - regularization(i++) = 1 / cartesianRadianRegularization; - regularization(i++) = 1 / cartesianRadianRegularization; + regularization(i++) = 1 / _cartesianRadianRegularization; + regularization(i++) = 1 / _cartesianRadianRegularization; + regularization(i++) = 1 / _cartesianRadianRegularization; } return regularization.topRows(i); } -bool CartesianVelocityController::adjustJacobiForJointsAtJointLimits(VirtualRobot::IKSolver::CartesianSelection mode, const Eigen::VectorXf& cartesianVel, float jointLimitCheckAccuracy) +bool CartesianVelocityController::clampJacobiAtJointLimits(VirtualRobot::IKSolver::CartesianSelection mode, const Eigen::VectorXf& cartesianVel, Eigen::MatrixXf& jacobi, Eigen::MatrixXf& inv, float jointLimitCheckAccuracy) { - bool modifiedJacobi = false; Eigen::VectorXf jointVel = inv * cartesianVel; @@ -252,22 +265,32 @@ bool CartesianVelocityController::adjustJacobiForJointsAtJointLimits(VirtualRobo modifiedJacobi = true; } } - if (modifiedJacobi) { - // calculate inverse jacobi again since atleast one joint would be driven into the limit inv = ik->computePseudoInverseJacobianMatrix(jacobi, ik->getJacobiRegularization(mode)); } + return modifiedJacobi; } bool CartesianVelocityController::getConsiderJointLimits() const { - return considerJointLimits; + return _considerJointLimits; } void CartesianVelocityController::setConsiderJointLimits(bool value) { - considerJointLimits = value; + _considerJointLimits = value; } + +void CartesianVelocityController::setJointCosts(const std::vector<float>& jointCosts) +{ + ARMARX_CHECK((int)jointCosts.size() == _jointCosts.rows()); + for (size_t i = 0; i < jointCosts.size(); i++) + { + _jointCosts(i) = jointCosts.at(i); + } +} + + diff --git a/source/RobotAPI/libraries/core/CartesianVelocityController.h b/source/RobotAPI/libraries/core/CartesianVelocityController.h index 1639e82f6..a3a577198 100644 --- a/source/RobotAPI/libraries/core/CartesianVelocityController.h +++ b/source/RobotAPI/libraries/core/CartesianVelocityController.h @@ -39,7 +39,7 @@ namespace armarx public: CartesianVelocityController(const VirtualRobot::RobotNodeSetPtr& rns, const VirtualRobot::RobotNodePtr& tcp = nullptr, const VirtualRobot::JacobiProvider::InverseJacobiMethod invJacMethod = VirtualRobot::JacobiProvider::eSVDDamped, - bool considerJointLimits = true); + bool _considerJointLimits = true); CartesianVelocityController(CartesianVelocityController&&) = default; CartesianVelocityController& operator=(CartesianVelocityController&&) = default; @@ -57,18 +57,23 @@ namespace armarx void setConsiderJointLimits(bool value); Eigen::MatrixXf jacobi; - Eigen::MatrixXf inv; VirtualRobot::RobotNodeSetPtr rns; VirtualRobot::DifferentialIKPtr ik; - VirtualRobot::RobotNodePtr tcp; + VirtualRobot::RobotNodePtr _tcp; Eigen::VectorXf maximumJointVelocities; + void setJointCosts(const std::vector<float>& _jointCosts); + private: + void calculateJacobis(VirtualRobot::IKSolver::CartesianSelection mode); + Eigen::MatrixXf _jacobiWithCosts; + Eigen::MatrixXf _inv; Eigen::VectorXf calculateRegularization(VirtualRobot::IKSolver::CartesianSelection mode); - bool adjustJacobiForJointsAtJointLimits(VirtualRobot::IKSolver::CartesianSelection mode, const Eigen::VectorXf& cartesianVel, float jointLimitCheckAccuracy = 0.001f); - bool considerJointLimits = true; - float cartesianMMRegularization; - float cartesianRadianRegularization; + bool clampJacobiAtJointLimits(VirtualRobot::IKSolver::CartesianSelection mode, const Eigen::VectorXf& cartesianVel, Eigen::MatrixXf& jacobi, Eigen::MatrixXf& _inv, float jointLimitCheckAccuracy = 0.001f); + bool _considerJointLimits = true; + float _cartesianMMRegularization; + float _cartesianRadianRegularization; + Eigen::VectorXf _jointCosts; }; } diff --git a/source/RobotAPI/libraries/core/CartesianVelocityControllerWithRamp.cpp b/source/RobotAPI/libraries/core/CartesianVelocityControllerWithRamp.cpp index 228f765b8..a72fe97e5 100644 --- a/source/RobotAPI/libraries/core/CartesianVelocityControllerWithRamp.cpp +++ b/source/RobotAPI/libraries/core/CartesianVelocityControllerWithRamp.cpp @@ -40,7 +40,7 @@ namespace armarx void CartesianVelocityControllerWithRamp::setCurrentJointVelocity(const Eigen::Ref<const Eigen::VectorXf>& currentJointVelocity) { - Eigen::MatrixXf jacobi = controller.ik->getJacobianMatrix(controller.tcp, mode); + Eigen::MatrixXf jacobi = controller.ik->getJacobianMatrix(controller._tcp, mode); //Eigen::MatrixXf inv = controller.ik->computePseudoInverseJacobianMatrix(jacobi, controller.ik->getJacobiRegularization(mode)); @@ -59,7 +59,7 @@ namespace armarx void CartesianVelocityControllerWithRamp::switchMode(const Eigen::VectorXf& currentJointVelocity, VirtualRobot::IKSolver::CartesianSelection mode) { - Eigen::MatrixXf jacobi = controller.ik->getJacobianMatrix(controller.tcp, mode); + Eigen::MatrixXf jacobi = controller.ik->getJacobianMatrix(controller._tcp, mode); cartesianVelocityRamp.setState(jacobi * currentJointVelocity, mode); this->mode = mode; } diff --git a/source/RobotAPI/libraries/core/test/CartesianVelocityControllerTest.cpp b/source/RobotAPI/libraries/core/test/CartesianVelocityControllerTest.cpp index 216c48d90..ce26e1c14 100644 --- a/source/RobotAPI/libraries/core/test/CartesianVelocityControllerTest.cpp +++ b/source/RobotAPI/libraries/core/test/CartesianVelocityControllerTest.cpp @@ -116,19 +116,19 @@ BOOST_AUTO_TEST_CASE(testJointLimitAwareness) // ARMARX_INFO << "diff\n" << (inv-inv2); rns->setJointValues(oldJV); - Eigen::Vector3f posBefore = h->tcp->getPositionInRootFrame(); + Eigen::Vector3f posBefore = h->_tcp->getPositionInRootFrame(); float accuracy = 0.001f; Eigen::VectorXf jointVel = inv * cartesianVel; rns->setJointValues(oldJV + jointVel * accuracy); - Eigen::VectorXf resultCartesianVel = ((h->tcp->getPositionInRootFrame() - posBefore) / accuracy); + Eigen::VectorXf resultCartesianVel = ((h->_tcp->getPositionInRootFrame() - posBefore) / accuracy); Eigen::VectorXf jointVel2 = inv2 * cartesianVel; rns->setJointValues(oldJV + jointVel2 * accuracy); - Eigen::VectorXf resultCartesianVel2 = ((h->tcp->getPositionInRootFrame() - posBefore) / accuracy); + Eigen::VectorXf resultCartesianVel2 = ((h->_tcp->getPositionInRootFrame() - posBefore) / accuracy); Eigen::Vector3f diff = (resultCartesianVel - cartesianVel); Eigen::Vector3f diff2 = (resultCartesianVel2 - cartesianVel); -- GitLab