KdlTreeIk.cpp
Go to the documentation of this file.
00001 #include <robodyn_controllers/KdlTreeIk.h>
00002 
00003 const int KdlTreeIk::IGNORE   = r2_msgs::PriorityArray::IGNORE;
00004 const int KdlTreeIk::LOW      = r2_msgs::PriorityArray::LOW;
00005 const int KdlTreeIk::MEDIUM   = r2_msgs::PriorityArray::MEDIUM;
00006 const int KdlTreeIk::HIGH     = r2_msgs::PriorityArray::HIGH;
00007 const int KdlTreeIk::CRITICAL = r2_msgs::PriorityArray::CRITICAL;
00008 
00009 KdlTreeIk::KdlTreeIk()
00010     : KdlTreeUtilities()
00011     , inertias(1)
00012     , useDampedLeastSquares(true)
00013 {
00014     setTimeStep();
00015     setMaxCriticalIterations();
00016     setMaxNonCriticalIterations();
00017     setEpsilon();
00018     setLambda();
00019 }
00020 
00021 KdlTreeIk::~KdlTreeIk()
00022 {
00023 }
00024 
00025 void KdlTreeIk::initialize()
00026 {
00027     KdlTreeUtilities::getJointNames(jointNames);
00028 
00029     // setup solver
00030     fkPosSolverPtr.reset(new KdlTreeFk());
00031     resetSolver();
00032     inertias.resize(jointNames.size());
00033 }
00034 
00035 void KdlTreeIk::resetSolver()
00036 {
00037     fkPosSolverPtr->setTree(tree);
00038     jacSolverPtr.reset(new KDL::TreeJntToJacSolver(tree));
00039 }
00040 
00041 void KdlTreeIk::setTimeStep(double timeStepIn)
00042 {
00043     if (timeStepIn > 0)
00044     {
00045         timeStep = timeStepIn;
00046     }
00047     else
00048     {
00049         std::stringstream err;
00050         err << "KdlTreeIk::setTimeStep() - Time step must be greater than 0";
00051         NasaCommonLogging::Logger::log("gov.nasa.controllers.KdlTreeIk", log4cpp::Priority::ERROR, err.str());
00052         throw std::invalid_argument(err.str());
00053     }
00054 }
00055 
00056 void KdlTreeIk::getFrames(const KDL::JntArray& joints_in, std::map<std::string, KDL::Frame>& frameMap)
00057 {
00058     fkPosSolverPtr->getPoses(joints_in, frameMap);
00059 }
00060 void KdlTreeIk::setJointInertias(const std::map<std::string, double>& inertiaIn)
00061 {
00062     // if the inertia map has changed, repopulate the inertias
00063     if (inertiaIn != inertiaMap)
00064     {
00065         inertiaMap = inertiaIn;
00066         minInertia = 1.;
00067         maxInertia = 1.;
00068         std::map<std::string, double>::iterator itr;
00069 
00070         for (itr = inertiaMap.begin(); itr != inertiaMap.end(); ++itr)
00071         {
00072             if (minInertia > itr->second)
00073             {
00074                 minInertia = itr->second;
00075             }
00076 
00077             if (maxInertia < itr->second)
00078             {
00079                 maxInertia = itr->second;
00080             }
00081         }
00082 
00083         for (unsigned int i = 0; i < jointNames.size(); ++i)
00084         {
00085             itr = inertiaMap.find(jointNames[i]);
00086 
00087             if (itr != inertiaMap.end())
00088             {
00089                 inertias(i) = itr->second;
00090             }
00091             else
00092             {
00093                 inertias(i) = minInertia;
00094             }
00095         }
00096     }
00097 }
00098 
00099 void KdlTreeIk::getJointPositions(const KDL::JntArray& jointsIn, const std::vector<std::string>& nodeNames,
00100                                   const std::vector<KDL::Frame>& nodeFrames, KDL::JntArray& joints_out,
00101                                   const std::vector<NodePriority>& nodePriorities)
00102 {
00103     // create frame and twist maps
00104     std::map<std::string, KDL::Frame> frameMap;
00105     std::vector<std::pair<std::string, KDL::Twist> > twistVec;
00106 
00107     for (unsigned int i = 0; i < nodeNames.size(); ++i)
00108     {
00109         if (tree.getSegment(nodeNames[i]) == tree.getSegments().end())
00110         {
00111             std::stringstream err;
00112             err << "KdlTreeIk node name (" << nodeNames[i] << ") not found in tree" << std::endl;
00113             NasaCommonLogging::Logger::log("gov.nasa.controllers.KdlTreeIk", log4cpp::Priority::ERROR, err.str());
00114             throw std::runtime_error(err.str());
00115             return;
00116         }
00117 
00118         frameMap.insert(std::make_pair(nodeNames[i], KDL::Frame()));
00119         twistVec.push_back(std::make_pair(nodeNames[i], KDL::Twist()));
00120     }
00121 
00122     KDL::JntArray delta_joints(jointsIn.rows());
00123     joints_out = jointsIn;
00124     unsigned int iter;
00125 
00126     for (iter = 0; iter < critMaxIter; ++iter)
00127     {
00128         //get the current poses of the nodes (frames) we are controlling
00129         fkPosSolverPtr->getPoses(joints_out, frameMap);
00130 
00131         bool twistZero = true;
00132 
00133         for (unsigned int nodeIndex = 0; nodeIndex < nodeNames.size(); ++nodeIndex)
00134         {
00135             //find the difference between the current frame pose (frameMap) and the deisred frame pose (nodeFrames)
00136             KDL::Twist twist = KDL::diff(frameMap.at(nodeNames[nodeIndex]), nodeFrames.at(nodeIndex));
00137             //save in twistVec
00138             twistVec[nodeIndex].second = twist;
00139 
00140             //determine if a move is necessary (twistZero = true, no movement)
00141             for (unsigned int axisIndex = 0; axisIndex < 3; ++axisIndex)
00142             {
00143                 if (!KDL::Equal(twist.vel[axisIndex], 0., eps))
00144                 {
00145                     if (nodePriorities[nodeIndex].vel[axisIndex] == KdlTreeIk::CRITICAL || iter < nonCritMaxIter)
00146                     {
00147                         twistZero = false;
00148                     }
00149                 }
00150             }
00151 
00152             for (unsigned int axisIndex = 0; axisIndex < 3; ++axisIndex)
00153             {
00154                 if (!KDL::Equal(twist.rot[axisIndex], 0., eps))
00155                 {
00156                     if (nodePriorities[nodeIndex].rot[axisIndex] == KdlTreeIk::CRITICAL || iter < nonCritMaxIter)
00157                     {
00158                         twistZero = false;
00159                     }
00160                 }
00161             }
00162         }
00163 
00164         if (twistZero)
00165         {
00166             break;
00167         }
00168 
00169         //a move is necessary, find the velocity
00170         getJointVelocities(joints_out, twistVec, nodePriorities, delta_joints);
00171 
00172         std::map<std::string, double>::const_iterator it;
00173 
00174         for (unsigned int jointIndex = 0; jointIndex < joints_out.rows(); ++jointIndex)
00175         {
00176             // deprecated joint limiting (leaving commented until RDEV-1375)
00177 //            if ((it = jointMin.find(jointNames.at(jointIndex))) != jointMin.end() // min set
00178 //                    && joints_out(jointIndex) <= it->second // min violated
00179 //                    && delta_joints(jointIndex) < 0.) // moving toward min
00180 //            {
00181 //                if (jointLimBuffer > 0.)
00182 //                    delta_joints(jointIndex) *= (1. + (joints_out(jointIndex) - it->second) / jointLimBuffer);
00183 //                else
00184 //                    delta_joints(jointIndex) = 0.;
00185 //            }
00186 //            else if ((it = jointMax.find(jointNames.at(jointIndex))) != jointMax.end() // max set
00187 //                     && joints_out(jointIndex) >= it->second // max violated
00188 //                     && delta_joints(jointIndex) > 0.) // moving toward max
00189 //            {
00190 //                if (jointLimBuffer > 0.)
00191 //                    delta_joints(jointIndex) *= (1. - (joints_out(jointIndex) - it->second) / jointLimBuffer);
00192 //                else
00193 //                    delta_joints(jointIndex) = 0.;
00194 //            }
00195 
00196             joints_out(jointIndex) += delta_joints(jointIndex);
00197 
00198             if (positionLimiter->hasLimits(jointNames.at(jointIndex)))
00199             {
00200                 positionLimiter->limit(jointNames.at(jointIndex), joints_out(jointIndex));
00201             }
00202         }
00203     }
00204 
00205     if (iter >= critMaxIter)
00206     {
00207         std::stringstream err;
00208         err << "Unable to find an IK solution" << std::endl;
00209         NasaCommonLogging::Logger::log("gov.nasa.controllers.KdlTreeIk", log4cpp::Priority::ERROR, err.str());
00210         throw std::runtime_error(err.str());
00211         return;
00212     }
00213 }
00214 
00215 void KdlTreeIk::getJointVelocities(const KDL::JntArray& jointsIn, const std::vector<std::pair<std::string, KDL::Twist> >& twist_deltas,
00216                                    const std::vector<NodePriority>& nodePriorities, KDL::JntArray& joint_deltas) const
00217 {
00218     // get the jacobian
00219     unsigned int numConstraints = 0;
00220 
00221     for (std::vector<NodePriority>::const_iterator it = nodePriorities.begin(); it != nodePriorities.end(); ++it)
00222     {
00223         for (int i = 0; i < 6; ++i)
00224         {
00225             if (it->operator[](i) != IGNORE)
00226             {
00227                 ++numConstraints;
00228             }
00229 
00230         }
00231 
00232     }
00233 
00234     unsigned int    numJoints = jointsIn.rows();
00235     KDL::Jacobian   jac(numJoints);
00236     Eigen::MatrixXd bigJac(numConstraints, numJoints);
00237     Eigen::VectorXd bigTwist(numConstraints);
00238     MatrixXd        Wy            = MatrixXd::Identity(numConstraints, numConstraints);
00239     unsigned int    priorityIndex = 0;
00240     unsigned int    jacIndex      = 0;
00241 
00242     for (std::vector<std::pair<std::string, KDL::Twist> >::const_iterator twistIt = twist_deltas.begin(); twistIt != twist_deltas.end(); ++twistIt)
00243     {
00244         KDL::Twist nPriority = nodePriorities[priorityIndex];
00245         //get jacobian for twist
00246         int ret = jacSolverPtr->JntToJac(jointsIn, jac, twistIt->first);
00247 
00248         if (ret < 0)
00249         {
00250             std::stringstream err;
00251             err << "Unable to find a Jacobian for Twist: " << twistIt->first << std::endl;
00252             NasaCommonLogging::Logger::log("gov.nasa.controllers.KdlTreeIk", log4cpp::Priority::ERROR, err.str());
00253             throw std::runtime_error(err.str());
00254             return;
00255         }
00256 
00257         // put jacobian in big matrix and put the twist in the big t
00258         for (unsigned int i = 0; i < 6; ++i)
00259         {
00260             if (nPriority[i] != IGNORE)
00261             {
00262                 bigJac.block(jacIndex, 0, 1, numJoints) = jac.data.block(i, 0, 1, numJoints);
00263                 bigTwist[jacIndex]                      = twistIt->second[i];
00264                 Wy(jacIndex, jacIndex)                  = (256 - static_cast<double>(nPriority[i])) / 255.;
00265                 ++jacIndex;
00266             }
00267 
00268         }
00269 
00270         ++priorityIndex;
00271     }
00272 
00273     // get weighted jacobian
00274     bigJac = Wy * bigJac;
00275 
00276     // get SVD
00277     VectorXd tmp(numJoints);
00278     VectorXd S(VectorXd::Zero(numJoints));
00279     MatrixXd U(MatrixXd::Identity(numConstraints, numJoints));
00280     MatrixXd V(MatrixXd::Identity(numJoints, numJoints));
00281 
00282     if (KDL::svd_eigen_HH(bigJac, U, S, V, tmp, critMaxIter) < 0)
00283     {
00284         std::stringstream err;
00285         err << "SVD calculation failed" << std::endl;
00286         NasaCommonLogging::Logger::log("gov.nasa.controllers.KdlTreeIk", log4cpp::Priority::ERROR, err.str());
00287         throw std::runtime_error(err.str());
00288         return;
00289     }
00290 
00291     // get weighted twists
00292     bigTwist = Wy * bigTwist;
00293 
00294     //first we calculate Ut*v_in
00295     double sum;
00296 
00297     for (unsigned int i = 0; i < numJoints; ++i)
00298     {
00299         sum = 0.0;
00300 
00301         for (unsigned int j = 0; j < numConstraints; ++j)
00302         {
00303             sum += U(j, i) * bigTwist(j);
00304         }
00305 
00306         if (useDampedLeastSquares)
00307         {
00308             // Damped Least Squares
00309             tmp[i] = sum * S[i] / (S[i] * S[i] + lambda_squared);
00310         }
00311         else
00312         {
00313             // truncated PseudoInverse
00314             tmp[i] = sum * (fabs(S[i]) < eps ? 0.0 : 1.0 / S[i]);
00315         }
00316     }
00317 
00318     //tmp is now: tmp=S_pinv*Ut*v_in, we still have to premultiply
00319     //it with V to get qdot_out
00320     for (unsigned int i = 0; i < numJoints; ++i)
00321     {
00322         sum = 0.0;
00323 
00324         for (unsigned int j = 0; j < numJoints; ++j)
00325         {
00326             sum += V(i, j) * tmp[j];
00327         }
00328 
00329         //Put the result in qdot_out
00330         joint_deltas(i) = sum;
00331     }
00332 }


robodyn_controllers
Author(s):
autogenerated on Sat Jun 8 2019 20:20:53