sampling.h
Go to the documentation of this file.
1 // Copyright 2017 Nicolas Mellado
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // -------------------------------------------------------------------------- //
16 //
17 // Authors: Nicolas Mellado, Dror Aiger
18 //
19 // An implementation of the Super 4-points Congruent Sets (Super 4PCS)
20 // algorithm presented in:
21 //
22 // Super 4PCS: Fast Global Pointcloud Registration via Smart Indexing
23 // Nicolas Mellado, Dror Aiger, Niloy J. Mitra
24 // Symposium on Geometry Processing 2014.
25 //
26 // Data acquisition in large-scale scenes regularly involves accumulating
27 // information across multiple scans. A common approach is to locally align scan
28 // pairs using Iterative Closest Point (ICP) algorithm (or its variants), but
29 // requires static scenes and small motion between scan pairs. This prevents
30 // accumulating data across multiple scan sessions and/or different acquisition
31 // modalities (e.g., stereo, depth scans). Alternatively, one can use a global
32 // registration algorithm allowing scans to be in arbitrary initial poses. The
33 // state-of-the-art global registration algorithm, 4PCS, however has a quadratic
34 // time complexity in the number of data points. This vastly limits its
35 // applicability to acquisition of large environments. We present Super 4PCS for
36 // global pointcloud registration that is optimal, i.e., runs in linear time (in
37 // the number of data points) and is also output sensitive in the complexity of
38 // the alignment problem based on the (unknown) overlap across scan pairs.
39 // Technically, we map the algorithm as an 'instance problem' and solve it
40 // efficiently using a smart indexing data organization. The algorithm is
41 // simple, memory-efficient, and fast. We demonstrate that Super 4PCS results in
42 // significant speedup over alternative approaches and allows unstructured
43 // efficient acquisition of scenes at scales previously not possible. Complete
44 // source code and datasets are available for research use at
45 // http://geometry.cs.ucl.ac.uk/projects/2014/super4PCS/.
46 
47 #ifndef _PCS_UTILS_H_
48 #define _PCS_UTILS_H_
49 
50 #ifdef WIN32
51 #undef NO_DATA
52 #endif
53 
54 #include <vector>
55 #include <array>
56 #include <gr/utils/shared.h>
57 
58 namespace gr {
59 
60 #ifdef PARSED_BY_DOXYGEN
61 template<typename PointType>
63  template <typename InputRange, typename OutputRange, class Options>
64  void operator() (const InputRange& /*inputset*/,
65  const Options& /*options*/,
66  OutputRange& /*output*/) const{}
67 };
68 #endif
69 
70 template<typename PointType>
72 #ifdef PARSED_BY_DOXYGEN
73  : public SamplerConcept<PointType>
74 #endif
75 {
76 private:
77  template <typename _Point>
78  class HashTable {
79  public:
80  using Point = _Point;
81  using Scalar = typename Point::Scalar;
82 
83  private:
84  const uint64_t MAGIC1 = 100000007;
85  const uint64_t MAGIC2 = 161803409;
86  const uint64_t MAGIC3 = 423606823;
87  const uint64_t NO_DATA = 0xffffffffu;
88  Scalar voxel_;
89  Scalar scale_;
90  using VoxelType = std::array<int,3>;
91  std::vector<VoxelType> voxels_;
92  std::vector<uint64_t> data_;
93 
94  public:
95  HashTable(int maxpoints, Scalar voxel) : voxel_(voxel), scale_(1.0f / voxel) {
96  uint64_t n = maxpoints;
97  voxels_.resize(n);
98  data_.resize(n, NO_DATA);
99  }
100  template <typename Point>
101  uint64_t& operator[](const Point& p) {
102  // TODO: use eigen power here.
103  VoxelType c {int(floor(p.pos()(0) * scale_)), /* TODO */
104  int(floor(p.pos()(1) * scale_)),
105  int(floor(p.pos()(2) * scale_))};
106 
107  uint64_t key = (MAGIC1 * c[0] + MAGIC2 * c[1] + MAGIC3 * c[2]) % data_.size();
108  while (1) {
109  if (data_[key] == NO_DATA) {
110  voxels_[key] = c;
111  break;
112  } else if (voxels_[key] == c) {
113  break;
114  }
115  key++;
116  if (key == data_.size()) key = 0;
117  }
118  return data_[key];
119  }
120  }; // end of class definition HashTable
121 
122  public:
123  template <typename InputRange, typename OutputRange, class Options>
124  inline
125  void operator() (const InputRange& inputset,
126  const Options& options,
127  OutputRange& output) const {
128  int num_input = inputset.size();
129  output.clear();
130  HashTable<PointType> hash(num_input, options.delta);
131 
132  for(const auto& p : inputset) {
133  uint64_t& ind = hash[PointType(p)];
134  if (ind >= uint64_t(num_input)) {
135  output.push_back( p );
136  ind = output.size();
137  }
138  }
139  }
140 };
141 
142 
143 } // namespace gr
144 
145 
146 #endif
Definition: sampling.h:71
CongruentSetExplorationBase< Traits, PointType, TransformVisitor, PairFilteringFunctor, OptExts... >::Scalar ComputeTransformation(const InputRange1 &P, const InputRange2 &Q, Eigen::Ref< typename CongruentSetExplorationBase< Traits, PointType, TransformVisitor, PairFilteringFunctor, OptExts... >::MatrixType > transformation, const Sampler< PointType > &sampler, TransformVisitor &v)
Definition: congruentSetExplorationBase.hpp:61
void operator()(const InputRange &inputset, const Options &options, OutputRange &output) const
Definition: sampling.h:125