Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ShapeBasedParticleFilter.h

Go to the documentation of this file.
00001 #ifndef _LOADED_ShapeBasedParticleFilter_h_
00002 #define _LOADED_ShapeBasedParticleFilter_h_
00003 
00004 #include <vector>
00005 #include <iostream>
00006 #include <cmath>
00007 
00008 #include "DualCoding/ShapePolygon.h"
00009 #include "Localization/LocalizationParticle.h"
00010 
00011 #include "Shared/RobotInfo.h"
00012 #ifdef TGT_IS_CREATE
00013 #  include "Localization/CreateMotionModel.h"
00014 #else
00015 #  include "Localization/DeadReckoningBehavior.h"
00016 #endif
00017 
00018 #include "ShapeSensorModel.h"
00019 
00020 namespace DualCoding {
00021   
00022   // Defined in this file: first ShapeParticleDistributionPolicy, then
00023   // ShapeBasedParticleFilter, which uses this policy
00024   
00025 
00026   //================ ShapeParticleDistributionPolicy ================
00027 
00028   template<typename ParticleT>
00029   class ShapeParticleDistributionPolicy : public LocalizationParticleDistributionPolicy<ParticleT> {
00030   public:
00031     typedef ParticleT particle_type;  //!< just for convenience
00032     typedef typename ParticleFilter<particle_type>::index_t index_t; //!< just for convenience
00033 
00034     ShapeParticleDistributionPolicy() : LocalizationParticleDistributionPolicy<ParticleT>(), worldBounds() {}
00035 
00036       // Override LocalizationParticleDistributionPolicy::randomize() so we can restrict particles
00037       // to fit within the worldBounds polygon if one is defined.
00038     virtual void randomize(particle_type* begin, index_t num) {
00039       particle_type* end=&begin[num]; 
00040       for(particle_type* p=begin; p!=end; p++) { 
00041   while (1) { // loop until particle is acceptable
00042     p->x = float(rand())/RAND_MAX * LocalizationParticleDistributionPolicy<ParticleT>::mapWidth + 
00043       LocalizationParticleDistributionPolicy<ParticleT>::mapMinX;
00044     p->y = float(rand())/RAND_MAX * LocalizationParticleDistributionPolicy<ParticleT>::mapHeight + 
00045       LocalizationParticleDistributionPolicy<ParticleT>::mapMinY;
00046     if ( !worldBounds.isValid() || worldBounds->isInside(Point(begin->x,begin->y)) )
00047       break;
00048   }
00049   p->theta = direction_t(rand())/RAND_MAX * 2 * direction_t(M_PI);
00050       }
00051     }
00052 
00053     virtual void jiggle(float var, particle_type* begin, index_t num) {
00054       if(var==0)
00055   return;
00056       particle_type* end=&begin[num]; 
00057       while(begin!=end) {
00058   float dx=0, dy=0;
00059   for (int i=0; i<4; i++) {
00060     float rx = (float)DRanNormalZig32()*LocalizationParticleDistributionPolicy<ParticleT>::positionVariance*var;
00061     float ry = (float)DRanNormalZig32()*LocalizationParticleDistributionPolicy<ParticleT>::positionVariance*var;
00062     if ( !worldBounds.isValid() || worldBounds->isInside(Point(begin->x+rx, begin->y+ry)) ) {
00063       dx = rx;
00064       dy = ry;
00065       break;
00066     }
00067   }
00068   begin->x += dx;
00069   begin->y += dy;
00070   begin->theta+=(float)DRanNormalZig32()*LocalizationParticleDistributionPolicy<ParticleT>::orientationVariance*var;
00071   ++begin;
00072       }
00073     }
00074 
00075     virtual void setWorldBounds(const Shape<PolygonData> bounds) {
00076       worldBounds = bounds;
00077       if ( worldBounds.isValid() ) {
00078   BoundingBox2D b(worldBounds->getBoundingBox());
00079   LocalizationParticleDistributionPolicy<ParticleT>::mapMinX = b.min[0];
00080   LocalizationParticleDistributionPolicy<ParticleT>::mapWidth = b.getDimension(0);
00081   LocalizationParticleDistributionPolicy<ParticleT>::mapMinY = b.min[1];
00082   LocalizationParticleDistributionPolicy<ParticleT>::mapHeight = b.getDimension(1);
00083       }
00084     }
00085 
00086   protected:
00087     Shape<PolygonData> worldBounds; //!< If valid shape, particles must lie inside it.
00088   };
00089 
00090   //================ ShapeBasedParticleFilter ================
00091 
00092   //! Bundles a motion model (DeadReckoningBehavior or CreateMotionModel) and a ShapeSensorModel for easy use of a shape-based particle filter for localization
00093 
00094   class ShapeBasedParticleFilter : public ParticleFilter<LocalizationParticle> {
00095   public:
00096     //! constructor, must pass local and world shape spaces, which will be used in future calls to update()
00097 #ifdef TGT_IS_CREATE
00098     ShapeBasedParticleFilter(ShapeSpace &camShS, ShapeSpace &localShS, ShapeSpace &worldShS, unsigned int numParticles=2000)
00099       : ParticleFilter<LocalizationParticle>(numParticles, new CreateMotionModel<LocalizationParticle>),
00100   sensorModel(new ShapeSensorModel<LocalizationParticle>(camShS,localShS,worldShS))
00101     {
00102       // std::cout<<"ShapeBasedParticleFilter using CreateMotionModel\n";
00103       getResamplingPolicy()->setDistributionPolicy(new ShapeParticleDistributionPolicy<LocalizationParticle>);
00104       if(BehaviorBase* motBeh = dynamic_cast<BehaviorBase*>(motion))
00105   motBeh->start();
00106     }
00107 #else
00108     ShapeBasedParticleFilter(ShapeSpace &camShS, ShapeSpace &localShS, ShapeSpace &worldShS, unsigned int numParticles=2000)
00109       : ParticleFilter<LocalizationParticle>(numParticles, new DeadReckoningBehavior<LocalizationParticle>),
00110   sensorModel(new ShapeSensorModel<LocalizationParticle>(camShS,localShS,worldShS))
00111     {
00112       // std::cout<<"ShapeBasedParticleFilter using DeadReckoningBehavior\n";
00113       getResamplingPolicy()->setDistributionPolicy(new ShapeParticleDistributionPolicy<LocalizationParticle>);
00114       if(BehaviorBase* motBeh = dynamic_cast<BehaviorBase*>(motion))
00115   motBeh->start();
00116     }
00117 #endif
00118   
00119 
00120     //! destructor
00121     virtual ~ShapeBasedParticleFilter() { 
00122       if(BehaviorBase* motBeh = dynamic_cast<BehaviorBase*>(motion)) {
00123   motBeh->stop();
00124   // behaviors are reference counted, stopping removes our reference, set to NULL to avoid call to delete in ParticleFilter
00125   motion=NULL;
00126       }
00127       delete sensorModel;
00128     }
00129   
00130     virtual void updateFromLocal() {
00131       getSensorModel().updateFromLocal(particles, estimate);
00132     }
00133   
00134     virtual void updateFromCamera() {
00135       getSensorModel().updateFromCamera(particles, estimate);
00136     }
00137   
00138     //! accessor for #sensorModel
00139     virtual ShapeSensorModel<LocalizationParticle>& getSensorModel() const { return *sensorModel; }
00140 
00141     //! replaces the sensor model in use, the particle filter will take responsibility for deallocating the sensor model's memory when destructed or replaced
00142     virtual void setSensorModel(ShapeSensorModel<LocalizationParticle>* customSensorModel) {
00143       delete sensorModel; 
00144       sensorModel=customSensorModel;
00145     }
00146 
00147     using ParticleFilter<LocalizationParticle>::resetFilter;
00148 
00149     //! randomizes all the particles
00150     virtual void resetFilter();
00151   
00152     //! Adjusts the size of the particle collection -- more particles gives better coverage, but more computation
00153     /*! You may wish to shrink the number of particles when the confidence interval is small or
00154      *  particle weights are high, and increase particles when the filter is getting "lost". */
00155     virtual void resizeParticles(unsigned int numParticles);
00156 
00157     //! Synchs the estimate to the agent's current position and heading in worldShS. During odometry, the Pilot will use the estimate to update the agent's position. 
00158     virtual void synchEstimateToAgent();
00159   
00160     //! Resets particles to the specified position and orientation, and optionally jiggles them by variance
00161     virtual void setPosition(float const x, float const y, AngTwoPi const orientation, float variance=0);
00162     using ParticleFilter<LocalizationParticle>::setPosition;
00163 
00164     //! Computes the weighted variance in the position and heading estimates of the particle collection.
00165     virtual void computeVariance();
00166 
00167     //! Sets boundary within which particles should lie
00168     virtual void setWorldBounds(const Shape<PolygonData> &bounds);
00169 
00170     //! Deletes particle shapes and "particle" GraphicsData object so we can prepare a new display
00171     static void deleteParticleDisplay(ShapeSpace &wShS);
00172 
00173     //! Displays particles on the world map using a GraphicsData shape; howmany can either be a percentage (<= 1.0) or a whole number
00174     virtual void displayParticles(float const howmany=100);
00175 
00176     //! Displays individual particles on the world map using LocalizationParticle shapes; howmany can either be a percentage (<= 1.0) or a whole number
00177     virtual void displayIndividualParticles(float const howmany=100);
00178 
00179   protected:
00180     ShapeSensorModel<LocalizationParticle> * sensorModel; //!< provides evaluation of particles
00181   
00182   private:
00183     ShapeBasedParticleFilter(const ShapeBasedParticleFilter&); //!< don't call (copy constructor)
00184     ShapeBasedParticleFilter& operator=(const ShapeBasedParticleFilter&); //!< don't call (assignment operator)
00185   }; 
00186 
00187 } // namespace
00188 
00189 #endif

Tekkotsu v5.1CVS
Generated Fri Mar 16 05:26:51 2012 by Doxygen 1.6.3