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
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
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
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
00129 fkPosSolverPtr->getPoses(joints_out, frameMap);
00130
00131 bool twistZero = true;
00132
00133 for (unsigned int nodeIndex = 0; nodeIndex < nodeNames.size(); ++nodeIndex)
00134 {
00135
00136 KDL::Twist twist = KDL::diff(frameMap.at(nodeNames[nodeIndex]), nodeFrames.at(nodeIndex));
00137
00138 twistVec[nodeIndex].second = twist;
00139
00140
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
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
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
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
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
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
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
00274 bigJac = Wy * bigJac;
00275
00276
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
00292 bigTwist = Wy * bigTwist;
00293
00294
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
00309 tmp[i] = sum * S[i] / (S[i] * S[i] + lambda_squared);
00310 }
00311 else
00312 {
00313
00314 tmp[i] = sum * (fabs(S[i]) < eps ? 0.0 : 1.0 / S[i]);
00315 }
00316 }
00317
00318
00319
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
00330 joint_deltas(i) = sum;
00331 }
00332 }