Main MRPT website > C++ reference
MRPT logo
PF_implementations_data.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 #ifndef PF_implementations_data_H
00029 #define PF_implementations_data_H
00030 
00031 #include <mrpt/slam/CActionRobotMovement2D.h>
00032 #include <mrpt/bayes/CParticleFilterData.h>
00033 #include <mrpt/math/lightweight_geom_data.h>
00034 #include <mrpt/poses/CPose3D.h>
00035 #include <mrpt/poses/CPose3DPDFGaussian.h>
00036 #include <mrpt/poses/CPoseRandomSampler.h>
00037 #include <mrpt/slam/TKLDParams.h>
00038 
00039 #include <mrpt/slam/link_pragmas.h>
00040 
00041 namespace mrpt
00042 {
00043         namespace slam
00044         {
00045                 using namespace std;
00046                 using namespace mrpt::poses;
00047                 using namespace mrpt::bayes;
00048                 using namespace mrpt::math;
00049 
00050 
00051                 // Frwd decl:
00052                 template <class PARTICLETYPE, class BINTYPE>
00053                 void KLF_loadBinFromParticle(
00054                         BINTYPE                         &outBin,
00055                         const TKLDParams        &opts,
00056                         const PARTICLETYPE      *currentParticleValue = NULL,
00057                         const TPose3D           *newPoseToBeInserted = NULL );
00058 
00059 
00060                 /** A set of common data shared by PF implementations for both SLAM and localization
00061                   *   \ingroup mrpt_slam_grp
00062                   */
00063                 template <class PARTICLE_TYPE, class MYSELF>
00064                 class PF_implementation
00065                 {
00066                 public:
00067                         PF_implementation() :
00068                                 m_accumRobotMovement2DIsValid(false),
00069                                 m_accumRobotMovement3DIsValid(false)
00070                         {
00071                         }
00072 
00073                         //typedef mrpt::bayes::CParticleFilterData<PARTICLE_TYPE> BASE;
00074                         //typedef mrpt::bayes::CParticleFilterCapable                           BASE2;
00075 
00076                 protected:
00077 
00078                         //BASE  &m_partdata;  //!< the particle filter data object, implementing CParticleFilterData<PARTICLE_TYPE>
00079                         //BASE2 &m_pfc;           //!< the particle filter data object, implementing CParticleFilterCapable
00080 
00081                         /** \name Data members and methods used by generic PF implementations
00082                             @{ */
00083 
00084                         CActionRobotMovement2D  m_accumRobotMovement2D;
00085                         bool                                    m_accumRobotMovement2DIsValid;
00086                         CPose3DPDFGaussian              m_accumRobotMovement3D;
00087                         bool                                    m_accumRobotMovement3DIsValid;
00088 
00089                         CPoseRandomSampler                              m_movementDrawer;                                               //!< Used in al PF implementations. \sa PF_SLAM_implementation_gatherActionsCheckBothActObs
00090                         mutable vector_double                   m_pfAuxiliaryPFOptimal_estimatedProb;   //!< Auxiliary variable used in the "pfAuxiliaryPFOptimal" algorithm.
00091                         mutable vector_double                   m_pfAuxiliaryPFStandard_estimatedProb;  //!< Auxiliary variable used in the "pfAuxiliaryPFStandard" algorithm.
00092                         mutable vector_double                   m_pfAuxiliaryPFOptimal_maxLikelihood;                                           //!< Auxiliary variable used in the "pfAuxiliaryPFOptimal" algorithm.
00093                         mutable std::vector<TPose3D>    m_pfAuxiliaryPFOptimal_maxLikDrawnMovement;             //!< Auxiliary variable used in the "pfAuxiliaryPFOptimal" algorithm.
00094                         std::vector<bool>                               m_pfAuxiliaryPFOptimal_maxLikMovementDrawHasBeenUsed;
00095 
00096                         /**  Compute w[i]·p(z_t | mu_t^i), with mu_t^i being
00097                           *    the mean of the new robot pose
00098                           *
00099                           * \param action MUST be a "const CPose3D*"
00100                           * \param observation MUST be a "const CSensoryFrame*"
00101                           */
00102                         template <class BINTYPE> // Template arg. actually not used, just to allow giving the definition in another file later on
00103                         static double PF_SLAM_particlesEvaluator_AuxPFStandard(
00104                                 const CParticleFilter::TParticleFilterOptions &PF_options,
00105                                 const CParticleFilterCapable    *obj,
00106                                 size_t index,
00107                                 const void * action,
00108                                 const void * observation );
00109 
00110                         template <class BINTYPE> // Template arg. actually not used, just to allow giving the definition in another file later on
00111                         static double  PF_SLAM_particlesEvaluator_AuxPFOptimal(
00112                                 const CParticleFilter::TParticleFilterOptions &PF_options,
00113                                 const CParticleFilterCapable    *obj,
00114                                 size_t                                  index,
00115                                 const void                              *action,
00116                                 const void                              *observation );
00117 
00118                         /** @} */
00119 
00120                         /** \name The generic PF implementations for localization & SLAM.
00121                             @{ */
00122 
00123                         /** A generic implementation of the PF method "prediction_and_update_pfAuxiliaryPFOptimal" (optimal sampling with rejection sampling approximation),
00124                           *  common to both localization and mapping.
00125                           *
00126                           * - BINTYPE: TPoseBin or whatever to discretize the sample space for KLD-sampling.
00127                           *
00128                           *  This method implements optimal sampling with a rejection sampling-based approximation of the true posterior.
00129                           *  For details, see the papers:
00130                           *
00131                           *  J.-L. Blanco, J. González, and J.-A. Fernández-Madrigal,
00132                           *    "An Optimal Filtering Algorithm for Non-Parametric Observation Models in
00133                           *     Robot Localization," in Proc. IEEE International Conference on Robotics
00134                           *     and Automation (ICRA'08), 2008, pp. 461–466.
00135                           */
00136                         template <class BINTYPE>
00137                         void PF_SLAM_implementation_pfAuxiliaryPFOptimal(
00138                                 const CActionCollection * actions,
00139                                 const CSensoryFrame             * sf,
00140                                 const CParticleFilter::TParticleFilterOptions &PF_options,
00141                                 const TKLDParams &KLD_options);
00142 
00143                         /** A generic implementation of the PF method "prediction_and_update_pfAuxiliaryPFStandard" (Auxiliary particle filter with the standard proposal),
00144                           *  common to both localization and mapping.
00145                           *
00146                           * - BINTYPE: TPoseBin or whatever to discretize the sample space for KLD-sampling.
00147                           *
00148                           *  This method is described in the paper:
00149                           *   Pitt, M.K.; Shephard, N. (1999). "Filtering Via Simulation: Auxiliary Particle Filters".
00150                           *    Journal of the American Statistical Association 94 (446): 590–591. doi:10.2307/2670179.
00151                           *
00152                           */
00153                         template <class BINTYPE>
00154                         void PF_SLAM_implementation_pfAuxiliaryPFStandard(
00155                                 const CActionCollection * actions,
00156                                 const CSensoryFrame             * sf,
00157                                 const CParticleFilter::TParticleFilterOptions &PF_options,
00158                                 const TKLDParams &KLD_options);
00159 
00160 
00161                         /** A generic implementation of the PF method "pfStandardProposal" (standard proposal distribution, that is, a simple SIS particle filter),
00162                           *  common to both localization and mapping.
00163                           *
00164                           * - BINTYPE: TPoseBin or whatever to discretize the sample space for KLD-sampling.
00165                           */
00166                         template <class BINTYPE>
00167                         void PF_SLAM_implementation_pfStandardProposal(
00168                                 const CActionCollection * actions,
00169                                 const CSensoryFrame             * sf,
00170                                 const CParticleFilter::TParticleFilterOptions &PF_options,
00171                                 const TKLDParams &KLD_options);
00172 
00173                         /** @} */
00174 
00175 
00176                 public:
00177                         /** \name Virtual methods that the PF_implementations assume exist.
00178                             @{ */
00179 
00180                         /** Return a pointer to the last robot pose in the i'th particle (or NULL if it's a path and it's empty). */
00181                         virtual const TPose3D * getLastPose(const size_t i) const = 0;
00182 
00183                         virtual void PF_SLAM_implementation_custom_update_particle_with_new_pose(
00184                                 PARTICLE_TYPE *particleData,
00185                                 const TPose3D &newPose) const = 0;
00186 
00187                         /** This is the default algorithm to efficiently replace one old set of samples by another new set.
00188                           *  The method uses pointers to make fast copies the first time each particle is duplicated, then
00189                           *   makes real copies for the next ones.
00190                           *
00191                           *  Note that more efficient specializations might exist for specific particle data structs.
00192                           */
00193                         virtual void PF_SLAM_implementation_replaceByNewParticleSet(
00194                                 typename CParticleFilterData<PARTICLE_TYPE>::CParticleList       &old_particles,
00195                                 const vector<TPose3D>           &newParticles,
00196                                 const vector_double                     &newParticlesWeight,
00197                                 const vector<size_t>            &newParticlesDerivedFromIdx ) const
00198                         {
00199                                 // ---------------------------------------------------------------------------------
00200                                 // Substitute old by new particle set:
00201                                 //   Old are in "m_particles"
00202                                 //   New are in "newParticles", "newParticlesWeight","newParticlesDerivedFromIdx"
00203                                 // ---------------------------------------------------------------------------------
00204                                 const size_t N = newParticles.size();
00205                                 typename MYSELF::CParticleList newParticlesArray(N);
00206 
00207                                 // For efficiency, just copy the "CParticleData" from the old particle into the
00208                                 //  new one, but this can be done only once:
00209                                 std::vector<bool>       oldParticleAlreadyCopied(old_particles.size(),false);
00210 
00211                                 size_t i;
00212                                 typename MYSELF::CParticleList::iterator        newPartIt;
00213                                 for (newPartIt=newParticlesArray.begin(),i=0;newPartIt!=newParticlesArray.end();newPartIt++,i++)
00214                                 {
00215                                         // The weight:
00216                                         newPartIt->log_w = newParticlesWeight[i];
00217 
00218                                         // The data (CParticleData):
00219                                         PARTICLE_TYPE *newPartData;
00220                                         if (!oldParticleAlreadyCopied[newParticlesDerivedFromIdx[i]])
00221                                         {
00222                                                 // The first copy of this old particle:
00223                                                 newPartData = old_particles[ newParticlesDerivedFromIdx[i] ].d;
00224                                                 oldParticleAlreadyCopied[newParticlesDerivedFromIdx[i]] = true;
00225                                         }
00226                                         else
00227                                         {
00228                                                 // Make a copy:
00229                                                 newPartData = new PARTICLE_TYPE( *old_particles[ newParticlesDerivedFromIdx[i] ].d );
00230                                         }
00231 
00232                                         newPartIt->d = newPartData;
00233                                 } // end for "newPartIt"
00234 
00235                                 // Now add the new robot pose to the paths:
00236                                 //  (this MUST be done after the above loop, separately):
00237                                 // Update the particle with the new pose: this part is caller-dependant and must be implemented there:
00238                                 for (newPartIt=newParticlesArray.begin(),i=0;i<N;++newPartIt,++i)
00239                                         PF_SLAM_implementation_custom_update_particle_with_new_pose( newPartIt->d, newParticles[i] );
00240 
00241                                 // Free those old m_particles not being copied into the new ones:
00242                                 for (size_t i=0;i<old_particles.size();i++)
00243                                         if (!oldParticleAlreadyCopied[i])
00244                                                 mrpt::utils::delete_safe( old_particles[ i ].d );
00245 
00246                                 // Copy into "m_particles"
00247                                 old_particles.resize( newParticlesArray.size() );
00248                                 typename MYSELF::CParticleList::iterator        trgPartIt;
00249                                 for (newPartIt=newParticlesArray.begin(),trgPartIt=old_particles.begin(); newPartIt!=newParticlesArray.end(); ++newPartIt, ++trgPartIt )
00250                                 {
00251                                         trgPartIt->log_w = newPartIt->log_w;
00252                                         trgPartIt->d = newPartIt->d;
00253                                 }
00254                         } // end of PF_SLAM_implementation_replaceByNewParticleSet
00255 
00256 
00257 
00258                         virtual bool PF_SLAM_implementation_doWeHaveValidObservations(
00259                                 const typename CParticleFilterData<PARTICLE_TYPE>::CParticleList        &particles,
00260                                 const CSensoryFrame *sf) const
00261                         {
00262                                 return true;    // By default, always process the SFs.
00263                         }
00264 
00265                         /** Make a specialization if needed, eg. in the first step in SLAM.  */
00266                         virtual bool PF_SLAM_implementation_skipRobotMovement() const
00267                         {
00268                                 return false; // By default, always allow the robot to move!
00269                         }
00270 
00271                         /** Evaluate the observation likelihood for one particle at a given location */
00272                         virtual double PF_SLAM_computeObservationLikelihoodForParticle(
00273                                 const CParticleFilter::TParticleFilterOptions   &PF_options,
00274                                 const size_t                    particleIndexForMap,
00275                                 const CSensoryFrame             &observation,
00276                                 const CPose3D                   &x )  const = 0;
00277 
00278                         /** @} */
00279 
00280 
00281                 /** Auxiliary method called by PF implementations: return true if we have both action & observation,
00282                   *   otherwise, return false AND accumulate the odometry so when we have an observation we didn't lose a thing.
00283                   *   On return=true, the "m_movementDrawer" member is loaded and ready to draw samples of the increment of pose since last step.
00284                   *  This method is smart enough to accumulate CActionRobotMovement2D or CActionRobotMovement3D, whatever comes in.
00285                   */
00286                 template <class BINTYPE> // Template arg. actually not used, just to allow giving the definition in another file later on
00287                 bool PF_SLAM_implementation_gatherActionsCheckBothActObs(
00288                         const CActionCollection * actions,
00289                         const CSensoryFrame             * sf );
00290 
00291                 private:
00292                         /** The shared implementation body of two PF methods: APF and Optimal-APF, depending on USE_OPTIMAL_SAMPLING */
00293                         template <class BINTYPE>
00294                         void PF_SLAM_implementation_pfAuxiliaryPFStandardAndOptimal(
00295                                 const CActionCollection * actions,
00296                                 const CSensoryFrame             * sf,
00297                                 const CParticleFilter::TParticleFilterOptions &PF_options,
00298                                 const TKLDParams &KLD_options,
00299                                 const bool USE_OPTIMAL_SAMPLING  );
00300 
00301                         template <class BINTYPE>
00302                         void PF_SLAM_aux_perform_one_rejection_sampling_step(
00303                                 const bool              USE_OPTIMAL_SAMPLING,
00304                                 const bool              doResample,
00305                                 const double    maxMeanLik,
00306                                 size_t    k, // The particle from the old set "m_particles[]"
00307                                 const CSensoryFrame             * sf,
00308                                 const CParticleFilter::TParticleFilterOptions &PF_options,
00309                                 CPose3D                 & out_newPose,
00310                                 double                  & out_newParticleLogWeight);
00311 
00312 
00313                 }; // end PF_implementation
00314         }
00315 }
00316 
00317 #endif



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