Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ShapeSLAMParticleFilter.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 
00003 #ifndef _LOADED_ShapeSLAMParticleFilter_h_
00004 #define _LOADED_ShapeSLAMParticleFilter_h_
00005 
00006 #include <vector>
00007 #include <iostream>
00008 #include <cmath>
00009 #include "DeadReckoningBehavior.h"
00010 #include "LocalizationParticle.h"
00011 
00012 namespace DualCoding {
00013   
00014   class ShapeSpace;
00015   class ShapeSLAMParticleDistributionPolicy;
00016 
00017   //! Each Particle represents a hypothesis about the match of the local map to the world map, considering changes to the map
00018   /*! Only handles adding or removing landmarks, not moving existing landmarks.  (A move
00019    *  can be modeled as an addition plus a deletion, but there will be two penalties to pay.)
00020    *
00021    *  Note that the particle evaluation doesn't modify the world map, only
00022    *  tracks suggestions about what @e should be changed.
00023    *
00024    *  The size of addLocal and deleteWorld may not exactly match the number
00025    *  of current local or world landmarks -- the SensorModel is lazy about resizing
00026    *  for efficiency reasons. */
00027   class ShapeSLAMParticle : public LocalizationParticle {
00028   public:
00029     //! Defines a default DistributionPolicy for the particle type (just reuse the same one as LocalizationParticle)
00030     typedef LocalizationParticleDistributionPolicy<ShapeSLAMParticle> DistributionPolicy;
00031 
00032     //! Constructor
00033     ShapeSLAMParticle() : LocalizationParticle(), addLocal(), deleteWorld() {}
00034   
00035     std::vector<bool> addLocal; //!< true for local landmarks missing from the world map
00036     std::vector<bool> deleteWorld;  //!< true for world landmarks missing from the local map
00037   };
00038 
00039   //! extends ParticleShapeEvaluator to handle the addition and removal of landmarks as necessary
00040   class ShapeSLAMParticleEvaluator : public LocalShapeEvaluator {
00041   public:
00042     //! constructor, addPenalty specifies how much to add/multiply (logspace/linear space) weight when considering a landmark as an addition
00043     ShapeSLAMParticleEvaluator(ShapeSpace &localShS, ShapeSpace &worldShS, float addPenalty);
00044     using LocalShapeEvaluator::evaluate;
00045     void evaluate(ShapeSLAMParticle& part); //!< provides evaluation of SLAM-particles
00046   protected:
00047     //! may mark landmarks for addition which don't appear in the world map
00048     void determineAdditions(ShapeSLAMParticle& part, unsigned int const nLocals,
00049           int localMatches[], float localScores[]);
00050     //! may mark landmarks for removal which don't appear in the world map
00051     void determineDeletions(ShapeSLAMParticle& part, unsigned int const nLocals, int const localMatches[],
00052           float const particleViewX[], float const particleViewY[],
00053           float const particleViewX2[], float const particleViewY2[]);
00054     bool localMobile; //!< set to true if *any* landmarks are marked as "mobile"
00055     bool worldMobile; //!< set to true if *any* landmarks are marked as "mobile"
00056     const float ADDITION_PENALTY; //!< the value passed to the constructor, limits how readily landmarks are added to the map
00057   };
00058 
00059 
00060 //================ ShapeSLAMSensorModel ================
00061 
00062   //! this wraps the ShapeSLAMParticleEvaluator in a ParticleFilter::SensorModel so it can be used by the particle filter
00063   /*! see ShapeSensorModel for discussion of architectural issues vs separation of ShapeSLAMParticleEvaluator */
00064   template<typename ParticleT>
00065   class ShapeSLAMSensorModel : public ParticleFilter<ParticleT>::SensorModel {
00066   public:
00067     typedef typename ParticleFilter<ParticleT>::SensorModel::particle_type particle_type; //!< convenience typedef
00068     typedef typename ParticleFilter<ParticleT>::SensorModel::particle_collection particle_collection; //!< convenience typedef
00069     typedef typename ParticleFilter<ParticleT>::SensorModel::index_t index_t; //!< convenience typedef
00070   
00071     //! constructor, the standard deviation on matches defaults to 60, but you can always reassign #stdevSq directly
00072     ShapeSLAMSensorModel(ShapeSpace &localShS, ShapeSpace &worldShS) :
00073       stdevSq(60*60), addPenalty(50), lShS(localShS), wShS(worldShS),
00074       particleLocalLandmarks(0), particleWorldLandmarks(0)
00075     {}
00076   
00077     //! controls how much weight is given to "near-misses"
00078     float stdevSq;
00079     //! controls how readily new landmarks are added to the map, vs. penalizing the particle for a bad match
00080     float addPenalty;
00081   
00082     //! applies the ShapeSLAMParticleEvaluator across a collection of particles
00083     virtual void evaluate(particle_collection& particles, particle_type& estimate) {
00084       float bestWeight=-FLT_MAX;
00085       ShapeSLAMParticleEvaluator eval(lShS,wShS,addPenalty);
00086     
00087       if(eval.localLms.size()>particleLocalLandmarks || eval.localLms.size()<particleLocalLandmarks/2)
00088   for(typename particle_collection::iterator it=particles.begin(); it!=particles.end(); ++it)
00089     it->addLocal.resize(particleLocalLandmarks);
00090     
00091       if(eval.worldLms.size()>particleWorldLandmarks || eval.worldLms.size()<particleWorldLandmarks/2)
00092   for(typename particle_collection::iterator it=particles.begin(); it!=particles.end(); ++it)
00093     it->deleteWorld.resize(particleWorldLandmarks);
00094     
00095       for(typename particle_collection::size_type p=0; p<particles.size(); ++p) {
00096   eval.evaluate(particles[p]);
00097   if(particles[p].weight>bestWeight) {
00098     bestWeight=particles[p].weight;
00099   }
00100       }
00101     }
00102   
00103   ShapeSpace& getLocalShS() const { return lShS; }
00104   ShapeSpace& getWorldShS() const { return wShS; }
00105 
00106   protected:
00107     ShapeSpace &lShS;     //!< Local shape space
00108     ShapeSpace &wShS;     //!< World shape space
00109 
00110     unsigned int particleLocalLandmarks; //!< number of entries in particles' individual addLocal (so we know if we need to resize it in all particles)
00111     unsigned int particleWorldLandmarks; //!<  number of entries in particles' individual deleteWorld (so we know if we need to resize it in all particles)
00112 
00113     //! computes a (non-normalized) gaussian distribution
00114     /*! normalization doesn't matter because it's constant across particles, and so
00115      *  doesn't matter for purposes of comparison between particles */
00116     inline float normpdf(float const distsq) { return std::exp(-distsq/stdevSq); }
00117   };
00118 
00119 
00120 //================ ShapeSLAMParticleFilter ================
00121 
00122   //! bundles a DeadReckoning motion model and a ShapeSLAMSensorModel for easy use of a shape-based particle filter for mapping and localization
00123   class ShapeSLAMParticleFilter : public ParticleFilter<ShapeSLAMParticle> {
00124   public:
00125     //! constructor, must pass local and world shape spaces, which will be used in future calls to update()
00126     ShapeSLAMParticleFilter(ShapeSpace &localShS, ShapeSpace &worldShS, unsigned int numParticles=2000)
00127       : ParticleFilter<ShapeSLAMParticle>(numParticles, new DeadReckoningBehavior<ShapeSLAMParticle>),
00128   sensorModel(new ShapeSLAMSensorModel<ShapeSLAMParticle>(localShS,worldShS))
00129     {
00130       if(BehaviorBase* motBeh = dynamic_cast<BehaviorBase*>(motion))
00131   motBeh->start();
00132     }
00133     //! destructor
00134     virtual ~ShapeSLAMParticleFilter() {
00135       if(BehaviorBase* motBeh = dynamic_cast<BehaviorBase*>(motion)) {
00136   motBeh->stop();
00137   // behaviors are reference counted, stopping removes our reference, set to NULL to avoid call to delete in ParticleFilter
00138   motion=NULL;
00139       }
00140       delete sensorModel;
00141     }
00142   
00143     //! update, triggers a particle filter update using the embedded #sensorModel
00144     virtual void update(bool updateMot=true, bool doResample=true) { updateSensors(*sensorModel,updateMot,doResample); }
00145   
00146     //! accessor for #sensorModel
00147     virtual ShapeSLAMSensorModel<ShapeSLAMParticle>& getSensorModel() const { return *sensorModel; }
00148 
00149     //! replaces the sensor model in use, the particle filter will take responsibility for deallocating the sensor model's memory when destructed or replaced
00150     virtual void setSensorModel(ShapeSLAMSensorModel<ShapeSLAMParticle>* customSensorModel) { delete sensorModel; sensorModel=customSensorModel; }
00151 
00152     //! updates the mapbuilder's agent's position on worldShS
00153     virtual void setAgent() const;
00154   
00155     //! Currently not working for SLAM particles, but should display particles on the world map; howmany can either be a percentage (<= 1.0) or a whole number
00156     virtual void displayParticles(float const howmany=100) const;
00157 
00158   protected:
00159     ShapeSLAMSensorModel<ShapeSLAMParticle> * sensorModel; //!< provides evaluation of particles
00160 
00161   private:
00162     ShapeSLAMParticleFilter(const ShapeSLAMParticleFilter&); //!< don't call (copy constructor)
00163     ShapeSLAMParticleFilter& operator=(const ShapeSLAMParticleFilter&); //!< don't call (assignment operator)
00164   };
00165 
00166   //! allows display of particles on console
00167   std::ostream& operator<< (std::ostream& os, const ShapeSLAMParticle &p);
00168 
00169 } // namespace
00170 
00171 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:50 2016 by Doxygen 1.6.3