HippocampusI.C

00001 /*!@file Hippocampus.C maintains the current thought location of the robot */
00002 //This modules invovles in the perception
00003 
00004 //////////////////////////////////////////////////////////////////// //
00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00006 // University of Southern California (USC) and the iLab at USC.         //
00007 // See http://iLab.usc.edu for information about this project.          //
00008 // //////////////////////////////////////////////////////////////////// //
00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00011 // in Visual Environments, and Applications'' by Christof Koch and      //
00012 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00013 // pending; application number 09/912,225 filed July 23, 2001; see      //
00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00015 // //////////////////////////////////////////////////////////////////// //
00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00017 //                                                                      //
00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00019 // redistribute it and/or modify it under the terms of the GNU General  //
00020 // Public License as published by the Free Software Foundation; either  //
00021 // version 2 of the License, or (at your option) any later version.     //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00026 // PURPOSE.  See the GNU General Public License for more details.       //
00027 //                                                                      //
00028 // You should have received a copy of the GNU General Public License    //
00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00031 // Boston, MA 02111-1307 USA.                                           //
00032 // //////////////////////////////////////////////////////////////////// //
00033 //
00034 // Primary maintainer for this file: Lior Elazary <lelazary@yahoo.com>
00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/RobotBrain/HippocampusI.C $
00036 // $Id: HippocampusI.C 10794 2009-02-08 06:21:09Z itti $
00037 //
00038 
00039 #include "Component/ModelManager.H"
00040 #include "Media/FrameSeries.H"
00041 #include "Transport/FrameInfo.H"
00042 #include "Raster/GenericFrame.H"
00043 #include "Image/Image.H"
00044 #include "Image/DrawOps.H"
00045 #include "Image/lapack.H"
00046 #include "Image/MatrixOps.H"
00047 #include "Image/MathOps.H"
00048 #include "GUI/ImageDisplayStream.H"
00049 #include "GUI/DebugWin.H"
00050 #include "Robots/RobotBrain/HippocampusI.H"
00051 #include <math.h>
00052 
00053 
00054 // ######################################################################
00055 HippocampusI::HippocampusI(OptionManager& mgr,
00056     const std::string& descrName, const std::string& tagName) :
00057   ModelComponent(mgr, descrName, tagName),
00058   itsCurrentState(new RobotSimEvents::StateMessage),
00059   itsCurrentGPSPos(new RobotSimEvents::GPSMessage),
00060   itsCurrentMotion(new RobotSimEvents::MotionMessage),
00061   itsCurrentLandmarks(new RobotSimEvents::LandmarksMessage),
00062   itsLastLandmarkState(new RobotSimEvents::StateMessage),
00063   itsLmDistanceMax(0),
00064   itsNumParticles(300),
00065   itsRangeVariance(50),
00066   itsBearingVariance(.5),
00067   itsFrame(0)
00068 {
00069 
00070   itsOfs = nub::ref<OutputFrameSeries>(new OutputFrameSeries(mgr));
00071   addSubComponent(itsOfs);
00072 
00073   //Starting position
00074   itsCurrentState->xPos = 0;
00075   itsCurrentState->yPos = 0;
00076   itsCurrentState->orientation = 0;
00077 
00078   itsLastLandmarkState->xPos = itsCurrentState->xPos;
00079   itsLastLandmarkState->yPos = itsCurrentState->yPos;
00080   itsLastLandmarkState->orientation = itsCurrentState->orientation;
00081 
00082 
00083   itsCurrentGPSPos->xPos = 0;
00084   itsCurrentGPSPos->yPos = 0;
00085   itsCurrentGPSPos->orientation = 0;
00086 
00087   itsCurrentMotion->distance = 0;
00088   itsCurrentMotion->angle = 0;
00089 
00090   itsMap = Image<PixRGB<byte> > (800, 800, ZEROS);
00091 
00092   //Initialize the particles to be at (0,0,0) with equal weight
00093   itsParticles.resize(itsNumParticles);
00094   for(int i=0; i<itsNumParticles; i++)
00095   {
00096     itsParticles.at(i).x     = itsCurrentState->xPos;
00097     itsParticles.at(i).y     = itsCurrentState->yPos;
00098     itsParticles.at(i).theta = itsCurrentState->orientation;
00099     itsParticles.at(i).w     = 1/itsNumParticles;
00100   }
00101 
00102   //init the landmarks
00103   //addLandmark(Landmark(1,  609.6*2, 609.6*7));
00104   //addLandmark(Landmark(2,  609.6*1, 609.6*5));
00105   //addLandmark(Landmark(3,  609.6*1, 609.6*3));
00106   //addLandmark(Landmark(4,  609.6*2, 609.6*2));
00107   //addLandmark(Landmark(5,  609.6*3, 609.6*4));
00108   //addLandmark(Landmark(6,  609.6*4.1, 609.6*2.2));
00109   //addLandmark(Landmark(7,  609.6*5, 609.6*4));
00110   //addLandmark(Landmark(8,  609.6*6, 609.6*4));
00111   //addLandmark(Landmark(9,  609.6*8, 609.6*4));
00112   //addLandmark(Landmark(10, 609.6*8, 609.6*3));
00113   //addLandmark(Landmark(11, 609.6*8, 609.6*6));
00114   //addLandmark(Landmark(12, 609.6*6, 609.6*7));
00115   //addLandmark(Landmark(13, 609.6*4, 609.6*7));
00116 
00117   //addLandmark(Landmark(1,  609.6*2, 609.6*-1));
00118   //addLandmark(Landmark(2,  609.6*4, 609.6*2));
00119   //addLandmark(Landmark(3,  609.6*4, 609.6*0));
00120   //addLandmark(Landmark(4,  609.6*3, 609.6*-1));
00121 
00122   //11_19/Path1
00123   //addLandmark(Landmark("L1",  609.6*2, 609.6*-0.75));
00124   //addLandmark(Landmark("L2",  609.6*-1, 609.6*1));
00125   //addLandmark(Landmark("L3",  609.6*-1, 609.6*4.2));
00126   //addLandmark(Landmark("L4",  609.6*-0.3, 609.6*-1));
00127   //addLandmark(Landmark("L5",  609.6*1, 609.6*5.5));
00128   //addLandmark(Landmark("L6",  609.6*-1.2, 609.6*3));
00129   //addLandmark(Landmark("L7",  609.6*-1.2, 609.6*2));
00130   //addLandmark(Landmark("L8",  609.6*1, 609.6*4));
00131   //addLandmark(Landmark("L9",  609.6*2, 609.6*3));
00132   //addLandmark(Landmark("L10", 609.6*0, 609.6*4));
00133   //addLandmark(Landmark("L11", 609.6*4, 609.6*0));
00134   //addLandmark(Landmark("L12", 609.6*2.2, 609.6*4));
00135   //addLandmark(Landmark("L14", 609.6*2.9, 609.6*6));
00136   //addLandmark(Landmark("L13", 609.6*-1, 609.6*0));
00137 
00138 
00139   //11_21/Path1
00140   Image<double> cov(2,2,ZEROS);
00141   addLandmark(Landmark(string("L1"),  609.6*3,    609.6*-1,   cov));
00142   addLandmark(Landmark(string("L2"),  609.6*-1,   609.6*4,    cov));
00143   addLandmark(Landmark(string("L3"),  609.6*4,    609.6*0,    cov));
00144   addLandmark(Landmark(string("L4"),  609.6*-1.5, 609.6*2,    cov));
00145   addLandmark(Landmark(string("L5"),  609.6*3.5,  609.6*3,    cov));
00146   addLandmark(Landmark(string("L6"),  609.6*1,    609.6*4,    cov));
00147   addLandmark(Landmark(string("L7"),  609.6*3.5,  609.6*1,    cov));
00148   addLandmark(Landmark(string("L8"),  609.6*1,    609.6*5.5,  cov));
00149   addLandmark(Landmark(string("L9"),  609.6*-1.5, 609.6*3,    cov));
00150   addLandmark(Landmark(string("L10"), 609.6*2,    609.6*3,    cov));
00151   addLandmark(Landmark(string("L11"), 609.6*-0.8, 609.6*5,    cov));
00152   addLandmark(Landmark(string("L12"), 609.6*-0.5, 609.6*-1,   cov));
00153   addLandmark(Landmark(string("L13"), 609.6*1,    609.6*-1,   cov));
00154   addLandmark(Landmark(string("L14"), 609.6*2.5,  609.6*6,    cov));
00155 
00156 
00157 }
00158 
00159 // ######################################################################
00160 HippocampusI::~HippocampusI()
00161 {
00162   SimEventsUtils::unsubscribeSimEvents(itsTopicsSubscriptions, itsObjectPrx);
00163 }
00164 
00165 
00166 // ######################################################################
00167 void HippocampusI::init(Ice::CommunicatorPtr ic, Ice::ObjectAdapterPtr adapter)
00168 {
00169 
00170   Ice::ObjectPtr hippPtr = this;
00171   itsObjectPrx = adapter->add(hippPtr,
00172       ic->stringToIdentity("Hippocampus"));
00173 
00174 
00175   IceStorm::TopicPrx topicPrx;
00176 
00177   itsTopicsSubscriptions.push_back(SimEventsUtils::TopicInfo("GPSMessageTopic", topicPrx));
00178   itsTopicsSubscriptions.push_back(SimEventsUtils::TopicInfo("MotionMessageTopic", topicPrx));
00179   itsTopicsSubscriptions.push_back(SimEventsUtils::TopicInfo("LandmarksMessageTopic", topicPrx));
00180 
00181   SimEventsUtils::initSimEvents(ic, itsObjectPrx, itsTopicsSubscriptions);
00182 
00183   itsEventsPub = RobotSimEvents::EventsPrx::uncheckedCast(
00184       SimEventsUtils::getPublisher(ic, "StateMessageTopic")
00185       );
00186 
00187   IceUtil::ThreadPtr hippThread = this;
00188   hippThread->start();
00189 
00190   usleep(10000);
00191 }
00192 
00193 
00194 // ######################################################################
00195 void HippocampusI::run()
00196 {
00197   sleep(1);
00198 
00199   while(1)
00200   {
00201     evolve();
00202     usleep(100000);
00203   }
00204 }
00205 
00206 // ######################################################################
00207 void HippocampusI::evolve()
00208 {
00209   //calculate the new state from the particles (mean)
00210   float xPos = 0, yPos = 0, orientation = 0;
00211   for(int i=0; i<itsNumParticles; i++)
00212   {
00213     xPos += itsParticles.at(i).x;
00214     yPos += itsParticles.at(i).y;
00215     orientation += itsParticles.at(i).theta;
00216   }
00217   xPos        /= itsParticles.size();
00218   yPos        /= itsParticles.size();
00219   orientation /= itsParticles.size();
00220 
00221   itsCurrentState->xPos = xPos;
00222   itsCurrentState->yPos = yPos;
00223   itsCurrentState->orientation = orientation;
00224 
00225   LDEBUG("%f %f %f\n",
00226       itsCurrentState->xPos,
00227       itsCurrentState->yPos,
00228       itsCurrentState->orientation);
00229 
00230   itsEventsPub->updateMessage(itsCurrentState);
00231 }
00232 
00233 // ######################################################################
00234 void HippocampusI::updateMessage(const RobotSimEvents::EventMessagePtr& eMsg, const Ice::Current&)
00235 {
00236   //Get a gps message
00237   if(eMsg->ice_isA("::RobotSimEvents::GPSMessage"))
00238   {
00239     RobotSimEvents::GPSMessagePtr gpsMsg = RobotSimEvents::GPSMessagePtr::dynamicCast(eMsg);
00240     itsCurrentGPSPos->xPos = gpsMsg->xPos;
00241     itsCurrentGPSPos->yPos = gpsMsg->yPos;
00242     itsCurrentGPSPos->orientation = gpsMsg->orientation;
00243   }
00244 
00245   if(eMsg->ice_isA("::RobotSimEvents::MotionMessage"))
00246   {
00247     RobotSimEvents::MotionMessagePtr motionMsg = RobotSimEvents::MotionMessagePtr::dynamicCast(eMsg);
00248     itsCurrentMotion->distance = motionMsg->distance;
00249     itsCurrentMotion->angle = motionMsg->angle;
00250 
00251     updateParticleMotion(itsCurrentMotion);
00252     itsFrame++;
00253 
00254    // printf("%i\t-1\t%f\t%f\n", itsFrame++,
00255    //     itsCurrentMotion->distance,
00256    //     itsCurrentMotion->angle);
00257 
00258   }
00259 
00260   if(eMsg->ice_isA("::RobotSimEvents::LandmarksMessage"))
00261   {
00262 
00263     RobotSimEvents::LandmarksMessagePtr landmarksMsg = RobotSimEvents::LandmarksMessagePtr::dynamicCast(eMsg);
00264     //updateParticleObservation(landmarksMsg);
00265     updateParticleSlamObservation(landmarksMsg);
00266 
00267     itsFrame++;
00268    // for(uint li=0; li<landmarksMsg->landmarks.size(); li++)
00269    // {
00270 
00271    //   printf("%i\t%s\t%f\t%f\n",itsFrame,
00272    //       landmarksMsg->landmarks[li].name.c_str(),
00273    //       landmarksMsg->landmarks[li].range,
00274    //       landmarksMsg->landmarks[li].bearing);
00275    // }
00276 
00277    /////// for(uint i=0; i<itsParticles.size(); i++)
00278    /////// {
00279    ///////   LINFO("%i %f\n",
00280    ///////       i, itsParticles[i].w);
00281    /////// }
00282     ////Save the current landmarks for latter display
00283     itsCurrentLandmarks->landmarks = landmarksMsg->landmarks;
00284 
00285     //find the max particle
00286     int maxP = 0; float maxVal=itsParticles[0].w;
00287     for(uint i=1; i<itsParticles.size(); i++)
00288     {
00289       if (itsParticles[i].w > maxVal)
00290       {
00291         maxVal = itsParticles[i].w;
00292         maxP = i;
00293       }
00294     }
00295 
00296     itsLandmarkDB = itsParticles[maxP].landmarksDB;
00297 
00298 
00299     displayMap();
00300     resampleParticles();
00301 
00302   }
00303   fflush(stdout);
00304 }
00305 
00306 // ######################################################################
00307 void HippocampusI::updateParticleMotion(RobotSimEvents::MotionMessagePtr newMotion)
00308 {
00309   /* Needed
00310      double time; //time for this newMotion, because each sampling is different
00311      double commandF; //forward or backward
00312      double commandS; //steer
00313      */
00314   double alpha[4] = {0.002, 0, 0.2, 0};
00315 
00316   // check out values
00317   //printf("%f %f %f %f %f\n", newMotion->distance, newMotion->angle,
00318   //    itsParticles.at(0).x, itsParticles.at(0).y, itsParticles.at(0).theta);
00319 
00320   //Move each particle according to the motion model, plus some noise
00321   if(abs(newMotion->angle)<10 && abs(newMotion->distance)<25) {
00322     itsParticlesMutex.lock();
00323 
00324     for(int i=0; i<itsNumParticles; i++)
00325     {
00326       //odometry data
00327       float theta = itsParticles.at(i).theta;
00328       float dx = newMotion->distance*cos(theta);
00329       float dy = newMotion->distance*sin(theta);
00330 
00331 //      itsParticles.at(i).x     += dx;
00332 //      itsParticles.at(i).y     += dy;
00333 //      itsParticles.at(i).theta += newMotion->angle*M_PI/180;
00334 //
00335       float rot1  = atan2(dy, dx) - theta;
00336       float trans = sqrt(pow(dx,2)+pow(dy,2));
00337       float rot2  = (theta+newMotion->angle*M_PI/180) - theta - rot1;
00338 
00339       //noise
00340       float nr1 = rot1  - randomDoubleFromNormal(alpha[0]*abs(rot1)+alpha[1]*abs(trans));      //rot1
00341       float ntr = trans - randomDoubleFromNormal(alpha[2]*abs(trans)+alpha[3]*abs(rot1+rot2)); //trans
00342       float nr2 = rot2  - randomDoubleFromNormal(alpha[0]*abs(rot2)+alpha[1]*abs(trans));      //rot2
00343 
00344       //new particle
00345       itsParticles.at(i).x     += ntr*cos(theta+nr1);
00346       itsParticles.at(i).y     += ntr*sin(theta+nr1);
00347       itsParticles.at(i).theta += nr1 + nr2;
00348 
00349       //Bound the angle to -PI <-> PI
00350       if(itsParticles.at(i).theta > M_PI)
00351       {
00352         itsParticles.at(i).theta -= 2*M_PI;
00353 
00354       }
00355       if(itsParticles.at(i).theta < M_PI)
00356       {
00357         itsParticles.at(i).theta += 2*M_PI;
00358       }
00359     }
00360     itsParticlesMutex.unlock();
00361   }
00362 
00363 }
00364 
00365 // ######################################################################
00366 void HippocampusI::updateParticleSlamObservation(RobotSimEvents::LandmarksMessagePtr landmarksMsg)
00367 {
00368   itsParticlesMutex.lock();
00369   float sum = 0;
00370   std::vector<Particle>::iterator particleIt =
00371     itsParticles.begin();
00372 
00373   for(; particleIt != itsParticles.end(); particleIt++)
00374   {
00375     for(uint li=0; li<landmarksMsg->landmarks.size(); li++)
00376     {
00377 
00378       std::string landmarkName = landmarksMsg->landmarks[li].name;
00379       float range = landmarksMsg->landmarks[li].range*1000;
00380       float bearing = landmarksMsg->landmarks[li].bearing;
00381 
00382       //Check to make sure we know about this landmark
00383       std::map<std::string, Landmark>::iterator landIt =
00384         particleIt->landmarksDB.find(landmarkName);
00385 
00386       //Landmark currLand = landIt->second;
00387 
00388       Image<double>  sensorNoise(2,2, ZEROS);
00389       sensorNoise.setVal(0,0, squareOf(500)); //Range noise
00390       sensorNoise.setVal(1,1, squareOf(5*M_PI/180)); //bearing noise
00391 
00392 
00393       //If we don't have the landmark in our database, then let's add it.
00394       if(landIt == particleIt->landmarksDB.end())
00395       {
00396         //initalize landmark mean as u_j = g-1(z,x);
00397 
00398         double landmarkXPos = particleIt->x +  range*cos(bearing + particleIt->theta);
00399         double landmarkYPos = particleIt->y +  range*sin(bearing + particleIt->theta);
00400 
00401         //initalize covariance
00402         double dx = landmarkXPos - particleIt->x;
00403         double dy = landmarkYPos - particleIt->y;
00404         double d2 = squareOf(dx) + squareOf(dy);
00405         double d = sqrt(d2);
00406 
00407 
00408         Image<double> G(2,2, NO_INIT);
00409         G.setVal(0,0, dx/d); G.setVal(1,0, dy/d);
00410         G.setVal(0,1, -dy/d2); G.setVal(1,1, dx/d2);
00411 
00412         Image<double> Ginv = matrixInv(G);
00413 
00414 
00415         Image<double> cov = matrixMult(matrixMult(Ginv,sensorNoise),transpose(Ginv));
00416 
00417         //add the landmark to the DB
00418         Landmark lm(landmarkName, landmarkXPos, landmarkYPos, cov);
00419         particleIt->landmarksDB[landmarkName] = lm;
00420         particleIt->w *= 0.00001;
00421       }
00422       else {
00423 
00424         //Use the Cholesky factorization for the EKF update
00425 
00426         //we have the landmark calculate the change in landmark position
00427         //predict the mesurment z=g(u,x)
00428         double landmarkXPos = landIt->second.posX;
00429         double landmarkYPos = landIt->second.posY;
00430 
00431         double dx = landmarkXPos - particleIt->x;
00432         double dy = landmarkYPos - particleIt->y;
00433         double d2 = squareOf(dx) + squareOf(dy);
00434         double d = sqrt(d2);
00435 
00436         double beliefRange = d;
00437         double beliefBearing = atan2(dy, dx) - particleIt->theta;
00438 
00439         //Limit the angle between -pi to pi
00440         if (beliefBearing < M_PI)
00441         {
00442           beliefBearing += 2*M_PI;
00443         }
00444         if (beliefBearing > M_PI)
00445         {
00446           beliefBearing -= 2*M_PI;
00447         }
00448 
00449 
00450         Image<double> G(2,2, NO_INIT);
00451         G.setVal(0,0, dx/d); G.setVal(1,0, dy/d);
00452         G.setVal(0,1, -dy/d2); G.setVal(1,1, dx/d2);
00453 
00454         Image<double> innov(1,2,NO_INIT);
00455         innov.setVal(0,0, range - beliefRange);
00456         innov.setVal(0,1, bearing - beliefBearing);
00457 
00458 
00459         Image<double> PHt = matrixMult(landIt->second.cov,transpose(G));
00460         Image<double> S = matrixMult(G, PHt) + sensorNoise;
00461 
00462         //Make symmetric
00463         S = S+transpose(S);
00464         S = S *0.5;
00465 
00466         Image<double> SChol = lapack::dpotrf(&S);
00467         SChol.setVal(0,1,0); //Set the bottom left to 0 ?
00468 
00469         Image<double> SCholInv = matrixInv(SChol);
00470 
00471 
00472         Image<double> W1 = matrixMult(PHt, SCholInv);
00473         Image<double> K = matrixMult(W1, transpose(SCholInv));
00474 
00475 
00476         Image<double> dLandmarkPos = matrixMult(K,innov);
00477         landIt->second.posX += dLandmarkPos.getVal(0,0);
00478         landIt->second.posY += dLandmarkPos.getVal(0,1);
00479 
00480         landIt->second.cov -= matrixMult(W1, transpose(W1));
00481 
00482 
00483         Image<double> Q = matrixMult(matrixMult(G, landIt->second.cov),transpose(G)) + sensorNoise;
00484 
00485         Image<double> diffSq = matrixMult(matrixMult(transpose(innov), matrixInv(Q)), innov);
00486 
00487         particleIt->w *= exp(-0.5*diffSq.getVal(0,0)) + 0.001;
00488 
00489       }
00490     }
00491 
00492     sum += particleIt->w;
00493 
00494   }
00495 
00496   //normalize
00497   for(uint i=0; i<itsParticles.size(); i++)
00498     itsParticles.at(i).w /= sum;
00499 
00500   itsParticlesMutex.unlock();
00501 }
00502 
00503 // ######################################################################
00504 void HippocampusI::updateParticleObservation(RobotSimEvents::LandmarksMessagePtr landmarksMsg)
00505 {
00506   itsParticlesMutex.lock();
00507   float sum = 0;
00508   for(int particle=0; particle<itsNumParticles; particle++)
00509   {
00510     for(uint li=0; li<landmarksMsg->landmarks.size(); li++)
00511     {
00512       //Check to make sure we know about this landmark
00513       std::map<std::string, Landmark>::iterator landIt = itsLandmarkDB.find(landmarksMsg->landmarks.at(li).name);
00514 
00515       //If we don't have the landmark in our database, then let's add it.
00516       if(landIt == itsLandmarkDB.end())
00517       {
00518         //addLandmark(landmarksMsg->landmarks.at(li));
00519         continue;
00520       }
00521 
00522       Landmark currLand = landIt->second;
00523 
00524       float bearing =  landmarksMsg->landmarks[li].bearing;
00525       float range   =  landmarksMsg->landmarks[li].range*1000;
00526 
00527       float beliefRange    = sqrt(pow(currLand.posY - itsParticles.at(particle).y, 2) +
00528                                   pow(currLand.posX - itsParticles.at(particle).x, 2));
00529       float beliefBearing  = atan2(currLand.posY - itsParticles.at(particle).y,
00530                                    currLand.posX - itsParticles.at(particle).x)
00531                              - itsParticles.at(particle).theta;
00532 
00533       if (beliefBearing < M_PI)
00534         beliefBearing += 2*M_PI;
00535       if (beliefBearing > M_PI)
00536         beliefBearing -= 2*M_PI;
00537 
00538       float innovRange   = range   - beliefRange;
00539       float innovBearing = bearing - beliefBearing;
00540 
00541 
00542       //TODO:Make this a 2D gaussian
00543       float prob = exp(-0.5*pow(innovRange,   2) / itsRangeVariance  ) + .0001;
00544       prob =   exp(-0.5*pow(innovBearing, 2) / itsBearingVariance) + .0001;
00545 
00546       itsParticles.at(particle).w = prob;
00547       //LINFO("%i %f\n", particle, prob);
00548     }
00549     sum += itsParticles.at(particle).w;
00550   }
00551 
00552   //normalize
00553   for(uint i=0; i<itsParticles.size(); i++)
00554     itsParticles.at(i).w /= sum;
00555 
00556   itsParticlesMutex.unlock();
00557 }
00558 
00559 // ######################################################################
00560 void HippocampusI::addLandmark(Landmark lm)
00561 {
00562   //Initalize the landmark position with a fixed range
00563   LINFO("Adding Landmark %s pos", lm.name.c_str());
00564   itsGTLandmarkDB[lm.name] = lm;
00565 }
00566 
00567 
00568 
00569 // ######################################################################
00570 void HippocampusI::resampleParticles()
00571 {
00572   //Use a roulette wheel to probabilistically duplicate particles with high weights,
00573   //and discard those with low weights
00574   itsParticlesMutex.lock();
00575 
00576   std::vector<Particle> newParticles;
00577 
00578   //Calculate a Cumulative Distribution Function for our particle weights
00579   std::vector<float> CDF;
00580   CDF.resize(itsParticles.size());
00581 
00582   CDF.at(0) = itsParticles.at(0).w;
00583   for(uint i=1; i<CDF.size(); i++)
00584     CDF.at(i) = CDF.at(i-1) + itsParticles.at(i).w;
00585 
00586   uint i = 0;
00587   float u = randomDouble()* 1.0/float(itsParticles.size());
00588 
00589   for(uint j=0; j < itsParticles.size(); j++)
00590   {
00591     while(u > CDF.at(i))
00592       i++;
00593 
00594     Particle p = itsParticles.at(i);
00595     p.w     = 1.0/float(itsParticles.size());
00596 
00597     newParticles.push_back(p);
00598 
00599     u += 1.0/float(itsParticles.size());
00600   }
00601 
00602   itsParticles = newParticles;
00603 
00604   itsParticlesMutex.unlock();
00605 }
00606 
00607 // ######################################################################
00608 void HippocampusI::displayMap()
00609 {
00610   int circRadius = 10;
00611   Image<PixRGB<byte> > tmpMap = itsMap;
00612 
00613 
00614  // //Graph the average distance between known landmarks, and their ground truthed positions
00615  // if(itsGTLandmarkDB.size() > 0) {
00616  //   std::map<std::string, Landmark>::iterator lIt = itsLandmarkDB.begin();
00617  //   float lmDistance = 0.0;
00618  //   for(;lIt != itsLandmarkDB.end(); lIt++)
00619  //   {
00620  //     //Make sure we have a ground truth of the found landmark
00621  //     std::map<std::string, Landmark>::iterator matchIt = itsGTLandmarkDB.find(lIt->second.name);
00622  //     if(matchIt != itsLandmarkDB.end())
00623  //     {
00624  //       lmDistance += sqrt(
00625  //           squareOf(matchIt->second.posX - lIt->second.posX) +
00626  //           squareOf(matchIt->second.posY - lIt->second.posY)
00627  //           );
00628  //     }
00629  //   }
00630  //   if(lmDistance > itsLmDistanceMax)
00631  //     itsLmDistanceMax = lmDistance;
00632 
00633  //   itsLmDistanceHistory.push_back(lmDistance);
00634  //
00635  //   Image<PixRGB<byte> > distanceGraph = linePlot(itsLmDistanceHistory, tmpMap.getWidth(), 150, 0, itsLmDistanceMax, "t");
00636  //   itsOfs->writeRGB(distanceGraph, "DistanceGraph", FrameInfo("DistanceGraph", SRC_POS));
00637  // }
00638 
00639   Image<float> probMap(itsMap.getDims(), ZEROS);
00640 
00641   //Draw the State on the map;
00642   float scale = 1.0/7.0;
00643   Point2D<int> offset((int)(609.6*3.0*scale), (int)(609.6*2.0*scale));
00644 
00645   Point2D<int> p1 = Point2D<int>(scale*609.6*0   , scale*609.6*0) + offset;
00646   Point2D<int> p2 = Point2D<int>(scale*609.6*3   , scale*609.6*0) + offset;
00647   Point2D<int> p3 = Point2D<int>(scale*609.6*3   , scale*609.6*5) + offset;
00648   Point2D<int> p4 = Point2D<int>(scale*609.6*-0.5, scale*609.6*5) + offset;
00649   Point2D<int> p5 = Point2D<int>(scale*609.6*-0.5, scale*609.6*0) + offset;
00650 
00651   drawLine(tmpMap, p1, p2, PixRGB<byte>(50,50,50));
00652   drawLine(tmpMap, p2, p3, PixRGB<byte>(50,50,50));
00653   drawLine(tmpMap, p3, p4, PixRGB<byte>(50,50,50));
00654   drawLine(tmpMap, p4, p5, PixRGB<byte>(50,50,50));
00655   drawLine(tmpMap, p5, p1, PixRGB<byte>(50,50,50));
00656 
00657   //Draw the particles on the map
00658   for(uint particle=0; particle<itsParticles.size(); particle++) {
00659     Point2D<int> particlePos( itsParticles.at(particle).x*scale,
00660         itsParticles.at(particle).y*scale);
00661     float prob = itsParticles.at(particle).w;
00662     if (probMap.coordsOk(offset + particlePos))
00663         probMap.setVal(offset + particlePos, prob);
00664   }
00665 
00666   //Draw the ground truth landmarks on the map
00667   std::map<std::string, Landmark>::iterator landIt = itsGTLandmarkDB.begin();
00668   for(;landIt != itsGTLandmarkDB.end(); ++landIt)
00669   {
00670     Point2D<int> lmPos(
00671         (*landIt).second.posX * scale,
00672         (*landIt).second.posY * scale
00673         );
00674     drawCross(tmpMap, lmPos + offset, PixRGB<byte>(0,100, 0));
00675 
00676   }
00677 
00678 
00679   //Draw the leading particle's landmarks on the map
00680   landIt = itsLandmarkDB.begin();
00681   for(;landIt != itsLandmarkDB.end(); ++landIt)
00682   {
00683     Point2D<int> lmPos(
00684         (*landIt).second.posX * scale,
00685         (*landIt).second.posY * scale
00686         );
00687 
00688     if(tmpMap.coordsOk(offset+lmPos) &&
00689         tmpMap.coordsOk(offset+lmPos+Point2D<int>(landIt->second.name.size()*10, circRadius*2.5)))
00690     {
00691       Image<PixRGB<byte> > labelImage(landIt->second.name.size()*10, circRadius*2.5, ZEROS);
00692 
00693       drawCircle(labelImage, Point2D<int>(circRadius,circRadius), circRadius, PixRGB<byte>(0,0,150),0);
00694 
00695       writeText(
00696           labelImage,
00697           Point2D<int>(circRadius/2,circRadius/2),
00698           landIt->second.name.c_str(),
00699           PixRGB<byte>(75,75,255),
00700           PixRGB<byte>(0,0,0),
00701           SimpleFont::FIXED(6),
00702           true
00703           );
00704 
00705       labelImage = flipVertic(labelImage);
00706       inplacePaste(tmpMap, labelImage, offset+lmPos-Point2D<int>(circRadius, circRadius));
00707     }
00708   }
00709 
00710   //draw the lines to the landmark
00711   for(uint li=0; li<itsCurrentLandmarks->landmarks.size(); li++)
00712   {
00713     float bearing = itsCurrentLandmarks->landmarks[li].bearing;
00714     float range = (itsCurrentLandmarks->landmarks[li].range*1000);
00715 
00716     float posX = itsCurrentState->xPos + (range*cos(itsCurrentState->orientation + bearing));
00717     float posY = itsCurrentState->yPos + (range*sin(itsCurrentState->orientation + bearing));
00718 
00719     drawLine(tmpMap,
00720         offset + Point2D<int>((int)(itsCurrentState->xPos*scale),
00721           ((int)(itsCurrentState->yPos*scale))),
00722         offset + Point2D<int>((int)(posX*scale), ((int)(posY*scale))),
00723         PixRGB<byte>(0,0,255));
00724   }
00725 
00726   Point2D<int> posOnMap((int)(itsCurrentState->xPos*scale),
00727       (int)( itsCurrentState->yPos*scale));
00728 
00729   //Draw the robot
00730   if (itsMap.coordsOk(offset + posOnMap))
00731   {
00732     itsMap.setVal(offset + posOnMap, PixRGB<byte>(255,0,0));
00733     drawDisk(tmpMap, offset + posOnMap, 10, PixRGB<byte>(100,200,100));
00734 
00735     Point2D<int> robotAng(int(cos(itsCurrentState->orientation)*9),
00736                           int(sin(itsCurrentState->orientation)*9));
00737 
00738     drawLine(tmpMap, offset + posOnMap, offset + posOnMap + robotAng, PixRGB<byte>(0,0,0), 2);
00739   }
00740 
00741   inplaceNormalize(probMap, 0.0F, 255.0F);
00742 
00743   //Print out the frame number and the believed robot position
00744   printf("%d %d %d ", itsFrame, posOnMap.i, posOnMap.j);
00745   std::map<std::string, Landmark>::iterator gtIt = itsGTLandmarkDB.begin();
00746   for(;gtIt != itsGTLandmarkDB.end(); gtIt++) {
00747     //Print out the name of this landmark
00748     printf("%s ", gtIt->second.name.c_str());
00749 
00750     //See if our current landmark DB knows about this ground truth
00751     std::map<std::string, Landmark>::iterator lIt = itsLandmarkDB.find(gtIt->second.name);
00752 
00753     if(lIt == itsLandmarkDB.end())
00754     {
00755       //If it does not, then output zeros for the position
00756       printf("0 0 ");
00757     }
00758     else
00759     {
00760       //If it does, then print out the believed position of this landmark
00761       printf("%f %f ", lIt->second.posX, lIt->second.posY);
00762     }
00763   }
00764   printf("\n");
00765 
00766 
00767   itsOfs->writeRGB(flipVertic(tmpMap), "Map", FrameInfo("Map", SRC_POS));
00768   itsOfs->writeRGB(flipVertic(toRGB(probMap)), "ProbMap", FrameInfo("Map", SRC_POS));
00769 }
00770 
Generated on Sun May 8 08:05:56 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3