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