Main MRPT website > C++ reference
MRPT logo
PF_implementations.h
Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                       http://www.mrpt.org/                                |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
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>  // chi2inv
00041 
00042 #include <mrpt/slam/PF_implementations_data.h>
00043 
00044 #include <mrpt/slam/link_pragmas.h>
00045 
00046 
00047 /** \file PF_implementations.h
00048   *  This file contains the implementations of the template members declared in mrpt::slam::PF_implementation
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                 /** Auxiliary method called by PF implementations: return true if we have both action & observation,
00063                   *   otherwise, return false AND accumulate the odometry so when we have an observation we didn't lose a thing.
00064                   *   On return=true, the "m_movementDrawer" member is loaded and ready to draw samples of the increment of pose since last step.
00065                   *  This method is smart enough to accumulate CActionRobotMovement2D or CActionRobotMovement3D, whatever comes in.
00066                   *   \ingroup mrpt_slam_grp 
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)      // A valid action?
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                                                 {               // First time:
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 // If there is no 2D action, look for a 3D action:
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                                                         // This "+=" takes care of all the Jacobians, etc... You MUST love C++!!! ;-)
00104 
00105                                                         m_accumRobotMovement3DIsValid = true;
00106                                                 }
00107                                                 else
00108                                                         return false; // We have no actions...
00109                                         }
00110                                 }
00111                         }
00112 
00113                         const bool SFhasValidObservations = (sf==NULL) ? false : PF_SLAM_implementation_doWeHaveValidObservations(me->m_particles,sf);
00114 
00115                         // All the things we need?
00116                         if (! ((m_accumRobotMovement2DIsValid || m_accumRobotMovement3DIsValid) && SFhasValidObservations))
00117                                 return false;
00118 
00119                         // Since we're gonna return true, load the pose-drawer:
00120                         // Take the accum. actions as input:
00121                         if (m_accumRobotMovement3DIsValid)
00122                         {
00123                                 m_movementDrawer.setPosePDF( m_accumRobotMovement3D );  // <--- Set mov. drawer
00124                                 m_accumRobotMovement3DIsValid = false; // Reset odometry for next iteration
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 );  // <--- Set mov. drawer
00134                                 m_accumRobotMovement2DIsValid = false; // Reset odometry for next iteration
00135                         }
00136                         return true;
00137                 } // end of PF_SLAM_implementation_gatherActionsCheckBothActObs
00138 
00139                 /** A generic implementation of the PF method "prediction_and_update_pfAuxiliaryPFOptimal" (optimal sampling with rejection sampling approximation),
00140                   *  common to both localization and mapping.
00141                   *
00142                   * - BINTYPE: TPoseBin or whatever to discretize the sample space for KLD-sampling.
00143                   *
00144                   *  This method implements optimal sampling with a rejection sampling-based approximation of the true posterior.
00145                   *  For details, see the papers:
00146                   *
00147                   *  J.-L. Blanco, J. González, and J.-A. Fernández-Madrigal,
00148                   *    "An Optimal Filtering Algorithm for Non-Parametric Observation Models in
00149                   *     Robot Localization," in Proc. IEEE International Conference on Robotics
00150                   *     and Automation (ICRA'08), 2008, pp. 461–466.
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                         // Standard and Optimal AuxiliaryPF actually have a shared implementation body:
00161                         PF_SLAM_implementation_pfAuxiliaryPFStandardAndOptimal<BINTYPE>(actions,sf,PF_options,KLD_options, true /*Optimal PF*/ );
00162                 }
00163 
00164 
00165                 /** A generic implementation of the PF method "pfStandardProposal" (standard proposal distribution, that is, a simple SIS particle filter),
00166                   *  common to both localization and mapping.
00167                   *
00168                   * - BINTYPE: TPoseBin or whatever to discretize the sample space for KLD-sampling.
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                         // In this method we don't need the "PF_SLAM_implementation_gatherActionsCheckBothActObs" machinery,
00184                         //  since prediction & update are two independent stages well separated for this algorithm.
00185 
00186                         // --------------------------------------------------------------------------------------
00187                         //  Prediction: Simply draw samples from the motion model
00188                         // --------------------------------------------------------------------------------------
00189                         if (actions)
00190                         {
00191                                 // Find a robot movement estimation:
00192                                 CPose3D                         motionModelMeanIncr;
00193                                 {
00194                                         CActionRobotMovement2DPtr       robotMovement2D = actions->getBestMovementEstimation();
00195                                         // If there is no 2D action, look for a 3D action:
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                                 // Update particle poses:
00214                                 if ( !PF_options.adaptiveSampleSize )
00215                                 {
00216                                         const size_t M = me->m_particles.size();
00217                                         // -------------------------------------------------------------
00218                                         // FIXED SAMPLE SIZE
00219                                         // -------------------------------------------------------------
00220                                         CPose3D incrPose;
00221                                         for (size_t i=0;i<M;i++)
00222                                         {
00223                                                 // Generate gaussian-distributed 2D-pose increments according to mean-cov:
00224                                                 m_movementDrawer.drawSample( incrPose );
00225                                                 CPose3D finalPose = CPose3D(*getLastPose(i)) + incrPose;
00226 
00227                                                 // Update the particle with the new pose: this part is caller-dependant and must be implemented there:
00228                                                 PF_SLAM_implementation_custom_update_particle_with_new_pose( me->m_particles[i].d, TPose3D(finalPose) );
00229                                         }
00230                                 }
00231                                 else
00232                                 {
00233                                         // -------------------------------------------------------------
00234                                         //   ADAPTIVE SAMPLE SIZE
00235                                         // Implementation of Dieter Fox's KLD algorithm
00236                                         //  31-Oct-2006 (JLBC): First version
00237                                         //  19-Jan-2009 (JLBC): Rewriten within a generic template
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                                         // Prepare data for executing "fastDrawSample"
00246                                         me->prepareFastDrawSample(PF_options);
00247 
00248                                         // The new particle set:
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      // THE MAIN DRAW SAMPLING LOOP
00257                                         {
00258                                                 // Draw a robot movement increment:
00259                                                 m_movementDrawer.drawSample( increment_i );
00260 
00261                                                 // generate the new particle:
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                                                 // Add to the new particles list:
00267                                                 newParticles.push_back( newPose_s );
00268                                                 newParticlesWeight.push_back(0);
00269                                                 newParticlesDerivedFromIdx.push_back(drawn_idx);
00270 
00271                                                 // Now, look if the particle falls in a new bin or not:
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                                                         // It falls into a new bin:
00279                                                         // Add to the stateSpaceBins:
00280                                                         stateSpaceBins.insert( p );
00281 
00282                                                         // K = K + 1
00283                                                         size_t  K = stateSpaceBins.size();
00284                                                         if ( K>1) //&& newParticles.size() > options.KLD_minSampleSize )
00285                                                         {
00286                                                                 // Update the number of m_particles!!
00287                                                                 Nx =  round(epsilon_1 * math::chi2inv(delta_1,K-1));
00288                                                                 //printf("k=%u \tn=%u \tNx:%u\n", k, newParticles.size(), Nx);
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                                         // Substitute old by new particle set:
00297                                         //   Old are in "m_particles"
00298                                         //   New are in "newParticles", "newParticlesWeight","newParticlesDerivedFromIdx"
00299                                         // ---------------------------------------------------------------------------------
00300                                         this->PF_SLAM_implementation_replaceByNewParticleSet(
00301                                                 me->m_particles,
00302                                                 newParticles,newParticlesWeight,newParticlesDerivedFromIdx );
00303 
00304                                 } // end adaptive sample size
00305                         }
00306 
00307                         if (sf)
00308                         {
00309                                 const size_t M = me->m_particles.size();
00310                                 //      UPDATE STAGE
00311                                 // ----------------------------------------------------------------------
00312                                 // Compute all the likelihood values & update particles weight:
00313                                 for (size_t i=0;i<M;i++)
00314                                 {
00315                                         const TPose3D  *partPose= getLastPose(i); // Take the particle data:
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                                 } // for each particle "i"
00320 
00321                                 // Normalization of weights is done outside of this method automatically.
00322                         }
00323 
00324                         MRPT_END
00325                 }  // end of PF_SLAM_implementation_pfStandardProposal
00326 
00327                 /** A generic implementation of the PF method "prediction_and_update_pfAuxiliaryPFStandard" (Auxiliary particle filter with the standard proposal),
00328                   *  common to both localization and mapping.
00329                   *
00330                   * - BINTYPE: TPoseBin or whatever to discretize the sample space for KLD-sampling.
00331                   *
00332                   *  This method is described in the paper:
00333                   *   Pitt, M.K.; Shephard, N. (1999). "Filtering Via Simulation: Auxiliary Particle Filters".
00334                   *    Journal of the American Statistical Association 94 (446): 590–591. doi:10.2307/2670179.
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                         // Standard and Optimal AuxiliaryPF actually have a shared implementation body:
00346                         PF_SLAM_implementation_pfAuxiliaryPFStandardAndOptimal<BINTYPE>(actions,sf,PF_options,KLD_options, false /*APF*/ );
00347                 }
00348 
00349                 /*---------------------------------------------------------------
00350                                         PF_SLAM_particlesEvaluator_AuxPFOptimal
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                         //const PF_implementation<PARTICLE_TYPE,MYSELF> *myObj = reinterpret_cast<const PF_implementation<PARTICLE_TYPE,MYSELF>*>( obj );
00364                         const MYSELF *me = static_cast<const MYSELF*>(obj);
00365 
00366                         // Compute the quantity:
00367                         //     w[i]·p(zt|z^{t-1},x^{[i],t-1})
00368                         // As the Monte-Carlo approximation of the integral over all posible $x_t$.
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);          // The vector with the individual log-likelihoods.
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                                 // Estimate the mean...
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                                 {       // Keep the maximum value:
00394                                         maxLikDraw      = drawnSample;
00395                                         maxLik          = indivLik;
00396                                 }
00397                         }
00398 
00399                         // This is done to avoid floating point overflow!!
00400                         //      average_lik    =      \sum(e^liks)   * e^maxLik  /     N
00401                         // log( average_lik  ) = log( \sum(e^liks) ) + maxLik   - log( N )
00402                         double avrgLogLik = math::averageLogLikelihood( vectLiks );
00403 
00404                         // Save into the object:
00405                         me->m_pfAuxiliaryPFOptimal_estimatedProb[index] = avrgLogLik; // log( accum / N );
00406                         me->m_pfAuxiliaryPFOptimal_maxLikelihood[index] = maxLik;
00407 
00408                         if (PF_options.pfAuxFilterOptimal_MLE)
00409                                 me->m_pfAuxiliaryPFOptimal_maxLikDrawnMovement[index] = maxLikDraw;
00410 
00411                         // and compute the resulting probability of this particle:
00412                         // ------------------------------------------------------------
00413                         return me->m_particles[index].log_w + me->m_pfAuxiliaryPFOptimal_estimatedProb[index];
00414 
00415                         MRPT_END
00416                 } // end of PF_SLAM_particlesEvaluator_AuxPFOptimal
00417 
00418 
00419                 /**  Compute w[i]·p(z_t | mu_t^i), with mu_t^i being
00420                   *    the mean of the new robot pose
00421                   *
00422                   * \param action MUST be a "const CPose3D*"
00423                   * \param observation MUST be a "const CSensoryFrame*"
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                         //const PF_implementation<PARTICLE_TYPE,MYSELF> *myObj = reinterpret_cast<const PF_implementation<PARTICLE_TYPE,MYSELF>*>( obj );
00437                         const MYSELF *myObj = static_cast<const MYSELF*>(obj);
00438 
00439                         // Take the previous particle weight:
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                                 // Just use the mean:
00446                                 // , take the mean of the posterior density:
00447                                 CPose3D  x_predict;
00448                                 x_predict.composeFrom( oldPose, *static_cast<const CPose3D*>(action) );
00449 
00450                                 // and compute the obs. likelihood:
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                                 // Combined log_likelihood: Previous weight * obs_likelihood:
00457                                 return cur_logweight + myObj->m_pfAuxiliaryPFStandard_estimatedProb[index];
00458                         }
00459                         else
00460                         {
00461                                 // Do something similar to in Optimal sampling:
00462                                 // Compute the quantity:
00463                                 //     w[i]·p(zt|z^{t-1},x^{[i],t-1})
00464                                 // As the Monte-Carlo approximation of the integral over all posible $x_t$.
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);          // The vector with the individual log-likelihoods.
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                                         // Estimate the mean...
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                                         {       // Keep the maximum value:
00489                                                 maxLikDraw      = drawnSample;
00490                                                 maxLik          = indivLik;
00491                                         }
00492                                 }
00493 
00494                                 // This is done to avoid floating point overflow!!
00495                                 //      average_lik    =      \sum(e^liks)   * e^maxLik  /     N
00496                                 // log( average_lik  ) = log( \sum(e^liks) ) + maxLik   - log( N )
00497                                 double avrgLogLik = math::averageLogLikelihood( vectLiks );
00498 
00499                                 // Save into the object:
00500                                 myObj->m_pfAuxiliaryPFStandard_estimatedProb[index] = avrgLogLik; // log( accum / N );
00501 
00502                                 myObj->m_pfAuxiliaryPFOptimal_maxLikelihood[index] = maxLik;
00503                                 if (PF_options.pfAuxFilterOptimal_MLE)
00504                                         myObj->m_pfAuxiliaryPFOptimal_maxLikDrawnMovement[index] = maxLikDraw;
00505 
00506                                 // and compute the resulting probability of this particle:
00507                                 // ------------------------------------------------------------
00508                                 return cur_logweight + myObj->m_pfAuxiliaryPFOptimal_estimatedProb[index];
00509                         }
00510                         MRPT_END
00511                 }
00512 
00513                 // USE_OPTIMAL_SAMPLING:
00514                 //   true -> PF_SLAM_implementation_pfAuxiliaryPFOptimal
00515                 //  false -> PF_SLAM_implementation_pfAuxiliaryPFStandard
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                         //        We can execute optimal PF only when we have both, an action, and
00534                         //     a valid observation from which to compute the likelihood:
00535                         //   Accumulate odometry/actions until we have a valid observation, then
00536                         //    process them simultaneously.
00537                         // ----------------------------------------------------------------------
00538                         if (!PF_SLAM_implementation_gatherActionsCheckBothActObs<BINTYPE>(actions,sf))
00539                                 return; // Nothing we can do here...
00540                         // OK, we have m_movementDrawer loaded and observations...let's roll!
00541 
00542 
00543                         // -------------------------------------------------------------------------------
00544                         //              0) Common part:  Prepare m_particles "draw" and compute "fastDrawSample"
00545                         // -------------------------------------------------------------------------------
00546                         // We need the (aproximate) maximum likelihood value for each
00547                         //  previous particle [i]:
00548                         //     max{ p( z^t | data^[i], x_(t-1)^[i], u_(t) ) }
00549                         //
00550 
00551                         m_pfAuxiliaryPFOptimal_maxLikelihood.assign(M, INVALID_LIKELIHOOD_VALUE);
00552                         m_pfAuxiliaryPFOptimal_maxLikDrawnMovement.resize(M);
00553 //                      if (USE_OPTIMAL_SAMPLING)
00554                                 m_pfAuxiliaryPFOptimal_estimatedProb.resize(M);
00555 //                      else
00556                                 m_pfAuxiliaryPFStandard_estimatedProb.resize(M);
00557 
00558                         // Pass the "mean" robot movement to the "weights" computing function:
00559                         CPose3D meanRobotMovement;
00560                         m_movementDrawer.getSamplingMean3D(meanRobotMovement);
00561 
00562                         // Prepare data for executing "fastDrawSample"
00563                         typedef PF_implementation<PARTICLE_TYPE,MYSELF> TMyClass; // Use this longer declaration to avoid errors in old GCC.
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                         // For USE_OPTIMAL_SAMPLING=1,  m_pfAuxiliaryPFOptimal_maxLikelihood is now computed.
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                         // Now we have the vector "m_fastDrawProbability" filled out with:
00583                         //               w[i]·p(zt|z^{t-1},x^{[i],t-1},X)
00584                         //  where,
00585                         //
00586                         //  =========== For USE_OPTIMAL_SAMPLING = true ====================
00587                         //  X is the robot pose prior (as implemented in
00588                         //  the aux. function "PF_SLAM_particlesEvaluator_AuxPFOptimal"),
00589                         //  and also the "m_pfAuxiliaryPFOptimal_maxLikelihood" filled with the maximum lik. values.
00590                         //
00591                         //  =========== For USE_OPTIMAL_SAMPLING = false ====================
00592                         //  X is a single point close to the mean of the robot pose prior (as implemented in
00593                         //  the aux. function "PF_SLAM_particlesEvaluator_AuxPFStandard").
00594                         //
00595                         vector<TPose3D>                 newParticles;
00596                         vector<double>                  newParticlesWeight;
00597                         vector<size_t>                  newParticlesDerivedFromIdx;
00598 
00599                         // We need the (aproximate) maximum likelihood value for each
00600                         //  previous particle [i]:
00601                         //
00602                         //     max{ p( z^t | data^[i], x_(t-1)^[i], u_(t) ) }
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                                 //                                              1) FIXED SAMPLE SIZE VERSION
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                                         // Generate a new particle:
00628                                         //   (a) Draw a "t-1" m_particles' index:
00629                                         // ----------------------------------------------------------------
00630                                         if (doResample)
00631                                                         k = me->fastDrawSample(PF_options);             // Based on weights of last step only!
00632                                         else    k = i;
00633 
00634                                         // Do one rejection sampling step:
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                                         // Insert the new particle
00645                                         newParticles[i] = newPose;
00646                                         newParticlesDerivedFromIdx[i] = k;
00647                                         newParticlesWeight[i] = newParticleLogWeight;
00648 
00649                                 } // for i
00650                         } // end fixed sample size
00651                         else
00652                         {
00653                                 // -------------------------------------------------------------------------------------------------
00654                                 //                                                              2) ADAPTIVE SAMPLE SIZE VERSION
00655                                 //
00656                                 //      Implementation of Dieter Fox's KLD algorithm
00657                                 //              JLBC (3/OCT/2006)
00658                                 // -------------------------------------------------------------------------------------------------
00659                                 // The new particle set:
00660                                 newParticles.clear();
00661                                 newParticlesWeight.clear();
00662                                 newParticlesDerivedFromIdx.clear();
00663 
00664                                 // ------------------------------------------------------------------------------
00665                                 // 2.1) PRELIMINARY STAGE: Build a list of pairs<TPathBin,vector_uint> with the
00666                                 //      indexes of m_particles that fall into each multi-dimensional-path bins
00667                                 //      //The bins will be saved into "stateSpaceBinsLastTimestep", and the list
00668                                 //      //of corresponding m_particles (in the last timestep), in "stateSpaceBinsLastTimestepParticles"
00669                                 //  - Added JLBC (01/DEC/2006)
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                                         // Load the bin from the path data:
00680                                         BINTYPE p;
00681                                         KLF_loadBinFromParticle<PARTICLE_TYPE,BINTYPE>(p, KLD_options,partIt->d );
00682 
00683                                         // Is it a new bin?
00684                                         typename TSetStateSpaceBins::iterator posFound=stateSpaceBinsLastTimestep.find(p);
00685                                         if ( posFound == stateSpaceBinsLastTimestep.end() )
00686                                         {       // Yes, create a new pair <bin,index_list> in the list:
00687                                                 stateSpaceBinsLastTimestep.insert( p );
00688                                                 stateSpaceBinsLastTimestepParticles.push_back( vector_uint(1,partIndex) );
00689                                         }
00690                                         else
00691                                         { // No, add the particle's index to the existing entry:
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                                 // 2.2)    THE MAIN KLD-BASED DRAW SAMPLING LOOP
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                                 //double        maxLik = math::maximum(m_pfAuxiliaryPFOptimal_maxLikelihood); // For normalization purposes only
00705 
00706                                 // The desired dynamic number of m_particles (to be modified dynamically below):
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);  // Use a list since we'll use "erase" a lot here.
00712                                 for (size_t k=0;k<Np1;k++) oldPartIdxsStillNotPropragated[k]=k; //.push_back(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                                 // Instead of picking randomly from "permutationPathsAuxVector", we can shuffle it now just once,
00719                                 // then pick in sequence from the tail and resize the container:
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 // "N" is the index of the current "new particle":
00731                                 {
00732                                         // Generate a new particle:
00733                                         //
00734                                         //   (a) Propagate the last set of m_particles, and only if the
00735                                         //       desired number of m_particles in this step is larger,
00736                                         //       perform a UNIFORM sampling from the last set. In this way
00737                                         //       the new weights can be computed in the same way for all m_particles.
00738                                         // ---------------------------------------------------------------------------
00739                                         if (doResample)
00740                                         {
00741                                                 k = me->fastDrawSample(PF_options);             // Based on weights of last step only!
00742                                         }
00743                                         else
00744                                         {
00745                                                 // Assure that at least one particle per "discrete-path" is taken (if the
00746                                                 //  number of samples allows it)
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                                                         // Also erase it from the other permutation vector list:
00757                                                         oldPartIdxsStillNotPropragated.erase(std::find(oldPartIdxsStillNotPropragated.begin(),oldPartIdxsStillNotPropragated.end(),k));
00758                                                 }
00759                                                 else
00760                                                 {
00761                                                         // Select a particle from the previous set with a UNIFORM distribution,
00762                                                         // in such a way we will assign each particle the updated weight accounting
00763                                                         // for its last weight.
00764                                                         // The first "old_N" m_particles will be drawn using a uniform random selection
00765                                                         // without repetitions:
00766                                                         //
00767                                                         // Select a index from "oldPartIdxsStillNotPropragated" and remove it from the list:
00768                                                         if (oldPartIdxsStillNotPropragated.size())
00769                                                         {
00770                                                                 const size_t idx = randomGenerator.drawUniform32bit() % oldPartIdxsStillNotPropragated.size();
00771                                                                 vector_size_t::iterator it = oldPartIdxsStillNotPropragated.begin() + idx; //advance(it,idx);
00772                                                                 k = *it;
00773                                                                 oldPartIdxsStillNotPropragated.erase(it);
00774                                                         }
00775                                                         else
00776                                                         {
00777                                                                 // N>N_old -> Uniformly draw index:
00778                                                                 k = randomGenerator.drawUniform32bit() % me->m_particles.size();
00779                                                         }
00780                                                 }
00781                                         }
00782 
00783                                         // Do one rejection sampling step:
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                                         // Insert the new particle
00794                                         newParticles.push_back( newPose );
00795                                         newParticlesDerivedFromIdx.push_back( k );
00796                                         newParticlesWeight.push_back(newParticleLogWeight);
00797 
00798                                         // ----------------------------------------------------------------
00799                                         // Now, the KLD-sampling dynamic sample size stuff:
00800                                         //  look if the particle's PATH falls into a new bin or not:
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                                         // Look for the bin "p" into "stateSpaceBins": If it is not yet into the set,
00808                                         //  then we may increase the desired particle number:
00809                                         // -----------------------------------------------------------------------------
00810 
00811                                         // Found?
00812                                         if ( stateSpaceBins.find(p)==stateSpaceBins.end() )
00813                                         {
00814                                                 // It falls into a new bin: add to the stateSpaceBins:
00815                                                 stateSpaceBins.insert( p );
00816 
00817                                                 // K = K + 1
00818                                                 int K = stateSpaceBins.size();
00819                                                 if ( K>1 )
00820                                                 {
00821                                                         // Update the number of m_particles!!
00822                                                         Nx = (size_t) (epsilon_1 * math::chi2inv(delta_1,K-1));
00823                                                         //printf("k=%u \tn=%u \tNx:%u\n", k, newParticles.size(), Nx);
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                         } // end adaptive sample size
00835 
00836 
00837                         // ---------------------------------------------------------------------------------
00838                         // Substitute old by new particle set:
00839                         //   Old are in "m_particles"
00840                         //   New are in "newParticles", "newParticlesWeight","newParticlesDerivedFromIdx"
00841                         // ---------------------------------------------------------------------------------
00842                         this->PF_SLAM_implementation_replaceByNewParticleSet(
00843                                 me->m_particles,
00844                                 newParticles,newParticlesWeight,newParticlesDerivedFromIdx );
00845 
00846 
00847                         // In this PF_algorithm, we must do weight normalization by ourselves:
00848                         me->normalizeWeights();
00849 
00850                         MRPT_END
00851                 } // end of PF_SLAM_implementation_pfAuxiliaryPFStandardAndOptimal
00852 
00853 
00854                 /* ------------------------------------------------------------------------
00855                                                         PF_SLAM_aux_perform_one_rejection_sampling_step
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, // The particle from the old set "m_particles[]"
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                         // ADD-ON: If the 'm_pfAuxiliaryPFOptimal_estimatedProb[k]' is **extremelly** low relative to the other m_particles,
00872                         //  resample only this particle with a copy of another one, uniformly:
00873                         while ( ( (USE_OPTIMAL_SAMPLING ? m_pfAuxiliaryPFOptimal_estimatedProb[k] : m_pfAuxiliaryPFStandard_estimatedProb[k] )
00874                                                 -maxMeanLik) < -PF_options.max_loglikelihood_dyn_range )
00875                         {
00876                                 // Select another 'k' uniformly:
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);        // Get the current pose of the k'th particle
00882 
00883                         //   (b) Rejection-sampling: Draw a new robot pose from x[k],
00884                         //       and accept it with probability p(zk|x) / maxLikelihood:
00885                         // ----------------------------------------------------------------
00886                         double poseLogLik;
00887                         if ( PF_SLAM_implementation_skipRobotMovement() )
00888                         {
00889                                 // The first robot pose in the SLAM execution: All m_particles start
00890                                 // at the same point (this is the lowest bound of subsequent uncertainty):
00891                                 out_newPose = oldPose;
00892                                 poseLogLik = 0;
00893                         }
00894                         else
00895                         {
00896                                 CPose3D movementDraw;
00897                                 if (!USE_OPTIMAL_SAMPLING)
00898                                 {       // APF:
00899                                         m_movementDrawer.drawSample( movementDraw );
00900                                         out_newPose.composeFrom(oldPose, movementDraw); // newPose = oldPose + movementDraw;
00901                                         // Compute likelihood:
00902                                         poseLogLik = PF_SLAM_computeObservationLikelihoodForParticle(PF_options, k,*sf,out_newPose);
00903                                 }
00904                                 else
00905                                 {       // Optimal APF with rejection sampling:
00906                                         // Rejection-sampling:
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                                                 // Draw new robot pose:
00915                                                 if (PF_options.pfAuxFilterOptimal_MLE && !m_pfAuxiliaryPFOptimal_maxLikMovementDrawHasBeenUsed[k])
00916                                                 {       // No! first take advantage of a good drawn value, but only once!!
00917                                                         m_pfAuxiliaryPFOptimal_maxLikMovementDrawHasBeenUsed[k] = true;
00918                                                         movementDraw = CPose3D( m_pfAuxiliaryPFOptimal_maxLikDrawnMovement[k] );
00919                                                 }
00920                                                 else
00921                                                 {
00922                                                         // Draw new robot pose:
00923                                                         m_movementDrawer.drawSample( movementDraw );
00924                                                 }
00925 
00926                                                 out_newPose.composeFrom(oldPose, movementDraw); // out_newPose = oldPose + movementDraw;
00927 
00928                                                 // Compute acceptance probability:
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                                                         //acceptanceProb = 0;           // Keep searching or keep this one?
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                                 // And its weight:
00957                                 if (USE_OPTIMAL_SAMPLING)
00958                                 {       // Optimal PF
00959                                         if (doResample)
00960                                                 out_newParticleLogWeight = 0;  // By definition of our optimal PF, all samples have identical weights.
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                                 {       // APF:
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                         // Done.
00977                 } // end PF_SLAM_aux_perform_one_rejection_sampling_step
00978 
00979 
00980         } // end namespace
00981 } // end namespace
00982 
00983 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011