Point Cloud Library (PCL)  1.11.0
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 <cassert>
41 #include <limits>
42 #include <mutex>
43 #include <vector>
44 
45 #include <cstdint>
46 
47 namespace pcl
48 {
49 
50  namespace io
51  {
52 
53  /** An abstract base class for fixed-size data buffers.
54  *
55  * A new chunk of data can be inserted using the push() method; the data
56  * elements stored in the buffer can be accessed using operator[]().
57  *
58  * Concrete implementations of this interface (such as AverageBuffer or
59  * MedianBuffer) may perform arbitrary data processing under the hood and
60  * provide access to certain quantities computed based on the input data
61  * rather than the data themselves.
62  *
63  * \author Sergey Alexandrov
64  * \ingroup io */
65  template <typename T>
66  class Buffer
67  {
68 
69  public:
70 
71  using value_type = T;
72 
73  virtual
74  ~Buffer ();
75 
76  /** Access an element at a given index. */
77  virtual T
78  operator[] (std::size_t idx) const = 0;
79 
80  /** Insert a new chunk of data into the buffer.
81  *
82  * Note that the \a data parameter is not `const`-qualified. This is
83  * done to allow deriving classes to implement no-copy data insertion,
84  * where the data is "stolen" from the input argument. */
85  virtual void
86  push (std::vector<T>& data) = 0;
87 
88  /** Get the size of the buffer. */
89  inline std::size_t
90  size () const
91  {
92  return (size_);
93  }
94 
95  protected:
96 
97  Buffer (std::size_t size);
98 
99  const std::size_t size_;
100 
101  };
102 
103  /** A simple buffer that only stores data.
104  *
105  * The buffer is thread-safe. */
106  template <typename T>
107  class SingleBuffer : public Buffer<T>
108  {
109 
110  public:
111 
112  /** Construct a buffer of given size. */
113  SingleBuffer (std::size_t size);
114 
115 
116  ~SingleBuffer ();
117 
118  T
119  operator[] (std::size_t idx) const override;
120 
121  void
122  push (std::vector<T>& data) override;
123 
124  private:
125 
126  std::vector<T> data_;
127  mutable std::mutex data_mutex_;
128 
129  using Buffer<T>::size_;
130 
131  };
132 
133  /** A buffer that computes running window median of the data inserted.
134  *
135  * The buffer and window sizes are specified at construction time. The
136  * buffer size defines the number of elements in each data chunk that is
137  * inserted in the buffer. The window size is the number of last data
138  * chunks that are considered for median computation. The median is
139  * computed separately for 1st, 2nd, etc. element in data chunks.
140  *
141  * The data can contain invalid elements. For integral types zeros are
142  * assumed to be invalid elements, whereas for floating-point types it is
143  * quiet NaN. Invalid elements are ignored when computing median.
144  *
145  * The buffer is thread-safe. */
146  template <typename T>
147  class MedianBuffer : public Buffer<T>
148  {
149 
150  public:
151 
152  /** Construct a buffer of given size with given running window size.
153  *
154  * \param[in] size buffer size
155  * \param[in] window_size running window size over which the median
156  * value should be computed (0..255) */
157  MedianBuffer (std::size_t size, unsigned char window_size);
158 
159 
160  ~MedianBuffer ();
161 
162  /** Access an element at a given index.
163  *
164  * This operation is constant time. */
165  T
166  operator[] (std::size_t idx) const override;
167 
168  /** Insert a new chunk of data into the buffer.
169  *
170  * This operation is linear in buffer size and window size.
171  *
172  * \param[in] data input data chunk, the memory will be "stolen" */
173  void
174  push (std::vector<T>& data) override;
175 
176  private:
177 
178  /** Compare two data elements.
179  *
180  * Invalid value is assumed to be larger than everything else. If both values
181  * are invalid, they are assumed to be equal.
182  *
183  * \return -1 if \c a < \c b, 0 if \c a == \c b, 1 if \c a > \c b */
184  static int compare (T a, T b);
185 
186  const unsigned char window_size_;
187  const unsigned char midpoint_;
188 
189  /// Data pushed into the buffer (last window_size_ chunks), logically
190  /// organized as a circular buffer
191  std::vector<std::vector<T> > data_;
192 
193  /// Index of the last pushed data chunk in the data_ circular buffer
194  unsigned char data_current_idx_;
195 
196  /// Indices that the argsort function would produce for data_ (with
197  /// dimensions swapped)
198  std::vector<std::vector<unsigned char> > data_argsort_indices_;
199 
200  /// Number of invalid values in the buffer
201  std::vector<unsigned char> data_invalid_count_;
202 
203  mutable std::mutex data_mutex_;
204 
205  using Buffer<T>::size_;
206 
207  };
208 
209  /** A buffer that computes running window average of the data inserted.
210  *
211  * The buffer and window sizes are specified at construction time. The
212  * buffer size defines the number of elements in each data chunk that is
213  * inserted in the buffer. The window size is the number of last data
214  * chunks that are considered for average computation. The average is
215  * computed separately for 1st, 2nd, etc. element in data chunks.
216  *
217  * The data can contain invalid elements. For integral types zeros are
218  * assumed to be invalid elements, whereas for floating-point types it is
219  * quiet NaN. Invalid elements are ignored when computing average.
220  *
221  * The buffer is thread-safe. */
222  template <typename T>
223  class AverageBuffer : public Buffer<T>
224  {
225 
226  public:
227 
228  /** Construct a buffer of given size with given running window size.
229  *
230  * \param[in] size buffer size
231  * \param[in] window_size running window size over which the median
232  * value should be computed (0..255) */
233  AverageBuffer (std::size_t size, unsigned char window_size);
234 
235 
236  ~AverageBuffer ();
237 
238  /** Access an element at a given index.
239  *
240  * This operation is constant time. */
241  T
242  operator[] (std::size_t idx) const override;
243 
244  /** Insert a new chunk of data into the buffer.
245  *
246  * This operation is linear in buffer size.
247  *
248  * \param[in] data input data chunk, the memory will be "stolen" */
249  void
250  push (std::vector<T>& data) override;
251 
252  private:
253 
254  const unsigned char window_size_;
255 
256  /// Data pushed into the buffer (last window_size_ chunks), logically
257  /// organized as a circular buffer
258  std::vector<std::vector<T> > data_;
259 
260  /// Index of the last pushed data chunk in the data_ circular buffer
261  unsigned char data_current_idx_;
262 
263  /// Current sum of the buffer
264  std::vector<T> data_sum_;
265 
266  /// Number of invalid values in the buffer
267  std::vector<unsigned char> data_invalid_count_;
268 
269  mutable std::mutex data_mutex_;
270 
271  using Buffer<T>::size_;
272 
273  };
274 
275  }
276 
277 }
278 
279 #include <pcl/io/impl/buffers.hpp>
pcl::io::SingleBuffer
A simple buffer that only stores data.
Definition: buffers.h:108
pcl::io::SingleBuffer::~SingleBuffer
~SingleBuffer()
Definition: buffers.hpp:94
pcl
Definition: convolution.h:46
pcl::io::AverageBuffer::operator[]
T operator[](std::size_t idx) const override
Access an element at a given index.
Definition: buffers.hpp:256
pcl::io::MedianBuffer::push
void push(std::vector< T > &data) override
Insert a new chunk of data into the buffer.
Definition: buffers.hpp:154
pcl::io::Buffer
An abstract base class for fixed-size data buffers.
Definition: buffers.h:67
pcl::io::MedianBuffer
A buffer that computes running window median of the data inserted.
Definition: buffers.h:148
pcl::io::MedianBuffer::operator[]
T operator[](std::size_t idx) const override
Access an element at a given index.
Definition: buffers.hpp:146
pcl::io::Buffer::size
std::size_t size() const
Get the size of the buffer.
Definition: buffers.h:90
pcl::io::SingleBuffer::SingleBuffer
SingleBuffer(std::size_t size)
Construct a buffer of given size.
Definition: buffers.hpp:87
pcl::io::AverageBuffer::AverageBuffer
AverageBuffer(std::size_t size, unsigned char window_size)
Construct a buffer of given size with given running window size.
Definition: buffers.hpp:233
pcl::io::AverageBuffer::push
void push(std::vector< T > &data) override
Insert a new chunk of data into the buffer.
Definition: buffers.hpp:265
pcl::io::Buffer::value_type
T value_type
Definition: buffers.h:71
pcl::io::AverageBuffer
A buffer that computes running window average of the data inserted.
Definition: buffers.h:224
pcl::io::Buffer::operator[]
virtual T operator[](std::size_t idx) const =0
Access an element at a given index.
pcl::io::Buffer::size_
const std::size_t size_
Definition: buffers.h:99
pcl::io::MedianBuffer::MedianBuffer
MedianBuffer(std::size_t size, unsigned char window_size)
Construct a buffer of given size with given running window size.
Definition: buffers.hpp:115
pcl::io::Buffer::~Buffer
virtual ~Buffer()
Definition: buffers.hpp:82
pcl::io::SingleBuffer::operator[]
T operator[](std::size_t idx) const override
Access an element at a given index.
Definition: buffers.hpp:99
pcl::io::MedianBuffer::~MedianBuffer
~MedianBuffer()
Definition: buffers.hpp:141
pcl::io::Buffer::push
virtual void push(std::vector< T > &data)=0
Insert a new chunk of data into the buffer.
pcl::io::Buffer::Buffer
Buffer(std::size_t size)
Definition: buffers.hpp:76
pcl::io::AverageBuffer::~AverageBuffer
~AverageBuffer()
Definition: buffers.hpp:251
pcl::io::SingleBuffer::push
void push(std::vector< T > &data) override
Insert a new chunk of data into the buffer.
Definition: buffers.hpp:106