CParticleFilter.cpp
Go to the documentation of this file.
00001 
00005 #include "ndt_mcl/CParticleFilter.h"
00006 
00007 using namespace mcl;
00008 
00009 CParticleFilter::CParticleFilter(){
00010     Particles=NULL;
00011     Lik=0;
00012     outLiers=0;
00013     NumOfParticles=0;
00014     size=0;
00015     isAvgSet = false;
00016 }
00017 CParticleFilter::~CParticleFilter(){
00018     //myfree();
00019 }
00020 
00025 void CParticleFilter::allocate(int num_particles){
00026     Particles = (TPoseParticle *) malloc(sizeof(TPoseParticle)*num_particles);
00027     //fprintf(stderr,"CParticleFilter::allocate():: Called and reserved %d bytes memory = %d particles\n", sizeof(TPoseParticle)*num_particles,num_particles );
00028     if(!Particles){
00029         fprintf(stderr,"Failed to reserve memory - exiting\n");
00030         exit(1);
00031     }
00032 
00033     tmp = (TPoseParticle *) malloc(sizeof(TPoseParticle)*num_particles);
00034 
00035     if(!tmp){
00036         fprintf(stderr,"Failed to reserve memory - exiting\n");
00037         exit(1);
00038     }
00039 
00040     size = num_particles;
00041     NumOfParticles=0;
00042     outLiers = 0;
00043     Lik=0;
00044 }
00048 void CParticleFilter::myfree(){
00049     if(Particles) free(Particles);
00050     if(tmp) free(tmp);
00051     size = 0; 
00052     NumOfParticles = 0;
00053 }
00054 
00059 mcl::pose CParticleFilter::getDistributionMean(bool doWeighting){
00060     double sumX=0,sumY=0,sumA=0;
00061     int i;
00062     mcl::pose pos;
00063     double sumW=0;                      
00064     isAvgSet = true;
00065 
00066     double dsum_a=0;
00067 
00068     double ax=0,ay=0;   
00069     if(doWeighting){
00070         for(i=0;i<NumOfParticles;i++){
00071             sumX += (double)Particles[i].p*(double)Particles[i].x;
00072             sumY += (double)Particles[i].p*(double)Particles[i].y;
00073             ax += (double)Particles[i].p * cos(Particles[i].a);
00074             ay += (double)Particles[i].p * sin(Particles[i].a);         
00075             sumW += (double)Particles[i].p; 
00076         }
00077 
00078         if(fabs(sumA)>10000){ 
00079             fprintf(stderr,"GANSKA ISOA (%.2f %.2f %.2f)\n",sumX,sumY,sumA);
00080             //usleep(1000*1000*10);
00081         }
00082         if( fabs(sumW-1.0)> 0.01){ 
00083             fprintf(stderr,"getDistributionMean::SUMW=%.2f\n",sumW); exit(1);
00084         }
00085         pos.set(sumX,sumY,atan2(ay,ax));
00086         //pos.toPI();
00087     }else{ 
00088         for(i=0;i<NumOfParticles;i++){
00089             sumX += Particles[i].x;
00090             sumY += Particles[i].y;
00091             ax += cos(Particles[i].a);
00092             ay += sin(Particles[i].a);
00093 
00094 
00095         }
00096         if(NumOfParticles==0) fprintf(stderr,"CParticleFilter::getDistributionMean():: WTF!!!!\n");
00097         pos.x = sumX / (float) NumOfParticles;
00098         pos.y = sumY / (float) NumOfParticles;
00099         pos.a =  atan2(ay,ax);
00100     }
00101     pos.toPI();                         
00102     average = pos;
00103 
00104     return pos;
00105 }
00106 
00113 Eigen::Matrix3d CParticleFilter::getDistributionVariances(){
00114     mcl::pose avg;
00115     int i;
00116 
00117     if(isAvgSet) avg = average;
00118     else avg = getDistributionMean();
00119 
00120     double xx = 0, yy=0, xy=0, aax=0, aay=0;
00121     double ax = cos(avg.a);
00122     double ay = sin(avg.a);
00123     double w2 = 0;
00124 
00125 
00126     for(i=0;i<NumOfParticles;i++){
00127         xx += Particles[i].p*(Particles[i].x - avg.x)*(Particles[i].x - avg.x);
00128         yy += Particles[i].p*(Particles[i].y - avg.y)*(Particles[i].y - avg.y);
00129         xy += Particles[i].p*(Particles[i].x - avg.x)*(Particles[i].y - avg.y);
00130 
00131         aax += Particles[i].p*(cos(Particles[i].a) - ax)*(cos(Particles[i].a) - ax);
00132         aay += Particles[i].p*(sin(Particles[i].a) - ay)*(sin(Particles[i].a) - ay);
00133         w2 += Particles[i].p * Particles[i].p;
00134     }
00135 
00136     if(w2 == 1.0){
00137         fprintf(stderr,"CParticleFilter::getDistributionVariances -- w2=%lf Should not happen!\n",w2);
00138         w2 = 0.99;
00139     }
00140     double wc = 1.0 / (1.0 - w2);
00141 
00142     Eigen::Matrix3d cov;
00143     cov << wc*xx , wc*xy , 0,
00144         wc*xy , wc*yy , 0,
00145         0     , 0     , atan2(wc*aay, wc*aax);
00146 
00147     return cov;
00148 }
00149 
00150 
00151 
00152 
00157 void CParticleFilter::initializeNormalRandom(mcl::pose p0, mcl::pose variance,int size){
00158     int i;
00159 
00160     if(this->size != size){
00161         this->allocate(size);
00162     }
00163     for(i=0;i<size;i++){
00164         Particles[i].x = p0.x + myrand.normalRandom() * variance.x;
00165         Particles[i].y = p0.y + myrand.normalRandom() * variance.y;
00166         Particles[i].a = p0.a + myrand.normalRandom() * variance.a;
00167         Particles[i].lik = 1.0;
00168         Particles[i].p = 1.0 / size;
00169         Particles[i].toPI();
00170     }
00171     NumOfParticles = size;
00172     isAvgSet = false;
00173 }
00174 
00182 void CParticleFilter::initializeUniform(mcl::pose Pmin, mcl::pose Pmax, mcl::pose dP){
00183     int Nx,Ny,Na; 
00184     int i,j,k;
00185 
00186     if(dP.x==0 || dP.y==0 || dP.a==0){
00187         fprintf(stderr,"initializeUniform():: Invalid argument\n");
00188         return;
00189     }
00190 
00191     Nx = (int)((Pmax.x - Pmin.x)/dP.x);
00192     Ny = (int)((Pmax.y - Pmin.y)/dP.y);
00193     Na = (int)((Pmax.a - Pmin.a)/dP.a);
00195     if(Nx == 0) Nx = 1;
00196     if(Ny == 0) Ny = 1;
00197     if(Na == 0) Na = 1;
00198 
00199     fprintf(stderr,"initializeUniform()::Allocating (%d * %d * %d) =  %d particles\n",Nx,Ny,Na,Nx*Ny*Na);
00200     this->allocate(Nx*Na*Ny);
00201 
00202     for(i=0;i<Nx;i++){
00203         for(j=0;j<Ny;j++){
00204             for(k=0;k<Na;k++){
00205                 Particles[NumOfParticles].x = Pmin.x + dP.x*i;
00206                 Particles[NumOfParticles].y = Pmin.y + dP.y*j;
00207                 Particles[NumOfParticles].a = Pmin.a + dP.a*k;
00208                 Particles[NumOfParticles].lik = 1.0;
00209                 Particles[NumOfParticles].p = 1.0 / (Nx*Ny*Na);
00210                 Particles[NumOfParticles].toPI();
00211                 NumOfParticles++;
00212             }
00213         }
00214     }
00215     isAvgSet = false;
00216 }
00226 void CParticleFilter::SIRUpdate(){
00227     TPoseParticle *tmp2;
00228     float U=0,Q=0;
00229     int i=0,j=0,k=0;
00230 
00231     U = myrand.uniformRandom() / (float) NumOfParticles;
00232     //fprintf(stderr,"SIRUpdate()::U=%.6f\n",U);
00233     while(U < 1.0){
00234 
00235         if(Q>U){
00236             U += 1.0/NumOfParticles;
00237 
00238             if(k>=NumOfParticles || i>=NumOfParticles){
00239                 while(i<NumOfParticles){
00240                     tmp[i]=Particles[NumOfParticles-1];
00241                     tmp[i].p = 1.0 / NumOfParticles;
00242                     i++;
00243                 }
00244                 //fprintf(stderr,"ERROR: SIRupdate:: Invalid index k='%d' or i='%d'\n",k,i);
00245                 tmp2 = Particles;
00246                 Particles = tmp;
00247                 tmp = tmp2;
00248                 return;        
00249             }
00250             tmp[i]=Particles[k];
00251             tmp[i].p = 1.0 / NumOfParticles;
00252             i++;
00253         }
00254         else{
00255             j++;
00256             k=j;
00257             if(j>=NumOfParticles){
00258                 while(i<NumOfParticles){
00259                     tmp[i]=Particles[NumOfParticles-1];
00260                     tmp[i].p = 1.0 / NumOfParticles;
00261                     i++;
00262                 }
00263                 //fprintf(stderr,"ERROR: SIRupdate:: Invalid index j='%d' \n",j);
00264                 tmp2 = Particles;
00265                 Particles = tmp;
00266                 tmp = tmp2;
00267                 return;        
00268             }
00269             Q += Particles[j].p;
00271 
00272             if(j==NumOfParticles){
00273                 while(i<NumOfParticles){
00274                     tmp[i]=Particles[k-1];
00275                     tmp[i].p = 1.0 / NumOfParticles;
00276                     i++;
00277                 }
00278                 tmp2 = Particles;
00279                 Particles = tmp;
00280                 tmp = tmp2;
00281                 return;
00282             }
00283         }
00284     }//While
00285     while(i<NumOfParticles){
00286         if(k>=NumOfParticles) k=NumOfParticles-1;
00287         tmp[i]=Particles[k];
00288         tmp[i].p = 1.0 / NumOfParticles;
00289         i++;
00290     }
00291     isAvgSet = false;
00292     tmp2 = Particles;
00293     Particles = tmp;
00294     tmp = tmp2;
00295 }
00296 
00303 void CParticleFilter::normalize(){
00304     int i;
00305     double summ=0;
00306     isAvgSet = false;
00307     for(i=0;i<NumOfParticles;i++){
00308         Particles[i].p *= Particles[i].lik; 
00309         summ+=Particles[i].p;
00310     }
00311     if(summ != 0){
00312         for(i=0;i<NumOfParticles;i++){
00313             Particles[i].p = Particles[i].p/summ;
00314         }
00315     }else{
00316         for(i=0;i<NumOfParticles;i++){
00317             Particles[i].p = 1.0/NumOfParticles;
00318         }
00319     }
00320 }
00321 
00322 
00330 void CParticleFilter::predict(mcl::pose dP, mcl::pose std){
00331     int i;
00332     float dx=0.0,dy=0.0,dl=0.0;
00333     float a=0.0;
00334 
00335     //dl = sqrt(dP.x*dP.x+dP.y*dP.y);
00336     //a  = atan2(dP.y,dP.x);
00337 
00342     float dxe,dye; 
00343     for(i=0;i<NumOfParticles;i++){
00345         dxe = dP.x + myrand.normalRandom()* std.x;
00346         dye = dP.y + myrand.normalRandom()* std.y;
00347 
00348         dl = sqrt(dxe*dxe+dye*dye);
00349         a  = atan2(dye,dxe);
00350 
00351         dx = dl * cos(Particles[i].a +a );
00352         dy = dl * sin(Particles[i].a +a );
00353 
00354         Particles[i].x = Particles[i].x + dx;
00355         Particles[i].y = Particles[i].y + dy;
00356         Particles[i].a = Particles[i].a + dP.a + myrand.normalRandom()* std.a;
00357         Particles[i].toPI();
00358     }
00359     isAvgSet = false;
00360 }
00361 
00371 void CParticleFilter::predict(mcl::pose dP, float Q[4]){
00372     int i;
00373     float dx,dy,dl;
00374     float cov[3];
00375     float xRand,yRand;
00376     float a,b,c;
00377     float eig1=1,eig2=1;
00378     float vx1,vy1,vx2,vy2;
00379     float d;
00380     float x,y;
00381 
00382     // calculate eigen values
00383     cov[0] = Q[0];
00384     cov[1] = Q[1];
00385     cov[2] = Q[2];
00386 
00387     a = 1.0;
00388     b = -(cov[0]+cov[2]);
00389     c = cov[0]*cov[2] - cov[1]*cov[1];
00390 
00391     if( (b*b-4*c)>=0){
00392         eig1 = (-b + sqrt(b*b-4*a*c))/(2*a);
00393         eig2 = (-b - sqrt(b*b-4*a*c))/(2*a);
00394 
00395         // calculate eigen vectors
00396         if(eig1 != eig2){
00397             vx1 = cov[1];
00398             vy1 = eig1 - cov[0];
00399             d = sqrt(vx1*vx1+vy1*vy1);
00400             vx1 /= d;
00401             vy1 /= d;
00402 
00403             vx2 = cov[1];
00404             vy2 = eig2 - cov[0];
00405             d = sqrt(vx2*vx2+vy2*vy2);
00406             vx2 /= d;
00407             vy2 /= d;
00408         }
00409         else{
00410             vx1 = 1.0;
00411             vx2 = 0.0;
00412             vy1 = 0.0;
00413             vy2 = 1.0;
00414         }
00415 
00416     }
00417     else{
00418         fprintf(stderr,"IMAGINARY EIGEN VALUES\n");
00419         eig1=1;
00420         eig2=1;
00421 
00422         vx1 = 1.0;
00423         vx2 = 0.0;
00424         vy1 = 0.0;
00425         vy2 = 1.0;
00426     }
00427     // Transform the random variable according to the covariance
00428 
00429     dl = sqrt(dP.x*dP.x+dP.y*dP.y);
00430 
00431     for(i=0;i<NumOfParticles;i++){
00432         xRand = myrand.normalRandom();
00433         yRand = myrand.normalRandom();
00434 
00435         x = xRand * sqrt(eig1);
00436         y = yRand * sqrt(eig2);
00437 
00438         xRand = x * vx1 + y * vx2;
00439         yRand = x * vy1 + y * vy2;
00440 
00441         dx = dl * cos(Particles[i].a + dP.a);
00442         dy = dl * sin(Particles[i].a + dP.a);
00443 
00446         float covX,covY,covA,covL;
00447         covL = sqrt(xRand*xRand + yRand*yRand);
00448         covA = atan2(yRand,xRand);
00449         covX = covL * cos(Particles[i].a+covA);
00450         covY = covL * sin(Particles[i].a+covA);
00451 
00452         Particles[i].x = Particles[i].x + dx + covX;
00453         Particles[i].y = Particles[i].y + dy + covY;
00454         Particles[i].a = Particles[i].a + dP.a + myrand.normalRandom()* Q[3];
00455         Particles[i].toPI();
00456     }
00457     isAvgSet = false;
00458 }
00459 
00469 void CParticleFilter::updateLikelihood(float *lik){
00470     int i;
00471     for(i=0;i<NumOfParticles;i++){
00472         Particles[i].lik = lik[i];
00473     }
00474     isAvgSet = false;
00475 }
00476 
00480 void CParticleFilter::print(){
00481     getDistributionMean();
00482     getDistributionVariances();
00483     fprintf(stderr,"Filter:: size=%d, AVG:(%.1f,%.1f,%.1f), VAR:(%.1f,%.1f,%.1f)\n",size, average.x,
00484             average.y,average.a, variance.x,variance.y,variance.a);
00485 }
00486 
00487 
00488 
00495 void CParticleFilter::resize(int n){
00496     int i;
00497     TPoseParticle *tmp2;
00498     int *ind = (int *) malloc(NumOfParticles * sizeof(int));
00499     for(i=0;i<NumOfParticles;i++) ind[i] = i;
00500     hpsrt(ind); 
00501     for(i=0;i<10;i++) fprintf(stderr,"%d ",ind[i]);
00502 
00503     fprintf(stderr,"The best p=%f and worst %f \n",Particles[ind[0]].p,Particles[ind[NumOfParticles-1]].p);
00504 
00505     for(i=0;i<n;i++){
00506         tmp[i] = Particles[ind[NumOfParticles-1-i]];
00507     }
00508 
00509 
00510     tmp2 = Particles;
00511     Particles = tmp;
00512     tmp = tmp2; 
00513     NumOfParticles = n; 
00514     free(ind);
00515     fprintf(stderr,"Filter resized. New size=%d. The Pb=%f Pw=%f\n",n,Particles[0].p,Particles[NumOfParticles-1].p);
00516 
00517 }
00518 
00519 mcl::pose CParticleFilter::averageOverNBestAndRandomize(int N, int M,float vx,float vy,float va){
00520 
00521     if(N>=NumOfParticles){
00522         return getDistributionMean(true);
00523     }
00524     mcl::pose avg;
00525     if(N<=0) return avg;
00526     int *ind = (int *) malloc(NumOfParticles * sizeof(int));
00527 
00528     for(int i=0;i<NumOfParticles;i++) ind[i] = i;
00529     hpsrt(ind); 
00530     avg.x = 0;
00531     avg.y = 0;
00532     avg.a = 0;
00533     float ax=0,ay=0;
00534 
00535     for(int i=0;i<N;i++){
00536         avg.x+=Particles[ind[i]].x;
00537         avg.y+=Particles[ind[i]].y;
00538         ax += cos(Particles[ind[i]].a);
00539         ay += sin(Particles[ind[i]].a);
00540     }
00541 
00542     avg.x/=N;
00543     avg.y/=N;
00544     avg.a = atan2(ay,ax);
00545 
00546     if(M>0 && M<NumOfParticles){
00547         for(int i=NumOfParticles-1;i>NumOfParticles-M;i--){
00548             Particles[ind[i]].x = avg.x + myrand.normalRandom() * vx;
00549             Particles[ind[i]].y = avg.y + myrand.normalRandom() * vy;
00550             Particles[ind[i]].a = avg.a + myrand.normalRandom() * va;
00551         }
00552 
00553     }
00554 
00555 
00556     free(ind);
00557     return avg;
00558 }
00559 
00565 void CParticleFilter::hpsrt(int * indx){
00566     unsigned long i,ir,j,k,ira;
00567     float rra;
00568     float *ra = (float *) malloc(NumOfParticles*sizeof(float));
00569     int n = NumOfParticles;
00570     //Arrange according to the probability
00571     for(i=0;i<NumOfParticles;i++) ra[i] = Particles[i].p; 
00572 
00573     if (n < 1) return;
00574     k=(n >> 1);
00575     ir=n-1;
00576     for (;;) 
00577     {
00578         if(k > 0)
00579         { 
00580             rra=ra[--k];
00581             ira=indx[k];
00582         }
00583         else 
00584         {
00585             rra=ra[ir];
00586             ira=indx[ir];
00587 
00588             ra[ir]=ra[0];
00589             indx[ir]=indx[0];
00590             if (--ir == 0) 
00591             {
00592                 ra[0]=rra; 
00593                 indx[0]=ira; 
00594                 break;
00595             }
00596         }
00597         i=k;
00598         j=k+1;
00599         while (j <= ir)
00600         {
00601             if (j < ir && ra[j] < ra[j+1]) j++;
00602             if (rra < ra[j])
00603             {
00604                 ra[i]=ra[j];
00605                 indx[i]=indx[j];  
00606                 i=j;
00607                 j <<= 1;
00608             } else break;
00609         }
00610         ra[i]=rra;
00611         indx[i]=ira;
00612     }
00613     free(ra);
00614 }
00615 
00616 void CParticleFilter::saveToFile(int Fileind){
00617     char name[20];
00618     FILE *f;
00619 
00620     sprintf(name,"particle%d.tx",Fileind);
00621 
00622     f= fopen(name,"wt");
00623     for(int i=0;i<NumOfParticles;i++){
00624         fprintf(f,"%.3f %.3f %.3f\n",Particles[i].x,Particles[i].y,Particles[i].a);
00625     }
00626     fclose(f);
00627 }
00628 
00629 
00630 
00631 


ndt_mcl
Author(s): Jari Saarinen
autogenerated on Wed Aug 26 2015 15:25:02