Point Cloud Library (PCL)  1.15.1
sac_model_torus.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, 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  * $Id$
38  *
39  */
40 
41 #pragma once
42 
43 #include <pcl/common/distances.h>
44 #include <pcl/sample_consensus/model_types.h>
45 #include <pcl/sample_consensus/sac_model.h>
46 
47 namespace pcl {
48 
49 /** \brief @b SampleConsensusModelTorus defines a model for 3D torus segmentation.
50  * The model coefficients are defined as:
51  * - \b radii.inner : the torus's inner radius
52  * - \b radii.outer : the torus's outer radius
53  * - \b torus_center_point.x : the X coordinate of the center of the torus
54  * - \b torus_center_point.y : the Y coordinate of the center of the torus
55  * - \b torus_center_point.z : the Z coordinate of the center of the torus
56  * - \b torus_normal.x : the X coordinate of the normal of the torus
57  * - \b torus_normal.y : the Y coordinate of the normal of the torus
58  * - \b torus_normal.z : the Z coordinate of the normal of the torus
59  *
60  * \author lasdasdas
61  * \ingroup sample_consensus
62  */
63 template <typename PointT, typename PointNT>
65 : public SampleConsensusModel<PointT>,
66  public SampleConsensusModelFromNormals<PointT, PointNT> {
75 
79 
80 public:
81  using Ptr = shared_ptr<SampleConsensusModelTorus<PointT, PointNT>>;
82  using ConstPtr = shared_ptr<const SampleConsensusModelTorus<PointT, PointNT>>;
83 
84  /** \brief Constructor for base SampleConsensusModelTorus.
85  * \param[in] cloud the input point cloud dataset
86  * \param[in] random if true set the random seed to the current time, else set to
87  * 12345 (default: false)
88  */
89  SampleConsensusModelTorus(const PointCloudConstPtr& cloud, bool random = false)
90  : SampleConsensusModel<PointT>(cloud, random)
92  {
93  model_name_ = "SampleConsensusModelTorus";
94  sample_size_ = 4;
95  model_size_ = 8;
96  }
97 
98  /** \brief Constructor for base SampleConsensusModelTorus.
99  * \param[in] cloud the input point cloud dataset
100  * \param[in] indices a vector of point indices to be used from \a cloud
101  * \param[in] random if true set the random seed to the current time, else set to
102  * 12345 (default: false)
103  */
105  const Indices& indices,
106  bool random = false)
107  : SampleConsensusModel<PointT>(cloud, indices, random)
109  {
110  model_name_ = "SampleConsensusModelTorus";
111  sample_size_ = 4;
112  model_size_ = 8;
113  }
114 
115  /** \brief Copy constructor.
116  * \param[in] source the model to copy into this
117  */
120  {
121  *this = source;
122  model_name_ = "SampleConsensusModelTorus";
123  }
124 
125  /** \brief Empty destructor */
126  ~SampleConsensusModelTorus() override = default;
127 
128  /** \brief Copy constructor.
129  * \param[in] source the model to copy into this
130  */
133  {
135  return (*this);
136  }
137  /** \brief Check whether the given index samples can form a valid torus model, compute
138  * the model coefficients from these samples and store them in model_coefficients. The
139  * torus coefficients are: radii, torus_center_point, torus_normal.
140  * \param[in] samples the point indices found as possible good candidates for creating a valid model
141  * \param[out] model_coefficients the resultant model coefficients
142  */
143  bool
144  computeModelCoefficients(const Indices& samples,
145  Eigen::VectorXf& model_coefficients) const override;
146 
147  /** \brief Compute all distances from the cloud data to a given torus model.
148  * \param[in] model_coefficients the coefficients of a torus model that we need to compute distances to
149  * \param[out] distances the resultant estimated distances
150  */
151  void
152  getDistancesToModel(const Eigen::VectorXf& model_coefficients,
153  std::vector<double>& distances) const override;
154 
155  /** \brief Select all the points which respect the given model coefficients as
156  * inliers.
157  * \param[in] model_coefficients the coefficients of a torus model that we need to compute distances to
158  * \param[in] threshold a maximum admissible distance threshold for determining the inliers from the outliers
159  * \param[out] inliers the
160  * resultant model inliers
161  */
162  void
163  selectWithinDistance(const Eigen::VectorXf& model_coefficients,
164  const double threshold,
165  Indices& inliers) override;
166 
167  /** \brief Count all the points which respect the given model coefficients as inliers.
168  *
169  * \param[in] model_coefficients the coefficients of a model that we need to compute distances to
170  * \param[in] threshold maximum admissible distance threshold for
171  * determining the inliers from the outliers \return the resultant number of inliers
172  */
173  std::size_t
174  countWithinDistance(const Eigen::VectorXf& model_coefficients,
175  const double threshold) const override;
176 
177  /** \brief Recompute the torus coefficients using the given inlier set and return them
178  * to the user.
179  * \param[in] inliers the data inliers found as supporting the model
180  * \param[in] model_coefficients the initial guess for the optimization
181  * \param[out] optimized_coefficients the resultant recomputed coefficients after
182  * non-linear optimization
183  */
184  void
185  optimizeModelCoefficients(const Indices& inliers,
186  const Eigen::VectorXf& model_coefficients,
187  Eigen::VectorXf& optimized_coefficients) const override;
188 
189  /** \brief Create a new point cloud with inliers projected onto the torus model.
190  * \param[in] inliers the data inliers that we want to project on the torus model
191  * \param[in] model_coefficients the coefficients of a torus model
192  * \param[out] projected_points the resultant projected points
193  * \param[in] copy_data_fields set to true if we need to copy the other data fields
194  */
195  void
196  projectPoints(const Indices& inliers,
197  const Eigen::VectorXf& model_coefficients,
198  PointCloud& projected_points,
199  bool copy_data_fields = true) const override;
200 
201  /** \brief Verify whether a subset of indices verifies the given torus model
202  * coefficients.
203  * \param[in] indices the data indices that need to be tested against the torus model
204  * \param[in] model_coefficients the torus model coefficients
205  * \param[in] threshold a maximum admissible distance threshold for determining the
206  * inliers from the outliers
207  */
208  bool
209  doSamplesVerifyModel(const std::set<index_t>& indices,
210  const Eigen::VectorXf& model_coefficients,
211  const double threshold) const override;
212 
213  /** \brief Return a unique id for this model (SACMODEL_TORUS). */
214  inline pcl::SacModel
215  getModelType() const override
216  {
217  return (SACMODEL_TORUS);
218  }
219 
220 protected:
223 
224  /** \brief Project a point onto a torus given by its model coefficients (radii,
225  * torus_center_point, torus_normal)
226  * \param[in] pt the input point to project
227  * \param[in] model_coefficients the coefficients of the torus (radii, torus_center_point, torus_normal)
228  * \param[out] pt_proj the resultant projected point
229  */
230  void
231  projectPointToTorus(const Eigen::Vector3f& pt,
232  const Eigen::Vector3f& pt_n,
233  const Eigen::VectorXf& model_coefficients,
234  Eigen::Vector3f& pt_proj) const;
235 
236  /** \brief Check whether a model is valid given the user constraints.
237  * \param[in] model_coefficients the set of model coefficients
238  */
239  bool
240  isModelValid(const Eigen::VectorXf& model_coefficients) const override;
241 
242  /** \brief Check if a sample of indices results in a good sample of points
243  * indices. Pure virtual.
244  * \param[in] samples the resultant index samples
245  */
246  bool
247  isSampleGood(const Indices& samples) const override;
248 
249 private:
250  struct OptimizationFunctor : pcl::Functor<double> {
251  /** Functor constructor
252  * \param[in] indices the indices of data points to evaluate
253  * \param[in] estimator pointer to the estimator object
254  */
255  OptimizationFunctor(const pcl::SampleConsensusModelTorus<PointT, PointNT>* model,
256  const Indices& indices)
257  : pcl::Functor<double>(indices.size()), model_(model), indices_(indices)
258  {}
259 
260  /** Cost function to be minimized
261  * \param[in] x the variables array
262  * \param[out] fvec the resultant functions evaluations
263  * \return 0
264  */
265  int
266  operator()(const Eigen::VectorXd& xs, Eigen::VectorXd& fvec) const
267  {
268  // Getting constants from state vector
269  const double& R = xs[0];
270  const double& r = xs[1];
271 
272  const double& x0 = xs[2];
273  const double& y0 = xs[3];
274  const double& z0 = xs[4];
275 
276  const Eigen::Vector3d centroid{x0, y0, z0};
277 
278  const double& nx = xs[5];
279  const double& ny = xs[6];
280  const double& nz = xs[7];
281 
282  const Eigen::Vector3d n1{0.0, 0.0, 1.0};
283  const Eigen::Vector3d n2 = Eigen::Vector3d{nx, ny, nz}.normalized();
284 
285  for (size_t j = 0; j < indices_.size(); j++) {
286 
287  size_t i = indices_[j];
288  const Eigen::Vector3d pt =
289  (*model_->input_)[i].getVector3fMap().template cast<double>();
290 
291  Eigen::Vector3d pte{pt - centroid};
292 
293  // Transposition is inversion
294  // Using Quaternions instead of Rodrigues
295  pte = Eigen::Quaterniond()
296  .setFromTwoVectors(n1, n2)
297  .toRotationMatrix()
298  .transpose() *
299  pte;
300 
301  const double& x = pte[0];
302  const double& y = pte[1];
303  const double& z = pte[2];
304 
305  fvec[j] = (std::pow(sqrt(x * x + y * y) - R, 2) + z * z - r * r);
306  }
307  return 0;
308  }
309 
311  const Indices& indices_;
312  };
313 };
314 } // namespace pcl
315 
316 #ifdef PCL_NO_PRECOMPILE
317 #include <pcl/sample_consensus/impl/sac_model_torus.hpp>
318 #endif
void selectWithinDistance(const Eigen::VectorXf &model_coefficients, const double threshold, Indices &inliers) override
Select all the points which respect the given model coefficients as inliers.
void projectPoints(const Indices &inliers, const Eigen::VectorXf &model_coefficients, PointCloud &projected_points, bool copy_data_fields=true) const override
Create a new point cloud with inliers projected onto the torus model.
bool isSampleGood(const Indices &samples) const override
Check if a sample of indices results in a good sample of points indices.
unsigned int model_size_
The number of coefficients in the model.
Definition: sac_model.h:592
Base functor all the models that need non linear optimization must define their own one and implement...
Definition: sac_model.h:679
pcl::SacModel getModelType() const override
Return a unique id for this model (SACMODEL_TORUS).
~SampleConsensusModelTorus() override=default
Empty destructor.
SampleConsensusModelTorus(const PointCloudConstPtr &cloud, bool random=false)
Constructor for base SampleConsensusModelTorus.
typename PointCloud::Ptr PointCloudPtr
Definition: sac_model.h:75
void projectPointToTorus(const Eigen::Vector3f &pt, const Eigen::Vector3f &pt_n, const Eigen::VectorXf &model_coefficients, Eigen::Vector3f &pt_proj) const
Project a point onto a torus given by its model coefficients (radii, torus_center_point, torus_normal)
std::size_t countWithinDistance(const Eigen::VectorXf &model_coefficients, const double threshold) const override
Count all the points which respect the given model coefficients as inliers.
bool computeModelCoefficients(const Indices &samples, Eigen::VectorXf &model_coefficients) const override
Check whether the given index samples can form a valid torus model, compute the model coefficients fr...
SampleConsensusModel represents the base model class.
Definition: sac_model.h:70
std::string model_name_
The model name.
Definition: sac_model.h:551
SampleConsensusModelTorus defines a model for 3D torus segmentation.
bool isModelValid(const Eigen::VectorXf &model_coefficients) const override
Check whether a model is valid given the user constraints.
typename PointCloud::ConstPtr PointCloudConstPtr
Definition: sac_model.h:74
void optimizeModelCoefficients(const Indices &inliers, const Eigen::VectorXf &model_coefficients, Eigen::VectorXf &optimized_coefficients) const override
Recompute the torus coefficients using the given inlier set and return them to the user...
SampleConsensusModelFromNormals represents the base model class for models that require the use of su...
Definition: sac_model.h:612
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition: types.h:133
SampleConsensusModelTorus(const SampleConsensusModelTorus &source)
Copy constructor.
PointCloud represents the base class in PCL for storing collections of 3D points. ...
Definition: distances.h:55
SacModel
Definition: model_types.h:45
shared_ptr< const SampleConsensusModel< pcl::PointXYZRGB > > ConstPtr
Definition: sac_model.h:79
IndicesPtr indices_
A pointer to the vector of point indices to use.
Definition: sac_model.h:557
SampleConsensusModelTorus & operator=(const SampleConsensusModelTorus &source)
Copy constructor.
A point structure representing Euclidean xyz coordinates, and the RGB color.
bool doSamplesVerifyModel(const std::set< index_t > &indices, const Eigen::VectorXf &model_coefficients, const double threshold) const override
Verify whether a subset of indices verifies the given torus model coefficients.
shared_ptr< SampleConsensusModel< pcl::PointXYZRGB > > Ptr
Definition: sac_model.h:78
SampleConsensusModelTorus(const PointCloudConstPtr &cloud, const Indices &indices, bool random=false)
Constructor for base SampleConsensusModelTorus.
void getDistancesToModel(const Eigen::VectorXf &model_coefficients, std::vector< double > &distances) const override
Compute all distances from the cloud data to a given torus model.
unsigned int sample_size_
The size of a sample from which the model is computed.
Definition: sac_model.h:589