00001 #include "PostureEngine.h"
00002 #include "Shared/WorldState.h"
00003 #include "Motion/IKSolver.h"
00004 #include "Shared/Config.h"
00005 #include "Shared/string_util.h"
00006 #include <stdio.h>
00007 #include <iostream>
00008 #include <regex.h>
00009 #include <map>
00010 #include <memory>
00011
00012 using namespace std;
00013
00014 PostureEngine::~PostureEngine() {}
00015
00016 void PostureEngine::takeSnapshot() {
00017 takeSnapshot(*WorldState::getCurrent());
00018 }
00019
00020 void PostureEngine::takeSnapshot(const WorldState& st) {
00021 for(unsigned int i=0; i<NumOutputs; i++)
00022 cmds[i].value=st.outputs[i];
00023 }
00024
00025 void PostureEngine::setWeights(float w, unsigned int lowjoint, unsigned int highjoint) {
00026 for(unsigned int i=lowjoint; i<highjoint; i++)
00027 cmds[i].weight=w;
00028 }
00029
00030 void PostureEngine::clear() {
00031 for(unsigned int i=0; i<NumOutputs; i++)
00032 cmds[i].unset();
00033 }
00034
00035 PostureEngine& PostureEngine::setOverlay(const PostureEngine& pe) {
00036 for(unsigned int i=0; i<NumOutputs; i++)
00037 if(pe.cmds[i].weight>0)
00038 cmds[i]=pe.cmds[i];
00039 return *this;
00040 }
00041 PostureEngine PostureEngine::createOverlay(const PostureEngine& pe) const {
00042 PostureEngine tmp(*this);
00043 return tmp.setOverlay(pe);
00044 }
00045 PostureEngine& PostureEngine::setUnderlay(const PostureEngine& pe) {
00046 for(unsigned int i=0; i<NumOutputs; i++)
00047 if(cmds[i].weight<=0)
00048 cmds[i]=pe.cmds[i];
00049 return *this;
00050 }
00051 PostureEngine PostureEngine::createUnderlay(const PostureEngine& pe) const {
00052 PostureEngine tmp(*this);
00053 return tmp.setUnderlay(pe);
00054 }
00055
00056
00057
00058
00059
00060
00061
00062
00063 PostureEngine& PostureEngine::setAverage(const PostureEngine& pe, float w) {
00064 if(w<0.001)
00065 return *this;
00066 if(w>0.999)
00067 return (*this=pe);
00068 float wp=1-w;
00069 for(unsigned int i=0; i<NumOutputs; i++)
00070 if(cmds[i].weight>0) {
00071 if(pe.cmds[i].weight>0)
00072 cmds[i].set(cmds[i].value*wp+pe.cmds[i].value*w,cmds[i].weight*wp+pe.cmds[i].weight*w);
00073 else
00074 cmds[i].weight*=wp;
00075 } else
00076 cmds[i].set(pe.cmds[i].value,pe.cmds[i].weight*w);
00077 return *this;
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087 PostureEngine PostureEngine::createAverage(const PostureEngine& pe, float w) const {
00088 PostureEngine tmp(*this);
00089 return tmp.setAverage(pe,w);
00090 }
00091 PostureEngine& PostureEngine::setCombine(const PostureEngine& pe) {
00092 for(unsigned int i=0; i<NumOutputs; i++) {
00093 float total=cmds[i].weight+pe.cmds[i].weight;
00094 cmds[i].set((cmds[i].value*cmds[i].weight+pe.cmds[i].value*pe.cmds[i].weight)/total,total);
00095 }
00096 return *this;
00097 }
00098 PostureEngine PostureEngine::createCombine(const PostureEngine& pe) const {
00099 PostureEngine tmp(*this);
00100 return tmp.setCombine(pe);
00101 }
00102
00103 float PostureEngine::diff(const PostureEngine& pe) const {
00104 float ans=0;
00105 for(unsigned int i=0; i<NumOutputs; i++)
00106 if(cmds[i].weight>0 && pe.cmds[i].weight>0) {
00107 float dif=cmds[i].value-pe.cmds[i].value;
00108 ans+=dif*dif;
00109 }
00110 return ans;
00111 }
00112
00113 float PostureEngine::avgdiff(const PostureEngine& pe) const {
00114 float ans=0;
00115 unsigned int cnt=0;
00116 for(unsigned int i=0; i<NumOutputs; i++)
00117 if(cmds[i].weight>0 && pe.cmds[i].weight>0) {
00118 float dif=cmds[i].value-pe.cmds[i].value;
00119 ans+=dif*dif;
00120 cnt++;
00121 }
00122 return ans/cnt;
00123 }
00124
00125 float PostureEngine::maxdiff(const PostureEngine& pe) const {
00126 float max=0;
00127 for(unsigned int i=0; i<NumOutputs; i++)
00128 if(cmds[i].weight>0 && pe.cmds[i].weight>0) {
00129 float dif=cmds[i].value-pe.cmds[i].value;
00130 if(dif>max)
00131 max=dif;
00132 }
00133 return max;
00134 }
00135
00136 void PostureEngine::setSaveFormat(bool condensed, WorldState* ws) {
00137 saveFormatCondensed=condensed;
00138 saveSensors=ws;
00139 }
00140
00141 unsigned int PostureEngine::getBinSize() const {
00142 unsigned int written=11;
00143 const unsigned int len=0;
00144 char buf[len];
00145 if(saveFormatCondensed) {
00146 #ifndef PLATFORM_APERIOS
00147 written+=snprintf(buf,len,"condensed %s\n",RobotName);
00148 #else
00149 written+=snprintf(buf,len,"condensed %s\n",RobotName.c_str());
00150 #endif
00151 if(saveSensors!=NULL)
00152 written+=snprintf(buf,len,"meta-info = %u %u\n",saveSensors->lastSensorUpdateTime,saveSensors->frameNumber);
00153 bool weightsAllEqual=true;
00154 float weightsVal=cmds[0].weight;
00155 for(unsigned int i=1; i<NumOutputs && weightsAllEqual; i++)
00156 weightsAllEqual=(cmds[i].weight==weightsVal);
00157 if(!weightsAllEqual || weightsVal!=0) {
00158 written+=snprintf(buf,len,"outputs =");
00159 for(unsigned int i=0; i<NumOutputs; i++) {
00160 written+=snprintf(buf,len," %g",cmds[i].value);
00161 }
00162 if(!weightsAllEqual || weightsVal!=1) {
00163 written+=snprintf(buf,len,"\nweights =");
00164 for(unsigned int i=0; i<NumOutputs; i++) {
00165 written+=snprintf(buf,len," %g",cmds[i].weight);
00166 }
00167 }
00168 written+=snprintf(buf,len,"\n");
00169 }
00170 if(saveSensors!=NULL) {
00171 written+=snprintf(buf,len,"buttons =");
00172 for(unsigned int i=0; i<NumButtons; i++) {
00173 written+=snprintf(buf,len," %g",saveSensors->buttons[i]);
00174 }
00175 written+=snprintf(buf,len,"\nsensors =");
00176 for(unsigned int i=0; i<NumSensors; i++) {
00177 written+=snprintf(buf,len," %g",saveSensors->sensors[i]);
00178 }
00179 written+=snprintf(buf,len,"\npidduties =");
00180 for(unsigned int i=0; i<NumPIDJoints; i++) {
00181 written+=snprintf(buf,len," %g",saveSensors->pidduties[i]);
00182 }
00183 written+=snprintf(buf,len,"\n");
00184 }
00185 } else {
00186 if(saveSensors!=NULL)
00187 written+=snprintf(buf,len,"<meta-info>\n timestamp\t%u\n framenumber\t%u\n</meta-info>\n",saveSensors->lastSensorUpdateTime,saveSensors->frameNumber);
00188 for(unsigned int i=0; i<NumOutputs; i++)
00189 if(cmds[i].weight>0) {
00190 if(cmds[i].weight==1)
00191 written+=snprintf(buf,len,"%s\t% .4f\n",outputNames[i],cmds[i].value);
00192 else
00193 written+=snprintf(buf,len,"%s\t% .4f\t% .4f\n",outputNames[i],cmds[i].value,cmds[i].weight);
00194 }
00195 if(saveSensors!=NULL) {
00196 written+=snprintf(buf,len,"<buttons>\n");
00197 for(unsigned int i=0; i<NumButtons; i++) {
00198 written+=snprintf(buf,len," %s\t% .4f\t\n",buttonNames[i],saveSensors->buttons[i]);
00199 }
00200 written+=snprintf(buf,len,"</buttons><sensors>\n");
00201 for(unsigned int i=0; i<NumSensors; i++) {
00202 written+=snprintf(buf,len," %s\t% .4f\t\n",sensorNames[i],saveSensors->sensors[i]);
00203 }
00204 written+=snprintf(buf,len,"</sensors><pidduties>\n");
00205 for(unsigned int i=0; i<NumPIDJoints; i++) {
00206 written+=snprintf(buf,len," %s\t% .4f\t\n",outputNames[i],saveSensors->pidduties[i]);
00207 }
00208 written+=snprintf(buf,len,"</pidduties>\n");
00209 }
00210 }
00211 return written;
00212 }
00213
00214 unsigned int PostureEngine::loadBuffer(const char buf[], unsigned int len, const char* filename) {
00215 unsigned int origlen=len;
00216 clear();
00217 if(buf==NULL || len==0) {
00218 cerr << "*** ERROR: PostureEngine::loadBuffer(" << static_cast<const void*>(buf) << ',' << len << ")" << endl;
00219 return 0;
00220 }
00221 if(strncmp("#POS",buf,4)!=0) {
00222
00223
00224
00225
00226 return 0;
00227 }
00228 saveFormatCondensed=false;
00229 const Capabilities* caps = &capabilities;
00230 unsigned int linenum=0;
00231 bool filtered=false;
00232 section_t curSection=SECTION_OUTPUTS;
00233 map<string,section_t> sectionMap;
00234 sectionMap["meta-info"]=SECTION_METAINFO;
00235 sectionMap["outputs"]=SECTION_OUTPUTS;
00236 sectionMap["buttons"]=SECTION_BUTTONS;
00237 sectionMap["sensors"]=SECTION_SENSORS;
00238 sectionMap["pidduties"]=SECTION_PIDDUTIES;
00239
00240
00241 while(len<=origlen && len>0) {
00242
00243 string line;
00244 for(unsigned int lineend=0; lineend<len; ++lineend) {
00245 bool isreturn = (buf[lineend]=='\r');
00246 bool isnewline = (buf[lineend]=='\n');
00247 bool iseof = (lineend+1==len);
00248 if(isreturn || isnewline || iseof) {
00249 line.assign(buf,(iseof && !isreturn && !isnewline) ? lineend+1 : lineend);
00250 ++linenum;
00251 ++lineend;
00252 buf+=lineend;
00253 len-=lineend;
00254 if(len==0)
00255 break;
00256 if(isreturn && buf[0]=='\n') {
00257 ++buf;
00258 --len;
00259 }
00260 break;
00261 }
00262 }
00263
00264
00265 string::size_type commentPos = line.find('#');
00266 if(commentPos!=string::npos) {
00267 if(line.substr(commentPos)=="#END")
00268 return origlen-len;
00269 line = line.substr(0,commentPos);
00270 }
00271
00272
00273
00274 vector<string> words;
00275 for(unsigned int i=0; i<line.size(); ++i) {
00276 if(isspace(line[i]) || line[i]=='=')
00277 continue;
00278 unsigned int j=i+1;
00279 while(j<line.size() && !isspace(line[j]) && line[j]!='=')
00280 ++j;
00281 words.push_back(line.substr(i,j-i));
00282 i=j;
00283 }
00284 if(words.size()==0)
00285 continue;
00286
00287
00288
00289
00290
00291
00292
00293 if(!loadLine(linenum,filename,sectionMap,words,curSection,caps,filtered))
00294 return 0;
00295
00296 }
00297
00298
00299 std::cout << "*** WARNING PostureEngine load missing #END" << std::endl;
00300 return origlen-len;
00301 }
00302
00303 bool PostureEngine::loadLine(unsigned int linenum, const char* filename, const std::map<std::string,section_t>& sectionMap, std::vector<std::string>& words, section_t& curSection, const Capabilities*& caps, bool& filtered) {
00304 if(words[0]=="specialize") {
00305 if(words.size()>2)
00306 cerr << "*** Warning line " << linenum << ", extra arguments to 'specialize'" << endl;
00307 filtered = false;
00308 if(words.size()>1) try {
00309 filtered = !string_util::reMatch(RobotName,words[1],REG_EXTENDED);
00310 } catch(const std::string& err) {
00311 cerr << "*** ERROR line " << linenum << ", bad regular expression: " << err << endl;
00312 return false;
00313 }
00314
00315 } else if(words[0]=="condensed") {
00316 if(words.size()>2)
00317 cerr << "*** Warning line " << linenum << ", extra arguments to 'condensed'" << endl;
00318 if(words.size()==1) {
00319 cerr << "*** ERROR line " << linenum << ", missing model name for 'condensed'" << endl;
00320 return false;
00321 } else {
00322 caps = getCapabilities(words[1]);
00323 if(caps==NULL) {
00324 cerr << "*** ERROR line " << linenum << ", unknown model for 'condensed': " << words[1] << endl;
00325 return false;
00326 }
00327 saveFormatCondensed=true;
00328 }
00329
00330 } else if(words[0]=="verbose") {
00331 if(words.size()>1)
00332 cerr << "*** Warning line " << linenum << ", extra arguments to 'verbose'" << endl;
00333 saveFormatCondensed=false;
00334
00335 } else if(words[0][0]=='<' && words[0][words[0].size()-1]=='>') {
00336 if(words.size()>1)
00337 cerr << "*** Warning line " << linenum << ", extra arguments to section tag (this isn't a real XML format, tag must be on line by itself)" << endl;
00338 bool isend = (words[0][1]=='/');
00339 const string name = words[0].substr((isend?2:1), words[0].size()-(isend?3:2));
00340 map<string,section_t>::const_iterator it = sectionMap.find(name);
00341 if(it==sectionMap.end()) {
00342 cerr << "*** ERROR line " << linenum << ", unknown section '" << name << "'" << endl;
00343 return false;
00344 }
00345 section_t section = it->second;
00346 if(isend) {
00347 if(curSection!=section)
00348 cerr << "*** Warning line " << linenum << ", mismatched close tag " << name << endl;
00349 curSection=SECTION_OUTPUTS;
00350 } else {
00351 if(curSection!=SECTION_OUTPUTS)
00352 cerr << "*** Warning line " << linenum << " (" << words[0] << "), nested tags not supported, or missing close tag" << endl;
00353 curSection=section;
00354 }
00355
00356 } else if(filtered) {
00357
00358
00359 } else {
00360
00361 map<string,section_t>::const_iterator it = sectionMap.find(words[0]);
00362 if(it==sectionMap.end()) {
00363
00364 if(words[0]=="weights") {
00365 if(caps==&capabilities) {
00366
00367 for(unsigned int i=1; i<words.size(); ++i)
00368 cmds[i-1].weight = (float)atof(words[i].c_str());
00369 } else {
00370
00371 for(unsigned int i=1; i<words.size(); ++i) {
00372 const char * name = caps->getOutputName(i-1);
00373 unsigned int off = capabilities.findOutputOffset(name);
00374 if(off==-1U) {
00375 cerr << "*** Warning line " << linenum;
00376 if (filename)
00377 cerr << " of " << filename;
00378 cerr << ", output '" << name << "' from robot " << caps->getRobotName() << " cannot be mapped to host " << RobotName << endl;
00379 } else {
00380 cmds[off].weight = (float)atof(words[i].c_str());
00381 }
00382 }
00383 }
00384 } else {
00385
00386 if(words.size()<2) {
00387 cerr << "*** ERROR line " << linenum;
00388 if (filename)
00389 cerr << " of " << filename;
00390 cerr << ", no value supplied for " << words[0] << endl;
00391 return false;
00392 }
00393 switch(curSection) {
00394 case SECTION_METAINFO: {
00395 if(words[0]=="timestamp") {
00396 if(loadSensors!=NULL)
00397 loadSensors->timestamp = atoi(words[1].c_str());
00398 } else if(words[0]=="framenumber") {
00399 if(loadSensors!=NULL)
00400 loadSensors->frameNumber = atoi(words[1].c_str());
00401 } else {
00402 cerr << "*** Warning line " << linenum;
00403 if (filename)
00404 cerr << " of " << filename;
00405 cerr << ", '" << words[0] << "' is not a valid meta-info" << endl;
00406 }
00407 } break;
00408 case SECTION_OUTPUTS: {
00409 stripTildes(words[0]);
00410 unsigned int off = capabilities.findOutputOffset(words[0].c_str()), loff=-1U;
00411 if(off==-1U) {
00412
00413 loff = capabilities.findOutputOffset(('L'+words[0]).c_str());
00414 if(loff!=-1U)
00415 off = capabilities.findOutputOffset(('R'+words[0]).c_str());
00416 }
00417 if(off==-1U) {
00418 cerr << "*** Warning line " << linenum;
00419 if (filename)
00420 cerr << " of " << filename;
00421 cerr << ", '" << words[0] << "' is not a valid output on this model (" << RobotName << ")" << endl;
00422 } else {
00423 float value = (float)atof(words[1].c_str());
00424 float weight=1;
00425 if(words.size()>2)
00426 weight = (float)atof(words[2].c_str());
00427 cmds[off].set(value,weight);
00428 if(loff!=-1U)
00429 cmds[loff].set(value,weight);
00430 }
00431 } break;
00432 case SECTION_BUTTONS: {
00433 unsigned int off = capabilities.findButtonOffset(words[0].c_str());
00434 if(off==-1U) {
00435 cerr << "*** Warning line " << linenum;
00436 if (filename)
00437 cerr << " of " << filename;
00438 cerr << ", '" << words[0] << "' is not a valid button on this model (" << RobotName << ")" << endl;
00439 } else if(loadSensors!=NULL) {
00440 loadSensors->buttons[off] = (float)atof(words[1].c_str());
00441 }
00442 } break;
00443 case SECTION_SENSORS: {
00444 unsigned int off = capabilities.findSensorOffset(words[0].c_str());
00445 if(off==-1U) {
00446 cerr << "*** Warning line " << linenum;
00447 if (filename)
00448 cerr << " of " << filename;
00449 cerr << ", '" << words[0] << "' is not a valid sensor on this model (" << RobotName << ")" << endl;
00450 } else if(loadSensors!=NULL) {
00451 loadSensors->sensors[off] = (float)atof(words[1].c_str());
00452 }
00453 } break;
00454 case SECTION_PIDDUTIES: {
00455 stripTildes(words[0]);
00456 unsigned int off = capabilities.findOutputOffset(words[0].c_str());
00457 if(off==-1U) {
00458 cerr << "*** Warning line " << linenum;
00459 if (filename)
00460 cerr << " of " << filename;
00461 cerr << ", '" << words[0] << "' is not a valid output on this model (" << RobotName << ")" << endl;
00462 } else if(off<PIDJointOffset || off>=PIDJointOffset+NumPIDJoints) {
00463 cerr << "*** Warning line " << linenum;
00464 if (filename)
00465 cerr << " of " << filename;
00466 cerr << ", output '" << words[0] << "' from robot " << caps->getRobotName() << " does not map to a PID joint on the local host " << RobotName << endl;
00467 } else if(loadSensors!=NULL) {
00468 loadSensors->pidduties[off-PIDJointOffset] = (float)atof(words[1].c_str());
00469 }
00470 } break;
00471 }
00472 }
00473
00474 } else {
00475
00476 switch(it->second) {
00477 case SECTION_METAINFO: {
00478 if(loadSensors==NULL)
00479 break;
00480 if(words.size()>1)
00481 loadSensors->timestamp = atoi(words[1].c_str());
00482 if(words.size()>1)
00483 loadSensors->frameNumber = atoi(words[2].c_str());
00484 } break;
00485 case SECTION_OUTPUTS: {
00486 unsigned int size=words.size();
00487 if(size-1!=caps->getNumOutputs()) {
00488 cerr << "*** ERROR line " << linenum;
00489 if (filename)
00490 cerr << " of " << filename;
00491 cerr << ", " << caps->getRobotName() << " expected " << caps->getNumOutputs() << " values, got " << (size-1) << endl;
00492 return 0;
00493 }
00494 if(caps==&capabilities) {
00495
00496 for(unsigned int i=1; i<size; ++i)
00497 cmds[i-1].set((float)atof(words[i].c_str()));
00498 } else {
00499
00500 for(unsigned int i=1; i<size; ++i) {
00501 const char * name = caps->getOutputName(i-1);
00502 unsigned int off = capabilities.findOutputOffset(name);
00503 if(off==-1U) {
00504 cerr << "*** Warning line " << linenum;
00505 if (filename)
00506 cerr << " of " << filename;
00507 cerr << ", output '" << name << "' from robot " << caps->getRobotName() << " cannot be mapped to host " << RobotName << endl;
00508 } else {
00509 cmds[off].set((float)atof(words[i].c_str()));
00510 }
00511 }
00512 }
00513 } break;
00514 case SECTION_BUTTONS: {
00515 if(loadSensors==NULL)
00516 break;
00517 unsigned int size=words.size();
00518 if(size-1!=caps->getNumButtons()) {
00519 cerr << "*** ERROR line " << linenum;
00520 if (filename)
00521 cerr << " of " << filename;
00522 cerr << ", " << caps->getRobotName() << " expected " << caps->getNumButtons() << " values, got " << (size-1) << endl;
00523 return 0;
00524 }
00525 if(caps==&capabilities) {
00526
00527 for(unsigned int i=1; i<size; ++i)
00528 loadSensors->buttons[i-1] = (float)atof(words[i].c_str());
00529 } else {
00530
00531 for(unsigned int i=1; i<size; ++i) {
00532 const char * name = caps->getButtonName(i-1);
00533 unsigned int off = capabilities.findButtonOffset(name);
00534 if(off==-1U) {
00535 cerr << "*** Warning line " << linenum;
00536 if (filename)
00537 cerr << " of " << filename;
00538 cerr << ", button '" << name << "' from robot " << caps->getRobotName() << " cannot be mapped to host " << RobotName << endl;
00539 } else {
00540 loadSensors->buttons[off] = (float)atof(words[i].c_str());
00541 }
00542 }
00543 }
00544 } break;
00545 case SECTION_SENSORS: {
00546 if(loadSensors==NULL)
00547 break;
00548 unsigned int size=words.size();
00549 if(size-1!=caps->getNumSensors()) {
00550 cerr << "*** ERROR line " << linenum;
00551 if (filename)
00552 cerr << " of " << filename;
00553 cerr << ", " << caps->getRobotName() << " expected " << caps->getNumSensors() << " values, got " << (size-1) << endl;
00554 return 0;
00555 }
00556 if(caps==&capabilities) {
00557
00558 for(unsigned int i=1; i<size; ++i)
00559 loadSensors->sensors[i-1] = (float)atof(words[i].c_str());
00560 } else {
00561
00562 for(unsigned int i=1; i<size; ++i) {
00563 const char * name = caps->getSensorName(i-1);
00564 unsigned int off = capabilities.findSensorOffset(name);
00565 if(off==-1U) {
00566 cerr << "*** Warning line " << linenum;
00567 if (filename)
00568 cerr << " of " << filename;
00569 cerr << ", sensor '" << name << "' from robot " << caps->getRobotName() << " cannot be mapped to host " << RobotName << endl;
00570 } else {
00571 loadSensors->sensors[off] = (float)atof(words[i].c_str());
00572 }
00573 }
00574 }
00575 } break;
00576 case SECTION_PIDDUTIES: {
00577 if(loadSensors==NULL)
00578 break;
00579 unsigned int size=words.size();
00580 if(size-1!=caps->getNumPIDJoints()) {
00581 cerr << "*** ERROR line " << linenum;
00582 if (filename)
00583 cerr << " of " << filename;
00584 cerr << ", " << caps->getRobotName() << " expected " << caps->getNumPIDJoints() << " values, got " << (size-1) << endl;
00585 return 0;
00586 }
00587 if(caps==&capabilities) {
00588 for(unsigned int i=1; i<size; ++i)
00589 loadSensors->pidduties[i-1] = (float)atof(words[i].c_str());
00590 } else {
00591
00592 unsigned int pidoff = caps->getPIDJointOffset();
00593 for(unsigned int i=1; i<size; ++i) {
00594 const char * name = caps->getOutputName(pidoff+i-1);
00595 unsigned int off = capabilities.findOutputOffset(name);
00596 if(off==-1U) {
00597 cerr << "*** Warning line " << linenum;
00598 if (filename)
00599 cerr << " of " << filename;
00600 cerr << ", output '" << name << "' from robot " << caps->getRobotName() << " cannot be mapped to host " << RobotName << endl;
00601 } else if(off<PIDJointOffset || off>=PIDJointOffset+NumPIDJoints) {
00602 cerr << "*** Warning line " << linenum;
00603 if (filename)
00604 cerr << " of " << filename;
00605 cerr << ", output '" << name << "' from robot " << caps->getRobotName()
00606 << " does not map to a PID joint on the local host " << RobotName << endl;
00607 } else {
00608 loadSensors->pidduties[off-PIDJointOffset] = (float)atof(words[i].c_str());
00609 }
00610 }
00611 }
00612 } break;
00613 }
00614 }
00615 }
00616 return true;
00617 }
00618
00619
00620 unsigned int PostureEngine::saveBuffer(char buf[], unsigned int len) const {
00621 unsigned int origlen=len;
00622 int written=snprintf(buf,len,"#POS\n");
00623 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save failed on header\n")) return 0;
00624 if(saveFormatCondensed) {
00625 #ifndef PLATFORM_APERIOS
00626 written=snprintf(buf,len,"condensed %s\n",RobotName);
00627 #else
00628 written=snprintf(buf,len,"condensed %s\n",RobotName.c_str());
00629 #endif
00630 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save condensed header failed\n")) return 0;
00631 if(saveSensors!=NULL) {
00632 written=snprintf(buf,len,"meta-info = %u %u\n",saveSensors->lastSensorUpdateTime,saveSensors->frameNumber);
00633 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save pidduty failed\n")) return 0;
00634 }
00635 bool weightsAllEqual=true;
00636 float weightsVal=cmds[0].weight;
00637 for(unsigned int i=1; i<NumOutputs && weightsAllEqual; i++)
00638 weightsAllEqual=(cmds[i].weight==weightsVal);
00639 if(!weightsAllEqual || weightsVal!=0) {
00640 written=snprintf(buf,len,"outputs =");
00641 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save outputs header failed\n")) return 0;
00642 for(unsigned int i=0; i<NumOutputs; i++) {
00643 written=snprintf(buf,len," %g",cmds[i].value);
00644 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save output failed\n")) return 0;
00645 }
00646 if(!weightsAllEqual || weightsVal!=1) {
00647 written=snprintf(buf,len,"\nweights =");
00648 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save weights header failed\n")) return 0;
00649 for(unsigned int i=0; i<NumOutputs; i++) {
00650 written=snprintf(buf,len," %g",cmds[i].weight);
00651 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save weight failed\n")) return 0;
00652 }
00653 }
00654 written=snprintf(buf,len,"\n");
00655 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save final newline failed\n")) return 0;
00656 }
00657 if(saveSensors!=NULL) {
00658 written=snprintf(buf,len,"buttons =");
00659 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save buttons header failed\n")) return 0;
00660 for(unsigned int i=0; i<NumButtons; i++) {
00661 written=snprintf(buf,len," %g",saveSensors->buttons[i]);
00662 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save button failed\n")) return 0;
00663 }
00664 written=snprintf(buf,len,"\nsensors =");
00665 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save sensors header failed\n")) return 0;
00666 for(unsigned int i=0; i<NumSensors; i++) {
00667 written=snprintf(buf,len," %g",saveSensors->sensors[i]);
00668 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save sensor failed\n")) return 0;
00669 }
00670 written=snprintf(buf,len,"\npidduties =");
00671 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save pidduties header failed\n")) return 0;
00672 for(unsigned int i=0; i<NumPIDJoints; i++) {
00673 written=snprintf(buf,len," %g",saveSensors->pidduties[i]);
00674 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save pidduty failed\n")) return 0;
00675 }
00676 written=snprintf(buf,len,"\n");
00677 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save final newline failed\n")) return 0;
00678 }
00679 } else {
00680 if(saveSensors!=NULL) {
00681 written=snprintf(buf,len,"<meta-info>\n timestamp\t%u\n framenumber\t%u\n</meta-info>\n",saveSensors->lastSensorUpdateTime,saveSensors->frameNumber);
00682 if(!checkInc(written,buf,len,"*** ERROR PostureEngine sensor begin save failed\n")) return 0;
00683 }
00684 for(unsigned int i=0; i<NumOutputs; i++) {
00685 if(cmds[i].weight>0) {
00686 if(cmds[i].weight==1)
00687 written=snprintf(buf,len,"%s\t% .4f\n",outputNames[i],cmds[i].value);
00688 else
00689 written=snprintf(buf,len,"%s\t% .4f\t% .4f\n",outputNames[i],cmds[i].value,cmds[i].weight);
00690 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save failed\n")) return 0;
00691 }
00692 }
00693 if(saveSensors!=NULL) {
00694 written=snprintf(buf,len,"<buttons>\n");
00695 if(!checkInc(written,buf,len,"*** ERROR PostureEngine sensor begin save failed\n")) return 0;
00696 for(unsigned int i=0; i<NumButtons; i++) {
00697 written=snprintf(buf,len," %s\t% .4f\t\n",buttonNames[i],saveSensors->buttons[i]);
00698 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save button failed\n")) return 0;
00699 }
00700 written=snprintf(buf,len,"</buttons><sensors>\n");
00701 if(!checkInc(written,buf,len,"*** ERROR PostureEngine sensor end save failed\n")) return 0;
00702 for(unsigned int i=0; i<NumSensors; i++) {
00703 written=snprintf(buf,len," %s\t% .4f\t\n",sensorNames[i],saveSensors->sensors[i]);
00704 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save sensor failed\n")) return 0;
00705 }
00706 written=snprintf(buf,len,"</sensors><pidduties>\n");
00707 if(!checkInc(written,buf,len,"*** ERROR PostureEngine sensor end save failed\n")) return 0;
00708 for(unsigned int i=0; i<NumPIDJoints; i++) {
00709 written=snprintf(buf,len," %s\t% .4f\t\n",outputNames[i],saveSensors->pidduties[i]);
00710 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save pidduties failed\n")) return 0;
00711 }
00712 written=snprintf(buf,len,"</pidduties>\n");
00713 if(!checkInc(written,buf,len,"*** ERROR PostureEngine sensor end save failed\n")) return 0;
00714 }
00715 }
00716 written=snprintf(buf,len,"#END\n");
00717 if(!checkInc(written,buf,len,"*** ERROR PostureEngine save failed on #END\n")) return 0;
00718 return origlen-len;
00719 }
00720
00721 unsigned int PostureEngine::loadFile(const char filename[]) {
00722 return LoadSave::loadFile(config->motion.makePath(filename).c_str());
00723 }
00724 unsigned int PostureEngine::saveFile(const char filename[]) const {
00725 return LoadSave::saveFile(config->motion.makePath(filename).c_str());
00726 }
00727
00728 bool
00729 PostureEngine::solveLinkPosition(const fmat::SubVector<3,const float>& Pobj, unsigned int link, const fmat::SubVector<3,const float>& Plink) {
00730 if(jointMaps[link]==NULL)
00731 return false;
00732 update();
00733 IKSolver& solver = jointMaps[link]->getIK();
00734 bool conv = solver.solve(Plink,*jointMaps[link],IKSolver::Point(Pobj));
00735 KinematicJoint * kj = jointMaps[link];
00736 while(kj!=NULL) {
00737 if(kj->outputOffset<NumOutputs)
00738 setOutputCmd(kj->outputOffset, kj->getQ());
00739 kj = kj->getParent();
00740 }
00741 return conv;
00742 }
00743
00744 bool
00745 PostureEngine::solveLinkVector(const fmat::SubVector<3,const float>& Pobj, unsigned int link, const fmat::SubVector<3,const float>& Plink) {
00746 solveLinkPosition(Pobj,link,Plink);
00747
00748
00749
00750 fmat::Column<3> poE=baseToLink(link)*Pobj;
00751 float plE_len=Plink.sumSq();
00752 float obj_comp_link=fmat::dotProduct(Plink,poE)/plE_len;
00753 if(obj_comp_link<plE_len)
00754 obj_comp_link=obj_comp_link*.975f;
00755 else
00756 obj_comp_link=obj_comp_link/.975f;
00757 fmat::Column<3> obj_proj_link(Plink*obj_comp_link);
00758 return solveLinkPosition(Pobj,link,obj_proj_link);
00759 }
00760
00761 bool
00762 PostureEngine::solveLinkOrientation(const fmat::Quaternion& oriTgt, unsigned int link, const fmat::Quaternion& oriOffset) {
00763 if(jointMaps[link]==NULL)
00764 return false;
00765 update();
00766 IKSolver& solver = jointMaps[link]->getIK();
00767 bool conv = solver.solve(oriOffset,*jointMaps[link],IKSolver::Rotation(oriTgt));
00768 KinematicJoint * kj = jointMaps[link];
00769 while(kj!=NULL) {
00770 if(kj->outputOffset<NumOutputs)
00771 setOutputCmd(kj->outputOffset, kj->getQ());
00772 kj = kj->getParent();
00773 }
00774 return conv;
00775 }
00776
00777 bool
00778 PostureEngine::solveLink(const fmat::SubVector<3,const float>& posTgt, const fmat::Quaternion& oriTgt, unsigned int link, const fmat::SubVector<3,const float>& posOffset, const fmat::Quaternion& oriOffset) {
00779 if(jointMaps[link]==NULL)
00780 return false;
00781 update();
00782 IKSolver& solver = jointMaps[link]->getIK();
00783 bool conv = solver.solve(posOffset,oriOffset,*jointMaps[link],IKSolver::Point(posTgt),1,IKSolver::Rotation(oriTgt),1);
00784 KinematicJoint * kj = jointMaps[link];
00785 while(kj!=NULL) {
00786 if(kj->outputOffset<NumOutputs)
00787 setOutputCmd(kj->outputOffset, kj->getQ());
00788 kj = kj->getParent();
00789 }
00790 return conv;
00791 }
00792
00793
00794 void
00795 PostureEngine::update() const {
00796 for(unsigned int j=0; j<NumOutputs; j++) {
00797 if(jointMaps[j]!=NULL)
00798 jointMaps[j]->setQ(getOutputCmd(j).value);
00799 }
00800 }
00801
00802
00803
00804
00805
00806