Apollo 11.0
自动驾驶开放平台
i_struct_s.h
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
17#pragma once
18
19#include <vector>
20
21#if defined(__x86_64__)
22#include <smmintrin.h>
23#elif defined(__aarch64__) && defined(__ARM_NEON)
24#include "sse2neon.h" // NOLINT
25#else
26#error "Processor architecture not supported!"
27#endif
28
32
33namespace apollo {
34namespace perception {
35namespace algorithm {
36template <typename T, unsigned int d>
37class PtCluster {
38 public:
39 typedef T *iterator;
40 typedef const T *const_iterator;
41 typedef T &reference;
42 typedef const T &const_reference;
43
44 static unsigned int NrPointElement() { return (d); }
45
46 static unsigned int PointsizeInByte() { return (d * sizeof(T)); }
47
48 unsigned int ClustersizeInByte() const {
49 return (d * sizeof(T) * nr_points_);
50 }
51
52 unsigned int NrPoints() const { return (nr_points_); }
53
54 bool Initialized() const { return (nr_points_ > 0); }
55
56 const T *ConstData() const { return (data_); }
57
58 T *Data() { return (data_); }
59
60 void CleanUp();
61
62 PtCluster();
63 explicit PtCluster(unsigned int n);
64 PtCluster(const T *data, unsigned int n);
65 PtCluster(const PtCluster<T, d> &c) : data_(nullptr), nr_points_(0) {
66 if (c.NrPoints()) {
67 nr_points_ = c.NrPoints();
68 data_ = IAllocAligned<T>(nr_points_ * d, 4);
69 assert(data_ != nullptr && IVerifyAlignment(data_, 4));
71 }
72 }
73
75 if (this != &c) {
76 if (this->nr_points_ != c.NrPoints()) {
78 data_ = IAllocAligned<T>(this->nr_points_ * d, 4);
79 assert(data_ != nullptr && IVerifyAlignment(data_, 4));
80 this->nr_points_ = c.NrPoints();
81 }
82 ICopy(c.ConstData(), data_, this->nr_points_ * d);
83 }
84 return (*this);
85 }
86
87 virtual ~PtCluster() { CleanUp(); }
88
89 T *operator[](unsigned int i) {
90 assert(i < nr_points_);
91 assert(data_ != nullptr);
92 return (data_ + i * d);
93 }
94
95 const T *operator[](unsigned int i) const {
96 assert(i < nr_points_);
97 assert(data_ != nullptr);
98 return (data_ + i * d);
99 }
100
101 reference operator()(unsigned int i, unsigned int j) {
102 assert(i < nr_points_ && j < d);
103 return data_[i * d + j];
104 }
105
106 const_reference operator()(unsigned int i, unsigned int j) const {
107 assert(i < nr_points_ && j < d);
108 return data_[i * d + j];
109 }
110
111 iterator Begin() { return data_; }
112
113 iterator End() { return data_ + (nr_points_ * d); }
114
115 const_iterator Begin() const { return data_; }
116
117 const_iterator End() const { return data_ + (nr_points_ * d); }
118
119 protected:
120 // continuous 16-byte aligned memory
122 unsigned int nr_points_;
123};
124
125template <typename T, unsigned int d>
126PtCluster<T, d>::PtCluster() : data_(nullptr), nr_points_(0) {}
127
128template <typename T, unsigned int d>
129PtCluster<T, d>::PtCluster(unsigned int n) : data_(nullptr), nr_points_(n) {
130 if (n != 0) {
131 data_ = IAllocAligned<T>(n * d, 4);
132 if (!data_ || !IVerifyAlignment(data_, 4)) {
133 nr_points_ = 0;
135 }
136 }
137}
138
139template <typename T, unsigned int d>
140PtCluster<T, d>::PtCluster(const T *data, unsigned int n)
141 : data_(nullptr), nr_points_(n) {
142 if (data && n) {
143 data_ = IAllocAligned<T>(n * d, 4);
144 if (data_ && IVerifyAlignment(data_, 4)) {
145 ICopy(data, data_, n * d);
146 } else {
147 nr_points_ = 0;
149 }
150 }
151}
152
153template <typename T, unsigned int d>
155 IFreeAligned(&data_);
156 nr_points_ = 0;
157}
158
159template <typename T>
160inline int IAssignPointToVoxel(const T *data, T bound_x_min, T bound_x_max,
161 T bound_y_min, T bound_y_max, T bound_z_min,
162 T bound_z_max, T voxel_width_x_rec,
163 T voxel_width_y_rec, int nr_voxel_x,
164 int nr_voxel_y) {
165 int i, j, k;
166 T x = data[0];
167 T y = data[1];
168 T z = data[2];
169
170 // points that are outside the defined BBOX are ignored
171 if (x < bound_x_min || x > bound_x_max || y < bound_y_min ||
172 y > bound_y_max || z < bound_z_min || z > bound_z_max) {
173 return (-1);
174 }
175
176 // compute the x, y voxel indices
177 k = IMin(nr_voxel_x - 1,
178 static_cast<int>((x - bound_x_min) * voxel_width_x_rec));
179 j = IMin(nr_voxel_y - 1,
180 static_cast<int>((y - bound_y_min) * voxel_width_y_rec));
181 i = (nr_voxel_x * j) + k;
182 return (i);
183}
184
185template <typename T>
186inline int AssignPointToVoxel(T xx, T yy, T zz, T bound_x_min, T bound_x_max,
187 T bound_y_min, T bound_y_max, T bound_z_min,
188 T bound_z_max, T voxel_width_x_rec,
189 T voxel_width_y_rec, int nr_voxel_x,
190 int nr_voxel_y) {
191 int i, j, k;
192 T x = xx;
193 T y = yy;
194 T z = zz;
195
196 // points that are outside the defined BBOX are ignored
197 if (x < bound_x_min || x > bound_x_max || y < bound_y_min ||
198 y > bound_y_max || z < bound_z_min || z > bound_z_max) {
199 return (-1);
200 }
201
202 // compute the x, y voxel indices
203 k = IMin(nr_voxel_x - 1,
204 static_cast<int>((x - bound_x_min) * voxel_width_x_rec));
205 j = IMin(nr_voxel_y - 1,
206 static_cast<int>((y - bound_y_min) * voxel_width_y_rec));
207 i = (nr_voxel_x * j) + k;
208 return (i);
209}
210
211template <typename T>
212class Voxel {
213 public:
214 Voxel() {}
216 Voxel(const Voxel<T> &voxel) {
217 dim_x_ = voxel.dim_x_;
218 dim_y_ = voxel.dim_y_;
219 dim_z_ = voxel.dim_z_;
220 ix_ = voxel.ix_;
221 iy_ = voxel.iy_;
222 iz_ = voxel.iz_;
223 ICopy3(voxel.v_, v_);
224 indices_.assign(voxel.indices_.begin(), voxel.indices_.end());
225 }
226
227 Voxel &operator=(const Voxel<T> &voxel) {
228 if (this != &voxel) {
229 this->dim_x_ = voxel.dim_x_;
230 this->dim_y_ = voxel.dim_y_;
231 this->dim_z_ = voxel.dim_z_;
232 this->ix_ = voxel.ix_;
233 this->iy_ = voxel.iy_;
234 this->iz_ = voxel.iz_;
235 ICopy3(voxel.v_, this->v_);
236 this->indices_.assign(voxel.indices_.begin(), voxel.indices_.end());
237 }
238 return (*this);
239 }
240
241 void Init(const T *v, T dim_x, T dim_y, T dim_z, int ix, int iy, int iz) {
242 ICopy3(v, v_);
243 dim_x_ = dim_x;
244 dim_y_ = dim_y;
245 dim_z_ = dim_z;
246 ix_ = ix;
247 iy_ = iy;
248 iz_ = iz;
249 indices_.clear();
250 }
251
252 void Init(T v_x, T v_y, T v_z, T dim_x, T dim_y, T dim_z, int ix, int iy,
253 int iz) {
254 v_[0] = v_x;
255 v_[1] = v_y;
256 v_[2] = v_z;
257 dim_x_ = dim_x;
258 dim_y_ = dim_y;
259 dim_z_ = dim_z;
260 ix_ = ix;
261 iy_ = iy;
262 iz_ = iz;
263 indices_.clear();
264 }
265
266 void Reset() {
267 IZero3(v_);
268 dim_x_ = dim_y_ = dim_z_ = 0;
269 ix_ = iy_ = iz_ = 0;
270 indices_.clear();
271 }
272
273 void Reserve(unsigned int size) { indices_.reserve(size); }
274
275 void PushBack(int id) { indices_.push_back(id); }
276
277 unsigned int Capacity() const { return (unsigned int)indices_.capacity(); }
278
279 unsigned int NrPoints() const { return (unsigned int)indices_.size(); }
280
281 bool Empty() const { return indices_.empty(); }
282
284
285 // voxel indices in the X, Y, Z dimensions - meaningful for voxel grid
286 int ix_, iy_, iz_;
287
288 // point indices
289 std::vector<int> indices_;
290};
291
292// -----Voxel Grid XY-----
293template <typename T>
295 // assuming at most 320000 points
296 static const unsigned int s_nr_max_reserved_points_ = 320000;
297
298 public:
300 VoxelGridXY(unsigned int nr_voxel_x, unsigned int nr_voxel_y,
301 T spatial_bound_x_min, T spatial_bound_x_max,
302 T spatial_bound_y_min, T spatial_bound_y_max,
303 T spatial_bound_z_min, T spatial_bound_z_max);
304
306 if (this != &vg) {
307 this->initialized_ = vg.Initialized();
308 this->nr_points_ = vg.NrPoints();
309 this->nr_point_element_ = vg.NrPointElement();
310 this->nr_voxel_x_ = vg.NrVoxelX();
311 this->nr_voxel_y_ = vg.NrVoxelY();
312 this->nr_voxel_z_ = vg.NrVoxelZ();
313 this->data_ = vg.const_data();
314 this->semantic_data_ = vg.const_semantic_data();
315 vg.GetGridDimension(&this->dim_x_[0], &this->dim_x_[1], &this->dim_y_[0],
316 &this->dim_y_[1], &this->dim_z_[0], &this->dim_z_[1]);
317 this->voxels_.resize(vg.NrVoxel());
318 for (unsigned int i = 0; i < vg.NrVoxel(); ++i) {
319 this->voxels_[i] = vg[i];
320 }
321
322 this->AllocAlignedMemory();
323 }
324 return (*this);
325 }
326
327 void CleanUp();
328
330 IFreeAligned<float>(&mem_aligned16_f32_);
331 IFreeAligned<int>(&mem_aligned16_i32_);
332 CleanUp();
333 }
334
335 bool Alloc(unsigned int nr_voxel_x, unsigned int nr_voxel_y,
336 T spatial_bound_x_min, T spatial_bound_x_max,
337 T spatial_bound_y_min, T spatial_bound_y_max,
338 T spatial_bound_z_min, T spatial_bound_z_max);
339
340 bool Set(const T *data, const int *semantic_data, unsigned int nr_points,
341 unsigned int nr_point_element);
342
343 // sse2 version: only for float type input Data
344 bool SetS(const float *data, const int *semantic_data,
345 unsigned int nr_points, unsigned int nr_point_element);
346
347 bool Set(const T *data, const int *semantic_data,
348 unsigned int nr_points, unsigned int nr_point_element,
349 unsigned int nr_voxel_x, unsigned int nr_voxel_y,
350 T spatial_bound_x_min, T spatial_bound_x_max, T spatial_bound_y_min,
351 T spatial_bound_y_max, T spatial_bound_z_min, T spatial_bound_z_max,
352 bool force_bound = true);
353
354 bool Initialized() const { return initialized_; }
355
356 unsigned int NrVoxel() const { return (unsigned int)voxels_.size(); }
357
358 unsigned int NrVoxelX() const { return nr_voxel_x_; }
359
360 unsigned int NrVoxelY() const { return nr_voxel_y_; }
361
362 unsigned int NrVoxelZ() const { return (1); }
363
364 unsigned int NrPoints() const { return nr_points_; }
365
366 unsigned int NrPointElement() const { return nr_point_element_; }
367
368 unsigned int NrIndexedPoints() const;
369
370 std::vector<Voxel<T>> &GetVoxels() { return voxels_; }
371
372 const std::vector<Voxel<T>> &GetConstVoxels() const { return voxels_; }
373
374 void SetVoxels(const std::vector<Voxel<T>> &voxels) {
375 voxels_.assign(voxels.begin(), voxels.end());
376 }
377
378 bool GetGridDimension(T *dim_min_x, T *dim_max_x, T *dim_min_y, T *dim_max_y,
379 T *dim_min_z, T *dim_max_z) const {
380 if (!initialized_) {
381 dim_min_x = dim_max_x = dim_min_y = dim_max_y = dim_min_z = dim_max_z =
382 static_cast<T>(0);
383 return (false);
384 }
385 *dim_min_x = dim_x_[0];
386 *dim_max_x = dim_x_[1];
387 *dim_min_y = dim_y_[0];
388 *dim_max_y = dim_y_[1];
389 *dim_min_z = dim_z_[0];
390 *dim_max_z = dim_z_[1];
391 return (true);
392 }
393
394 void SetGridDimension(T dim_min_x, T dim_max_x, T dim_min_y, T dim_max_y,
395 T dim_min_z, T dim_max_z) {
396 dim_x_[0] = dim_min_x;
397 dim_x_[1] = dim_max_x;
398 dim_y_[0] = dim_min_y;
399 dim_y_[1] = dim_max_y;
400 dim_z_[0] = dim_min_z;
401 dim_z_[1] = dim_max_z;
402 }
403
404 bool GetVoxelDimension(T *voxel_width_x, T *voxel_width_y,
405 T *voxel_width_z) const {
406 if (!initialized_) {
407 *voxel_width_x = *voxel_width_y = *voxel_width_z = static_cast<T>(0);
408 return (false);
409 }
410 *voxel_width_x = voxel_dim_[0];
411 *voxel_width_y = voxel_dim_[1];
412 *voxel_width_z = voxel_dim_[2];
413 return (true);
414 }
415
416 void SetVoxelDimension(T voxel_width_x, T voxel_width_y, T voxel_width_z) {
417 voxel_dim_[0] = voxel_width_x;
418 voxel_dim_[1] = voxel_width_y;
419 voxel_dim_[2] = voxel_width_z;
420 }
421
422 void SetNrPoints(unsigned int nr_points) { nr_points_ = nr_points; }
423
424 void SetNrPointElement(unsigned int nr_point_element) {
425 nr_point_element_ = nr_point_element;
426 }
427
428 void SetNrVoxel(unsigned int nr_voxel_x, unsigned int nr_voxel_y,
429 unsigned int nr_voxel_z) {
430 nr_voxel_x_ = nr_voxel_x;
431 nr_voxel_y_ = nr_voxel_y;
432 nr_voxel_z_ = nr_voxel_z;
433 }
434
435 void SetPointCloudsData(const T *data) { data_ = data; }
436
437 void SetSematicValueData(const int *data) { semantic_data_ = data; }
438
439 void SetInitialized(bool initialized) { initialized_ = initialized; }
440
441 // int GetAllIndices(std::vector<int> &indices) const;
442
443 int WhichVoxel(T x, T y, T z) const;
444
445 // add by Fangzhen Li on 03/27/17
446 bool GetVoxelCoordinateXY(T x, T y, int *row, int *col) const;
447
448 Voxel<T> &operator[](unsigned int i) {
449 assert(i >= 0 && i < voxels_.size());
450 return (voxels_[i]);
451 }
452
453 const Voxel<T> &operator[](unsigned int i) const {
454 assert(i >= 0 && i < voxels_.size());
455 return (voxels_[i]);
456 }
457
459 assert(i >= 0 && i < static_cast<int>(voxels_.size()));
460 return (voxels_[i]);
461 }
462 const Voxel<T> &operator[](int i) const {
463 assert(i >= 0 && i < static_cast<int>(voxels_.size()));
464 return (voxels_[i]);
465 }
466
467 Voxel<T> &operator()(unsigned int iy, unsigned int ix) {
468 assert(iy < nr_voxel_y_ && ix < nr_voxel_x_);
469 unsigned int i = nr_voxel_x_ * iy + ix;
470 assert(i < voxels_.size());
471 return (voxels_[i]);
472 }
473
474 const Voxel<T> &operator()(unsigned int iy, unsigned int ix) const {
475 assert(iy < nr_voxel_y_ && ix < nr_voxel_x_);
476 unsigned int i = nr_voxel_x_ * iy + ix;
477 assert(i < voxels_.size());
478 return (voxels_[i]);
479 }
480
481 T *Data() { return (data_); }
482
483 const T *const_data() const { return (data_); }
484
485 int *SemanticData() { return (semantic_data_); }
486
487 const int *const_semantic_data() const { return (semantic_data_); }
488
489 private:
490 void Reserve();
491 bool AllocAlignedMemory();
492
493 private:
494 unsigned int nr_points_ = 0;
495 unsigned int nr_point_element_ = 0;
496 unsigned int nr_voxel_x_ = 0;
497 unsigned int nr_voxel_y_ = 0;
498 unsigned int nr_voxel_z_ = 0;
499 const T *data_ = nullptr; // point clouds memory
500 const int* semantic_data_ = nullptr; // semantic value memory
501 bool initialized_ = false;
502 T dim_x_[2], dim_y_[2], dim_z_[2], voxel_dim_[3];
503 float *mem_aligned16_f32_ = nullptr;
504 int *mem_aligned16_i32_ = nullptr;
505 std::vector<Voxel<T>> voxels_;
506};
507
508template <typename T>
510 : nr_points_(0),
511 nr_point_element_(0),
512 nr_voxel_x_(0),
513 nr_voxel_y_(0),
514 nr_voxel_z_(1),
515 data_(nullptr),
516 semantic_data_(nullptr),
517 initialized_(false),
518 mem_aligned16_f32_(nullptr),
519 mem_aligned16_i32_(nullptr) {
520 IZero2(dim_x_);
521 IZero2(dim_y_);
522 IZero2(dim_z_);
523 IZero3(voxel_dim_);
524 AllocAlignedMemory();
525}
526
527template <typename T>
529 initialized_ = false;
530 data_ = nullptr;
531 semantic_data_ = nullptr;
532 nr_points_ = nr_point_element_ = nr_voxel_x_ = nr_voxel_y_ = 0;
533 nr_voxel_z_ = 1;
534 IZero2(dim_x_);
535 IZero2(dim_y_);
536 IZero2(dim_z_);
537 IZero3(voxel_dim_);
538 voxels_.clear();
539}
540
541template <typename T>
542VoxelGridXY<T>::VoxelGridXY(unsigned int nr_voxel_x, unsigned int nr_voxel_y,
543 T spatial_bound_x_min, T spatial_bound_x_max,
544 T spatial_bound_y_min, T spatial_bound_y_max,
545 T spatial_bound_z_min, T spatial_bound_z_max) {
546 Alloc(nr_voxel_x, nr_voxel_y, spatial_bound_x_min, spatial_bound_x_max,
547 spatial_bound_y_min, spatial_bound_y_max, spatial_bound_z_min,
548 spatial_bound_z_max);
549 AllocAlignedMemory();
550 initialized_ = false;
551}
552
553template <typename T>
555 int r, c, i = 0, m = 0;
556 unsigned int n = (nr_voxel_x_ * nr_voxel_y_);
557
558 if (n == 0 || voxels_.size() != n) {
559 return;
560 }
561
562 double cen_x = (static_cast<double>(nr_voxel_x_ - 1)) * 0.5;
563 double cen_y = (static_cast<double>(nr_voxel_y_ - 1)) * 0.5;
564
565 // normalization factor = 1/(2sigma*sigma)
566 // hardcode sigma 10.0
567 double sigma = static_cast<double>(IAverage(nr_voxel_x_, nr_voxel_y_) / 10.0);
568 double nf = IDiv(0.5, (sigma * sigma));
569 double dr, drsqr, dc, dcsqr, v, ksum = 0.0;
570 std::vector<double> kernel(n, 0.0);
571
572 // pre-compute kernel
573 for (r = 0; r < static_cast<int>(nr_voxel_y_); ++r) {
574 dr = static_cast<double>(r) - cen_y;
575 drsqr = ISqr(dr);
576 for (c = 0; c < static_cast<int>(nr_voxel_x_); ++c) {
577 dc = static_cast<double>(c) - cen_x;
578 dcsqr = ISqr(dc);
579 v = IExp(-(drsqr + dcsqr) * nf);
580 ksum += v;
581 kernel[i++] = v;
582 }
583 }
584
585 // normalize the kernel, sum to 1.0
586 v = IRec(ksum);
587 for (i = 0; i < static_cast<int>(n); ++i) {
588 kernel[i] *= v;
589 }
590
591 // Alloc at least 8 positions
592 for (i = 0; i < static_cast<int>(n); ++i) {
593 m = IMax(8, static_cast<int>(s_nr_max_reserved_points_ * kernel[i]));
594 voxels_[i].Reserve(m);
595 }
596}
597
598template <typename T>
599bool VoxelGridXY<T>::AllocAlignedMemory() {
600 if (!mem_aligned16_f32_) {
601 mem_aligned16_f32_ = IAllocAligned<float>(4, 4);
602 }
603 if (!mem_aligned16_i32_) {
604 mem_aligned16_i32_ = IAllocAligned<int>(4, 4);
605 }
606 return (mem_aligned16_f32_ != nullptr && mem_aligned16_i32_ != nullptr &&
607 IVerifyAlignment(mem_aligned16_f32_, 4) &&
608 IVerifyAlignment(mem_aligned16_i32_, 4));
609}
610
611template <typename T>
612int VoxelGridXY<T>::WhichVoxel(T x, T y, T z) const {
613 int j, k;
614 if (!initialized_) {
615 return (-1);
616 }
617
618 if (x < dim_x_[0] || x > dim_x_[1] || y < dim_y_[0] || y > dim_y_[1] ||
619 z < dim_z_[0] || z > dim_z_[1]) {
620 return (-1); // points that are outside the defined BBOX are ignored
621 }
622
623 k = static_cast<int>(IMax(
624 (unsigned int)0,
625 IMin(nr_voxel_x_ - 1, (unsigned int)((x - dim_x_[0]) / voxel_dim_[0]))));
626 j = static_cast<int>(IMax(
627 (unsigned int)0,
628 IMin(nr_voxel_y_ - 1, (unsigned int)((y - dim_y_[0]) / voxel_dim_[1]))));
629 return (nr_voxel_x_ * j + k);
630}
631
632// add by Fangzhen Li on 03/27/17
633template <typename T>
634bool VoxelGridXY<T>::GetVoxelCoordinateXY(T x, T y, int *row, int *col) const {
635 if (x < dim_x_[0] || x > dim_x_[1] || y < dim_y_[0] || y > dim_y_[1]) {
636 return false; // points that are outside the defined BBOX are ignored
637 }
638
639 *col = static_cast<int>((x - dim_x_[0]) / voxel_dim_[0]);
640 *row = static_cast<int>((y - dim_y_[0]) / voxel_dim_[1]);
641 return true;
642}
643
644template <typename T>
645bool VoxelGridXY<T>::Alloc(unsigned int nr_voxel_x, unsigned int nr_voxel_y,
646 T spatial_bound_x_min, T spatial_bound_x_max,
647 T spatial_bound_y_min, T spatial_bound_y_max,
648 T spatial_bound_z_min, T spatial_bound_z_max) {
649 if (!nr_voxel_x || !nr_voxel_y) {
650 initialized_ = false;
651 return initialized_;
652 }
653 nr_voxel_x_ = nr_voxel_x;
654 nr_voxel_y_ = nr_voxel_y;
655
656 unsigned int i, j, k, n = 0;
657 unsigned int nr_voxel_xy = (nr_voxel_x_ * nr_voxel_y_);
658 unsigned int nr_voxel = nr_voxel_xy;
659
660 T vx, vy, vz, voxel_width_x, voxel_width_y, voxel_width_z;
661
662 voxels_.clear();
663 voxels_.resize(nr_voxel);
664
665 // voxel grid dimesion is forced to be the manual input
666 dim_x_[0] = spatial_bound_x_min;
667 dim_x_[1] = spatial_bound_x_max;
668
669 dim_y_[0] = spatial_bound_y_min;
670 dim_y_[1] = spatial_bound_y_max;
671
672 dim_z_[0] = spatial_bound_z_min;
673 dim_z_[1] = spatial_bound_z_max;
674
675 T span_x = (dim_x_[1] - dim_x_[0]);
676 T span_y = (dim_y_[1] - dim_y_[0]);
677 T span_z = (dim_z_[1] - dim_z_[0]);
678
679 assert(span_x > 0 && span_y > 0 && span_z > 0);
680
681 voxel_dim_[0] = voxel_width_x = IDiv(span_x, static_cast<int>(nr_voxel_x_));
682 voxel_dim_[1] = voxel_width_y = IDiv(span_y, static_cast<int>(nr_voxel_y_));
683 voxel_dim_[2] = voxel_width_z = span_z;
684
685 std::vector<T> vxs(nr_voxel_x_);
686
687 vxs[0] = dim_x_[0];
688 for (i = 1; i < nr_voxel_x_; i++) {
689 vxs[i] = vxs[i - 1] + voxel_width_x;
690 }
691
692 vy = dim_y_[0];
693 vz = dim_z_[0];
694
695 for (j = 0; j < nr_voxel_y_; j++) {
696 for (k = 0; k < nr_voxel_x_; k++) {
697 vx = vxs[k];
698 voxels_[n++].Init(vx, vy, vz, voxel_width_x, voxel_width_y, voxel_width_z,
699 static_cast<int>(k), static_cast<int>(j), 0);
700 }
701 vy += voxel_width_y;
702 }
703
704 // pre-Alloc capacaity for indices_ vector - speed-up the code slightly
705 Reserve();
706 return (true);
707}
708
709template <typename T>
710bool VoxelGridXY<T>::Set(const T *data, const int *semantic_data,
711 unsigned int nr_points, unsigned int nr_point_element) {
712 if (!data || !nr_points || !nr_point_element || !nr_voxel_x_ ||
713 !semantic_data || !nr_voxel_y_ || nr_voxel_z_ != 1) {
714 initialized_ = false;
715 return initialized_;
716 }
717
718 data_ = data;
719 semantic_data_ = semantic_data;
720 nr_points_ = nr_points;
721 nr_point_element_ = nr_point_element;
722
723 unsigned int nr_voxel = (nr_voxel_x_ * nr_voxel_y_);
724 unsigned int i, nd = 0;
725 int id, n = 0;
726
727 T voxel_width_x_rec = IRec(voxel_dim_[0]);
728 T voxel_width_y_rec = IRec(voxel_dim_[1]);
729
730 T bound_x_min = dim_x_[0];
731 T bound_x_max = dim_x_[1];
732 T bound_y_min = dim_y_[0];
733 T bound_y_max = dim_y_[1];
734 T bound_z_min = dim_z_[0];
735 T bound_z_max = dim_z_[1];
736
737 // clear the old index buffer
738 for (i = 0; i < nr_voxel; ++i) {
739 voxels_[i].indices_.clear();
740 }
741
742 // Assign point indices
743 for (; n < static_cast<int>(nr_points_); n++, nd += nr_point_element_) {
745 data_ + nd, bound_x_min, bound_x_max, bound_y_min, bound_y_max,
746 bound_z_min, bound_z_max, voxel_width_x_rec, voxel_width_y_rec,
747 static_cast<int>(nr_voxel_x_), static_cast<int>(nr_voxel_y_));
748
749 if (id >= 0) {
750 voxels_[id].indices_.push_back(n);
751 }
752 }
753
754 initialized_ = true;
755 return (initialized_);
756}
757
758template <typename T>
759bool VoxelGridXY<T>::SetS(const float *data, const int *semantic_data,
760 unsigned int nr_points, unsigned int nr_point_element) {
761 if (!data || !nr_points || !nr_point_element || !nr_voxel_x_ ||
762 !semantic_data || !nr_voxel_y_ || nr_voxel_z_ != 1) {
763 initialized_ = false;
764 return initialized_;
765 }
766
767 data_ = data;
768 semantic_data_ = semantic_data;
769 nr_points_ = nr_points;
770 nr_point_element_ = nr_point_element;
771
772 unsigned int nr_voxel = (nr_voxel_x_ * nr_voxel_y_);
773 unsigned int i, n = 0;
774 int id;
775
776 float voxel_width_x_rec = IRec(static_cast<float>(voxel_dim_[0]));
777 float voxel_width_y_rec = IRec(static_cast<float>(voxel_dim_[1]));
778
779 __m128i iv_nr_voxel_x = _mm_setr_epi32(static_cast<int>(nr_voxel_x_), 0,
780 static_cast<int>(nr_voxel_x_), 0);
781 __m128i iv_nr_voxel_x_m1 = _mm_set1_epi32(static_cast<int>(nr_voxel_x_ - 1));
782 __m128i iv_nr_voxel_y_m1 = _mm_set1_epi32(static_cast<int>(nr_voxel_y_ - 1));
783
784 __m128 v_width_x_rec = _mm_set_ps1(voxel_width_x_rec);
785 __m128 v_width_y_rec = _mm_set_ps1(voxel_width_y_rec);
786
787 __m128 v_x_min = _mm_set_ps1(dim_x_[0]);
788 __m128 v_x_max = _mm_set_ps1(dim_x_[1]);
789 __m128 v_y_min = _mm_set_ps1(dim_y_[0]);
790 __m128 v_y_max = _mm_set_ps1(dim_y_[1]);
791 __m128 v_z_min = _mm_set_ps1(dim_z_[0]);
792 __m128 v_z_max = _mm_set_ps1(dim_z_[1]);
793
794 __m128 v_cmp_x, v_cmp_y, v_cmp_z, v_in_roi;
795 v_in_roi = _mm_setr_ps(1.0, 1.0, 1.0, 1.0);
796
797 __m128 v_xs, v_ys, v_zs;
798 __m128i iv_indices, iv_x_indices, iv_y_indices, iv_v_indices_02,
799 iv_v_indices_13;
800
801 for (i = 0; i < nr_voxel; ++i) {
802 voxels_[i].indices_.clear();
803 }
804
805 unsigned int nr_loops = (nr_points >> 2);
806 unsigned int nr_fast_processed = (nr_loops << 2);
807 unsigned int remainder = nr_points - nr_fast_processed;
808
809 unsigned int d1 = nr_point_element;
810 unsigned int d2 = (nr_point_element << 1);
811 unsigned int d3 = d1 + d2;
812 unsigned int d4 = (nr_point_element << 2);
813
814 // xyz are required to be stored in continuous memory
815 const float *cptr_x = data;
816 const float *cptr_y = data + 1;
817 const float *cptr_z = data + 2;
818 const float *cptr_remainder = data + (nr_fast_processed * nr_point_element);
819
820 for (i = 0; i < nr_loops; ++i, n += 4) {
821 // Set memory
822 v_xs = _mm_setr_ps(cptr_x[0], cptr_x[d1], cptr_x[d2], cptr_x[d3]);
823 v_ys = _mm_setr_ps(cptr_y[0], cptr_y[d1], cptr_y[d2], cptr_y[d3]);
824 v_zs = _mm_setr_ps(cptr_z[0], cptr_z[d1], cptr_z[d2], cptr_z[d3]);
825
826 // compare range:
827 v_cmp_x =
828 _mm_and_ps(_mm_cmpge_ps(v_xs, v_x_min), _mm_cmple_ps(v_xs, v_x_max));
829 v_cmp_y =
830 _mm_and_ps(_mm_cmpge_ps(v_ys, v_y_min), _mm_cmple_ps(v_ys, v_y_max));
831 v_cmp_z =
832 _mm_and_ps(_mm_cmpge_ps(v_zs, v_z_min), _mm_cmple_ps(v_zs, v_z_max));
833 v_in_roi = _mm_and_ps(_mm_and_ps(v_cmp_x, v_cmp_y), v_cmp_z);
834
835 // vector operations, cast into signed integers
836 v_xs = _mm_sub_ps(v_xs, v_x_min);
837 v_xs = _mm_mul_ps(v_xs, v_width_x_rec);
838 iv_x_indices = _mm_cvttps_epi32(v_xs); // truncate towards zero
839 iv_x_indices = _mm_min_epi32(iv_nr_voxel_x_m1, iv_x_indices);
840
841 // vector operations, cast into signed integers
842 v_ys = _mm_sub_ps(v_ys, v_y_min);
843 v_ys = _mm_mul_ps(v_ys, v_width_y_rec);
844 iv_y_indices = _mm_cvttps_epi32(v_ys); // truncate towards zero
845 iv_y_indices = _mm_min_epi32(iv_nr_voxel_y_m1, iv_y_indices);
846
847 iv_v_indices_02 = _mm_mullo_epi32(iv_y_indices, iv_nr_voxel_x);
848 iv_y_indices = _mm_shuffle_epi32(iv_y_indices, _MM_SHUFFLE(2, 3, 0, 1));
849
850 iv_v_indices_13 = _mm_mullo_epi32(iv_y_indices, iv_nr_voxel_x);
851 iv_v_indices_13 =
852 _mm_shuffle_epi32(iv_v_indices_13, _MM_SHUFFLE(2, 3, 0, 1));
853
854 iv_indices = _mm_add_epi32(iv_v_indices_02, iv_v_indices_13);
855 iv_indices = _mm_add_epi32(iv_indices, iv_x_indices);
856
857 // store values from registers to memory
858 // address 16byte-aligned
859 _mm_store_ps(mem_aligned16_f32_, v_in_roi);
860 // address 16byte-aligned
861 _mm_store_si128(reinterpret_cast<__m128i *>(mem_aligned16_i32_),
862 iv_indices);
863
864 if (mem_aligned16_f32_[0] != 0) {
865 voxels_[mem_aligned16_i32_[0]].indices_.push_back(n);
866 }
867 if (mem_aligned16_f32_[1] != 0) {
868 voxels_[mem_aligned16_i32_[1]].indices_.push_back(n + 1);
869 }
870 if (mem_aligned16_f32_[2] != 0) {
871 voxels_[mem_aligned16_i32_[2]].indices_.push_back(n + 2);
872 }
873 if (mem_aligned16_f32_[3] != 0) {
874 voxels_[mem_aligned16_i32_[3]].indices_.push_back(n + 3);
875 }
876 cptr_x += d4;
877 cptr_y += d4;
878 cptr_z += d4;
879 }
880
881 // handling remaining points
882 for (i = 0; i < remainder; i++, n++) {
883 id = IAssignPointToVoxel(cptr_remainder, dim_x_[0], dim_x_[1], dim_y_[0],
884 dim_y_[1], dim_z_[0], dim_z_[1], voxel_width_x_rec,
885 voxel_width_y_rec, static_cast<int>(nr_voxel_x_),
886 static_cast<int>(nr_voxel_y_));
887
888 if (id >= 0) {
889 voxels_[id].indices_.push_back(n);
890 }
891
892 cptr_remainder += nr_point_element;
893 }
894
895 // for (i = 0; i < nr_voxel; ++i) {
896 // voxels_[i].indices_.clear();
897 // }
898 // for (i = 0; i < nr_points; i++, n++) {
899 // float x = data_[nr_point_element_ * i];
900 // float y = data_[nr_point_element_ * i + 1];
901 // float z = data_[nr_point_element_ * i + 2];
902 // id = AssignPointToVoxel(x, y, z, dim_x_[0], dim_x_[1], dim_y_[0], dim_y_[1], dim_z_[0], dim_z_[1],
903 // voxel_width_x_rec, voxel_width_y_rec, static_cast<int>(nr_voxel_x_), static_cast<int>(nr_voxel_y_));
904
905 // if (id >= 0) {
906 // voxels_[id].indices_.push_back(i);
907 // }
908 // }
909
910 initialized_ = true;
911 return (initialized_);
912}
913
914template <typename T>
915bool VoxelGridXY<T>::Set(const T *data, const int *semantic_data,
916 unsigned int nr_points, unsigned int nr_point_element,
917 unsigned int nr_voxel_x, unsigned int nr_voxel_y, T spatial_bound_x_min,
918 T spatial_bound_x_max, T spatial_bound_y_min, T spatial_bound_y_max,
919 T spatial_bound_z_min, T spatial_bound_z_max, bool force_bound) {
920 if (!data || !nr_points || !nr_point_element || !nr_voxel_x || !nr_voxel_y) {
921 initialized_ = false;
922 return initialized_;
923 }
924
925 data_ = data;
926 semantic_data_ = semantic_data;
927 nr_points_ = nr_points;
928 nr_point_element_ = nr_point_element;
929 nr_voxel_x_ = nr_voxel_x;
930 nr_voxel_y_ = nr_voxel_y;
931 nr_voxel_z_ = 1;
932
933 unsigned int i, j, k, n = 0, nd = 0;
934 unsigned int nr_voxel_xy = (nr_voxel_x_ * nr_voxel_y_);
935 unsigned int nr_voxel = nr_voxel_xy;
936 unsigned int nr_voxel_xm1 = nr_voxel_x - 1;
937 unsigned int nr_voxel_ym1 = nr_voxel_y - 1;
938 T vx, vy, vz, x, y, z;
939 T voxel_width_x, voxel_width_y, voxel_width_z;
940
941 voxels_.clear();
942 voxels_.resize(nr_voxel);
943
944 // if force_bound then the voxel grid dimesion is forced to be the manual
945 // * input
946 if (force_bound) {
947 dim_x_[0] = spatial_bound_x_min;
948 dim_x_[1] = spatial_bound_x_max;
949
950 dim_y_[0] = spatial_bound_y_min;
951 dim_y_[1] = spatial_bound_y_max;
952
953 dim_z_[0] = spatial_bound_z_min;
954 dim_z_[1] = spatial_bound_z_max;
955 } else {
957 data_, nr_points_, 0, nr_point_element_, &dim_x_[0], &dim_x_[1],
958 &dim_y_[0], &dim_y_[1], &dim_z_[0], &dim_z_[1], spatial_bound_x_min,
959 spatial_bound_x_max, spatial_bound_y_min, spatial_bound_y_max,
960 spatial_bound_z_min, spatial_bound_z_max);
961 }
962
963 T dim_x_min = dim_x_[0];
964 T dim_x_max = dim_x_[1];
965
966 T dim_y_min = dim_y_[0];
967 T dim_y_max = dim_y_[1];
968
969 T dim_z_min = dim_z_[0];
970 T dim_z_max = dim_z_[1];
971
972 T span_x = (dim_x_max - dim_x_min);
973 T span_y = (dim_y_max - dim_y_min);
974 T span_z = (dim_z_max - dim_z_min);
975
976 assert(span_x > 0 && span_y > 0 && span_z > 0);
977
978 voxel_dim_[0] = voxel_width_x = IDiv(span_x, static_cast<int>(nr_voxel_x_));
979 voxel_dim_[1] = voxel_width_y = IDiv(span_y, static_cast<int>(nr_voxel_y_));
980 voxel_dim_[2] = voxel_width_z = span_z;
981
982 T voxel_width_x_rec = IRec(voxel_dim_[0]);
983 T voxel_width_y_rec = IRec(voxel_dim_[1]);
984
985 std::vector<T> vxs(nr_voxel_x_);
986 vxs[0] = dim_x_[0];
987
988 for (i = 1; i < nr_voxel_x_; i++) {
989 vxs[i] = vxs[i - 1] + voxel_width_x;
990 }
991
992 vy = dim_y_[0];
993 vz = dim_z_[0];
994
995 for (j = 0; j < nr_voxel_y_; j++) {
996 for (k = 0; k < nr_voxel_x_; k++) {
997 vx = vxs[k];
998 voxels_[n++].init(vx, vy, vz, voxel_width_x, voxel_width_y, voxel_width_z,
999 static_cast<int>(k), static_cast<int>(j), 0);
1000 }
1001 vy += voxel_width_y;
1002 }
1003
1004 // Assign point indices
1005 for (; n < nr_points_; n++, nd += nr_point_element_) {
1006 x = data_[nd];
1007 y = data_[nd + 1];
1008 z = data_[nd + 2];
1009
1010 if (x < dim_x_min || x > dim_x_max || y < dim_y_min || y > dim_y_max ||
1011 z < dim_z_min || z > dim_z_max) {
1012 // points that are outside the defined BBOX are ignored
1013 continue;
1014 }
1015
1016 k = IMax((unsigned int)0,
1017 IMin(nr_voxel_xm1,
1018 (unsigned int)((x - dim_x_min) * voxel_width_x_rec)));
1019 j = IMax((unsigned int)0,
1020 IMin(nr_voxel_ym1,
1021 (unsigned int)((y - dim_y_min) * voxel_width_y_rec)));
1022 i = nr_voxel_x * j + k;
1023
1024 assert(i < nr_voxel);
1025 voxels_[i].indices_.push_back(n);
1026 }
1027 initialized_ = true;
1028 return initialized_;
1029}
1030
1031// template <typename T>
1032// int VoxelGridXY<T>::GetAllIndices(std::vector<int> &indices) const {
1033// unsigned int i, j;
1034// indices.clear();
1035
1036// if (!initialized_) {
1037// return -1;
1038// }
1039// for (i = 0; i < voxels_.size(); ++i) {
1040// for (j = 0; j < voxels_[i].indices_.size(); ++j) {
1041// indices.push_back(voxels_[i].indices_.at(j));
1042// }
1043// }
1044
1045// return static_cast<int> (indices.size());
1046// }
1047
1048template <typename T>
1050 if (!initialized_) {
1051 return 0;
1052 }
1053 unsigned int i, n = 0;
1054 for (i = 0; i < voxels_.size(); ++i) {
1055 n += voxels_[i].indices_.size();
1056 }
1057 return n;
1058}
1059
1060template <typename T>
1061static void IPushBackVectors(const std::vector<T> &src, std::vector<T> *dst) {
1062 unsigned int i = src.size();
1063 unsigned int j = dst->size();
1064
1065 if (i == 0) {
1066 return;
1067 } else if (j == 0) {
1068 dst->assign(src.begin(), src.end());
1069 } else {
1070 dst->resize(i + j);
1071 ICopy(src.data(), dst->data() + j, static_cast<int>(i));
1072 }
1073}
1074
1075// VoxelgridXY downsample functions
1076template <typename T>
1078 unsigned int dsf_dim_x, unsigned int dsf_dim_y) {
1079 if (!src.Initialized()) {
1080 return (false);
1081 } else if (dsf_dim_x == 0 && dsf_dim_y == 0) {
1082 *dst = src;
1083 return (true);
1084 } else {
1085 if (&src == dst) {
1086 return (false); // not allowed to downsample a voxel grid from itself
1087 }
1088 }
1089
1090 dst->CleanUp(); // perform CleanUp first
1091
1092 // # of voxels of the src voxel grid
1093 unsigned int nr_voxel_x_src = src.NrVoxelX();
1094 unsigned int nr_voxel_y_src = src.NrVoxelY();
1095 unsigned int nr_voxel_z_src = src.NrVoxelZ();
1096
1097 assert(nr_voxel_z_src == 1);
1098
1099 // scale factors
1100 unsigned int sf_x = (unsigned int)IPow((unsigned int)2, dsf_dim_x);
1101 unsigned int sf_y = (unsigned int)IPow((unsigned int)2, dsf_dim_y);
1102
1103 // compute the # of voxels for the new scale
1104 unsigned int nr_voxel_x_dst = nr_voxel_x_src / sf_x;
1105 unsigned int nr_voxel_y_dst = nr_voxel_y_src / sf_y;
1106 unsigned int nr_voxel_z_dst = nr_voxel_z_src;
1107
1108 if (!nr_voxel_x_dst || !nr_voxel_y_dst || !nr_voxel_z_dst) {
1109 return (false); // do not continue
1110 }
1111
1112 unsigned int nr_res_voxel_x_dst = (nr_voxel_x_src % sf_x);
1113 unsigned int nr_res_voxel_y_dst = (nr_voxel_y_src % sf_y);
1114
1115 T voxel_width_x_src = 0;
1116 T voxel_width_y_src = 0;
1117 T voxel_width_z_src = 0;
1118 T dim_min_x_src = 0;
1119 T dim_max_x_src = 0;
1120 T dim_min_y_src = 0;
1121 T dim_max_y_src = 0;
1122 T dim_min_z_src = 0;
1123 T dim_max_z_src = 0;
1124
1125 // the dimension of the voxels in the src voxel grid
1126 src.GetVoxelDimension(&voxel_width_x_src, &voxel_width_y_src,
1127 &voxel_width_z_src);
1128
1129 src.GetGridDimension(&dim_min_x_src, &dim_max_x_src, &dim_min_y_src,
1130 &dim_max_y_src, &dim_min_z_src, &dim_max_z_src);
1131
1132 // new voxel dimensions after downsampling the 3D grid
1133 T voxel_width_x_dst = (sf_x * voxel_width_x_src);
1134 T voxel_width_y_dst = (sf_y * voxel_width_y_src);
1135 T voxel_width_z_dst = voxel_width_z_src;
1136
1137 // new grid dimensions after downsampling the 3D grid
1138 T dim_x_dst[2], dim_y_dst[2], dim_z_dst[2];
1139
1140 dim_x_dst[0] = dim_min_x_src;
1141 dim_y_dst[0] = dim_min_y_src;
1142 dim_z_dst[0] = dim_min_z_src;
1143
1144 dim_x_dst[1] = (0 == nr_res_voxel_x_dst)
1145 ? dim_max_x_src
1146 : (voxel_width_x_dst * nr_voxel_x_dst + dim_x_dst[0]);
1147 dim_y_dst[1] = (0 == nr_res_voxel_y_dst)
1148 ? dim_max_y_src
1149 : (voxel_width_y_dst * nr_voxel_y_dst + dim_y_dst[0]);
1150 dim_z_dst[1] = dim_max_z_src;
1151
1152 // Set dst
1153 dst->SetNrPoints(src.NrPoints());
1155 dst->SetVoxelDimension(voxel_width_x_dst, voxel_width_y_dst,
1156 voxel_width_z_dst);
1157 dst->SetGridDimension(dim_x_dst[0], dim_x_dst[1], dim_y_dst[0], dim_y_dst[1],
1158 dim_z_dst[0], dim_z_dst[1]);
1159 dst->SetNrVoxel(nr_voxel_x_dst, nr_voxel_y_dst, nr_voxel_z_dst);
1160 dst->SetPointCloudsData(src.const_data());
1161
1162 unsigned int i, j, r, c, rs, cs, rspi, n = 0;
1163
1164 T vy, vz = dim_z_dst[0];
1165 std::vector<T> vxs(nr_voxel_x_dst);
1166
1167 vxs[0] = dim_x_dst[0];
1168
1169 for (i = 1; i < nr_voxel_x_dst; i++) {
1170 vxs[i] = vxs[i - 1] + voxel_width_x_dst;
1171 }
1172
1173 std::vector<Voxel<T>> voxels(nr_voxel_y_dst * nr_voxel_x_dst);
1174
1175 for (r = 0; r < nr_voxel_y_dst; r++) {
1176 rs = (r * sf_y);
1177 vy = dim_y_dst[0] + (r * voxel_width_y_dst);
1178
1179 for (c = 0; c < nr_voxel_x_dst; c++) {
1180 cs = (c * sf_x);
1181 voxels[n].init(vxs[c], vy, vz, voxel_width_x_dst, voxel_width_y_dst,
1182 voxel_width_z_dst, static_cast<int>(c),
1183 static_cast<int>(r), static_cast<int>(0));
1184 // collect samples from its lower scale:
1185 for (i = 0; i < sf_y; ++i) {
1186 rspi = rs + i;
1187 for (j = 0; j < sf_x; ++j) {
1188 IPushBackVectors(src(rspi, cs + j).indices_, &voxels[n].indices_);
1189 }
1190 }
1191 // increase voxel index by 1
1192 n++;
1193 }
1194 }
1195 dst->SetVoxels(voxels);
1196 dst->SetInitialized(true);
1197 return (true);
1198}
1199
1200// -----Multiscale Voxel Grid Pyramid-----
1201template <typename DATA_TYPE>
1203 public:
1205 VoxelGridXYPyramid(unsigned int nr_scale, unsigned int nr_voxel_x_base,
1206 unsigned int nr_voxel_y_base, unsigned int dsf_x,
1207 unsigned int dsf_y, DATA_TYPE spatial_bound_x_min,
1208 DATA_TYPE spatial_bound_x_max,
1209 DATA_TYPE spatial_bound_y_min,
1210 DATA_TYPE spatial_bound_y_max,
1211 DATA_TYPE spatial_bound_z_min,
1212 DATA_TYPE spatial_bound_z_max) {
1213 Alloc(nr_scale, nr_voxel_x_base, nr_voxel_y_base, dsf_x, dsf_y,
1214 spatial_bound_x_min, spatial_bound_x_max, spatial_bound_y_min,
1215 spatial_bound_y_max, spatial_bound_z_min, spatial_bound_z_max);
1216 }
1217
1218 void CleanUp();
1219
1221
1222 bool Alloc(unsigned int nr_scale, unsigned int nr_voxel_x_base,
1223 unsigned int nr_voxel_y_base, unsigned int dsf_x,
1224 unsigned int dsf_y, DATA_TYPE spatial_bound_x_min,
1225 DATA_TYPE spatial_bound_x_max, DATA_TYPE spatial_bound_y_min,
1226 DATA_TYPE spatial_bound_y_max, DATA_TYPE spatial_bound_z_min,
1227 DATA_TYPE spatial_bound_z_max);
1228
1229 // non-sse2 version
1230 bool Set(const DATA_TYPE *pc, unsigned int nr_points,
1231 unsigned int nr_point_element);
1232
1233 // the sse2 version - speed up the voxel grid construction, for float type
1234 // * points only
1235 bool SetS(const float *pc, unsigned int nr_points,
1236 unsigned int nr_point_element);
1237
1238 bool Set(const DATA_TYPE *pc, unsigned int nr_scale, unsigned int nr_points,
1239 unsigned int nr_point_element, unsigned int nr_voxel_x_base,
1240 unsigned int nr_voxel_y_base, unsigned int dsf_x, unsigned int dsf_y,
1241 DATA_TYPE spatial_bound_x_min, DATA_TYPE spatial_bound_x_max,
1242 DATA_TYPE spatial_bound_y_min, DATA_TYPE spatial_bound_y_max,
1243 DATA_TYPE spatial_bound_z_min, DATA_TYPE spatial_bound_z_max);
1244
1245 unsigned int NrScale() const { return (unsigned int)vgrids_.size(); }
1246
1247 unsigned int NrVoxel(unsigned int i = 0) const {
1248 return (i < vgrids_.size()) ? vgrids_[i].nr_voxel() : 0;
1249 }
1250
1251 unsigned int NrVoxelX(unsigned int i = 0) const {
1252 return (i < vgrids_.size()) ? vgrids_[i].nr_voxel_x() : 0;
1253 }
1254
1255 unsigned int NrVoxelY(unsigned int i = 0) const {
1256 return (i < vgrids_.size()) ? vgrids_[i].nr_voxel_y() : 0;
1257 }
1258
1259 unsigned int NrVoxelZ(unsigned int i = 0) const {
1260 return (i < vgrids_.size()) ? vgrids_[i].nr_voxel_z() : 0;
1261 }
1262
1263 unsigned int NrPoints(unsigned int scale) const {
1264 return (scale < vgrids_.size()) ? vgrids_[scale].nr_points() : 0;
1265 }
1266
1267 unsigned int NrPoints() const { return nr_points_; }
1268
1269 unsigned int NrPointElement() const { return nr_point_element_; }
1270
1271 bool Initialized() const;
1272
1273 unsigned int GetDsfX() const { return dsf_x_; }
1274 unsigned int GetDsfY() const { return dsf_y_; }
1275 unsigned int GetDsfZ() const { return (0); }
1276
1278 assert(i >= 0 && i < vgrids_.size());
1279 return vgrids_[i];
1280 }
1281
1282 const VoxelGridXY<DATA_TYPE> &operator[](unsigned int i) const {
1283 assert(i >= 0 && i < vgrids_.size());
1284 return vgrids_[i];
1285 }
1286
1288 assert(i >= 0 && i < static_cast<int>(vgrids_.size()));
1289 return vgrids_[i];
1290 }
1291
1293 assert(i >= 0 && i < static_cast<int>(vgrids_.size()));
1294 return vgrids_[i];
1295 }
1296
1297 const DATA_TYPE *ConstData() const { return pc_; }
1298
1299 DATA_TYPE *Data() { return pc_; }
1300
1301 private:
1302 unsigned int nr_points_, nr_point_element_;
1303 unsigned int dsf_x_, dsf_y_, dsf_z_;
1304 const DATA_TYPE *pc_;
1305 std::vector<VoxelGridXY<DATA_TYPE>> vgrids_;
1306};
1307
1308template <typename DATA_TYPE>
1310 : pc_(nullptr),
1311 nr_points_(0),
1312 nr_point_element_(0),
1313 dsf_x_(0),
1314 dsf_y_(0),
1315 dsf_z_(0) {}
1316
1317template <typename DATA_TYPE>
1319 unsigned int nr_scale, unsigned int nr_voxel_x_base,
1320 unsigned int nr_voxel_y_base, unsigned int dsf_x, unsigned int dsf_y,
1321 DATA_TYPE spatial_bound_x_min, DATA_TYPE spatial_bound_x_max,
1322 DATA_TYPE spatial_bound_y_min, DATA_TYPE spatial_bound_y_max,
1323 DATA_TYPE spatial_bound_z_min, DATA_TYPE spatial_bound_z_max) {
1324 if (!nr_scale || !nr_voxel_x_base || !nr_voxel_y_base) {
1325 return false;
1326 }
1327
1328 unsigned int scale;
1329 unsigned int nr_voxel_x = nr_voxel_x_base;
1330 unsigned int nr_voxel_y = nr_voxel_y_base;
1331 unsigned int sf_x = (unsigned int)IPow((unsigned int)2, dsf_x);
1332 unsigned int sf_y = (unsigned int)IPow((unsigned int)2, dsf_y);
1333
1334 dsf_x_ = dsf_x;
1335 dsf_y_ = dsf_y;
1336 dsf_z_ = 0;
1337
1338 vgrids_.clear();
1339 vgrids_.resize(nr_scale);
1340
1341 for (scale = 0; scale < nr_scale; ++scale) {
1342 if (!vgrids_[scale].alloc(nr_voxel_x, nr_voxel_y, spatial_bound_x_min,
1343 spatial_bound_x_max, spatial_bound_y_min,
1344 spatial_bound_y_max, spatial_bound_z_min,
1345 spatial_bound_z_max)) {
1346 break;
1347 }
1348 nr_voxel_x /= sf_x;
1349 nr_voxel_y /= sf_y;
1350 }
1351
1352 if (scale == 0) {
1353 vgrids_.clear();
1354 return false;
1355 } else {
1356 if (scale != nr_scale) {
1357 vgrids_.resize(scale);
1358 }
1359 }
1360
1361 return (true);
1362}
1363
1364template <typename DATA_TYPE>
1365bool VoxelGridXYPyramid<DATA_TYPE>::Set(const DATA_TYPE *pc,
1366 unsigned int nr_points,
1367 unsigned int nr_point_element) {
1368 if (!pc || !nr_points || !nr_point_element || vgrids_.empty()) {
1369 return false;
1370 }
1371
1372 unsigned int scale, nr_scale = (unsigned int)vgrids_.size();
1373
1374 pc_ = pc;
1375 nr_points_ = nr_points;
1376 nr_point_element_ = nr_point_element;
1377
1378 for (scale = 0; scale < nr_scale; ++scale) {
1379 if (!vgrids_[scale].set(pc, nr_points, nr_point_element)) {
1380 break;
1381 }
1382 }
1383
1384 // break in the middle - last (NrScale - s) grids are invalid
1385 if (scale < nr_scale) {
1386 vgrids_.resize(scale);
1387 }
1388
1389 return (vgrids_.size() == nr_scale);
1390}
1391
1392template <typename DATA_TYPE>
1394 unsigned int nr_points,
1395 unsigned int nr_point_element) {
1396 if (!pc || !nr_points || !nr_point_element || vgrids_.empty()) {
1397 return false;
1398 }
1399
1400 unsigned int scale, nr_scale = (unsigned int)vgrids_.size();
1401
1402 pc_ = pc;
1403 nr_points_ = nr_points;
1404 nr_point_element_ = nr_point_element;
1405
1406 for (scale = 0; scale < nr_scale; ++scale) {
1407 if (!vgrids_[scale].set_s(pc, nr_points, nr_point_element)) {
1408 break;
1409 }
1410 }
1411
1412 // break in the middle - last (NrScale - s) grids are invalid
1413 if (scale < nr_scale) {
1414 vgrids_.resize(scale);
1415 }
1416
1417 return (vgrids_.size() == nr_scale);
1418}
1419
1420template <typename DATA_TYPE>
1422 const DATA_TYPE *pc, unsigned int nr_scale, unsigned int nr_points,
1423 unsigned int nr_point_element, unsigned int nr_voxel_x_base,
1424 unsigned int nr_voxel_y_base, unsigned int dsf_x, unsigned int dsf_y,
1425 DATA_TYPE spatial_bound_x_min, DATA_TYPE spatial_bound_x_max,
1426 DATA_TYPE spatial_bound_y_min, DATA_TYPE spatial_bound_y_max,
1427 DATA_TYPE spatial_bound_z_min, DATA_TYPE spatial_bound_z_max) {
1428 if (!pc || !nr_scale || !nr_points || !nr_point_element || !nr_voxel_x_base ||
1429 !nr_voxel_y_base) {
1430 return false;
1431 }
1432
1433 unsigned int i, s;
1434 pc_ = pc;
1435 nr_points_ = nr_points;
1436 nr_point_element_ = nr_point_element;
1437
1438 dsf_x_ = dsf_x;
1439 dsf_y_ = dsf_y;
1440 dsf_z_ = 0;
1441
1442 vgrids_.clear();
1443 vgrids_.resize(nr_scale);
1444
1445 // Set the base level pyramid
1446 if (!vgrids_[0].set(pc_, nr_points, nr_point_element, nr_voxel_x_base,
1447 nr_voxel_y_base, spatial_bound_x_min, spatial_bound_x_max,
1448 spatial_bound_y_min, spatial_bound_y_max,
1449 spatial_bound_z_min, spatial_bound_z_max)) {
1450 vgrids_.clear();
1451 return false;
1452 }
1453
1454 for (s = 1; s < nr_scale; ++s) {
1455 if (!IDownsampleVoxelGridXY(vgrids_[s - 1], &vgrids_[s], dsf_x_, dsf_y_)) {
1456 break;
1457 }
1458 }
1459
1460 if (s < nr_scale) {
1461 for (i = 0; i < (nr_scale - s); ++i) {
1462 vgrids_.pop_back();
1463 }
1464 }
1465
1466 return (vgrids_.size() == nr_scale); // check if all scales are valid
1467}
1468
1469template <typename DATA_TYPE>
1471 pc_ = nullptr;
1472 vgrids_.clear();
1473 nr_points_ = nr_point_element_ = dsf_x_ = dsf_y_ = dsf_z_ = 0;
1474}
1475
1476template <typename DATA_TYPE>
1478 unsigned int i;
1479 if (vgrids_.empty()) {
1480 return false;
1481 }
1482 for (i = 0; i < vgrids_.size(); ++i) {
1483 if (!vgrids_[i].initialized()) {
1484 break;
1485 }
1486 }
1487 return (i == vgrids_.size());
1488}
1489
1490} // namespace algorithm
1491} // namespace perception
1492} // namespace apollo
const T * operator[](unsigned int i) const
Definition i_struct_s.h:95
PtCluster & operator=(const PtCluster< T, d > &c)
Definition i_struct_s.h:74
reference operator()(unsigned int i, unsigned int j)
Definition i_struct_s.h:101
const_reference operator()(unsigned int i, unsigned int j) const
Definition i_struct_s.h:106
static unsigned int PointsizeInByte()
Definition i_struct_s.h:46
PtCluster(const PtCluster< T, d > &c)
Definition i_struct_s.h:65
bool Alloc(unsigned int nr_scale, unsigned int nr_voxel_x_base, unsigned int nr_voxel_y_base, unsigned int dsf_x, unsigned int dsf_y, DATA_TYPE spatial_bound_x_min, DATA_TYPE spatial_bound_x_max, DATA_TYPE spatial_bound_y_min, DATA_TYPE spatial_bound_y_max, DATA_TYPE spatial_bound_z_min, DATA_TYPE spatial_bound_z_max)
unsigned int NrVoxel(unsigned int i=0) const
bool SetS(const float *pc, unsigned int nr_points, unsigned int nr_point_element)
unsigned int NrVoxelZ(unsigned int i=0) const
const VoxelGridXY< DATA_TYPE > & operator[](unsigned int i) const
unsigned int NrPoints(unsigned int scale) const
unsigned int NrVoxelX(unsigned int i=0) const
unsigned int NrVoxelY(unsigned int i=0) const
bool Set(const DATA_TYPE *pc, unsigned int nr_points, unsigned int nr_point_element)
VoxelGridXY< DATA_TYPE > & operator[](unsigned int i)
VoxelGridXY< DATA_TYPE > & operator[](int i)
const VoxelGridXY< DATA_TYPE > & operator[](int i) const
VoxelGridXYPyramid(unsigned int nr_scale, unsigned int nr_voxel_x_base, unsigned int nr_voxel_y_base, unsigned int dsf_x, unsigned int dsf_y, DATA_TYPE spatial_bound_x_min, DATA_TYPE spatial_bound_x_max, DATA_TYPE spatial_bound_y_min, DATA_TYPE spatial_bound_y_max, DATA_TYPE spatial_bound_z_min, DATA_TYPE spatial_bound_z_max)
Voxel< T > & operator()(unsigned int iy, unsigned int ix)
Definition i_struct_s.h:467
const Voxel< T > & operator[](unsigned int i) const
Definition i_struct_s.h:453
void SetGridDimension(T dim_min_x, T dim_max_x, T dim_min_y, T dim_max_y, T dim_min_z, T dim_max_z)
Definition i_struct_s.h:394
const Voxel< T > & operator()(unsigned int iy, unsigned int ix) const
Definition i_struct_s.h:474
VoxelGridXY & operator=(const VoxelGridXY< T > &vg)
Definition i_struct_s.h:305
bool Set(const T *data, const int *semantic_data, unsigned int nr_points, unsigned int nr_point_element)
Definition i_struct_s.h:710
const Voxel< T > & operator[](int i) const
Definition i_struct_s.h:462
bool GetVoxelDimension(T *voxel_width_x, T *voxel_width_y, T *voxel_width_z) const
Definition i_struct_s.h:404
void SetVoxelDimension(T voxel_width_x, T voxel_width_y, T voxel_width_z)
Definition i_struct_s.h:416
void SetNrPointElement(unsigned int nr_point_element)
Definition i_struct_s.h:424
void SetNrPoints(unsigned int nr_points)
Definition i_struct_s.h:422
bool GetGridDimension(T *dim_min_x, T *dim_max_x, T *dim_min_y, T *dim_max_y, T *dim_min_z, T *dim_max_z) const
Definition i_struct_s.h:378
bool Set(const T *data, const int *semantic_data, unsigned int nr_points, unsigned int nr_point_element, unsigned int nr_voxel_x, unsigned int nr_voxel_y, T spatial_bound_x_min, T spatial_bound_x_max, T spatial_bound_y_min, T spatial_bound_y_max, T spatial_bound_z_min, T spatial_bound_z_max, bool force_bound=true)
Definition i_struct_s.h:915
VoxelGridXY(unsigned int nr_voxel_x, unsigned int nr_voxel_y, T spatial_bound_x_min, T spatial_bound_x_max, T spatial_bound_y_min, T spatial_bound_y_max, T spatial_bound_z_min, T spatial_bound_z_max)
Definition i_struct_s.h:542
Voxel< T > & operator[](unsigned int i)
Definition i_struct_s.h:448
const std::vector< Voxel< T > > & GetConstVoxels() const
Definition i_struct_s.h:372
void SetVoxels(const std::vector< Voxel< T > > &voxels)
Definition i_struct_s.h:374
bool GetVoxelCoordinateXY(T x, T y, int *row, int *col) const
Definition i_struct_s.h:634
bool Alloc(unsigned int nr_voxel_x, unsigned int nr_voxel_y, T spatial_bound_x_min, T spatial_bound_x_max, T spatial_bound_y_min, T spatial_bound_y_max, T spatial_bound_z_min, T spatial_bound_z_max)
Definition i_struct_s.h:645
std::vector< Voxel< T > > & GetVoxels()
Definition i_struct_s.h:370
bool SetS(const float *data, const int *semantic_data, unsigned int nr_points, unsigned int nr_point_element)
Definition i_struct_s.h:759
void SetNrVoxel(unsigned int nr_voxel_x, unsigned int nr_voxel_y, unsigned int nr_voxel_z)
Definition i_struct_s.h:428
Voxel & operator=(const Voxel< T > &voxel)
Definition i_struct_s.h:227
void Init(T v_x, T v_y, T v_z, T dim_x, T dim_y, T dim_z, int ix, int iy, int iz)
Definition i_struct_s.h:252
void Init(const T *v, T dim_x, T dim_y, T dim_z, int ix, int iy, int iz)
Definition i_struct_s.h:241
Voxel(const Voxel< T > &voxel)
Definition i_struct_s.h:216
void Reserve(unsigned int size)
Definition i_struct_s.h:273
int AssignPointToVoxel(T xx, T yy, T zz, T bound_x_min, T bound_x_max, T bound_y_min, T bound_y_max, T bound_z_min, T bound_z_max, T voxel_width_x_rec, T voxel_width_y_rec, int nr_voxel_x, int nr_voxel_y)
Definition i_struct_s.h:186
void ICopy(const T *src, T *dst, int n)
Definition i_blas.h:27
int IAssignPointToVoxel(const T *data, T bound_x_min, T bound_x_max, T bound_y_min, T bound_y_max, T bound_z_min, T bound_z_max, T voxel_width_x_rec, T voxel_width_y_rec, int nr_voxel_x, int nr_voxel_y)
Definition i_struct_s.h:160
void ICopy3(const T src[3], T dst[3])
Definition i_blas.h:40
int IVerifyAlignment(const T *mem, int alignment_power=4)
Definition i_alloc.h:150
float IDiv(float a, float b)
Definition i_basic.h:35
float IPow(float a, float b)
Definition i_basic.h:142
void IGetPointcloudsDimWBound(const T *threeds, int n, int start_offset, int element_size, T *dim_min_x, T *dim_max_x, T *dim_min_y, T *dim_max_y, T *dim_min_z, T *dim_max_z, T bound_min_x, T bound_max_x, T bound_min_y, T bound_max_y, T bound_min_z, T bound_max_z)
Definition i_util.h:27
bool IDownsampleVoxelGridXY(const VoxelGridXY< T > &src, VoxelGridXY< T > *dst, unsigned int dsf_dim_x, unsigned int dsf_dim_y)
class register implement
Definition arena_queue.h:37
FORCE_INLINE __m128 _mm_sub_ps(__m128 a, __m128 b)
Definition sse2neon.h:2963
FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a)
Definition sse2neon.h:6110
float32x4_t __m128
Definition sse2neon.h:307
FORCE_INLINE __m128i _mm_add_epi32(__m128i a, __m128i b)
Definition sse2neon.h:3113
FORCE_INLINE __m128 _mm_setr_ps(float w, float z, float y, float x)
Definition sse2neon.h:2629
FORCE_INLINE __m128 _mm_cmpge_ps(__m128 a, __m128 b)
Definition sse2neon.h:1252
FORCE_INLINE __m128i _mm_set1_epi32(int)
Definition sse2neon.h:5378
FORCE_INLINE __m128i _mm_setr_epi32(int i3, int i2, int i1, int i0)
Definition sse2neon.h:5444
FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b)
Definition sse2neon.h:2299
FORCE_INLINE __m128i _mm_cvttps_epi32(__m128 a)
Definition sse2neon.h:4479
FORCE_INLINE __m128 _mm_cmple_ps(__m128 a, __m128 b)
Definition sse2neon.h:1294
FORCE_INLINE __m128 _mm_set_ps1(float)
Definition sse2neon.h:2544
FORCE_INLINE __m128i _mm_min_epi32(__m128i a, __m128i b)
Definition sse2neon.h:8102
FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b)
Definition sse2neon.h:1183
FORCE_INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b)
Definition sse2neon.h:8295
#define _MM_SHUFFLE(fp3, fp2, fp1, fp0)
MACRO for shuffle parameter for _mm_shuffle_ps().
Definition sse2neon.h:247
int64x2_t __m128i
Definition sse2neon.h:316
FORCE_INLINE void _mm_store_ps(float *p, __m128 a)
Definition sse2neon.h:2833
#define _mm_shuffle_epi32(a, imm)
Definition sse2neon.h:5524