MRPT  2.0.4
CParticleFilterData.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
13 #include <mrpt/core/bits_math.h>
14 #include <mrpt/core/exceptions.h>
15 
16 #include <algorithm>
17 #include <cmath>
18 #include <deque>
19 
20 namespace mrpt::bayes
21 {
22 class CParticleFilterCapable;
23 
24 /** A curiously recurring template pattern (CRTP) approach to providing the
25  * basic functionality of any CParticleFilterData<> class.
26  * Users should inherit from CParticleFilterData<>, which in turn will
27  * automatically inhirit from this base class.
28  * \sa CParticleFilter, CParticleFilterCapable, CParticleFilterData
29  * \ingroup mrpt_bayes_grp
30  */
31 template <class Derived, class particle_list_t>
33 {
34  /// CRTP helper method
35  inline const Derived& derived() const
36  {
37  return *dynamic_cast<const Derived*>(this);
38  }
39  /// CRTP helper method
40  inline Derived& derived() { return *dynamic_cast<Derived*>(this); }
41  double getW(size_t i) const override
42  {
43  if (i >= derived().m_particles.size())
44  THROW_EXCEPTION_FMT("Index %i is out of range!", (int)i);
45  return derived().m_particles[i].log_w;
46  }
47 
48  void setW(size_t i, double w) override
49  {
50  if (i >= derived().m_particles.size())
51  THROW_EXCEPTION_FMT("Index %i is out of range!", (int)i);
52  derived().m_particles[i].log_w = w;
53  }
54 
55  size_t particlesCount() const override
56  {
57  return derived().m_particles.size();
58  }
59 
60  double normalizeWeights(double* out_max_log_w = nullptr) override
61  {
63  if (derived().m_particles.empty()) return 0;
64  double minW = derived().m_particles[0].log_w;
65  double maxW = minW;
66 
67  /* Compute the max/min of weights: */
68  for (auto it = derived().m_particles.begin();
69  it != derived().m_particles.end(); ++it)
70  {
71  maxW = std::max<double>(maxW, it->log_w);
72  minW = std::min<double>(minW, it->log_w);
73  }
74  /* Normalize: */
75  for (auto it = derived().m_particles.begin();
76  it != derived().m_particles.end(); ++it)
77  it->log_w -= maxW;
78  if (out_max_log_w) *out_max_log_w = maxW;
79 
80  /* Return the max/min ratio: */
81  return std::exp(maxW - minW);
82  MRPT_END
83  }
84 
85  double ESS() const override
86  {
88  double cum = 0;
89 
90  /* Sum of weights: */
91  double sumLinearWeights = 0;
92  for (auto it = derived().m_particles.begin();
93  it != derived().m_particles.end(); ++it)
94  sumLinearWeights += std::exp(it->log_w);
95  /* Compute ESS: */
96  for (auto it = derived().m_particles.begin();
97  it != derived().m_particles.end(); ++it)
98  cum += mrpt::square(std::exp(it->log_w) / sumLinearWeights);
99 
100  if (cum == 0)
101  return 0;
102  else
103  return 1.0 / (derived().m_particles.size() * cum);
104  MRPT_END
105  }
106 
107  /** Replaces the old particles by copies determined by the indexes in
108  * "indx", performing an efficient copy of the necesary particles only and
109  * allowing the number of particles to change.*/
110  void performSubstitution(const std::vector<size_t>& indx) override
111  {
112  MRPT_START
113  // Ensure input indices are sorted
114  std::vector<size_t> sorted_indx(indx);
115  std::sort(sorted_indx.begin(), sorted_indx.end());
116 
117  /* Temporary buffer: */
118  particle_list_t parts;
119  parts.resize(sorted_indx.size());
120 
121  // Implementation for particles as pointers:
122  if constexpr (
123  Derived::PARTICLE_STORAGE == particle_storage_mode::POINTER)
124  {
125  const size_t M_old = derived().m_particles.size();
126  // Index, in the *new* set, of reused particle data, indexed
127  // by *old* indices, or "-1" if not reused.
128  std::vector<int> reusedIdx(M_old, -1);
129  typename particle_list_t::iterator itDest;
130  for (size_t i = 0; i < parts.size(); i++)
131  {
132  const size_t sorted_idx = sorted_indx[i];
133  parts[i].log_w = derived().m_particles[sorted_idx].log_w;
134 
135  // The first time that the old particle "indx[i]" appears, we
136  // can reuse the old "data" instead of creating a new copy:
137  const int idx_of_this_in_new_set = reusedIdx[sorted_idx];
138  if (idx_of_this_in_new_set == -1)
139  {
140  // First time: Reuse the data from the particle.
141  parts[i].d = std::move(derived().m_particles[sorted_idx].d);
142  reusedIdx[sorted_idx] = i;
143  }
144  else
145  {
146  // Make a copy of the particle's data
147  // (The "= operator" already makes a deep copy)
148  parts[i].d = parts[idx_of_this_in_new_set].d;
149  }
150  }
151  // Free memory of unused particles: Done automatically.
152  }
153  else
154  {
155  // Implementation for particles as values:
156  auto it_idx = sorted_indx.begin();
157  auto itDest = parts.begin();
158  for (; itDest != parts.end(); ++it_idx, ++itDest)
159  *itDest = derived().m_particles[*it_idx];
160  }
161  /* Move particles to the final container: */
162  derived().m_particles = std::move(parts);
163  MRPT_END
164  }
165 
166 }; // end CParticleFilterDataImpl<>
167 
168 /** This template class declares the array of particles and its internal data,
169  * managing some memory-related issues and providing an easy implementation of
170  * virtual methods required for implementing a CParticleFilterCapable.
171  * See also the methods in the base class CParticleFilterDataImpl<>.
172  *
173  * Since CProbabilityParticle implements all the required operators, the
174  * member "m_particles" can be safely copied with "=" or copy constructor
175  * operators
176  * and new objects will be created internally instead of copying the internal
177  * pointers, which would lead to memory corruption.
178  *
179  * \sa CParticleFilter, CParticleFilterCapable, CParticleFilterDataImpl
180  * \ingroup mrpt_bayes_grp
181  */
182 template <
185 {
186  public:
187  /** This is the type inside the corresponding CParticleData class */
189  /** Use this to refer to each element in the m_particles array. */
191  /** Use this type to refer to the list of particles m_particles. */
192  using CParticleList = std::deque<CParticleData>;
193  static const particle_storage_mode PARTICLE_STORAGE = STORAGE;
194 
195  /** The array of particles */
197 
198  /** Default constructor */
200  /** Free the memory of all the particles and reset the array "m_particles"
201  * to length zero */
202  void clearParticles() { m_particles.clear(); }
203  /** Dumps the sequence of particles and their weights to a stream (requires
204  * T implementing CSerializable).
205  * \sa readParticlesFromStream
206  */
207  template <class STREAM>
208  void writeParticlesToStream(STREAM& out) const
209  {
210  MRPT_START
211  auto n = static_cast<uint32_t>(m_particles.size());
212  out << n;
213  typename CParticleList::const_iterator it;
214  for (it = m_particles.begin(); it != m_particles.end(); ++it)
215  {
216  out << it->log_w;
217  if constexpr (STORAGE == particle_storage_mode::POINTER)
218  out << (*it->d);
219  else
220  out << it->d;
221  }
222  MRPT_END
223  }
224 
225  /** Reads the sequence of particles and their weights from a stream
226  * (requires T implementing CSerializable).
227  * \sa writeParticlesToStream
228  */
229  template <class STREAM>
230  void readParticlesFromStream(STREAM& in)
231  {
232  MRPT_START
233  clearParticles(); // Erase previous content:
234  uint32_t n;
235  in >> n;
236  m_particles.resize(n);
237  typename CParticleList::iterator it;
238  for (it = m_particles.begin(); it != m_particles.end(); ++it)
239  {
240  in >> it->log_w;
241  if constexpr (STORAGE == particle_storage_mode::POINTER)
242  {
243  it->d.reset(new T());
244  in >> *it->d;
245  }
246  else
247  {
248  in >> it->d;
249  }
250  }
251  MRPT_END
252  }
253 
254  /** Returns a vector with the sequence of the logaritmic weights of all the
255  * samples.
256  */
257  void getWeights(std::vector<double>& out_logWeights) const
258  {
259  MRPT_START
260  out_logWeights.resize(m_particles.size());
261  std::vector<double>::iterator it;
262  typename CParticleList::const_iterator it2;
263  for (it = out_logWeights.begin(), it2 = m_particles.begin();
264  it2 != m_particles.end(); ++it, ++it2)
265  *it = it2->log_w;
266  MRPT_END
267  }
268 
269  /** Returns the particle with the highest weight.
270  */
272  {
273  MRPT_START
274  const CParticleData* ret = nullptr;
275  ASSERT_(m_particles.size() > 0);
276 
277  for (const auto& p : m_particles)
278  if (ret == nullptr || p.log_w > ret->log_w) ret = &p;
279  return ret;
280  MRPT_END
281  }
282 
283 }; // End of class def.
284 
285 } // namespace mrpt::bayes
void clearParticles()
Free the memory of all the particles and reset the array "m_particles" to length zero.
#define MRPT_START
Definition: exceptions.h:241
void writeParticlesToStream(STREAM &out) const
Dumps the sequence of particles and their weights to a stream (requires T implementing CSerializable)...
void getWeights(std::vector< double > &out_logWeights) const
Returns a vector with the sequence of the logaritmic weights of all the samples.
Derived & derived()
CRTP helper method.
CParticleList m_particles
The array of particles.
double normalizeWeights(double *out_max_log_w=nullptr) override
Normalize the (logarithmic) weights, such as the maximum weight is zero.
static const particle_storage_mode PARTICLE_STORAGE
The namespace for Bayesian filtering algorithm: different particle filters and Kalman filter algorith...
double ESS() const override
Returns the normalized ESS (Estimated Sample Size), in the range [0,1].
size_t particlesCount() const override
Get the m_particles count.
CParticleFilterData()
Default constructor.
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:120
void readParticlesFromStream(STREAM &in)
Reads the sequence of particles and their weights from a stream (requires T implementing CSerializabl...
This virtual class defines the interface that any particles based PDF class must implement in order t...
std::deque< CParticleData > CParticleList
Use this type to refer to the list of particles m_particles.
const CParticleData * getMostLikelyParticle() const
Returns the particle with the highest weight.
This template class declares the array of particles and its internal data, managing some memory-relat...
void performSubstitution(const std::vector< size_t > &indx) override
Replaces the old particles by copies determined by the indexes in "indx", performing an efficient cop...
return_t square(const num_t x)
Inline function for the square of a number.
double getW(size_t i) const override
Access to i&#39;th particle (logarithm) weight, where first one is index 0.
A template class for holding a the data and the weight of a particle.
mrpt::vision::TStereoCalibResults out
const Derived & derived() const
CRTP helper method.
#define MRPT_END
Definition: exceptions.h:245
particle_storage_mode
use for CProbabilityParticle
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Definition: exceptions.h:69
A curiously recurring template pattern (CRTP) approach to providing the basic functionality of any CP...
CRBPFParticleData CParticleDataContent
This is the type inside the corresponding CParticleData class.
void setW(size_t i, double w) override
Modifies i&#39;th particle (logarithm) weight, where first one is index 0.



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 33de1d0ad Sat Jun 20 11:02:42 2020 +0200 at sáb jun 20 17:35:17 CEST 2020