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 #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
00049 class ParticleTracker : public UKF
00050 {
00051 public:
00052 ParticleTracker() :
00053 UKF(5, 2)
00054 {
00055
00056
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
00064 itsSigma.setVal(0,0,150.0*150.0);
00065 itsSigma.setVal(1,1,150.0*150.0);
00066 itsSigma.setVal(2,2,(1*M_PI/180)*(1*M_PI/180));
00067 itsSigma.setVal(3,3,0.01*0.01);
00068 itsSigma.setVal(4,4,(1*M_PI/180)*(1*M_PI/180));
00069
00070
00071
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
00127 mu.i = itsState[0];
00128 mu.j = itsState[1];
00129
00130
00131
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
00148 if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) return(1);
00149
00150 manager.start();
00151
00152 ParticleTracker pt;
00153
00154
00155 Image<PixRGB<byte> > worldImg(640,480,ZEROS);
00156
00157 Point3D<double> particlePosition(640/2,480/2-100,0);
00158
00159 Point3D<double> distractorPosition(640/2,480/2-100,0);
00160
00161 initRandomNumbersZero();
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;
00169 double angNoise = 0;
00170
00171
00172
00173
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
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
00197 double zrn=10.0;
00198 double zan=5*M_PI/180;
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
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;
00213 z1[1] += 2*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;
00220 z2[1] += 3*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
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
00247 Image<PixRGB<byte> > tmp = worldImg;
00248
00249
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
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
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
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