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