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)
00743 return (sign<0)?-fabs(d):fabs(d);
00744
00745 a*=(float)M_PI/180;
00746
00747 float radius=fabs(d/2/sin(a/2));
00748
00749 if(sign<0)
00750 return -a*radius;
00751 return a*radius;
00752 }
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
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
00898
00899
00900
00901