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