Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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_;
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
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 }
00419 }
00420
00421 #endif // MCL_3DL_PF_H