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 #ifndef PF_implementations_H
00030 #define PF_implementations_H
00031
00032 #include <mrpt/utils/stl_extensions.h>
00033 #include <mrpt/bayes/CParticleFilterData.h>
00034 #include <mrpt/random.h>
00035 #include <mrpt/slam/CActionCollection.h>
00036 #include <mrpt/slam/CActionRobotMovement3D.h>
00037 #include <mrpt/slam/CActionRobotMovement2D.h>
00038 #include <mrpt/slam/TKLDParams.h>
00039
00040 #include <mrpt/math/distributions.h>
00041
00042 #include <mrpt/slam/PF_implementations_data.h>
00043
00044 #include <mrpt/slam/link_pragmas.h>
00045
00046
00047
00048
00049
00050
00051 namespace mrpt
00052 {
00053 namespace slam
00054 {
00055 using namespace std;
00056 using namespace mrpt::utils;
00057 using namespace mrpt::random;
00058 using namespace mrpt::poses;
00059 using namespace mrpt::bayes;
00060 using namespace mrpt::math;
00061
00062
00063
00064
00065
00066
00067 template <class PARTICLE_TYPE>
00068 template <class BINTYPE>
00069 bool PF_implementation<PARTICLE_TYPE>::PF_SLAM_implementation_gatherActionsCheckBothActObs(
00070 const CActionCollection * actions,
00071 const CSensoryFrame * sf )
00072 {
00073 if (actions!=NULL)
00074 {
00075 {
00076 CActionRobotMovement2DPtr robotMovement2D = actions->getBestMovementEstimation();
00077 if (robotMovement2D.present())
00078 {
00079 if (m_accumRobotMovement3DIsValid) THROW_EXCEPTION("Mixing 2D and 3D actions is not allowed.")
00080
00081 if (!m_accumRobotMovement2DIsValid)
00082 {
00083 robotMovement2D->poseChange->getMean( m_accumRobotMovement2D.rawOdometryIncrementReading );
00084 m_accumRobotMovement2D.motionModelConfiguration = robotMovement2D->motionModelConfiguration;
00085 }
00086 else m_accumRobotMovement2D.rawOdometryIncrementReading += robotMovement2D->poseChange->getMeanVal();
00087
00088 m_accumRobotMovement2DIsValid = true;
00089 }
00090 else
00091 {
00092 CActionRobotMovement3DPtr robotMovement3D = actions->getActionByClass<CActionRobotMovement3D>();
00093 if (robotMovement3D)
00094 {
00095 if (m_accumRobotMovement2DIsValid) THROW_EXCEPTION("Mixing 2D and 3D actions is not allowed.")
00096
00097 if (!m_accumRobotMovement3DIsValid)
00098 m_accumRobotMovement3D = robotMovement3D->poseChange;
00099 else m_accumRobotMovement3D += robotMovement3D->poseChange;
00100
00101
00102 m_accumRobotMovement3DIsValid = true;
00103 }
00104 else
00105 return false;
00106 }
00107 }
00108 }
00109
00110 const bool SFhasValidObservations = (sf==NULL) ? false : PF_SLAM_implementation_doWeHaveValidObservations(m_partdata.m_particles,sf);
00111
00112
00113 if (! ((m_accumRobotMovement2DIsValid || m_accumRobotMovement3DIsValid) && SFhasValidObservations))
00114 return false;
00115
00116
00117
00118 if (m_accumRobotMovement3DIsValid)
00119 {
00120 m_movementDrawer.setPosePDF( m_accumRobotMovement3D );
00121 m_accumRobotMovement3DIsValid = false;
00122 }
00123 else
00124 {
00125 CActionRobotMovement2D theResultingRobotMov;
00126 theResultingRobotMov.computeFromOdometry(
00127 m_accumRobotMovement2D.rawOdometryIncrementReading,
00128 m_accumRobotMovement2D.motionModelConfiguration );
00129
00130 m_movementDrawer.setPosePDF( theResultingRobotMov.poseChange );
00131 m_accumRobotMovement2DIsValid = false;
00132 }
00133 return true;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 template <class PARTICLE_TYPE>
00150 template <class BINTYPE>
00151 void PF_implementation<PARTICLE_TYPE>::PF_SLAM_implementation_pfAuxiliaryPFOptimal(
00152 const CActionCollection * actions,
00153 const CSensoryFrame * sf,
00154 const CParticleFilter::TParticleFilterOptions &PF_options,
00155 const TKLDParams &KLD_options)
00156 {
00157
00158 PF_SLAM_implementation_pfAuxiliaryPFStandardAndOptimal<BINTYPE>(actions,sf,PF_options,KLD_options, true );
00159 }
00160
00161
00162
00163
00164
00165
00166
00167 template <class PARTICLE_TYPE>
00168 template <class BINTYPE>
00169 void PF_implementation<PARTICLE_TYPE>::PF_SLAM_implementation_pfStandardProposal(
00170 const CActionCollection * actions,
00171 const CSensoryFrame * sf,
00172 const CParticleFilter::TParticleFilterOptions &PF_options,
00173 const TKLDParams &KLD_options)
00174 {
00175 MRPT_START
00176 typedef std::set<BINTYPE,typename BINTYPE::lt_operator> TSetStateSpaceBins;
00177
00178
00179
00180
00181
00182
00183
00184 if (actions)
00185 {
00186
00187 CPose3D motionModelMeanIncr;
00188 {
00189 CActionRobotMovement2DPtr robotMovement2D = actions->getBestMovementEstimation();
00190
00191 if (robotMovement2D.present())
00192 {
00193 m_movementDrawer.setPosePDF( robotMovement2D->poseChange );
00194 motionModelMeanIncr = robotMovement2D->poseChange->getMeanVal();
00195 }
00196 else
00197 {
00198 CActionRobotMovement3DPtr robotMovement3D = actions->getActionByClass<CActionRobotMovement3D>();
00199 if (robotMovement3D)
00200 {
00201 m_movementDrawer.setPosePDF( robotMovement3D->poseChange );
00202 robotMovement3D->poseChange.getMean( motionModelMeanIncr );
00203 }
00204 else { THROW_EXCEPTION("Action list does not contain any CActionRobotMovement2D or CActionRobotMovement3D object!"); }
00205 }
00206 }
00207
00208
00209 if ( !PF_options.adaptiveSampleSize )
00210 {
00211 const size_t M = m_partdata.m_particles.size();
00212
00213
00214
00215 CPose3D incrPose;
00216 for (size_t i=0;i<M;i++)
00217 {
00218
00219 m_movementDrawer.drawSample( incrPose );
00220 CPose3D finalPose = CPose3D(*getLastPose(i)) + incrPose;
00221
00222
00223 PF_SLAM_implementation_custom_update_particle_with_new_pose( m_partdata.m_particles[i].d, TPose3D(finalPose) );
00224 }
00225 }
00226 else
00227 {
00228
00229
00230
00231
00232
00233
00234 TSetStateSpaceBins stateSpaceBins;
00235
00236 size_t Nx = KLD_options.KLD_minSampleSize;
00237 const double delta_1 = 1.0 - KLD_options.KLD_delta;
00238 const double epsilon_1 = 0.5 / KLD_options.KLD_epsilon;
00239
00240
00241 m_pfc.prepareFastDrawSample(PF_options);
00242
00243
00244 std::vector<TPose3D> newParticles;
00245 vector_double newParticlesWeight;
00246 vector<size_t> newParticlesDerivedFromIdx;
00247
00248 CPose3D increment_i;
00249 size_t N = 1;
00250
00251 do
00252 {
00253
00254 m_movementDrawer.drawSample( increment_i );
00255
00256
00257 const size_t drawn_idx = m_pfc.fastDrawSample(PF_options);
00258 const CPose3D newPose = CPose3D(*getLastPose(drawn_idx)) + increment_i;
00259 const TPose3D newPose_s = newPose;
00260
00261
00262 newParticles.push_back( newPose_s );
00263 newParticlesWeight.push_back(0);
00264 newParticlesDerivedFromIdx.push_back(drawn_idx);
00265
00266
00267
00268 BINTYPE p;
00269 KLF_loadBinFromParticle<PARTICLE_TYPE,BINTYPE>(p,KLD_options, m_partdata.m_particles[drawn_idx].d, &newPose_s);
00270
00271 if (stateSpaceBins.find( p )==stateSpaceBins.end())
00272 {
00273
00274
00275 stateSpaceBins.insert( p );
00276
00277
00278 size_t K = stateSpaceBins.size();
00279 if ( K>1)
00280 {
00281
00282 Nx = round(epsilon_1 * math::chi2inv(delta_1,K-1));
00283
00284 }
00285 }
00286 N = newParticles.size();
00287 } while ( N < max(Nx,(size_t)KLD_options.KLD_minSampleSize) &&
00288 N < KLD_options.KLD_maxSampleSize );
00289
00290
00291
00292
00293
00294
00295 this->PF_SLAM_implementation_replaceByNewParticleSet(
00296 m_partdata.m_particles,
00297 newParticles,newParticlesWeight,newParticlesDerivedFromIdx );
00298
00299 }
00300 }
00301
00302 if (sf)
00303 {
00304 const size_t M = m_partdata.m_particles.size();
00305
00306
00307
00308 for (size_t i=0;i<M;i++)
00309 {
00310 const TPose3D *partPose= getLastPose(i);
00311 CPose3D partPose2 = CPose3D(*partPose);
00312 const double obs_log_likelihood = PF_SLAM_computeObservationLikelihoodForParticle(PF_options,i,*sf,partPose2);
00313 m_partdata.m_particles[i].log_w += obs_log_likelihood * PF_options.powFactor;
00314 }
00315
00316
00317 }
00318
00319 MRPT_END
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 template <class PARTICLE_TYPE>
00333 template <class BINTYPE>
00334 void PF_implementation<PARTICLE_TYPE>::PF_SLAM_implementation_pfAuxiliaryPFStandard(
00335 const CActionCollection * actions,
00336 const CSensoryFrame * sf,
00337 const CParticleFilter::TParticleFilterOptions &PF_options,
00338 const TKLDParams &KLD_options)
00339 {
00340
00341 PF_SLAM_implementation_pfAuxiliaryPFStandardAndOptimal<BINTYPE>(actions,sf,PF_options,KLD_options, false );
00342 }
00343
00344
00345
00346
00347 template <class PARTICLE_TYPE>
00348 template <class BINTYPE>
00349 double PF_implementation<PARTICLE_TYPE>::PF_SLAM_particlesEvaluator_AuxPFOptimal(
00350 const CParticleFilter::TParticleFilterOptions &PF_options,
00351 const CParticleFilterCapable *obj,
00352 size_t index,
00353 const void *action,
00354 const void *observation )
00355 {
00356 MRPT_START
00357
00358 const PF_implementation<PARTICLE_TYPE> *myObj = reinterpret_cast<const PF_implementation<PARTICLE_TYPE>*>( obj );
00359
00360
00361
00362
00363
00364 double indivLik, maxLik= -1e300;
00365 CPose3D maxLikDraw;
00366 size_t N = PF_options.pfAuxFilterOptimal_MaximumSearchSamples;
00367 ASSERT_(N>1)
00368
00369 const CPose3D oldPose = *myObj->getLastPose(index);
00370 vector_double vectLiks(N,0);
00371 CPose3D drawnSample;
00372 for (size_t q=0;q<N;q++)
00373 {
00374 myObj->m_movementDrawer.drawSample(drawnSample);
00375 CPose3D x_predict = oldPose + drawnSample;
00376
00377
00378 indivLik = myObj->PF_SLAM_computeObservationLikelihoodForParticle(
00379 PF_options,
00380 index,
00381 *static_cast<const CSensoryFrame*>(observation),
00382 x_predict );
00383
00384 MRPT_CHECK_NORMAL_NUMBER(indivLik);
00385 vectLiks[q] = indivLik;
00386 if ( indivLik > maxLik )
00387 {
00388 maxLikDraw = drawnSample;
00389 maxLik = indivLik;
00390 }
00391 }
00392
00393
00394
00395
00396 double avrgLogLik = math::averageLogLikelihood( vectLiks );
00397
00398
00399 myObj->m_pfAuxiliaryPFOptimal_estimatedProb[index] = avrgLogLik;
00400 myObj->m_pfAuxiliaryPFOptimal_maxLikelihood[index] = maxLik;
00401
00402 if (PF_options.pfAuxFilterOptimal_MLE)
00403 myObj->m_pfAuxiliaryPFOptimal_maxLikDrawnMovement[index] = maxLikDraw;
00404
00405
00406
00407 return myObj->m_partdata.m_particles[index].log_w + myObj->m_pfAuxiliaryPFOptimal_estimatedProb[index];
00408
00409 MRPT_END
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419 template <class PARTICLE_TYPE>
00420 template <class BINTYPE>
00421 double PF_implementation<PARTICLE_TYPE>::PF_SLAM_particlesEvaluator_AuxPFStandard(
00422 const CParticleFilter::TParticleFilterOptions &PF_options,
00423 const CParticleFilterCapable *obj,
00424 size_t index,
00425 const void *action,
00426 const void *observation )
00427 {
00428 MRPT_START
00429
00430 const PF_implementation<PARTICLE_TYPE> *myObj = reinterpret_cast<const PF_implementation<PARTICLE_TYPE>*>( obj );
00431
00432
00433 const double cur_logweight = myObj->m_partdata.m_particles[index].log_w;
00434 const CPose3D oldPose = *myObj->getLastPose(index);
00435
00436 if (!PF_options.pfAuxFilterStandard_FirstStageWeightsMonteCarlo)
00437 {
00438
00439
00440 CPose3D x_predict;
00441 x_predict.composeFrom( oldPose, *static_cast<const CPose3D*>(action) );
00442
00443
00444
00445 myObj->m_pfAuxiliaryPFStandard_estimatedProb[index] = myObj->PF_SLAM_computeObservationLikelihoodForParticle(
00446 PF_options, index,
00447 *static_cast<const CSensoryFrame*>(observation), x_predict );
00448
00449
00450 return cur_logweight + myObj->m_pfAuxiliaryPFStandard_estimatedProb[index];
00451 }
00452 else
00453 {
00454
00455
00456
00457
00458
00459 double indivLik, maxLik= -1e300;
00460 CPose3D maxLikDraw;
00461 size_t N = PF_options.pfAuxFilterOptimal_MaximumSearchSamples;
00462 ASSERT_(N>1)
00463
00464 vector_double vectLiks(N,0);
00465 CPose3D drawnSample;
00466 for (size_t q=0;q<N;q++)
00467 {
00468 myObj->m_movementDrawer.drawSample(drawnSample);
00469 CPose3D x_predict = oldPose + drawnSample;
00470
00471
00472 indivLik = myObj->PF_SLAM_computeObservationLikelihoodForParticle(
00473 PF_options,
00474 index,
00475 *static_cast<const CSensoryFrame*>(observation),
00476 x_predict );
00477
00478 MRPT_CHECK_NORMAL_NUMBER(indivLik);
00479 vectLiks[q] = indivLik;
00480 if ( indivLik > maxLik )
00481 {
00482 maxLikDraw = drawnSample;
00483 maxLik = indivLik;
00484 }
00485 }
00486
00487
00488
00489
00490 double avrgLogLik = math::averageLogLikelihood( vectLiks );
00491
00492
00493 myObj->m_pfAuxiliaryPFStandard_estimatedProb[index] = avrgLogLik;
00494
00495 myObj->m_pfAuxiliaryPFOptimal_maxLikelihood[index] = maxLik;
00496 if (PF_options.pfAuxFilterOptimal_MLE)
00497 myObj->m_pfAuxiliaryPFOptimal_maxLikDrawnMovement[index] = maxLikDraw;
00498
00499
00500
00501 return cur_logweight + myObj->m_pfAuxiliaryPFOptimal_estimatedProb[index];
00502 }
00503 MRPT_END
00504 }
00505
00506
00507
00508
00509 template <class PARTICLE_TYPE>
00510 template <class BINTYPE>
00511 void PF_implementation<PARTICLE_TYPE>::PF_SLAM_implementation_pfAuxiliaryPFStandardAndOptimal(
00512 const CActionCollection * actions,
00513 const CSensoryFrame * sf,
00514 const CParticleFilter::TParticleFilterOptions &PF_options,
00515 const TKLDParams &KLD_options,
00516 const bool USE_OPTIMAL_SAMPLING )
00517 {
00518 MRPT_START
00519 typedef std::set<BINTYPE,typename BINTYPE::lt_operator> TSetStateSpaceBins;
00520
00521 const size_t M = m_partdata.m_particles.size();
00522
00523
00524
00525
00526
00527
00528
00529 if (!PF_SLAM_implementation_gatherActionsCheckBothActObs<BINTYPE>(actions,sf))
00530 return;
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 m_pfAuxiliaryPFOptimal_maxLikelihood.assign(M, INVALID_LIKELIHOOD_VALUE);
00543 m_pfAuxiliaryPFOptimal_maxLikDrawnMovement.resize(M);
00544
00545 m_pfAuxiliaryPFOptimal_estimatedProb.resize(M);
00546
00547 m_pfAuxiliaryPFStandard_estimatedProb.resize(M);
00548
00549
00550 CPose3D meanRobotMovement;
00551 m_movementDrawer.getSamplingMean3D(meanRobotMovement);
00552
00553
00554 typedef PF_implementation<PARTICLE_TYPE> TMyClass;
00555 CParticleFilterCapable::TParticleProbabilityEvaluator funcOpt = &TMyClass::template PF_SLAM_particlesEvaluator_AuxPFOptimal<BINTYPE>;
00556 CParticleFilterCapable::TParticleProbabilityEvaluator funcStd = &TMyClass::template PF_SLAM_particlesEvaluator_AuxPFStandard<BINTYPE>;
00557
00558 m_pfc.prepareFastDrawSample(
00559 PF_options,
00560 USE_OPTIMAL_SAMPLING ? funcOpt : funcStd,
00561 &meanRobotMovement,
00562 sf );
00563
00564
00565
00566 if (USE_OPTIMAL_SAMPLING && PF_options.verbose)
00567 {
00568 printf("[prepareFastDrawSample] max (log) = %10.06f\n", math::maximum(m_pfAuxiliaryPFOptimal_estimatedProb) );
00569 printf("[prepareFastDrawSample] max-mean (log) = %10.06f\n", -math::mean(m_pfAuxiliaryPFOptimal_estimatedProb) + math::maximum(m_pfAuxiliaryPFOptimal_estimatedProb) );
00570 printf("[prepareFastDrawSample] max-min (log) = %10.06f\n", -math::minimum(m_pfAuxiliaryPFOptimal_estimatedProb) + math::maximum(m_pfAuxiliaryPFOptimal_estimatedProb) );
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 vector<TPose3D> newParticles;
00587 vector_double newParticlesWeight;
00588 vector<size_t> newParticlesDerivedFromIdx;
00589
00590
00591
00592
00593
00594
00595 if (PF_options.pfAuxFilterOptimal_MLE)
00596 m_pfAuxiliaryPFOptimal_maxLikMovementDrawHasBeenUsed.assign(M, false);
00597
00598 const double maxMeanLik = math::maximum(
00599 USE_OPTIMAL_SAMPLING ?
00600 m_pfAuxiliaryPFOptimal_estimatedProb :
00601 m_pfAuxiliaryPFStandard_estimatedProb );
00602
00603 if ( !PF_options.adaptiveSampleSize )
00604 {
00605
00606
00607
00608 newParticles.resize(M);
00609 newParticlesWeight.resize(M);
00610 newParticlesDerivedFromIdx.resize(M);
00611
00612 const bool doResample = m_pfc.ESS() < PF_options.BETA;
00613
00614 for (size_t i=0;i<M;i++)
00615 {
00616 size_t k;
00617
00618
00619
00620
00621 if (doResample)
00622 k = m_pfc.fastDrawSample(PF_options);
00623 else k = i;
00624
00625
00626
00627 CPose3D newPose;
00628 double newParticleLogWeight;
00629 PF_SLAM_aux_perform_one_rejection_sampling_step<BINTYPE>(
00630 USE_OPTIMAL_SAMPLING,doResample,maxMeanLik,
00631 k,
00632 sf,PF_options,
00633 newPose, newParticleLogWeight);
00634
00635
00636 newParticles[i] = newPose;
00637 newParticlesDerivedFromIdx[i] = k;
00638 newParticlesWeight[i] = newParticleLogWeight;
00639
00640 }
00641 }
00642 else
00643 {
00644
00645
00646
00647
00648
00649
00650
00651 newParticles.clear();
00652 newParticlesWeight.clear();
00653 newParticlesDerivedFromIdx.clear();
00654
00655
00656
00657
00658
00659
00660
00661
00662 TSetStateSpaceBins stateSpaceBinsLastTimestep;
00663 std::vector<vector_uint> stateSpaceBinsLastTimestepParticles;
00664 typename BASE::CParticleList::iterator partIt;
00665 unsigned int partIndex;
00666
00667 printf( "[FIXED_SAMPLING] Computing...");
00668 for (partIt = m_partdata.m_particles.begin(),partIndex=0; partIt!=m_partdata.m_particles.end(); ++partIt,++partIndex)
00669 {
00670
00671 BINTYPE p;
00672 KLF_loadBinFromParticle<PARTICLE_TYPE,BINTYPE>(p, KLD_options,partIt->d );
00673
00674
00675 typename TSetStateSpaceBins::iterator posFound=stateSpaceBinsLastTimestep.find(p);
00676 if ( posFound == stateSpaceBinsLastTimestep.end() )
00677 {
00678 stateSpaceBinsLastTimestep.insert( p );
00679 stateSpaceBinsLastTimestepParticles.push_back( vector_uint(1,partIndex) );
00680 }
00681 else
00682 {
00683 const size_t idx = std::distance(stateSpaceBinsLastTimestep.begin(),posFound);
00684 stateSpaceBinsLastTimestepParticles[idx].push_back( partIndex );
00685 }
00686 }
00687 printf( "done (%u bins in t-1)\n",(unsigned int)stateSpaceBinsLastTimestep.size());
00688
00689
00690
00691
00692 double delta_1 = 1.0 - KLD_options.KLD_delta;
00693 double epsilon_1 = 0.5 / KLD_options.KLD_epsilon;
00694 bool doResample = m_pfc.ESS() < 0.5;
00695
00696
00697
00698 const size_t minNumSamples_KLD = max((size_t)KLD_options.KLD_minSampleSize, (size_t)round(KLD_options.KLD_minSamplesPerBin*stateSpaceBinsLastTimestep.size()) );
00699 size_t Nx = minNumSamples_KLD ;
00700
00701 const size_t Np1 = m_partdata.m_particles.size();
00702 vector_size_t oldPartIdxsStillNotPropragated(Np1);
00703 for (size_t k=0;k<Np1;k++) oldPartIdxsStillNotPropragated[k]=k;
00704
00705 const size_t Np = stateSpaceBinsLastTimestepParticles.size();
00706 vector_size_t permutationPathsAuxVector(Np);
00707 for (size_t k=0;k<Np;k++) permutationPathsAuxVector[k]=k;
00708
00709
00710
00711 std::random_shuffle(
00712 permutationPathsAuxVector.begin(),
00713 permutationPathsAuxVector.end(),
00714 mrpt::random::random_generator_for_STL );
00715
00716 size_t k = 0;
00717 size_t N = 0;
00718
00719 TSetStateSpaceBins stateSpaceBins;
00720
00721 do
00722 {
00723
00724
00725
00726
00727
00728
00729
00730 if (doResample)
00731 {
00732 k = m_pfc.fastDrawSample(PF_options);
00733 }
00734 else
00735 {
00736
00737
00738 if (permutationPathsAuxVector.size())
00739 {
00740 const size_t idxBinSpacePath = *permutationPathsAuxVector.rbegin();
00741 permutationPathsAuxVector.resize(permutationPathsAuxVector.size()-1);
00742
00743 const size_t idx = randomGenerator.drawUniform32bit() % stateSpaceBinsLastTimestepParticles[idxBinSpacePath].size();
00744 k = stateSpaceBinsLastTimestepParticles[idxBinSpacePath][idx];
00745 ASSERT_(k<m_partdata.m_particles.size());
00746
00747
00748 oldPartIdxsStillNotPropragated.erase(std::find(oldPartIdxsStillNotPropragated.begin(),oldPartIdxsStillNotPropragated.end(),k));
00749 }
00750 else
00751 {
00752
00753
00754
00755
00756
00757
00758
00759 if (oldPartIdxsStillNotPropragated.size())
00760 {
00761 const size_t idx = randomGenerator.drawUniform32bit() % oldPartIdxsStillNotPropragated.size();
00762 vector_size_t::iterator it = oldPartIdxsStillNotPropragated.begin() + idx;
00763 k = *it;
00764 oldPartIdxsStillNotPropragated.erase(it);
00765 }
00766 else
00767 {
00768
00769 k = randomGenerator.drawUniform32bit() % m_partdata.m_particles.size();
00770 }
00771 }
00772 }
00773
00774
00775
00776 CPose3D newPose;
00777 double newParticleLogWeight;
00778 PF_SLAM_aux_perform_one_rejection_sampling_step<BINTYPE>(
00779 USE_OPTIMAL_SAMPLING,doResample,maxMeanLik,
00780 k,
00781 sf,PF_options,
00782 newPose, newParticleLogWeight);
00783
00784
00785 newParticles.push_back( newPose );
00786 newParticlesDerivedFromIdx.push_back( k );
00787 newParticlesWeight.push_back(newParticleLogWeight);
00788
00789
00790
00791
00792
00793 BINTYPE p;
00794 const TPose3D newPose_s = newPose;
00795 KLF_loadBinFromParticle<PARTICLE_TYPE,BINTYPE>( p,KLD_options, m_partdata.m_particles[k].d, &newPose_s );
00796
00797
00798
00799
00800
00801
00802
00803 if ( stateSpaceBins.find(p)==stateSpaceBins.end() )
00804 {
00805
00806 stateSpaceBins.insert( p );
00807
00808
00809 int K = stateSpaceBins.size();
00810 if ( K>1 )
00811 {
00812
00813 Nx = (size_t) (epsilon_1 * math::chi2inv(delta_1,K-1));
00814
00815 }
00816 }
00817
00818 N = newParticles.size();
00819
00820 } while (( N < KLD_options.KLD_maxSampleSize &&
00821 N < max(Nx,minNumSamples_KLD)) ||
00822 (permutationPathsAuxVector.size() && !doResample) );
00823
00824 printf("\n[ADAPTIVE SAMPLE SIZE] #Bins: %u \t #Particles: %u \t Nx=%u\n", static_cast<unsigned>(stateSpaceBins.size()),static_cast<unsigned>(N), (unsigned)Nx);
00825 }
00826
00827
00828
00829
00830
00831
00832
00833 this->PF_SLAM_implementation_replaceByNewParticleSet(
00834 m_partdata.m_particles,
00835 newParticles,newParticlesWeight,newParticlesDerivedFromIdx );
00836
00837
00838
00839 m_pfc.normalizeWeights();
00840
00841 MRPT_END
00842 }
00843
00844
00845
00846
00847
00848 template <class PARTICLE_TYPE>
00849 template <class BINTYPE>
00850 void PF_implementation<PARTICLE_TYPE>::PF_SLAM_aux_perform_one_rejection_sampling_step(
00851 const bool USE_OPTIMAL_SAMPLING,
00852 const bool doResample,
00853 const double maxMeanLik,
00854 size_t k,
00855 const CSensoryFrame * sf,
00856 const CParticleFilter::TParticleFilterOptions &PF_options,
00857 CPose3D & out_newPose,
00858 double & out_newParticleLogWeight)
00859 {
00860
00861
00862 while ( ( (USE_OPTIMAL_SAMPLING ? m_pfAuxiliaryPFOptimal_estimatedProb[k] : m_pfAuxiliaryPFStandard_estimatedProb[k] )
00863 -maxMeanLik) < -PF_options.max_loglikelihood_dyn_range )
00864 {
00865
00866 k = randomGenerator.drawUniform32bit() % m_partdata.m_particles.size();
00867 if (PF_options.verbose) cout << "[PF_implementation] Warning: Discarding very unlikely particle" << endl;
00868 }
00869
00870 const CPose3D oldPose = *getLastPose(k);
00871
00872
00873
00874
00875 double poseLogLik;
00876 if ( PF_SLAM_implementation_skipRobotMovement() )
00877 {
00878
00879
00880 out_newPose = oldPose;
00881 poseLogLik = 0;
00882 }
00883 else
00884 {
00885 CPose3D movementDraw;
00886 if (!USE_OPTIMAL_SAMPLING)
00887 {
00888 m_movementDrawer.drawSample( movementDraw );
00889 out_newPose.composeFrom(oldPose, movementDraw);
00890
00891 poseLogLik = PF_SLAM_computeObservationLikelihoodForParticle(PF_options, k,*sf,out_newPose);
00892 }
00893 else
00894 {
00895
00896 double acceptanceProb;
00897 int timeout = 0;
00898 const int maxTries=10000;
00899 double bestTryByNow_loglik= -std::numeric_limits<double>::max();
00900 TPose3D bestTryByNow_pose;
00901 do
00902 {
00903
00904 if (PF_options.pfAuxFilterOptimal_MLE && !m_pfAuxiliaryPFOptimal_maxLikMovementDrawHasBeenUsed[k])
00905 {
00906 m_pfAuxiliaryPFOptimal_maxLikMovementDrawHasBeenUsed[k] = true;
00907 movementDraw = CPose3D( m_pfAuxiliaryPFOptimal_maxLikDrawnMovement[k] );
00908 }
00909 else
00910 {
00911
00912 m_movementDrawer.drawSample( movementDraw );
00913 }
00914
00915 out_newPose.composeFrom(oldPose, movementDraw);
00916
00917
00918 poseLogLik = PF_SLAM_computeObservationLikelihoodForParticle(PF_options, k,*sf,out_newPose);
00919
00920 if (poseLogLik>bestTryByNow_loglik)
00921 {
00922 bestTryByNow_loglik = poseLogLik;
00923 bestTryByNow_pose = out_newPose;
00924 }
00925
00926 double ratioLikLik = std::exp( poseLogLik - m_pfAuxiliaryPFOptimal_maxLikelihood[k] );
00927 acceptanceProb = std::min( 1.0, ratioLikLik );
00928
00929 if ( ratioLikLik > 1)
00930 {
00931 m_pfAuxiliaryPFOptimal_maxLikelihood[k] = poseLogLik;
00932
00933 }
00934 } while ( ++timeout<maxTries && acceptanceProb < randomGenerator.drawUniform(0.0,0.999) );
00935
00936 if (timeout>=maxTries)
00937 {
00938 out_newPose = bestTryByNow_pose;
00939 poseLogLik = bestTryByNow_loglik;
00940 if (PF_options.verbose) cout << "[PF_implementation] Warning: timeout in rejection sampling." << endl;
00941 }
00942
00943 }
00944
00945
00946 if (USE_OPTIMAL_SAMPLING)
00947 {
00948 if (doResample)
00949 out_newParticleLogWeight = 0;
00950 else
00951 {
00952 const double weightFact = m_pfAuxiliaryPFOptimal_estimatedProb[k] * PF_options.powFactor;
00953 out_newParticleLogWeight = m_partdata.m_particles[k].log_w + weightFact;
00954 }
00955 }
00956 else
00957 {
00958 const double weightFact = (poseLogLik-m_pfAuxiliaryPFStandard_estimatedProb[k]) * PF_options.powFactor;
00959 if (doResample)
00960 out_newParticleLogWeight = weightFact;
00961 else out_newParticleLogWeight = weightFact + m_partdata.m_particles[k].log_w;
00962 }
00963
00964 }
00965
00966 }
00967
00968
00969 }
00970 }
00971
00972 #endif