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/GistSal_Navigation/GistSal_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 #define IMAX 1.0
00064 #define IMIN 0.0
00065 #define LOST_TIME_LIMIT 6500000
00066 #define ROT_TIME_LIMIT 3000000
00067 #define JUNCTION_START_DIST 8.0
00068 #define REVERSE_COUNT_MAX 10
00069 #define INVALID_ANGLE -100.0
00070 #define INVALID_DISTANCE -200.0
00071
00072 #define C_PROCEDURE_INACTIVE 0
00073 #define C_PROCEDURE_ACTIVE 1
00074 #define C_PROCEDURE_CONCLUDING 2
00075
00076
00077 GistSal_Navigation::GistSal_Navigation(OptionManager& mgr,
00078 const std::string& descrName,
00079 const std::string& tagName)
00080 :
00081 RobotBrainComponent(mgr, descrName, tagName),
00082 itsOfs(new OutputFrameSeries(mgr)),
00083 itsTimer(1000000),
00084 itsCurrImgID(-1),
00085 itsPrevProcImgID(-1),
00086 itsTransSpeed(0.0),
00087 itsRotSpeed(0.0),
00088 itsDir(0),
00089 itsIState(0.0),
00090 itsDState(0.0),
00091 itsPGain(1.0),
00092 itsIGain(0.01),
00093 itsDGain(0.0),
00094 itsReverseCount(0),
00095 itsReverseDir(false),
00096 itsDistToGoal(-1.0),
00097 itsLastFoundTimer(1000000),
00098 itsSearchTracker(new SalientRegionTracker(mgr)),
00099 itsNewMovementTracker(new SalientRegionTracker(mgr)),
00100 itsCurrMovementTracker(new SalientRegionTracker(mgr))
00101 {
00102 addSubComponent(itsOfs);
00103
00104
00105 addSubComponent(itsSearchTracker);
00106 addSubComponent(itsNewMovementTracker);
00107 addSubComponent(itsCurrMovementTracker);
00108 itsResetSearchTracker = true;
00109
00110
00111
00112 itsTurnAngle = 0.0;
00113 itsJunctionDist = -1.0;
00114 itsLastFoundTimer.reset();
00115
00116
00117 itsDesiredSegmentLocation = 3;
00118 itsDesiredSegmentLengthTraveled = 0.95;
00119 itsInGoal = false;
00120
00121
00122 itsCurrentSegmentLocation = 0;
00123 itsCurrentSegmentLengthTraveled = 0.0;
00124
00125 itsCornerProcStatus = C_PROCEDURE_INACTIVE;
00126 }
00127
00128
00129 void GistSal_Navigation::setEnvironment
00130 (rutz::shared_ptr<Environment> env)
00131 {
00132 itsEnvironment = env;
00133
00134
00135 itsTopologicalMap = env->getTopologicalMap();
00136
00137
00138 itsLandmarkDB = env->getLandmarkDB();
00139 }
00140
00141
00142 GistSal_Navigation::~GistSal_Navigation()
00143 { }
00144
00145
00146 void GistSal_Navigation::start1()
00147 { }
00148
00149
00150 void GistSal_Navigation::registerTopics()
00151 {
00152
00153 this->registerSubscription("LandmarkTrackMessageTopic");
00154 this->registerSubscription("LandmarkDBSearchResultMessageTopic");
00155 this->registerSubscription("CurrentLocationMessageTopic");
00156 this->registerSubscription("MotorMessageTopic");
00157 this->registerSubscription("CornerMotorRequestTopic");
00158
00159 this->registerPublisher("CornerLocationMessageTopic");
00160 this->registerPublisher("MotorRequestTopic");
00161 }
00162
00163
00164 void GistSal_Navigation::updateMessage
00165 (const RobotSimEvents::EventMessagePtr& eMsg, const Ice::Current&)
00166 {
00167 Timer timer(1000000);
00168
00169
00170 if(eMsg->ice_isA("::BeobotEvents::LandmarkTrackMessage"))
00171 {
00172
00173 BeobotEvents::LandmarkTrackMessagePtr lTrackMsg =
00174 BeobotEvents::LandmarkTrackMessagePtr::dynamicCast(eMsg);
00175
00176 int currRequestID = lTrackMsg->RequestID;
00177 Image<PixRGB<byte> > img = Ice2Image<PixRGB<byte> >(lTrackMsg->currIma);
00178
00179 LINFO("Got an lTrackMessage with Request ID = %d", currRequestID);
00180
00181
00182 its_input_mutex.lock();
00183 itsCurrImg = img;
00184 itsCurrImgID = currRequestID;
00185
00186
00187 uint inputSize = lTrackMsg->salientRegions.size();
00188 itsCurrSalPoints.clear();
00189 itsCurrSalRects.clear();
00190 for(uint i = 0; i < inputSize; i++)
00191 {
00192 BeobotEvents::SalientRegion salReg = lTrackMsg->salientRegions[i];
00193 LINFO("M[%4d] sp[%4d,%4d] rect[%4d,%4d,%4d,%4d]",
00194 i, salReg.salpt.i, salReg.salpt.j,
00195 salReg.objRect.tl.i, salReg.objRect.tl.j,
00196 salReg.objRect.br.i, salReg.objRect.br.j);
00197
00198 Point2D<int> salpt(salReg.salpt.i, salReg.salpt.j);
00199 itsCurrSalPoints.push_back(salpt);
00200
00201 Rectangle rect = Rectangle::tlbrO
00202 (salReg.objRect.tl.j, salReg.objRect.tl.i,
00203 salReg.objRect.br.j, salReg.objRect.br.i);
00204 itsCurrSalRects.push_back(rect);
00205 }
00206
00207
00208 itsCurrCmap.clear();
00209 itsCurrCmap.reset(NUM_CHANNELS);
00210 for(uint i = 0; i < NUM_CHANNELS; i++)
00211 itsCurrCmap[i] = Ice2Image<float>(lTrackMsg->conspicuityMaps[i]);
00212
00213 its_input_mutex.unlock();
00214
00215 LINFO("[input time: %f ms]\n\n", timer.get()/1000.0f);
00216 }
00217
00218
00219 else if(eMsg->ice_isA("::BeobotEvents::LandmarkDBSearchResultMessage"))
00220 {
00221 BeobotEvents::LandmarkDBSearchResultMessagePtr dbrMsg =
00222 BeobotEvents::LandmarkDBSearchResultMessagePtr::dynamicCast(eMsg);
00223
00224 int currRequestID = dbrMsg->RequestID;
00225
00226 LINFO("Got a LandmarkDBSearchResultMessage with Request ID = %d",
00227 currRequestID);
00228
00229 its_tracker_mutex.lock();
00230 its_Curr_Dbr_mutex.lock();
00231 itsCurrImgID = currRequestID;
00232
00233
00234 uint numRecognized = dbrMsg->matches.size();
00235
00236
00237 if(numRecognized > 0)
00238 {
00239 uint mIndex = dbrMsg->matches[numRecognized - 1].inputSalRegID;
00240 if(mIndex >= itsSearchTracker->getNumTrackedPoints())
00241 {
00242 LINFO("\n\n\nASYNCHRONIZATION HAS OCCURED: %d %d\n\n",
00243 mIndex, itsSearchTracker->getNumTrackedPoints());
00244 numRecognized = 0;
00245
00246
00247 }
00248 }
00249
00250
00251 if(numRecognized > 0)
00252 {
00253 itsNewMovementTracker->clear();
00254
00255 itsNewMovementTracker->reset(numRecognized);
00256 itsNewMovementTracker->setCurrInputImage
00257 (itsSearchTracker->getCurrInputImage());
00258 itsNewMovementTracker->setOriginalInputImage
00259 (itsSearchTracker->getOriginalInputImage());
00260
00261
00262 itsNewLandmarkDBMatches.clear();
00263 for(uint i = 0; i < dbrMsg->matches.size(); i++)
00264 {
00265 uint index = dbrMsg->matches[i].inputSalRegID;
00266 itsNewMovementTracker->move(itsSearchTracker, index);
00267
00268
00269
00270 rutz::shared_ptr<LandmarkDBMatch> ldbm(new LandmarkDBMatch());
00271 GSlocJobData dbmi(index,
00272 dbrMsg->matches[i].dbSegNum,
00273 dbrMsg->matches[i].dbLmkNum,
00274 dbrMsg->matches[i].dbVOStart,
00275 dbrMsg->matches[i].dbVOEnd);
00276 ldbm->dbi = dbmi;
00277 itsNewLandmarkDBMatches.push_back(ldbm);
00278
00279 LINFO("DB Match sent: %d: (%d %d - %d %d)",
00280 itsNewLandmarkDBMatches[i]->dbi.objNum,
00281 itsNewLandmarkDBMatches[i]->dbi.segNum,
00282 itsNewLandmarkDBMatches[i]->dbi.lmkNum,
00283 itsNewLandmarkDBMatches[i]->dbi.voStartNum,
00284 itsNewLandmarkDBMatches[i]->dbi.voEndNum);
00285 }
00286 }
00287
00288
00289 itsResetSearchTracker = true;
00290
00291 its_Curr_Dbr_mutex.unlock();
00292 its_tracker_mutex.unlock();
00293 LINFO("Found %d new landmarks in %f ms \n\n",
00294 numRecognized, timer.get()/1000.0f);
00295 }
00296
00297
00298 else if(eMsg->ice_isA("::BeobotEvents::CurrentLocationMessage"))
00299 {
00300 BeobotEvents::CurrentLocationMessagePtr clMsg =
00301 BeobotEvents::CurrentLocationMessagePtr::dynamicCast(eMsg);
00302 LDEBUG("Got a CurrentLocationMessage with Request ID = %d"
00303 ": loc(%d, %f)",
00304 clMsg->RequestID, clMsg->segNum, clMsg->lenTrav);
00305 its_Curr_Loc_mutex.lock();
00306 itsCurrentSegmentLocation = clMsg->segNum;
00307 itsCurrentSegmentLengthTraveled = clMsg->lenTrav;
00308 its_Curr_Loc_mutex.unlock();
00309 }
00310
00311
00312 else if(eMsg->ice_isA("::BeobotEvents::MotorMessage"))
00313 {
00314 BeobotEvents::MotorMessagePtr mtrMsg =
00315 BeobotEvents::MotorMessagePtr::dynamicCast(eMsg);
00316 its_Curr_Mtr_mutex.lock();
00317 itsRemoteMode = mtrMsg->rcMode;
00318 itsRcTransSpeed = mtrMsg->rcTransVel;
00319 itsRcRotSpeed = mtrMsg->rcRotVel;
00320 its_Curr_Mtr_mutex.unlock();
00321
00322 LDEBUG("Got a MotorMessage with Request ID = %d: RC Trans %f, Rot %f",
00323 mtrMsg->RequestID, itsRcTransSpeed, itsRcRotSpeed);
00324 }
00325
00326
00327 else if(eMsg->ice_isA("::BeobotEvents::CornerMotorRequest"))
00328 {
00329 BeobotEvents::CornerMotorRequestPtr cmtrMsg =
00330 BeobotEvents::CornerMotorRequestPtr::dynamicCast(eMsg);
00331
00332 its_Curr_CornerMtr_mutex.lock();
00333 itsCornerTransSpeed = cmtrMsg->transVel;
00334 itsCornerRotSpeed = cmtrMsg->rotVel;
00335
00336 if(cmtrMsg->status == C_PROCEDURE_INACTIVE)
00337 itsCornerProcStatus = C_PROCEDURE_INACTIVE;
00338 else if(cmtrMsg->status == C_PROCEDURE_ACTIVE)
00339 itsCornerProcStatus = C_PROCEDURE_ACTIVE;
00340 else if(cmtrMsg->status == C_PROCEDURE_CONCLUDING)
00341 itsCornerProcStatus = C_PROCEDURE_CONCLUDING;
00342
00343 its_Curr_CornerMtr_mutex.unlock();
00344 LINFO("Got a CornerMotorRequest Trans %f, Rot %f",
00345 itsCornerTransSpeed, itsCornerRotSpeed);
00346 }
00347 }
00348
00349
00350 void GistSal_Navigation::evolve()
00351 {
00352
00353 its_input_mutex.lock();
00354 bool newInputFlag = (itsPrevProcImgID < itsCurrImgID);
00355 its_input_mutex.unlock();
00356
00357
00358 if(newInputFlag)
00359 {
00360 itsTimer.reset();
00361
00362 its_tracker_mutex.lock();
00363 its_Curr_Dbr_mutex.lock();
00364 its_Curr_CornerMtr_mutex.lock();
00365
00366 its_input_mutex.lock();
00367 itsProcImg = itsCurrImg;
00368 itsPrevProcImgID = itsCurrImgID;
00369 std::vector<Point2D<int> > salPoints = itsCurrSalPoints;
00370 ImageSet<float> cmap = itsCurrCmap;
00371 std::vector<Rectangle> rects = itsCurrSalRects;
00372 its_input_mutex.unlock();
00373
00374
00375 LINFO("\n search tracker: reset: %d ", itsResetSearchTracker);
00376
00377 std::vector<rutz::shared_ptr<VisualObject> > fakeVO;
00378 itsSearchTracker->input
00379 (itsProcImg, cmap, itsResetSearchTracker,
00380 salPoints, rects, fakeVO);
00381 LINFO("\n movement tracker");
00382 itsCurrMovementTracker->input
00383 (itsProcImg, cmap, false,
00384 salPoints, rects, fakeVO);
00385 itsNewMovementTracker->input
00386 (itsProcImg, cmap, false,
00387 salPoints, rects, fakeVO);
00388
00389
00390 itsResetSearchTracker = false;
00391
00392
00393
00394
00395 bool nearJunction = estimateProgressToDestination();
00396
00397
00398
00399
00400 if(nearJunction &&
00401 itsCornerProcStatus == C_PROCEDURE_INACTIVE)
00402 {
00403
00404
00405 BeobotEvents::CornerLocationMessagePtr msg =
00406 new BeobotEvents::CornerLocationMessage;
00407 msg->cornerLocation = itsCurrentSegmentLocation;
00408 this->publish("CornerLocationMessageTopic", msg);
00409 LINFO("Publishing corner location %d", msg->cornerLocation);
00410 }
00411
00412
00413 if(itsCornerProcStatus == C_PROCEDURE_ACTIVE)
00414 {
00415 itsTransSpeed = itsCornerTransSpeed;
00416 itsRotSpeed = itsCornerRotSpeed;
00417
00418 itsLastFoundTimer.reset();
00419 }
00420
00421 if(itsCornerProcStatus == C_PROCEDURE_CONCLUDING ||
00422 itsCornerProcStatus == C_PROCEDURE_INACTIVE )
00423 {
00424
00425 uint64 kpst = itsTimer.get();
00426 bool foundSomething = (getKeypointMatches() != 0);
00427
00428
00429 LINFO("[KP time: %f]\n\n", (itsTimer.get() - kpst)/1000.0f);
00430 if(itsCurrLandmarkDBMatches.size() != 0)
00431 {
00432
00433 computeErrorDifference();
00434
00435
00436 itsLastFoundTimer.reset();
00437 itsReverseCount = 0;
00438
00439
00440 itsCornerProcStatus = C_PROCEDURE_INACTIVE;
00441 }
00442 else
00443 {
00444 if(itsCornerProcStatus == C_PROCEDURE_CONCLUDING)
00445 {
00446 itsTransSpeed = itsCornerTransSpeed;
00447 itsRotSpeed = itsCornerRotSpeed;
00448
00449 itsLastFoundTimer.reset();
00450 }
00451 else
00452 {
00453
00454 itsTransSpeed = 0.6;
00455
00456
00457
00458
00459
00460
00461
00462
00463 }
00464 }
00465
00466
00467 if(itsLastFoundTimer.get() > LOST_TIME_LIMIT)
00468 recover(foundSomething);
00469 }
00470
00471
00472 navigation();
00473
00474 its_Curr_CornerMtr_mutex.unlock();
00475 its_Curr_Dbr_mutex.unlock();
00476 its_tracker_mutex.unlock();
00477
00478
00479 drawState();
00480 itsOfs->writeRGB(itsDispImg, " ><\" GistSal_nav",
00481 FrameInfo("GistSal_nav",SRC_POS));
00482
00483 LINFO("[time: %f]\n\n\n\n", itsTimer.get()/1000.0f);
00484 }
00485 }
00486
00487
00488
00489 uint GistSal_Navigation::getKeypointMatches()
00490 {
00491 Timer tim(1000000);
00492 uint nCount, cCount;
00493
00494
00495
00496
00497
00498
00499 nCount = projectForward(itsNewLandmarkDBMatches,
00500 itsNewMovementTracker);
00501 if(nCount == 0)
00502 {
00503
00504
00505
00506 cCount = projectForward(itsCurrLandmarkDBMatches,
00507 itsCurrMovementTracker);
00508 }
00509 else
00510 {
00511
00512
00513 itsCurrLandmarkDBMatches = itsNewLandmarkDBMatches;
00514
00515 itsCurrMovementTracker->clear();
00516 itsCurrMovementTracker->reset(nCount);
00517 itsCurrMovementTracker->setCurrInputImage
00518 (itsNewMovementTracker->getCurrInputImage());
00519 itsCurrMovementTracker->setOriginalInputImage
00520 (itsNewMovementTracker->getOriginalInputImage());
00521 for(uint i = 0; i < nCount; i++)
00522 itsCurrMovementTracker->move(itsNewMovementTracker, i);
00523 }
00524 cCount = itsCurrLandmarkDBMatches.size();
00525 LINFO("\n\n\n Project forward: %d time: %f\n\n\n",
00526 cCount, tim.get()/1000.0f);
00527
00528
00529
00530
00531 uint count = itsNewLandmarkDBMatches.size();
00532
00533
00534
00535 if (count == 0)
00536 {
00537 count = itsCurrLandmarkDBMatches.size();
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 return count;
00569 }
00570
00571
00572 uint GistSal_Navigation::projectForward
00573 (std::vector<rutz::shared_ptr<LandmarkDBMatch> > &landmarkDBMatches,
00574 nub::soft_ref<SalientRegionTracker> tracker)
00575 {
00576
00577 std::vector<rutz::shared_ptr<LandmarkDBMatch> > tempLandmarkDBMatches;
00578
00579 LINFO("start: %"ZU, landmarkDBMatches.size());
00580
00581 for(uint i = 0; i < landmarkDBMatches.size(); i++)
00582 {
00583
00584 Rectangle rect = tracker->getCurrTrackedROI(i);
00585
00586
00587 Point2D<int> offset= rect.topLeft();
00588 Image<PixRGB<byte> > objImg = crop(itsCurrImg, rect);
00589 std::string iName("iName");
00590 std::string ifName = iName + std::string(".png");
00591 rutz::shared_ptr<VisualObject>
00592 vo(new VisualObject(iName, ifName, objImg));
00593
00594
00595
00596 LINFO("DB Match sent: %d: (%d %d - %d %d)",
00597 landmarkDBMatches[i]->dbi.objNum,
00598 landmarkDBMatches[i]->dbi.segNum,
00599 landmarkDBMatches[i]->dbi.lmkNum,
00600 landmarkDBMatches[i]->dbi.voStartNum,
00601 landmarkDBMatches[i]->dbi.voEndNum);
00602
00603 rutz::shared_ptr<VisualObjectMatch> cmatch;
00604 int index = itsLandmarkDB->getLandmark
00605 (landmarkDBMatches[i]->dbi.segNum,
00606 landmarkDBMatches[i]->dbi.lmkNum)->match
00607 (vo, cmatch, landmarkDBMatches[i]->dbi.voStartNum,
00608 -1, 10.0F, .75F, 2.5F, 4, M_PI/4, 1.25F);
00609 landmarkDBMatches[i]->dbi.voStartNum = index;
00610 landmarkDBMatches[i]->dbi.voEndNum = index;
00611
00612
00613 if(index != -1)
00614 {
00615 LINFO("\nProject Forward succeed: %d\n\n", index);
00616
00617 landmarkDBMatches[i]->vo = vo;
00618
00619
00620 Point2D<int> pt =
00621 itsLandmarkDB->getLandmark
00622 (landmarkDBMatches[i]->dbi.segNum,
00623 landmarkDBMatches[i]->dbi.lmkNum)
00624 ->getOffsetCoords
00625 (landmarkDBMatches[i]->dbi.voStartNum);
00626
00627 landmarkDBMatches[i]->voOffset = offset;
00628 landmarkDBMatches[i]->dbOffset = pt;
00629 landmarkDBMatches[i]->matchRes = cmatch;
00630
00631 tempLandmarkDBMatches.push_back(landmarkDBMatches[i]);
00632
00633 LINFO("project success %d", i);
00634 }
00635 else
00636 LINFO("\nProject Forward fail: %d\n\n", index);
00637 }
00638
00639
00640
00641 landmarkDBMatches = tempLandmarkDBMatches;
00642
00643 return uint(landmarkDBMatches.size());
00644 }
00645
00646
00647
00648 void GistSal_Navigation::computeErrorDifference()
00649 {
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 int dirF = 0,dirL = 0,dirR = 0;
00661
00662 uint w = itsProcImg.getWidth();
00663 uint h = itsProcImg.getHeight();
00664
00665
00666
00667 double avgdx = 0.0, avgdy = 0.0;
00668
00669 uint nLDBMatch = itsCurrLandmarkDBMatches.size();
00670 uint totalMatchSize = 0;
00671
00672 for(uint i = 0; i < nLDBMatch; i++)
00673 totalMatchSize += itsCurrLandmarkDBMatches[i]->matchRes->size();
00674
00675
00676 for(uint i = 0; i < nLDBMatch; i++)
00677 {
00678 int dirGain = 1;
00679
00680 rutz::shared_ptr<LandmarkDBMatch> ldbm =
00681 itsCurrLandmarkDBMatches[i];
00682 rutz::shared_ptr<VisualObjectMatch> matchRes =
00683 ldbm->matchRes;
00684
00685 Point2D<int> obOffset = ldbm->voOffset;
00686 Point2D<int> dbOffset = ldbm->dbOffset;
00687
00688 bool isODmatch =
00689 (ldbm->vo == matchRes->getVoRef());
00690
00691
00692 for (uint j = 0; j < matchRes->size(); j++)
00693 {
00694 rutz::shared_ptr<Keypoint> obkp;
00695 rutz::shared_ptr<Keypoint> dbkp;
00696 if(isODmatch)
00697 {
00698 obkp = matchRes->getKeypointMatch(j).refkp;
00699 dbkp = matchRes->getKeypointMatch(j).tstkp;
00700 }
00701 else
00702 {
00703 obkp = matchRes->getKeypointMatch(j).tstkp;
00704 dbkp = matchRes->getKeypointMatch(j).refkp;
00705 }
00706
00707
00708 double ud = dbkp->getX() + dbOffset.i - w/2;
00709 double ut = obkp->getX() + obOffset.i - w/2;
00710
00711 double vd = dbkp->getY() + dbOffset.j - h/2;
00712 double vt = obkp->getY() + obOffset.j - h/2;
00713
00714 double dx = fabs(ut - ud);
00715 double dy = fabs(vt - vd);
00716
00717
00718
00719
00720 avgdx += dx;
00721 avgdy += dy;
00722
00723
00724 if(ut > 0.0 && ud < 0.0)
00725 {
00726 dirR += dirGain;
00727 }
00728 else if(ut < 0.0 && ud > 0.0)
00729 {
00730 dirL += dirGain;
00731 }
00732 else if(ut > 0.0 && ut > ud)
00733 {
00734 dirR += dirGain;
00735 }
00736 else if(ut < 0.0 && ut < ud)
00737 {
00738 dirL += dirGain;
00739 }
00740 else
00741 {
00742 dirF +=dirGain;
00743 }
00744 }
00745 }
00746 LINFO("dirL: %4d dirF: %4d dirR: %4d", dirL, dirF, dirR);
00747 avgdx /= totalMatchSize;
00748 avgdy /= totalMatchSize;
00749 LINFO("avgdx %f avgdy %f", avgdx, avgdy);
00750
00751
00752
00753
00754
00755
00756
00757 itsXError = avgdx;
00758 itsYError = avgdy;
00759 itsError = sqrt(avgdx*avgdx + avgdy*avgdy);
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 itsTransSpeed = 0.8;
00776
00777
00778 if(dirF >= abs(dirR + dirL))
00779 { itsRotSpeed = 0.0; itsDir = 0; }
00780 else if(dirR > dirL)
00781 {
00782
00783
00784
00785 if(itsXError > 50.0)
00786 itsRotSpeed = -0.40;
00787 else
00788 itsRotSpeed = -0.20 + itsXError/50.0 * -0.20;
00789
00790 itsDir = 1.0;
00791 }
00792 else
00793 {
00794
00795
00796
00797 if(itsXError > 50.0)
00798 itsRotSpeed = 0.60;
00799 else
00800 itsRotSpeed = 0.30 + itsXError/50.0 * 0.30;
00801
00802 itsDir = -1.0;
00803 }
00804
00805 LINFO("Speed: [trans: %7.3f, rot: %7.3f] Error: %f",
00806 itsTransSpeed, itsRotSpeed, itsError);
00807 }
00808
00809
00810 bool GistSal_Navigation::estimateProgressToDestination()
00811 {
00812 bool nearJunction = false;
00813
00814 its_Curr_Loc_mutex.lock();
00815 uint currSegNum = itsCurrentSegmentLocation;
00816 float currLenTrav = itsCurrentSegmentLengthTraveled;
00817 uint desSegNum = itsDesiredSegmentLocation;
00818 float desLenTrav = itsDesiredSegmentLengthTraveled;
00819 its_Curr_Loc_mutex.unlock();
00820
00821
00822 float dist =
00823 itsTopologicalMap->getPath
00824 (currSegNum, currLenTrav, desSegNum, desLenTrav, itsMoves);
00825
00826 dist *= itsTopologicalMap->getMapScale();
00827 itsDistToGoal = dist;
00828
00829
00830 uint msize = itsMoves.size();
00831 for(uint i = 0; i < msize; i++)
00832 LINFO("Moves[%d]: %d", i, itsMoves[i]);
00833
00834 itsJunctionDist = INVALID_DISTANCE;
00835
00836
00837 if(dist < 3.5 || msize == 0)
00838 {
00839
00840 itsInGoal = true;
00841 itsTransSpeed = 0.0;
00842 itsRotSpeed = 0.0;
00843 return false;
00844 }
00845 else itsInGoal = false;
00846
00847
00848 if(itsMoves[0] == TOPOMAP_TURN_AROUND)
00849 {
00850
00851 itsTurnAngle = M_PI;
00852 LINFO("1 Move: TURN AROUND");
00853
00854
00855
00856
00857
00858
00859 }
00860 else if(itsMoves[0] == TOPOMAP_MOVE_FORWARD)
00861 {
00862
00863 if(msize == 1)
00864 {
00865 LINFO("1 Move: almost there just MOVE FORWARD");
00866
00867
00868 double speed = 0.8;
00869 if(dist < 10.0 && dist > 0.0) speed *= dist/10.0;
00870 itsTransSpeed = speed;
00871
00872 itsTurnAngle = 0.0;
00873 itsJunctionDist = -1111.0;
00874 }
00875
00876 else
00877 {
00878
00879 float ds, de;
00880 rutz::shared_ptr<Edge> e1 =
00881 itsTopologicalMap->getEdge(currSegNum, currLenTrav, ds, de);
00882
00883
00884 float jdist = de * itsTopologicalMap->getMapScale();
00885 itsJunctionDist = jdist;
00886 LINFO("JDIST: %f", jdist );
00887
00888
00889 if(jdist > JUNCTION_START_DIST)
00890 {
00891
00892
00893
00894
00895
00896
00897
00898 itsTurnAngle = 0.0;
00899 }
00900 else
00901 {
00902
00903 rutz::shared_ptr<Edge> e2 =
00904 itsTopologicalMap->getEdge(itsMoves[1]);
00905
00906
00907 float angle = itsTopologicalMap->getAngle(e1,e2);
00908 float dangle = angle*180.0/M_PI;
00909 LINFO("ANGLE: %f or %f", angle, dangle);
00910
00911 itsTurnAngle = angle;
00912 double addRot = 0.0;
00913 double fdangle = fabs(dangle);
00914
00915
00916
00917 if(fdangle < 30.0)
00918 addRot = 0.0;
00919
00920 else if(dangle > 30.0 && dangle < 150.0)
00921 addRot = -0.3;
00922
00923 else if(dangle >= 150.0)
00924 addRot = -0.6;
00925
00926 else if(dangle < -30.0 && dangle > -150.0)
00927 addRot = 0.3;
00928
00929 else if(dangle <= -150.0)
00930 addRot = 0.6;
00931
00932 LINFO("\n\n\naddRot: %f dangle: %f\n\n\n\n", addRot, dangle);
00933
00934
00935
00936
00937
00938
00939 itsTransSpeed = 0.8;
00940 itsRotSpeed += addRot;
00941
00942 nearJunction = true;
00943 }
00944 }
00945 }
00946
00947 return nearJunction;
00948
00949
00950
00951
00952
00953
00954
00955 }
00956
00957
00958
00959 void GistSal_Navigation::recover(bool foundSomething)
00960 {
00961 itsTurnAngle = INVALID_ANGLE;
00962 itsJunctionDist = INVALID_DISTANCE;
00963
00964
00965 itsTransSpeed = 0.0;
00966
00967
00968
00969
00970
00971
00972 if(foundSomething && itsReverseCount != 0)
00973 {
00974 itsRotSpeed = 0.0;
00975 if(itsReverseCount > 0) itsReverseCount--;
00976 }
00977 else if(foundSomething || itsReverseCount > 0)
00978 {
00979 itsRotSpeed = -0.6;
00980
00981 itsReverseCount++;
00982 if(itsReverseCount > REVERSE_COUNT_MAX)
00983 itsReverseCount = 0;
00984 }
00985 else
00986 itsRotSpeed = 0.6;
00987 }
00988
00989
00990
00991 void GistSal_Navigation::navigation()
00992 {
00993
00994
00995
00996
00997
00998 updateMotor(itsTransSpeed, itsRotSpeed);
00999 }
01000
01001
01002 void GistSal_Navigation::drawState()
01003 {
01004 uint w = itsProcImg.getWidth();
01005 uint h = itsProcImg.getHeight();
01006
01007 itsDispImg.resize(5*w, 3*h, NO_INIT);
01008
01009 for(uint i = 0; i < itsCurrLandmarkDBMatches.size(); i++)
01010 {
01011
01012
01013
01014 rutz::shared_ptr<LandmarkDBMatch> ldbm =
01015 itsCurrLandmarkDBMatches[i];
01016
01017 rutz::shared_ptr<VisualObjectMatch> matchRes =
01018 ldbm->matchRes;
01019
01020 Dims d(w,h);
01021 Point2D<int> objOffset1 = ldbm->voOffset;
01022 Point2D<int> objOffset2 = ldbm->dbOffset;
01023
01024 bool isODmatch = (ldbm->vo == matchRes->getVoRef());
01025 bool isDOmatch = (ldbm->vo == matchRes->getVoTest());
01026
01027 Image< PixRGB<byte> > result;
01028 if(isODmatch)
01029 {
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 result = matchRes->getMatchImage(d, objOffset1, objOffset2);
01040 }
01041 else if(isDOmatch)
01042 {
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052 result = matchRes->getMatchImage(d, objOffset2, objOffset1);
01053 }
01054 else{LFATAL("boom. Object neither ref nor tst."); }
01055
01056 std::string ntext(sformat("[%d]", i));
01057 if(isODmatch) ntext += std::string("OD");
01058 else ntext += std::string("OD");
01059 inplacePaste(itsDispImg, result, Point2D<int>(i*w,0));
01060 writeText(itsDispImg, Point2D<int>(w*i,0), ntext.c_str());
01061
01062 SIFTaffine aff = matchRes->getSIFTaffine();
01063 float theta, sx, sy, str;
01064 aff.decompose(theta, sx, sy, str);
01065 std::string ntext2(sformat("[%6.3f, %6.3f", sx, sy));
01066 writeText(itsDispImg, Point2D<int>(w*i,20), ntext2.c_str());
01067 }
01068
01069 inplacePaste(itsDispImg, drawInfoImg(), Point2D<int>(0, 2*h));
01070 }
01071
01072
01073
01074 Image<PixRGB<byte> > GistSal_Navigation::drawInfoImg()
01075 {
01076 uint w = itsProcImg.getWidth();
01077 uint h = itsProcImg.getHeight();
01078
01079 Image<PixRGB<byte> > dirImg(5*w, h,ZEROS);
01080
01081 std::string text;
01082 if(itsDir == 0) { text = sformat("Dir: ||| "); }
01083 else if(itsDir > 0) { text = sformat("Dir: --> "); }
01084 else { text = sformat("Dir: <-- "); }
01085
01086 uint totalMatchSize = 0;
01087 uint nLDBMatch = itsCurrLandmarkDBMatches.size();
01088 for(uint i = 0; i < nLDBMatch; i++)
01089 totalMatchSize += itsCurrLandmarkDBMatches[i]->matchRes->size();
01090 text += sformat("#kp[%4d]", totalMatchSize);
01091
01092 text += sformat("lDiff:[%8.3f] X:[%8.3f] Y:[%8.3f] ",
01093 itsError, itsXError, itsYError);
01094
01095 text += sformat("Trans[%8.3f] Rot[%8.3f]",
01096 itsTransSpeed, itsRotSpeed);
01097
01098 writeText(dirImg, Point2D<int>(0,0), text.c_str(),
01099 PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01100 SimpleFont::FIXED(8));
01101
01102 std::string text2;
01103 its_Curr_Loc_mutex.lock();
01104 uint currSegNum = itsCurrentSegmentLocation;
01105 float currLenTrav = itsCurrentSegmentLengthTraveled;
01106 uint desSegNum = itsDesiredSegmentLocation;
01107 float desLenTrav = itsDesiredSegmentLengthTraveled;
01108 its_Curr_Loc_mutex.unlock();
01109
01110 text2 += sformat("C[%3d, %6.3f] -> ", currSegNum, currLenTrav);
01111 text2 += sformat("D[%3d, %6.3f]: ", desSegNum, desLenTrav);
01112 text2 += sformat("dist:[%8.3f]: ", itsDistToGoal);
01113 text2 += sformat("M:[%"ZU"]: [", itsMoves.size());
01114 for(uint i = 0; i < itsMoves.size(); i++)
01115 text2 += sformat(" %d", itsMoves[i]);
01116
01117 if(itsTurnAngle == INVALID_ANGLE)
01118 text2 += sformat("] tAng: \">< ");
01119 else
01120 text2 += sformat("] tAng: %7.3f ", itsTurnAngle*180.0/M_PI);
01121 text2 += sformat("jDist: %8.3f", itsJunctionDist);
01122
01123 writeText(dirImg, Point2D<int>(0,20), text2.c_str(),
01124 PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01125 SimpleFont::FIXED(8));
01126
01127 std::string text3;
01128 if(itsInGoal) text3 += sformat("IN GOAL ");
01129 else text3 += sformat("NOT IN GOAL ");
01130 uint64 tim = itsLastFoundTimer.get();
01131 float lftime = tim/1000.0;
01132 text3 += sformat("%f ", lftime);
01133 if(tim > LOST_TIME_LIMIT)
01134 text3 += sformat("- OVER LOST TIME LIMIT. ");
01135 text3 += sformat("STATUS: %3d", itsCornerProcStatus);
01136
01137 writeText(dirImg, Point2D<int>(0,40), text3.c_str(),
01138 PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01139 SimpleFont::FIXED(8));
01140
01141 return dirImg;
01142 }
01143
01144
01145 void GistSal_Navigation::updateMotorPID(double tran, double rot,double error)
01146 {
01147 error/=100.0;
01148 if(itsDir == 1)
01149 error *= -1.0;
01150 double pTerm,iTerm,dTerm;
01151 pTerm = itsPGain * error;
01152 itsIState += error;
01153 if(itsIState > IMAX)
01154 itsIState = IMAX;
01155 else if(itsIState < IMIN)
01156 itsIState = IMIN;
01157 iTerm = itsIGain * itsIState;
01158 dTerm = itsDGain * (rot - itsDState);
01159 itsDState = rot;
01160 double pid = pTerm + iTerm - dTerm;
01161
01162 LINFO("P[%1.2f] I[%1.2f] D[%1.2f], Istate[%1.2f] DState[%1.2f]",
01163 pTerm,iTerm,dTerm,itsIState,itsDState);
01164 LINFO("pid[%1.2f],rot[%1.2f]",pid,rot);
01165 updateMotor(tran,pid);
01166 }
01167
01168
01169 void GistSal_Navigation::updateMotor(double tran, double rot)
01170 {
01171 BeobotEvents::MotorRequestPtr msg = new BeobotEvents::MotorRequest;
01172 msg->transVel = tran;
01173 msg->rotVel = rot;
01174 this->publish("MotorRequestTopic", msg);
01175 LINFO("[%d] Publish motor request Trans %f Rotation %f",
01176 itsPrevProcImgID,tran,rot);
01177 }
01178
01179
01180
01181
01182
01183