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
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
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;
00079 #endif
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089
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
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);
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
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;
00403 heights[i]=h;
00404 }
00405
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
00437 unsigned int highleg=0;
00438 for(unsigned int i=1; i<NumLegs; i++)
00439 if(heights[i]>heights[highleg])
00440 highleg=i;
00441
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)
00449 down=pack(0,0,-1);
00450 return calculateGroundPlane(down);
00451 }
00452
00453
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);
00461 float heights[3];
00462 unsigned int legs[3];
00463 std::string names[3];
00464
00465 for(unsigned int i=0; i<3; i++) {
00466 heights[i]=FLT_MAX;
00467 legs[i]=-1U;
00468 }
00469
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;
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
00505
00506
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
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
00606
00607
00608
00609
00610
00611
00612
00613 NEWMAT::Matrix T2=linkToLink(b,j);
00614
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
00618 NEWMAT::ColumnVector p_j=T2*p_b;
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
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
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
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671