Point Cloud Library (PCL)  1.8.0
sac_model_cone.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2009-2012, Willow Garage, Inc.
6  * Copyright (c) 2012-, Open Perception, Inc.
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of the copyright holder(s) nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  */
38 
39 #ifndef PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_CONE_H_
40 #define PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_CONE_H_
41 
42 #include <pcl/sample_consensus/eigen.h>
43 #include <pcl/sample_consensus/sac_model_cone.h>
44 #include <pcl/common/concatenate.h>
45 
46 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
47 template <typename PointT, typename PointNT> bool
49 {
50  return (true);
51 }
52 
53 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54 template <typename PointT, typename PointNT> bool
56  const std::vector<int> &samples, Eigen::VectorXf &model_coefficients)
57 {
58  // Need 3 samples
59  if (samples.size () != 3)
60  {
61  PCL_ERROR ("[pcl::SampleConsensusModelCone::computeModelCoefficients] Invalid set of samples given (%lu)!\n", samples.size ());
62  return (false);
63  }
64 
65  if (!normals_)
66  {
67  PCL_ERROR ("[pcl::SampleConsensusModelCone::computeModelCoefficients] No input dataset containing normals was given!\n");
68  return (false);
69  }
70 
71  Eigen::Vector4f p1 (input_->points[samples[0]].x, input_->points[samples[0]].y, input_->points[samples[0]].z, 0);
72  Eigen::Vector4f p2 (input_->points[samples[1]].x, input_->points[samples[1]].y, input_->points[samples[1]].z, 0);
73  Eigen::Vector4f p3 (input_->points[samples[2]].x, input_->points[samples[2]].y, input_->points[samples[2]].z, 0);
74 
75  Eigen::Vector4f n1 (normals_->points[samples[0]].normal[0], normals_->points[samples[0]].normal[1], normals_->points[samples[0]].normal[2], 0);
76  Eigen::Vector4f n2 (normals_->points[samples[1]].normal[0], normals_->points[samples[1]].normal[1], normals_->points[samples[1]].normal[2], 0);
77  Eigen::Vector4f n3 (normals_->points[samples[2]].normal[0], normals_->points[samples[2]].normal[1], normals_->points[samples[2]].normal[2], 0);
78 
79  //calculate apex (intersection of the three planes defined by points and belonging normals
80  Eigen::Vector4f ortho12 = n1.cross3(n2);
81  Eigen::Vector4f ortho23 = n2.cross3(n3);
82  Eigen::Vector4f ortho31 = n3.cross3(n1);
83 
84  float denominator = n1.dot(ortho23);
85 
86  float d1 = p1.dot (n1);
87  float d2 = p2.dot (n2);
88  float d3 = p3.dot (n3);
89 
90  Eigen::Vector4f apex = (d1 * ortho23 + d2 * ortho31 + d3 * ortho12) / denominator;
91 
92  //compute axis (normal of plane defined by: { apex+(p1-apex)/(||p1-apex||), apex+(p2-apex)/(||p2-apex||), apex+(p3-apex)/(||p3-apex||)}
93  Eigen::Vector4f ap1 = p1 - apex;
94  Eigen::Vector4f ap2 = p2 - apex;
95  Eigen::Vector4f ap3 = p3 - apex;
96 
97  Eigen::Vector4f np1 = apex + (ap1/ap1.norm ());
98  Eigen::Vector4f np2 = apex + (ap2/ap2.norm ());
99  Eigen::Vector4f np3 = apex + (ap3/ap3.norm ());
100 
101  Eigen::Vector4f np1np2 = np2 - np1;
102  Eigen::Vector4f np1np3 = np3 - np1;
103 
104  Eigen::Vector4f axis_dir = np1np2.cross3 (np1np3);
105  axis_dir.normalize ();
106 
107  // normalize the vector (apex->p) for opening angle calculation
108  ap1.normalize ();
109  ap2.normalize ();
110  ap3.normalize ();
111 
112  //compute opening angle
113  float opening_angle = ( acosf (ap1.dot (axis_dir)) + acosf (ap2.dot (axis_dir)) + acosf (ap3.dot (axis_dir)) ) / 3.0f;
114 
115  model_coefficients.resize (7);
116  // model_coefficients.template head<3> () = line_pt.template head<3> ();
117  model_coefficients[0] = apex[0];
118  model_coefficients[1] = apex[1];
119  model_coefficients[2] = apex[2];
120  // model_coefficients.template segment<3> (3) = line_dir.template head<3> ();
121  model_coefficients[3] = axis_dir[0];
122  model_coefficients[4] = axis_dir[1];
123  model_coefficients[5] = axis_dir[2];
124  // cone radius
125  model_coefficients[6] = opening_angle;
126 
127  if (model_coefficients[6] != -std::numeric_limits<double>::max() && model_coefficients[6] < min_angle_)
128  return (false);
129  if (model_coefficients[6] != std::numeric_limits<double>::max() && model_coefficients[6] > max_angle_)
130  return (false);
131 
132  return (true);
133 }
134 
135 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
136 template <typename PointT, typename PointNT> void
138  const Eigen::VectorXf &model_coefficients, std::vector<double> &distances)
139 {
140  // Check if the model is valid given the user constraints
141  if (!isModelValid (model_coefficients))
142  {
143  distances.clear ();
144  return;
145  }
146 
147  distances.resize (indices_->size ());
148 
149  Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0);
150  Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0);
151  float opening_angle = model_coefficients[6];
152 
153  float apexdotdir = apex.dot (axis_dir);
154  float dirdotdir = 1.0f / axis_dir.dot (axis_dir);
155  // Iterate through the 3d points and calculate the distances from them to the cone
156  for (size_t i = 0; i < indices_->size (); ++i)
157  {
158  Eigen::Vector4f pt (input_->points[(*indices_)[i]].x, input_->points[(*indices_)[i]].y, input_->points[(*indices_)[i]].z, 0);
159  Eigen::Vector4f n (normals_->points[(*indices_)[i]].normal[0], normals_->points[(*indices_)[i]].normal[1], normals_->points[(*indices_)[i]].normal[2], 0);
160 
161  // Calculate the point's projection on the cone axis
162  float k = (pt.dot (axis_dir) - apexdotdir) * dirdotdir;
163  Eigen::Vector4f pt_proj = apex + k * axis_dir;
164  Eigen::Vector4f dir = pt - pt_proj;
165  dir.normalize ();
166 
167  // Calculate the actual radius of the cone at the level of the projected point
168  Eigen::Vector4f height = apex - pt_proj;
169  float actual_cone_radius = tanf (opening_angle) * height.norm ();
170  height.normalize ();
171 
172  // Calculate the cones perfect normals
173  Eigen::Vector4f cone_normal = sinf (opening_angle) * height + cosf (opening_angle) * dir;
174 
175  // Aproximate the distance from the point to the cone as the difference between
176  // dist(point,cone_axis) and actual cone radius
177  double d_euclid = fabs (pointToAxisDistance (pt, model_coefficients) - actual_cone_radius);
178 
179  // Calculate the angular distance between the point normal and the (dir=pt_proj->pt) vector
180  double d_normal = fabs (getAngle3D (n, cone_normal));
181  d_normal = (std::min) (d_normal, M_PI - d_normal);
182 
183  distances[i] = fabs (normal_distance_weight_ * d_normal + (1 - normal_distance_weight_) * d_euclid);
184  }
185 }
186 
187 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
188 template <typename PointT, typename PointNT> void
190  const Eigen::VectorXf &model_coefficients, const double threshold, std::vector<int> &inliers)
191 {
192  // Check if the model is valid given the user constraints
193  if (!isModelValid (model_coefficients))
194  {
195  inliers.clear ();
196  return;
197  }
198 
199  int nr_p = 0;
200  inliers.resize (indices_->size ());
201  error_sqr_dists_.resize (indices_->size ());
202 
203  Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0);
204  Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0);
205  float opening_angle = model_coefficients[6];
206 
207  float apexdotdir = apex.dot (axis_dir);
208  float dirdotdir = 1.0f / axis_dir.dot (axis_dir);
209  // Iterate through the 3d points and calculate the distances from them to the cone
210  for (size_t i = 0; i < indices_->size (); ++i)
211  {
212  Eigen::Vector4f pt (input_->points[(*indices_)[i]].x, input_->points[(*indices_)[i]].y, input_->points[(*indices_)[i]].z, 0);
213  Eigen::Vector4f n (normals_->points[(*indices_)[i]].normal[0], normals_->points[(*indices_)[i]].normal[1], normals_->points[(*indices_)[i]].normal[2], 0);
214 
215  // Calculate the point's projection on the cone axis
216  float k = (pt.dot (axis_dir) - apexdotdir) * dirdotdir;
217  Eigen::Vector4f pt_proj = apex + k * axis_dir;
218 
219  // Calculate the direction of the point from center
220  Eigen::Vector4f pp_pt_dir = pt - pt_proj;
221  pp_pt_dir.normalize ();
222 
223  // Calculate the actual radius of the cone at the level of the projected point
224  Eigen::Vector4f height = apex - pt_proj;
225  double actual_cone_radius = tan(opening_angle) * height.norm ();
226  height.normalize ();
227 
228  // Calculate the cones perfect normals
229  Eigen::Vector4f cone_normal = sinf (opening_angle) * height + cosf (opening_angle) * pp_pt_dir;
230 
231  // Aproximate the distance from the point to the cone as the difference between
232  // dist(point,cone_axis) and actual cone radius
233  double d_euclid = fabs (pointToAxisDistance (pt, model_coefficients) - actual_cone_radius);
234 
235  // Calculate the angular distance between the point normal and the (dir=pt_proj->pt) vector
236  double d_normal = fabs (getAngle3D (n, cone_normal));
237  d_normal = (std::min) (d_normal, M_PI - d_normal);
238 
239  double distance = fabs (normal_distance_weight_ * d_normal + (1 - normal_distance_weight_) * d_euclid);
240 
241  if (distance < threshold)
242  {
243  // Returns the indices of the points whose distances are smaller than the threshold
244  inliers[nr_p] = (*indices_)[i];
245  error_sqr_dists_[nr_p] = distance;
246  ++nr_p;
247  }
248  }
249  inliers.resize (nr_p);
250  error_sqr_dists_.resize (nr_p);
251 }
252 
253 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
254 template <typename PointT, typename PointNT> int
256  const Eigen::VectorXf &model_coefficients, const double threshold)
257 {
258 
259  // Check if the model is valid given the user constraints
260  if (!isModelValid (model_coefficients))
261  return (0);
262 
263  int nr_p = 0;
264 
265  Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0);
266  Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0);
267  float opening_angle = model_coefficients[6];
268 
269  float apexdotdir = apex.dot (axis_dir);
270  float dirdotdir = 1.0f / axis_dir.dot (axis_dir);
271  // Iterate through the 3d points and calculate the distances from them to the cone
272  for (size_t i = 0; i < indices_->size (); ++i)
273  {
274  Eigen::Vector4f pt (input_->points[(*indices_)[i]].x, input_->points[(*indices_)[i]].y, input_->points[(*indices_)[i]].z, 0);
275  Eigen::Vector4f n (normals_->points[(*indices_)[i]].normal[0], normals_->points[(*indices_)[i]].normal[1], normals_->points[(*indices_)[i]].normal[2], 0);
276 
277  // Calculate the point's projection on the cone axis
278  float k = (pt.dot (axis_dir) - apexdotdir) * dirdotdir;
279  Eigen::Vector4f pt_proj = apex + k * axis_dir;
280 
281  // Calculate the direction of the point from center
282  Eigen::Vector4f pp_pt_dir = pt - pt_proj;
283  pp_pt_dir.normalize ();
284 
285  // Calculate the actual radius of the cone at the level of the projected point
286  Eigen::Vector4f height = apex - pt_proj;
287  double actual_cone_radius = tan(opening_angle) * height.norm ();
288  height.normalize ();
289 
290  // Calculate the cones perfect normals
291  Eigen::Vector4f cone_normal = sinf (opening_angle) * height + cosf (opening_angle) * pp_pt_dir;
292 
293  // Aproximate the distance from the point to the cone as the difference between
294  // dist(point,cone_axis) and actual cone radius
295  double d_euclid = fabs (pointToAxisDistance (pt, model_coefficients) - actual_cone_radius);
296 
297  // Calculate the angular distance between the point normal and the (dir=pt_proj->pt) vector
298  double d_normal = fabs (getAngle3D (n, cone_normal));
299  d_normal = (std::min) (d_normal, M_PI - d_normal);
300 
301  if (fabs (normal_distance_weight_ * d_normal + (1 - normal_distance_weight_) * d_euclid) < threshold)
302  nr_p++;
303  }
304  return (nr_p);
305 }
306 
307 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
308 template <typename PointT, typename PointNT> void
310  const std::vector<int> &inliers, const Eigen::VectorXf &model_coefficients, Eigen::VectorXf &optimized_coefficients)
311 {
312  optimized_coefficients = model_coefficients;
313 
314  // Needs a set of valid model coefficients
315  if (model_coefficients.size () != 7)
316  {
317  PCL_ERROR ("[pcl::SampleConsensusModelCone::optimizeModelCoefficients] Invalid number of model coefficients given (%lu)!\n", model_coefficients.size ());
318  return;
319  }
320 
321  if (inliers.empty ())
322  {
323  PCL_DEBUG ("[pcl::SampleConsensusModelCone:optimizeModelCoefficients] Inliers vector empty! Returning the same coefficients.\n");
324  return;
325  }
326 
327  tmp_inliers_ = &inliers;
328 
329  OptimizationFunctor functor (static_cast<int> (inliers.size ()), this);
330  Eigen::NumericalDiff<OptimizationFunctor > num_diff (functor);
331  Eigen::LevenbergMarquardt<Eigen::NumericalDiff<OptimizationFunctor>, float> lm (num_diff);
332  int info = lm.minimize (optimized_coefficients);
333 
334  // Compute the L2 norm of the residuals
335  PCL_DEBUG ("[pcl::SampleConsensusModelCone::optimizeModelCoefficients] LM solver finished with exit code %i, having a residual norm of %g. \nInitial solution: %g %g %g %g %g %g %g \nFinal solution: %g %g %g %g %g %g %g\n",
336  info, lm.fvec.norm (), model_coefficients[0], model_coefficients[1], model_coefficients[2], model_coefficients[3],
337  model_coefficients[4], model_coefficients[5], model_coefficients[6], optimized_coefficients[0], optimized_coefficients[1], optimized_coefficients[2], optimized_coefficients[3], optimized_coefficients[4], optimized_coefficients[5], optimized_coefficients[6]);
338 
339  Eigen::Vector3f line_dir (optimized_coefficients[3], optimized_coefficients[4], optimized_coefficients[5]);
340  line_dir.normalize ();
341  optimized_coefficients[3] = line_dir[0];
342  optimized_coefficients[4] = line_dir[1];
343  optimized_coefficients[5] = line_dir[2];
344 }
345 
346 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
347 template <typename PointT, typename PointNT> void
349  const std::vector<int> &inliers, const Eigen::VectorXf &model_coefficients, PointCloud &projected_points, bool copy_data_fields)
350 {
351  // Needs a valid set of model coefficients
352  if (model_coefficients.size () != 7)
353  {
354  PCL_ERROR ("[pcl::SampleConsensusModelCone::projectPoints] Invalid number of model coefficients given (%lu)!\n", model_coefficients.size ());
355  return;
356  }
357 
358  projected_points.header = input_->header;
359  projected_points.is_dense = input_->is_dense;
360 
361  Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0);
362  Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0);
363  float opening_angle = model_coefficients[6];
364 
365  float apexdotdir = apex.dot (axis_dir);
366  float dirdotdir = 1.0f / axis_dir.dot (axis_dir);
367 
368  // Copy all the data fields from the input cloud to the projected one?
369  if (copy_data_fields)
370  {
371  // Allocate enough space and copy the basics
372  projected_points.points.resize (input_->points.size ());
373  projected_points.width = input_->width;
374  projected_points.height = input_->height;
375 
376  typedef typename pcl::traits::fieldList<PointT>::type FieldList;
377  // Iterate over each point
378  for (size_t i = 0; i < projected_points.points.size (); ++i)
379  // Iterate over each dimension
380  pcl::for_each_type <FieldList> (NdConcatenateFunctor <PointT, PointT> (input_->points[i], projected_points.points[i]));
381 
382  // Iterate through the 3d points and calculate the distances from them to the cone
383  for (size_t i = 0; i < inliers.size (); ++i)
384  {
385  Eigen::Vector4f pt (input_->points[inliers[i]].x,
386  input_->points[inliers[i]].y,
387  input_->points[inliers[i]].z,
388  1);
389 
390  float k = (pt.dot (axis_dir) - apexdotdir) * dirdotdir;
391 
392  pcl::Vector4fMap pp = projected_points.points[inliers[i]].getVector4fMap ();
393  pp.matrix () = apex + k * axis_dir;
394 
395  Eigen::Vector4f dir = pt - pp;
396  dir.normalize ();
397 
398  // Calculate the actual radius of the cone at the level of the projected point
399  Eigen::Vector4f height = apex - pp;
400  float actual_cone_radius = tanf (opening_angle) * height.norm ();
401 
402  // Calculate the projection of the point onto the cone
403  pp += dir * actual_cone_radius;
404  }
405  }
406  else
407  {
408  // Allocate enough space and copy the basics
409  projected_points.points.resize (inliers.size ());
410  projected_points.width = static_cast<uint32_t> (inliers.size ());
411  projected_points.height = 1;
412 
413  typedef typename pcl::traits::fieldList<PointT>::type FieldList;
414  // Iterate over each point
415  for (size_t i = 0; i < inliers.size (); ++i)
416  // Iterate over each dimension
417  pcl::for_each_type <FieldList> (NdConcatenateFunctor <PointT, PointT> (input_->points[inliers[i]], projected_points.points[i]));
418 
419  // Iterate through the 3d points and calculate the distances from them to the cone
420  for (size_t i = 0; i < inliers.size (); ++i)
421  {
422  pcl::Vector4fMap pp = projected_points.points[i].getVector4fMap ();
423  pcl::Vector4fMapConst pt = input_->points[inliers[i]].getVector4fMap ();
424 
425  float k = (pt.dot (axis_dir) - apexdotdir) * dirdotdir;
426  // Calculate the projection of the point on the line
427  pp.matrix () = apex + k * axis_dir;
428 
429  Eigen::Vector4f dir = pt - pp;
430  dir.normalize ();
431 
432  // Calculate the actual radius of the cone at the level of the projected point
433  Eigen::Vector4f height = apex - pp;
434  float actual_cone_radius = tanf (opening_angle) * height.norm ();
435 
436  // Calculate the projection of the point onto the cone
437  pp += dir * actual_cone_radius;
438  }
439  }
440 }
441 
442 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
443 template <typename PointT, typename PointNT> bool
445  const std::set<int> &indices, const Eigen::VectorXf &model_coefficients, const double threshold)
446 {
447  // Needs a valid model coefficients
448  if (model_coefficients.size () != 7)
449  {
450  PCL_ERROR ("[pcl::SampleConsensusModelCone::doSamplesVerifyModel] Invalid number of model coefficients given (%lu)!\n", model_coefficients.size ());
451  return (false);
452  }
453 
454  Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0);
455  Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0);
456  float openning_angle = model_coefficients[6];
457 
458  float apexdotdir = apex.dot (axis_dir);
459  float dirdotdir = 1.0f / axis_dir.dot (axis_dir);
460 
461  // Iterate through the 3d points and calculate the distances from them to the cone
462  for (std::set<int>::const_iterator it = indices.begin (); it != indices.end (); ++it)
463  {
464  Eigen::Vector4f pt (input_->points[*it].x, input_->points[*it].y, input_->points[*it].z, 0);
465 
466  // Calculate the point's projection on the cone axis
467  float k = (pt.dot (axis_dir) - apexdotdir) * dirdotdir;
468  Eigen::Vector4f pt_proj = apex + k * axis_dir;
469  Eigen::Vector4f dir = pt - pt_proj;
470  dir.normalize ();
471 
472  // Calculate the actual radius of the cone at the level of the projected point
473  Eigen::Vector4f height = apex - pt_proj;
474  double actual_cone_radius = tan (openning_angle) * height.norm ();
475 
476  // Aproximate the distance from the point to the cone as the difference between
477  // dist(point,cone_axis) and actual cone radius
478  if (fabs (static_cast<double>(pointToAxisDistance (pt, model_coefficients) - actual_cone_radius)) > threshold)
479  return (false);
480  }
481 
482  return (true);
483 }
484 
485 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
486 template <typename PointT, typename PointNT> double
488  const Eigen::Vector4f &pt, const Eigen::VectorXf &model_coefficients)
489 {
490  Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0);
491  Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0);
492  return sqrt(pcl::sqrPointToLineDistance (pt, apex, axis_dir));
493 }
494 
495 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
496 template <typename PointT, typename PointNT> bool
497 pcl::SampleConsensusModelCone<PointT, PointNT>::isModelValid (const Eigen::VectorXf &model_coefficients)
498 {
499  if (!SampleConsensusModel<PointT>::isModelValid (model_coefficients))
500  return (false);
501 
502  // Check against template, if given
503  if (eps_angle_ > 0.0)
504  {
505  // Obtain the cone direction
506  Eigen::Vector4f coeff;
507  coeff[0] = model_coefficients[3];
508  coeff[1] = model_coefficients[4];
509  coeff[2] = model_coefficients[5];
510  coeff[3] = 0;
511 
512  Eigen::Vector4f axis (axis_[0], axis_[1], axis_[2], 0);
513  double angle_diff = fabs (getAngle3D (axis, coeff));
514  angle_diff = (std::min) (angle_diff, M_PI - angle_diff);
515  // Check whether the current cone model satisfies our angle threshold criterion with respect to the given axis
516  if (angle_diff > eps_angle_)
517  return (false);
518  }
519 
520  if (model_coefficients[6] != -std::numeric_limits<double>::max() && model_coefficients[6] < min_angle_)
521  return (false);
522  if (model_coefficients[6] != std::numeric_limits<double>::max() && model_coefficients[6] > max_angle_)
523  return (false);
524 
525  return (true);
526 }
527 
528 #define PCL_INSTANTIATE_SampleConsensusModelCone(PointT, PointNT) template class PCL_EXPORTS pcl::SampleConsensusModelCone<PointT, PointNT>;
529 
530 #endif // PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_CONE_H_
531 
bool computeModelCoefficients(const std::vector< int > &samples, Eigen::VectorXf &model_coefficients)
Check whether the given index samples can form a valid cone model, compute the model coefficients fro...
double getAngle3D(const Eigen::Vector4f &v1, const Eigen::Vector4f &v2, const bool in_degree=false)
Compute the smallest angle between two 3D vectors in radians (default) or degree. ...
Definition: common.hpp:46
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:410
double pointToAxisDistance(const Eigen::Vector4f &pt, const Eigen::VectorXf &model_coefficients)
Get the distance from a point to a line (represented by a point and a direction)
void optimizeModelCoefficients(const std::vector< int > &inliers, const Eigen::VectorXf &model_coefficients, Eigen::VectorXf &optimized_coefficients)
Recompute the cone coefficients using the given inlier set and return them to the user...
bool isSampleGood(const std::vector< int > &samples) const
Check if a sample of indices results in a good sample of points indices.
const Eigen::Map< const Eigen::Vector4f, Eigen::Aligned > Vector4fMapConst
uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:415
bool doSamplesVerifyModel(const std::set< int > &indices, const Eigen::VectorXf &model_coefficients, const double threshold)
Verify whether a subset of indices verifies the given cone model coefficients.
uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:413
SampleConsensusModel represents the base model class.
Definition: sac_model.h:66
double sqrPointToLineDistance(const Eigen::Vector4f &pt, const Eigen::Vector4f &line_pt, const Eigen::Vector4f &line_dir)
Get the square distance from a point to a line (represented by a point and a direction) ...
Definition: distances.h:69
void selectWithinDistance(const Eigen::VectorXf &model_coefficients, const double threshold, std::vector< int > &inliers)
Select all the points which respect the given model coefficients as inliers.
virtual bool isModelValid(const Eigen::VectorXf &model_coefficients)
Check whether a model is valid given the user constraints.
void getDistancesToModel(const Eigen::VectorXf &model_coefficients, std::vector< double > &distances)
Compute all distances from the cloud data to a given cone model.
PointCloud represents the base class in PCL for storing collections of 3D points. ...
pcl::PCLHeader header
The point cloud header.
Definition: point_cloud.h:407
void projectPoints(const std::vector< int > &inliers, const Eigen::VectorXf &model_coefficients, PointCloud &projected_points, bool copy_data_fields=true)
Create a new point cloud with inliers projected onto the cone model.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values).
Definition: point_cloud.h:418
Eigen::Map< Eigen::Vector4f, Eigen::Aligned > Vector4fMap
Helper functor structure for concatenate.
Definition: concatenate.h:64
virtual int countWithinDistance(const Eigen::VectorXf &model_coefficients, const double threshold)
Count all the points which respect the given model coefficients as inliers.