00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Robots/Beobot2/Navigation/QT_Navigation/QT_Navigation.H"
00039 #include "Ice/BeobotEvents.ice.H"
00040
00041 #include "Raster/Raster.H"
00042 #include "Util/sformat.H"
00043 #include "Image/Image.H"
00044 #include "Image/DrawOps.H"
00045 #include "Image/ColorOps.H"
00046 #include "Image/ShapeOps.H"
00047 #include "Image/MathOps.H"
00048 #include "Image/MatrixOps.H"
00049 #include "Image/CutPaste.H"
00050
00051 #include "Util/Timer.H"
00052
00053 #include "SIFT/Keypoint.H"
00054 #include "SIFT/VisualObject.H"
00055 #include "SIFT/VisualObjectMatch.H"
00056 #include "Transport/FrameInfo.H"
00057
00058 #include "Ice/IceImageUtils.H"
00059
00060 #include "Component/ModelParam.H"
00061 #include "Component/ModelOptionDef.H"
00062
00063
00064 #define TEACH_FOLDER "../data/logs/2010_02_26__18_32_21/image_0000000000"
00065 #define TEACH_START_NUMBER 14363
00066 #define TEACH_END_NUMBER 15038
00067
00068
00069
00070
00071
00072 #define REPLAY_FOLDER "../data/logs/2010_02_26__18_33_26/image_0000000000"
00073 #define REPLAY_START_NUMBER 16298
00074 #define REPLAY_END_NUMBER 17136
00075
00076 #define DFRAME (TEACH_START_NUMBER - REPLAY_START_NUMBER)
00077 #define IMAX 1.0
00078 #define IMIN 0.0
00079
00080 const ModelOptionCateg MOC_QT_Navigation =
00081 { MOC_SORTPRI_3, "QT Navigation Related Options" };
00082 const ModelOptionDef OPT_RealCamera =
00083 { MODOPT_ARG(bool), "RealCamera", &MOC_QT_Navigation, OPTEXP_CORE,
00084 "Do we want use real camera from BeoCamera? Default will load from image files.",
00085 "camera", '\0', "true | false", "false" };
00086
00087
00088 QT_Navigation::QT_Navigation(OptionManager& mgr,
00089 const std::string& descrName, const std::string& tagName) :
00090 RobotBrainComponent(mgr, descrName, tagName),
00091 itsFftComputer(new GistEstimatorFFT(mgr)),
00092 itsOfs(new OutputFrameSeries(mgr)),
00093 itsMapImg(320,240,ZEROS),
00094 itsVisualObjectDB(new VisualObjectDB()),
00095 itsVisualObjectDB2(new VisualObjectDB()),
00096 itsFfn(new FeedForwardNetwork()),
00097 itsTimer(1000000),
00098 itsCurrImgID(-1),
00099 itsPrevProcImgID(-1),
00100 itsTeachImgID(TEACH_START_NUMBER +5 +300),
00101 itsReplayImgID(REPLAY_START_NUMBER +300),
00102 itsTransSpeed(0.0),
00103 itsRotSpeed(0.0),
00104 itsDirVector(0.0),
00105 itsDir(0),
00106 itsMilestoneErr(999.99),
00107 itsFalseErrRate(0.0),
00108 itsDirCount(0),
00109 itsPosition(0.0, 0.0, 0.0),
00110 itsError(0.0, 0.0, 0.0),
00111 itsRealCamera(&OPT_RealCamera, this, 0),
00112 itsEstop(true),
00113 itsReplayDBLoaded(false),
00114 itsIState(0.0),
00115 itsDState(0.0),
00116 itsPGain(1.0),
00117 itsIGain(0.01),
00118 itsDGain(0.0)
00119 {
00120 addSubComponent(itsOfs);
00121
00122
00123 loadDB(sformat("%s.sift",TEACH_FOLDER));
00124 }
00125
00126
00127 void QT_Navigation::loadReplayDB()
00128 {
00129 if(!itsReplayDBLoaded)
00130 {
00131 if(!itsRealCamera.getVal())
00132 {
00133
00134 if(itsVisualObjectDB2->loadFrom
00135 (sformat("%s.sift",REPLAY_FOLDER), false))
00136 LINFO("Load Replay Database");
00137 else
00138 {
00139 LINFO("Can't load database");
00140 saveDB(REPLAY_START_NUMBER,
00141 REPLAY_END_NUMBER,
00142 REPLAY_FOLDER);
00143 }
00144 }
00145 itsReplayDBLoaded = true;
00146 }
00147 }
00148
00149
00150 void QT_Navigation::initFFN()
00151 { }
00152
00153
00154 QT_Navigation::~QT_Navigation()
00155 { }
00156
00157
00158 void QT_Navigation::start1()
00159 { }
00160
00161
00162 void QT_Navigation::registerTopics()
00163 {
00164
00165 this->registerSubscription("CameraMessageTopic");
00166 this->registerSubscription("MotorMessageTopic");
00167 this->registerPublisher("MotorRequestTopic");
00168 }
00169
00170
00171 void QT_Navigation::evolve()
00172 {
00173
00174 if(!itsRealCamera.getVal())
00175 {
00176 navigation();
00177 }
00178
00179
00180 else
00181 {
00182
00183 its_Curr_Img_mutex.lock();
00184 bool newImageFlag = (itsPrevProcImgID < itsCurrImgID);
00185 its_Curr_Img_mutex.unlock();
00186
00187
00188 if(newImageFlag)
00189 {
00190 itsTimer.reset();
00191 its_Curr_Img_mutex.lock();
00192 itsProcImg = itsCurrImg;
00193 itsPrevProcImgID = itsCurrImgID;
00194 its_Curr_Img_mutex.unlock();
00195 navigation();
00196 }
00197 }
00198
00199 drawState();
00200 itsOfs->writeRGB(itsDispImg, "QT_nav", FrameInfo("QT_nav",SRC_POS));
00201 if(itsEstop == false)
00202 {
00203
00204
00205 }
00206 }
00207
00208
00209 void QT_Navigation::recovery()
00210 {
00211 int trytimes = 0;
00212 do{
00213 loadFrame();
00214 std::vector< rutz::shared_ptr<VisualObjectMatch> > matches;
00215 int nmatches =
00216 itsVisualObjectDB->getObjectMatches
00217 (itsReplayVo,matches,VOMA_SIMPLE,
00218 10U,
00219 0.5F,
00220 0.5F,
00221 1.0F,
00222 4U,
00223 100U,
00224 false
00225 );
00226 std::string objName;
00227 int closestFrame = 999999999;
00228 int tmpFrameID = itsTeachImgID;
00229 LINFO("Searching For Nearest Key Frame in the Database");
00230 if (nmatches > 0 )
00231 {
00232 for(int i = 0; i < nmatches; i++)
00233 {
00234 LINFO("Found [%d] frames matches Frame[%d]", nmatches, i);
00235
00236
00237 rutz::shared_ptr<VisualObject> obj;
00238 rutz::shared_ptr<VisualObjectMatch> vom;
00239 vom = matches[i];
00240 obj = vom->getVoTest();
00241
00242
00243
00244
00245 objName = obj->getName();
00246 int tmpID = atoi(objName.c_str());
00247 int dx = tmpID - itsTeachImgID;
00248
00249 LINFO("Dist. from current teach frame[%d]=======new ID[%d]",
00250 dx,tmpID);
00251
00252
00253 if(dx < closestFrame)
00254 {
00255 closestFrame = dx;
00256 tmpFrameID = tmpID;
00257 }
00258 }
00259 LINFO("Recovery Found:TID[%d]RID[%d] Match[%d]",
00260 itsTeachImgID,itsReplayImgID,tmpFrameID);
00261 itsTeachImgID = tmpFrameID;
00262 itsEstop = true;
00263 itsTransSpeed = 0.8;
00264 loadFrame();
00265 computeSIFT();
00266 }
00267 else
00268 {
00269 LINFO("No Match Point,Try get new frame and try again");
00270 loadFrame();
00271 trytimes++;
00272 }
00273 }
00274 while(!itsEstop && trytimes < 10);
00275 }
00276
00277
00278
00279 void QT_Navigation::navigation()
00280 {
00281
00282
00283
00284 loadFrame();
00285
00286
00287
00288 double error = computeDirection2(itsTeachImgID);
00289
00290
00291
00292 if(error != 0.0 && itsMatchList->size()!=0 &&
00293 (itsMatchList->checkSIFTaffine() || itsFalseErrRate > 1.0)
00294 ){
00295 updateMotorPID(itsTransSpeed, itsRotSpeed,error);
00296 updateMotor(itsTransSpeed, itsRotSpeed);
00297 updateKeyframe(error);
00298 itsEstop = true;
00299
00300
00301 updateKeyframe(error);
00302 itsEstop = true;
00303 }
00304
00305
00306
00307 else
00308 {
00309 itsEstop = false;
00310 LINFO("lost matching; start recover mechanism");
00311 itsTransSpeed = 0.0;
00312 itsRotSpeed = 0.0;
00313 updateMotor(itsTransSpeed, itsRotSpeed);
00314
00315
00316
00317 }
00318 }
00319
00320
00321 void QT_Navigation::loadDB(const std::string& path)
00322 {
00323
00324 if(itsVisualObjectDB->loadFrom(path,false))
00325 {
00326 LINFO("Load SIFT Database");
00327 }
00328 else
00329 {
00330 LINFO("SIFT Database %s not exist, create new", path.c_str());
00331 saveDB(TEACH_START_NUMBER,TEACH_END_NUMBER,TEACH_FOLDER);
00332 }
00333 }
00334
00335
00336 void QT_Navigation::saveDB(int start,int end,const std::string& path)
00337 {
00338 itsVisualObjectDB.reset(new VisualObjectDB());
00339 for(int i = start; i < end; i++)
00340 {
00341 itsTimer.reset();
00342 std::string teachFileName(sformat("%s%05d.ppm",path.c_str(),i));
00343 Image< PixRGB<byte> > img = Raster::ReadRGB(teachFileName);
00344 rutz::shared_ptr<VisualObject> vo1
00345 (new VisualObject(sformat("%d",i),
00346 sformat("%s%05d.png",path.c_str(),i),
00347 rescale(img,img.getWidth()/2, img.getHeight()/2)));
00348 itsVisualObjectDB->addObject(vo1);
00349 LINFO("Time[%f] Compute SIFT for Frame %d/%d",
00350 itsTimer.get()/1000.0,i-start+1,end-start+1);
00351 }
00352 std::string teachDB(sformat("%s.sift",path.c_str()));
00353
00354 itsVisualObjectDB->saveTo(teachDB);
00355 }
00356
00357
00358 void QT_Navigation::loadFrame()
00359 {
00360
00361 itsTimer.reset();
00362 std::string teachFileName
00363 (sformat("%s%05d.ppm", TEACH_FOLDER, itsTeachImgID));
00364 itsTeachImg = Raster::ReadRGB(teachFileName);
00365 itsTeachVo = itsVisualObjectDB->getObject
00366 (itsTeachImgID - TEACH_START_NUMBER);
00367 LINFO("Time for Computing SIFT on TeachImg %f",
00368 itsTimer.get()/1000.0);
00369 itsTimer.reset();
00370
00371
00372
00373
00374 if(!itsRealCamera.getVal())
00375 {
00376 loadReplayDB();
00377 std::string replayFileName
00378 (sformat("%s%05d.ppm", REPLAY_FOLDER, itsReplayImgID));
00379 itsReplayImg = Raster::ReadRGB(replayFileName);
00380
00381 itsReplayVo = itsVisualObjectDB2->
00382 getObject(itsReplayImgID - REPLAY_START_NUMBER);
00383 itsReplayImgID++;
00384 }
00385
00386
00387 else
00388 {
00389 itsReplayImg = itsProcImg;
00390 itsReplayImgID = itsPrevProcImgID;
00391
00392
00393
00394
00395
00396
00397
00398
00399 rutz::shared_ptr<VisualObject> vo2
00400 (new VisualObject
00401 ("1", "",
00402 rescale(itsReplayImg,itsReplayImg.getWidth()/2,
00403 itsReplayImg.getHeight()/2)));
00404 itsReplayVo = vo2;
00405 }
00406 LINFO("Time for Computing SIFT on ReplayImg %f",
00407 itsTimer.get()/1000.0);
00408 }
00409
00410
00411 bool QT_Navigation::computeSIFT()
00412 {
00413 itsTimer.reset();
00414 VisualObjectMatchAlgo voma(VOMA_SIMPLE);
00415 itsMatchList.reset(new VisualObjectMatch(itsTeachVo, itsReplayVo, voma));
00416 LINFO("=========================================");
00417
00418
00419
00420
00421 itsMatchList->prune();
00422
00423 LINFO("Match size now is %u ", itsMatchList->size());
00424
00425
00426
00427
00428
00429
00430
00431 if (itsMatchList->checkSIFTaffine() == false)
00432 LINFO("### Affine is too weird -- BOGUS MATCH");
00433
00434
00435 LINFO("Time for Matching SIFT %f",itsTimer.get()/1000.0);
00436
00437
00438 return (itsMatchList->size()!=0 && itsMatchList->checkSIFTaffine());
00439 }
00440
00441
00442 double QT_Navigation::computeDirection2(int teachID)
00443 {
00444 int dirF = 0,dirL = 0,dirR = 0;
00445 rutz::shared_ptr<VisualObjectMatch> bestMatch;
00446 int bestMatchSize = -1;
00447 int bestID = 0;
00448 LINFO("Direction2 Start");
00449
00450
00451 if((teachID-5) < TEACH_START_NUMBER) teachID = TEACH_START_NUMBER+2;
00452
00453
00454 for(int id = teachID-2; id < teachID+10; id++)
00455 {
00456 std::string teachFileName(sformat("%s%05d.ppm",TEACH_FOLDER,id));
00457 rutz::shared_ptr<VisualObject> vo1 =
00458 itsVisualObjectDB->getObject(id - TEACH_START_NUMBER);
00459
00460 VisualObjectMatchAlgo voma(VOMA_SIMPLE);
00461 rutz::shared_ptr<VisualObjectMatch>
00462 match(new VisualObjectMatch(vo1, itsReplayVo, voma));
00463 match->prune();
00464
00465
00466
00467 float theta = 2.0, sx = 2.0, sy = 2.0, str = 0;
00468
00469
00470 if (match->checkSIFTaffine())
00471 {
00472 match->getSIFTaffine().decompose(theta, sx, sy, str);
00473 }
00474 int msize = match->size();
00475 if((msize > bestMatchSize && sx < 1.0 && sy < 1.0) ||
00476 (bestMatchSize == -1 && id==teachID))
00477 {
00478 bestMatchSize = msize;
00479 bestMatch = match;
00480 bestID = id;
00481 }
00482 LINFO("Best Match Size %d,",bestMatchSize);
00483 itsMatchList = bestMatch;
00484
00485 int dirGain = 1; if(id == bestID) dirGain = 2;
00486
00487
00488 for (int i = 0; i < msize; i ++)
00489 {
00490 rutz::shared_ptr<Keypoint> refk = match->getKeypointMatch(i).refkp;
00491 rutz::shared_ptr<Keypoint> tstk = match->getKeypointMatch(i).tstkp;
00492
00493 double ut = tstk->getX() - itsTeachImg.getWidth()/4;
00494 double ud = refk->getX() - itsTeachImg.getWidth()/4;
00495
00496 if(ut > 0.0 && ud < 0.0)
00497 {
00498 dirR += dirGain;
00499 }
00500 else if(ut < 0.0 && ud > 0.0)
00501 {
00502 dirL += dirGain;
00503 }
00504 else if(ut > 0.0 && ut > ud)
00505 {
00506 dirR += dirGain;
00507 }
00508 else if(ut < 0.0 && ut < ud)
00509 {
00510 dirL += dirGain;
00511 }
00512 else
00513 {
00514 dirF +=dirGain;
00515 }
00516 }
00517 }
00518
00519
00520 double stdx = 0.0,stdy = 0.0;
00521 double avgdx = 0.0,avgdy = 0.0;
00522
00523
00524 for (int i = 0; i < bestMatchSize; i ++)
00525 {
00526
00527 rutz::shared_ptr<Keypoint> refk = bestMatch->getKeypointMatch(i).refkp;
00528 rutz::shared_ptr<Keypoint> tstk = bestMatch->getKeypointMatch(i).tstkp;
00529 double dx = fabs(tstk->getX() - refk->getX())+ 0.000001;
00530 stdx += dx * dx;
00531 avgdx+= dx;
00532
00533 double dy = fabs(tstk->getY() - refk->getY())+ 0.000001;
00534 stdy += dy * dy;
00535 avgdy+= dy;
00536 LINFO("Error! i=[%d] BestMatchSize[%d] "
00537 "avgdx[%f] avgdy[%f],dx[%f], dy[%f]",
00538 i,bestMatchSize,avgdx,avgdy,dx,dy);
00539 }
00540 if(bestMatchSize != 0)
00541 {
00542 avgdx/= bestMatchSize;
00543 avgdy/= bestMatchSize;
00544 stdx -= (avgdx*avgdx);
00545 stdy -= (avgdy*avgdy);
00546 stdx /= bestMatchSize;
00547 stdx = sqrt(stdx);
00548 stdy /= bestMatchSize;
00549 stdy = sqrt(stdy);
00550 LINFO("Error! BestMatchSize[%d] avgdx[%f] avgdy[%f]",
00551 bestMatchSize,avgdx,avgdy);
00552 }
00553 else
00554 {
00555 avgdx = 0;
00556 avgdy = 0;
00557 stdx = 0;
00558 stdy = 0;
00559 }
00560
00561 LINFO("stdx %f stdy %f",stdx,stdy);
00562 uint stdcount = 0;
00563 double newAvgX = 0.0,newAvgY = 0.0;
00564
00565
00566 for (int i = 0; i < bestMatchSize; i ++)
00567 {
00568 rutz::shared_ptr<Keypoint> refk = bestMatch->getKeypointMatch(i).refkp;
00569 rutz::shared_ptr<Keypoint> tstk = bestMatch->getKeypointMatch(i).tstkp;
00570 double dx = fabs(tstk->getX() - refk->getX())+ 0.000001;
00571 double dy = fabs(tstk->getY() - refk->getY())+ 0.000001 ;
00572 double ddx = fabs(dx - avgdx);
00573 double ddy = fabs(dy - avgdy);
00574
00575 if(ddx < stdx && ddy < stdy)
00576 {
00577 newAvgX += dx;
00578 newAvgY += dy;
00579 stdcount++;
00580 }
00581 }
00582
00583 if(stdcount != 0)
00584 {
00585 newAvgX/= stdcount;
00586 newAvgY/= stdcount;
00587 }
00588 double newAvgerr = sqrt(newAvgX*newAvgX + newAvgY*newAvgY);
00589 double avgerr = sqrt(avgdx*avgdx + avgdy*avgdy);
00590 double angle = (newAvgX*(16.0/33.0));
00591 itsError.x = newAvgX;
00592 itsError.y = newAvgY;
00593 itsError.z = newAvgerr;
00594
00595 if(newAvgerr == 0.0)
00596 {
00597
00598 newAvgerr = avgerr;
00599 itsFalseErrRate = 0;
00600 }
00601 else
00602 {
00603 itsFalseErrRate = avgerr/newAvgerr;
00604 }
00605 LINFO("False Error Rate %1.3f",itsFalseErrRate);
00606 if(itsFalseErrRate == 0.0)
00607 {
00608 LINFO("Error!!!! stdcount[%d] avgerr[%f]",
00609 stdcount,avgerr);
00610 LINFO("Error!!!! bestMatchSize[%d] stdx[%f] stdy[%f]",
00611 bestMatchSize,stdx,stdy);
00612
00613 }
00614
00615
00616 if(bestID > itsTeachImgID && newAvgerr < 10.0)
00617 itsTeachImgID = bestID;
00618
00619
00620 if (bestMatch->checkSIFTaffine())
00621 {
00622 float theta = 0.0 , sx = 0.0, sy = 0.0, str = 0.0 ;
00623 bestMatch->getSIFTaffine().decompose(theta, sx, sy, str);
00624
00625 double rms = 1.0 -(sqrt(sx*sx+sy*sy)/sqrt(2));
00626
00627 double gain = 1.0;
00628 if(rms > 0.0)
00629 itsTransSpeed = 0.8 + rms * gain;
00630 if(itsTransSpeed > 1.0)itsTransSpeed = 1.0;
00631 if(itsTransSpeed < 0.0)itsTransSpeed = 0.0;
00632 }
00633 else
00634 {
00635 itsTransSpeed = 0.8;
00636 }
00637
00638
00639 if(dirF >= abs(dirR + dirL))
00640 {
00641 updatePosition(0);
00642 itsRotSpeed = 0.4;
00643 if(itsDir == 0)
00644 {
00645 itsDirCount++;
00646 }
00647 else
00648 {
00649 itsDirCount = 0;
00650 itsDir = 0;
00651 }
00652 }
00653 else if(dirR > dirL)
00654 {
00655 updatePosition(angle);
00656
00657 itsRotSpeed -= newAvgX/100.0;
00658 itsRotSpeed /= 2.0;
00659 if(itsDir == 1)
00660 {
00661 itsDirCount++;
00662 }
00663 else
00664 {
00665 itsDirCount = 0;
00666 itsDir = 1;
00667 }
00668 }
00669 else
00670 {
00671 updatePosition(-1*angle);
00672
00673 itsRotSpeed += newAvgX/100.0+1.0;
00674 itsRotSpeed /= 2.0;
00675 if(itsDir == -1)
00676 {
00677 itsDirCount++;
00678 }else{
00679 itsDirCount = 0;
00680 itsDir = -1;
00681 }
00682 }
00683 return newAvgerr;
00684 }
00685
00686
00687 double QT_Navigation::computeDirection()
00688 {
00689 itsTimer.reset();
00690 int dirF = 0,dirL = 0,dirR = 0;
00691 double avgdx = 0.0,avgdy = 0.0;
00692 uint msize = itsMatchList->size();
00693
00694
00695 for (uint i = 0; i < msize; i ++)
00696 {
00697 rutz::shared_ptr<Keypoint> refk =
00698 itsMatchList->getKeypointMatch(i).refkp;
00699 rutz::shared_ptr<Keypoint> tstk =
00700 itsMatchList->getKeypointMatch(i).tstkp;
00701
00702 double ut = tstk->getX() - itsTeachImg.getWidth()/4;
00703 double ud = refk->getX() - itsTeachImg.getWidth()/4;
00704 double dx = fabs(ut - ud);
00705 double dy = fabs(tstk->getY() - refk->getY());
00706 avgdx += dx;
00707 avgdy += dy;
00708 std::string dir;
00709
00710 if(ut > 0.0 && ud < 0.0)
00711 {
00712 dir = std::string("RIGHT");
00713 dirR ++;
00714 }
00715 else if(ut < 0.0 && ud > 0.0)
00716 {
00717 dir = std::string("LEFT");
00718 dirL ++;
00719 }
00720 else if(ut > 0.0 && ut > ud )
00721 {
00722 dir = std::string("RIGHT");
00723 dirR ++;
00724 }
00725 else if(ut < 0.0 && ut < ud)
00726 {
00727 dir = std::string("LEFT");
00728 dirL ++;
00729 }
00730 else
00731 {
00732 dir = std::string("Forward");
00733 dirF ++;
00734 }
00735 LDEBUG("MatchPoint[%d] Teach(%f,%f) Replay(%f,%f), "
00736 "ud:[%f],ut:[%f],dx:[%f],dy:[%f] Turn %s",
00737 i,
00738 (refk->getX()),
00739 (refk->getY()),
00740 (tstk->getX()),
00741 (tstk->getY()),
00742 ud,ut,dx,dy,dir.c_str()
00743 );
00744 }
00745 avgdx/= msize;
00746 avgdy/= msize;
00747 double stdx = 0.0,stdy = 0.0;
00748
00749
00750 for (uint i = 0; i < msize; i ++)
00751 {
00752 rutz::shared_ptr<Keypoint> refk =
00753 itsMatchList->getKeypointMatch(i).refkp;
00754 rutz::shared_ptr<Keypoint> tstk =
00755 itsMatchList->getKeypointMatch(i).tstkp;
00756 double ddx = fabs(tstk->getX() - refk->getX()) - avgdx;
00757 stdx += ddx * ddx;
00758 double ddy = fabs(tstk->getY() - refk->getY()) - avgdy;
00759 stdy += ddy * ddy;
00760 }
00761 stdx /= msize;
00762
00763 stdy /= msize;
00764
00765 uint stdcount = 0;
00766 double newAvgX = 0.0,newAvgY = 0.0;
00767
00768
00769 for (uint i = 0; i < msize; i ++)
00770 {
00771 rutz::shared_ptr<Keypoint> refk =
00772 itsMatchList->getKeypointMatch(i).refkp;
00773 rutz::shared_ptr<Keypoint> tstk =
00774 itsMatchList->getKeypointMatch(i).tstkp;
00775 double dx = fabs(tstk->getX() - refk->getX()) ;
00776 double dy = fabs(tstk->getY() - refk->getY()) ;
00777 double ddx = fabs(dx - avgdx);
00778 double ddy = fabs(dy - avgdy);
00779
00780 if(ddx < sqrt(stdx) && ddy < sqrt(stdy))
00781 {
00782 newAvgX += dx;
00783 newAvgY += dy;
00784 stdcount++;
00785 }
00786 }
00787 if(stdcount != 0)
00788 {
00789 newAvgX/=stdcount;
00790 newAvgY/=stdcount;
00791 }
00792
00793 double stdeverr = sqrt(stdx+stdy);
00794 double avgerr = sqrt(avgdx*avgdx + avgdy*avgdy);
00795 double newAvgerr = sqrt(newAvgX*newAvgX + newAvgY*newAvgY);
00796 double df = DFRAME - (itsTeachImgID - itsReplayImgID );
00797 double angle = (newAvgX*(56.0/33.0))/df;
00798
00799 LINFO("StdError[%f],StdErrX[%f],StdErrY[%f],Frame[%1.0f]",
00800 stdeverr,sqrt(stdx),sqrt(stdy),df);
00801 LINFO("AvgErr[%f],AvgX[%f],AvgY[%f]",avgerr,avgdx,avgdy);
00802 LINFO("StdAvgErr[%f],StdAvgX[%f],StdAvgY[%f]",newAvgerr,newAvgX,newAvgY);
00803 LINFO("Forward[%d], Right[%d], Left[%d] Angle[%f]",dirF,dirR,dirL,angle);
00804 itsError.x = newAvgX;
00805 itsError.y = newAvgY;
00806 itsError.z = newAvgerr;
00807
00808 if(newAvgerr == 0.0)
00809 {
00810
00811 newAvgerr = avgerr;
00812 }
00813
00814 itsFalseErrRate = avgerr/newAvgerr;
00815
00816 LINFO("Time for QT Navigation %f",itsTimer.get()/1000.0);
00817 return newAvgerr;
00818 }
00819
00820
00821 void QT_Navigation::updateKeyframe(double error)
00822 {
00823 LINFO("itsMerror %f,new error %f", itsMilestoneErr, error);
00824
00825
00826 if (itsMatchList->checkSIFTaffine())
00827 {
00828 float theta, sx, sy, str;
00829 itsMatchList->getSIFTaffine().decompose(theta, sx, sy, str);
00830 LINFO("SIFT SCALE SX[%f] SY[%f] Theta[%f] Str[%f]",sx,sy,theta,str);
00831
00832
00833
00834
00835
00836
00837
00838 if(((sx >=0.9 && sy >=0.9) && error <50.0 ) && itsMatchList->size()>2){
00839 itsMilestoneErr = 999.99;
00840 itsTeachImgID += 20;
00841 LINFO("*********=========Switch Keyframe=========**********");
00842 }
00843
00844 }
00845 }
00846
00847
00848
00849
00850 int QT_Navigation::computeEntropy()
00851 {
00852 return 1;
00853 }
00854
00855
00856 void QT_Navigation::drawState()
00857 {
00858 uint w = 320, h = 240;
00859
00860 itsDispImg.resize(w*2, 3*h, NO_INIT);
00861
00862 inplacePaste(itsDispImg, itsProcImg, Point2D<int>(0, 0));
00863
00864 its_Curr_Img_mutex.lock();
00865 bool newImageFlag = (itsPrevProcImgID < itsCurrImgID);
00866 its_Curr_Img_mutex.unlock();
00867 if(!itsRealCamera.getVal() || newImageFlag){
00868 char buffer[128];
00869 sprintf(buffer,"img%5d",itsTeachImgID);
00870 Image< PixRGB<byte> > tmpImg = itsTeachImg;
00871 writeText(tmpImg, Point2D<int>(5,5),
00872 buffer, PixRGB<byte>(255,255,255),
00873 PixRGB<byte>(0,0,0), SimpleFont::FIXED(8));
00874 inplacePaste(itsDispImg, tmpImg, Point2D<int>(0, h));
00875
00876
00877
00878
00879 tmpImg = itsReplayImg;
00880
00881
00882
00883 sprintf(buffer,"img%5d",itsReplayImgID);
00884 writeText(itsReplayImg, Point2D<int>(5,5),
00885 buffer, PixRGB<byte>(255,255,255),
00886 PixRGB<byte>(0,0,0),SimpleFont::FIXED(8));
00887
00888 inplacePaste(itsDispImg, tmpImg, Point2D<int>(0, 2*h));
00889 inplacePaste(itsDispImg, itsTeachVo->getKeypointImage(1.0) ,
00890 Point2D<int>(w, h));
00891 inplacePaste(itsDispImg, itsReplayVo->getKeypointImage(1.0),
00892 Point2D<int>(w, h*1.5));
00893 if(itsEstop)
00894 {
00895 Image< PixRGB<byte> > mimg = itsMatchList->getMatchImage(1.0F);
00896 inplacePaste(itsDispImg, mimg, Point2D<int>(w*1.5, h));
00897 }
00898 double mapScale = 0.20;
00899 Point2D<int> drawPos
00900 (int(itsPosition.x*mapScale + itsMapImg.getWidth()/2),
00901 int(itsPosition.y*mapScale + itsMapImg.getHeight()/2));
00902 if(itsMapImg.coordsOk(drawPos))
00903 itsMapImg.setVal(drawPos, PixRGB<byte>(0,255,0));
00904 inplacePaste(itsDispImg, itsMapImg, Point2D<int>(w, h*2));
00905 inplacePaste(itsDispImg, drawInfoImg(), Point2D<int>(w, 0));
00906 }
00907 }
00908
00909
00910
00911 Image<PixRGB<byte> > QT_Navigation::drawInfoImg()
00912 {
00913 char buffer[128];
00914 Image<PixRGB<byte> > dirImg(320,240,ZEROS);
00915
00916 if(itsDir == 0)
00917 {
00918 sprintf(buffer, "|||");
00919 }
00920 else if(itsDir > 0)
00921 {
00922 sprintf(buffer, "--> ");
00923 }
00924 else
00925 {
00926 sprintf(buffer, "<-- ");
00927 }
00928 writeText(dirImg, Point2D<int>(dirImg.getWidth()/2-20,
00929 dirImg.getHeight()/2-20),
00930 buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
00931 SimpleFont::FIXED(20));
00932
00933 sprintf(buffer, "[%d]",itsDirCount);
00934 writeText(dirImg, Point2D<int>(dirImg.getWidth()/2-10,
00935 dirImg.getHeight()/2+40),
00936 buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
00937 SimpleFont::FIXED(20));
00938
00939 sprintf(buffer, "False Error Rate:[%1.3f]",itsFalseErrRate);
00940 writeText(dirImg, Point2D<int>(10,10),
00941 buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
00942 SimpleFont::FIXED(8));
00943 if(itsEstop)
00944 {
00945 sprintf(buffer, "Match:[%d]",itsMatchList->size());
00946 writeText(dirImg, Point2D<int>(210,10),
00947 buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
00948 SimpleFont::FIXED(8));
00949 }
00950 sprintf(buffer, "Error:[%1.3f] X:[%1.3f] Y:[%1.3f]",
00951 itsError.z,itsError.x,itsError.y);
00952 writeText(dirImg, Point2D<int>(10,25),
00953 buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
00954 SimpleFont::FIXED(8));
00955
00956
00957 if (itsEstop && itsMatchList->checkSIFTaffine())
00958 {
00959 float theta, sx, sy, str;
00960 itsMatchList->getSIFTaffine().decompose(theta, sx, sy, str);
00961 sprintf(buffer, "Affine T:[%1.3f] X:[%1.3f] Y:[%1.3f]",theta,sx,sy);
00962 writeText(dirImg, Point2D<int>(10,40),
00963 buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
00964 SimpleFont::FIXED(8));
00965 }
00966 sprintf(buffer, "Motor Speed :[%1.3f] Motor Rot:[%1.3f]",
00967 itsTransSpeed, itsRotSpeed);
00968 writeText(dirImg, Point2D<int>(10,55),
00969 buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
00970 SimpleFont::FIXED(8));
00971 return dirImg;
00972 }
00973
00974
00975 void QT_Navigation::updatePosition(double turn)
00976 {
00977 itsDirVector += turn;
00978 if(itsDirVector > 360.0) itsDirVector = 0.0;
00979 if(itsDirVector < 0.0) itsDirVector = 360.0;
00980
00981 itsPosition.x -= sin(itsDirVector*(M_PI/180.0));
00982 itsPosition.y -= cos(itsDirVector*(M_PI/180.0));
00983 }
00984
00985
00986 void QT_Navigation::updateMessage
00987 (const RobotSimEvents::EventMessagePtr& eMsg, const Ice::Current&)
00988 {
00989
00990 if(eMsg->ice_isA("::BeobotEvents::CameraMessage"))
00991 {
00992
00993 BeobotEvents::CameraMessagePtr cameraMsg =
00994 BeobotEvents::CameraMessagePtr::dynamicCast(eMsg);
00995
00996 int currRequestID = cameraMsg->RequestID;
00997 Image<PixRGB<byte> > img = Ice2Image<PixRGB<byte> >(cameraMsg->image);
00998
00999 LDEBUG("Got a CameraMessage with Request ID = %d", currRequestID);
01000
01001 its_Curr_Img_mutex.lock();
01002 itsCurrImg = img;
01003 itsCurrImgID = cameraMsg->RequestID;
01004 its_Curr_Img_mutex.unlock();
01005 }
01006
01007
01008 else if(eMsg->ice_isA("::BeobotEvents::MotorMessage"))
01009 {
01010 BeobotEvents::MotorMessagePtr mtrMsg =
01011 BeobotEvents::MotorMessagePtr::dynamicCast(eMsg);
01012 LDEBUG("Got a MotorMessage with Request ID = %d: RC Trans %f, Rot %f",
01013 mtrMsg->RequestID, itsRcTransSpeed, itsRcRotSpeed);
01014 its_Curr_Mtr_mutex.lock();
01015 itsRemoteMode = mtrMsg->rcMode;
01016 itsRcTransSpeed = mtrMsg->rcTransVel;
01017 itsRcRotSpeed = mtrMsg->rcRotVel;
01018 its_Curr_Mtr_mutex.unlock();
01019 }
01020
01021 }
01022
01023
01024 void QT_Navigation::updateMotorPID(double tran, double rot,double error)
01025 {
01026 error/=100.0;
01027 if(itsDir == 1)
01028 error *= -1.0;
01029 double pTerm,iTerm,dTerm;
01030 pTerm = itsPGain * error;
01031 itsIState += error;
01032 if(itsIState > IMAX)
01033 itsIState = IMAX;
01034 else if(itsIState < IMIN)
01035 itsIState = IMIN;
01036 iTerm = itsIGain * itsIState;
01037 dTerm = itsDGain * (rot - itsDState);
01038 itsDState = rot;
01039 double pid = pTerm + iTerm - dTerm;
01040
01041 LINFO("P[%1.2f] I[%1.2f] D[%1.2f], Istate[%1.2f] DState[%1.2f]",
01042 pTerm,iTerm,dTerm,itsIState,itsDState);
01043 LINFO("pid[%1.2f],rot[%1.2f]",pid,rot);
01044 updateMotor(tran,pid);
01045 }
01046
01047
01048 void QT_Navigation::updateMotor(double tran, double rot)
01049 {
01050 BeobotEvents::MotorRequestPtr msg = new BeobotEvents::MotorRequest;
01051 msg->transVel = tran;
01052 msg->rotVel = rot;
01053 this->publish("MotorRequestTopic", msg);
01054 LINFO("[%d] Publish motor request Trans %f Rotation %f",
01055 itsPrevProcImgID,tran,rot);
01056 }
01057
01058
01059
01060
01061
01062