00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef PCL_SURFACE_IMPL_MLS_H_
00039 #define PCL_SURFACE_IMPL_MLS_H_
00040
00041 #include "pcl/surface/mls.h"
00042
00044 template <typename PointInT, typename NormalOutT> void
00045 pcl::MovingLeastSquares<PointInT, NormalOutT>::reconstruct (PointCloudIn &output)
00046 {
00047
00048 if (normals_)
00049 {
00050
00051 normals_->header = input_->header;
00052
00053 normals_->width = normals_->height = 0;
00054 normals_->points.clear ();
00055 }
00056
00057
00058 output.header = input_->header;
00059
00060 if (!initCompute ())
00061 {
00062 output.width = output.height = 0;
00063 output.points.clear ();
00064 return;
00065 }
00066
00067
00068 if (!tree_)
00069 {
00070 ROS_ERROR ("[pcl::%s::compute] No spatial search method was given!", getClassName ().c_str ());
00071 output.width = output.height = 0;
00072 output.points.clear ();
00073 return;
00074 }
00075
00076
00077 tree_->setInputCloud (input_, indices_);
00078
00079
00080 if (output.points.size () != indices_->size ())
00081 output.points.resize (indices_->size ());
00082
00083 if (indices_->size () != input_->points.size ())
00084 {
00085 output.width = indices_->size ();
00086 output.height = 1;
00087 }
00088 else
00089 {
00090 output.width = input_->width;
00091 output.height = input_->height;
00092 }
00093 output.is_dense = input_->is_dense;
00094
00095
00096 if (normals_)
00097 {
00098 normals_->points.resize (output.points.size ());
00099 normals_->width = output.width;
00100 normals_->height = output.height;
00101 normals_->is_dense = output.is_dense;
00102 }
00103
00104
00105 performReconstruction (output);
00106
00107 deinitCompute ();
00108 }
00109
00111 template <typename PointInT, typename NormalOutT> void
00112 pcl::MovingLeastSquares<PointInT, NormalOutT>::performReconstruction (PointCloudIn &output)
00113 {
00114 if (search_radius_ <= 0 || sqr_gauss_param_ <= 0)
00115 {
00116 ROS_ERROR ("[pcl::%s::performReconstruction] Invalid search radius (%f) or Gaussian parameter (%f)!", getClassName ().c_str (), search_radius_, sqr_gauss_param_);
00117 output.width = output.height = 0;
00118 output.points.clear ();
00119 if (normals_)
00120 {
00121 normals_->width = normals_->height = 0;
00122 normals_->points.clear ();
00123 }
00124 return;
00125 }
00126
00127
00128 nr_coeff_ = (order_ + 1) * (order_ + 2) / 2;
00129
00130
00131
00132 std::vector<int> nn_indices;
00133 std::vector<float> nn_sqr_dists;
00134
00135
00136
00137 output.points.resize (indices_->size ());
00138 pcl::copyPointCloud (*input_, *indices_, output);
00139
00140
00141 for (size_t cp = 0; cp < indices_->size (); ++cp)
00142 {
00143
00145
00146
00147 if (!searchForNeighbors ((*indices_)[cp], nn_indices, nn_sqr_dists))
00148 {
00149 if (normals_)
00150 normals_->points[cp].normal[0] = normals_->points[cp].normal[1] = normals_->points[cp].normal[2] = normals_->points[cp].curvature = std::numeric_limits<float>::quiet_NaN ();
00151 continue;
00152 }
00153
00154
00155
00156 int k = nn_indices.size ();
00157 if (k < 3)
00158 continue;
00159
00160
00162
00163
00164 Eigen::Vector4f model_coefficients;
00165 float curvature;
00166 pcl::computePointNormal<PointInT> (*input_, nn_indices, model_coefficients, curvature);
00167
00168
00169 Eigen::Vector3f point = output.points[cp].getVector3fMap ();
00170 float distance = point.dot (model_coefficients.head<3> ()) + model_coefficients[3];
00171 point -= distance * model_coefficients.head<3> ();
00172
00173
00175 if (polynomial_fit_ && k >= nr_coeff_)
00176 {
00177
00178 typedef Eigen::Vector3d Evector3;
00179 typedef Eigen::VectorXd Evector;
00180 typedef Eigen::MatrixXd Ematrix;
00181
00182 Evector3 plane_normal = model_coefficients.head<3> ().cast<double> ();
00183
00184
00185
00186 std::vector<Evector3> de_meaned (k);
00187 for (int ni = 0; ni < k; ++ni)
00188 {
00189 de_meaned[ni][0] = input_->points[nn_indices[ni]].x - point[0];
00190 de_meaned[ni][1] = input_->points[nn_indices[ni]].y - point[1];
00191 de_meaned[ni][2] = input_->points[nn_indices[ni]].z - point[2];
00192 nn_sqr_dists[ni] = de_meaned[ni].dot (de_meaned[ni]);
00193 }
00194
00195
00196
00197 Evector weight_vec_ (k);
00198 Ematrix P_ (nr_coeff_, k);
00199 Evector f_vec_ (k);
00200 Evector c_vec_;
00201 Ematrix P_weight_;
00202 Ematrix P_weight_Pt_ (nr_coeff_, nr_coeff_);
00203
00204
00205 Evector3 v = plane_normal.unitOrthogonal ();
00206 Evector3 u = plane_normal.cross (v);
00207
00208
00209
00210 double u_coord, v_coord, u_pow, v_pow;
00211 for (int ni = 0; ni < k; ++ni)
00212 {
00213
00214 weight_vec_ (ni) = exp (-nn_sqr_dists[ni] / sqr_gauss_param_);
00215
00216
00217 u_coord = de_meaned[ni].dot (u);
00218 v_coord = de_meaned[ni].dot (v);
00219 f_vec_(ni) = de_meaned[ni].dot (plane_normal);
00220
00221
00222 int j = 0;
00223 u_pow = 1;
00224 for (int ui = 0; ui <= order_; ++ui)
00225 {
00226 v_pow = 1;
00227 for (int vi = 0; vi <= order_ - ui; ++vi)
00228 {
00229 P_ (j++, ni) = u_pow * v_pow;
00230 v_pow *= v_coord;
00231 }
00232 u_pow *= u_coord;
00233 }
00234 }
00235
00236
00237 P_weight_ = P_ * weight_vec_.asDiagonal ();
00238 P_weight_Pt_ = P_weight_ * P_.transpose ();
00239 c_vec_ = P_weight_ * f_vec_;
00240 P_weight_Pt_.llt ().solveInPlace (c_vec_);
00241
00242
00243 if (!pcl_isfinite (c_vec_[0]))
00244 {
00245 point += (c_vec_[0] * plane_normal).cast<float> ();
00246
00247
00248 if (normals_)
00249 {
00250 Evector3 n_a = u + plane_normal * c_vec_[order_ + 1];
00251 Evector3 n_b = v + plane_normal * c_vec_[1];
00252 model_coefficients.head<3> () = n_a.cross (n_b).cast<float> ();
00253 model_coefficients.head<3> ().normalize ();
00254 }
00255 }
00256 }
00257
00258
00260 output.points[cp].x = point[0];
00261 output.points[cp].y = point[1];
00262 output.points[cp].z = point[2];
00263 if (normals_)
00264 {
00265 normals_->points[cp].normal[0] = model_coefficients[0];
00266 normals_->points[cp].normal[1] = model_coefficients[1];
00267 normals_->points[cp].normal[2] = model_coefficients[2];
00268 normals_->points[cp].curvature = curvature;
00269 }
00270 }
00271 }
00272
00273 #define PCL_INSTANTIATE_MovingLeastSquares(T,OutT) template class pcl::MovingLeastSquares<T,OutT>;
00274
00275 #endif // PCL_SURFACE_IMPL_MLS_H_
00276