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