match4pcsBase.hpp
Go to the documentation of this file.
1 //
2 // Created by Sandra Alfaro on 24/05/18.
3 //
4 
5 #include <vector>
6 #include <chrono>
7 #include <atomic>
8 #include <Eigen/Geometry> // MatrixBase.homogeneous()
9 #include <Eigen/SVD>
10 #include <Eigen/Core> // Transform.computeRotationScaling()
11 
12 
13 #ifdef OpenGR_USE_OPENMP
14 #include <omp.h>
15 #endif
16 
17 #include "gr/utils/sampling.h"
18 #include "gr/utils/shared.h"
19 #include "gr/utils/logger.h"
20 #include "gr/accelerators/kdtree.h"
21 #include "match4pcsBase.h"
22 
23 #ifdef TEST_GLOBAL_TIMINGS
24 # include "gr/utils/timer.h"
25 #endif
26 
27 
28 namespace gr {
29  template <template <typename, typename, typename> class _Functor,
30  typename PointType,
31  typename TransformVisitor,
32  typename PairFilteringFunctor,
33  template < class, class > class PFO>
35  , const Utils::Logger& logger)
38  {
39  }
40 
41  template <template <typename, typename, typename> class _Functor,
42  typename PointType,
43  typename TransformVisitor,
44  typename PairFilteringFunctor,
45  template < class, class > class PFO>
47 
48  template <template <typename, typename, typename> class _Functor,
49  typename PointType,
50  typename TransformVisitor,
51  typename PairFilteringFunctor,
52  template < class, class > class PFO>
54  typename PointType::Scalar &invariant1,
55  typename PointType::Scalar &invariant2,
56  int &id1, int &id2, int &id3, int &id4) {
57 
59  int best1, best2, best3, best4;
60  best1 = best2 = best3 = best4 = -1;
61  for (int i = 0; i < 4; ++i) {
62  for (int j = 0; j < 4; ++j) {
63  if (i == j) continue;
64  int k = 0;
65  while (k == i || k == j) k++;
66  int l = 0;
67  while (l == i || l == j || l == k) l++;
70  // Compute the closest points on both segments, the corresponding
71  // invariants and the distance between the closest points.
76  // Retail the smallest distance and the best order so far.
79  best1 = i;
80  best2 = j;
81  best3 = k;
82  best4 = l;
85  }
86  }
87  }
88 
89  if(best1 < 0 || best2 < 0 || best3 < 0 || best4 < 0 ) return false;
90 
96 
98  id1 = tmpId[best1];
99  id2 = tmpId[best2];
100  id3 = tmpId[best3];
101  id4 = tmpId[best4];
102 
103  return true;
104  }
105 
106  template <template <typename, typename, typename> class _Functor,
107  typename PointType,
108  typename TransformVisitor,
109  typename PairFilteringFunctor,
110  template < class, class > class PFO>
114  int& base1, int& base2, int& base3, int& base4) {
115 
116  const Scalar kBaseTooSmall (0.2);
117  int current_trial = 0;
118 
119  // Try fix number of times.
121  // Select a triangle if possible. otherwise fail.
123  return false;
124  }
125 
126  const auto& b0 = *(MatchBaseType::base_3D_[0] = &MatchBaseType::sampled_P_3D_[base1]);
127  const auto& b1 = *(MatchBaseType::base_3D_[1] = &MatchBaseType::sampled_P_3D_[base2]);
128  const auto& b2 = *(MatchBaseType::base_3D_[2] = &MatchBaseType::sampled_P_3D_[base3]);
129 
130  // The 4th point will be a one that is close to be planar to the other 3
131  // while still not too close to them.
132  const double x1 = b0.pos()(0);
133  const double y1 = b0.pos()(1);
134  const double z1 = b0.pos()(2);
135  const double x2 = b1.pos()(0);
136  const double y2 = b1.pos()(1);
137  const double z2 = b1.pos()(2);
138  const double x3 = b2.pos()(0);
139  const double y3 = b2.pos()(1);
140  const double z3 = b2.pos()(2);
141 
142  // Fit a plan.
143  Scalar denom = (-x3 * y2 * z1 + x2 * y3 * z1 + x3 * y1 * z2 - x1 * y3 * z2 -
144  x2 * y1 * z3 + x1 * y2 * z3);
145 
146  if (denom != 0) {
147  Scalar A =
148  (-y2 * z1 + y3 * z1 + y1 * z2 - y3 * z2 - y1 * z3 + y2 * z3) / denom;
149  Scalar B =
150  (x2 * z1 - x3 * z1 - x1 * z2 + x3 * z2 + x1 * z3 - x2 * z3) / denom;
151  Scalar C =
152  (-x2 * y1 + x3 * y1 + x1 * y2 - x3 * y2 - x1 * y3 + x2 * y3) / denom;
153  base4 = -1;
155  // Go over all points in P.
157  for (unsigned int i = 0; i < MatchBaseType::sampled_P_3D_.size(); ++i) {
158  const auto &p = MatchBaseType::sampled_P_3D_[i];
159  if ((p.pos() - b0.pos()).squaredNorm() >= too_small &&
160  (p.pos() - b1.pos()).squaredNorm() >= too_small &&
161  (p.pos() - b2.pos()).squaredNorm() >= too_small) {
162  // Not too close to any of the first 3.
163  const Scalar distance =
164  std::abs(A * p.pos()(0) + B * p.pos()(1) + C * p.pos()(2) - 1.0);
165  // Search for the most planar.
166  if (distance < best_distance) {
168  base4 = int(i);
169  }
170  }
171  }
172  // If we have a good one we can quit.
173  if (base4 != -1) {
176  return true;
177  }
178  }
179  current_trial++;
180  }
181 
182  // We failed to find good enough base..
183  return false;
184  }
185 
186  template <template <typename, typename, typename> class _Functor,
187  typename PointType,
188  typename TransformVisitor,
189  typename PairFilteringFunctor,
190  template < class, class > class PFO>
191  // Initialize all internal data structures and data members.
193  fun_.Initialize();
194  }
195 
196 
197  template <template <typename, typename, typename> class _Functor,
198  typename PointType,
199  typename TransformVisitor,
200  typename PairFilteringFunctor,
201  template < class, class > class PFO>
204 // std::cout << "------------------" << std::endl;
206 
207  if(!initBase(base, invariant1, invariant2)) return false;
208 
209 // std::cout << "Found a new base !" << std::endl;
210  const auto& b0 = *MatchBaseType::base_3D_[0];
211  const auto& b1 = *MatchBaseType::base_3D_[1];
212  const auto& b2 = *MatchBaseType::base_3D_[2];
213  const auto& b3 = *MatchBaseType::base_3D_[3];
214 
215  // Computes distance between pairs.
216  const Scalar distance1 = (b0.pos()- b1.pos()).norm();
217  const Scalar distance2 = (b2.pos()- b3.pos()).norm();
218 
219  std::vector<std::pair<int, int>> pairs1, pairs2;
220 
221  // Compute normal angles.
222  const Scalar normal_angle1 = (b0.normal() - b1.normal()).norm();
223  const Scalar normal_angle2 = (b2.normal() - b3.normal()).norm();
224 
227 
228 
229 // std::cout << "Pair set 1 has " << pairs1.size() << " elements" << std::endl;
230 // std::cout << "Pair set 2 has " << pairs2.size() << " elements" << std::endl;
231 
232 // Log<LogLevel::Verbose>( "Pair creation ouput: ", pairs1.size(), " - ", pairs2.size());
233 
234  if (pairs1.size() == 0 || pairs2.size() == 0) {
235  return false;
236  }
237 
241  pairs1,
242  pairs2,
243  &congruent_quads)) {
244  return false;
245  }
246 
247  return true;
248  }
249 
250  template <template <typename, typename, typename> class _Functor,
251  typename PointType,
252  typename TransformVisitor,
253  typename PairFilteringFunctor,
254  template < class, class > class PFO>
256  {
257  Scalar invariant1, invariant2; // dummy
258 
260  }
261 
262  template <template <typename, typename, typename> class _Functor,
263  typename PointType,
264  typename TransformVisitor,
265  typename PairFilteringFunctor,
266  template < class, class > class PFO>
268  {
269  #ifdef STATIC_BASE
270  static bool first_time = true;
271 
272  if (first_time){
273  std::cerr << "Warning: Running with static base" << std::endl;
274  base[0] = 0;
275  base[1] = 3;
276  base[2] = 1;
277  base[3] = 4;
278 
284 
285  first_time = false;
286  }
287  else
288  return false;
289 
290  #else
291  if (!SelectQuadrilateral(invariant1, invariant2, base[0], base[1], base[2], base[3])) {
292  // std::cout << "Skipping wrong base" << std::endl;
293  return false;
294  }
295  #endif
296 
297  return true;
298  }
299 
300 
301  template <template <typename, typename, typename> class _Functor,
302  typename PointType,
303  typename TransformVisitor,
304  typename PairFilteringFunctor,
305  template < class, class > class PFO>
308  const VectorType& p1, const VectorType& p2,
309  const VectorType& q1, const VectorType& q2,
311 
312  static const Scalar kSmallNumber = 0.0001;
313  VectorType u = p2 - p1;
314  VectorType v = q2 - q1;
315  VectorType w = p1 - q1;
316  Scalar a = u.dot(u);
317  Scalar b = u.dot(v);
318  Scalar c = v.dot(v);
319  Scalar d = u.dot(w);
320  Scalar e = v.dot(w);
321  Scalar f = a * c - b * b;
322  // s1,s2 and t1,t2 are the parametric representation of the intersection.
323  // they will be the invariants at the end of this simple computation.
324  Scalar s1 = 0.0;
325  Scalar s2 = f;
326  Scalar t1 = 0.0;
327  Scalar t2 = f;
328 
329  if (f < kSmallNumber) {
330  s1 = 0.0;
331  s2 = 1.0;
332  t1 = e;
333  t2 = c;
334  } else {
335  s1 = (b * e - c * d);
336  t1 = (a * e - b * d);
337  if (s1 < 0.0) {
338  s1 = 0.0;
339  t1 = e;
340  t2 = c;
341  } else if (s1 > s2) {
342  s1 = s2;
343  t1 = e + b;
344  t2 = c;
345  }
346  }
347 
348  if (t1 < 0.0) {
349  t1 = 0.0;
350  if (-d < 0.0)
351  s1 = 0.0;
352  else if (-d > a)
353  s1 = s2;
354  else {
355  s1 = -d;
356  s2 = a;
357  }
358  } else if (t1 > t2) {
359  t1 = t2;
360  if ((-d + b) < 0.0)
361  s1 = 0;
362  else if ((-d + b) > a)
363  s1 = s2;
364  else {
365  s1 = (-d + b);
366  s2 = a;
367  }
368  }
369  invariant1 = (std::abs(s1) < kSmallNumber ? 0.0 : s1 / s2);
370  invariant2 = (std::abs(t1) < kSmallNumber ? 0.0 : t1 / t2);
371 
372  return ( w + (invariant1 * u) - (invariant2 * v)).norm();
373  }
374 }
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