Point Cloud Library (PCL)
1.15.1
Toggle main menu visibility
Loading...
Searching...
No Matches
pcl
io
impl
buffers.hpp
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
#ifndef PCL_IO_IMPL_BUFFERS_HPP
39
#define PCL_IO_IMPL_BUFFERS_HPP
40
41
#include <iostream>
42
43
#include <
pcl/pcl_macros.h
>
44
45
46
template
<
typename
T>
47
struct
buffer_traits
48
{
49
static
T
invalid
() {
return
0; }
50
static
bool
is_invalid
(T value) {
return
value ==
invalid
(); };
51
};
52
53
template
<>
54
struct
buffer_traits
<float>
55
{
56
static
float
invalid
() {
return
std::numeric_limits<float>::quiet_NaN (); };
57
static
bool
is_invalid
(
float
value) {
return
std::isnan (value); };
58
};
59
60
template
<>
61
struct
buffer_traits
<double>
62
{
63
static
double
invalid
() {
return
std::numeric_limits<double>::quiet_NaN (); };
64
static
bool
is_invalid
(
double
value) {
return
std::isnan (value); };
65
};
66
67
68
namespace
pcl
69
{
70
71
namespace
io
72
{
73
74
template
<
typename
T>
75
Buffer<T>::Buffer
(std::size_t
size
)
76
:
size_
(
size
)
77
{
78
}
79
80
template
<
typename
T>
81
Buffer<T>::~Buffer
()
82
=
default
;
83
84
template
<
typename
T>
85
SingleBuffer<T>::SingleBuffer
(std::size_t
size
)
86
:
Buffer
<T> (
size
)
87
, data_ (
size
,
buffer_traits
<T>::invalid ())
88
{
89
}
90
91
template
<
typename
T>
92
SingleBuffer<T>::~SingleBuffer
()
93
=
default
;
94
95
template
<
typename
T> T
96
SingleBuffer<T>::operator[]
(std::size_t idx)
const
97
{
98
assert (idx <
size_
);
99
return
(data_[idx]);
100
}
101
102
template
<
typename
T>
void
103
SingleBuffer<T>::push
(std::vector<T>& data)
104
{
105
assert (data.size () ==
size_
);
106
std::lock_guard<std::mutex> lock (data_mutex_);
107
data_.swap (data);
108
data.clear ();
109
}
110
111
template
<
typename
T>
112
MedianBuffer<T>::MedianBuffer
(std::size_t
size
,
113
unsigned
char
window_size)
114
:
Buffer
<T> (
size
)
115
, window_size_ (window_size)
116
, midpoint_ (window_size_ / 2)
117
, data_current_idx_ (window_size_ - 1)
118
{
119
assert (
size_
> 0);
120
assert (window_size_ > 0);
121
122
data_.resize (window_size_);
123
for
(std::size_t i = 0; i < window_size_; ++i)
124
data_[i].resize (
size_
,
buffer_traits<T>::invalid
());
125
126
data_argsort_indices_.resize (
size_
);
127
for
(std::size_t i = 0; i <
size_
; ++i)
128
{
129
data_argsort_indices_[i].resize (window_size_);
130
for
(std::size_t j = 0; j < window_size_; ++j)
131
data_argsort_indices_[i][j] = j;
132
}
133
134
data_invalid_count_.resize (
size_
, window_size_);
135
}
136
137
template
<
typename
T>
138
MedianBuffer<T>::~MedianBuffer
()
139
=
default
;
140
141
template
<
typename
T> T
142
MedianBuffer<T>::operator[]
(std::size_t idx)
const
143
{
144
assert (idx <
size_
);
145
int
midpoint = (window_size_ - data_invalid_count_[idx]) / 2;
146
return
(data_[data_argsort_indices_[idx][midpoint]][idx]);
147
}
148
149
template
<
typename
T>
void
150
MedianBuffer<T>::push
(std::vector<T>& data)
151
{
152
assert (data.size () ==
size_
);
153
std::lock_guard<std::mutex> lock (data_mutex_);
154
155
if
(++data_current_idx_ >= window_size_)
156
data_current_idx_ = 0;
157
158
// New data will replace the column with index data_current_idx_. Before
159
// overwriting it, we go through all the new-old value pairs and update
160
// data_argsort_indices_ to maintain sorted order.
161
for
(std::size_t i = 0; i <
size_
; ++i)
162
{
163
const
T& new_value = data[i];
164
const
T& old_value = data_[data_current_idx_][i];
165
bool
new_is_invalid =
buffer_traits<T>::is_invalid
(new_value);
166
bool
old_is_invalid =
buffer_traits<T>::is_invalid
(old_value);
167
if
(compare (new_value, old_value) == 0)
168
continue
;
169
std::vector<unsigned char>& argsort_indices = data_argsort_indices_[i];
170
// Rewrite the argsort indices before or after the position where we insert
171
// depending on the relation between the old and new values
172
if
(compare (new_value, old_value) == 1)
173
{
174
for
(
int
j = 0; j < window_size_; ++j)
175
if
(argsort_indices[j] == data_current_idx_)
176
{
177
int
k = j + 1;
178
while
(k < window_size_ && compare (new_value, data_[argsort_indices[k]][i]) == 1)
179
{
180
std::swap (argsort_indices[k - 1], argsort_indices[k]);
181
++k;
182
}
183
break
;
184
}
185
}
186
else
187
{
188
for
(
int
j = window_size_ - 1; j >= 0; --j)
189
if
(argsort_indices[j] == data_current_idx_)
190
{
191
int
k = j - 1;
192
while
(k >= 0 && compare (new_value, data_[argsort_indices[k]][i]) == -1)
193
{
194
std::swap (argsort_indices[k], argsort_indices[k + 1]);
195
--k;
196
}
197
break
;
198
}
199
}
200
201
if
(new_is_invalid && !old_is_invalid)
202
++data_invalid_count_[i];
203
else
if
(!new_is_invalid && old_is_invalid)
204
--data_invalid_count_[i];
205
}
206
207
// Finally overwrite the data
208
data_[data_current_idx_].swap (data);
209
data.clear ();
210
}
211
212
template
<
typename
T>
int
213
MedianBuffer<T>::compare (T a, T b)
214
{
215
bool
a_is_invalid =
buffer_traits<T>::is_invalid
(a);
216
bool
b_is_invalid =
buffer_traits<T>::is_invalid
(b);
217
if
(a_is_invalid && b_is_invalid)
218
return
0;
219
if
(a_is_invalid)
220
return
1;
221
if
(b_is_invalid)
222
return
-1;
223
if
(a == b)
224
return
0;
225
return
a > b ? 1 : -1;
226
}
227
228
template
<
typename
T>
229
AverageBuffer<T>::AverageBuffer
(std::size_t
size
,
230
unsigned
char
window_size)
231
:
Buffer
<T> (
size
)
232
, window_size_ (window_size)
233
, data_current_idx_ (window_size_ - 1)
234
{
235
assert (
size_
> 0);
236
assert (window_size_ > 0);
237
238
data_.resize (window_size_);
239
for
(std::size_t i = 0; i < window_size_; ++i)
240
data_[i].resize (
size_
,
buffer_traits<T>::invalid
());
241
242
data_sum_.resize (
size_
, 0);
243
data_invalid_count_.resize (
size_
, window_size_);
244
}
245
246
template
<
typename
T>
247
AverageBuffer<T>::~AverageBuffer
()
248
=
default
;
249
250
template
<
typename
T> T
251
AverageBuffer<T>::operator[]
(std::size_t idx)
const
252
{
253
assert (idx <
size_
);
254
if
(data_invalid_count_[idx] == window_size_)
255
return
(
buffer_traits<T>::invalid
());
256
return
(data_sum_[idx] /
static_cast<
T
>
(window_size_ - data_invalid_count_[idx]));
257
}
258
259
template
<
typename
T>
void
260
AverageBuffer<T>::push
(std::vector<T>& data)
261
{
262
assert (data.size () ==
size_
);
263
std::lock_guard<std::mutex> lock (data_mutex_);
264
265
if
(++data_current_idx_ >= window_size_)
266
data_current_idx_ = 0;
267
268
// New data will replace the column with index data_current_idx_. Before
269
// overwriting it, we go through the old values and subtract them from the
270
// data_sum_
271
for
(std::size_t i = 0; i <
size_
; ++i)
272
{
273
const
float
& new_value = data[i];
274
const
float
& old_value = data_[data_current_idx_][i];
275
bool
new_is_invalid =
buffer_traits<T>::is_invalid
(new_value);
276
bool
old_is_invalid =
buffer_traits<T>::is_invalid
(old_value);
277
278
if
(!old_is_invalid)
279
data_sum_[i] -= old_value;
280
if
(!new_is_invalid)
281
data_sum_[i] += new_value;
282
283
if
(new_is_invalid && !old_is_invalid)
284
++data_invalid_count_[i];
285
else
if
(!new_is_invalid && old_is_invalid)
286
--data_invalid_count_[i];
287
}
288
289
// Finally overwrite the data
290
data_[data_current_idx_].swap (data);
291
data.clear ();
292
}
293
294
}
// namespace io
295
}
// namespace pcl
296
297
#endif
/* PCL_IO_IMPL_BUFFERS_HPP */
298
pcl::io::AverageBuffer::push
void push(std::vector< T > &data) override
Insert a new chunk of data into the buffer.
Definition
buffers.hpp:260
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:229
pcl::io::AverageBuffer::~AverageBuffer
~AverageBuffer() override
pcl::io::AverageBuffer::operator[]
T operator[](std::size_t idx) const override
Access an element at a given index.
Definition
buffers.hpp:251
pcl::io::Buffer::size_
const std::size_t size_
Definition
buffers.h:95
pcl::io::Buffer::Buffer
Buffer(std::size_t size)
Definition
buffers.hpp:75
pcl::io::Buffer::size
std::size_t size() const
Get the size of the buffer.
Definition
buffers.h:86
pcl::io::Buffer::~Buffer
virtual ~Buffer()
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:112
pcl::io::MedianBuffer::push
void push(std::vector< T > &data) override
Insert a new chunk of data into the buffer.
Definition
buffers.hpp:150
pcl::io::MedianBuffer::~MedianBuffer
~MedianBuffer() override
pcl::io::MedianBuffer::operator[]
T operator[](std::size_t idx) const override
Access an element at a given index.
Definition
buffers.hpp:142
pcl::io::SingleBuffer::push
void push(std::vector< T > &data) override
Insert a new chunk of data into the buffer.
Definition
buffers.hpp:103
pcl::io::SingleBuffer::operator[]
T operator[](std::size_t idx) const override
Access an element at a given index.
Definition
buffers.hpp:96
pcl::io::SingleBuffer::~SingleBuffer
~SingleBuffer() override
pcl::io::SingleBuffer::SingleBuffer
SingleBuffer(std::size_t size)
Construct a buffer of given size.
Definition
buffers.hpp:85
pcl::io
Definition
io.h:517
pcl
Definition
convolution.h:46
pcl_macros.h
Defines all the PCL and non-PCL macros used.
buffer_traits< double >::is_invalid
static bool is_invalid(double value)
Definition
buffers.hpp:64
buffer_traits< double >::invalid
static double invalid()
Definition
buffers.hpp:63
buffer_traits< float >::invalid
static float invalid()
Definition
buffers.hpp:56
buffer_traits< float >::is_invalid
static bool is_invalid(float value)
Definition
buffers.hpp:57
buffer_traits
Definition
buffers.hpp:48
buffer_traits::invalid
static T invalid()
Definition
buffers.hpp:49
buffer_traits::is_invalid
static bool is_invalid(T value)
Definition
buffers.hpp:50