normalset.h
Go to the documentation of this file.
1 // Copyright 2014 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
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 
48 #ifndef _OPENGR_ACCELERATORS_INDEXED_NORMAL_SET_H_
49 #define _OPENGR_ACCELERATORS_INDEXED_NORMAL_SET_H_
50 
51 #include "gr/utils/disablewarnings.h"
52 #include "gr/accelerators/utils.h"
53 
54 #include <vector>
55 #include <array>
56 #include <cmath> //log2
57 
58 namespace gr{
59 
60 /*!
61  Normal set indexed by a position in euclidean space.
62  The size used to hash euclidean coordinates is defined at runtime.
63  The size used to hash the normals in an euclidean cell is defined at compile
64  time
65 
66  Loops over dimensions used to compute index values are unrolled at compile
67  time.
68  */
69 template <
70  class Point, //! <\brief Type of point to work with
71  int dim, //! <\brief Number of dimension in ambient space
72  int _ngSize, //! <\brief Normal grid size in 1 dimension
73  typename _Scalar //! <\brief Scalar type
74  >
76  typedef std::array< std::vector<unsigned int>,
78 
80  using Scalar = _Scalar;
82 
83 #ifdef DEBUG
84 #define VALIDATE_INDICES true
85 #pragma message "Index validation is enabled in debug mode"
86 #else
87 #define VALIDATE_INDICES false
88 #endif
89 
90 private:
91  const Scalar _nepsilon;
92  std::vector<AngularGrid*> _grid;
93  Scalar _epsilon;
94  int _egSize; //! <\brief Size of the euclidean grid for each dimension
95 
96  /// Get the index corresponding to position p \warning Bounds are not tested
97  inline int indexPos ( const Point& p) const;
98  /// Get the index corresponding to normal n \warning Bounds are not tested
99  inline int indexNormal( const Point& n) const;
100 
101  /// Get the coordinates corresponding to position p \warning Bounds are not tested
102  inline Point coordinatesPos ( const Point& p) const
103  { return p/_epsilon; }
104  /// Get the index corresponding to normal n \warning Bounds are not tested
105  inline Point coordinatesNormal( const Point& n) const
106  {
107  static const Point half = Point::Ones()/Scalar(2.);
108  return (n/Scalar(2.) + half)/_nepsilon;
109  }
110 
111  /// Get the coordinates corresponding to position p \warning Bounds are not tested
112  inline int indexCoordinatesPos ( const Point& pCoord) const;
113  /// Get the index corresponding to normal n \warning Bounds are not tested
114  inline int indexCoordinatesNormal( const Point& nCoord) const;
115 
116  //inline Point indexToPos (int id) const;
117 
118 public:
119  inline IndexedNormalSet(const Scalar epsilon)
120  : _nepsilon(Scalar(1.)/Scalar(_ngSize) + 0.00001),
121  _epsilon(epsilon)
122  {
123  /// We need to check if epsilon is a power of two and correct it if needed
124  const int gridDepth = -std::log2(epsilon);
125  _egSize = std::pow(2,gridDepth);
126  _epsilon = 1.f/_egSize;
127 
128  _grid = std::vector<AngularGrid*> (std::pow(_egSize, dim), NULL);
129  }
130 
131  virtual inline ~IndexedNormalSet();
132 
133  //! \brief Add a new couple pos/normal, and its associated id
134  inline bool addElement(const Point& pos,
135  const Point& normal,
136  unsigned int id);
137 
138  //! \return NULL if the grid does not exist or p is out of bound
139  inline AngularGrid* angularGrid(const Point& p) {
140  const int pId = indexPos(p);
141  if (pId == -1) return NULL;
142  return _grid[pId];
143  }
144 
145  //! \return the Angular Grid contained in p cell + its n*n neighb
147  std::vector<AngularGrid*> buf;
148  const int pId = indexPos(p);
149  if (pId != -1) {
150  gr::Utils::OneRingNeighborhood neiFun;
151  NeiIdsBox arr;
152  neiFun.get<dim>( pId, _egSize, arr );
153  buf.reserve(arr.size());
154  for (auto& id : arr){
155  if ( id != -1 && _grid[id] != nullptr){
156  buf.push_back(_grid[id]);
157  }
158  }
159  }
160  return buf;
161  }
162 
163  //! Get closest points in euclidean space
164  inline void getNeighbors( const Point& p,
165  std::vector<unsigned int>&nei);
166  //! Get closest points in euclidean an normal space
167  inline void getNeighbors( const Point& p,
168  const Point& n,
169  std::vector<unsigned int>&nei);
170  //! Get closest poitns in euclidean an normal space with angular deviation
171  inline void getNeighbors( const Point& p,
172  const Point& n,
173  Scalar alpha,
174  std::vector<unsigned int>&nei,
175  bool tryReverse = false);
176 };
177 
178 } // namespace gr
179 
180 #include "gr/accelerators/normalset.hpp"
181 
182 #endif // _INDEXED_NORMAL_SET_H_
bool addElement(const Point &pos, const Point &normal, unsigned int id)
Add a new couple pos/normal, and its associated id.
Definition: normalset.hpp:113
IndexedNormalSet(const Scalar epsilon)
Definition: normalset.h:119
Definition: normalset.h:79
AngularGrid * angularGrid(const Point &p)
Definition: normalset.h:139
MOVE_DIR
Definition: normalset.h:79
virtual ~IndexedNormalSet()
Definition: normalset.hpp:59
Definition: normalset.h:79
void getNeighbors(const Point &p, std::vector< unsigned int > &nei)
Get closest points in euclidean space.
Definition: normalset.hpp:145
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 getNeighbors(const Point &p, const Point &n, Scalar alpha, std::vector< unsigned int > &nei, bool tryReverse=false)
Get closest poitns in euclidean an normal space with angular deviation.
Definition: normalset.hpp:177
std::vector< AngularGrid * > angularGrids(const Point &p)
Definition: normalset.h:146