Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ShapeSensorModel.h

Go to the documentation of this file.
00001 #ifndef _ShapeSensorModel_h_
00002 #define _ShapeSensorModel_h_
00003 
00004 #include "LocalizationParticle.h"
00005 
00006 class PfRoot;
00007 class PfLine;
00008 
00009 namespace DualCoding {
00010   class ShapeSpace;
00011 }
00012 
00013 // Contents:  LocalShapeEvaluator, CameraShapeEvaluator, and
00014 //   ShapeSensorModel (child of ParticleFilter<ParticleT>::SensorModel)
00015 
00016 //! Provides evaluation of the match between local or camera and world given a candidate particle
00017 /*! The reason for separating LocalShapeEvaluator and ShapeSensorModel?  Partly so the
00018  *  fairly lengthy evaluation code can go in the .cc file to avoid repeated recompilation, but also to
00019  *  allow inheritance (e.g. ShapeSLAMParticleEvaluator) as a clean way to extend the 
00020  *  evaluation code for particle sub-types. */
00021 class LocalShapeEvaluator {
00022 public:
00023   //! constructor, pass the local and world shape spaces, these will be used to initialize the appropriate particle-independent fields of the class
00024   LocalShapeEvaluator(DualCoding::ShapeSpace &localShS, DualCoding::ShapeSpace &worldShS);
00025   virtual ~LocalShapeEvaluator() {} //!< destructor
00026     
00027   //! the heart of the class, call with a particle, will adjust the weight
00028   void evaluate(LocalizationParticle& part);
00029 
00030   //! the real work is done here; shared with SLAM version
00031   void evaluateWorkhorse (LocalizationParticle& p, const unsigned int nLocals,
00032         float particleViewX[], float particleViewY[], float particleViewX2[], float ParticleViewY2[],
00033         int localMatches[], float localScores[]);
00034 
00035   //! update the particle weight after computing local match scores (and possibly additions/deletions if SLAM)
00036   void updateWeight(LocalizationParticle &p, int const localMatches[], float const localScores[]);
00037     
00038   std::vector<PfRoot*> localLms; //!< a vector of the landmarks in the local space
00039   std::vector<PfRoot*> worldLms; //!< a vector of landmarks in the world space
00040     
00041   static float const maxDist;  //!< maximum distance for a landmark to be useful in distance error calculation;  value should be < 1e10
00042   static float const stdevSq;  //!< controls how much weight is given to "near-misses"
00043     
00044   //! helper function which calculates the distance between a point and a line along a perpendicular
00045   static float distanceFromLine(coordinate_t x0, coordinate_t y0, PfLine &wline);
00046   
00047   //!< computes a (non-normalized) gaussian distribution
00048   /*! normalization isn't needed because the scale factor is constant across particles, and so
00049    *  doesn't matter for purposes of comparison between particles */
00050   inline float normpdf(float const distsq) { return std::exp(-distsq/stdevSq); }
00051 };
00052   
00053 class CameraShapeEvaluator {
00054 public:
00055   //! constructor, pass the camera and world shape spaces, these will be used to initialize the appropriate particle-independent fields of the class
00056   CameraShapeEvaluator(DualCoding::ShapeSpace &camShS, DualCoding::ShapeSpace &worldShS):
00057     pRandom(0.2f), alpha(1), xvar(3000), yvar(1000), cShS(camShS), wShS(worldShS)
00058   {}
00059     
00060   virtual ~CameraShapeEvaluator(){}
00061     
00062   // compute the likelihood of a given sensor reading
00063   virtual void computeLikelihood(LocalizationParticle& particle);
00064     
00065   float pRandom;                        //!< Probability sensor reading is random noise
00066   float alpha;                          //!< Attentuate weight of each individual marker match
00067     
00068   float xvar;                           //!< variance of sensor reading in x direction (image)
00069   float yvar;                           //!< variance of sensor reading in y direction (image)
00070   DualCoding::ShapeSpace &cShS;     //!< Camera shape space
00071   DualCoding::ShapeSpace &wShS;     //!< World shape space
00072 
00073   //!< computes a (non-normalized) gaussian distribution
00074   /*! normalization isn't needed because the scale factor is constant across particles, and so
00075    *  doesn't matter for purposes of comparison between particles */
00076   inline float normpdf(float const dist, float variance) { return std::exp(-dist*dist/variance); }
00077 };
00078 
00079 //================ ShapeSensorModel ================
00080 //! this wraps the ParticleShapeEvaluator in a ParticleFilter::SensorModel so it can be used by the particle filter
00081 /*! The reason for separating ParticleShapeEvaluator and ShapeSensorModel?  Partly so the
00082  *  fairly length evaluation code can go in the .cc file to avoid repeated recompilation, but also to
00083  *  allow inheritance (e.g. SLAMShapesParticleEvaluator) as a clean way to extend the 
00084  *  evaluation code for particle sub-types.  Ideally, I'd like to combine these classes. */
00085 
00086 template<typename ParticleT>
00087 class ShapeSensorModel : public ParticleFilter<ParticleT>::SensorModel {
00088 public:
00089   typedef typename ParticleFilter<ParticleT>::SensorModel::index_t index_t; //!< convenience typedef
00090   typedef typename ParticleFilter<ParticleT>::SensorModel::particle_collection particle_collection; //!< convenience typedef
00091   typedef typename ParticleFilter<ParticleT>::SensorModel::particle_type particle_type; //!< convenience typedef
00092   
00093   //! constructor, the standard deviation on matches defaults to 60, but you can always reassign #stdevSq directly
00094   ShapeSensorModel(DualCoding::ShapeSpace &camShS, DualCoding::ShapeSpace &localShS, DualCoding::ShapeSpace &worldShS) :
00095     cShS(camShS), lShS(localShS), wShS(worldShS)
00096   {}
00097   
00098   //! Applies the ParticleShapeEvaluator across a collection of particles
00099   virtual void evaluate(particle_collection& particles, particle_type &estimate) {
00100     // We could handle some shapes in camera space and others in local space, but for now we'll handle everything in local space.
00101     updateFromLocal(particles, estimate);
00102   }
00103   
00104   virtual void updateFromLocal(particle_collection& particles, particle_type &estimate) {
00105     LocalShapeEvaluator localEval(lShS,wShS);
00106     float bestWeight = -FLT_MAX;
00107     typename particle_collection::size_type bestIndex = 0;
00108     double tx=0, ty=0, tcos=0, tsin=0;
00109     double totalWeight = 0;
00110     for(typename particle_collection::size_type p=0; p<particles.size(); ++p) {
00111       localEval.evaluate(particles[p]);
00112       if (particles[p].weight > bestWeight) {
00113         bestWeight = particles[p].weight;
00114         bestIndex = p;
00115       }
00116       double w = exp((double)particles[p].weight);
00117       totalWeight += w;
00118       tx += particles[p].x * w;
00119       ty += particles[p].y * w;
00120       tcos += cos(particles[p].theta) * w;
00121       tsin += sin(particles[p].theta) * w;
00122     }
00123     if ( totalWeight > 1e-200 ) {
00124       estimate.x = tx / totalWeight;
00125       estimate.y = ty / totalWeight;
00126       estimate.theta = atan2(tsin/totalWeight, tcos/totalWeight);
00127     } else { // avoid divide-by-zero error: can't use totalWeight
00128       estimate.x = particles[bestIndex].x;
00129       estimate.y = particles[bestIndex].y;
00130       estimate.theta = particles[bestIndex].theta;
00131     }
00132     estimate.weight = bestWeight;
00133   }
00134 
00135   virtual void updateFromCamera(particle_collection& particles, particle_type& estimate) {
00136     CameraShapeEvaluator cameraEval(cShS,wShS);
00137     for(typename particle_collection::size_type p=0; p<particles.size(); ++p) {
00138       // resample should already do this....
00139       // but it doesn't seem to work
00140       //      particles[p].weight = 0;
00141       
00142       // evaluate weight for particle p
00143       cameraEval.computeLikelihood(particles[p]);
00144     }
00145   }
00146   
00147   DualCoding::ShapeSpace& getcamShS() const { return lShS; }
00148   DualCoding::ShapeSpace& getLocalShS() const { return lShS; }
00149   DualCoding::ShapeSpace& getWorldShS() const { return wShS; }
00150   
00151 protected:
00152   DualCoding::ShapeSpace &cShS;     //!< Camera shape space
00153   DualCoding::ShapeSpace &lShS;     //!< Local shape space
00154   DualCoding::ShapeSpace &wShS;     //!< World shape space
00155 };
00156 
00157 #endif

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