29 #ifndef PF_implementations_H
30 #define PF_implementations_H
56 using namespace mrpt::utils;
57 using namespace mrpt::random;
58 using namespace mrpt::poses;
59 using namespace mrpt::bayes;
60 using namespace mrpt::math;
68 template <
class PARTICLE_TYPE,
class MY
SELF>
69 template <
class BINTYPE>
74 MYSELF *me =
static_cast<MYSELF*
>(
this);
82 if (m_accumRobotMovement3DIsValid)
THROW_EXCEPTION(
"Mixing 2D and 3D actions is not allowed.")
84 if (!m_accumRobotMovement2DIsValid)
86 robotMovement2D->
poseChange->
getMean( m_accumRobotMovement2D.rawOdometryIncrementReading );
89 else m_accumRobotMovement2D.rawOdometryIncrementReading += robotMovement2D->
poseChange->
getMeanVal();
91 m_accumRobotMovement2DIsValid =
true;
98 if (m_accumRobotMovement2DIsValid)
THROW_EXCEPTION(
"Mixing 2D and 3D actions is not allowed.")
100 if (!m_accumRobotMovement3DIsValid)
101 m_accumRobotMovement3D = robotMovement3D->
poseChange;
102 else m_accumRobotMovement3D += robotMovement3D->
poseChange;
105 m_accumRobotMovement3DIsValid =
true;
113 const bool SFhasValidObservations = (sf==NULL) ?
false : PF_SLAM_implementation_doWeHaveValidObservations(me->m_particles,sf);
116 if (! ((m_accumRobotMovement2DIsValid || m_accumRobotMovement3DIsValid) && SFhasValidObservations))
121 if (m_accumRobotMovement3DIsValid)
123 m_movementDrawer.setPosePDF( m_accumRobotMovement3D );
124 m_accumRobotMovement3DIsValid =
false;
130 m_accumRobotMovement2D.rawOdometryIncrementReading,
131 m_accumRobotMovement2D.motionModelConfiguration );
133 m_movementDrawer.setPosePDF( theResultingRobotMov.
poseChange );
134 m_accumRobotMovement2DIsValid =
false;
152 template <
class PARTICLE_TYPE,
class MY
SELF>
153 template <
class BINTYPE>
161 PF_SLAM_implementation_pfAuxiliaryPFStandardAndOptimal<BINTYPE>(actions,sf,PF_options,KLD_options,
true );
170 template <
class PARTICLE_TYPE,
class MY
SELF>
171 template <
class BINTYPE>
179 typedef std::set<BINTYPE,typename BINTYPE::lt_operator> TSetStateSpaceBins;
181 MYSELF *me =
static_cast<MYSELF*
>(
this);
198 m_movementDrawer.setPosePDF( robotMovement2D->
poseChange );
206 m_movementDrawer.setPosePDF( robotMovement3D->
poseChange );
209 else {
THROW_EXCEPTION(
"Action list does not contain any CActionRobotMovement2D or CActionRobotMovement3D object!"); }
216 const size_t M = me->m_particles.size();
221 for (
size_t i=0;i<M;i++)
224 m_movementDrawer.drawSample( incrPose );
228 PF_SLAM_implementation_custom_update_particle_with_new_pose( me->m_particles[i].d,
TPose3D(finalPose) );
239 TSetStateSpaceBins stateSpaceBins;
242 const double delta_1 = 1.0 - KLD_options.
KLD_delta;
243 const double epsilon_1 = 0.5 / KLD_options.
KLD_epsilon;
246 me->prepareFastDrawSample(PF_options);
249 std::vector<TPose3D> newParticles;
251 std::vector<size_t> newParticlesDerivedFromIdx;
259 m_movementDrawer.drawSample( increment_i );
262 const size_t drawn_idx = me->fastDrawSample(PF_options);
263 const CPose3D newPose =
CPose3D(*getLastPose(drawn_idx)) + increment_i;
264 const TPose3D newPose_s = newPose;
267 newParticles.push_back( newPose_s );
268 newParticlesWeight.push_back(0);
269 newParticlesDerivedFromIdx.push_back(drawn_idx);
274 KLF_loadBinFromParticle<PARTICLE_TYPE,BINTYPE>(p,KLD_options, me->m_particles[drawn_idx].d, &newPose_s);
276 if (stateSpaceBins.find( p )==stateSpaceBins.end())
280 stateSpaceBins.insert( p );
283 size_t K = stateSpaceBins.size();
291 N = newParticles.size();
300 this->PF_SLAM_implementation_replaceByNewParticleSet(
302 newParticles,newParticlesWeight,newParticlesDerivedFromIdx );
309 const size_t M = me->m_particles.size();
313 for (
size_t i=0;i<M;i++)
315 const TPose3D *partPose= getLastPose(i);
317 const double obs_log_likelihood = PF_SLAM_computeObservationLikelihoodForParticle(PF_options,i,*sf,partPose2);
318 me->m_particles[i].log_w += obs_log_likelihood * PF_options.
powFactor;
337 template <
class PARTICLE_TYPE,
class MY
SELF>
338 template <
class BINTYPE>
346 PF_SLAM_implementation_pfAuxiliaryPFStandardAndOptimal<BINTYPE>(actions,sf,PF_options,KLD_options,
false );
352 template <
class PARTICLE_TYPE,
class MY
SELF>
353 template <
class BINTYPE>
359 const void *observation )
364 const MYSELF *me =
static_cast<const MYSELF*
>(obj);
370 double indivLik, maxLik= -1e300;
375 const CPose3D oldPose = *me->getLastPose(index);
378 for (
size_t q=0;q<N;q++)
380 me->m_movementDrawer.drawSample(drawnSample);
381 CPose3D x_predict = oldPose + drawnSample;
384 indivLik = me->PF_SLAM_computeObservationLikelihoodForParticle(
387 *static_cast<const CSensoryFrame*>(observation),
391 vectLiks[q] = indivLik;
392 if ( indivLik > maxLik )
394 maxLikDraw = drawnSample;
405 me->m_pfAuxiliaryPFOptimal_estimatedProb[index] = avrgLogLik;
406 me->m_pfAuxiliaryPFOptimal_maxLikelihood[index] = maxLik;
409 me->m_pfAuxiliaryPFOptimal_maxLikDrawnMovement[index] = maxLikDraw;
413 return me->m_particles[index].log_w + me->m_pfAuxiliaryPFOptimal_estimatedProb[index];
425 template <
class PARTICLE_TYPE,
class MY
SELF>
426 template <
class BINTYPE>
432 const void *observation )
437 const MYSELF *myObj =
static_cast<const MYSELF*
>(obj);
440 const double cur_logweight = myObj->m_particles[index].log_w;
441 const CPose3D oldPose = *myObj->getLastPose(index);
448 x_predict.
composeFrom( oldPose, *static_cast<const CPose3D*>(action) );
452 myObj->m_pfAuxiliaryPFStandard_estimatedProb[index] = myObj->PF_SLAM_computeObservationLikelihoodForParticle(
454 *static_cast<const CSensoryFrame*>(observation), x_predict );
457 return cur_logweight + myObj->m_pfAuxiliaryPFStandard_estimatedProb[index];
466 double indivLik, maxLik= -1e300;
473 for (
size_t q=0;q<N;q++)
475 myObj->m_movementDrawer.drawSample(drawnSample);
476 CPose3D x_predict = oldPose + drawnSample;
479 indivLik = myObj->PF_SLAM_computeObservationLikelihoodForParticle(
482 *static_cast<const CSensoryFrame*>(observation),
486 vectLiks[q] = indivLik;
487 if ( indivLik > maxLik )
489 maxLikDraw = drawnSample;
500 myObj->m_pfAuxiliaryPFStandard_estimatedProb[index] = avrgLogLik;
502 myObj->m_pfAuxiliaryPFOptimal_maxLikelihood[index] = maxLik;
504 myObj->m_pfAuxiliaryPFOptimal_maxLikDrawnMovement[index] = maxLikDraw;
508 return cur_logweight + myObj->m_pfAuxiliaryPFOptimal_estimatedProb[index];
516 template <
class PARTICLE_TYPE,
class MY
SELF>
517 template <
class BINTYPE>
523 const bool USE_OPTIMAL_SAMPLING )
526 typedef std::set<BINTYPE,typename BINTYPE::lt_operator> TSetStateSpaceBins;
528 MYSELF *me =
static_cast<MYSELF*
>(
this);
530 const size_t M = me->m_particles.size();
538 if (!PF_SLAM_implementation_gatherActionsCheckBothActObs<BINTYPE>(actions,sf))
552 m_pfAuxiliaryPFOptimal_maxLikDrawnMovement.resize(M);
554 m_pfAuxiliaryPFOptimal_estimatedProb.resize(M);
556 m_pfAuxiliaryPFStandard_estimatedProb.resize(M);
560 m_movementDrawer.getSamplingMean3D(meanRobotMovement);
567 me->prepareFastDrawSample(
569 USE_OPTIMAL_SAMPLING ? funcOpt : funcStd,
575 if (USE_OPTIMAL_SAMPLING && PF_options.
verbose)
577 printf(
"[prepareFastDrawSample] max (log) = %10.06f\n",
math::maximum(m_pfAuxiliaryPFOptimal_estimatedProb) );
578 printf(
"[prepareFastDrawSample] max-mean (log) = %10.06f\n", -
math::mean(m_pfAuxiliaryPFOptimal_estimatedProb) +
math::maximum(m_pfAuxiliaryPFOptimal_estimatedProb) );
579 printf(
"[prepareFastDrawSample] max-min (log) = %10.06f\n", -
math::minimum(m_pfAuxiliaryPFOptimal_estimatedProb) +
math::maximum(m_pfAuxiliaryPFOptimal_estimatedProb) );
595 vector<TPose3D> newParticles;
596 vector<double> newParticlesWeight;
597 vector<size_t> newParticlesDerivedFromIdx;
605 m_pfAuxiliaryPFOptimal_maxLikMovementDrawHasBeenUsed.assign(M,
false);
608 USE_OPTIMAL_SAMPLING ?
609 m_pfAuxiliaryPFOptimal_estimatedProb :
610 m_pfAuxiliaryPFStandard_estimatedProb );
617 newParticles.resize(M);
618 newParticlesWeight.resize(M);
619 newParticlesDerivedFromIdx.resize(M);
621 const bool doResample = me->ESS() < PF_options.
BETA;
623 for (
size_t i=0;i<M;i++)
631 k = me->fastDrawSample(PF_options);
637 double newParticleLogWeight;
638 PF_SLAM_aux_perform_one_rejection_sampling_step<BINTYPE>(
639 USE_OPTIMAL_SAMPLING,doResample,maxMeanLik,
642 newPose, newParticleLogWeight);
645 newParticles[i] = newPose;
646 newParticlesDerivedFromIdx[i] = k;
647 newParticlesWeight[i] = newParticleLogWeight;
660 newParticles.clear();
661 newParticlesWeight.clear();
662 newParticlesDerivedFromIdx.clear();
671 TSetStateSpaceBins stateSpaceBinsLastTimestep;
672 std::vector<vector_uint> stateSpaceBinsLastTimestepParticles;
674 unsigned int partIndex;
676 printf(
"[FIXED_SAMPLING] Computing...");
677 for (partIt = me->m_particles.begin(),partIndex=0; partIt!=me->m_particles.end(); ++partIt,++partIndex)
681 KLF_loadBinFromParticle<PARTICLE_TYPE,BINTYPE>(p, KLD_options,partIt->d );
685 if ( posFound == stateSpaceBinsLastTimestep.end() )
687 stateSpaceBinsLastTimestep.insert( p );
688 stateSpaceBinsLastTimestepParticles.push_back(
vector_uint(1,partIndex) );
692 const size_t idx =
std::distance(stateSpaceBinsLastTimestep.begin(),posFound);
693 stateSpaceBinsLastTimestepParticles[idx].push_back( partIndex );
696 printf(
"done (%u bins in t-1)\n",(
unsigned int)stateSpaceBinsLastTimestep.size());
701 double delta_1 = 1.0 - KLD_options.
KLD_delta;
703 bool doResample = me->ESS() < 0.5;
708 size_t Nx = minNumSamples_KLD ;
710 const size_t Np1 = me->m_particles.size();
712 for (
size_t k=0;k<Np1;k++) oldPartIdxsStillNotPropragated[k]=k;
714 const size_t Np = stateSpaceBinsLastTimestepParticles.size();
716 for (
size_t k=0;k<Np;k++) permutationPathsAuxVector[k]=k;
721 permutationPathsAuxVector.begin(),
722 permutationPathsAuxVector.end(),
728 TSetStateSpaceBins stateSpaceBins;
741 k = me->fastDrawSample(PF_options);
747 if (permutationPathsAuxVector.size())
749 const size_t idxBinSpacePath = *permutationPathsAuxVector.rbegin();
750 permutationPathsAuxVector.resize(permutationPathsAuxVector.size()-1);
753 k = stateSpaceBinsLastTimestepParticles[idxBinSpacePath][idx];
754 ASSERT_(k<me->m_particles.size());
757 oldPartIdxsStillNotPropragated.erase(std::find(oldPartIdxsStillNotPropragated.begin(),oldPartIdxsStillNotPropragated.end(),k));
768 if (oldPartIdxsStillNotPropragated.size())
773 oldPartIdxsStillNotPropragated.erase(it);
786 double newParticleLogWeight;
787 PF_SLAM_aux_perform_one_rejection_sampling_step<BINTYPE>(
788 USE_OPTIMAL_SAMPLING,doResample,maxMeanLik,
791 newPose, newParticleLogWeight);
794 newParticles.push_back( newPose );
795 newParticlesDerivedFromIdx.push_back( k );
796 newParticlesWeight.push_back(newParticleLogWeight);
803 const TPose3D newPose_s = newPose;
804 KLF_loadBinFromParticle<PARTICLE_TYPE,BINTYPE>( p,KLD_options, me->m_particles[k].d, &newPose_s );
812 if ( stateSpaceBins.find(p)==stateSpaceBins.end() )
815 stateSpaceBins.insert( p );
818 int K = stateSpaceBins.
size();
827 N = newParticles.size();
830 N < max(Nx,minNumSamples_KLD)) ||
831 (permutationPathsAuxVector.size() && !doResample) );
833 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);
842 this->PF_SLAM_implementation_replaceByNewParticleSet(
844 newParticles,newParticlesWeight,newParticlesDerivedFromIdx );
848 me->normalizeWeights();
857 template <
class PARTICLE_TYPE,
class MY
SELF>
858 template <
class BINTYPE>
860 const bool USE_OPTIMAL_SAMPLING,
861 const bool doResample,
862 const double maxMeanLik,
867 double & out_newParticleLogWeight)
869 MYSELF *me =
static_cast<MYSELF*
>(
this);
873 while ( ( (USE_OPTIMAL_SAMPLING ? m_pfAuxiliaryPFOptimal_estimatedProb[k] : m_pfAuxiliaryPFStandard_estimatedProb[k] )
878 if (PF_options.
verbose) cout <<
"[PF_implementation] Warning: Discarding very unlikely particle" << endl;
881 const CPose3D oldPose = *getLastPose(k);
887 if ( PF_SLAM_implementation_skipRobotMovement() )
891 out_newPose = oldPose;
897 if (!USE_OPTIMAL_SAMPLING)
899 m_movementDrawer.drawSample( movementDraw );
902 poseLogLik = PF_SLAM_computeObservationLikelihoodForParticle(PF_options, k,*sf,out_newPose);
907 double acceptanceProb;
909 const int maxTries=10000;
910 double bestTryByNow_loglik= -std::numeric_limits<double>::max();
917 m_pfAuxiliaryPFOptimal_maxLikMovementDrawHasBeenUsed[k] =
true;
918 movementDraw =
CPose3D( m_pfAuxiliaryPFOptimal_maxLikDrawnMovement[k] );
923 m_movementDrawer.drawSample( movementDraw );
929 poseLogLik = PF_SLAM_computeObservationLikelihoodForParticle(PF_options, k,*sf,out_newPose);
931 if (poseLogLik>bestTryByNow_loglik)
933 bestTryByNow_loglik = poseLogLik;
934 bestTryByNow_pose = out_newPose;
937 double ratioLikLik = std::exp( poseLogLik - m_pfAuxiliaryPFOptimal_maxLikelihood[k] );
938 acceptanceProb = std::min( 1.0, ratioLikLik );
940 if ( ratioLikLik > 1)
942 m_pfAuxiliaryPFOptimal_maxLikelihood[k] = poseLogLik;
947 if (timeout>=maxTries)
949 out_newPose = bestTryByNow_pose;
950 poseLogLik = bestTryByNow_loglik;
951 if (PF_options.
verbose) cout <<
"[PF_implementation] Warning: timeout in rejection sampling." << endl;
957 if (USE_OPTIMAL_SAMPLING)
960 out_newParticleLogWeight = 0;
963 const double weightFact = m_pfAuxiliaryPFOptimal_estimatedProb[k] * PF_options.
powFactor;
964 out_newParticleLogWeight = me->m_particles[k].log_w + weightFact;
969 const double weightFact = (poseLogLik-m_pfAuxiliaryPFStandard_estimatedProb[k]) * PF_options.
powFactor;
971 out_newParticleLogWeight = weightFact;
972 else out_newParticleLogWeight = weightFact + me->m_particles[k].log_w;