test-UKF.C

Go to the documentation of this file.
00001 /*!@file BayesFilters/test-UKF.C test the filter*/
00002 
00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
00004 // by the 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 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu>
00032 // $HeadURL: $
00033 // $Id: $
00034 
00035 
00036 #include "BayesFilters/UKF.H"
00037 #include "Component/ModelManager.H"
00038 #include "Raster/GenericFrame.H"
00039 #include "Image/Layout.H"
00040 #include "Image/MatrixOps.H"
00041 #include "Image/DrawOps.H"
00042 #include "Image/Point3D.H"
00043 #include "GUI/DebugWin.H"
00044 #include "Util/MathFunctions.H"
00045 #include "Media/FrameSeries.H"
00046 #include "Transport/FrameInfo.H"
00047 
00048 //Create a tracker to track a particle with a position and velocity
00049 class ParticleTracker : public UKF
00050 {
00051   public:
00052     ParticleTracker() : 
00053       UKF(5, 2) //Position (x,y,theta) Vel and 2 observation
00054     {
00055 
00056       //Initial state
00057       itsState.setVal(0,0, 640/2);
00058       itsState.setVal(0,1, 480/2);
00059       itsState.setVal(0,2, 0);
00060       itsState.setVal(0,3, 0);
00061       itsState.setVal(0,4, 0);
00062 
00063       ////Initial covariance 
00064       itsSigma.setVal(0,0,150.0*150.0); //X Position
00065       itsSigma.setVal(1,1,150.0*150.0); //Y Position
00066       itsSigma.setVal(2,2,(1*M_PI/180)*(1*M_PI/180)); //Theta
00067       itsSigma.setVal(3,3,0.01*0.01); //Trans Velocity
00068       itsSigma.setVal(4,4,(1*M_PI/180)*(1*M_PI/180)); //Ang Velocity
00069 
00070 
00071       //Initial noise matrix
00072       double posVar=4.0;
00073       double angVar=1.0*M_PI/180;
00074       double tranVelVar=0.1;
00075       double angVelVar=0.1*M_PI/180;
00076       itsR.setVal(0,0,posVar*posVar);
00077       itsR.setVal(1,1,posVar*posVar);
00078       itsR.setVal(2,2,angVar*angVar);
00079       itsR.setVal(3,3,tranVelVar*tranVelVar);
00080       itsR.setVal(4,4,angVelVar*angVelVar);
00081     }
00082 
00083    ~ParticleTracker() {}; 
00084 
00085    Image<double> getNextState(const Image<double>& X, int k)
00086     {
00087       double posX = X.getVal(k,0);
00088       double posY = X.getVal(k,1);
00089       double ang =  X.getVal(k,2);
00090       double tranVel = X.getVal(k,3);
00091       double angVel = X.getVal(k,4);
00092 
00093       Image<double> Xnew(1,itsNumStates, ZEROS);
00094       double eps = 2.22044604925031e-16;
00095 
00096       double xc = posX - tranVel/(angVel+eps)*sin(ang);
00097       double yc = posY + tranVel/(angVel+eps)*cos(ang);
00098 
00099       posX = xc + tranVel/(angVel+eps)*sin(ang + angVel);
00100       posY = yc - tranVel/(angVel+eps)*cos(ang + angVel);
00101       ang += angVel;
00102 
00103       Xnew[0] = posX;
00104       Xnew[1] = posY;
00105       Xnew[2] = ang;
00106       Xnew[3] = tranVel;
00107       Xnew[4] = angVel;
00108 
00109       return Xnew;
00110     }
00111 
00112    Image<double> getObservation(const Image<double>& X, int k)
00113     {
00114       double posX = X.getVal(k,0);
00115       double posY = X.getVal(k,1);
00116 
00117 
00118       Image<double> zNew(1,itsNumObservations, ZEROS);
00119       zNew[0] = sqrt((posX*posX) + (posY*posY));
00120       zNew[1] = atan2(posY,posX);
00121       return zNew;
00122     }
00123 
00124    void getPosEllipse(Point2D<float>& mu, Point2D<float>& sigma)
00125     {
00126       //Set the Mean
00127       mu.i = itsState[0];
00128       mu.j = itsState[1];
00129 
00130       //Get the 95% uncertainty region
00131       //Set the major/minor axis
00132       sigma = Point2D<float>(2*sqrt(itsSigma.getVal(0,0)),
00133                              2*sqrt(itsSigma.getVal(1,1)));
00134     }
00135 
00136 
00137 };
00138 
00139 
00140 int main(int argc, char *argv[]){
00141 
00142   ModelManager manager("Test UKF");
00143 
00144   nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager));
00145   manager.addSubComponent(ofs);
00146 
00147   // Parse command-line:
00148   if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) return(1);
00149   // let's get all our ModelComponent instances started:
00150   manager.start();
00151 
00152   ParticleTracker pt; //Initialize tracker with 4 states and 2 observations
00153 
00154   //Simulate a moving particle with a particular velocity
00155   Image<PixRGB<byte> > worldImg(640,480,ZEROS);
00156 
00157   Point3D<double> particlePosition(640/2,480/2-100,0); //Initial position
00158   
00159   Point3D<double> distractorPosition(640/2,480/2-100,0); //Initial position
00160 
00161   initRandomNumbersZero(); //For checking for correct values
00162 
00163   Point2D<int> lastParticlePosition;
00164   Point2D<int> lastSensorPosition;
00165   Point2D<int> lastPredictedPosition;
00166   for(uint t=0; t<360; t++)
00167   {
00168     double rangeNoise = 0; //(drand48()*8.0)-4.0;
00169     double angNoise = 0; //(drand48()*4.0)- 2.0;
00170     
00171     //Move the particle along a circular path
00172 
00173     //Center of circle
00174     double dR = 5+rangeNoise;
00175     double dA = (2 + angNoise)*M_PI/180;
00176     double eps = 2.22044604925031e-16;
00177     double distRatio = dR/(dA+eps);
00178     double xc = particlePosition.x - distRatio*sin(particlePosition.z);
00179     double yc = particlePosition.y + distRatio*cos(particlePosition.z);
00180 
00181     particlePosition.x = xc + distRatio*sin(particlePosition.z + dA);
00182     particlePosition.y = yc - distRatio*cos(particlePosition.z + dA);
00183     particlePosition.z += dA;
00184 
00185     //Distractor
00186     double dDR = -5-rangeNoise;
00187     double dDA = (-2 - angNoise)*M_PI/180;
00188     double distDRatio = dDR/(dDA+eps);
00189     double xdc = distractorPosition.x - distDRatio*sin(distractorPosition.z);
00190     double ydc = distractorPosition.y + distDRatio*cos(distractorPosition.z);
00191 
00192     distractorPosition.x = xdc + distDRatio*sin(distractorPosition.z + dDA);
00193     distractorPosition.y = ydc - distDRatio*cos(distractorPosition.z + dDA);
00194     distractorPosition.z += dDA;
00195 
00196     //Set the Sensor noise
00197     double zrn=10.0; 
00198     double zan=5*M_PI/180; //0.5 degrees uncertainty
00199     Image<double> zNoise(2,2,ZEROS);
00200     zNoise.setVal(0,0,zrn*zrn);
00201     zNoise.setVal(1,1,zan*zan);
00202 
00203     pt.predictState();
00204     pt.predictObservation(zNoise);
00205 
00206 
00207     //Compute the measurements
00208     Image<double> z1(1,2,ZEROS);
00209     z1[0] = sqrt(squareOf(particlePosition.x) + squareOf(particlePosition.y));
00210     z1[1] = atan2(particlePosition.y, particlePosition.x);
00211 
00212     z1[0] += 2; //(drand48()*16.0)- 8.0; 
00213     z1[1] += 2*M_PI/180; //((drand48()*5.0) - 2.5)*M_PI/180;
00214 
00215     Image<double> z2(1,2,ZEROS);
00216     z2[0] = sqrt(squareOf(distractorPosition.x) + squareOf(distractorPosition.y));
00217     z2[1] = atan2(distractorPosition.y, distractorPosition.x);
00218 
00219     z2[0] += 3; //(drand48()*10.0)- 5.0; 
00220     z2[1] += 3*M_PI/180; //((drand48()*3.0) - 1.5)*M_PI/180;
00221 
00222     double z1Prob = pt.getLikelihood(z1, Image<double>());
00223     double z2Prob = pt.getLikelihood(z2, Image<double>());
00224 
00225     Image<double> zUsed;
00226     if (z1Prob > 1.0e-5)
00227       zUsed=z1;
00228     if (z2Prob > 1.0e-5)
00229       zUsed=z1;
00230       
00231 
00232     //Store prediction for latter display
00233     Point2D<float> muP, sigmaP;
00234     pt.getPosEllipse(muP,sigmaP);
00235 
00236     pt.update(zUsed, zNoise);
00237 
00238     Point2D<float> mu, sigma;
00239     pt.getPosEllipse(mu,sigma);
00240 
00241     LINFO("True Pos: %f,%f predicted Pos: %f,%f Likelihood: z1 = %f z2 = %f",
00242         particlePosition.x, particlePosition.y,
00243         mu.i, mu.j,
00244         z1Prob, z2Prob);
00245 
00246     //Show the results
00247     Image<PixRGB<byte> > tmp = worldImg;
00248 
00249     //Draw the real particle position
00250     drawCircle(tmp, Point2D<int>(particlePosition.x, particlePosition.y), 2, PixRGB<byte>(0,255,0),2);
00251     drawCircle(tmp, Point2D<int>(distractorPosition.x, distractorPosition.y), 2, PixRGB<byte>(0,255,255),2);
00252     //Show the sensor
00253     Point2D<int> sensorPos(zUsed[0]*cos(zUsed[1]), zUsed[0]*sin(zUsed[1]));
00254     drawCircle(tmp, sensorPos, 2, PixRGB<byte>(0,0,255),2);
00255 
00256     //Show the predicted region
00257     drawCircle(tmp, (Point2D<int>)muP, 1, PixRGB<byte>(255,255,0), 1); 
00258     if (sigmaP.i < 500 && sigmaP.j < 500)
00259       drawEllipse(tmp, (Point2D<int>)muP, sigmaP.i,sigmaP.j, PixRGB<byte>(255,255,0));
00260 
00261     drawCircle(tmp, (Point2D<int>)mu, 1, PixRGB<byte>(255,0,0), 1); 
00262     if (sigma.i < 500 && sigma.j < 500)
00263       drawEllipse(tmp, (Point2D<int>)mu, sigma.i,sigma.j, PixRGB<byte>(255,0,0));
00264 
00265 
00266     //Draw history traces
00267     if (!lastParticlePosition.isValid())
00268       lastParticlePosition = Point2D<int>(particlePosition.x, particlePosition.y);
00269     drawLine(worldImg, lastParticlePosition,
00270         Point2D<int>(particlePosition.x, particlePosition.y),
00271         PixRGB<byte>(0,255,0));
00272     lastParticlePosition = Point2D<int>(particlePosition.x,
00273         particlePosition.y);
00274 
00275     if (!lastSensorPosition.isValid())
00276       lastSensorPosition = sensorPos;
00277     drawLine(worldImg, lastSensorPosition, sensorPos, PixRGB<byte>(0,0,255));
00278     lastSensorPosition = sensorPos;
00279 
00280     if (!lastPredictedPosition.isValid())
00281       lastPredictedPosition = (Point2D<int>)mu;
00282     drawLine(worldImg, lastPredictedPosition, (Point2D<int>)mu, PixRGB<byte>(255,0,0));
00283     lastPredictedPosition = (Point2D<int>)mu;
00284 
00285     ofs->writeRGB(tmp, "Particle Tracker", FrameInfo("Particle Tracker", SRC_POS));
00286     usleep(100000);
00287   }
00288 
00289   manager.stop();
00290   exit(0);
00291 
00292 }
00293 
00294 
Generated on Sun May 8 08:40:11 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3