particle_filter.h
Go to the documentation of this file.
1 #ifndef SLAM_CTOR_PARTICLE_FILTER_H_INCLUDED
2 #define SLAM_CTOR_PARTICLE_FILTER_H_INCLUDED
3 
4 #include <memory>
5 #include <vector>
6 #include <random>
7 #include <unordered_set>
8 
9 /* An element of ParticleFilter. Used to approximate target distribution */
10 class Particle {
11 public:
12  Particle(): _weight(1.0) {}
13  virtual ~Particle() = default;
14 
15  double weight() const { return _weight; }
16  void set_weight(double w) { _weight = w; }
17 
18  virtual void sample() {}
19 private:
20  double _weight;
21 };
22 
23 template <typename ParticleT>
25 public:
26  virtual std::shared_ptr<ParticleT> create_particle() = 0;
27  virtual ~ParticleFactory() = default;
28 };
29 
30 template <typename ParticlePtr>
31 class UniformResamling { /* Strategy */
32 public:
33  // TODO: should be moved to separate strategy
34  bool resampling_is_required(std::vector<ParticlePtr> particles) {
35  // TODO: resampling is not required if robot haven't traveled far enough
36  // Computer N_eff from gMapping (based on Doucet work)
37  double sq_sum = 0;
38  for (auto &p : particles) {
39  sq_sum += p->weight() * p->weight();
40  }
41  double effective_particles_cnt = 1.0 / sq_sum;
42  return effective_particles_cnt * 2 < particles.size();
43  }
44 
45  std::vector<unsigned> resample(std::vector<ParticlePtr> particles) {
46  // TODO: implement O(n) resampling from gmapping
47  //double total_weight = 0;
48  //for (auto &p : particles) { total_weight += particles.weight; }
49  std::vector<unsigned> new_particle_inds(particles.size());
50 
51  std::random_device rd;
52  std::mt19937 engine(rd());
53  std::uniform_real_distribution<> uniform_distr(0, 1);
54  for (uint i = 0; i < particles.size(); i++) {
55  double sample = uniform_distr(engine);
56  double total_w = 0;
57  for (uint j = 0; j < particles.size(); j++) {
58  total_w += particles[j]->weight();
59  if (sample < total_w) {
60  new_particle_inds[i] = j;
61  break;
62  }
63  }
64  }
65  return new_particle_inds;
66  }
67 };
68 
69 template <typename ParticleT>
71 private:
72  using ParticlePtr = std::shared_ptr<ParticleT>;
73 public: // methods
74  ParticleFilter(std::shared_ptr<ParticleFactory<ParticleT>> p_ftry,
75  unsigned n = 1) : _particle_supplier{p_ftry} {
76  for (unsigned i = 0; i < n; i++) {
77  ParticlePtr particle = p_ftry->create_particle();
78  particle->set_weight(1.0 / n);
79  _particles.push_back(particle);
80  }
81  }
82 
83  bool try_resample() {
84  // TODO: heuristic with traveled distange, move to common sample_particles
85  if (!_resampler.resampling_is_required(_particles)) {
86  return false;
87  }
88 
89  std::vector<ParticlePtr> new_particles;
90  std::unordered_set<unsigned> new_part_inds;
91  for (unsigned i : _resampler.resample(_particles)) {
92  ParticlePtr sampled = _particles[i];
93  if (new_part_inds.count(i)) {
94  ParticlePtr new_particle = _particle_supplier->create_particle();
95  *new_particle = *sampled;
96  new_particle->sample();
97  sampled = new_particle;
98  } else {
99  new_part_inds.insert(i);
100  }
101  new_particles.push_back(sampled);
102  }
103  _particles = std::move(new_particles);
104  normalize_weights();
105  return true;
106  }
107 
109  double total_weight = 0;
110  for (auto &p : _particles) { total_weight += p->weight(); }
111  for (auto &p : _particles) { p->set_weight(p->weight() / total_weight); }
112  }
113 
114  const ParticleT& heaviest_particle() const {
115  const ParticleT *heaviest = nullptr;
116  for (auto &p : particles()) {
117  if (heaviest && p->weight() < heaviest->weight()) { continue; }
118  heaviest = p.get();
119  }
120  return *heaviest;
121  }
122 
123  ParticleT& heaviest_particle() {
124  return const_cast<ParticleT&>(
125  static_cast<const ParticleFilter<ParticleT>>(*this).heaviest_particle());
126  }
127 
128  inline std::vector<ParticlePtr>& particles() { return _particles; }
129  inline const std::vector<ParticlePtr>& particles() const {
130  return _particles;
131  }
132 
133 private:
134  std::shared_ptr<ParticleFactory<ParticleT>> _particle_supplier;
135  std::vector<ParticlePtr> _particles;
136  /* TODO: make template parameter/set at runtime */
138 };
139 
140 #endif // header-guard
std::vector< unsigned > resample(std::vector< ParticlePtr > particles)
std::shared_ptr< GmappingWorld > ParticlePtr
std::vector< ParticlePtr > & particles()
const std::vector< ParticlePtr > & particles() const
ParticleFilter(std::shared_ptr< ParticleFactory< ParticleT >> p_ftry, unsigned n=1)
void normalize_weights()
const ParticleT & heaviest_particle() const
bool resampling_is_required(std::vector< ParticlePtr > particles)
UniformResamling< ParticlePtr > _resampler
std::shared_ptr< ParticleFactory< ParticleT > > _particle_supplier
std::vector< ParticlePtr > _particles
void set_weight(double w)
virtual ~Particle()=default
ParticleT & heaviest_particle()
double weight() const
double _weight
virtual void sample()


slam_constructor
Author(s): JetBrains Research, OSLL team
autogenerated on Mon Jun 10 2019 15:08:25