// SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (C) 2007 Ruben Smits // Version: 1.0 // Author: Ruben Smits // Maintainer: Ruben Smits // URL: http://www.orocos.org/kdl // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "chainiksolvervel_wdls.hpp" #include "utilities/svd_eigen_HH.hpp" namespace KDL { ChainIkSolverVel_wdls::ChainIkSolverVel_wdls(const Chain& _chain,double _eps,int _maxiter): chain(_chain), jnt2jac(chain), jac(chain.getNrOfJoints()), U(MatrixXd::Zero(6,chain.getNrOfJoints())), S(VectorXd::Zero(chain.getNrOfJoints())), V(MatrixXd::Zero(chain.getNrOfJoints(),chain.getNrOfJoints())), eps(_eps), maxiter(_maxiter), tmp(VectorXd::Zero(chain.getNrOfJoints())), tmp_jac(MatrixXd::Zero(6,chain.getNrOfJoints())), tmp_jac_weight1(MatrixXd::Zero(6,chain.getNrOfJoints())), tmp_jac_weight2(MatrixXd::Zero(6,chain.getNrOfJoints())), tmp_ts(MatrixXd::Zero(6,6)), tmp_js(MatrixXd::Zero(chain.getNrOfJoints(),chain.getNrOfJoints())), weight_ts(MatrixXd::Identity(6,6)), weight_js(MatrixXd::Identity(chain.getNrOfJoints(),chain.getNrOfJoints())), lambda(0.0), lambda_scaled(0.0), nrZeroSigmas(0), svdResult(0), sigmaMin(0) { } ChainIkSolverVel_wdls::~ChainIkSolverVel_wdls() { } void ChainIkSolverVel_wdls::setWeightJS(const Eigen::MatrixXd& Mq){ weight_js = Mq; } void ChainIkSolverVel_wdls::setWeightTS(const Eigen::MatrixXd& Mx){ weight_ts = Mx; } void ChainIkSolverVel_wdls::setLambda(const double lambda_in) { lambda=lambda_in; } void ChainIkSolverVel_wdls::setEps(const double eps_in) { eps=eps_in; } void ChainIkSolverVel_wdls::setMaxIter(const int maxiter_in) { maxiter=maxiter_in; } int ChainIkSolverVel_wdls::CartToJnt(const JntArray& q_in, const Twist& v_in, JntArray& qdot_out) { jnt2jac.JntToJac(q_in,jac); double sum; unsigned int i,j; // Initialize (internal) return values nrZeroSigmas = 0 ; sigmaMin = 0.; lambda_scaled = 0.; /* for (i=0;i=6 and 0 for <6 if ( jac.columns() >= 6 ) { sigmaMin = S(5); } else { sigmaMin = 0.; } // tmp = (Si*U'*Ly*y), for (i=0;i eps, then wdls is not active and lambda_scaled = 0 (default value) // If sigmaMin < eps, then wdls is active and lambda_scaled is scaled from 0 to lambda // Note: singular values are always positive so sigmaMin >=0 if ( sigmaMin < eps ) { lambda_scaled = sqrt(1.0-(sigmaMin/eps)*(sigmaMin/eps))*lambda ; } if(fabs(S(i))=6 due to cols>rows } // Count number of singular values near zero ++nrZeroSigmas ; } else { tmp(i) = sum/S(i); } } /* // x = Lx^-1*V*tmp + x for (i=0;i (jac.columns()-jac.rows()) ) { return (error = E_CONVERGE_PINV_SINGULAR); // converged but pinv singular } else { return (error = E_NOERROR); // have converged } } const char* ChainIkSolverVel_wdls::strError(const int error) const { if (E_SVD_FAILED == error) return "SVD failed"; else return SolverI::strError(error); } }