Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

Kinematics.cc

Go to the documentation of this file.
00001 #include "Kinematics.h"
00002 #include "Shared/Config.h"
00003 #include "roboop/robot.h"
00004 #include "roboop/config.h"
00005 #include "Shared/WorldState.h"
00006 #include <sstream>
00007 #include <float.h>
00008 #include <iostream>
00009 
00010 using namespace std;
00011 
00012 Kinematics * kine = NULL;
00013 ROBOOP::Config * Kinematics::roconfig = NULL;
00014 Kinematics::InterestPointMap * Kinematics::ips = NULL;
00015 std::vector< std::vector<unsigned int> > Kinematics::chainMaps;
00016 Kinematics::JointMap Kinematics::jointMaps[NumReferenceFrames];
00017 bool Kinematics::staticsInited=false;
00018 #ifndef THREADSAFE_KINEMATICS
00019 std::vector<ROBOOP::Robot*> Kinematics::chains;
00020 #endif
00021 
00022 void
00023 Kinematics::init() {
00024 #ifdef THREADSAFE_KINEMATICS
00025   unsigned int nchains=::config->motion.kinematic_chains.size();
00026   chains.resize(nchains);
00027   for(unsigned int i=0; i<nchains; i++) {
00028     chains[i]=newChain(i);
00029     //cout << "Created " << chains[i] << " for " << this << endl;
00030   }
00031 #endif
00032   checkStatics();
00033 }
00034 
00035 void Kinematics::initStatics() {
00036   if(!staticsInited) {
00037     unsigned int nchains=::config->motion.kinematic_chains.size();
00038     if(nchains==0) {
00039       serr->printf("ERROR Kinematics::init(): no kinematic chains were selected\n");
00040       return;
00041     }
00042     jointMaps[BaseFrameOffset]=JointMap(0,0);
00043     
00044 #ifndef THREADSAFE_KINEMATICS
00045     chains.resize(nchains);
00046     for(unsigned int i=0; i<nchains; i++) {
00047       chains[i]=newChain(i);
00048       //cout << "Created " << chains[i] << " for " << this << endl;
00049     }
00050 #endif
00051     
00052     if(ips==NULL) {
00053       int numIP=0;
00054       roconfig->select_int("InterestPoints","Length",numIP);
00055       ips=new InterestPointMap(numIP);
00056       pair<string,InterestPoint> ip;
00057       string chain;
00058       for(int i=1; i<=numIP; i++) {
00059         char section[100];
00060         snprintf(section,100,"InterestPoint%d",i);
00061         roconfig->select_float(section,"x",ip.second.x);
00062         roconfig->select_float(section,"y",ip.second.y);
00063         roconfig->select_float(section,"z",ip.second.z);
00064         roconfig->select_string(section,"chain",chain);
00065         roconfig->select_int(section,"link",ip.second.link);
00066         roconfig->select_string(section,"name",ip.first);
00067         for(ip.second.chain=0; ip.second.chain<(::config->motion.kinematic_chains.size()); ip.second.chain++)
00068           if(::config->motion.kinematic_chains[ip.second.chain]==chain)
00069             break;
00070         if(ip.second.chain==::config->motion.kinematic_chains.size())
00071           serr->printf("WARNING: Chain %s is not recognized for interest point %d\n",chain.c_str(),i);
00072         else
00073           ips->insert(ip);
00074       }
00075     }
00076     staticsInited=true;
00077 #ifndef THREADSAFE_KINEMATICS
00078     delete roconfig; // static chains are initialized, don't need to keep this around...
00079 #endif
00080   }
00081   /*cout << "Joint Maps" << endl;
00082   for(unsigned int i=0; i<NumOutputs; i++)
00083     cout << outputNames[i] << ": " << jointMaps[i].chain << ' ' << jointMaps[i].link << endl;
00084   for(unsigned int i=NumOutputs; i<NumReferenceFrames; i++)
00085     cout << i << ": " << jointMaps[i].chain << ' ' << jointMaps[i].link << endl;
00086   cout << "Chain Maps" << endl;
00087   for(unsigned int i=0; i<chains.size(); i++)
00088     for(unsigned int j=1; j<chainMaps[i].size(); j++)
00089     cout << "chainMaps["<<i<<"]["<<j<<"] == " << chainMaps[i][j] << endl;*/
00090 }
00091 
00092 ROBOOP::Robot* Kinematics::newChain(unsigned int chainIdx) {
00093   if(roconfig==NULL) {
00094     unsigned int nchains=::config->motion.kinematic_chains.size();
00095     chainMaps.resize(nchains);
00096     roconfig=new ROBOOP::Config(::config->motion.makePath(::config->motion.kinematics),true);
00097     for(unsigned int i=0; i<nchains; i++) {
00098       string section=::config->motion.kinematic_chains[i];
00099       int dof=0;
00100       if(roconfig->select_int(section,"dof",dof)!=0) {
00101         serr->printf("ERROR Kinematics::init(): unable to find 'dof' in chain %d (%s)\n",i,section.c_str());
00102         chainMaps[i].resize(0);
00103         continue;
00104       }
00105       chainMaps[i].resize(dof+1);
00106       for(int l=0; l<=dof; l++)
00107         chainMaps[i][l]=-1U;
00108       for(int l=1; l<=dof; l++) {
00109         ostringstream ostr;
00110         ostr << section << "_LINK" << l;
00111         string link = ostr.str();
00112         if(roconfig->parameter_exists(link,"tekkotsu_output")) {
00113           int tkout=-1U;
00114           roconfig->select_int(link,"tekkotsu_output",tkout);
00115           if((unsigned int)tkout>=NumOutputs) {
00116             serr->printf("WARNING Kinematics::init(): invalid tekkotsu_output %d on chain %d (%s), link %d (%s)\n",tkout,i,section.c_str(),l,link.c_str());
00117           } else {
00118             jointMaps[tkout]=JointMap(i,l);
00119             chainMaps[i][l]=tkout;
00120           }
00121         }
00122         if(roconfig->parameter_exists(link,"tekkotsu_frame")) {
00123           int tkout=-1U;
00124           roconfig->select_int(link,"tekkotsu_frame",tkout);
00125           tkout+=NumOutputs;
00126           if((unsigned int)tkout>=NumReferenceFrames)
00127             serr->printf("WARNING Kinematics::init(): invalid tekkotsu_frame %d on chain %d (%s), link %d (%s)\n",tkout,i,section.c_str(),l,link.c_str());
00128           else {
00129             jointMaps[tkout]=JointMap(i,l);
00130             chainMaps[i][l]=tkout;
00131           }
00132         }
00133       }
00134     }
00135   }
00136   if(chainMaps[chainIdx].size()==0)
00137     return NULL;
00138   return new ROBOOP::Robot(*roconfig,::config->motion.kinematic_chains[chainIdx]);
00139 }
00140 
00141 Kinematics::~Kinematics() {
00142 #ifdef THREADSAFE_KINEMATICS
00143   for(unsigned int i=0; i<chains.size(); i++) {
00144     if(chains[i]==NULL)
00145       cerr << "Warning: Kinematics chains appear to already be deleted! (multiple free?)" << endl;
00146     delete chains[i];
00147     chains[i]=NULL;
00148   }
00149 #endif
00150 }
00151 
00152 NEWMAT::ReturnMatrix
00153 Kinematics::jointToBase(unsigned int j) {
00154 #ifndef THREADSAFE_KINEMATICS
00155   checkStatics();
00156 #endif
00157   unsigned int c=-1U,l=-1U;
00158   if(!lookup(j,c,l)) {
00159     NEWMAT::Matrix A(4,4);
00160     A<<ROBOOP::fourbyfourident;
00161     A.Release(); return A;
00162   }
00163   update(c,l);
00164   return chains[c]->convertFrame(l,0);
00165 }
00166 
00167 NEWMAT::ReturnMatrix
00168 Kinematics::linkToBase(unsigned int j) {
00169 #ifndef THREADSAFE_KINEMATICS
00170   checkStatics();
00171 #endif
00172   unsigned int c=-1U,l=-1U;
00173   if(!lookup(j,c,l)) {
00174     NEWMAT::Matrix A(4,4);
00175     A<<ROBOOP::fourbyfourident;
00176     A.Release(); return A;
00177   }
00178   update(c,l);
00179   return chains[c]->convertLink(l,0);
00180 }
00181 
00182 NEWMAT::ReturnMatrix
00183 Kinematics::baseToJoint(unsigned int j) {
00184 #ifndef THREADSAFE_KINEMATICS
00185   checkStatics();
00186 #endif
00187   unsigned int c=-1U,l=-1U;
00188   if(!lookup(j,c,l)) {
00189     NEWMAT::Matrix A(4,4);
00190     A<<ROBOOP::fourbyfourident;
00191     A.Release(); return A;
00192   }
00193   update(c,l);
00194   return chains[c]->convertFrame(0,l);
00195 }
00196 
00197 NEWMAT::ReturnMatrix
00198 Kinematics::baseToLink(unsigned int j) {
00199 #ifndef THREADSAFE_KINEMATICS
00200   checkStatics();
00201 #endif
00202   unsigned int c=-1U,l=-1U;
00203   if(!lookup(j,c,l)) {
00204     NEWMAT::Matrix A(4,4);
00205     A<<ROBOOP::fourbyfourident;
00206     A.Release(); return A;
00207   }
00208   update(c,l);
00209   return chains[c]->convertLink(0,l);
00210 }
00211 
00212 NEWMAT::ReturnMatrix
00213 Kinematics::jointToJoint(unsigned int ij, unsigned int oj) {
00214 #ifndef THREADSAFE_KINEMATICS
00215   checkStatics();
00216 #endif
00217   unsigned int ci=-1U,li=-1U,co=-1U,lo=-1U;
00218   if(ij==oj || !lookup(ij,ci,li) || !lookup(oj,co,lo)) {
00219     NEWMAT::Matrix A(4,4);
00220     A<<ROBOOP::fourbyfourident;
00221     A.Release(); return A;
00222   }
00223   if(ci==co) {
00224     update(ci,li>lo?li:lo);
00225     return chains[ci]->convertFrame(li,lo);
00226   } else if(li==0) {
00227     update(co,lo);
00228     return chains[co]->convertFrame(0,lo);
00229   } else if(lo==0) {
00230     update(ci,li);
00231     return chains[ci]->convertFrame(li,0);
00232   } else {
00233     update(ci,li);
00234     update(co,lo);
00235     NEWMAT::Matrix ans=chains[co]->convertFrame(0,lo)*chains[ci]->convertFrame(li,0);
00236     ans.Release(); return ans;
00237   }
00238 }
00239 
00240 NEWMAT::ReturnMatrix
00241 Kinematics::jointToLink(unsigned int ij, unsigned int oj) {
00242 #ifndef THREADSAFE_KINEMATICS
00243   checkStatics();
00244 #endif
00245   unsigned int ci=-1U,li=-1U,co=-1U,lo=-1U;
00246   if(!lookup(ij,ci,li) || !lookup(oj,co,lo)) {
00247     NEWMAT::Matrix A(4,4);
00248     A<<ROBOOP::fourbyfourident;
00249     A.Release(); return A;
00250   }
00251   if(ci==co) {
00252     update(ci,li>lo?li:lo);
00253     return chains[ci]->convertFrameToLink(li,lo);
00254   } else if(li==0) {
00255     update(co,lo);
00256     return chains[co]->convertFrameToLink(0,lo);
00257   } else if(lo==0) {
00258     update(ci,li);
00259     return chains[ci]->convertFrameToLink(li,0);
00260   } else {
00261     update(ci,li);
00262     update(co,lo);
00263     NEWMAT::Matrix ans=chains[co]->convertLink(0,lo)*chains[ci]->convertFrame(li,0);
00264     ans.Release(); return ans;
00265   }
00266 }
00267 
00268 NEWMAT::ReturnMatrix
00269 Kinematics::linkToJoint(unsigned int ij, unsigned int oj) {
00270 #ifndef THREADSAFE_KINEMATICS
00271   checkStatics();
00272 #endif
00273   unsigned int ci=-1U,li=-1U,co=-1U,lo=-1U;
00274   if(!lookup(ij,ci,li) || !lookup(oj,co,lo)) {
00275     NEWMAT::Matrix A(4,4);
00276     A<<ROBOOP::fourbyfourident;
00277     A.Release(); return A;
00278   }
00279   if(ci==co) {
00280     update(ci,li>lo?li:lo);
00281     return chains[ci]->convertLinkToFrame(li,lo);
00282   } else if(li==0) {
00283     update(co,lo);
00284     return chains[co]->convertLinkToFrame(0,lo);
00285   } else if(lo==0) {
00286     update(ci,li);
00287     return chains[ci]->convertLinkToFrame(li,0);
00288   } else {
00289     update(ci,li);
00290     update(co,lo);
00291     NEWMAT::Matrix ans=chains[co]->convertFrame(0,lo)*chains[ci]->convertLink(li,0);
00292     ans.Release(); return ans;
00293   }
00294 }
00295 
00296 NEWMAT::ReturnMatrix
00297 Kinematics::linkToLink(unsigned int ij, unsigned int oj) {
00298 #ifndef THREADSAFE_KINEMATICS
00299   checkStatics();
00300 #endif
00301   unsigned int ci=-1U,li=-1U,co=-1U,lo=-1U;
00302   if(ij==oj || !lookup(ij,ci,li) || !lookup(oj,co,lo)) {
00303     NEWMAT::Matrix A(4,4);
00304     A<<ROBOOP::fourbyfourident;
00305     A.Release(); return A;
00306   }
00307   if(ci==co) {
00308     update(ci,li>lo?li:lo);
00309     return chains[ci]->convertLink(li,lo);
00310   } else if(li==0) {
00311     update(co,lo);
00312     return chains[co]->convertLink(0,lo);
00313   } else if(lo==0) {
00314     update(ci,li);
00315     return chains[ci]->convertLink(li,0);
00316   } else {
00317     update(ci,li);
00318     update(co,lo);
00319     NEWMAT::Matrix ans=chains[co]->convertLink(0,lo)*chains[ci]->convertLink(li,0);
00320     ans.Release(); return ans;
00321   }
00322 }
00323 
00324 void
00325 Kinematics::getInterestPoint(const std::string& name, unsigned int& j, NEWMAT::Matrix& ip) {
00326 #ifndef THREADSAFE_KINEMATICS
00327   checkStatics();
00328 #endif
00329   unsigned int c=-1U,l=-1U;
00330   getInterestPoint(name,c,l,ip);
00331   j=chainMaps[c][l];
00332 }
00333 
00334 void
00335 Kinematics::getInterestPoint(const std::string& name, unsigned int& c, unsigned int& l, NEWMAT::Matrix& ip) {
00336 #ifndef THREADSAFE_KINEMATICS
00337   checkStatics();
00338 #endif
00339   InterestPointMap::iterator it=ips->find(name);
00340   ip=NEWMAT::ColumnVector(4);
00341   if(it==ips->end()) {
00342     serr->printf("ERROR: '%s' is not a recognized interest point\n",name.c_str());
00343     ip=0;
00344     c=l=-1U;
00345   }
00346   c=(*it).second.chain;
00347   l=(*it).second.link;
00348   ip=pack((*it).second.x,(*it).second.y,(*it).second.z);
00349   //cout << ci << ' ' << li << ' ' << co << ' ' << lo << endl;
00350 }
00351 
00352 NEWMAT::ReturnMatrix
00353 Kinematics::getJointInterestPoint(unsigned int joint, const std::string& name) {
00354 #ifndef THREADSAFE_KINEMATICS
00355   checkStatics();
00356 #endif
00357   NEWMAT::ColumnVector ans(4);
00358   ans=0;
00359   unsigned int co=-1U,lo=-1U;
00360   if(!lookup(joint,co,lo)) {
00361     ans.Release(); return ans;
00362   }
00363   for(std::string::size_type pos=0,len=0; pos<name.size(); pos+=len+1) {
00364     len=name.find(',',pos);
00365     if(len==string::npos)
00366       len=name.size();
00367     len-=pos;
00368     unsigned int ci=-1U,li=-1U;
00369     NEWMAT::ColumnVector ip;
00370     getInterestPoint(name.substr(pos,len),ci,li,ip);
00371     if(ci==-1U) {
00372       ip.Release(); return ip;
00373     }
00374     if(ci==co) {
00375       update(ci,li>lo?li:lo);
00376       ans+=chains[ci]->convertLinkToFrame(li,lo)*ip;
00377     } else if(li==0) {
00378       update(co,lo);
00379       ans+=chains[co]->convertLinkToFrame(0,lo)*ip;
00380     } else if(lo==0) {
00381       update(ci,li);
00382       ans+=chains[ci]->convertLinkToFrame(li,0)*ip;
00383     } else {
00384       update(ci,li);
00385       update(co,lo);
00386       ans+=chains[co]->convertFrame(0,lo)*chains[ci]->convertLink(li,0)*ip;
00387     }
00388   }
00389   ans/=ans(4); //not strictly necessary, but may save some people headaches
00390   ans.Release(); return ans;
00391 }
00392 
00393 void
00394 Kinematics::calcLegHeights(const NEWMAT::ColumnVector& down, float heights[NumLegs]) {
00395 #ifndef THREADSAFE_KINEMATICS
00396   checkStatics();
00397 #endif
00398   //initialize to the height of the ball of the foot
00399   for(unsigned int i=0; i<NumLegs; i++) {
00400     NEWMAT::ColumnVector ip_b=jointToBase(PawFrameOffset+i).SubMatrix(1,3,4,4);
00401     float h=-ip_b(1)*down(1) - ip_b(2)*down(2) - ip_b(3)*down(3);
00402     h-=BallOfFootRadius; //add the ball's radius
00403     heights[i]=h;
00404   }
00405   //see if any interest points are lower
00406   for(InterestPointMap::const_iterator it=ips->begin(); it!=ips->end(); ++it) {
00407     unsigned int c=(*it).second.chain;
00408     LegOrder_t leg;
00409     if(config->motion.kinematic_chains[c]=="LFr")
00410       leg=LFrLegOrder;
00411     else if(config->motion.kinematic_chains[c]=="RFr")
00412       leg=RFrLegOrder;
00413     else if(config->motion.kinematic_chains[c]=="LBk")
00414       leg=LBkLegOrder;
00415     else if(config->motion.kinematic_chains[c]=="RBk")
00416       leg=RBkLegOrder;
00417     else
00418       continue;
00419     unsigned int l=(*it).second.link;
00420     NEWMAT::Matrix ip=pack((*it).second.x,(*it).second.y,(*it).second.z);
00421     update(c,l);
00422     NEWMAT::ColumnVector ip_b=chains[c]->convertLinkToFrame(l,0)*ip;
00423     float h=-ip_b(1)*down(1) - ip_b(2)*down(2) - ip_b(3)*down(3);
00424     if(h<heights[leg])
00425       heights[leg]=h;
00426   }
00427 }
00428 
00429 LegOrder_t
00430 Kinematics::findUnusedLeg(const NEWMAT::ColumnVector& down) {
00431 #ifndef THREADSAFE_KINEMATICS
00432   checkStatics();
00433 #endif
00434   float heights[NumLegs];
00435   calcLegHeights(down,heights);
00436   //Find the highest foot
00437   unsigned int highleg=0;
00438   for(unsigned int i=1; i<NumLegs; i++)
00439     if(heights[i]>heights[highleg])
00440       highleg=i;
00441   //cout << "High: " << highleg << endl;
00442   return static_cast<LegOrder_t>(highleg);
00443 }
00444 
00445 NEWMAT::ReturnMatrix
00446 Kinematics::calculateGroundPlane() {
00447   NEWMAT::ColumnVector down=pack(state->sensors[BAccelOffset],-state->sensors[LAccelOffset],state->sensors[DAccelOffset]);
00448   if(down.SumSquare()<1.01) //1 because homogenous coord is 1
00449     down=pack(0,0,-1); //default to a down vector if sensors don't give a significant indication of gravity
00450   return calculateGroundPlane(down);
00451 }
00452 
00453 // TODO comment out name tracking (and this following #include) once we're sure it's working
00454 #include "PostureEngine.h"
00455 NEWMAT::ReturnMatrix
00456 Kinematics::calculateGroundPlane(const NEWMAT::ColumnVector& down) {
00457 #ifndef THREADSAFE_KINEMATICS
00458   checkStatics();
00459 #endif
00460   NEWMAT::Matrix lowip(3,3); //3 points define a plane
00461   float heights[3];
00462   unsigned int legs[3];
00463   std::string names[3];
00464   //initialize to max float
00465   for(unsigned int i=0; i<3; i++) {
00466     heights[i]=FLT_MAX;
00467     legs[i]=-1U;
00468   }
00469   //Check the balls of the foot
00470   for(unsigned int i=0; i<NumLegs; i++) {
00471     NEWMAT::ColumnVector ip_b=jointToBase(PawFrameOffset+i).SubMatrix(1,3,4,4);
00472     float h=-ip_b(1)*down(1) - ip_b(2)*down(2) - ip_b(3)*down(3);
00473     h-=BallOfFootRadius; //add the ball's radius
00474     if(h<heights[0]) {
00475       if(h<heights[1]) {
00476         heights[0]=heights[1];
00477         lowip.SubMatrix(1,3,1,1)=lowip.SubMatrix(1,3,2,2);
00478         legs[0]=legs[1];
00479         names[0]=names[1];
00480         if(h<heights[2]) {
00481           heights[1]=heights[2];
00482           lowip.SubMatrix(1,3,2,2)=lowip.SubMatrix(1,3,3,3);
00483           legs[1]=legs[2];
00484           names[1]=names[2];
00485           
00486           heights[2]=h;
00487           lowip.SubMatrix(1,3,3,3)=ip_b;
00488           legs[2]=i;
00489           names[2]="paw"; names[2]+=(char)('0'+i);
00490         } else {
00491           heights[1]=h;
00492           lowip.SubMatrix(1,3,2,2)=ip_b;
00493           legs[1]=i;
00494           names[1]="paw"; names[1]+=(char)('0'+i);
00495         }
00496       } else {
00497         heights[0]=h;
00498         lowip.SubMatrix(1,3,1,1)=ip_b;
00499         legs[0]=i;
00500         names[0]="paw"; names[0]+=(char)('0'+i);
00501       }
00502     }
00503   }
00504   //cout << "Ground plane initial: " << names[0] <<" ("<<heights[0]<<") " << names[1] << " ("<<heights[1]<<") " << names[2] << " ("<<heights[2]<<")"<< endl;
00505   
00506   //now check interest points
00507   for(InterestPointMap::const_iterator it=ips->begin(); it!=ips->end(); ++it) {
00508     if((*it).first.substr(0,3)=="Toe")
00509       continue;
00510     unsigned int c=(*it).second.chain;
00511     unsigned int l=(*it).second.link;
00512     NEWMAT::Matrix ip=pack((*it).second.x,(*it).second.y,(*it).second.z);
00513     update(c,l);
00514     NEWMAT::ColumnVector ip_b=chains[c]->convertLinkToFrame(l,0)*ip;
00515     float h=-ip_b(1)*down(1) - ip_b(2)*down(2) - ip_b(3)*down(3);
00516     if(h<heights[0]) {
00517       unsigned int leg;
00518       if(config->motion.kinematic_chains[c]=="LFr")
00519         leg=LFrLegOrder;
00520       else if(config->motion.kinematic_chains[c]=="RFr")
00521         leg=RFrLegOrder;
00522       else if(config->motion.kinematic_chains[c]=="LBk")
00523         leg=LBkLegOrder;
00524       else if(config->motion.kinematic_chains[c]=="RBk")
00525         leg=RBkLegOrder;
00526       else
00527         leg=-1U;
00528       
00529       if(h<heights[1]) {
00530         if(h<heights[2]) {
00531           if(leg==-1U || legs[1]!=leg && legs[2]!=leg) {
00532             heights[0]=heights[1];
00533             lowip.SubMatrix(1,3,1,1)=lowip.SubMatrix(1,3,2,2);
00534             legs[0]=legs[1];
00535             names[0]=names[1];
00536           }
00537           if(leg==-1U || legs[2]!=leg) {
00538             heights[1]=heights[2];
00539             lowip.SubMatrix(1,3,2,2)=lowip.SubMatrix(1,3,3,3);
00540             if(legs[2]!=leg)
00541               legs[1]=legs[2];
00542             names[1]=names[2];
00543           }
00544           
00545           heights[2]=h;
00546           lowip.SubMatrix(1,3,3,3)=ip_b.SubMatrix(1,3,1,1);
00547           legs[2]=leg;
00548           names[2]=(*it).first;
00549         } else {
00550           if(leg!=-1U && legs[2]==leg)
00551             continue;
00552           if(leg==-1U || legs[1]!=leg) {
00553             heights[0]=heights[1];
00554             lowip.SubMatrix(1,3,1,1)=lowip.SubMatrix(1,3,2,2);
00555             legs[0]=legs[1];
00556             names[0]=names[1];
00557           }
00558           heights[1]=h;
00559           lowip.SubMatrix(1,3,2,2)=ip_b.SubMatrix(1,3,1,1);
00560           legs[1]=leg;
00561           names[1]=(*it).first;
00562         }
00563       } else {
00564         if(leg!=-1U && (legs[1]==leg || legs[2]==leg))
00565           continue;
00566         heights[0]=h;
00567         lowip.SubMatrix(1,3,1,1)=ip_b.SubMatrix(1,3,1,1);
00568         legs[0]=leg;
00569         names[0]=(*it).first;
00570       }
00571     }
00572   }
00573   
00574   //Fit a plane to the remaining 3 feet
00575   NEWMAT::ColumnVector ones(3); ones=1;
00576   NEWMAT::ColumnVector p(4);
00577   try {
00578     p.SubMatrix(1,3,1,1) = lowip.t().i()*ones;
00579   } catch(...) {
00580     std::cout << "Exception during ground plane processing, saving current posture..." << std::flush;
00581     if(PostureEngine * tpose=dynamic_cast<PostureEngine*>(this)) {
00582       tpose->setSaveFormat(true,state);
00583       tpose->saveFile("/error.pos");
00584     } else {
00585       PostureEngine pose;
00586       pose.takeSnapshot();
00587       pose.setWeights(1);
00588       pose.setSaveFormat(true,state);
00589       pose.saveFile("/error.pos");
00590     }
00591     std::cout << "Wrote current sensor info \"error.pos\" on memstick" << std::endl;
00592     cout << "Ground plane was using " << names[0] <<" ("<<heights[0]<<") " << names[1] << " ("<<heights[1]<<") " << names[2] << " ("<<heights[2]<<")"<< endl;
00593     cout << lowip;
00594     throw;
00595   }
00596   p(4)=1;
00597   p.Release(); return p;
00598 }
00599 
00600 NEWMAT::ReturnMatrix
00601 Kinematics::projectToPlane(unsigned int j, const NEWMAT::ColumnVector& r_j,
00602                            unsigned int b, const NEWMAT::ColumnVector& p_b,
00603                            unsigned int f)
00604 {
00605   /*! Mathematical implementation:
00606    *  
00607    *  Need to convert @a p_b to @a p_j
00608    *  
00609    *  Once we have the transformation Tb_j from b to j, we need:\n
00610    *    T2=inv(Tb_j)'; T2(3,1:end-1)=-T2(3,1:end-1);\n
00611    *  but since we know a few things about the structure of T,
00612    *  we don't have to explicitly calculate that inverse. */
00613   NEWMAT::Matrix T2=linkToLink(b,j);
00614   //cout << "Transform b->j:\n"<<T2;
00615   T2.SubMatrix(4,4,1,3)=T2.SubMatrix(1,3,4,4).t()*T2.SubMatrix(1,3,1,3);
00616   T2.SubMatrix(1,3,4,4)=0;
00617   //cout << "Transform plane b->j:\n"<<T2;
00618   NEWMAT::ColumnVector p_j=T2*p_b;
00619   //cout << "p_j:\n"<<p_j.t();
00620 
00621   
00622   /*! After we obtain @a p_j, we can find the point of intersection of
00623    *  @a r_j and @a p_j using:
00624    *  @f[ \frac{p_d}{p_{xyz} \cdot r}r @f]
00625    *  Where @f$p_{xyz}@f$ is the first three elemnts of @a p_j, and
00626    *  @f$p_d@f$ is the fourth (hopefully last) element of p_j.
00627    *
00628    *  Of course, if @f$p_{xyz} \cdot r@f$ is 0, then r and p are parallel
00629    *  (since @a p_j is the normal of the plane, so a line perpendicular to
00630    *  the normal is parallel to the plane), so we set the resulting
00631    *  homogeneous coordinates accordingly to represent an interesection at
00632    *  infinity. */
00633 
00634   float denom=0;
00635   for(unsigned int i=1; i<=3; i++)
00636     denom+=r_j(i)*p_j(i);
00637   NEWMAT::ColumnVector intersect=r_j;
00638   if(denom==0)
00639     intersect(4)=0;
00640   else {
00641     float s=p_j(4)/denom;
00642     for(unsigned int i=1; i<=3; i++)
00643       intersect(i)*=s;
00644     intersect(4)=1;
00645   }
00646   //cout << "Intersect_j:\n"<<intersect.t();
00647   NEWMAT::Matrix ans=linkToLink(j,f)*intersect;
00648   ans.Release(); return ans;
00649 }
00650 
00651 void
00652 Kinematics::update(unsigned int c, unsigned int l) {
00653   for(unsigned int j=1; j<=l; j++) {
00654     unsigned int tkout=chainMaps[c][j];
00655     if(tkout<NumOutputs)
00656       chains[c]->set_q(state->outputs[tkout],j);
00657   }
00658 }
00659 
00660 
00661 /*! @file
00662  * @brief 
00663  * @author ejt (Creator)
00664  *
00665  * $Author: ejt $
00666  * $Name: tekkotsu-3_0 $
00667  * $Revision: 1.35 $
00668  * $State: Exp $
00669  * $Date: 2006/09/09 04:32:53 $
00670  */
00671 

Tekkotsu v3.0
Generated Wed Oct 4 00:03:43 2006 by Doxygen 1.4.7