pf.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2016-2017, the mcl_3dl authors
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the copyright holder nor the names of its 
00014  *       contributors may be used to endorse or promote products derived from 
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #ifndef MCL_3DL_PF_H
00031 #define MCL_3DL_PF_H
00032 
00033 #include <random>
00034 #include <vector>
00035 #include <algorithm>
00036 #include <functional>
00037 #include <cmath>
00038 
00039 namespace mcl_3dl
00040 {
00041 namespace pf
00042 {
00043 template <typename FLT_TYPE = float>
00044 class ParticleBase
00045 {
00046 public:
00047   virtual FLT_TYPE& operator[](const size_t i) = 0;
00048   virtual size_t size() const = 0;
00049   virtual void normalize() = 0;
00050   template <typename T>
00051   T operator+(const T& a)
00052   {
00053     T in = a;
00054     T ret;
00055     for (size_t i = 0; i < size(); i++)
00056     {
00057       ret[i] = (*this)[i] + in[i];
00058     }
00059     return ret;
00060   }
00061   template <typename T>
00062   FLT_TYPE covElement(
00063       const T& e, const size_t& j, const size_t& k)
00064   {
00065     T exp = e;
00066     return ((*this)[k] - exp[k]) * ((*this)[j] - exp[j]);
00067   }
00068   template <typename T>
00069   static T generateNoise(
00070       std::default_random_engine& engine_,
00071       T mean, T sigma)
00072   {
00073     T noise;
00074     for (size_t i = 0; i < noise.size(); i++)
00075     {
00076       std::normal_distribution<FLT_TYPE> nd(mean[i], sigma[i]);
00077       noise[i] = nd(engine_);
00078     }
00079     return noise;
00080   }
00081 
00082 protected:
00083 };
00084 
00085 template <typename T, typename FLT_TYPE = float>
00086 class Particle
00087 {
00088 public:
00089   Particle()
00090   {
00091     probability_ = 0.0;
00092     probability_bias_ = 0.0;
00093   }
00094   explicit Particle(FLT_TYPE prob)
00095   {
00096     accum_probability_ = prob;
00097   }
00098   T state_;
00099   FLT_TYPE probability_;
00100   FLT_TYPE probability_bias_;
00101   FLT_TYPE accum_probability_;
00102   bool operator<(const Particle& p2) const
00103   {
00104     return this->accum_probability_ < p2.accum_probability_;
00105   }
00106 };
00107 
00108 template <typename T, typename FLT_TYPE = float>
00109 class ParticleWeightedMean
00110 {
00111 protected:
00112   T e_;
00113   FLT_TYPE p_sum_;
00114 
00115 public:
00116   ParticleWeightedMean()
00117     : e_()
00118     , p_sum_(0.0)
00119   {
00120   }
00121 
00122   void add(const T& s, const FLT_TYPE& prob)
00123   {
00124     p_sum_ += prob;
00125 
00126     T e1 = s;
00127     for (size_t i = 0; i < e1.size(); i++)
00128     {
00129       e1[i] = e1[i] * prob;
00130     }
00131     e_ = e1 + e_;
00132   }
00133 
00134   T getMean()
00135   {
00136     assert(p_sum_ > 0.0);
00137 
00138     T s = e_;
00139 
00140     for (size_t i = 0; i < s.size(); i++)
00141     {
00142       s[i] = s[i] / p_sum_;
00143     }
00144 
00145     return s;
00146   }
00147 
00148   FLT_TYPE getTotalProbability()
00149   {
00150     return p_sum_;
00151   }
00152 };
00153 
00154 template <typename T, typename FLT_TYPE = float, typename MEAN = ParticleWeightedMean<T, FLT_TYPE>>
00155 class ParticleFilter
00156 {
00157 public:
00158   explicit ParticleFilter(const int nParticles)
00159     : engine_(seed_gen_())
00160   {
00161     particles_.resize(nParticles);
00162   }
00163   void init(T mean, T sigma)
00164   {
00165     for (auto& p : particles_)
00166     {
00167       p.state_ = T::generateNoise(engine_, mean, sigma);
00168       p.probability_ = 1.0 / particles_.size();
00169     }
00170   }
00171   void resample(T sigma)
00172   {
00173     FLT_TYPE accum = 0;
00174     for (auto& p : particles_)
00175     {
00176       accum += p.probability_;
00177       p.accum_probability_ = accum;
00178     }
00179 
00180     particles_dup_ = particles_;
00181     std::sort(particles_dup_.begin(), particles_dup_.end());
00182 
00183     const FLT_TYPE pstep = accum / (particles_.size() - 1);
00184     FLT_TYPE pscan = 0;
00185     auto it = particles_dup_.begin();
00186     auto it_prev = particles_dup_.begin();
00187 
00188     const FLT_TYPE prob = 1.0 / particles_.size();
00189     for (auto& p : particles_)
00190     {
00191       it = std::lower_bound(it, particles_dup_.end(), Particle<T, FLT_TYPE>(pscan));
00192       pscan += pstep;
00193       p.probability_ = prob;
00194       if (it == particles_dup_.end())
00195       {
00196         p.state_ = it_prev->state_;
00197         continue;
00198       }
00199       else if (it == it_prev)
00200       {
00201         p.state_ = it->state_ + T::generateNoise(engine_, T(), sigma);
00202         p.state_.normalize();
00203       }
00204       else
00205       {
00206         p.state_ = it->state_;
00207       }
00208       it_prev = it;
00209     }
00210   }
00211   void noise(T sigma)
00212   {
00213     for (auto& p : particles_)
00214     {
00215       p.state_ = p.state_ + T::generateNoise(engine_, T(), sigma);
00216     }
00217   }
00218   void predict(std::function<void(T&)> model)
00219   {
00220     for (auto& p : particles_)
00221     {
00222       model(p.state_);
00223     }
00224   }
00225   void bias(std::function<void(const T&, float& p_bias)> prob)
00226   {
00227     for (auto& p : particles_)
00228     {
00229       prob(p.state_, p.probability_bias_);
00230     }
00231   }
00232   void measure(std::function<FLT_TYPE(const T&)> likelihood)
00233   {
00234     auto particles_prev = particles_;  // backup old
00235     FLT_TYPE sum = 0;
00236     for (auto& p : particles_)
00237     {
00238       p.probability_ *= likelihood(p.state_);
00239       sum += p.probability_;
00240     }
00241     if (sum > 0.0)
00242     {
00243       for (auto& p : particles_)
00244       {
00245         p.probability_ /= sum;
00246       }
00247     }
00248     else
00249     {
00250       particles_ = particles_prev;
00251       // std::cerr << "No Particle alive, restoring." << std::endl;
00252     }
00253   }
00254   T expectation(const FLT_TYPE pass_ratio = 1.0)
00255   {
00256     MEAN mean;
00257 
00258     if (pass_ratio < 1.0)
00259       std::sort(particles_.rbegin(), particles_.rend());
00260     for (auto& p : particles_)
00261     {
00262       mean.add(p.state_, p.probability_);
00263       if (mean.getTotalProbability() > pass_ratio)
00264         break;
00265     }
00266     return mean.getMean();
00267   }
00268   T expectationBiased()
00269   {
00270     MEAN mean;
00271 
00272     for (auto& p : particles_)
00273     {
00274       mean.add(p.state_, p.probability_ * p.probability_bias_);
00275     }
00276     return mean.getMean();
00277   }
00278   std::vector<T> covariance(const FLT_TYPE pass_ratio = 1.0)
00279   {
00280     T e = expectation(pass_ratio);
00281     FLT_TYPE p_sum = 0;
00282     size_t p_num = 0;
00283     std::vector<T> cov;
00284     cov.resize(e.size());
00285 
00286     for (auto& p : particles_)
00287     {
00288       p_num++;
00289       p_sum += p.probability_;
00290       if (p_sum > pass_ratio)
00291         break;
00292     }
00293     p_sum = 0;
00294     for (auto& p : particles_)
00295     {
00296       for (size_t j = 0; j < ie_.size(); j++)
00297       {
00298         for (size_t k = j; k < ie_.size(); k++)
00299         {
00300           cov[k][j] = cov[j][k] += p.state_.covElement(e, j, k) * p.probability_;
00301         }
00302       }
00303 
00304       p_sum += p.probability_;
00305       if (p_sum > pass_ratio)
00306         break;
00307     }
00308     for (size_t j = 0; j < ie_.size(); j++)
00309     {
00310       for (size_t k = j; k < ie_.size(); k++)
00311       {
00312         cov[k][j] /= p_sum;
00313         cov[j][k] /= p_sum;
00314       }
00315     }
00316 
00317     return cov;
00318   }
00319   T max()
00320   {
00321     T* m = &particles_[0].state_;
00322     FLT_TYPE max_probability = particles_[0].probability_;
00323     for (auto& p : particles_)
00324     {
00325       if (max_probability < p.probability_)
00326       {
00327         max_probability = p.probability_;
00328         m = &p.state_;
00329       }
00330     }
00331     return *m;
00332   }
00333   T maxBiased()
00334   {
00335     T* m = &particles_[0].state_;
00336     FLT_TYPE max_probability =
00337         particles_[0].probability_ * particles_[0].probability_bias_;
00338     for (auto& p : particles_)
00339     {
00340       const FLT_TYPE prob = p.probability_ * p.probability_bias_;
00341       if (max_probability < prob)
00342       {
00343         max_probability = prob;
00344         m = &p.state_;
00345       }
00346     }
00347     return *m;
00348   }
00349   T getParticle(const size_t i) const
00350   {
00351     return particles_[i].state_;
00352   }
00353   size_t getParticleSize() const
00354   {
00355     return particles_.size();
00356   }
00357   void resizeParticle(const size_t num)
00358   {
00359     FLT_TYPE accum = 0;
00360     for (auto& p : particles_)
00361     {
00362       accum += p.probability_;
00363       p.accum_probability_ = accum;
00364     }
00365 
00366     particles_dup_ = particles_;
00367     std::sort(particles_dup_.begin(), particles_dup_.end());
00368 
00369     FLT_TYPE pstep = accum / num;
00370     FLT_TYPE pscan = 0;
00371     auto it = particles_dup_.begin();
00372     auto it_prev = particles_dup_.begin();
00373 
00374     particles_.resize(num);
00375 
00376     FLT_TYPE prob = 1.0 / num;
00377     for (auto& p : particles_)
00378     {
00379       pscan += pstep;
00380       it = std::lower_bound(it, particles_dup_.end(),
00381                             Particle<T, FLT_TYPE>(pscan));
00382       p.probability_ = prob;
00383       if (it == particles_dup_.end())
00384       {
00385         p.state_ = it_prev->state_;
00386         continue;
00387       }
00388       else
00389       {
00390         p.state_ = it->state_;
00391       }
00392       it_prev = it;
00393     }
00394   }
00395   typename std::vector<Particle<T, FLT_TYPE>>::iterator appendParticle(const size_t num)
00396   {
00397     const size_t size_orig = particles_.size();
00398     particles_.resize(size_orig + num);
00399     return begin() + size_orig;
00400   }
00401   typename std::vector<Particle<T, FLT_TYPE>>::iterator begin()
00402   {
00403     return particles_.begin();
00404   }
00405   typename std::vector<Particle<T, FLT_TYPE>>::iterator end()
00406   {
00407     return particles_.end();
00408   }
00409 
00410 protected:
00411   std::vector<Particle<T, FLT_TYPE>> particles_;
00412   std::vector<Particle<T, FLT_TYPE>> particles_dup_;
00413   std::random_device seed_gen_;
00414   std::default_random_engine engine_;
00415   T ie_;
00416 };
00417 
00418 }  // namespace pf
00419 }  // namespace mcl_3dl
00420 
00421 #endif  // MCL_3DL_PF_H


mcl_3dl
Author(s): Atsushi Watanabe
autogenerated on Thu Jun 20 2019 20:04:43