Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
shot_lrf.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2012, 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$
35  */
36 
37 #ifndef PCL_FEATURES_IMPL_SHOT_LRF_H_
38 #define PCL_FEATURES_IMPL_SHOT_LRF_H_
39 
40 #include <utility>
41 #include <pcl/features/shot_lrf.h>
42 
44 // Compute a local Reference Frame for a 3D feature; the output is stored in the "rf" matrix
45 template<typename PointInT, typename PointOutT> float
46 pcl::SHOTLocalReferenceFrameEstimation<PointInT, PointOutT>::getLocalRF (const int& current_point_idx, Eigen::Matrix3f &rf)
47 {
48  const Eigen::Vector4f& central_point = (*input_)[current_point_idx].getVector4fMap ();
49  std::vector<int> n_indices;
50  std::vector<float> n_sqr_distances;
51 
52  this->searchForNeighbors (current_point_idx, search_parameter_, n_indices, n_sqr_distances);
53 
54  Eigen::Matrix<double, Eigen::Dynamic, 4> vij (n_indices.size (), 4);
55 
56  Eigen::Matrix3d cov_m = Eigen::Matrix3d::Zero ();
57 
58  double distance = 0.0;
59  double sum = 0.0;
60 
61  int valid_nn_points = 0;
62 
63  for (size_t i_idx = 0; i_idx < n_indices.size (); ++i_idx)
64  {
65  Eigen::Vector4f pt = surface_->points[n_indices[i_idx]].getVector4fMap ();
66  if (pt.head<3> () == central_point.head<3> ())
67  continue;
68 
69  // Difference between current point and origin
70  vij.row (valid_nn_points) = (pt - central_point).cast<double> ();
71  vij (valid_nn_points, 3) = 0;
72 
73  distance = search_parameter_ - sqrt (n_sqr_distances[i_idx]);
74 
75  // Multiply vij * vij'
76  cov_m += distance * (vij.row (valid_nn_points).head<3> ().transpose () * vij.row (valid_nn_points).head<3> ());
77 
78  sum += distance;
79  valid_nn_points++;
80  }
81 
82  if (valid_nn_points < 5)
83  {
84  //PCL_ERROR ("[pcl::%s::getLocalRF] Warning! Neighborhood has less than 5 vertexes. Aborting Local RF computation of feature point (%lf, %lf, %lf)\n", "SHOTLocalReferenceFrameEstimation", central_point[0], central_point[1], central_point[2]);
85  rf.setConstant (std::numeric_limits<float>::quiet_NaN ());
86 
87  return (std::numeric_limits<float>::max ());
88  }
89 
90  cov_m /= sum;
91 
92  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver (cov_m);
93 
94  const double& e1c = solver.eigenvalues ()[0];
95  const double& e2c = solver.eigenvalues ()[1];
96  const double& e3c = solver.eigenvalues ()[2];
97 
98  if (!pcl_isfinite (e1c) || !pcl_isfinite (e2c) || !pcl_isfinite (e3c))
99  {
100  //PCL_ERROR ("[pcl::%s::getLocalRF] Warning! Eigenvectors are NaN. Aborting Local RF computation of feature point (%lf, %lf, %lf)\n", "SHOTLocalReferenceFrameEstimation", central_point[0], central_point[1], central_point[2]);
101  rf.setConstant (std::numeric_limits<float>::quiet_NaN ());
102 
103  return (std::numeric_limits<float>::max ());
104  }
105 
106  // Disambiguation
107  Eigen::Vector4d v1 = Eigen::Vector4d::Zero ();
108  Eigen::Vector4d v3 = Eigen::Vector4d::Zero ();
109  v1.head<3> () = solver.eigenvectors ().col (2);
110  v3.head<3> () = solver.eigenvectors ().col (0);
111 
112  int plusNormal = 0, plusTangentDirection1=0;
113  for (int ne = 0; ne < valid_nn_points; ne++)
114  {
115  double dp = vij.row (ne).dot (v1);
116  if (dp >= 0)
117  plusTangentDirection1++;
118 
119  dp = vij.row (ne).dot (v3);
120  if (dp >= 0)
121  plusNormal++;
122  }
123 
124  //TANGENT
125  plusTangentDirection1 = 2*plusTangentDirection1 - valid_nn_points;
126  if (plusTangentDirection1 == 0)
127  {
128  int points = 5; //std::min(valid_nn_points*2/2+1, 11);
129  int medianIndex = valid_nn_points/2;
130 
131  for (int i = -points/2; i <= points/2; i++)
132  if ( vij.row (medianIndex - i).dot (v1) > 0)
133  plusTangentDirection1 ++;
134 
135  if (plusTangentDirection1 < points/2+1)
136  v1 *= - 1;
137  } else if (plusTangentDirection1 < 0)
138  v1 *= - 1;
139 
140  //Normal
141  plusNormal = 2*plusNormal - valid_nn_points;
142  if (plusNormal == 0)
143  {
144  int points = 5; //std::min(valid_nn_points*2/2+1, 11);
145  int medianIndex = valid_nn_points/2;
146 
147  for (int i = -points/2; i <= points/2; i++)
148  if ( vij.row (medianIndex - i).dot (v3) > 0)
149  plusNormal ++;
150 
151  if (plusNormal < points/2+1)
152  v3 *= - 1;
153  } else if (plusNormal < 0)
154  v3 *= - 1;
155 
156  rf.row (0) = v1.head<3> ().cast<float> ();
157  rf.row (2) = v3.head<3> ().cast<float> ();
158  rf.row (1) = rf.row (2).cross (rf.row (0));
159 
160  return (0.0f);
161 }
162 
163 template <typename PointInT, typename PointOutT> void
165 {
166  //check whether used with search radius or search k-neighbors
167  if (this->getKSearch () != 0)
168  {
169  PCL_ERROR(
170  "[pcl::%s::computeFeature] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n",
171  getClassName().c_str ());
172  return;
173  }
174  tree_->setSortedResults (true);
175 
176  for (size_t i = 0; i < indices_->size (); ++i)
177  {
178  // point result
179  Eigen::Matrix3f rf;
180  PointOutT& output_rf = output[i];
181 
182  //output_rf.confidence = getLocalRF ((*indices_)[i], rf);
183  //if (output_rf.confidence == std::numeric_limits<float>::max ())
184  if (getLocalRF ((*indices_)[i], rf) == std::numeric_limits<float>::max ())
185  {
186  output.is_dense = false;
187  }
188 
189  output_rf.x_axis.getNormalVector3fMap () = rf.row (0);
190  output_rf.y_axis.getNormalVector3fMap () = rf.row (1);
191  output_rf.z_axis.getNormalVector3fMap () = rf.row (2);
192  }
193 
194 }
195 
196 template <typename PointInT, typename PointOutT> void
198 {
199  //check whether used with search radius or search k-neighbors
200  if (this->getKSearch () != 0)
201  {
202  PCL_ERROR(
203  "[pcl::%s::computeFeatureEigen] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n",
204  getClassName().c_str ());
205  return;
206  }
207  tree_->setSortedResults (true);
208 
209  // Set up the output channels
210  output.channels["shot_lrf"].name = "shot_lrf";
211  output.channels["shot_lrf"].offset = 0;
212  output.channels["shot_lrf"].size = 4;
213  output.channels["shot_lrf"].count = 9;
214  output.channels["shot_lrf"].datatype = sensor_msgs::PointField::FLOAT32;
215 
216  //output.points.resize (indices_->size (), 10);
217  output.points.resize (indices_->size (), 9);
218  for (size_t i = 0; i < indices_->size (); ++i)
219  {
220  // point result
221  Eigen::Matrix3f rf;
222 
223  //output.points (i, 9) = getLocalRF ((*indices_)[i], rf);
224  //if (output.points (i, 9) == std::numeric_limits<float>::max ())
225  if (getLocalRF ((*indices_)[i], rf) == std::numeric_limits<float>::max ())
226  {
227  output.is_dense = false;
228  }
229 
230  output.points.block<1, 3> (i, 0) = rf.row (0);
231  output.points.block<1, 3> (i, 3) = rf.row (1);
232  output.points.block<1, 3> (i, 6) = rf.row (2);
233  }
234 
235 }
236 
237 #define PCL_INSTANTIATE_SHOTLocalReferenceFrameEstimation(T,OutT) template class PCL_EXPORTS pcl::SHOTLocalReferenceFrameEstimation<T,OutT>;
238 
239 #endif // PCL_FEATURES_IMPL_SHOT_LRF_H_
240