Point Cloud Library (PCL)  1.14.0-dev
buffers.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2014-, Open Perception, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of the copyright holder(s) nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #pragma once
39 
40 #include <mutex>
41 #include <vector>
42 
43 namespace pcl
44 {
45 
46  namespace io
47  {
48 
49  /** An abstract base class for fixed-size data buffers.
50  *
51  * A new chunk of data can be inserted using the push() method; the data
52  * elements stored in the buffer can be accessed using operator[]().
53  *
54  * Concrete implementations of this interface (such as AverageBuffer or
55  * MedianBuffer) may perform arbitrary data processing under the hood and
56  * provide access to certain quantities computed based on the input data
57  * rather than the data themselves.
58  *
59  * \author Sergey Alexandrov
60  * \ingroup io */
61  template <typename T>
62  class Buffer
63  {
64 
65  public:
66 
67  using value_type = T;
68 
69  virtual
70  ~Buffer ();
71 
72  /** Access an element at a given index. */
73  virtual T
74  operator[] (std::size_t idx) const = 0;
75 
76  /** Insert a new chunk of data into the buffer.
77  *
78  * Note that the \a data parameter is not `const`-qualified. This is
79  * done to allow deriving classes to implement no-copy data insertion,
80  * where the data is "stolen" from the input argument. */
81  virtual void
82  push (std::vector<T>& data) = 0;
83 
84  /** Get the size of the buffer. */
85  inline std::size_t
86  size () const
87  {
88  return (size_);
89  }
90 
91  protected:
92 
93  Buffer (std::size_t size);
94 
95  const std::size_t size_;
96 
97  };
98 
99  /** A simple buffer that only stores data.
100  *
101  * The buffer is thread-safe. */
102  template <typename T>
103  class SingleBuffer : public Buffer<T>
104  {
105 
106  public:
107 
108  /** Construct a buffer of given size. */
109  SingleBuffer (std::size_t size);
110 
111 
112  ~SingleBuffer () override;
113 
114  T
115  operator[] (std::size_t idx) const override;
116 
117  void
118  push (std::vector<T>& data) override;
119 
120  private:
121 
122  std::vector<T> data_;
123  mutable std::mutex data_mutex_;
124 
125  using Buffer<T>::size_;
126 
127  };
128 
129  /** A buffer that computes running window median of the data inserted.
130  *
131  * The buffer and window sizes are specified at construction time. The
132  * buffer size defines the number of elements in each data chunk that is
133  * inserted in the buffer. The window size is the number of last data
134  * chunks that are considered for median computation. The median is
135  * computed separately for 1st, 2nd, etc. element in data chunks.
136  *
137  * The data can contain invalid elements. For integral types zeros are
138  * assumed to be invalid elements, whereas for floating-point types it is
139  * quiet NaN. Invalid elements are ignored when computing median.
140  *
141  * The buffer is thread-safe. */
142  template <typename T>
143  class MedianBuffer : public Buffer<T>
144  {
145 
146  public:
147 
148  /** Construct a buffer of given size with given running window size.
149  *
150  * \param[in] size buffer size
151  * \param[in] window_size running window size over which the median
152  * value should be computed (0..255) */
153  MedianBuffer (std::size_t size, unsigned char window_size);
154 
155 
156  ~MedianBuffer () override;
157 
158  /** Access an element at a given index.
159  *
160  * This operation is constant time. */
161  T
162  operator[] (std::size_t idx) const override;
163 
164  /** Insert a new chunk of data into the buffer.
165  *
166  * This operation is linear in buffer size and window size.
167  *
168  * \param[in] data input data chunk, the memory will be "stolen" */
169  void
170  push (std::vector<T>& data) override;
171 
172  private:
173 
174  /** Compare two data elements.
175  *
176  * Invalid value is assumed to be larger than everything else. If both values
177  * are invalid, they are assumed to be equal.
178  *
179  * \return -1 if \c a < \c b, 0 if \c a == \c b, 1 if \c a > \c b */
180  static int compare (T a, T b);
181 
182  const unsigned char window_size_;
183  const unsigned char midpoint_;
184 
185  /// Data pushed into the buffer (last window_size_ chunks), logically
186  /// organized as a circular buffer
187  std::vector<std::vector<T> > data_;
188 
189  /// Index of the last pushed data chunk in the data_ circular buffer
190  unsigned char data_current_idx_;
191 
192  /// Indices that the argsort function would produce for data_ (with
193  /// dimensions swapped)
194  std::vector<std::vector<unsigned char> > data_argsort_indices_;
195 
196  /// Number of invalid values in the buffer
197  std::vector<unsigned char> data_invalid_count_;
198 
199  mutable std::mutex data_mutex_;
200 
201  using Buffer<T>::size_;
202 
203  };
204 
205  /** A buffer that computes running window average of the data inserted.
206  *
207  * The buffer and window sizes are specified at construction time. The
208  * buffer size defines the number of elements in each data chunk that is
209  * inserted in the buffer. The window size is the number of last data
210  * chunks that are considered for average computation. The average is
211  * computed separately for 1st, 2nd, etc. element in data chunks.
212  *
213  * The data can contain invalid elements. For integral types zeros are
214  * assumed to be invalid elements, whereas for floating-point types it is
215  * quiet NaN. Invalid elements are ignored when computing average.
216  *
217  * The buffer is thread-safe. */
218  template <typename T>
219  class AverageBuffer : public Buffer<T>
220  {
221 
222  public:
223 
224  /** Construct a buffer of given size with given running window size.
225  *
226  * \param[in] size buffer size
227  * \param[in] window_size running window size over which the median
228  * value should be computed (0..255) */
229  AverageBuffer (std::size_t size, unsigned char window_size);
230 
231 
232  ~AverageBuffer () override;
233 
234  /** Access an element at a given index.
235  *
236  * This operation is constant time. */
237  T
238  operator[] (std::size_t idx) const override;
239 
240  /** Insert a new chunk of data into the buffer.
241  *
242  * This operation is linear in buffer size.
243  *
244  * \param[in] data input data chunk, the memory will be "stolen" */
245  void
246  push (std::vector<T>& data) override;
247 
248  private:
249 
250  const unsigned char window_size_;
251 
252  /// Data pushed into the buffer (last window_size_ chunks), logically
253  /// organized as a circular buffer
254  std::vector<std::vector<T> > data_;
255 
256  /// Index of the last pushed data chunk in the data_ circular buffer
257  unsigned char data_current_idx_;
258 
259  /// Current sum of the buffer
260  std::vector<T> data_sum_;
261 
262  /// Number of invalid values in the buffer
263  std::vector<unsigned char> data_invalid_count_;
264 
265  mutable std::mutex data_mutex_;
266 
267  using Buffer<T>::size_;
268 
269  };
270 
271  }
272 
273 }
274 
275 #include <pcl/io/impl/buffers.hpp>
A buffer that computes running window average of the data inserted.
Definition: buffers.h:220
void push(std::vector< T > &data) override
Insert a new chunk of data into the buffer.
Definition: buffers.hpp:260
AverageBuffer(std::size_t size, unsigned char window_size)
Construct a buffer of given size with given running window size.
Definition: buffers.hpp:229
T operator[](std::size_t idx) const override
Access an element at a given index.
Definition: buffers.hpp:251
An abstract base class for fixed-size data buffers.
Definition: buffers.h:63
const std::size_t size_
Definition: buffers.h:95
virtual void push(std::vector< T > &data)=0
Insert a new chunk of data into the buffer.
Buffer(std::size_t size)
Definition: buffers.hpp:75
std::size_t size() const
Get the size of the buffer.
Definition: buffers.h:86
virtual T operator[](std::size_t idx) const =0
Access an element at a given index.
virtual ~Buffer()
A buffer that computes running window median of the data inserted.
Definition: buffers.h:144
MedianBuffer(std::size_t size, unsigned char window_size)
Construct a buffer of given size with given running window size.
Definition: buffers.hpp:112
void push(std::vector< T > &data) override
Insert a new chunk of data into the buffer.
Definition: buffers.hpp:150
~MedianBuffer() override
T operator[](std::size_t idx) const override
Access an element at a given index.
Definition: buffers.hpp:142
A simple buffer that only stores data.
Definition: buffers.h:104
void push(std::vector< T > &data) override
Insert a new chunk of data into the buffer.
Definition: buffers.hpp:103
T operator[](std::size_t idx) const override
Access an element at a given index.
Definition: buffers.hpp:96
~SingleBuffer() override
SingleBuffer(std::size_t size)
Construct a buffer of given size.
Definition: buffers.hpp:85