Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

PostureEngine.cc

Go to the documentation of this file.
00001 #include "PostureEngine.h"
00002 #include "Shared/WorldState.h"
00003 #include "Motion/roboop/robot.h"
00004 #include "Shared/Config.h"
00005 #include <stdio.h>
00006 #include <iostream>
00007 
00008 PostureEngine::~PostureEngine() {}
00009 
00010 void PostureEngine::takeSnapshot() {
00011   takeSnapshot(*WorldState::getCurrent());
00012 }
00013 
00014 void PostureEngine::takeSnapshot(const WorldState& st) {
00015   for(unsigned int i=0; i<NumOutputs; i++)
00016     cmds[i].value=st.outputs[i];
00017 }
00018 
00019 void PostureEngine::setWeights(float w, unsigned int lowjoint, unsigned int highjoint) {
00020   for(unsigned int i=lowjoint; i<highjoint; i++)
00021     cmds[i].weight=w;
00022 }
00023 
00024 void PostureEngine::clear() {
00025   for(unsigned int i=0; i<NumOutputs; i++)
00026     cmds[i].unset();
00027 }
00028 
00029 PostureEngine& PostureEngine::setOverlay(const PostureEngine& pe) {
00030   for(unsigned int i=0; i<NumOutputs; i++)
00031     if(pe.cmds[i].weight>0)
00032       cmds[i]=pe.cmds[i];
00033   return *this;
00034 }
00035 PostureEngine PostureEngine::createOverlay(const PostureEngine& pe) const {
00036   PostureEngine tmp(*this);
00037   return tmp.setOverlay(pe);
00038 }
00039 PostureEngine& PostureEngine::setUnderlay(const PostureEngine& pe) {
00040   for(unsigned int i=0; i<NumOutputs; i++)
00041     if(cmds[i].weight<=0)
00042       cmds[i]=pe.cmds[i];
00043   return *this;
00044 }
00045 PostureEngine PostureEngine::createUnderlay(const PostureEngine& pe) const {
00046   PostureEngine tmp(*this);
00047   return tmp.setUnderlay(pe);
00048 }
00049 /*! joints being averaged with unused joints have their weights averaged, but not their values (so an output can crossfade properly)\n
00050  *  @param pe the other PostureEngine
00051  *  @param w amount to weight towards @a pe
00052  *  - if @a w < .001, nothing is done
00053  *  - if @a w > .999, a straight copy of @a pe occurs (sets joints to unused properly at end of fade)
00054  *  - .001 and .999 is used instead of 0 and 1 to allow for slight addition errors in a loop (if
00055  *    using repeated additions of a delta value instead of repeated divisions)
00056  *  @return @c *this, stores results into this */
00057 PostureEngine& PostureEngine::setAverage(const PostureEngine& pe, float w) {
00058   if(w<0.001)
00059     return *this;
00060   if(w>0.999)
00061     return (*this=pe);
00062   float wp=1-w;
00063   for(unsigned int i=0; i<NumOutputs; i++)
00064     if(cmds[i].weight>0) {
00065       if(pe.cmds[i].weight>0)
00066         cmds[i].set(cmds[i].value*wp+pe.cmds[i].value*w,cmds[i].weight*wp+pe.cmds[i].weight*w);
00067       else
00068         cmds[i].weight*=wp;
00069     } else
00070       cmds[i].set(pe.cmds[i].value,pe.cmds[i].weight*w);
00071   return *this;
00072 }
00073 /*! joints being averaged with weight<=0 have their weights averaged, but not their values (so an output can crossfade properly)\n
00074  *  @param pe the other PostureEngine
00075  *  @param w amount to weight towards @a pe
00076  *  - if @a w < .001, nothing is done
00077  *  - if @a w > .999, a straight copy of @a pe occurs (sets joints to unused properly at end of fade)
00078  *  - .001 and .999 is used instead of 0 and 1 to allow for slight addition errors in a loop (if
00079  *    using repeated additions of a delta value instead of repeated divisions)
00080  *  @return a new posture containing the results */
00081 PostureEngine PostureEngine::createAverage(const PostureEngine& pe, float w) const {
00082   PostureEngine tmp(*this);
00083   return tmp.setAverage(pe,w);
00084 }
00085 PostureEngine& PostureEngine::setCombine(const PostureEngine& pe) {
00086   for(unsigned int i=0; i<NumOutputs; i++) {
00087     float total=cmds[i].weight+pe.cmds[i].weight;
00088     cmds[i].set((cmds[i].value*cmds[i].weight+pe.cmds[i].value*pe.cmds[i].weight)/total,total);
00089   }
00090   return *this;
00091 }
00092 PostureEngine PostureEngine::createCombine(const PostureEngine& pe) const {
00093   PostureEngine tmp(*this);
00094   return tmp.setCombine(pe);
00095 }
00096 
00097 float PostureEngine::diff(const PostureEngine& pe) const {
00098   float ans=0;
00099   for(unsigned int i=0; i<NumOutputs; i++)
00100     if(cmds[i].weight>0 && pe.cmds[i].weight>0) {
00101       float dif=cmds[i].value-pe.cmds[i].value;
00102       ans+=dif*dif;
00103     }
00104   return ans;
00105 }
00106 
00107 float PostureEngine::avgdiff(const PostureEngine& pe) const {
00108   float ans=0;
00109   unsigned int cnt=0;
00110   for(unsigned int i=0; i<NumOutputs; i++)
00111     if(cmds[i].weight>0 && pe.cmds[i].weight>0) {
00112       float dif=cmds[i].value-pe.cmds[i].value;
00113       ans+=dif*dif;
00114       cnt++;
00115     }
00116   return ans/cnt;
00117 }
00118 
00119 float PostureEngine::maxdiff(const PostureEngine& pe) const {
00120   float max=0;
00121   for(unsigned int i=0; i<NumOutputs; i++)
00122     if(cmds[i].weight>0 && pe.cmds[i].weight>0) {
00123       float dif=cmds[i].value-pe.cmds[i].value;
00124       if(dif>max)
00125         max=dif;
00126     }
00127   return max;
00128 }
00129 
00130 void PostureEngine::setSaveFormat(bool condensed, WorldState* ws) {
00131   saveFormatCondensed=condensed;
00132   loadSaveSensors=ws;
00133 }
00134 
00135 unsigned int PostureEngine::getBinSize() const {
00136   unsigned int written=11; //accounts for initial #POS\n and final #END\n, plus 1
00137   const unsigned int len=0;
00138   char buf[len];
00139   if(saveFormatCondensed) {
00140     written+=snprintf(buf,len,"condensed %s\n",RobotName);
00141     if(loadSaveSensors!=NULL)
00142       written+=snprintf(buf,len,"meta-info = %u %u\n",loadSaveSensors->lastSensorUpdateTime,loadSaveSensors->frameNumber);
00143     bool weightsAllEqual=true;
00144     float weightsVal=cmds[0].weight;
00145     for(unsigned int i=1; i<NumOutputs && weightsAllEqual; i++)
00146       weightsAllEqual=(cmds[i].weight==weightsVal);
00147     if(!weightsAllEqual || weightsVal!=0) { //if they're all 0, skip outputs and weights
00148       written+=snprintf(buf,len,"outputs =");
00149       for(unsigned int i=0; i<NumOutputs; i++) {
00150         written+=snprintf(buf,len," %g",cmds[i].value);
00151       }
00152       if(!weightsAllEqual || weightsVal!=1) { //if they're all 1, skip weights
00153         written+=snprintf(buf,len,"\nweights =");
00154         for(unsigned int i=0; i<NumOutputs; i++) {
00155           written+=snprintf(buf,len," %g",cmds[i].weight);
00156         }
00157       }
00158       written+=snprintf(buf,len,"\n");
00159     }
00160     if(loadSaveSensors!=NULL) {
00161       written+=snprintf(buf,len,"buttons =");
00162       for(unsigned int i=0; i<NumButtons; i++) {
00163         written+=snprintf(buf,len," %g",loadSaveSensors->buttons[i]);
00164       }
00165       written+=snprintf(buf,len,"\nsensors =");
00166       for(unsigned int i=0; i<NumSensors; i++) {
00167         written+=snprintf(buf,len," %g",loadSaveSensors->sensors[i]);
00168       }
00169       written+=snprintf(buf,len,"\npidduties =");
00170       for(unsigned int i=0; i<NumPIDJoints; i++) {
00171         written+=snprintf(buf,len," %g",loadSaveSensors->pidduties[i]);
00172       }
00173       written+=snprintf(buf,len,"\n");
00174     }   
00175   } else {
00176     if(loadSaveSensors!=NULL)
00177       written+=snprintf(buf,len,"<meta-info>\n  timestamp\t%u\n  framenumber\t%u\n</meta-info>\n",loadSaveSensors->lastSensorUpdateTime,loadSaveSensors->frameNumber);
00178     for(unsigned int i=0; i<NumOutputs; i++)
00179       if(cmds[i].weight>0) {
00180         written+=snprintf(buf,len,"%s\t% .4f\t% .4f\n",outputNames[i],cmds[i].value,cmds[i].weight);
00181       }
00182     if(loadSaveSensors!=NULL) {
00183       written+=snprintf(buf,len,"<buttons>\n");
00184       for(unsigned int i=0; i<NumButtons; i++) {
00185         written+=snprintf(buf,len,"  %s\t% .4f\t\n",buttonNames[i],loadSaveSensors->buttons[i]);
00186       }
00187       written+=snprintf(buf,len,"</buttons><sensors>\n");
00188       for(unsigned int i=0; i<NumSensors; i++) {
00189         written+=snprintf(buf,len,"  %s\t% .4f\t\n",sensorNames[i],loadSaveSensors->sensors[i]);
00190       }
00191       written+=snprintf(buf,len,"</sensors><pidduties>\n");
00192       for(unsigned int i=0; i<NumPIDJoints; i++) {
00193         written+=snprintf(buf,len,"  duty-%s\t% .4f\t\n",outputNames[i],loadSaveSensors->pidduties[i]);
00194       }
00195       written+=snprintf(buf,len,"</pidduties>\n");
00196     }
00197   }
00198   return written;
00199 }
00200 
00201 unsigned int PostureEngine::loadBuffer(const char buf[], unsigned int len) {
00202   unsigned int origlen=len;
00203   clear();
00204   if(strncmp("#POS",buf,4)!=0) {
00205     // we don't want to display an error here because we may be only testing file type,
00206     // so it's up to the caller to decide if it's necessarily an error if the file isn't
00207     // a posture
00208     //std::cout << "ERROR PostureEngine load corrupted - expected #POS header" << std::endl;
00209     return 0;
00210   }
00211   saveFormatCondensed=false;
00212   char formatstring[64];
00213   snprintf(formatstring,64,"%%%dc %%g %%g%%n",outputNameLen); //std::cout << "Format: " << formatstring << std::endl;
00214   unsigned int idx=0;
00215   unsigned int linenum=1;
00216   enum section_t {
00217     SECTION_METAINFO, SECTION_OUTPUTS, SECTION_BUTTONS, SECTION_SENSORS, SECTION_PIDDUTIES
00218   } curSection=SECTION_OUTPUTS;
00219   char jname[outputNameLen+1];
00220   jname[outputNameLen]='\0';
00221   while(len<=origlen && len>0) {
00222     float fval, fwht=1;
00223     int written;
00224     //    printf("%d %.9s\n",linenum+1,buf);
00225     if(buf[0]=='\r') {
00226       buf++; len--;
00227       if(buf[0]=='\n') {
00228   buf++; len--;
00229       }
00230       linenum++;
00231       continue;
00232     }
00233     if(buf[0]=='\n') {
00234       buf++; len--;
00235       linenum++;
00236       continue;
00237     }
00238     if(buf[0]=='#') {
00239       if(strncmp("#END\n",buf,5)==0 || strncmp("#END\r",buf,5)==0) {
00240   return origlen-len+5;
00241       } else if(strncmp("#END\r\n",buf,6)==0) {
00242   return origlen-len+6;
00243       } else {
00244   while(len>0 && *buf!='\n' && *buf!='\r') {len--;buf++;}
00245   if(*buf=='\n') { //in case of \r\n
00246     buf++;
00247     len--;
00248   }
00249   linenum++;
00250   continue;
00251       }
00252     }
00253     if(isspace(buf[0])) {
00254       buf++; len--;
00255       continue;
00256     }
00257     written=-1;
00258     if(strncmp(buf,"condensed ",strlen("condensed"))==0) {
00259       char model[64];
00260       written=0; sscanf(buf,"condensed %64s%n",model,&written);
00261       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00262       if(strncmp(model,RobotName,64)!=0) {
00263   printf("*** ERROR line %d, specified model (%.64s) for condensed mode does not match current robot (%s)\n",linenum,model,RobotName);
00264   return 0;
00265       }
00266       saveFormatCondensed=true;
00267       for(unsigned int i=0; i<NumOutputs; i++)
00268   cmds[i].unset();
00269       /*} else if(strncmp(buf,"verbose",strlen("verbose"))==0) {
00270   written=strlen("verbose");
00271   if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00272   saveFormatCondensed=false;*/
00273     } else {
00274       if(saveFormatCondensed) {
00275   const unsigned int sectionLen=64;
00276   char section[sectionLen];
00277   written=0; sscanf(buf,"%64s = %n",section,&written);
00278   if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00279   if(strncmp(section,"outputs",sectionLen)==0) {
00280     for(unsigned int i=0; i<NumOutputs; i++) {
00281       float val;
00282       written=0; sscanf(buf,"%g%n",&val,&written);
00283       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00284       cmds[i].set(val);
00285     }
00286   } else if(strncmp(section,"weights",sectionLen)==0) {
00287     for(unsigned int i=0; i<NumOutputs; i++) {
00288       written=0; sscanf(buf,"%g%n",&cmds[i].weight,&written);
00289       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00290     }
00291   } else if(strncmp(section,"buttons",sectionLen)==0) {
00292     for(unsigned int i=0; i<NumButtons; i++) {
00293       written=0; sscanf(buf,"%g%n",&loadSaveSensors->buttons[i],&written);
00294       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00295     }
00296   } else if(strncmp(section,"sensors",sectionLen)==0) {
00297     for(unsigned int i=0; i<NumSensors; i++) {
00298       written=0; sscanf(buf,"%g%n",&loadSaveSensors->sensors[i],&written);
00299       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00300     }
00301   } else if(strncmp(section,"pidduties",sectionLen)==0) {
00302     for(unsigned int i=0; i<NumPIDJoints; i++) {
00303       written=0; sscanf(buf,"%g%n",&loadSaveSensors->pidduties[i],&written);
00304       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00305     }
00306   } else if(strncmp(section,"meta-info",sectionLen)==0) {
00307     written=0; sscanf(buf,"%u %u%n",&loadSaveSensors->lastSensorUpdateTime,&loadSaveSensors->frameNumber,&written);
00308     if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00309   } else {
00310     printf("*** Warning: line %d, unknown section '%.64s', skipping.\n",linenum,section);
00311   }
00312       } else {
00313   if(strncmp(buf,"<meta-info>",strlen("<meta-info>"))==0) {
00314     written=0; sscanf(buf,"<meta-info>%n",&written);
00315     if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00316     if(curSection!=SECTION_OUTPUTS)
00317       printf("*** WARNING PostureEngine encountered nested <meta-info> - line %d\n",linenum);
00318     curSection=SECTION_METAINFO;
00319     idx=0; //reset idx any time we switch sections, avoid illegal idx values
00320     continue;
00321   } else if(strncmp(buf,"</meta-info>",strlen("</meta-info>"))==0) {
00322     written=0; sscanf(buf,"</meta-info>%n",&written);
00323     if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00324     if(curSection!=SECTION_METAINFO)
00325       printf("*** WARNING PostureEngine encountered </meta-info> when not in sensor section - line %d\n",linenum);
00326     curSection=SECTION_OUTPUTS;
00327     idx=0; //reset idx any time we switch sections, avoid illegal idx values
00328     continue;
00329   } else if(strncmp(buf,"<buttons>",strlen("<buttons>"))==0) {
00330     written=0; sscanf(buf,"<buttons>%n",&written);
00331     if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00332     if(curSection!=SECTION_OUTPUTS)
00333       printf("*** WARNING PostureEngine encountered nested <buttons> - line %d\n",linenum);
00334     curSection=SECTION_BUTTONS;
00335     idx=0; //reset idx any time we switch sections, avoid illegal idx values
00336     continue;
00337   } else if(strncmp(buf,"</buttons>",strlen("</buttons>"))==0) {
00338     written=0; sscanf(buf,"</buttons>%n",&written);
00339     if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00340     if(curSection!=SECTION_BUTTONS)
00341       printf("*** WARNING PostureEngine encountered </buttons> when not in sensor section - line %d\n",linenum);
00342     curSection=SECTION_OUTPUTS;
00343     idx=0; //reset idx any time we switch sections, avoid illegal idx values
00344     continue;
00345   } else if(strncmp(buf,"<sensors>",strlen("<sensors>"))==0) {
00346     written=0; sscanf(buf,"<sensors>%n",&written);
00347     if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00348     if(curSection!=SECTION_OUTPUTS)
00349       printf("*** WARNING PostureEngine encountered nested <sensors> - line %d\n",linenum);
00350     curSection=SECTION_SENSORS;
00351     idx=0; //reset idx any time we switch sections, avoid illegal idx values
00352     continue;
00353   } else if(strncmp(buf,"</sensors>",strlen("</sensors>"))==0) {
00354     written=0; sscanf(buf,"</sensors>%n",&written);
00355     if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00356     if(curSection!=SECTION_SENSORS)
00357       printf("*** WARNING PostureEngine encountered </sensors> when not in sensor section - line %d\n",linenum);
00358     curSection=SECTION_OUTPUTS;
00359     idx=0; //reset idx any time we switch sections, avoid illegal idx values
00360     continue;
00361   } else if(strncmp(buf,"<pidduties>",strlen("<pidduties>"))==0) {
00362     written=0; sscanf(buf,"<pidduties>%n",&written);
00363     if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00364     if(curSection!=SECTION_OUTPUTS)
00365       printf("*** WARNING PostureEngine encountered nested <pidduties> - line %d\n",linenum);
00366     curSection=SECTION_PIDDUTIES;
00367     idx=0; //reset idx any time we switch sections, avoid illegal idx values
00368     continue;
00369   } else if(strncmp(buf,"</pidduties>",strlen("</pidduties>"))==0) {
00370     written=0; sscanf(buf,"</pidduties>%n",&written);
00371     if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00372     if(curSection!=SECTION_PIDDUTIES)
00373       printf("*** WARNING PostureEngine encountered </pidduties> when not in sensor section - line %d\n",linenum);
00374     curSection=SECTION_OUTPUTS;
00375     idx=0; //reset idx any time we switch sections, avoid illegal idx values
00376     continue;
00377   } else {
00378     if(curSection==SECTION_METAINFO) {
00379       const unsigned int nameLen=64;
00380       char name[nameLen];
00381       unsigned int ival;
00382       written=0; sscanf(buf,"%64s %u%n",name,&ival,&written);
00383       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00384       if(strncmp(name,"timestamp",nameLen)==0) {
00385         loadSaveSensors->lastSensorUpdateTime=ival;
00386       } else if(strncmp(name,"framenumber",nameLen)==0) {
00387         loadSaveSensors->frameNumber=ival;
00388       } else {
00389         std::cout << "*** WARNING '" << name << "' is not a valid meta-info on this model. (ignoring line " << linenum << ")" << std::endl;
00390       }
00391     } else if(curSection==SECTION_BUTTONS) {
00392       const unsigned int nameLen=64;
00393       char name[nameLen];
00394       written=0; sscanf(buf,"%64s %g%n",name,&fval,&written);
00395       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00396       unsigned int startidx=idx;
00397       for(;idx<NumButtons;idx++)
00398         if(strncmp(name,buttonNames[idx],nameLen)==0) {
00399     loadSaveSensors->buttons[idx]=fval;
00400     break;
00401         }
00402       if(idx==NumButtons) { //not found following startidx, look from beginning
00403         for(idx=0;idx<startidx;idx++)
00404     if(strncmp(name,buttonNames[idx],nameLen)==0) {
00405       loadSaveSensors->buttons[idx]=fval;
00406       break;
00407     }
00408         if(idx==startidx && strcmp(name,buttonNames[idx])!=0) //not found at all
00409     std::cout << "*** WARNING '" << name << "' is not a valid button on this model. (ignoring line " << linenum << ")" << std::endl;
00410       }
00411     } else if(curSection==SECTION_SENSORS) {
00412       const unsigned int nameLen=64;
00413       char name[nameLen];
00414       written=0; sscanf(buf,"%64s %g%n",name,&fval,&written);
00415       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00416       unsigned int startidx=idx;
00417       for(;idx<NumSensors;idx++)
00418         if(strncmp(name,sensorNames[idx],nameLen)==0) {
00419     loadSaveSensors->sensors[idx]=fval;
00420     break;
00421         }
00422       if(idx==NumSensors) { //not found following startidx, look from beginning
00423         for(idx=0;idx<startidx;idx++)
00424     if(strncmp(name,sensorNames[idx],nameLen)==0) {
00425       loadSaveSensors->sensors[idx]=fval;
00426       break;
00427     }
00428         if(idx==startidx && strcmp(name,sensorNames[idx])!=0) //not found at all
00429     std::cout << "*** WARNING '" << name << "' is not a valid sensor on this model. (ignoring line " << linenum << ")" << std::endl;
00430       }
00431     } else if(curSection==SECTION_PIDDUTIES) {
00432       const unsigned int nameLen=64;
00433       char name[nameLen];
00434       written=0; sscanf(buf,"%64s %g%n",name,&fval,&written);
00435       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00436       unsigned int startidx=idx;
00437       for(;idx<NumPIDJoints;idx++)
00438         if(strncmp(name,outputNames[idx],nameLen)==0) {
00439     loadSaveSensors->pidduties[PIDJointOffset+idx]=fval;
00440     break;
00441         }
00442       if(idx==NumPIDJoints) { //not found following startidx, look from beginning
00443         for(idx=0;idx<startidx;idx++)
00444     if(strncmp(name,outputNames[idx],nameLen)==0) {
00445       loadSaveSensors->pidduties[PIDJointOffset+idx]=fval;
00446       break;
00447     }
00448         if(idx==startidx && strcmp(name,outputNames[idx])!=0) //not found at all
00449     std::cout << "*** WARNING '" << name << "' is not a valid PID joint on this model. (ignoring line " << linenum << ")" << std::endl;
00450       }
00451     } else { //general joint specification
00452       jname[0]='\0';
00453       written=0; sscanf(buf,formatstring,jname,&fval,&fwht,&written);
00454       if(!checkInc(written,buf,len,"*** ERROR PostureEngine load corrupted - line %d\n",linenum)) return 0;
00455       //std::cout << '"' << jname << "\"\t" << (float)fval << '\t' << (float)fwht << std::endl;
00456       // we continue the search in order from where we left off - these are often
00457       // going to go in order, so might as well save a little time
00458       unsigned int startidx=idx;
00459       for(;idx<NumOutputs;idx++)
00460         if(strncmp(jname,outputNames[idx],outputNameLen+1)==0) {
00461     cmds[idx].set(fval,fwht);
00462     break;
00463         }
00464       if(idx==NumOutputs) { //not found following startidx, look from beginning
00465         for(idx=0;idx<startidx;idx++)
00466     if(strncmp(jname,outputNames[idx],outputNameLen+1)==0) {
00467       cmds[idx].set(fval,fwht);
00468       break;
00469     }
00470       if(idx==startidx && strcmp(jname,outputNames[idx])!=0) {//not found at all, check if this is a symmetric case
00471         unsigned int lidx=NumOutputs, ridx=NumOutputs;
00472         char tname[outputNameLen+1];
00473         strncpy(tname+1,jname,outputNameLen);
00474         tname[0]='L';
00475         for(idx=0;idx<NumOutputs;idx++) {
00476           if(strncmp(tname,outputNames[idx],outputNameLen+1)==0) {
00477             lidx=idx;
00478             break;
00479           }
00480         }
00481         tname[0]='R';
00482         for(idx=0;idx<NumOutputs;idx++) {
00483           if(strncmp(tname,outputNames[idx],outputNameLen+1)==0) {
00484             ridx=idx;
00485             break;
00486           }
00487         }
00488         if(lidx!=NumOutputs && ridx!=NumOutputs) {
00489           cmds[lidx].set(fval,fwht);
00490           cmds[ridx].set(fval,fwht);
00491         } else {
00492           idx=startidx;
00493           std::cout << "*** WARNING '" << jname << "' is not a valid joint on this model. (ignoring line " << linenum << ")" << std::endl;
00494         }
00495       }
00496       }
00497     }
00498   }
00499       }
00500     }
00501     while(*buf!='\n' && *buf!='\r') {
00502       buf++; len--;
00503     }
00504     if(buf[0]=='\r' && buf[1]=='\n') {
00505       buf+=2; len-=2;
00506     } else {
00507       buf++; len--;
00508     }
00509     linenum++;
00510   }
00511   std::cout << "*** WARNING PostureEngine load missing #END" << std::endl;
00512   return origlen-len;
00513 }
00514 
00515 //Why do i need a cast to const char**??? It doesn't work without, should be automatic... grrrr
00516 unsigned int PostureEngine::saveBuffer(char buf[], unsigned int len) const {
00517   unsigned int origlen=len;
00518   int written=snprintf(buf,len,"#POS\n");
00519   if(!checkInc(written,buf,len,"*** ERROR PostureEngine save failed on header\n")) return 0;
00520   if(saveFormatCondensed) {
00521     written=snprintf(buf,len,"condensed %s\n",RobotName);
00522     if(!checkInc(written,buf,len,"*** ERROR PostureEngine save condensed header failed\n")) return 0;
00523     if(loadSaveSensors!=NULL) {
00524       written=snprintf(buf,len,"meta-info = %u %u\n",loadSaveSensors->lastSensorUpdateTime,loadSaveSensors->frameNumber);
00525       if(!checkInc(written,buf,len,"*** ERROR PostureEngine save pidduty failed\n")) return 0;
00526     }
00527     bool weightsAllEqual=true;
00528     float weightsVal=cmds[0].weight;
00529     for(unsigned int i=1; i<NumOutputs && weightsAllEqual; i++)
00530       weightsAllEqual=(cmds[i].weight==weightsVal);
00531     if(!weightsAllEqual || weightsVal!=0) { //if they're all 0, skip outputs and weights
00532       written=snprintf(buf,len,"outputs =");
00533       if(!checkInc(written,buf,len,"*** ERROR PostureEngine save outputs header failed\n")) return 0;
00534       for(unsigned int i=0; i<NumOutputs; i++) {
00535         written=snprintf(buf,len," %g",cmds[i].value);
00536         if(!checkInc(written,buf,len,"*** ERROR PostureEngine save output failed\n")) return 0;
00537       }
00538       if(!weightsAllEqual || weightsVal!=1) { //if they're all 1, skip weights
00539         written=snprintf(buf,len,"\nweights =");
00540         if(!checkInc(written,buf,len,"*** ERROR PostureEngine save weights header failed\n")) return 0;
00541         for(unsigned int i=0; i<NumOutputs; i++) {
00542           written=snprintf(buf,len," %g",cmds[i].weight);
00543           if(!checkInc(written,buf,len,"*** ERROR PostureEngine save weight failed\n")) return 0;
00544         }
00545       }
00546       written=snprintf(buf,len,"\n");
00547       if(!checkInc(written,buf,len,"*** ERROR PostureEngine save final newline failed\n")) return 0;
00548     }
00549     if(loadSaveSensors!=NULL) {
00550       written=snprintf(buf,len,"buttons =");
00551       if(!checkInc(written,buf,len,"*** ERROR PostureEngine save buttons header failed\n")) return 0;
00552       for(unsigned int i=0; i<NumButtons; i++) {
00553         written=snprintf(buf,len," %g",loadSaveSensors->buttons[i]);
00554         if(!checkInc(written,buf,len,"*** ERROR PostureEngine save button failed\n")) return 0;
00555       }
00556       written=snprintf(buf,len,"\nsensors =");
00557       if(!checkInc(written,buf,len,"*** ERROR PostureEngine save sensors header failed\n")) return 0;
00558       for(unsigned int i=0; i<NumSensors; i++) {
00559         written=snprintf(buf,len," %g",loadSaveSensors->sensors[i]);
00560         if(!checkInc(written,buf,len,"*** ERROR PostureEngine save sensor failed\n")) return 0;
00561       }
00562       written=snprintf(buf,len,"\npidduties =");
00563       if(!checkInc(written,buf,len,"*** ERROR PostureEngine save pidduties header failed\n")) return 0;
00564       for(unsigned int i=0; i<NumPIDJoints; i++) {
00565         written=snprintf(buf,len," %g",loadSaveSensors->pidduties[i]);
00566         if(!checkInc(written,buf,len,"*** ERROR PostureEngine save pidduty failed\n")) return 0;
00567       }
00568       written=snprintf(buf,len,"\n");
00569       if(!checkInc(written,buf,len,"*** ERROR PostureEngine save final newline failed\n")) return 0;
00570     }   
00571   } else {
00572     if(loadSaveSensors!=NULL) {
00573       written=snprintf(buf,len,"<meta-info>\n  timestamp\t%u\n  framenumber\t%u\n</meta-info>\n",loadSaveSensors->lastSensorUpdateTime,loadSaveSensors->frameNumber);
00574       if(!checkInc(written,buf,len,"*** ERROR PostureEngine sensor begin save failed\n")) return 0;
00575     }
00576     for(unsigned int i=0; i<NumOutputs; i++)
00577       if(cmds[i].weight>0) {
00578         written=snprintf(buf,len,"%s\t% .4f\t% .4f\n",outputNames[i],cmds[i].value,cmds[i].weight);
00579         if(!checkInc(written,buf,len,"*** ERROR PostureEngine save failed\n")) return 0;
00580       }
00581     if(loadSaveSensors!=NULL) {
00582       written=snprintf(buf,len,"<buttons>\n");
00583       if(!checkInc(written,buf,len,"*** ERROR PostureEngine sensor begin save failed\n")) return 0;
00584       for(unsigned int i=0; i<NumButtons; i++) {
00585         written=snprintf(buf,len,"  %s\t% .4f\t\n",buttonNames[i],loadSaveSensors->buttons[i]);
00586         if(!checkInc(written,buf,len,"*** ERROR PostureEngine save button failed\n")) return 0;
00587       }
00588       written=snprintf(buf,len,"</buttons><sensors>\n");
00589       if(!checkInc(written,buf,len,"*** ERROR PostureEngine sensor end save failed\n")) return 0;
00590       for(unsigned int i=0; i<NumSensors; i++) {
00591         written=snprintf(buf,len,"  %s\t% .4f\t\n",sensorNames[i],loadSaveSensors->sensors[i]);
00592         if(!checkInc(written,buf,len,"*** ERROR PostureEngine save sensor failed\n")) return 0;
00593       }
00594       written=snprintf(buf,len,"</sensors><pidduties>\n");
00595       if(!checkInc(written,buf,len,"*** ERROR PostureEngine sensor end save failed\n")) return 0;
00596       for(unsigned int i=0; i<NumPIDJoints; i++) {
00597         written=snprintf(buf,len,"  %s\t% .4f\t\n",outputNames[i],loadSaveSensors->pidduties[i]);
00598         if(!checkInc(written,buf,len,"*** ERROR PostureEngine save pidduties failed\n")) return 0;
00599       }
00600       written=snprintf(buf,len,"</pidduties>\n");
00601       if(!checkInc(written,buf,len,"*** ERROR PostureEngine sensor end save failed\n")) return 0;
00602     }
00603   }
00604   written=snprintf(buf,len,"#END\n");
00605   if(!checkInc(written,buf,len,"*** ERROR PostureEngine save failed on #END\n")) return 0;
00606   return origlen-len;
00607 }
00608 
00609 unsigned int PostureEngine::loadFile(const char filename[]) {
00610   return LoadSave::loadFile(config->motion.makePath(filename).c_str());
00611 }
00612 unsigned int PostureEngine::saveFile(const char filename[]) const {
00613   return LoadSave::saveFile(config->motion.makePath(filename).c_str());
00614 }
00615 
00616 /*
00617 NEWMAT::ReturnMatrix
00618 Kinematics::getOrientation(unsigned int j) {
00619   unsigned int c=-1U,l=-1U;
00620   if(!lookup(j,c,l)) {
00621     NEWMAT::Matrix A(4,4);
00622     A<<ROBOOP::fourbyfourident;
00623     A.Release(); return A;
00624   }
00625   update(c,l);
00626   NEWMAT::Matrix R;
00627   NEWMAT::ColumnVector p;
00628   chains[c]->kine(R,p,j);
00629   R.Release(); return R;
00630 }
00631 
00632 NEWMAT::ReturnMatrix
00633 Kinematics::getPosition(unsigned int j) {
00634   unsigned int c=-1U,l=-1U;
00635   if(!lookup(j,c,l)) {
00636     NEWMAT::Matrix A(4,4);
00637     A<<ROBOOP::fourbyfourident;
00638     A.Release(); return A;
00639   }
00640   update(c,l);
00641   NEWMAT::Matrix R;
00642   NEWMAT::ColumnVector p;
00643   chains[c]->kine(R,p,j);
00644   p.Release(); return p;
00645 }
00646 */
00647 
00648 bool
00649 PostureEngine::solveLinkPosition(const NEWMAT::ColumnVector& Pobj, unsigned int j, const NEWMAT::ColumnVector& Plink) {
00650   unsigned int c=-1U,l=-1U;
00651   if(!lookup(j,c,l))
00652     return false;
00653   update(c,l);
00654   bool conv=false;
00655   NEWMAT::ColumnVector q=chains[c]->inv_kin_pos(Pobj,0,l,Plink,conv);
00656   for(unsigned int i=1; i<=l && i<=chainMaps[c].size(); i++)
00657     if(chainMaps[c][i]<NumOutputs)
00658       setOutputCmd(chainMaps[c][i],chains[c]->get_q(i));
00659   return conv;
00660 }
00661 
00662 bool
00663 PostureEngine::solveLinkVector(const NEWMAT::ColumnVector& Pobj, unsigned int j, const NEWMAT::ColumnVector& Plink) {
00664   solveLinkPosition(Pobj,j,Plink);
00665   //This method is an approximation, not entirely precise or fast as it could be
00666   //Something to work on some more down the road! :)
00667   //(this method is shared with HeadPointerMC::lookAtPoint(x,y,z))
00668   NEWMAT::ColumnVector poE=baseToLink(j)*Pobj;
00669   if(poE.nrows()>3 && poE(4)!=0) {
00670     poE/=poE(4);
00671   }
00672   poE=poE.SubMatrix(1,3,1,1);
00673   NEWMAT::ColumnVector plE=Plink.SubMatrix(1,3,1,1);
00674   if(Plink.nrows()>3 && Plink(4)!=0)
00675     plE/=Plink(4);
00676   float plE2=plE.SumSquare();
00677   float plE_len=sqrt(plE2);
00678   float obj_comp_link=NEWMAT::DotProduct(plE,poE)/plE_len;
00679   if(obj_comp_link<plE_len)
00680     obj_comp_link=obj_comp_link*.975; //.975 is a bit of fudge - accounts for joints moving Plink when adjusting
00681   else
00682     obj_comp_link=obj_comp_link/.975; //.975 is a bit of fudge - accounts for joints moving Plink when adjusting
00683   NEWMAT::ColumnVector obj_proj_link(4);
00684   obj_proj_link.SubMatrix(1,3,1,1)=obj_comp_link*plE/plE_len;
00685   obj_proj_link(4)=1;
00686   return solveLinkPosition(Pobj,j,obj_proj_link);
00687 }
00688 
00689 void
00690 PostureEngine::update(unsigned int c, unsigned int l) {
00691   for(unsigned int j=1; j<=l; j++) {
00692     unsigned int tkout=chainMaps[c][j];
00693     if(tkout<NumOutputs)
00694       chains[c]->set_q(getOutputCmd(tkout).value,j);
00695   }
00696 }
00697 
00698 /*! @file
00699  * @brief Implements PostureEngine, a base class for managing the values and weights of all the outputs
00700  * @author ejt (Creator)
00701  *
00702  * $Author: ejt $
00703  * $Name: tekkotsu-3_0 $
00704  * $Revision: 1.32 $
00705  * $State: Exp $
00706  * $Date: 2006/09/09 04:32:55 $
00707  */
00708 

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