Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

IKMantis.cc

Go to the documentation of this file.
00001 #if defined(TGT_IS_MANTIS) && defined(TGT_HAS_HEAD)
00002 
00003 #include "IKMantis.h"
00004 #include "IKGradientSolver.h"
00005 #include "Kinematics.h"
00006 
00007 //const float IKMantis::EPSILON = 1e-3;
00008 const std::string IKMantis::autoRegisterIKMantis = IKSolver::getRegistry().registerType<IKMantis>("IKMantis");
00009 
00010 IKMantis::IKMantis() { //const KinematicJoint* j = kine->getKinematicJoint(CameraFrameOffset);
00011     // qOffset = kine->getKinematicJoint(HeadPanOffset)->qOffset;
00012     // cameraOffset = kine->getKinematicJoint(CameraFrameOffset)->qOffset;
00013     // baseToHead = kine->getKinematicJoint(HeadPanOffset)->getTo().inverse();
00014 }
00015 
00016 bool IKMantis::solve(const Point& pEff, const Rotation& oriEff, KinematicJoint& j, const Position& pTgt, float posPri, const Orientation& oriTgt, float oriPri) const {
00017   
00018   bool solved;
00019   if(j.outputOffset == CameraFrameOffset) 
00020     solved = solveHead(j,pTgt);
00021   else if(j.outputOffset >= FootFrameOffset+LMdLegOrder && j.outputOffset <= FootFrameOffset+RBkLegOrder)
00022     solved = solvePosLeg(j,pTgt);
00023   else
00024     solved = solveFrontLeg(j,pTgt); 
00025   return solved;
00026 }
00027 
00028 bool IKMantis::solveHead(KinematicJoint& j, const Position& pTgt) const {       
00029   // translate target point from BaseFrame to the frame of the Pan Servo
00030   const Point& pTgtPoint = dynamic_cast<const Point&>(pTgt);
00031   KinematicJoint *roll = j.getParent();
00032   KinematicJoint *tilt = roll->getParent();
00033   KinematicJoint *pan = tilt->getParent();
00034   roll->tryQ(0.f);
00035   tilt->tryQ(0.f);
00036   //std::cout << "qPan is :" << qPan*180/M_PI << "  targ1 = " << targ1 << std::endl; 
00037   //std::cout << kine->linkToBase(HeadOffset+PanOffset) << std::endl;
00038   
00039   //correcting the camera angle
00040   //fmat::Column<3> start = pan->getWorldPosition();
00041   float radius =  kine->linkToLink(CameraFrameOffset, HeadOffset+PanOffset)(1,3);
00042   std::cout << " radius = " << radius << std::endl;
00043   fmat::Column<3> targ1 = pan->getFullInvT() * pTgtPoint;
00044   targ1[2] = 0; // We're working in the x-y plane; want norm to ignore z distance
00045   float d = targ1.norm();
00046   std::cout << " distance d = " << d << std::endl;
00047   float R = radius/d;
00048   float X = targ1[0] / d;
00049   float Y = targ1[1] / d;
00050   float rsq = sqrt(1 - R*R);
00051   float a = R*X - Y*rsq;
00052   float b = R*Y + X*rsq;
00053   float theta = atan2(-a,b);
00054   float qPan = pan->getQ() + theta; 
00055   pan->tryQ(qPan);
00056   //std::cout << "Camera to pan: " << std::endl << kine->linkToLink(CameraFrameOffset, HeadOffset+PanOffset) << std::endl;
00057 
00058   // tilt
00059   radius =  kine->linkToLink(CameraFrameOffset, HeadOffset+TiltOffset)(1,3);
00060   fmat::Column<3> targ2 = tilt->getFullInvT() * pTgtPoint;
00061   targ2[2] = 0; // We're working in the x-y plane; want norm to ignore z distance
00062   d = targ2.norm();
00063   //std::cout << " distance d = " << d << std::endl;
00064   R = radius/d;
00065   X = targ2[0] / d;
00066   Y = targ2[1] / d;
00067   rsq = sqrt(1 - R*R);
00068   a = R*X - Y*rsq;
00069   b = R*Y + X*rsq;
00070   theta = atan2(-a,b);
00071   float qTilt = tilt->getQ() + theta; 
00072   tilt->tryQ(qTilt);
00073 
00074   //fmat::Column<3> targ2 = tilt->getFullInvT() * pTgtPoint;
00075   //float qTilt = std::atan2(targ2[1],targ2[0]) + tilt->getQ();
00076   //std::cout << "qTilt is :" << qTilt*180/M_PI << std::endl;
00077   //std::cout<< kine->linkToBase(HeadOffset+TiltOffset) << "  targ2 = " << targ2 << std::endl;
00078   std::cout << "Pan to tilt:" << kine->linkToLink(HeadOffset+PanOffset, HeadOffset+TiltOffset) << std::endl;
00079   return true;
00080 }
00081 
00082 bool IKMantis::solvePosLeg(KinematicJoint& j, const Position& pTgt) const { 
00083   const Point& pTgtPoint = dynamic_cast<const Point&>(pTgt);
00084   KinematicJoint *knee = j.getParent()->getParent();
00085   KinematicJoint *elevator = knee->getParent();
00086   KinematicJoint *rotor = elevator->getParent();
00087   KinematicJoint *sweep = rotor->getParent();
00088   //std::cout << "sweep at " << sweep->getWorldPosition() << std::endl;
00089   //std::cout << "rotor at " << rotor->getWorldPosition() << std::endl;
00090   //std::cout << "elev  at " << elevator->getWorldPosition() << std::endl;
00091   //std::cout << "knee  at " << knee->getWorldPosition() << std::endl;
00092   rotor->tryQ(0.f);
00093     
00094   bool solved; 
00095   // sweep
00096   fmat::Column<3> targ1 = sweep->getFullInvT() * pTgtPoint;
00097   //std::cout << " sweepInv : " << sweep->getFullInvT() << std::endl; // transformation matrix from base to link(sweep) frame 
00098   float qsweep = atan2(targ1[1],targ1[0]) + sweep->getQ(); 
00099   sweep->tryQ(qsweep);
00100   //std::cout << "qsweep is :" << qsweep*180/M_PI << std::endl /*<< "  targ1 = " << targ1 << std::endl*/;
00101   
00102   // 2-link IK
00103   fmat::Column<3> targ2 = elevator->getFullInvT() * pTgtPoint; // target point in the frame of elevator
00104   //unsigned int legLink = LegOffset + (j.outputOffset - FootFrameOffset)*JointsPerPosLeg + FrontLegExtra;
00105   
00106   fmat::Column<3> elvtrPos = elevator->getWorldPosition();
00107   fmat::Column<3> len1 = knee->getFullInvT() * elvtrPos;
00108   fmat::Column<3> footframe = j.getWorldPosition();
00109   fmat::Column<3> len2 = knee->getFullInvT() * footframe;
00110 
00111   //fmat::Column<3> len1 = kine->linkToLink(legLink+PosElevatorOffset, legLink+PosKneeOffset).translation();
00112   //fmat::Column<3> len2 = kine->linkToLink(j.outputOffset, legLink+PosKneeOffset).translation();
00113   float L1 = hypotf(len1[0],len1[1]);
00114   float L2 = hypotf(len2[0],len2[1]);
00115   float qknee;
00116   float qelevtr;
00117   //std::cout << "Translation vector for length1 = " << len1 << std::endl << "Length1 normalization vector = " << L1 << std::endl;
00118   //std::cout << "Translation vector for length2 = " << len2 << std::endl << "Length2 normalization vector = " << L2 << std::endl;
00119   //std::cout << " targ2 = " << targ2 << std::endl;
00120   float t2angle = atan2(targ2[1],targ2[0]);
00121   float k_cos = (targ2[0]*targ2[0] + targ2[1]*targ2[1] - L1*L1 - L2*L2) / (2*L1*L2); // using law of cosines
00122   float k_sin = std::sqrt(1 - k_cos*k_cos) * (t2angle > 0.0 ? 1 : -1);
00123   float k1 = L1 + k_cos*L2;
00124   float k2 = k_sin*L2;
00125 
00126   // The tibia is bent, so we must calculate a correction angle alpha.
00127   float alpha = atan2(len2[1],len2[0]);
00128   //std::cout << " alpha = " << alpha << std::endl;
00129   
00130   if (L1 + L2 <= hypotf(targ2[0],targ2[1])) {
00131   // point too far away
00132     qknee = -alpha;
00133     qelevtr = t2angle + elevator->getQ();
00134     solved = false;
00135     //std::cout << " Point too far away " << std::endl;
00136   } else {
00137     qknee = atan2(k_sin,k_cos) - alpha /*+ knee->getQ()*/; 
00138     qelevtr = t2angle - atan2(k2,k1) + elevator->getQ(); 
00139     //std::cout << "qelevtr atan2t=" << atan2(targ2[1],targ2[0]) << "  atan2k=" << atan2(k2,k1) << "  getQ=" << elevator->getQ() << std::endl;
00140     solved = true;
00141   }
00142   //std::cout << "K1 = " << k1 << std::endl << "K2 = " << k2 << std::endl;  
00143   //std::cout << "cos = " << k_cos << std::endl << "sin = " << k_sin << std::endl;  
00144   //std::cout << "x = " << targ2[0] << std::endl << "y = " << targ2[1] << std::endl;
00145   //std::cout << "Elevator angle = " << qelevtr*180/M_PI << std::endl << "Knee angle = " << qknee*180/M_PI << std::endl << std::endl;
00146   elevator->tryQ(qelevtr);
00147   knee->tryQ(qknee);
00148 
00149   return solved;  
00150 }
00151 
00152 bool IKMantis::solveFrontLeg(KinematicJoint& j, const Position& pTgt) const {
00153   const Point& pTgtPoint = dynamic_cast<const Point&>(pTgt);
00154   bool solved;
00155   KinematicJoint *wrist = j.getParent()->getParent();
00156   KinematicJoint *twist2 = wrist->getParent();
00157   KinematicJoint *elbow = twist2->getParent();
00158   KinematicJoint *twist1 = elbow->getParent();
00159   KinematicJoint *elevator = twist1->getParent();
00160   KinematicJoint *sweep = elevator->getParent();
00161   //std::cout << "Initial joint values: " << sweep->getQ() << " " << elevator->getQ() << " " << elbow->getQ() << " " << twist2->getQ() << " " << wrist->getQ() << std::endl;
00162   twist1->tryQ(0);
00163    
00164   //unsigned int legLink = LegOffset + (j.outputOffset - FootFrameOffset)*JointsPerFrLeg;
00165   //fmat::Column<3> footToWrist = kine->linkToLink(j.outputOffset, legLink+FrWristOffset).translation();
00166     
00167       fmat::Column<3> footframe = j.getWorldPosition();
00168       fmat::Column<3> footToWrist = wrist->getFullInvT() * footframe;
00169       float len_tibia = hypotf(footToWrist[0],footToWrist[1]);
00170       //std::cout << "FootToWrist translation vector = " << footToWrist << std::endl << "Length of the tibia = " << len_tibia << std::endl;
00171       const Point pTgtWrist = pTgtPoint;
00172       pTgtWrist.z = pTgtPoint.z + len_tibia;
00173       //std::cout << "Target position of the wrist servo = " << pTgtWrist << std::endl;
00174     
00175       // sweep
00176       fmat::Column<3> targ1 = sweep->getFullInvT() * pTgtWrist; // target wrist position in the frame of sweep servo
00177       //std::cout << "sweepInv : " << sweep->getFullInvT() << std::endl; // transformation matrix from base to link(sweep) frame
00178       //std::cout << "baseToLink " << kine->baseToLink(legLink+FrSweepOffset) << std::endl;
00179       float qsweep = atan2(targ1[1],targ1[0]) + sweep->getQ();
00180       sweep->tryQ(qsweep);
00181       //std::cout << "qsweep is :" << qsweep*180/M_PI << std::endl << "targ1 = " << targ1 << std::endl;
00182 
00183       // 2-link IK
00184       fmat::Column<3> targ2 = elevator->getFullInvT() * pTgtWrist; // target wrist position in the frame of elevator
00185 
00186       fmat::Column<3> elvtrPos = elevator->getWorldPosition();
00187       fmat::Column<3> len1 = elbow->getFullInvT() * elvtrPos;
00188       fmat::Column<3> wristPos = wrist->getWorldPosition();
00189       fmat::Column<3> len2 = elbow->getFullInvT() * wristPos;
00190 
00191       //fmat::Column<3> len1 = kine->linkToLink(legLink+FrElevatorOffset, legLink+FrElbowOffset).translation();
00192       //fmat::Column<3> len2 = kine->linkToLink(legLink+FrWristOffset, legLink+FrElbowOffset).translation();
00193       float L1 = hypotf(len1[0],len1[1]);
00194       float L2 = hypotf(len2[0],len2[1]);
00195       float qelevtr;
00196       float qelbow;
00197       //std::cout << "Translation vector for length1 = " << len1 << std::endl << "Length1 normalization vector = " << L1 << std::endl;
00198       //std::cout << "Translation vector for length2 = " << len2 << std::endl << "Length2 normalization vector = " << L2 << std::endl;
00199       //std::cout << "targ2 = " << targ2 << std::endl;
00200       float k_cos = (targ2[0]*targ2[0] + targ2[1]*targ2[1] - L1*L1 - L2*L2) / (2*L1*L2); // using law of cosines
00201       float k_sin = std::sqrt(1 - k_cos*k_cos);
00202         if (j.outputOffset == FootFrameOffset+LFrLegOrder) k_sin = -k_sin;  //! hack..fix it later
00203       float k1 = L1 + k_cos*L2;
00204       float k2 = k_sin*L2;
00205     
00206       if (L1 + L2 <= hypotf(targ2[0],targ2[1])) {
00207         // point too far away
00208           qelbow = 0;
00209           qelevtr = atan2(targ2[1],targ2[0]) + elevator->getQ();
00210           std::cout << "Point too far away " << std::endl;
00211           solved = false; 
00212       } else {
00213           qelbow = atan2(k_sin,k_cos) /*+ elbow->getQ()*/;
00214           qelevtr = atan2(targ2[1],targ2[0]) - atan2(k2,k1) + elevator->getQ();
00215           solved = true;
00216       }
00217       //std::cout << "K1 = " << k1 << std::endl << "K2 = " << k2 << std::endl;
00218       //std::cout << "cos = " << k_cos << std::endl << "sin = " << k_sin << std::endl;
00219       //std::cout << "x = " << targ2[0] << std::endl << "y = " << targ2[1] << std::endl;
00220       //std::cout << "Elevator angle = " << qelevtr*180/M_PI << std::endl << "Elbow angle = " << qelbow*180/M_PI << std::endl;
00221       elevator->tryQ(qelevtr);
00222       elbow->tryQ(qelbow);
00223   
00224     // Put leg vertically on the ground
00225 
00226 /*    //fmat::Column<3> vec = fmat::pack(0, 1, 0); 
00227       //fmat::Column<3>  tvec = twist2->getFullInvT() * vec;
00228       //std::cout << "vec in twist2 frame = " << tvec << std::endl;
00229       fmat::Matrix<3,3> rot =  kine->linkToBase(legLink+FrTwist2Offset).rotation();
00230       std::cout << "Orientation of twist2 in base coordinates = " << rot << std::endl;
00231       fmat::Quaternion q = twist2->getWorldQuaternion();
00232       std::cout << "q = " << q << std::endl;
00233       float qtwist2 = -atan2(2*(q.getW()*q.getZ() + q.getX()*q.getY()), 1 - 2*(q.getY()*q.getY() + q.getZ()*q.getZ())) - M_PI/2;
00234       std::cout << " qtwist2 = " << qtwist2 << std::endl;
00235       twist2->tryQ(0);
00236 */  
00237       fmat::Column<3> targ3 = twist2->getFullInvT() * pTgtPoint; //target point in the frame of twrist2 servo
00238         float qtwist2;
00239       //std::cout << "target point in twist2 frame = " << targ3 << std::endl;
00240         if (j.outputOffset == FootFrameOffset+LFrLegOrder) qtwist2 = -atan2(-targ3[0], -targ3[1]) + twist2->getQ();  //! hack..fix it later
00241       else qtwist2 = -atan2(targ3[0], targ3[1]) + twist2->getQ();
00242         //std::cout << "atan2 of targ3 = " << atan2(targ3[0],targ3[1]) << std::endl;
00243       //std::cout << "Twist2 angle (in degrees) = " << qtwist2*180/M_PI << std::endl; 
00244       twist2->tryQ(qtwist2);
00245 
00246      
00247       // The tibia is bent, so we must calculate a correction angle beta.
00248       float beta = atan2(footToWrist[1],footToWrist[0]); 
00249       //std::cout << "beta  = " << beta*180/M_PI << std::endl;
00250       fmat::Column<3> targ4 = wrist->getFullInvT() * pTgtPoint; //target point in the frame of wrist servo
00251       //std::cout << "target point in wrist frame = " << targ4 << std::endl;
00252       float qwrist = atan2(targ4[1],targ4[0]) - beta + wrist->getQ();
00253       //std::cout << "atan2 of targ4 = " << atan2(targ4[1],targ4[0]) << std::endl;
00254       wrist->tryQ(qwrist);
00255       //std::cout << "Wrist angle (in degrees) = " << qwrist*180/M_PI << std::endl; 
00256 
00257       //fmat::Column<3> legT = j.getWorldPosition();
00258       //std::cout << " The position of toe is :  " << std::endl << legT << std::endl;
00259 
00260       return solved;
00261 }
00262 
00263 IKSolver::StepResult_t IKMantis::step(const Point& pEff, const Rotation& oriEff, KinematicJoint& j, const Position& pTgt, float pDist, float posPri, const Orientation& oriTgt, float oriDist, float oriPri) const {
00264     // find the closest target point
00265   fmat::Transform Tj = j.getFullT();
00266   fmat::Column<3> pEffBase(Tj*pEff);
00267   fmat::Quaternion qj = j.getWorldQuaternion(); //cout << "WorldQ: " << qj;
00268   Rotation oEffBase = qj*oriEff;
00269   Point de;
00270   pTgt.computeErrorGradient(pEffBase,oEffBase,de);
00271 
00272   StepResult_t res=SUCCESS;
00273   if(de.norm()>pDist) {
00274     de*=pDist/de.norm();
00275     res = PROGRESS;
00276   }
00277   Point pTgtP = pEffBase+de;
00278   if(solve(pEff,oriEff,j,pTgtP,posPri,oriTgt,oriPri))
00279     return res;
00280   return LIMITS;
00281 }
00282 
00283 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:42 2016 by Doxygen 1.6.3