00001
00018 #include <urdf2inventor/Helpers.h>
00019 #include <urdf2graspit/DHParam.h>
00020 #include <ros/ros.h>
00021
00022
00023
00024 #define DH_ZERO_EPSILON 1e-05
00025
00026
00027
00028 #define DH_ZERO_DOT_EPSILON 1e-03
00029
00030
00031
00032
00033
00034
00035
00036 using urdf2graspit::DHParam;
00037
00038 template<typename Derived> Eigen::VectorBlock<Derived, 2> subVec2(Eigen::MatrixBase<Derived>& v)
00039 {
00040 return Eigen::VectorBlock<Derived, 2>(v.derived(), 0);
00041 }
00042
00043 bool equalAxis(const Eigen::Vector3d& z1, const Eigen::Vector3d& z2)
00044 {
00045 double dot = z1.dot(z2);
00046 return (std::fabs(dot - 1.0)) < DH_ZERO_DOT_EPSILON;
00047 }
00048
00049
00050 bool parallelAxis(const Eigen::Vector3d& z1, const Eigen::Vector3d& z2)
00051 {
00052 double dot = z1.dot(z2);
00053
00054 return std::fabs((std::fabs(dot) - 1.0)) < DH_ZERO_DOT_EPSILON;
00055 }
00056
00062 int equalOrParallelAxis(const Eigen::Vector3d& z1, const Eigen::Vector3d& z2)
00063 {
00064 double dot = z1.dot(z2);
00065
00066
00067 bool parallel = std::fabs((std::fabs(dot) - 1.0)) < DH_ZERO_DOT_EPSILON;
00068 bool equal = std::fabs(dot - 1.0) < DH_ZERO_DOT_EPSILON;
00069 if (equal) return 2;
00070 if (parallel) return 1;
00071 return 0;
00072 }
00073
00074
00075 bool intersectLinePlane(const Eigen::Vector3d& linePoint, const Eigen::Vector3d& lineDir,
00076 const Eigen::Vector3d& planePoint, const Eigen::Vector3d& n,
00077 Eigen::Vector3d& intersect)
00078 {
00079 if (fabs(lineDir.dot(n)) < DH_ZERO_DOT_EPSILON)
00080 {
00081 ROS_ERROR_STREAM("Line "<<lineDir<<" and plane "<<n<<" are parallel");
00082 return false;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 double u = n.dot(planePoint-linePoint) / n.dot(lineDir);
00103 intersect = linePoint + lineDir*u;
00104 return true;
00105 }
00106
00107
00114 double squaredLinesDistance(const Eigen::Vector3d& zi_1, const Eigen::Vector3d& zi,
00115 const Eigen::Vector3d& pi_1, const Eigen::Vector3d& pi,
00116 bool& parallel, Eigen::Vector3d& cli_1, Eigen::Vector3d& cli)
00117 {
00118 parallel = false;
00119
00120 Eigen::Vector3d diff = pi_1 - pi;
00121 double alpha = -zi_1.dot(zi);
00122 double bi_1 = diff.dot(zi_1);
00123 double c = diff.squaredNorm();
00124 double det = std::fabs(1.0 - alpha * alpha);
00125 double det2 = std::fabs(1.0 - std::fabs(alpha));
00126 double bi, si_1, si, sqrDist;
00127
00128
00129
00130
00131 if (det2 >= DH_ZERO_DOT_EPSILON)
00132 {
00133
00134 bi = -diff.dot(zi);
00135 double invDet = 1.0 / det;
00136 si_1 = (alpha * bi - bi_1) * invDet;
00137 si = (alpha * bi_1 - bi) * invDet;
00138 sqrDist = si_1 * (si_1 + alpha * si + 2.0 * bi_1) +
00139 si * (alpha * si_1 + si + 2.0 * bi) + c;
00140 }
00141 else
00142 {
00143
00144 si_1 = -bi_1;
00145 si = 0.0;
00146 sqrDist = bi_1 * si_1 + c;
00147 parallel = true;
00148 }
00149
00150 cli_1 = pi_1 + si_1 * zi_1;
00151 cli = pi + si * zi;
00152
00153
00154 if (sqrDist < 0.0)
00155 {
00156 sqrDist = 0.0;
00157 }
00158
00159 return sqrDist;
00160 }
00161
00162
00163
00164 #if 1
00165
00166
00167 double linesDistance(const Eigen::Vector3d& zi_1, const Eigen::Vector3d& zi,
00168 const Eigen::Vector3d& pi_1, const Eigen::Vector3d& pi,
00169 bool& parallel, Eigen::Vector3d& cli_1, Eigen::Vector3d& cli)
00170 {
00171 return sqrt(squaredLinesDistance(zi_1, zi, pi_1, pi, parallel, cli_1, cli));
00172 }
00173
00174 #else
00175
00176
00177 double linesDistance(const Eigen::Vector3d& zi_1, const Eigen::Vector3d& zi,
00178 const Eigen::Vector3d& pi_1, const Eigen::Vector3d& pi,
00179 bool& parallel, Eigen::Vector3d& cli_1, Eigen::Vector3d& cli)
00180 {
00181 parallel=parallelAxis(zi_1,zi);
00182 if (parallel)
00183 {
00184 ROS_WARN("Not tested yet: parallel z axes");
00185 cli_1=pi_1;
00186 cli=pi;
00187 Eigen::Vector3d pi_conn=pi_1-pi;
00188 if (pi_conn.norm() < DH_ZERO_EPSILON)
00189 {
00190 ROS_INFO("DHParam debug info: pi_1 and pi are equal");
00191 return 0;
00192 }
00193 if (std::fabs(pi_conn.dot(zi_1)) < DH_ZERO_DOT_EPSILON)
00194 {
00195 ROS_INFO("DHParam debug info: points are already on closest line");
00196 return pi_conn.norm();
00197 }
00198 Eigen::Vector3d lineDir = zi_1;
00199 Eigen::Vector3d linePoint = pi_1;
00200 Eigen::Vector3d point = pi;
00201 Eigen::Vector3d linePointPlaneN = lineDir.cross(linePoint-point);
00202 Eigen::Vector3d distLine = linePointPlaneN.cross(lineDir);
00203 if (!intersectLinePlane(point, distLine, linePoint, distLine, cli_1))
00204 {
00205 ROS_ERROR("Could not intersect line and plane");
00206 return 0;
00207 }
00208 cli = point;
00209 }
00210
00211 ROS_INFO("Lines are skew");
00212
00213 Eigen::Vector3d n=zi_1.cross(zi);
00214 if (std::fabs(n.norm()-1.0) > DH_ZERO_EPSILON)
00215 {
00216 ROS_ERROR_STREAM("DHParams: n should be of uniform length! Is "
00217 <<n.norm()<<" and obtained from "<<zi_1<<" (len "
00218 <<zi_1.norm()<<"), "<<zi<<"("<<zi.norm()<<"), dot "<<zi_1.dot(zi));
00219 return 0;
00220 }
00221
00222
00223 Eigen::Vector3d zi_1_n = n.cross(zi_1);
00224
00225 Eigen::Vector3d zi_n = n.cross(zi);
00226
00227 if (!intersectLinePlane(pi, zi, pi_1, zi_1_n, cli))
00228 {
00229 ROS_ERROR("Could not intersect line along zi with plane through zi_1");
00230 return 0;
00231 }
00232
00233 if (!intersectLinePlane(pi_1, zi_1, pi, zi_n, cli_1))
00234 {
00235 ROS_ERROR("Could not intersect line along zi with plane through zi_1");
00236 return 0;
00237 }
00238
00239 return (cli_1-cli).norm();
00240 }
00241 #endif
00242
00243
00244 #if 0
00245 bool DHParam::getRAndAlpha(const Eigen::Vector3d& zi_1, const Eigen::Vector3d& zi,
00246 const Eigen::Vector3d& pi_1, const Eigen::Vector3d& pi,
00247 double& r, double& alpha,
00248 Eigen::Vector3d& commonNormal, Eigen::Vector3d& nOriginOnZi_1)
00249 {
00250 ROS_INFO_STREAM("getRAndAlpha for "<<zi_1<<", "<<zi);
00251
00252 bool parallel = false;
00253 if (!getCommonNormal(zi_1, zi, pi_1, pi, commonNormal, nOriginOnZi_1, r, parallel))
00254 {
00255 ROS_ERROR("Common normal can't be obtained");
00256 alpha = 0;
00257 return false;
00258 }
00259
00260 ROS_INFO_STREAM("Common normal: "<<commonNormal);
00261
00262 if (std::fabs(zi_1.dot(commonNormal)) > DH_ZERO_DOT_EPSILON)
00263 {
00264 ROS_ERROR_STREAM("Consistency: Zi-1 and common normal not orthogonal: "<<zi_1.dot(commonNormal)<<", zi_1 = "<<zi_1<<", commonNormal = "<<commonNormal);
00265 ROS_INFO_STREAM("angle "<<acos(zi_1.dot(commonNormal))*180/M_PI);
00266 return false;
00267 }
00268 if (std::fabs(zi.dot(commonNormal)) > DH_ZERO_DOT_EPSILON)
00269 {
00270 ROS_ERROR_STREAM("Consistency: Zi and common normal not orthogonal: "<<zi.dot(commonNormal)<<", zi = "<<zi<<", commonNormal = "<<commonNormal);
00271 ROS_INFO_STREAM("angle "<<acos(zi.dot(commonNormal))*180/M_PI);
00272 return false;
00273 }
00274
00275
00276
00277 int zAxEqPl = equalOrParallelAxis(zi_1, zi);
00278 if ((zAxEqPl > 0) != parallel)
00279 {
00280 ROS_ERROR_STREAM("Consistency in DHParams functions: "
00281 <<"both functions must have considered axes parallel. zi: "
00282 <<zi_1<<" zi: "<<zi<<", parallel = "
00283 <<parallel<<" zAxEqPl = "<<zAxEqPl);
00284 }
00285
00286 if (parallel)
00287 {
00288 ROS_INFO("DEBUG-INFO DHParam: Parallel case for getRAndAlpha");
00289
00290
00291
00292
00293 nOriginOnZi_1 = pi_1;
00294 alpha = 0;
00295 if (zAxEqPl != 2)
00296 {
00297 ROS_INFO_STREAM("DEBUG-INFO DHParam: Correcting alpha for "<<zi<<" as it's not equal to "<<zi_1);
00298 alpha = M_PI;
00299 }
00300 return true;
00301 }
00302
00303
00304 alpha = acos(zi_1.dot(zi));
00305 Eigen::AngleAxisd corr(alpha, commonNormal);
00306 Eigen::Vector3d corrV = corr * zi_1;
00307 int corrEqPl = equalOrParallelAxis(zi, corrV);
00308 if (corrEqPl != 2)
00309 {
00310
00311
00312 ROS_INFO_STREAM("DEBUG-INFO DHParams: Correcting alpha (is "
00313 <<alpha<<"): "<<zi<<", "<<corrV);
00314 alpha = -alpha;
00315 }
00316
00317 if (fabs(r) < 1e-07) r=0;
00318 if (fabs(alpha) < 1e-07) alpha=0;
00319 return true;
00320 }
00321 #endif
00322
00323 bool DHParam::getAlpha(const Eigen::Vector3d& zi_1, const Eigen::Vector3d& zi,
00324 const Eigen::Vector3d& pi_1, const Eigen::Vector3d& pi,
00325 const Eigen::Vector3d& xi, double& alpha)
00326 {
00327
00328
00329 int zAxEqPl = equalOrParallelAxis(zi_1, zi);
00330 if (zAxEqPl > 0)
00331 {
00332 ROS_INFO("DEBUG-INFO DHParam: Parallel case for getAlpha");
00333 alpha = 0;
00334 if (zAxEqPl != 2)
00335 {
00336 ROS_INFO_STREAM("DEBUG-INFO DHParam: Correcting alpha for "<<zi<<" as it's not equal to "<<zi_1);
00337 alpha = M_PI;
00338 }
00339 return true;
00340 }
00341
00342
00343 alpha = acos(zi_1.dot(zi));
00344 Eigen::AngleAxisd corr(alpha, xi);
00345 Eigen::Vector3d corrV = corr * zi_1;
00346 int corrEqPl = equalOrParallelAxis(zi, corrV);
00347 if (corrEqPl != 2)
00348 {
00349
00350
00351 ROS_INFO_STREAM("DEBUG-INFO DHParams: Correcting alpha (is "
00352 <<alpha<<"): "<<zi<<", "<<corrV);
00353 alpha = -alpha;
00354 }
00355
00356 if (fabs(alpha) < 1e-07) alpha=0;
00357 return true;
00358 }
00359
00360
00361 bool DHParam::getDAndTheta(const Eigen::Vector3d& zi_1,
00362 const Eigen::Vector3d& xi_1,
00363 const Eigen::Vector3d& pi_1,
00364 const Eigen::Vector3d& xi,
00365 const Eigen::Vector3d& normOriginOnZi_1,
00366 double& d, double& theta)
00367 {
00368 Eigen::Vector3d originDiff = normOriginOnZi_1 - pi_1;
00369 d = originDiff.norm();
00370
00371 if (d > DH_ZERO_EPSILON)
00372 {
00373 originDiff.normalize();
00374 int zAxEqPl = equalOrParallelAxis(originDiff, zi_1);
00375 if (zAxEqPl == 0)
00376 {
00377
00378 ROS_ERROR_STREAM("Consistency: translation along z axis should have "
00379 <<"been parallel or equal to the z axis!"
00380 <<originDiff<<", "<<zi_1<<" (normOriginOnZ="<<normOriginOnZi_1<<")");
00381 return false;
00382 }
00383 else if (zAxEqPl == 1)
00384 {
00385 ROS_INFO_STREAM("DEBUG-INFO: Translation along z parallel to z, but not equal, so d is negative");
00386 d = -d;
00387 }
00388 }
00389
00390 if ((xi_1.norm() < DH_ZERO_EPSILON) || (xi.norm() < DH_ZERO_EPSILON))
00391 {
00392 ROS_WARN("One of the x-axises is 0, hence theta will be 0");
00393 theta = 0;
00394 return true;
00395 }
00396
00397
00398 theta = acos(xi_1.dot(xi));
00399
00400 if (std::fabs(theta) < DH_ZERO_EPSILON)
00401 {
00402 return true;
00403 }
00404
00405
00406 Eigen::AngleAxisd corr(theta, zi_1);
00407 Eigen::Vector3d corrV = corr * xi_1;
00408 int corrEqPl = equalOrParallelAxis(xi, corrV);
00409 if (corrEqPl != 2)
00410 {
00411 theta = -theta;
00412 ROS_INFO_STREAM("DEBUG-INFO DHParams: Correcting theta: "<<xi<<", "<<corrV
00413 <<", theta="<<theta);
00414 }
00415
00416 if (fabs(theta) < 1e-07) theta=0;
00417 if (fabs(d) < 1e-07) d=0;
00418
00419 return true;
00420 }
00421
00422 bool DHParam::toDenavitHartenberg(DHParam& param,
00423 const Eigen::Vector3d& zi_1,
00424 const Eigen::Vector3d& xi_1,
00425 const Eigen::Vector3d& pi_1,
00426 const Eigen::Vector3d& zi,
00427 const Eigen::Vector3d& pi,
00428 Eigen::Vector3d& xi)
00429 {
00430
00431 bool parallel = false;
00432 Eigen::Vector3d nOriginOnZi_1;
00433 if (!getCommonNormal(zi_1, zi, pi_1, pi, xi, nOriginOnZi_1, param.r, parallel))
00434 {
00435 ROS_ERROR("Common normal can't be obtained");
00436 return false;
00437 }
00438
00439 if (std::fabs(zi_1.dot(xi)) > DH_ZERO_DOT_EPSILON)
00440 {
00441 ROS_ERROR_STREAM("Consistency: Zi-1 and common normal not orthogonal: "<<zi_1.dot(xi)<<", zi_1 = "<<zi_1<<", xi = "<<xi);
00442 ROS_INFO_STREAM("angle "<<acos(zi_1.dot(xi))*180/M_PI);
00443 return false;
00444 }
00445 if (std::fabs(zi.dot(xi)) > DH_ZERO_DOT_EPSILON)
00446 {
00447 ROS_ERROR_STREAM("Consistency: Zi and common normal not orthogonal: "<<zi.dot(xi)<<", zi = "<<zi<<", xi = "<<xi);
00448 ROS_INFO_STREAM("angle "<<acos(zi.dot(xi))*180/M_PI);
00449 return false;
00450 }
00451
00452
00453
00454
00455
00456 int zAxEqPl = equalOrParallelAxis(zi_1, zi);
00457 if ((zAxEqPl > 0) != parallel)
00458 {
00459 ROS_ERROR_STREAM("Consistency in DHParams functions: "
00460 <<"both functions must have considered axes parallel. zi: "
00461 <<zi_1<<" zi: "<<zi<<", parallel = "
00462 <<parallel<<" zAxEqPl = "<<zAxEqPl);
00463 }
00464
00465
00466 if (parallel)
00467 {
00468 ROS_INFO("DEBUG-INFO DHParam: Parallel case for getCommonNormal");
00469
00470
00471
00472
00473
00474 nOriginOnZi_1 = pi_1;
00475 }
00476
00477
00478 if (fabs(param.r) < 1e-07) param.r=0;
00479
00480 if (!getAlpha(zi_1, zi, pi_1, pi, xi, param.alpha))
00481
00482 {
00483 ROS_ERROR("Could not get alpha");
00484 return false;
00485 }
00486
00487
00488 if (!getDAndTheta(zi_1, xi_1, pi_1, xi, nOriginOnZi_1, param.d, param.theta))
00489 {
00490 ROS_ERROR("Could not get d and theta");
00491 return false;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 return true;
00514 }
00515
00516
00517
00518 bool DHParam::getCommonNormal(const Eigen::Vector3d& zi_1, const Eigen::Vector3d& zi,
00519 const Eigen::Vector3d& pi_1, const Eigen::Vector3d& pi,
00520 Eigen::Vector3d& commonNormal, Eigen::Vector3d& nOriginOnZi_1,
00521 double& shortestDistance, bool& parallel)
00522 {
00523 parallel = false;
00524 Eigen::Vector3d cli_1;
00525 Eigen::Vector3d cli;
00526
00527 shortestDistance = linesDistance(zi_1, zi, pi_1, pi, parallel, cli_1, cli);
00528
00529 nOriginOnZi_1 = cli_1;
00530
00531 if (shortestDistance < DH_ZERO_EPSILON)
00532 {
00533
00534 if ((zi_1 - zi).norm() < DH_ZERO_EPSILON)
00535 {
00536
00537
00538 if (!parallel)
00539 {
00540 ROS_ERROR("DHParam: inconsistency, lines should have been found parallel");
00541 }
00542 Eigen::Vector3d testP = pi - pi_1;
00543 if (testP.norm() > 1e-05)
00544 {
00545
00546
00547 testP.normalize();
00548 if ((fabs(testP.dot(zi)) - 1) > 1e-03)
00549 {
00550 ROS_ERROR("DHParam: inconsistency, lines should be collinear");
00551 }
00552 }
00553
00554
00555 ROS_WARN_STREAM("z-axes equal. Common normal cannot be obtained ("
00556 << zi_1 << " at " << pi_1 << ", " << zi << " at " << pi << ")"
00557 << ", taking any perpendicular axis.");
00558
00559
00560 Eigen::Vector3d cross = Eigen::Vector3d::UnitX().cross(zi);
00561 if (cross.norm() < 1e-03)
00562 {
00563 cross = Eigen::Vector3d::UnitY().cross(zi);
00564 if (cross.norm() < 1e-03)
00565 {
00566 cross = Eigen::Vector3d::UnitZ().cross(zi);
00567 if (cross.norm() < 1e-03)
00568 {
00569 ROS_ERROR_STREAM("Could not determine perpendicular normal");
00570 commonNormal = Eigen::Vector3d(0, 0, 0);
00571 return false;
00572 }
00573 }
00574 }
00575 commonNormal = cross;
00576 }
00577 else
00578 {
00579 ROS_INFO_STREAM("DEBUG-INFO: z-axes intersect! "<<zi_1<<" at "<<pi_1<<", "<<zi<<" at "<<pi);
00580 commonNormal = zi_1.cross(zi);
00581
00582 }
00583
00584 }
00585 else
00586 {
00587 commonNormal = cli - cli_1;
00588
00589 commonNormal.normalize();
00590
00591
00592
00593
00594
00595 }
00596
00597
00598
00599 if (std::fabs(commonNormal.norm()-1.0) > DH_ZERO_EPSILON)
00600 {
00601 ROS_ERROR_STREAM("DHParams: common normal should be of uniform length! Is "
00602 <<commonNormal.norm()<<" and obtained from "<<zi_1<<" (len "
00603 <<zi_1.norm()<<"), "<<zi<<" (len "<<zi.norm()<<"), dot "<<zi_1.dot(zi));
00604 return false;
00605 }
00606
00607
00608 commonNormal.normalize();
00609
00610 if (parallel)
00611 {
00612 nOriginOnZi_1 = pi_1;
00613 }
00614 return true;
00615 }
00616
00617 DHParam::EigenTransform DHParam::getTransform(const DHParam& p)
00618 {
00619 Eigen::Matrix4d m = Eigen::Matrix4d::Identity();
00620
00621 EigenTransform ret;
00622 ret.setIdentity();
00623
00624 #if 1
00625
00626 double ct = cos(p.theta);
00627 double ca = cos(p.alpha);
00628 double st = sin(p.theta);
00629 double sa = sin(p.alpha);
00630 m(0, 0) = ct;
00631 m(0, 1) = -st * ca;
00632 m(0, 2) = st * sa;
00633 m(0, 3) = p.r * ct;
00634 m(1, 0) = st;
00635 m(1, 1) = ct * ca;
00636 m(1, 2) = -ct * sa;
00637 m(1, 3) = p.r * st;
00638 m(2, 0) = 0;
00639 m(2, 1) = sa;
00640 m(2, 2) = ca;
00641 m(2, 3) = p.d;
00642
00643 ret = EigenTransform(m);
00644
00645 #else
00646
00647
00648
00649
00650 ret.setIdentity();
00651 Eigen::AngleAxisd trot(p.theta,Eigen::Vector3d(0,0,1));
00652 ret.rotate(trot);
00653 ret.translate(Eigen::Vector3d(0,0,p.d));
00654 Eigen::AngleAxisd arot(p.alpha,Eigen::Vector3d(1,0,0));
00655 ret.translate(Eigen::Vector3d(p.r,0,0));
00656 ret.rotate(arot);
00657
00658 ROS_INFO_STREAM("Transform compares: "<<std::endl<<ret<<std::endl<<EigenTransform(m));
00659 #endif
00660 return ret;
00661 }
00662
00663
00664
00665 DHParam::EigenTransform DHParam::getTransform(const urdf::Pose& p)
00666 {
00667 urdf::Vector3 _jtr = p.position;
00668 Eigen::Vector3d jtr(_jtr.x, _jtr.y, _jtr.z);
00669 urdf::Rotation _jrot = p.rotation;
00670 Eigen::Quaterniond jrot(_jrot.w, _jrot.x, _jrot.y, _jrot.z);
00671 jrot.normalize();
00672 DHParam::EigenTransform tr;
00673 tr.setIdentity();
00674 tr = tr.translate(jtr);
00675 tr = tr.rotate(jrot);
00676 return tr;
00677 }
00678
00679
00680 DHParam::EigenTransform DHParam::getTransform(const DHParam::JointConstPtr& joint)
00681 {
00682 return getTransform(joint->parent_to_joint_origin_transform);
00683 }
00684
00685
00686 bool DHParam::getTransforms(const std::vector<DHParam>& dh, const bool dh2urdf,
00687 std::map<std::string,EigenTransform>& transforms)
00688 {
00689
00690
00691
00692 EigenTransform refFrameDH;
00693 EigenTransform refFrameURDF;
00694 refFrameDH.setIdentity();
00695 refFrameURDF.setIdentity();
00696
00697 JointConstPtr root_joint;
00698 int chainCnt = -1;
00699 bool resetChain = false;
00700 for (std::vector<DHParam>::const_iterator it = dh.begin(); it != dh.end(); ++it)
00701 {
00702 if (resetChain)
00703 {
00704 refFrameDH.setIdentity();
00705 refFrameURDF.setIdentity();
00706 chainCnt = -1;
00707 }
00708 resetChain = false;
00709
00710 ++chainCnt;
00711 JointConstPtr joint = it->joint;
00712 LinkConstPtr childLink = it->childLink;
00713 if (!childLink.get())
00714 {
00715 ROS_ERROR("DHParam::urdf2DHTransforms: child link is NULL");
00716 return false;
00717 }
00718
00719 if (childLink->child_joints.empty())
00720 {
00721
00722
00723
00724 resetChain = true;
00725 }
00726
00727 EigenTransform dhTrans = DHParam::getTransform(*it);
00728
00729 EigenTransform jointTransform = EigenTransform::Identity();
00730 if (chainCnt > 0) jointTransform = getTransform(joint);
00731
00732
00733
00734
00735 refFrameDH = refFrameDH * dhTrans;
00736 refFrameURDF = refFrameURDF * jointTransform;
00737
00738 EigenTransform trans;
00739 if (dh2urdf)
00740 {
00741 trans = refFrameDH.inverse() * refFrameURDF;
00742 }
00743 else
00744 {
00745 trans = refFrameURDF.inverse() * refFrameDH;
00746 }
00747
00748
00749 if (!transforms.insert(std::make_pair(childLink->name, trans)).second)
00750 {
00751 ROS_ERROR_STREAM("Consistency: The link "<<childLink->name<<" was already encountered");
00752 return false;
00753 }
00754 }
00755 return true;
00756 }
00757