Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gicp.h
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2010, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage, Inc. nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * $Id: gicp.h 5026 2012-03-12 02:51:44Z rusu $
35  *
36  */
37 
38 #ifndef PCL_GICP_H_
39 #define PCL_GICP_H_
40 
41 #include <pcl/registration/icp.h>
42 #include <pcl/registration/bfgs.h>
43 
44 namespace pcl
45 {
56  template <typename PointSource, typename PointTarget>
57  class GeneralizedIterativeClosestPoint : public IterativeClosestPoint<PointSource, PointTarget>
58  {
76 
78  typedef typename PointCloudSource::Ptr PointCloudSourcePtr;
79  typedef typename PointCloudSource::ConstPtr PointCloudSourceConstPtr;
80 
82  typedef typename PointCloudTarget::Ptr PointCloudTargetPtr;
83  typedef typename PointCloudTarget::ConstPtr PointCloudTargetConstPtr;
84 
85  typedef PointIndices::Ptr PointIndicesPtr;
86  typedef PointIndices::ConstPtr PointIndicesConstPtr;
87 
88  typedef typename pcl::KdTree<PointSource> InputKdTree;
89  typedef typename pcl::KdTree<PointSource>::Ptr InputKdTreePtr;
90 
91  typedef Eigen::Matrix<double, 6, 1> Vector6d;
92 
93  public:
96  : k_correspondences_(20)
97  , gicp_epsilon_(0.001)
98  , rotation_epsilon_(2e-3)
99  , input_covariances_(0)
100  , target_covariances_(0)
101  , mahalanobis_(0)
102  , max_inner_iterations_(20)
103  {
104  min_number_correspondences_ = 4;
105  reg_name_ = "GeneralizedIterativeClosestPoint";
106  max_iterations_ = 200;
107  transformation_epsilon_ = 5e-4;
108  corr_dist_threshold_ = 5.;
109  rigid_transformation_estimation_ =
111  this, _1, _2, _3, _4, _5);
112  input_tree_.reset (new pcl::KdTreeFLANN<PointSource>);
113  }
114 
118  inline void
119  setInputCloud (const PointCloudSourceConstPtr &cloud)
120  {
121  if (cloud->points.empty ())
122  {
123  PCL_ERROR ("[pcl::%s::setInputInput] Invalid or empty point cloud dataset given!\n", getClassName ().c_str ());
124  return;
125  }
126  PointCloudSource input = *cloud;
127  // Set all the point.data[3] values to 1 to aid the rigid transformation
128  for (size_t i = 0; i < input.size (); ++i)
129  input[i].data[3] = 1.0;
130 
131  input_ = input.makeShared ();
132  input_tree_->setInputCloud (input_);
133  input_covariances_.reserve (input_->size ());
134  }
135 
139  inline void
140  setInputTarget (const PointCloudTargetConstPtr &target)
141  {
143  target_covariances_.reserve (target_->size ());
144  }
145 
154  void
155  estimateRigidTransformationBFGS (const PointCloudSource &cloud_src,
156  const std::vector<int> &indices_src,
157  const PointCloudTarget &cloud_tgt,
158  const std::vector<int> &indices_tgt,
159  Eigen::Matrix4f &transformation_matrix);
160 
162  inline const Eigen::Matrix3d& mahalanobis(size_t index) const
163  {
164  assert(index < mahalanobis_.size());
165  return mahalanobis_[index];
166  }
167 
175  void
176  computeRDerivative(const Vector6d &x, const Eigen::Matrix3d &R, Vector6d &g) const;
177 
183  inline void
184  setRotationEpsilon (double epsilon) { rotation_epsilon_ = epsilon; }
185 
189  inline double
190  getRotationEpsilon () { return (rotation_epsilon_); }
191 
198  void
199  setCorrespondenceRandomness (int k) { k_correspondences_ = k; }
200 
204  int
205  getCorrespondenceRandomness () { return (k_correspondences_); }
206 
210  void
211  setMaximumOptimizerIterations (int max) { max_inner_iterations_ = max; }
212 
214  int
215  getMaximumOptimizerIterations () { return (max_inner_iterations_); }
216 
217  private:
218 
222  int k_correspondences_;
223 
228  double gicp_epsilon_;
229 
234  double rotation_epsilon_;
235 
237  Eigen::Matrix4f base_transformation_;
238 
240  const PointCloudSource *tmp_src_;
241 
243  const PointCloudTarget *tmp_tgt_;
244 
246  const std::vector<int> *tmp_idx_src_;
247 
249  const std::vector<int> *tmp_idx_tgt_;
250 
252  InputKdTreePtr input_tree_;
253 
255  std::vector<Eigen::Matrix3d> input_covariances_;
256 
258  std::vector<Eigen::Matrix3d> target_covariances_;
259 
261  std::vector<Eigen::Matrix3d> mahalanobis_;
262 
264  int max_inner_iterations_;
265 
272  template<typename PointT>
273  void computeCovariances(typename pcl::PointCloud<PointT>::ConstPtr cloud,
274  const typename pcl::KdTree<PointT>::Ptr tree,
275  std::vector<Eigen::Matrix3d>& cloud_covariances);
276 
281  inline double
282  matricesInnerProd(const Eigen::MatrixXd& mat1, const Eigen::MatrixXd& mat2) const
283  {
284  double r = 0.;
285  size_t n = mat1.rows();
286  // tr(mat1^t.mat2)
287  for(size_t i = 0; i < n; i++)
288  for(size_t j = 0; j < n; j++)
289  r += mat1 (j, i) * mat2 (i,j);
290  return r;
291  }
292 
297  void
298  computeTransformation (PointCloudSource &output, const Eigen::Matrix4f &guess);
299 
305  inline bool
306  searchForNeighbors (const PointSource &query, std::vector<int>& index, std::vector<float>& distance)
307  {
308  int k = tree_->nearestKSearch (query, 1, index, distance);
309  if (k == 0)
310  return (false);
311  return (true);
312  }
313 
315  void applyState(Eigen::Matrix4f &t, const Vector6d& x) const;
316 
318  struct OptimizationFunctorWithIndices : public BFGSDummyFunctor<double,6>
319  {
320  OptimizationFunctorWithIndices (const GeneralizedIterativeClosestPoint* gicp)
321  : BFGSDummyFunctor<double,6> (), gicp_(gicp) {}
322  double operator() (const Vector6d& x);
323  void df(const Vector6d &x, Vector6d &df);
324  void fdf(const Vector6d &x, double &f, Vector6d &df);
325 
327  };
328 
329  protected:
330  boost::function<void(const pcl::PointCloud<PointSource> &cloud_src,
331  const std::vector<int> &src_indices,
332  const pcl::PointCloud<PointTarget> &cloud_tgt,
333  const std::vector<int> &tgt_indices,
334  Eigen::Matrix4f &transformation_matrix)> rigid_transformation_estimation_;
335  };
336 }
337 
339 
340 #endif //#ifndef PCL_GICP_H_