Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CreateMotionModel.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef _CreateMotionModel_h_
00003 #define _CreateMotionModel_h_
00004 
00005 #include "Shared/RobotInfo.h"
00006 
00007 #if defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00008 
00009 #include "Behaviors/BehaviorBase.h"
00010 #include "DualCoding/VRmixin.h"
00011 #include "Shared/zignor.h"
00012 #include "Shared/Measures.h"
00013 #include "Shared/ParticleFilter.h"
00014 #include "Shared/WorldState.h"
00015 #include "Vision/VisualOdometry/VisualOdometry.h"
00016 
00017 
00018 //! Holds particle-independent odometry code so we can avoid templating and just recompile the cc file
00019 class CreateOdometry {
00020 private:
00021   float lastdist;
00022   AngTwoPi lastang;
00023   AngTwoPi lastOdoAng;
00024 
00025 public:
00026   CreateOdometry() :
00027     lastdist(state->sensors[EncoderDistanceOffset]),
00028     lastang(state->sensors[EncoderAngleOffset]/180.0*(float)M_PI),
00029     lastOdoAng(0) {}
00030 
00031   virtual ~CreateOdometry() {}
00032 
00033   //! Calculate translation and rotation using both Create hardware odometry and visual odometry
00034   void getCreateOdometry(float &dd, AngSignPi &da);
00035 
00036   //! Compute distance update for a given linear distance and angular distance traveled
00037   virtual void computeCreateMotion(float len, float omega, float theta, float &dx, float &dy, float &dtheta);
00038 
00039   static constexpr float minUpdateDistance = 5.0f;
00040   static constexpr float minUpdateAngle = 0.05f;
00041 };
00042 
00043 template<class ParticleT>
00044 class CreateMotionModel : public BehaviorBase, public ParticleFilter<ParticleT>::MotionModel, public CreateOdometry {
00045 private:
00046   /* mean and variance for added gaussian noise */
00047   float dmean;
00048   AngTwoPi amean;
00049   float ddvar, davar, aavar, advar;
00050 
00051 public:
00052   typedef typename ParticleFilter<ParticleT>::MotionModel::particle_type particle_type;
00053   typedef typename ParticleFilter<ParticleT>::MotionModel::particle_collection particle_collection;
00054   typedef typename particle_collection::size_type index_t;
00055 
00056   //! Constructor
00057   CreateMotionModel(float dm=0.1f, float am=0.2f, float ddv=0.001f, float dav=0.001f, float aav=0.001f, float adv=0.000001f) :
00058     BehaviorBase("CreateMotionModel"), ParticleFilter<ParticleT>::MotionModel(), CreateOdometry(),
00059     dmean(dm), amean(am), ddvar(ddv), davar(dav), aavar(aav), advar(adv)
00060     {}
00061 
00062   float sampleNormal(float mean, float var) {
00063     // N(m,s^2) ~ s*N(0,1) + m
00064     return mean + (float)DRanNormalZig32()*std::sqrt(var);
00065   }
00066 
00067   virtual void updateMotion(particle_collection& particles, particle_type& estimate) {
00068     float dd;
00069     AngSignPi da;
00070     getCreateOdometry(dd,da);
00071 
00072     // If we haven't moved much, don't bother updating the particles
00073     if (fabs(dd) < minUpdateDistance && fabs(da) < minUpdateAngle)
00074       return;
00075 
00076     // First update the estimate, using zero noise
00077     float dx, dy, dtheta;
00078     computeCreateMotion(dd, float(da), estimate.theta, dx, dy, dtheta);
00079     estimate.x += dx;
00080     estimate.y += dy;
00081     estimate.theta += dtheta;
00082 
00083     // Now  update the particles using our noise model
00084     for(typename particle_collection::iterator it=particles.begin(); it!=particles.end(); ++it) {
00085       // noise perturbed distance and angle travelled
00086       // Note: original code was:
00087       //
00088       //    float dnoise = sampleNormal(dmean*dd, ddvar*dd*dd + davar*da*da);
00089       //    float anoise = sampleNormal(amean*da, aavar*da*da + advar*dd*dd);
00090       //
00091       // but with current parameters, this caused a 10% distance
00092       // overshoot, while the actual robot seems to show a 3%
00093       // undershoot.  Also, for long turns (90 degrees) the angular
00094       // error was way too high.  So the version below gives zero mean
00095       // translational error; might replace this later with original
00096       // code plus better parameter settings.  Our trick doesn't work
00097       // for the angular component because if we don't command a turn,
00098       // the Create will always report 0 angular change so scaling by
00099       // da would zero the noise entirely.
00100 
00101       float dnoise, anoise;
00102       dnoise = dmean * dd * sampleNormal(0, ddvar*dd*dd + davar*da*da);
00103       anoise = float(amean) * sampleNormal(0, aavar*da*da + advar*dd*dd);
00104       float ddn = dd + dnoise;
00105       AngSignPi dan = float(da) + anoise;
00106       computeCreateMotion(ddn, float(dan), float(it->theta), dx, dy, dtheta);
00107       it->x += dx;
00108       it->y += dy;
00109       it->theta += dtheta;
00110     }
00111   }
00112 
00113 };
00114 
00115 #endif
00116 
00117 #endif
00118 

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