Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

WalkCalibration.cc

Go to the documentation of this file.
00001 #include "WalkCalibration.h"
00002 #include "FileInputControl.h"
00003 #include "StringInputControl.h"
00004 #include "NullControl.h"
00005 #include "Wireless/Wireless.h"
00006 #include "Behaviors/Controller.h"
00007 #include "Shared/WorldState.h"
00008 #include "Shared/string_util.h"
00009 #include "Shared/Config.h"
00010 #include "Sound/SoundManager.h"
00011 #include <stdlib.h>
00012 #include <fstream>
00013 
00014 using namespace std;
00015 
00016 const char * WalkCalibration::datanames[WalkCalibration::NUM_SRC] = { "fs","fr","sr","br","bs","rr" };
00017 
00018 
00019 WalkCalibration::WalkCalibration()
00020   : ControlBase("Interactive Calibration","Leads you through the process of calibrating the current walk"),
00021     st(ROOT), curType(NUM_SRC), 
00022     old_x(0), old_y(0), old_a(0), startTime(0), stopTime(0), 
00023     help(NULL), load(NULL), save(NULL), measure(NULL), clear(NULL), polar(NULL), rect(NULL), isPolar(true),
00024     lastLoad(), firstIn(0), secondIn(0), status()
00025 {
00026   help=new ControlBase("Help");
00027   help->pushSlot(new NullControl("This control will"));
00028   help->pushSlot(new NullControl("lead you through the"));
00029   help->pushSlot(new NullControl("process of taking"));
00030   help->pushSlot(new NullControl("measurements."));
00031   help->pushSlot(new NullControl(""));
00032   help->pushSlot(new NullControl("In order to take"));
00033   help->pushSlot(new NullControl("accurate measurements,"));
00034   help->pushSlot(new NullControl("the types of motion"));
00035   help->pushSlot(new NullControl("have been broken"));
00036   help->pushSlot(new NullControl("down into 6"));
00037   help->pushSlot(new NullControl("categories:"));
00038   help->pushSlot(new NullControl(""));
00039   help->pushSlot(new NullControl("fs - forward/strafe"));
00040   help->pushSlot(new NullControl("fr - forward/rotate"));
00041   help->pushSlot(new NullControl("sr - strafe/rotate"));
00042   help->pushSlot(new NullControl("br - backwards/rotate"));
00043   help->pushSlot(new NullControl("bs - backwards/strafe"));
00044   help->pushSlot(new NullControl("rr - pure rotation"));
00045   help->pushSlot(new NullControl(""));
00046   help->pushSlot(new NullControl("In each of these"));
00047   help->pushSlot(new NullControl("categories, you will"));
00048   help->pushSlot(new NullControl("set the aibo to walk"));
00049   help->pushSlot(new NullControl("in a direction using"));
00050   help->pushSlot(new NullControl("mainly the two noted"));
00051   help->pushSlot(new NullControl("parameters, and then"));
00052   help->pushSlot(new NullControl("tweak the \"unused\""));
00053   help->pushSlot(new NullControl("parameter to cancel"));
00054   help->pushSlot(new NullControl("out any drift in"));
00055   help->pushSlot(new NullControl("that direction."));
00056   help->pushSlot(new NullControl(""));
00057   help->pushSlot(new NullControl("For example, if"));
00058   help->pushSlot(new NullControl("taking an 'fs'"));
00059   help->pushSlot(new NullControl("measurement, you"));
00060   help->pushSlot(new NullControl("would pick any"));
00061   help->pushSlot(new NullControl("forward and strafe"));
00062   help->pushSlot(new NullControl("values, and then"));
00063   help->pushSlot(new NullControl("fiddle with the"));
00064   help->pushSlot(new NullControl("rotational speed"));
00065   help->pushSlot(new NullControl("until it maintained"));
00066   help->pushSlot(new NullControl("a constant heading."));
00067   help->pushSlot(new NullControl(""));
00068   help->pushSlot(new NullControl("If measuring one of"));
00069   help->pushSlot(new NullControl("the rotational"));
00070   help->pushSlot(new NullControl("types, you will"));
00071   help->pushSlot(new NullControl("tweak the unused"));
00072   help->pushSlot(new NullControl("directional movement"));
00073   help->pushSlot(new NullControl("so the aibo is"));
00074   help->pushSlot(new NullControl("facing exactly 180"));
00075   help->pushSlot(new NullControl("degrees from its"));
00076   help->pushSlot(new NullControl("original heading"));
00077   help->pushSlot(new NullControl("whenever it is on"));
00078   help->pushSlot(new NullControl("the opposite side of"));
00079   help->pushSlot(new NullControl("the circle from"));
00080   help->pushSlot(new NullControl("where it started."));
00081   help->pushSlot(new NullControl(""));
00082   help->pushSlot(new NullControl("For pure rotations,"));
00083   help->pushSlot(new NullControl("tweak both strafe"));
00084   help->pushSlot(new NullControl("and forward so the"));
00085   help->pushSlot(new NullControl("rotation is centered"));
00086   help->pushSlot(new NullControl("around the middle of"));
00087   help->pushSlot(new NullControl("the body.  Take"));
00088   help->pushSlot(new NullControl("displacement"));
00089   help->pushSlot(new NullControl("readings for other"));
00090   help->pushSlot(new NullControl("measurements"));
00091   help->pushSlot(new NullControl("relative to this"));
00092   help->pushSlot(new NullControl("point."));
00093   help->pushSlot(new NullControl(""));
00094   help->pushSlot(new NullControl("Enter angular"));
00095   help->pushSlot(new NullControl("measurements in"));
00096   help->pushSlot(new NullControl("degrees.  Enter"));
00097   help->pushSlot(new NullControl("distances as "));
00098   help->pushSlot(new NullControl("centimeters."));
00099   help->pushSlot(new NullControl(""));
00100   help->pushSlot(new NullControl("You will almost"));
00101   help->pushSlot(new NullControl("always enter"));
00102   help->pushSlot(new NullControl("positive values for"));
00103   help->pushSlot(new NullControl("all measurements."));
00104   help->pushSlot(new NullControl("Enter negative"));
00105   help->pushSlot(new NullControl("values only when"));
00106   help->pushSlot(new NullControl("using cartesian"));
00107   help->pushSlot(new NullControl("measurements with a"));
00108   help->pushSlot(new NullControl("right strafe or"));
00109   help->pushSlot(new NullControl("backward motion, or"));
00110   help->pushSlot(new NullControl("when a rotation is"));
00111   help->pushSlot(new NullControl("opposite of the"));
00112   help->pushSlot(new NullControl("intended direction."));
00113   help->pushSlot(new NullControl(""));
00114   help->pushSlot(new NullControl("Remember that"));
00115   help->pushSlot(new NullControl("POSITIVE strafe is"));
00116   help->pushSlot(new NullControl("to the Aibo's LEFT."));
00117   help->pushSlot(new NullControl(""));
00118   help->pushSlot(new NullControl("Finally, when you"));
00119   help->pushSlot(new NullControl("have taken at least"));
00120   help->pushSlot(new NullControl("6 (I suggest at"));
00121   help->pushSlot(new NullControl("least 16)"));
00122   help->pushSlot(new NullControl("measurements of each"));
00123   help->pushSlot(new NullControl("type, you can save"));
00124   help->pushSlot(new NullControl("the data set."));
00125   help->pushSlot(new NullControl(""));
00126   help->pushSlot(new NullControl("You can also save"));
00127   help->pushSlot(new NullControl("intermediate sets"));
00128   help->pushSlot(new NullControl("and concatenate them"));
00129   help->pushSlot(new NullControl("later."));
00130   help->pushSlot(new NullControl(""));
00131   help->pushSlot(new NullControl("IMPORTANT: It is"));
00132   help->pushSlot(new NullControl("recommended to keep"));
00133   help->pushSlot(new NullControl("a telnet connection"));
00134   help->pushSlot(new NullControl("to port 59000 open"));
00135   help->pushSlot(new NullControl("so you can log data"));
00136   help->pushSlot(new NullControl("samples there, in"));
00137   help->pushSlot(new NullControl("case of an"));
00138   help->pushSlot(new NullControl("unexpected crash,"));
00139   help->pushSlot(new NullControl("freeze, or shutdown."));
00140   help->pushSlot(new NullControl("Each data sample is"));
00141   help->pushSlot(new NullControl("a line of 6 numbers."));
00142   help->pushSlot(new NullControl(""));
00143   help->pushSlot(new NullControl("You will then need"));
00144   help->pushSlot(new NullControl("to run the matlab"));
00145   help->pushSlot(new NullControl("function in"));
00146   help->pushSlot(new NullControl("tools/WalkCalibration.m"));
00147   help->pushSlot(new NullControl("(Linear Least"));
00148   help->pushSlot(new NullControl("Squares) on these"));
00149   help->pushSlot(new NullControl("files to get the"));
00150   help->pushSlot(new NullControl("calibration matrix."));
00151   help->pushSlot(new NullControl(""));
00152   help->pushSlot(new NullControl("Copy this matrix"));
00153   help->pushSlot(new NullControl("back on to the"));
00154   help->pushSlot(new NullControl("memory stick and use"));
00155   help->pushSlot(new NullControl("the \"Load"));
00156   help->pushSlot(new NullControl("Calibration\""));
00157   help->pushSlot(new NullControl("control to apply it"));
00158   help->pushSlot(new NullControl("to the current walk."));
00159   help->pushSlot(new NullControl(""));
00160   help->pushSlot(new NullControl("You will then need"));
00161   help->pushSlot(new NullControl("to save the walk"));
00162   help->pushSlot(new NullControl("itself to retain the"));
00163   help->pushSlot(new NullControl("calibration for the"));
00164   help->pushSlot(new NullControl("next reboot."));
00165 
00166 
00167   load=new FileInputControl("Load Data Set","Load data files - select any file from the set, all will be loaded","/");
00168   save=new StringInputControl("Save Data Set","Saves current data","Enter the base name (up to 6 char)");
00169   measure=new NullControl("Take Measurements","Begins the data gathering process");
00170   measure->pushSlot(new NullControl());
00171   clear=new NullControl("Clear Data","Clear the current data and start over");
00172   clear->pushSlot(new NullControl());
00173   for(unsigned int i=0; i<NUM_SRC; i++)
00174     cnts[i]=0;
00175   setupRoot();
00176 }
00177 
00178 
00179 WalkCalibration::~WalkCalibration() {
00180   options.clear();
00181   delete help;
00182   delete load;
00183   delete save;
00184   delete measure;
00185   delete clear;
00186 }
00187 
00188 ControlBase * WalkCalibration::activate(MC_ID disp_id, Socket * gui) {
00189   erouter->addListener(this,EventBase::locomotionEGID);
00190   return ControlBase::activate(disp_id, gui);
00191 }
00192 
00193 
00194 void WalkCalibration::refresh() {
00195   if(load->getLastInput()!=lastLoad) {
00196     for(int i=0; i<NUM_SRC; i++) {
00197       unsigned int strlen=load->getLastInput().size();
00198       loadData(load->getLastInput().substr(0,strlen-6)+datanames[i]+std::string(".txt"),data[i]);
00199       cnts[i]=data[i].size();
00200     }
00201     lastLoad=load->getLastInput();
00202   }
00203   if(save->getLastInput().size()>0) {
00204     for(int i=0; i<NUM_SRC; i++)
00205       saveData(save->getLastInput()+datanames[i]+std::string(".txt"),data[i]);
00206     save->takeInput("");
00207   }
00208   if(st==READY && (curType==fs || curType==bs))
00209     isPolar=polar->getStatus();
00210   ControlBase::refresh();
00211   if(gui_comm!=NULL && wireless->isConnected(gui_comm->sock)) {
00212     if(status.size()==0)
00213       gui_comm->printf("status\n1\n# Samples: fs=%d fr=%d sr=%d br=%d bs=%d r=%d\n",cnts[0], cnts[1], cnts[2], cnts[3], cnts[4], cnts[5]);
00214     else
00215       gui_comm->printf("status\n%td\n%s\n",std::count(status.begin(),status.end(),'\n'),status.c_str());
00216   }
00217 }
00218 
00219 ControlBase* WalkCalibration::doSelect() {
00220   if(st==ROOT) {
00221     if(hilights.size()==0)
00222       return this;
00223     if(options[hilights.front()]==measure) {
00224       sndman->playFile(config->controller.select_snd);
00225       setupChoose();
00226       refresh();
00227       return this;
00228     } else if(options[hilights.front()]==clear) {
00229       sndman->playFile(config->controller.select_snd);
00230       setupClear();
00231       refresh();
00232       return this;
00233     } else {
00234       return ControlBase::doSelect();
00235     }
00236   } else if(st==CLEAR) {
00237     if(hilights.size()==0)
00238       return this;
00239     sndman->playFile(config->controller.select_snd);
00240     if(hilights.front()!=0) {
00241       sout->printf("Clearing data...\n");
00242       sndman->playFile(config->controller.cancel_snd);
00243       for(int i=0; i<NUM_SRC; i++) {
00244         clearData(data[i]);
00245         cnts[i]=0;
00246       }
00247     }
00248     setupRoot();
00249     refresh();
00250     return this;
00251   } else if(st==CHOOSE) {
00252     if(hilights.size()==0)
00253       return this;
00254     if(hilights.front()-2<NUM_SRC) {
00255       curType=static_cast<dataSource>(hilights.front()-2);
00256       sndman->playFile(config->controller.select_snd);
00257       setupReady();
00258       refresh();
00259       return this;
00260     }
00261     sndman->playFile(config->controller.cancel_snd);
00262     setupRoot();
00263     refresh();
00264     return this;
00265   } else if(st==READY) {
00266     if(hilights.size()==0 || options[hilights.front()]->getName()=="Go!") {
00267       sndman->playFile(config->controller.select_snd);
00268       setupMoving();
00269       refresh();
00270       return this;
00271     }
00272     if(options[hilights.front()]==polar || options[hilights.front()]==rect) {
00273       return ControlBase::doSelect();
00274     }
00275     sndman->playFile(config->controller.cancel_snd);
00276     setupChoose();
00277     refresh();
00278     return this;
00279   } else {
00280     sndman->playFile(config->controller.cancel_snd);
00281     setupChoose();
00282     refresh();
00283     return this;
00284   }
00285 }
00286 
00287 void WalkCalibration::processEvent(const EventBase& e) {
00288   if(st==MOVING) {
00289     stopTime=e.getTimeStamp();
00290     sout->printf("Ran for %g seconds\n",(stopTime-startTime)/1000.f);
00291     sndman->playFile(config->controller.select_snd);
00292     setupReading1();
00293     refresh();
00294     if(curType!=5)
00295       doReadStdIn(std::string("Enter ")+getFirstMeasure(curType));
00296     else
00297       doReadStdIn(std::string("Enter ")+getSecondMeasure(curType));
00298   }
00299 }
00300  
00301 
00302 ControlBase * WalkCalibration::takeInput(const std::string& msg) {
00303   if(st!=READING_1 && st!=READING_2)
00304     return ControlBase::takeInput(msg);
00305   else {
00306     char * end;
00307     const char * str=msg.c_str();
00308     if(st==READING_1) {
00309       firstIn=(float)strtod(str,&end);
00310       if(end==str) {
00311         err("Invalid input: "+msg);
00312         return doReadStdIn(std::string("Enter ")+getFirstMeasure(curType));
00313       }
00314       sndman->playFile(config->controller.select_snd);
00315       setupReading2();
00316       refresh();
00317       if(*end!='\0')
00318         return takeInput(end);
00319       else
00320         return doReadStdIn(std::string("Enter ")+getSecondMeasure(curType));
00321     }
00322     if(st==READING_2) {
00323       secondIn=(float)strtod(str,&end);
00324       if(end==str) {
00325         err("Invalid input: "+msg);
00326         return doReadStdIn(std::string("Enter ")+getSecondMeasure(curType));
00327       }
00328       addSample();
00329       sndman->playFile(config->controller.select_snd);
00330       setupReady();
00331       refresh();
00332       return this;
00333     }
00334     return NULL;
00335   }
00336 }
00337  
00338 
00339 void WalkCalibration::setHilights(const std::vector<unsigned int>& hi) {
00340   if(st==ROOT || st==CLEAR)
00341     ControlBase::setHilights(hi);
00342   else {
00343     std::vector<unsigned int> h;
00344     for(unsigned int i=0; i<hi.size(); i++)
00345       if((options[hi[i]]!=NULL && options[hi[i]]->slotsSize()>0) || (st==READY && (options[hi[i]]==polar || options[hi[i]]==rect)))
00346         h.push_back(hi[i]);
00347     ControlBase::setHilights(h);
00348   }
00349 }
00350  
00351 
00352 void WalkCalibration::hilightFirst() {
00353   if(st==ROOT || st==CLEAR)
00354     ControlBase::hilightFirst();
00355   else {
00356     std::vector<unsigned int> h;
00357     for(unsigned int i=0; i<options.size(); i++)
00358       if(options[i]!=NULL && options[i]->slotsSize()>0) {
00359         h.push_back(i);
00360         break;
00361       }
00362     ControlBase::setHilights(h);    
00363   }
00364 }
00365  
00366 void WalkCalibration::loadData(const std::string& n, std::vector<float*>& dat) {
00367   clearData(dat);
00368   sout->printf("Loading data from '%s'...\n",n.c_str());
00369   std::ifstream in(n.c_str());
00370   if(!in) {
00371     err("Could not open file for saving");
00372     return;
00373   }
00374   while(in) {
00375     dat.push_back(new float[6]);
00376     for(unsigned int c=0; c<6; c++) {
00377       in >> dat.back()[c];
00378       if(!in) {
00379         if(c!=0)
00380           err("Data file ended mid row");
00381         break;
00382       }
00383     }
00384   }
00385   delete [] dat.back();
00386   dat.pop_back();
00387   in.close();
00388 }
00389 
00390 void WalkCalibration::saveData(const std::string& n, const std::vector<float*>& dat) {
00391   std::string p=config->portPath(n);
00392   sout->printf("Saving data to '%s'...\n",p.c_str());
00393   std::ofstream out(p.c_str());
00394   if(!out) {
00395     err("Could not open file for saving");
00396     return;
00397   }
00398   unsigned int i=0;
00399   for(; i<dat.size(); i++) {
00400     for(unsigned int c=0; c<6; c++)
00401       out << dat[i][c] << ' ';
00402     out << endl;
00403     if(!out) {
00404       err("It appears the memory stick ran out of space?");
00405       break;
00406     }
00407   }
00408   out.close();
00409   sout->printf("%d rows written\n",i);
00410 }
00411 
00412 void WalkCalibration::clearData(std::vector<float*>& dat) {
00413   for(unsigned int i=0; i<dat.size(); i++)
00414     delete [] dat[i];
00415   dat.clear();
00416 }
00417 
00418 void WalkCalibration::setupRoot() {
00419   clearSlots();
00420   setName("Interactive Calibration");
00421   status="";
00422   pushSlot(help);
00423   pushSlot(load);
00424   pushSlot(save);
00425   pushSlot(measure);
00426   pushSlot(clear);
00427   st=ROOT;
00428 }
00429 
00430 void WalkCalibration::setupChoose() {
00431   bool isFromRoot=(st==ROOT);
00432   if(isFromRoot) {
00433     options.clear();
00434     hilights.clear();
00435   } else
00436     clearSlots();
00437   pushSlot(new NullControl("Choose Category"));
00438   pushSlot(NULL);
00439   NullControl * tmp;
00440   for(unsigned int i=0; i<NUM_SRC; i++) {
00441     dataSource s=static_cast<dataSource>(i);
00442     if(s==r)
00443       pushSlot(tmp=new NullControl(getIndexName(getSecondIndex(s))));
00444     else
00445       pushSlot(tmp=new NullControl(getIndexName(getFirstIndex(s))+std::string("/")+getIndexName(getSecondIndex(s))));
00446     tmp->pushSlot(NULL);
00447   }
00448   pushSlot(NULL);
00449   pushSlot(tmp=new NullControl(isFromRoot?"Cancel":"Done"));
00450   tmp->pushSlot(NULL);
00451   st=CHOOSE;
00452 }
00453 
00454 void WalkCalibration::setupReady() {
00455   polar=rect=NULL;
00456   clearSlots();
00457   pushSlot(new NullControl("Ready to record"));
00458   if(curType==r)
00459     pushSlot(new NullControl(string_util::makeUpper(getIndexName(getSecondIndex(curType)))));
00460   else
00461     pushSlot(new NullControl(string_util::makeUpper(getIndexName(getFirstIndex(curType)))+std::string("/")+string_util::makeUpper(getIndexName(getSecondIndex(curType)))));
00462   pushSlot(NULL);
00463   switch(curType) {
00464   case fs:
00465     pushSlot(new NullControl("Choose any forward"));
00466     pushSlot(new NullControl("and sideways vel."));
00467     pushSlot(new NullControl("Then tweak rotation"));
00468     pushSlot(new NullControl("to maintain heading"));
00469     polar=new ToggleControl("Take polar measurements","Check this if you want to take measurements as displacement,heading",new ToggleControl::RadioGroup());
00470     rect=new ToggleControl("Take cartesian measurements","Check this if you want to take measurements as x,y",polar->getRadioGroup());
00471     if(isPolar)
00472       polar->setStatus(true);
00473     else
00474       rect->setStatus(true);
00475     pushSlot(polar);
00476     pushSlot(rect);
00477     break;
00478   case fr:
00479     pushSlot(new NullControl("Choose any rotational"));
00480     pushSlot(new NullControl("and forward vel."));
00481     pushSlot(new NullControl("Tweak sideways vel."));
00482     pushSlot(new NullControl("to line up heading"));
00483     pushSlot(new NullControl("on opposite side of"));
00484     pushSlot(new NullControl("circle."));
00485     break;
00486   case sr:
00487     pushSlot(new NullControl("Choose any sideways"));
00488     pushSlot(new NullControl("vel.  Tweak forward"));
00489     pushSlot(new NullControl("vel. to cancel drift"));
00490     pushSlot(new NullControl("Then choose any"));
00491     pushSlot(new NullControl("rotational vel."));
00492     break;
00493   case br:
00494     pushSlot(new NullControl("Choose any rotational"));
00495     pushSlot(new NullControl("and sideways vel."));
00496     pushSlot(new NullControl("Tweak forward vel."));
00497     pushSlot(new NullControl("to line up heading"));
00498     pushSlot(new NullControl("on opposite side of"));
00499     pushSlot(new NullControl("circle."));
00500     break;
00501   case bs:
00502     pushSlot(new NullControl("Choose any forward"));
00503     pushSlot(new NullControl("and sideways vel."));
00504     pushSlot(new NullControl("Then tweak rotation"));
00505     pushSlot(new NullControl("to maintain heading"));
00506     polar=new ToggleControl("Take polar measurements","Check this if you want to take measurements as displacement,heading",new ToggleControl::RadioGroup());
00507     rect=new ToggleControl("Take cartesian measurements","Check this if you want to take measurements as x,y",polar->getRadioGroup());
00508     polar->setStatus(true);
00509     if(isPolar)
00510       polar->setStatus(true);
00511     else
00512       rect->setStatus(true);
00513     pushSlot(polar);
00514     pushSlot(rect);
00515     break;
00516   case r:
00517     pushSlot(new NullControl("Choose any"));
00518     pushSlot(new NullControl("rotational vel."));
00519     pushSlot(new NullControl("Tweak others to"));
00520     pushSlot(new NullControl("center rotation"));
00521     break;
00522   case NUM_SRC:
00523     {
00524       pushSlot(new NullControl("An error has occured."));
00525       pushSlot(new NullControl("Please go back and"));
00526       pushSlot(new NullControl("try again"));
00527       pushSlot(NULL);
00528       NullControl * tmp;
00529       pushSlot(tmp=new NullControl((st==CHOOSE)?"Cancel":"Done"));
00530       tmp->pushSlot(new NullControl());
00531       st=READY;
00532       return;
00533     }
00534   }
00535   pushSlot(NULL);
00536   NullControl * tmp;
00537   pushSlot(tmp=new NullControl("Go!"));
00538   tmp->pushSlot(new NullControl());
00539   pushSlot(tmp=new NullControl((st==CHOOSE)?"Cancel":"Done"));
00540   tmp->pushSlot(new NullControl());
00541   st=READY;
00542 }
00543 
00544 void WalkCalibration::setupMoving() {
00545   old_x=state->vel_x;
00546   old_y=state->vel_y;
00547   old_a=state->vel_a;
00548   if(old_x+old_y+old_a==0) {
00549     err("The WorldState velocities are all 0.\n\n"
00550         "Make sure whatever code is causing the motion is throwing\n"
00551         "a LocomotionEvent, and that the EStop is off.  You can use\n"
00552         "the EventLogger to check for LocomotionEvents.");
00553     return;
00554   }
00555   switch(curType) {
00556   case fs:
00557   case fr:
00558     if(old_x<0) {
00559       err("Have to be moving FORWARD for this category");
00560       return;
00561     }
00562     break;
00563   case bs:
00564   case br:
00565     if(old_x>0) {
00566       err("Have to be moving BACKWARD for this category");
00567       return;
00568     }
00569     break;
00570   case NUM_SRC:
00571     err("Bad category");
00572     return;
00573   case sr:
00574   case r:
00575     ;
00576   }
00577   sout->printf("Velocity is: %g %g %g\n",old_x,old_y,old_a);
00578   clearSlots();
00579   pushSlot(new NullControl("Running..."));
00580   if(curType!=5)
00581     pushSlot(new NullControl(std::string(getIndexName(getFirstIndex(curType)))+"/"+std::string(getIndexName(getSecondIndex(curType)))));
00582   else
00583     pushSlot(new NullControl(getIndexName(getSecondIndex(curType))));
00584   pushSlot(NULL);
00585   pushSlot(new NullControl("Recording will stop"));
00586   pushSlot(new NullControl("on the next"));
00587   pushSlot(new NullControl("LocomotionEvent."));
00588   pushSlot(new NullControl("EStop is recommended."));
00589   char str[255];
00590   sprintf(str,"vel_x=%g",old_x);
00591   pushSlot(new NullControl(str));
00592   sprintf(str,"vel_y=%g",old_y);
00593   pushSlot(new NullControl(str));
00594   sprintf(str,"vel_a=%g",old_a);
00595   pushSlot(new NullControl(str));
00596   pushSlot(NULL);
00597   NullControl * tmp;
00598   pushSlot(tmp=new NullControl("Cancel"));
00599   tmp->pushSlot(new NullControl());
00600   st=MOVING;
00601   startTime=get_time();
00602 }
00603 
00604 void WalkCalibration::setupReading1() {
00605   if(curType==5) {
00606     setupReading2();
00607     return;
00608   }
00609   clearSlots();
00610   pushSlot(new NullControl("Reading first input"));
00611   pushSlot(NULL);
00612   pushSlot(new NullControl("Please enter:"));
00613   pushSlot(new NullControl(getFirstMeasure(curType)));
00614   pushSlot(NULL);
00615   NullControl * tmp;
00616   pushSlot(tmp=new NullControl("Cancel"));
00617   tmp->pushSlot(new NullControl());
00618   st=READING_1;
00619 }
00620 
00621 void WalkCalibration::setupReading2() {
00622   clearSlots();
00623   if(curType==5)
00624     pushSlot(new NullControl("Reading input"));
00625   else
00626     pushSlot(new NullControl("Reading second input"));
00627   pushSlot(NULL);
00628   pushSlot(new NullControl("Please enter:"));
00629   pushSlot(new NullControl(getSecondMeasure(curType)));
00630   pushSlot(NULL);
00631   NullControl * tmp;
00632   pushSlot(tmp=new NullControl("Cancel"));
00633   tmp->pushSlot(new NullControl());
00634   st=READING_2;
00635 }
00636 
00637 
00638 
00639 void WalkCalibration::setupClear() {
00640   options.clear();
00641   setName("Clear Data");
00642   char tmp[255];
00643   sprintf(tmp,"There are %d samples.  Are you sure?",cnts[0]+cnts[1]+cnts[2]+cnts[3]+cnts[4]+cnts[5]);
00644   status=tmp;
00645   pushSlot(new NullControl("No","Don't clear the data"));
00646   pushSlot(new NullControl("Yes","Start over"));
00647   hilightFirst();
00648   st=CLEAR;
00649 }
00650 
00651 unsigned int WalkCalibration::getFirstIndex(WalkCalibration::dataSource t) {
00652   switch(t) {
00653   case fs:
00654   case fr:
00655     return 0;
00656   case sr:
00657     return 1;
00658   case bs:
00659   case br:
00660     return 3;
00661   case r:
00662   case NUM_SRC:
00663     return -1U;
00664   }
00665   return -1U;
00666 }
00667 
00668 unsigned int WalkCalibration::getSecondIndex(WalkCalibration::dataSource t) {
00669   switch(t) {
00670   case fs:
00671   case bs:
00672     return 1;
00673   case fr:
00674   case sr:
00675   case br:
00676   case r:
00677     return 2;
00678   case NUM_SRC:
00679     return -1U;
00680   }
00681   return -1U;
00682 }
00683 
00684 const char * WalkCalibration::getIndexName(unsigned int t) {
00685   switch(t) {
00686   case 0:
00687     return "Forward";
00688   case 1:
00689     return "Strafe";
00690   case 2:
00691     return "Rotate";
00692   case 3:
00693     return "Backward";
00694   }
00695   return NULL;
00696 }
00697 
00698 const char * WalkCalibration::getFirstMeasure(WalkCalibration::dataSource t) {
00699   switch(t) {
00700   case fs:
00701     if(isPolar)
00702       return "displacement";
00703     else
00704       return "forward distance";
00705   case fr:
00706   case sr:
00707   case br:
00708     return "displacement";
00709   case bs:
00710     if(isPolar)
00711       return "displacement";
00712     else
00713     return "backward distance";
00714   case r:
00715     return NULL;
00716   case NUM_SRC:
00717     return NULL;
00718   }
00719   return NULL;
00720 }
00721 
00722 const char * WalkCalibration::getSecondMeasure(WalkCalibration::dataSource t) {
00723   switch(t) {
00724   case fs:
00725   case bs:
00726     if(isPolar)
00727       return "bearing";
00728     else
00729       return "sideways distance";
00730   case fr:
00731   case sr:
00732   case br:
00733   case r:
00734     return "angular distance";
00735   case NUM_SRC:
00736     return NULL;
00737   }
00738   return NULL;
00739 }
00740 
00741 float WalkCalibration::arclen(float d, float a, float sign) {
00742   if(fabs(a)<=1) //if the angle is small (in particular, 0) leads to numerical instability.
00743     return (sign<0)?-fabs(d):fabs(d);
00744   //otherwise, convert to radians
00745   a*=(float)M_PI/180;
00746   //calculate radius of the circle we're tracing (there's some simple geometry to get this)
00747   float radius=fabs(d/2/sin(a/2));
00748   //and return the length of the sector we've traced (with the requested sign)
00749   if(sign<0)
00750     return -a*radius;
00751   return a*radius;
00752 }
00753 
00754 
00755 //this will allow you to solve for the conversion from commands to actual
00756 //which I was planning to then invert for the conversion from desired to command
00757 //but then I realized I could just solve for the inverted for directly
00758 // (never was actually tested btw, and also out of date with rest of this code)
00759 /*
00760 void WalkCalibration::addSample() {
00761   switch(getType()) {
00762   case 0: //fs
00763     addSample(forward,0, firstIn*10);
00764     addSample(forward,1, secondIn*10);
00765     addSample(forward,2, 0);
00766     break;
00767   case 1: //fr
00768     addSample(forward,0, arclen(firstIn*10,secondIn, 1));
00769     addSample(forward,1, 0);
00770     addSample(forward,2, (old_a>0?secondIn:-secondIn)*M_PI/180);
00771     break;
00772   case 2: //sr
00773     addSample(forward,0, 0);
00774     addSample(reverse,0, 0);
00775     addSample(forward,1, arclen(firstIn*10,secondIn,old_y));
00776     addSample(reverse,1, arclen(firstIn*10,secondIn,old_y));
00777     addSample(forward,2, (old_a>0?secondIn:-secondIn)*M_PI/180);
00778     addSample(reverse,2, (old_a>0?secondIn:-secondIn)*M_PI/180);
00779     break;
00780   case 3: //br
00781     addSample(reverse,0, arclen(firstIn*10,secondIn,-1));
00782     addSample(reverse,1, 0);
00783     addSample(reverse,2, (old_a>0?secondIn:-secondIn)*M_PI/180);
00784     break;
00785   case 4: //bs
00786     addSample(reverse,0, firstIn*10);
00787     addSample(reverse,1, secondIn*10);
00788     addSample(reverse,2, 0);
00789     break;
00790   case 5: //r
00791     addSample(forward,2, (old_a>0?secondIn:-secondIn)*M_PI/180);
00792     addSample(reverse,2, (old_a>0?secondIn:-secondIn)*M_PI/180);
00793     break;
00794   }
00795   cnts[getType()]++;
00796 }
00797 */
00798 
00799 void WalkCalibration::addSample() {
00800   float dx=0, dy=0, da=0;
00801   float dt=(stopTime-startTime)/1000.f;
00802   switch(curType) {
00803   case fs:
00804     if(isPolar) {
00805       dx=firstIn*std::cos(secondIn*(float)M_PI/180)*10/dt;
00806       dy=firstIn*std::sin(secondIn*(float)M_PI/180)*10/dt;
00807     } else {
00808       dx=firstIn*10/dt;
00809       dy=secondIn*10/dt;
00810     }
00811     addSample(data[curType], dx,dy,da);
00812     report(0,old_x,dx);
00813     report(1,old_y,dy);
00814     break;
00815   case fr:
00816     dx=arclen(firstIn*10,secondIn, 1)/dt;
00817     da=(old_a>0?secondIn:-secondIn)*(float)M_PI/180/dt;
00818     addSample(data[curType], dx,dy,da);
00819     report(0,old_x,dx);
00820     report(2,old_a,da);
00821     break;
00822   case sr:
00823     dy=arclen(firstIn*10,secondIn,old_y)/dt;
00824     da=(old_a>0?secondIn:-secondIn)*(float)M_PI/180/dt;
00825     addSample(data[curType], dx,dy,da);
00826     report(1,old_y,dy);
00827     report(2,old_a,da);
00828     break;
00829   case br:
00830     dx=arclen(firstIn*10,secondIn,-1)/dt;
00831     da=(old_a>0?secondIn:-secondIn)*(float)M_PI/180/dt;
00832     addSample(data[curType], dx,dy,da);
00833     report(0,old_x,dx);
00834     report(2,old_a,da);
00835     break;
00836   case bs:
00837     if(isPolar) {
00838       dx=firstIn*cos(secondIn*(float)M_PI/180)*10/dt;
00839       dy=firstIn*sin(secondIn*(float)M_PI/180)*10/dt;
00840     } else {
00841       dx=firstIn*10/dt;
00842       dy=secondIn*10/dt;
00843     }
00844     addSample(data[curType], dx,dy,da);
00845     report(0,old_x,dx);
00846     report(1,old_y,dy);
00847     break;
00848   case r:
00849     da=(old_a>0?secondIn:-secondIn)*(float)M_PI/180/dt;
00850     addSample(data[curType], dx,dy,da);
00851     report(2,old_a,da);
00852     break;
00853   default:
00854     serr->printf("unknown type! %d\n",curType);
00855     return;
00856   }
00857   cnts[curType]++;
00858 }
00859 
00860 void WalkCalibration::report(unsigned int row, float cmd, float actual) {
00861   switch(row) {
00862   case 0:
00863     sout->printf("Forwrd command=%6.4g  Actual=%6.4g\n",cmd,actual); break;
00864   case 1:
00865     sout->printf("Strafe command=%6.4g  Actual=%6.4g\n",cmd,actual); break;
00866   case 2:
00867     sout->printf("Rotate command=%6.4g  Actual=%6.4g\n",cmd,actual); break;
00868   }
00869 }
00870  
00871 void WalkCalibration::err(const std::string& str) {
00872     std::vector<std::string> errmsg;
00873     errmsg.push_back("Error");
00874     errmsg.push_back(str);
00875     serr->printf("%s\n",str.c_str());
00876     Controller::loadGUI("org.tekkotsu.mon.ControllerErr","msg",0,errmsg);
00877     sndman->playFile(config->controller.error_snd);
00878     return;
00879 }
00880 
00881 void WalkCalibration::addSample(std::vector<float*>& dat, float x, float y, float a) {
00882   float * d=new float[6];
00883   dat.push_back(d);
00884   d[0]=x;
00885   d[1]=y;
00886   d[2]=a;
00887   d[3]=old_x;
00888   d[4]=old_y;
00889   d[5]=old_a;
00890 
00891   for(unsigned int i=0; i<6; i++)
00892     cout << d[i] << ' ';
00893   cout << endl;
00894 }
00895   
00896 
00897 /*! @file
00898  * @brief 
00899  * @author ejt (Creator)
00900  */
00901 

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