CornerNavigation.C

00001 /*!@file Robots2/Beobot2/Navigation/GistSal_Navigation/CornerNavigation.C */
00002 // //////////////////////////////////////////////////////////////////// //
00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00004 // University of Southern California (USC) and the iLab at USC.         //
00005 // See http://iLab.usc.edu for information about this project.          //
00006 // //////////////////////////////////////////////////////////////////// //
00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00009 // in Visual Environments, and Applications'' by Christof Koch and      //
00010 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00011 // pending; application number 09/912,225 filed July 23, 2001; see      //
00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00013 // //////////////////////////////////////////////////////////////////// //
00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00015 //                                                                      //
00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00017 // redistribute it and/or modify it under the terms of the GNU General  //
00018 // Public License as published by the Free Software Foundation; either  //
00019 // version 2 of the License, or (at your option) any later version.     //
00020 //                                                                      //
00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00024 // PURPOSE.  See the GNU General Public License for more details.       //
00025 //                                                                      //
00026 // You should have received a copy of the GNU General Public License    //
00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00029 // Boston, MA 02111-1307 USA.                                           //
00030 // //////////////////////////////////////////////////////////////////// //
00031 //
00032 // Primary maintainer for this file: Chin-Kai Chang <chinkaic@usc.edu>
00033 // $HeadURL: svn://ilab.usc.edu/trunk/saliency/src/Robots/Beobot2/CornerNavigation.C
00034 // $ $Id: CornerNavigation.C 13084 2010-03-30 02:42:00Z kai $
00035 //
00036 //////////////////////////////////////////////////////////////////////////
00037 
00038 #include "Robots/Beobot2/Navigation/GistSal_Navigation/CornerNavigation.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"   // for luminance()
00046 #include "Image/ShapeOps.H"   // for rescale()
00047 #include "Image/MathOps.H"    // for stdev()
00048 #include "Image/MatrixOps.H"  // for matrixMult()
00049 #include "Image/CutPaste.H"   // for inplacePaste()
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  FOLDER                                                 "../data/corner"
00064 #define  DBNAME                                                 "HNB"
00065 #define  IMAGE_PREFIX                           "image_0000000000"
00066 #define  IMAX                      1.0
00067 #define  IMIN                      0.0
00068 
00069 #define C_PROCEDURE_INACTIVE       0
00070 #define C_PROCEDURE_ACTIVE         1
00071 #define C_PROCEDURE_CONCLUDING     2
00072 
00073 const ModelOptionCateg MOC_CornerNavigation =
00074   { MOC_SORTPRI_3, "QT Navigation Related Options" };
00075 const ModelOptionDef OPT_RealCamera =
00076   { MODOPT_ARG(bool), "RealCamera", &MOC_CornerNavigation, OPTEXP_CORE,
00077     "Do we want use real camera from BeoCamera? Default will load from image files.",
00078     "camera", '\0', "true | false", "false" };
00079 
00080 // ######################################################################
00081 CornerNavigation::CornerNavigation(OptionManager& mgr,
00082                                    const std::string& descrName,
00083                                    const std::string& tagName) :
00084   RobotBrainComponent(mgr, descrName, tagName),
00085   itsFftComputer(new GistEstimatorFFT(mgr)),
00086   itsOfs(new OutputFrameSeries(mgr)),
00087   itsMapImg(320,240,ZEROS),
00088   itsReplayDBnum(0),
00089   itsFfn(new FeedForwardNetwork()),
00090   itsTimer(1000000),
00091   itsCurrImgID(-1),
00092   itsPrevProcImgID(-1),
00093   itsTeachImgID(0),
00094   itsReplayImgID(0),
00095   itsTransSpeed(0.0),
00096   itsRotSpeed(0.0),
00097   itsDirVector(0.0),
00098   itsDir(0),
00099   itsMilestoneErr(999.99),
00100   itsFalseErrRate(0.0),
00101   itsDirCount(0),
00102   itsPosition(0.0, 0.0, 0.0),
00103   itsError(0.0, 0.0, 0.0),
00104   itsRealCamera(&OPT_RealCamera, this, 0),
00105   itsEstop(true),
00106   itsIState(0.0),
00107   itsDState(0.0),
00108   itsPGain(1.0),
00109   itsIGain(0.01),
00110   itsDGain(0.0)
00111 {
00112   addSubComponent(itsOfs);
00113 
00114   itsStatus = C_PROCEDURE_INACTIVE;
00115   // load the teach Visual Object Database
00116   openDB(sformat("%s/%s/%s.conf",FOLDER,DBNAME,DBNAME));
00117 }
00118 
00119 // ######################################################################
00120 void CornerNavigation::openDB(const std::string& path)
00121 {
00122         FILE *dbconf = fopen(path.c_str(),"r");
00123         if(dbconf == NULL){
00124                 LFATAL("Can not open file: %s",path.c_str());
00125         }else{
00126                 char line[512];
00127                         while(fgets(line,sizeof line,dbconf)!= NULL)
00128                         {
00129                                 //Skip the line start at#
00130                                 if(line[0] != '#')
00131                                 {
00132                                         char subdb[256];
00133                                         char type;//Teach or Replay
00134                                         int start,end;
00135                                         int ret = sscanf(line,"%s %d %d %c",subdb,&start,&end,&type);
00136                                         if(ret == 4){
00137                                                 LINFO("Got [%s],start[%d],end[%d],type[%c]",subdb,start,end,type);
00138                                                 cornerDB tmpDB;
00139                                                 tmpDB.path = sformat("%s/%s/%s/%s",FOLDER,DBNAME,subdb,IMAGE_PREFIX);
00140                                                 tmpDB.start = start;
00141                                                 tmpDB.end = end;
00142                                                 tmpDB.type = type;
00143                                                 loadDB(tmpDB);
00144 
00145                                         }
00146                                 }
00147                         
00148                         }
00149         
00150         
00151         }
00152 }
00153 
00154 // ######################################################################
00155 void CornerNavigation::initFFN()
00156 { }
00157 
00158 // ######################################################################
00159 CornerNavigation::~CornerNavigation()
00160 { }
00161 
00162 // ######################################################################
00163 void CornerNavigation::start1()
00164 {
00165   //if it runing in simulation
00166   if(!itsRealCamera.getVal())
00167     itsDBnum = 0;
00168   else // corner location to turn: initially set none
00169     itsDBnum = -1;
00170   LINFO("itsDBNUM: %d", itsDBnum);
00171 }
00172 
00173 // ######################################################################
00174 void CornerNavigation::registerTopics()
00175 {
00176   // subscribe to all sensor data
00177   //this->registerSubscription("CameraMessageTopic");
00178   this->registerSubscription("GistSalMessageTopic");
00179   this->registerSubscription("MotorMessageTopic");
00180   this->registerSubscription("CornerLocationMessageTopic");
00181 
00182   this->registerPublisher("CornerMotorRequestTopic");
00183   //this->registerPublisher("MotorRequestTopic");
00184 }
00185 
00186 // ######################################################################
00187 void CornerNavigation::evolve()
00188 {
00189   // check if the current image is updated
00190   its_Curr_Img_mutex.lock();
00191   bool newImageFlag = (itsPrevProcImgID < itsCurrImgID);
00192   its_Curr_Img_mutex.unlock();
00193 
00194   // if simulation
00195   if(!itsRealCamera.getVal())
00196     {
00197       navigation();
00198     }
00199 
00200   // if real camera
00201   else
00202     {
00203       // if so, process
00204       if(newImageFlag)
00205         {
00206           // get the input image
00207           itsTimer.reset();
00208           its_Curr_Img_mutex.lock();
00209           itsProcImg = itsCurrImg;
00210           itsPrevProcImgID = itsCurrImgID;
00211           its_Curr_Img_mutex.unlock();
00212 
00213           // check if we are turning a corner
00214           its_Corner_Loc_mutex.lock();
00215           int dbNum = itsDBnum;
00216           int status =  itsStatus;
00217           its_Corner_Loc_mutex.unlock();
00218 
00219           // if so navigate
00220           if(dbNum != -1 && status != C_PROCEDURE_INACTIVE)
00221             {
00222               LINFO("size: %"ZU, itsVisualObjectDBs.size() );
00223               int cornerSize = itsVisualObjectDBs[dbNum].vdb->numObjects();
00224 
00225             if(itsTeachImgID >= cornerSize)
00226               {
00227                 itsStatus = C_PROCEDURE_INACTIVE;
00228               }
00229             else if(itsTeachImgID > int(cornerSize*0.9))
00230               {
00231                 itsStatus = C_PROCEDURE_CONCLUDING;
00232               }
00233             else
00234               {
00235                 itsStatus = C_PROCEDURE_ACTIVE;
00236               }
00237             LINFO("5");
00238             navigation();
00239             LINFO("6");
00240           }
00241         }
00242     }
00243 
00244   if(!itsRealCamera.getVal() || newImageFlag)
00245     {
00246       drawState();
00247       itsOfs->writeRGB(itsDispImg, "CornerNav",
00248                        FrameInfo("CornerNav",SRC_POS));
00249     }
00250 
00251 //   if(itsEstop == false)
00252 //     {
00253 //       Raster::waitForKey();
00254 //       itsEstop = true;
00255 //     }
00256 }
00257 
00258 // ######################################################################
00259 void CornerNavigation::recovery()
00260 {
00261   int trytimes = 0;
00262   do{
00263     loadFrame();
00264     std::vector< rutz::shared_ptr<VisualObjectMatch> > matches;
00265 
00266     its_Corner_Loc_mutex.lock();
00267     int dbNum = itsDBnum;
00268     its_Corner_Loc_mutex.unlock();
00269 
00270     int nmatches =
00271       itsVisualObjectDBs[dbNum].vdb->getObjectMatches
00272       (itsReplayVo,matches,VOMA_SIMPLE,
00273        10U,
00274        0.5F, //keypoint distance score default 0.5F
00275        0.5F, //affine distance score default 0.5F
00276        1.0F, //minscore  default 1.0F
00277        4U, //min # of keypoint match
00278        100U, //keypoint selection thershold
00279        false //sort by preattentive
00280        );
00281     std::string objName;
00282     int closestFrame = 999999999;
00283     int tmpFrameID = itsTeachImgID;
00284     LINFO("Searching For Nearest Key Frame in the Database");
00285     if (nmatches > 0 )
00286       {
00287         for(int i = 0; i < nmatches; i++)
00288           {
00289             LINFO("Found [%d] frames matches Frame[%d]", nmatches, i);
00290 
00291             // so that we will have a ref to the last matches obj
00292             rutz::shared_ptr<VisualObject> obj;
00293             rutz::shared_ptr<VisualObjectMatch> vom;
00294             vom = matches[i];
00295             obj = vom->getVoTest();
00296             //      score = vom->getScore();
00297             //      nkeyp = vom->size();
00298             //      avgScore = vom->getKeypointAvgDist();
00299             //      affineAvgDist = vom->getAffineAvgDist();
00300             objName = obj->getName();
00301             int tmpID = atoi(objName.c_str());
00302             int dx = tmpID - itsTeachImgID;
00303 
00304             LINFO("Dist. from current teach frame[%d]=======new ID[%d]",
00305                   dx,tmpID);
00306             // find closest frame that matches
00307             //FIXX: we don't consider the match rate yet.
00308             if(dx < closestFrame)
00309               {
00310                 closestFrame = dx;
00311                 tmpFrameID = tmpID;
00312               }
00313           }
00314         LINFO("Recovery Found:TID[%d]RID[%d] Match[%d]",
00315               itsTeachImgID,itsReplayImgID,tmpFrameID);
00316         itsTeachImgID = tmpFrameID;
00317         itsEstop = true;
00318         itsTransSpeed = 0.8;
00319         loadFrame();
00320         computeSIFT();
00321       }
00322     else
00323       {
00324         LINFO("No Match Point,Try get new frame and try again");
00325         loadFrame();
00326         trytimes++;
00327       }
00328   }
00329   while(!itsEstop && trytimes < 10);
00330 }
00331 
00332 // ######################################################################
00333 // The main function of navigation
00334 void CornerNavigation::navigation()
00335 {
00336   // load key frame from database
00337   // compute SIFT keypoint and matching
00338   loadFrame();
00339   //computeSIFT();
00340 
00341   // apply QT algo for direction
00342   double error = computeDirection2(itsTeachImgID);
00343 
00344         //When the mean error and stderr have too much difference
00345         //Then ignore the SIFT bogus match
00346         if(error != 0.0 && itsMatchList->size()!=0 &&
00347                         (itsMatchList->checkSIFTaffine() || itsFalseErrRate > 1.0)
00348                 ){
00349                 updateMotor(itsTransSpeed, itsRotSpeed,itsStatus);
00350                 updateKeyframe(error);
00351                 itsEstop = true;
00352 
00353       // update keyframe when reaching milestone
00354       updateKeyframe(error);
00355       itsEstop = true;
00356     }
00357 
00358   // when the mean error and stderr have too much difference
00359   // then ignore the SIFT bogus match
00360   else
00361     {
00362       itsEstop = false;
00363       LINFO("lost matching; start recover mechanism");
00364       itsTransSpeed = 0.0;
00365       itsRotSpeed = 0.0;
00366 
00367                         if(itsRealCamera.getVal())
00368                         {
00369                                 its_Corner_Loc_mutex.lock();
00370                                 itsStatus = C_PROCEDURE_INACTIVE;
00371                                 int status = itsStatus;
00372                                 itsDBnum  = -1;
00373                                 its_Corner_Loc_mutex.unlock();
00374                                 updateMotor(itsTransSpeed, itsRotSpeed, status);
00375                         }else{
00376                                 updateMotor(itsTransSpeed, itsRotSpeed, 0);
00377                                 //recovery();
00378                                 //itsEstop = true; 
00379                         }
00380     }
00381 }
00382 
00383 // ######################################################################
00384 void CornerNavigation::loadDB(cornerDB db)
00385 {
00386 
00387   //std::string path = sformat("%s/%s.sift",db.path.c_str(),IMAGE_PREFIX);
00388 
00389   // load the actual VisualObjectDatabase but don't load images
00390   db.vdb.reset(new VisualObjectDB());
00391   bool rt = db.vdb->loadFrom(sformat("%s.sift",db.path.c_str()),false);
00392   if(rt)
00393     {
00394       LINFO("Load SIFT Database");
00395       itsVisualObjectDBs.push_back(db);
00396 
00397       //Check if db is use for replay
00398       if(db.type =='R')
00399         itsReplayDBnum = int(itsVisualObjectDBs.size())-1;
00400     }
00401   else
00402     {
00403       LINFO("SIFT Database %s not exist, create new", db.path.c_str());
00404       saveDB(db.start,db.end,db.path.c_str());
00405     }
00406 }
00407 // ######################################################################
00408 void CornerNavigation::saveDB(int start,int end,const std::string& path)
00409 {
00410   cornerDB tmp;
00411   tmp.vdb.reset(new VisualObjectDB());
00412   for(int i = start; i < end; i++)
00413     {
00414       itsTimer.reset();
00415       std::string teachFileName(sformat("%s%05d.ppm",path.c_str(),i));
00416       Image< PixRGB<byte> > img = Raster::ReadRGB(teachFileName);
00417       rutz::shared_ptr<VisualObject> vo1
00418         (new VisualObject(sformat("%d",i),
00419                           sformat("%s%05d.png",path.c_str(),i),
00420                           rescale(img,img.getWidth()/2, img.getHeight()/2)));
00421       tmp.vdb->addObject(vo1);
00422       LINFO("Time[%f] Compute SIFT for Frame %d/%d",
00423             itsTimer.get()/1000.0,i-start+1,end-start+1);
00424     }
00425   std::string teachDB(sformat("%s.sift",path.c_str()));
00426   //        itsVisualObjectDB->setName();
00427   tmp.vdb->saveTo(teachDB);
00428 }
00429 
00430 // ######################################################################
00431 void CornerNavigation::loadFrame()
00432 {
00433   // load teach image data
00434   itsTimer.reset();
00435 
00436   its_Corner_Loc_mutex.lock();
00437   int dbNum = itsDBnum;
00438   its_Corner_Loc_mutex.unlock();
00439 
00440   //Check the size of subdb
00441   if(itsTeachImgID < (int)itsVisualObjectDBs[dbNum].vdb->numObjects())
00442     {
00443       itsTeachVo = itsVisualObjectDBs[dbNum].vdb->getObject(itsTeachImgID);
00444       itsTeachImg = itsTeachVo->getImage();
00445     }
00446   else
00447     {
00448       LINFO("=======Teach DB End=====");
00449       itsTeachImgID = 0;
00450       //itsReplayImgID = 0;
00451     }
00452 
00453   LINFO("Time for Computing SIFT on TeachImg %f",
00454         itsTimer.get()/1000.0);
00455   itsTimer.reset();
00456 
00457   // Load Current Replay image data
00458 
00459   // running from image files
00460   if(!itsRealCamera.getVal())
00461     {
00462       if(itsReplayImgID < (int)itsVisualObjectDBs[itsReplayDBnum].vdb->numObjects())
00463         {
00464                                         if(itsReplayImgID <(int)itsVisualObjectDBs[itsReplayDBnum].vdb->numObjects())
00465                                         {
00466                   itsReplayVo = itsVisualObjectDBs[itsReplayDBnum].vdb-> getObject(itsReplayImgID);     
00467                                                 itsReplayImg = itsReplayVo->getImage(); 
00468                                                 itsProcImg = itsReplayImg;
00469                                                 itsReplayImgID++;
00470                                         }
00471         }
00472     }
00473 
00474   // running from real camera
00475   else
00476     {
00477       itsReplayImg   = itsProcImg;
00478       itsReplayImgID = itsPrevProcImgID;
00479       rutz::shared_ptr<VisualObject> vo2 (new VisualObject ("1", "", itsReplayImg));
00480       itsReplayVo = vo2;
00481     }
00482   LINFO("Time for Computing SIFT on ReplayImg %f",
00483         itsTimer.get()/1000.0);
00484 }
00485 
00486 // ######################################################################
00487 bool CornerNavigation::computeSIFT()
00488 {
00489   itsTimer.reset();
00490   VisualObjectMatchAlgo voma(VOMA_SIMPLE);
00491   itsMatchList.reset(new VisualObjectMatch(itsTeachVo, itsReplayVo, voma));
00492   LINFO("=========================================");
00493   //LINFO("Found %u matches between Teach and Replay", match.size());
00494 
00495   // let's prune the matches:
00496   //uint np =
00497   itsMatchList->prune();
00498   //LINFO("Pruned %u outlier matches.", np);
00499   LINFO("Match size now is %u ", itsMatchList->size());
00500 
00501   // show our final affine transform:
00502   //        std::cerr<<match.getSIFTaffine();
00503 
00504   //LINFO("getKeypointAvgDist = %f", match.getKeypointAvgDist());
00505   //LINFO("getAffineAvgDist = %f", match.getAffineAvgDist());
00506   //LINFO("getScore = %f", match.getScore());
00507   if (itsMatchList->checkSIFTaffine() == false)
00508     LINFO("### Affine is too weird -- BOGUS MATCH");
00509 
00510   // record the time
00511   LINFO("Time for Matching SIFT %f",itsTimer.get()/1000.0);
00512 
00513   // if the sift point is valid, return true
00514   return (itsMatchList->size()!=0 && itsMatchList->checkSIFTaffine());
00515 }
00516 
00517 // ######################################################################
00518 double CornerNavigation::computeDirection2(int teachID)
00519 {
00520   int dirF = 0,dirL = 0,dirR = 0;
00521   rutz::shared_ptr<VisualObjectMatch> bestMatch;
00522   int bestMatchSize = -1;
00523   int bestID = 0;
00524   LINFO("Direction2 Start");
00525 
00526   // boundary condition
00527   if((teachID-2) < 0) teachID = 2;
00528 
00529   // looking 10 frame ahead to find best match frame
00530   for(int id = teachID-2; id < teachID+10; id++)
00531     {
00532 
00533       its_Corner_Loc_mutex.lock();
00534       int dbNum = itsDBnum;
00535       its_Corner_Loc_mutex.unlock();
00536 
00537       //std::string teachFileName(sformat("%s%05d.ppm",TEACH_FOLDER,id));
00538       rutz::shared_ptr<VisualObject> vo1;
00539         if(id < (int)itsVisualObjectDBs[dbNum].vdb->numObjects()){
00540       vo1 = itsVisualObjectDBs[dbNum].vdb->getObject(id);
00541         }
00542         else{
00543                 LINFO("DB END");
00544                         return 0.0;
00545         }
00546       VisualObjectMatchAlgo voma(VOMA_SIMPLE);
00547       rutz::shared_ptr<VisualObjectMatch>
00548         match(new VisualObjectMatch(vo1, itsReplayVo, voma));
00549       match->prune();
00550 
00551       // =========================
00552       // find the best Keyframe
00553       float theta = 2.0, sx = 2.0, sy = 2.0, str = 0;
00554 
00555       // check if the match is valid
00556       if (match->checkSIFTaffine())
00557         {
00558           match->getSIFTaffine().decompose(theta, sx, sy, str);
00559         }
00560       int msize = match->size();
00561       if((msize > bestMatchSize && sx < 1.0 && sy < 1.0) ||
00562          (bestMatchSize == -1 && id==teachID))
00563         {
00564           bestMatchSize = msize;
00565           bestMatch = match;
00566           bestID = id;
00567         }
00568       LDEBUG("Best Match Size %d,",bestMatchSize);
00569       itsMatchList = bestMatch;
00570 
00571       int dirGain = 1; if(id == bestID) dirGain = 2;
00572 
00573       // compute the direction and find mean of error
00574       for (int i = 0; i < msize; i ++)
00575         {
00576           rutz::shared_ptr<Keypoint> refk = match->getKeypointMatch(i).refkp;
00577           rutz::shared_ptr<Keypoint> tstk = match->getKeypointMatch(i).tstkp;
00578 
00579           double ut = tstk->getX() - itsReplayVo->getImage().getWidth()/2;
00580           double ud = refk->getX() -  itsTeachVo->getImage().getWidth()/2;
00581 
00582           if(ut > 0.0 && ud < 0.0)
00583             {
00584               dirR += dirGain;
00585             }
00586           else if(ut < 0.0 && ud > 0.0)
00587             {
00588               dirL += dirGain;
00589             }
00590           else if(ut > 0.0 && ut > ud)
00591             {
00592               dirR += dirGain;
00593             }
00594           else if(ut < 0.0 && ut < ud)
00595             {
00596               dirL += dirGain;
00597             }
00598           else
00599             {
00600               dirF +=dirGain;
00601             }
00602         }
00603     }//end for
00604 
00605   //=========================
00606   double stdx = 0.0,stdy = 0.0;
00607   double avgdx = 0.0,avgdy = 0.0;
00608 
00609   // compute the std error
00610   for (int i = 0; i < bestMatchSize; i ++)
00611     {
00612       // LINFO("Loading best match point %d",i);
00613       rutz::shared_ptr<Keypoint> refk = bestMatch->getKeypointMatch(i).refkp;
00614       rutz::shared_ptr<Keypoint> tstk = bestMatch->getKeypointMatch(i).tstkp;
00615       double dx = fabs(tstk->getX() - refk->getX())+ 0.000001;
00616       stdx += dx * dx;
00617       avgdx+= dx;
00618 
00619       double dy = fabs(tstk->getY() - refk->getY())+ 0.000001;
00620       stdy += dy * dy;
00621       avgdy+= dy;
00622       LDEBUG("Error! i=[%d] BestMatchSize[%d] "
00623             "avgdx[%f] avgdy[%f],dx[%f], dy[%f]",
00624             i,bestMatchSize,avgdx,avgdy,dx,dy);
00625     }
00626   if(bestMatchSize != 0)
00627     {
00628       avgdx/= bestMatchSize;
00629       avgdy/= bestMatchSize;
00630       stdx -= (avgdx*avgdx);
00631       stdy -= (avgdy*avgdy);
00632       stdx /= bestMatchSize;
00633       stdx  = sqrt(stdx);
00634       stdy /= bestMatchSize;
00635       stdy  = sqrt(stdy);
00636       LDEBUG("Error! BestMatchSize[%d]  avgdx[%f] avgdy[%f]",
00637             bestMatchSize,avgdx,avgdy);
00638     }
00639   else
00640     {
00641       avgdx = 0;
00642       avgdy = 0;
00643       stdx  = 0;
00644       stdy  = 0;
00645     }
00646 
00647   LDEBUG("stdx %f stdy %f",stdx,stdy);
00648   uint stdcount = 0;
00649   double newAvgX = 0.0,newAvgY = 0.0;
00650 
00651   // Pick one stddev error as the new error data
00652   for (int i = 0; i < bestMatchSize; i ++)
00653     {
00654       rutz::shared_ptr<Keypoint> refk = bestMatch->getKeypointMatch(i).refkp;
00655       rutz::shared_ptr<Keypoint> tstk = bestMatch->getKeypointMatch(i).tstkp;
00656       double dx = fabs(tstk->getX() - refk->getX())+ 0.000001;
00657       double dy = fabs(tstk->getY() - refk->getY())+ 0.000001 ;
00658       double ddx = fabs(dx - avgdx);
00659       double ddy = fabs(dy - avgdy);
00660 
00661       if(ddx < stdx && ddy < stdy)
00662         {
00663           newAvgX += dx;
00664           newAvgY += dy;
00665           stdcount++;
00666         }
00667     }
00668 
00669   if(stdcount != 0)
00670     {
00671       newAvgX/= stdcount;
00672       newAvgY/= stdcount;
00673     }
00674   double newAvgerr = sqrt(newAvgX*newAvgX + newAvgY*newAvgY);
00675   double avgerr = sqrt(avgdx*avgdx + avgdy*avgdy);
00676   double angle = (newAvgX*(16.0/33.0));
00677   itsError.x = newAvgX;
00678   itsError.y = newAvgY;
00679   itsError.z = newAvgerr;
00680   //FIXXX
00681   if(newAvgerr == 0.0)
00682     {
00683       //Raster::waitForKey();
00684       newAvgerr = avgerr;
00685       itsFalseErrRate = 0;
00686     }
00687   else
00688     {
00689       itsFalseErrRate = avgerr/newAvgerr;
00690     }
00691   LDEBUG("False Error Rate %1.3f",itsFalseErrRate);
00692   if(itsFalseErrRate == 0.0)
00693     {
00694       LDEBUG("Error!!!! stdcount[%d]  avgerr[%f]",
00695             stdcount,avgerr);
00696       LDEBUG("Error!!!! bestMatchSize[%d]  stdx[%f] stdy[%f]",
00697             bestMatchSize,stdx,stdy);
00698       //Raster::waitForKey();
00699     }
00700 
00701   // reset target keyframe if we found better match
00702   if(bestID > itsTeachImgID && newAvgerr < 10.0)
00703     itsTeachImgID = bestID;
00704 
00705   // compute the forward speed based on scale
00706   if (bestMatch->checkSIFTaffine())//Check if the match is valid
00707     {
00708       float theta = 0.0 , sx = 0.0, sy = 0.0, str = 0.0 ;
00709       bestMatch->getSIFTaffine().decompose(theta, sx, sy, str);
00710       //if the size difference is large(sx/sy << 1.0),we can speed up
00711       double rms = 1.0 -(sqrt(sx*sx+sy*sy)/sqrt(2));
00712 
00713       double gain = 1.0;
00714       if(rms > 0.0)
00715         itsTransSpeed = 0.8 + rms * gain;
00716       if(itsTransSpeed > 1.0)itsTransSpeed = 1.0;
00717       if(itsTransSpeed < 0.0)itsTransSpeed = 0.0;
00718     }
00719   else
00720     {
00721       itsTransSpeed = 0.8;
00722     }
00723 
00724   // compute turning speed
00725   if(dirF >= abs(dirR + dirL))
00726     {
00727       updatePosition(0);
00728       itsRotSpeed = 0.4;
00729       if(itsDir == 0)//same heading since last time
00730         {
00731           itsDirCount++;
00732         }
00733       else
00734         {
00735           itsDirCount = 0;//reset direction count
00736           itsDir = 0;//reset direction
00737         }
00738     }
00739   else if(dirR > dirL)
00740     {
00741       updatePosition(angle);
00742       //Average the speed
00743       itsRotSpeed -= newAvgX/100.0;
00744       itsRotSpeed /= 2.0;
00745       if(itsDir == 1)//same heading since last time
00746         {
00747           itsDirCount++;
00748         }
00749       else
00750         {
00751           itsDirCount = 0;//reset direction count
00752           itsDir = 1;//reset direction
00753         }
00754     }
00755   else
00756     {
00757       updatePosition(-1*angle);
00758       //Average the speed
00759       itsRotSpeed += newAvgX/100.0+1.0;
00760       itsRotSpeed /= 2.0;
00761       if(itsDir == -1)//same heading since last time
00762         {
00763           itsDirCount++;
00764         }else{
00765         itsDirCount = 0;//reset direction count
00766         itsDir = -1;//reset direction
00767       }
00768     }
00769   return newAvgerr;
00770 }
00771 
00772 // ######################################################################
00773 double CornerNavigation::computeDirection()
00774 {
00775   itsTimer.reset();
00776   int dirF = 0,dirL = 0,dirR = 0;
00777   double avgdx = 0.0,avgdy = 0.0;
00778   uint msize = itsMatchList->size();
00779 
00780   // compute the direction and find mean of error
00781   for (uint i = 0; i < msize; i ++)
00782     {
00783       rutz::shared_ptr<Keypoint> refk =
00784         itsMatchList->getKeypointMatch(i).refkp;
00785       rutz::shared_ptr<Keypoint> tstk =
00786         itsMatchList->getKeypointMatch(i).tstkp;
00787 
00788       double ut = tstk->getX() - itsReplayVo->getImage().getWidth()/2;
00789       double ud = refk->getX() - itsTeachVo->getImage().getWidth()/2;
00790       double dx = fabs(ut - ud);
00791       double dy = fabs(tstk->getY() - refk->getY());
00792       avgdx += dx;
00793       avgdy += dy;
00794       std::string dir;
00795 
00796       if(ut > 0.0 && ud < 0.0)
00797         {
00798           dir = std::string("RIGHT");
00799           dirR ++;
00800         }
00801       else if(ut < 0.0 && ud > 0.0)
00802         {
00803           dir = std::string("LEFT");
00804           dirL ++;
00805         }
00806       else if(ut > 0.0 && ut > ud  )
00807         {
00808           dir = std::string("RIGHT");
00809           dirR ++;
00810         }
00811       else if(ut < 0.0 && ut < ud)
00812         {
00813           dir = std::string("LEFT");
00814           dirL ++;
00815         }
00816       else
00817         {
00818           dir = std::string("Forward");
00819           dirF ++;
00820         }
00821       LDEBUG("MatchPoint[%d] Teach(%f,%f) Replay(%f,%f), "
00822              "ud:[%f],ut:[%f],dx:[%f],dy:[%f] Turn %s",
00823              i,
00824              (refk->getX()),
00825              (refk->getY()),
00826              (tstk->getX()),
00827              (tstk->getY()),
00828              ud,ut,dx,dy,dir.c_str()
00829              );
00830     }
00831   avgdx/= msize;
00832   avgdy/= msize;
00833   double stdx = 0.0,stdy = 0.0;
00834 
00835   // compute the std error
00836   for (uint i = 0; i < msize; i ++)
00837     {
00838       rutz::shared_ptr<Keypoint> refk =
00839         itsMatchList->getKeypointMatch(i).refkp;
00840       rutz::shared_ptr<Keypoint> tstk =
00841         itsMatchList->getKeypointMatch(i).tstkp;
00842       double ddx = fabs(tstk->getX() - refk->getX()) - avgdx;
00843       stdx += ddx * ddx;
00844       double ddy = fabs(tstk->getY() - refk->getY()) - avgdy;
00845       stdy += ddy * ddy;
00846     }
00847   stdx /= msize;
00848   //stdx = sqrt(stdx);
00849   stdy /= msize;
00850   //stdy = sqrt(stdy);
00851   uint stdcount = 0;
00852   double newAvgX = 0.0,newAvgY = 0.0;
00853 
00854   // pick one std error as the new error data
00855   for (uint i = 0; i < msize; i ++)
00856     {
00857       rutz::shared_ptr<Keypoint> refk =
00858         itsMatchList->getKeypointMatch(i).refkp;
00859       rutz::shared_ptr<Keypoint> tstk =
00860         itsMatchList->getKeypointMatch(i).tstkp;
00861       double dx = fabs(tstk->getX() - refk->getX()) ;
00862       double dy = fabs(tstk->getY() - refk->getY()) ;
00863       double ddx = fabs(dx - avgdx);
00864       double ddy = fabs(dy - avgdy);
00865 
00866       if(ddx < sqrt(stdx) && ddy < sqrt(stdy))
00867         {
00868           newAvgX += dx;
00869           newAvgY += dy;
00870           stdcount++;
00871         }
00872     }
00873   if(stdcount != 0)
00874     {
00875       newAvgX/=stdcount;
00876       newAvgY/=stdcount;
00877     }
00878 
00879   double stdeverr = sqrt(stdx+stdy);
00880   double avgerr = sqrt(avgdx*avgdx + avgdy*avgdy);
00881   double newAvgerr = sqrt(newAvgX*newAvgX + newAvgY*newAvgY);
00882   double df = (itsTeachImgID - itsReplayImgID );
00883   double angle = (newAvgX*(56.0/33.0))/df;
00884   //double angle = (newAvgX*(16.0/33.0));
00885   LDEBUG("StdError[%f],StdErrX[%f],StdErrY[%f],Frame[%1.0f]",
00886         stdeverr,sqrt(stdx),sqrt(stdy),df);
00887   LDEBUG("AvgErr[%f],AvgX[%f],AvgY[%f]",avgerr,avgdx,avgdy);
00888   LDEBUG("StdAvgErr[%f],StdAvgX[%f],StdAvgY[%f]",newAvgerr,newAvgX,newAvgY);
00889   LDEBUG("Forward[%d], Right[%d], Left[%d] Angle[%f]",dirF,dirR,dirL,angle);
00890   itsError.x = newAvgX;
00891   itsError.y = newAvgY;
00892   itsError.z = newAvgerr;
00893   //FIXXX
00894   if(newAvgerr == 0.0)
00895     {
00896       //Raster::waitForKey();
00897       newAvgerr = avgerr;
00898     }
00899 
00900   itsFalseErrRate = avgerr/newAvgerr;
00901 
00902   LINFO("Time for QT Navigation %f",itsTimer.get()/1000.0);
00903   return newAvgerr;
00904 }
00905 
00906 // ######################################################################
00907 void CornerNavigation::updateKeyframe(double error)
00908 {
00909   LINFO("itsMerror %f,new error %f", itsMilestoneErr, error);
00910 
00911   // check if the match is valid
00912   if (itsMatchList->checkSIFTaffine())
00913     {
00914       float theta, sx, sy, str;
00915       itsMatchList->getSIFTaffine().decompose(theta, sx, sy, str);
00916       LDEBUG("SIFT SCALE SX[%f] SY[%f] Theta[%f] Str[%f]",sx,sy,theta,str);
00917 
00918       //Check the frame reach the milestone image or not
00919       //if(itsMilestoneErr > error && (sx <1.0&&sy <1.0))
00920       //        itsMilestoneErr = error;
00921       //else
00922       //{
00923       //FIXXX: Hack,Single threshold will not work in all environment
00924       if(((sx >=0.9 && sy >=0.9) && error <50.0 ) && itsMatchList->size()>2){
00925         itsMilestoneErr = 999.99;
00926         itsTeachImgID += 20;//FIXXX when turning sharp,slow down the forward rate
00927         LINFO("*********=========Switch Keyframe=========**********");
00928       }
00929       //}
00930     }
00931 }
00932 
00933 //Given Current image frame,it will try to find proper keyframe for navation
00934 //
00935 // ######################################################################
00936 int CornerNavigation::computeEntropy()
00937 {
00938   return 1;
00939 }
00940 
00941 // ######################################################################
00942 void CornerNavigation::drawState()
00943 {
00944   its_Corner_Loc_mutex.lock();
00945   int dbNum = itsDBnum;
00946   its_Corner_Loc_mutex.unlock();
00947 
00948   uint w = itsProcImg.getWidth()*2, h = itsProcImg.getHeight()*2;
00949   //uint w = 320, h = 240;
00950   LINFO("TeachImg w=%d,h=%d, dbNum: %d", w, h, dbNum);
00951   itsDispImg.resize(w*2, 3*h, NO_INIT);
00952   char buffer[128];
00953 
00954   // original image
00955   inplacePaste(itsDispImg, itsProcImg, Point2D<int>(0, 0));
00956 
00957   if(dbNum != -1)
00958     {
00959       // replay image
00960       Image< PixRGB<byte> > replayImg = rescale(itsReplayImg,w,h);
00961       sprintf(buffer,"img%5d",itsReplayImgID);
00962       writeText(replayImg, Point2D<int>(5,5),
00963                 buffer, PixRGB<byte>(255,255,255),
00964                 PixRGB<byte>(0,0,0),SimpleFont::FIXED(8));
00965       inplacePaste(itsDispImg, replayImg, Point2D<int>(0, 2*h));
00966 
00967       // teach image
00968       Image< PixRGB<byte> > teachImg = rescale(itsTeachImg,w,h);
00969       sprintf(buffer,"img%5d",itsTeachImgID);
00970       writeText(teachImg, Point2D<int>(5,5),
00971                 buffer, PixRGB<byte>(255,255,255),
00972                 PixRGB<byte>(0,0,0), SimpleFont::FIXED(8));
00973       inplacePaste(itsDispImg, teachImg, Point2D<int>(0, h));
00974 
00975       // teach keypoint image
00976       //inplacePaste(itsDispImg, itsTeachVo->getKeypointImage(1.0) ,
00977       //             Point2D<int>(w, h));
00978 
00979       // replay keypoint image
00980       //inplacePaste(itsDispImg, itsReplayVo->getKeypointImage(1.0),
00981       //             Point2D<int>(w, h*1.5));
00982 
00983       // match image
00984       if(itsEstop)
00985         {
00986           Image< PixRGB<byte> > mimg = itsMatchList->getMatchImage(1.0F);
00987           LDEBUG("itsdispImg[%d,%d] mimg[%d,%d] pt[%d,%d]",
00988                  itsDispImg.getWidth(), itsDispImg.getHeight(),
00989                  mimg.getWidth(), mimg.getHeight(), int(w*1.5), h);
00990 
00991           inplacePaste(itsDispImg, mimg, Point2D<int>(w*1.5, h));
00992         }
00993 
00994       // visual odometry
00995       double mapScale = 0.20;
00996       Point2D<int> drawPos
00997         (int(itsPosition.x*mapScale + itsMapImg.getWidth()/2),
00998          int(itsPosition.y*mapScale + itsMapImg.getHeight()/2));
00999       if(itsMapImg.coordsOk(drawPos))
01000         itsMapImg.setVal(drawPos, PixRGB<byte>(0,255,0));
01001       inplacePaste(itsDispImg, itsMapImg, Point2D<int>(w, h*2));
01002     }
01003 
01004   // information
01005   inplacePaste(itsDispImg, drawInfoImg(), Point2D<int>(w, 0));
01006 }
01007 
01008 // ######################################################################
01009 // Only for display current heading
01010 Image<PixRGB<byte> > CornerNavigation::drawInfoImg()
01011 {
01012   char buffer[128];
01013   Image<PixRGB<byte> > dirImg(320,240,ZEROS);
01014 
01015   its_Corner_Loc_mutex.lock();
01016   int dbNum = itsDBnum;
01017   int status = itsStatus;
01018   its_Corner_Loc_mutex.unlock();
01019 
01020   // return if currently not turning
01021   sprintf(buffer, "DB# :[%d] Status:[%d]", dbNum, status);
01022   writeText(dirImg, Point2D<int>(10,70),
01023             buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01024             SimpleFont::FIXED(8));
01025   if (dbNum == -1) return dirImg;
01026 
01027   // heading direction
01028   if(itsDir == 0)    { sprintf(buffer, "||| "); }
01029   else if(itsDir > 0){ sprintf(buffer, "--> "); }
01030   else               { sprintf(buffer, "<-- "); }
01031   writeText(dirImg, Point2D<int>(dirImg.getWidth()/2-20,
01032                                  dirImg.getHeight()/2-20),
01033             buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01034             SimpleFont::FIXED(20));
01035 
01036   // vote count
01037   sprintf(buffer, "[%d]",itsDirCount);
01038   writeText(dirImg, Point2D<int>(dirImg.getWidth()/2-10,
01039                                  dirImg.getHeight()/2+40),
01040             buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01041             SimpleFont::FIXED(20));
01042 
01043   // error rate
01044   sprintf(buffer, "False Error Rate:[%1.3f]",itsFalseErrRate);
01045   writeText(dirImg, Point2D<int>(10,10),
01046             buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01047             SimpleFont::FIXED(8));
01048   if(itsEstop)
01049     {
01050       sprintf(buffer, "Match:[%d]",itsMatchList->size());
01051       writeText(dirImg, Point2D<int>(210,10),
01052                 buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01053                 SimpleFont::FIXED(8));
01054     }
01055   sprintf(buffer, "Error:[%1.3f] X:[%1.3f] Y:[%1.3f]",
01056           itsError.z,itsError.x,itsError.y);
01057   writeText(dirImg, Point2D<int>(10,25),
01058             buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01059             SimpleFont::FIXED(8));
01060 
01061   // check if the match is valid
01062   if (itsEstop && itsMatchList->checkSIFTaffine())
01063     {
01064       float theta, sx, sy, str;
01065       itsMatchList->getSIFTaffine().decompose(theta, sx, sy, str);
01066       sprintf(buffer, "Affine T:[%1.3f] X:[%1.3f] Y:[%1.3f]",theta,sx,sy);
01067       writeText(dirImg, Point2D<int>(10,40),
01068                 buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01069                 SimpleFont::FIXED(8));
01070     }
01071   sprintf(buffer, "Motor Speed :[%1.3f] Motor Rot:[%1.3f]",
01072           itsTransSpeed, itsRotSpeed);
01073   writeText(dirImg, Point2D<int>(10,55),
01074             buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
01075             SimpleFont::FIXED(8));
01076   return dirImg;
01077 }
01078 
01079 // ######################################################################
01080 void CornerNavigation::updatePosition(double turn)
01081 {
01082   itsDirVector += turn;
01083   if(itsDirVector > 360.0) itsDirVector = 0.0;
01084   if(itsDirVector < 0.0) itsDirVector = 360.0;
01085 
01086   itsPosition.x -= sin(itsDirVector*(M_PI/180.0));
01087   itsPosition.y -= cos(itsDirVector*(M_PI/180.0));
01088 }
01089 
01090 // ######################################################################
01091 void CornerNavigation::updateMessage
01092 (const RobotSimEvents::EventMessagePtr& eMsg, const Ice::Current&)
01093 {
01094 //   // camera message
01095 //   if(eMsg->ice_isA("::BeobotEvents::CameraMessage"))
01096 //     {
01097 //       // store the image
01098 //       BeobotEvents::CameraMessagePtr cameraMsg =
01099 //         BeobotEvents::CameraMessagePtr::dynamicCast(eMsg);
01100 
01101 //       int currRequestID = cameraMsg->RequestID;
01102 //       Image<PixRGB<byte> > img = Ice2Image<PixRGB<byte> >(cameraMsg->image);
01103 
01104 //       LDEBUG("Got a CameraMessage with Request ID = %d", currRequestID);
01105 
01106 //       its_Curr_Img_mutex.lock();
01107 //       itsCurrImg = img;
01108 //       itsCurrImgID = cameraMsg->RequestID;
01109 //       its_Curr_Img_mutex.unlock();
01110 //     }
01111 
01112   // Get a gist-sal message
01113   if(eMsg->ice_isA("::BeobotEvents::GistSalMessage"))
01114   {
01115     BeobotEvents::GistSalMessagePtr gistSalMsg =
01116       BeobotEvents::GistSalMessagePtr::dynamicCast(eMsg);
01117 
01118     // Get the current request ID
01119     int currRequestID = gistSalMsg->RequestID;
01120     Image<PixRGB<byte> > img = Ice2Image<PixRGB<byte> >(gistSalMsg->currIma);
01121 
01122     its_Curr_Img_mutex.lock();
01123     itsCurrImg = img;
01124     itsCurrImgID = gistSalMsg->RequestID;
01125     its_Curr_Img_mutex.unlock();
01126 
01127     LINFO("Got a GSMessage with Request ID = %d", currRequestID);
01128   }
01129 
01130   // motor message
01131   else if(eMsg->ice_isA("::BeobotEvents::MotorMessage"))
01132     {
01133       BeobotEvents::MotorMessagePtr mtrMsg =
01134         BeobotEvents::MotorMessagePtr::dynamicCast(eMsg);
01135       LDEBUG("Got a MotorMessage with Request ID = %d: RC Trans %f, Rot %f",
01136              mtrMsg->RequestID, itsRcTransSpeed, itsRcRotSpeed);
01137       its_Curr_Mtr_mutex.lock();
01138       itsRemoteMode = mtrMsg->rcMode;
01139       itsRcTransSpeed = mtrMsg->rcTransVel;
01140       itsRcRotSpeed = mtrMsg->rcRotVel;
01141       its_Curr_Mtr_mutex.unlock();
01142     }
01143 
01144   // corner location message
01145   else if(eMsg->ice_isA("::BeobotEvents::CornerLocationMessage"))
01146     {
01147       BeobotEvents::CornerLocationMessagePtr clMsg =
01148         BeobotEvents::CornerLocationMessagePtr::dynamicCast(eMsg);
01149       LINFO("Turn on on corner %d", clMsg->cornerLocation);
01150 
01151       // check if the corner location exceed the maximum index
01152       int index = clMsg->cornerLocation;
01153       LINFO("Got Corner location Message Corner:[%d]",index);
01154 
01155       //only take new command if corner system is not running
01156       its_Corner_Loc_mutex.lock();
01157       int status = itsStatus;
01158       its_Corner_Loc_mutex.unlock();
01159 
01160       if(status == C_PROCEDURE_INACTIVE)
01161         {
01162           if(index >= (int)itsVisualObjectDBs.size()) index = -1;
01163           its_Corner_Loc_mutex.lock();
01164           itsStatus = C_PROCEDURE_ACTIVE;
01165           itsTeachImgID = 0;
01166           itsDBnum = index;
01167           its_Corner_Loc_mutex.unlock();
01168         }
01169     }
01170 }
01171 
01172 // ######################################################################
01173 void CornerNavigation::updateMotorPID(double tran, double rot,double error)
01174 {
01175   error/=100.0;
01176   if(itsDir == 1)
01177     error *= -1.0;
01178   double pTerm,iTerm,dTerm;
01179   pTerm = itsPGain * error;
01180   itsIState += error;
01181   if(itsIState > IMAX)
01182     itsIState = IMAX;
01183   else if(itsIState < IMIN)
01184     itsIState = IMIN;
01185   iTerm = itsIGain * itsIState;
01186   dTerm = itsDGain * (rot - itsDState);
01187   itsDState = rot;
01188   double pid = pTerm + iTerm - dTerm;
01189 
01190   LINFO("P[%1.2f] I[%1.2f] D[%1.2f], Istate[%1.2f] DState[%1.2f]",
01191         pTerm,iTerm,dTerm,itsIState,itsDState);
01192   LINFO("pid[%1.2f],rot[%1.2f]",pid,rot);
01193   updateMotor(tran,pid,itsStatus);
01194 }
01195 
01196 // // ######################################################################
01197 // void CornerNavigation::updateMotor(double tran, double rot)
01198 // {
01199 //   BeobotEvents::MotorRequestPtr msg = new BeobotEvents::MotorRequest;
01200 //   msg->transVel = tran;
01201 //   msg->rotVel   = rot;
01202 //   this->publish("MotorRequestTopic", msg);
01203 //   LINFO("[%d] Publish motor request Trans %f Rotation %f",
01204 //         itsPrevProcImgID,tran,rot);
01205 // }
01206 
01207 // ######################################################################
01208 void CornerNavigation::updateMotor(double tran, double rot, int status)
01209 {
01210   BeobotEvents::CornerMotorRequestPtr msg =
01211     new BeobotEvents::CornerMotorRequest;
01212   msg->transVel = tran;
01213   msg->rotVel   = rot;
01214   msg->status   = status;
01215   this->publish("CornerMotorRequestTopic", msg);
01216   LINFO("[%d] Publish corner motor request Trans %f Rotation %f",
01217         itsPrevProcImgID, tran, rot);
01218 }
01219 
01220 // ######################################################################
01221 /* So things look consistent in everyone's emacs... */
01222 /* Local Variables: */
01223 /* indent-tabs-mode: nil */
01224 /* End: */
Generated on Sun May 8 08:41:19 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3