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_SEGMENTATION_IMPL_SAC_SEGMENTATION_H_
00039 #define PCL_SEGMENTATION_IMPL_SAC_SEGMENTATION_H_
00040
00041 #include "pcl/segmentation/sac_segmentation.h"
00042
00043 #include "pcl/io/io.h"
00044
00045
00046 #include "pcl/sample_consensus/method_types.h"
00047 #include "pcl/sample_consensus/sac.h"
00048 #include "pcl/sample_consensus/lmeds.h"
00049 #include "pcl/sample_consensus/mlesac.h"
00050 #include "pcl/sample_consensus/msac.h"
00051 #include "pcl/sample_consensus/ransac.h"
00052 #include "pcl/sample_consensus/rmsac.h"
00053 #include "pcl/sample_consensus/rransac.h"
00054
00055
00056 #include "pcl/sample_consensus/model_types.h"
00057 #include "pcl/sample_consensus/sac_model.h"
00058 #include "pcl/sample_consensus/sac_model_circle.h"
00059 #include "pcl/sample_consensus/sac_model_cylinder.h"
00060 #include "pcl/sample_consensus/sac_model_line.h"
00061 #include "pcl/sample_consensus/sac_model_normal_plane.h"
00062 #include "pcl/sample_consensus/sac_model_parallel_plane.h"
00063 #include "pcl/sample_consensus/sac_model_normal_parallel_plane.h"
00064 #include "pcl/sample_consensus/sac_model_parallel_line.h"
00065 #include "pcl/sample_consensus/sac_model_perpendicular_plane.h"
00066 #include "pcl/sample_consensus/sac_model_plane.h"
00067 #include "pcl/sample_consensus/sac_model_sphere.h"
00068
00069
00071 template <typename PointT> void
00072 pcl::SACSegmentation<PointT>::segment (PointIndices &inliers, ModelCoefficients &model_coefficients)
00073 {
00074
00075 inliers.header = model_coefficients.header = input_->header;
00076
00077 if (!initCompute ())
00078 {
00079 inliers.indices.clear (); model_coefficients.values.clear ();
00080 return;
00081 }
00082
00083
00084 if (!initSACModel (model_type_))
00085 {
00086 ROS_ERROR ("[pcl::%s::segment] Error initializing the SAC model!", getClassName ().c_str ());
00087 deinitCompute ();
00088 inliers.indices.clear (); model_coefficients.values.clear ();
00089 return;
00090 }
00091
00092 initSAC (method_type_);
00093
00094 if (!sac_->computeModel (0))
00095 {
00096 ROS_ERROR ("[pcl::%s::segment] Error segmenting the model! No solution found.", getClassName ().c_str ());
00097 deinitCompute ();
00098 inliers.indices.clear (); model_coefficients.values.clear ();
00099 return;
00100 }
00101
00102
00103 sac_->getInliers (inliers.indices);
00104
00105
00106 Eigen::VectorXf coeff;
00107 sac_->getModelCoefficients (coeff);
00108
00109
00110 if (optimize_coefficients_)
00111 {
00112 Eigen::VectorXf coeff_refined;
00113 model_->optimizeModelCoefficients (inliers.indices, coeff, coeff_refined);
00114 model_coefficients.values.resize (coeff_refined.size ());
00115 memcpy (&model_coefficients.values[0], &coeff_refined[0], coeff_refined.size () * sizeof (float));
00116
00117 model_->selectWithinDistance (coeff_refined, threshold_, inliers.indices);
00118 }
00119 else
00120 {
00121 model_coefficients.values.resize (coeff.size ());
00122 memcpy (&model_coefficients.values[0], &coeff[0], coeff.size () * sizeof (float));
00123 }
00124
00125 deinitCompute ();
00126 }
00127
00129 template <typename PointT> bool
00130 pcl::SACSegmentation<PointT>::initSACModel (const int model_type)
00131 {
00132 if (model_)
00133 model_.reset ();
00134
00135
00136 switch (model_type)
00137 {
00138 case SACMODEL_PLANE:
00139 {
00140 ROS_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_PLANE", getClassName ().c_str ());
00141 model_.reset (new SampleConsensusModelPlane<PointT> (input_, *indices_));
00142 break;
00143 }
00144 case SACMODEL_LINE:
00145 {
00146 ROS_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_LINE", getClassName ().c_str ());
00147 model_.reset (new SampleConsensusModelLine<PointT> (input_, *indices_));
00148 break;
00149 }
00150 case SACMODEL_CIRCLE2D:
00151 {
00152 ROS_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_CIRCLE2D", getClassName ().c_str ());
00153 model_.reset (new SampleConsensusModelCircle2D<PointT> (input_, *indices_));
00154 typename SampleConsensusModelCircle2D<PointT>::Ptr model_circle = boost::static_pointer_cast<SampleConsensusModelCircle2D<PointT> > (model_);
00155 double min_radius, max_radius;
00156 model_circle->getRadiusLimits (min_radius, max_radius);
00157 if (radius_min_ != min_radius && radius_max_ != max_radius)
00158 {
00159 ROS_DEBUG ("[pcl::%s::initSACModel] Setting radius limits to %f/%f", getClassName ().c_str (), radius_min_, radius_max_);
00160 model_circle->setRadiusLimits (radius_min_, radius_max_);
00161 }
00162 break;
00163 }
00164 case SACMODEL_SPHERE:
00165 {
00166 ROS_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_SPHERE", getClassName ().c_str ());
00167 model_.reset (new SampleConsensusModelSphere<PointT> (input_, *indices_));
00168 typename SampleConsensusModelSphere<PointT>::Ptr model_sphere = boost::static_pointer_cast<SampleConsensusModelSphere<PointT> > (model_);
00169 double min_radius, max_radius;
00170 model_sphere->getRadiusLimits (min_radius, max_radius);
00171 if (radius_min_ != min_radius && radius_max_ != max_radius)
00172 {
00173 ROS_DEBUG ("[pcl::%s::initSACModel] Setting radius limits to %f/%f", getClassName ().c_str (), radius_min_, radius_max_);
00174 model_sphere->setRadiusLimits (radius_min_, radius_max_);
00175 }
00176 break;
00177 }
00178 case SACMODEL_PARALLEL_LINE:
00179 {
00180 ROS_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_PARALLEL_LINE", getClassName ().c_str ());
00181 model_.reset (new SampleConsensusModelParallelLine<PointT> (input_, *indices_));
00182 typename SampleConsensusModelParallelLine<PointT>::Ptr model_parallel = boost::static_pointer_cast<SampleConsensusModelParallelLine<PointT> > (model_);
00183 if (axis_ != Eigen::Vector3f::Zero () && model_parallel->getAxis () != axis_)
00184 {
00185 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00186 model_parallel->setAxis (axis_);
00187 }
00188 if (eps_angle_ != 0.0 && model_parallel->getEpsAngle () != eps_angle_)
00189 {
00190 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00191 model_parallel->setEpsAngle (eps_angle_);
00192 }
00193 break;
00194 }
00195 case SACMODEL_PERPENDICULAR_PLANE:
00196 {
00197 ROS_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_PERPENDICULAR_PLANE", getClassName ().c_str ());
00198 model_.reset (new SampleConsensusModelPerpendicularPlane<PointT> (input_, *indices_));
00199 typename SampleConsensusModelPerpendicularPlane<PointT>::Ptr model_perpendicular = boost::static_pointer_cast<SampleConsensusModelPerpendicularPlane<PointT> > (model_);
00200 if (axis_ != Eigen::Vector3f::Zero () && model_perpendicular->getAxis () != axis_)
00201 {
00202 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00203 model_perpendicular->setAxis (axis_);
00204 }
00205 if (eps_angle_ != 0.0 && model_perpendicular->getEpsAngle () != eps_angle_)
00206 {
00207 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00208 model_perpendicular->setEpsAngle (eps_angle_);
00209 }
00210 break;
00211 }
00212 case SACMODEL_PARALLEL_PLANE:
00213 {
00214 ROS_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_PARALLEL_PLANE", getClassName ().c_str ());
00215 model_.reset (new SampleConsensusModelParallelPlane<PointT> (input_, *indices_));
00216 typename SampleConsensusModelParallelPlane<PointT>::Ptr model_parallel = boost::static_pointer_cast<SampleConsensusModelParallelPlane<PointT> > (model_);
00217 if (axis_ != Eigen::Vector3f::Zero () && model_parallel->getAxis () != axis_)
00218 {
00219 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00220 model_parallel->setAxis (axis_);
00221 }
00222 if (eps_angle_ != 0.0 && model_parallel->getEpsAngle () != eps_angle_)
00223 {
00224 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00225 model_parallel->setEpsAngle (eps_angle_);
00226 }
00227 break;
00228 }
00229 default:
00230 {
00231 ROS_ERROR ("[pcl::%s::initSACModel] No valid model given!", getClassName ().c_str ());
00232 return (false);
00233 }
00234 }
00235 return (true);
00236 }
00237
00239 template <typename PointT> void
00240 pcl::SACSegmentation<PointT>::initSAC (const int method_type)
00241 {
00242 if (sac_)
00243 sac_.reset ();
00244
00245 switch (method_type)
00246 {
00247 case SAC_RANSAC:
00248 default:
00249 {
00250 ROS_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_RANSAC with a model threshold of %f", getClassName ().c_str (), threshold_);
00251 sac_.reset (new RandomSampleConsensus<PointT> (model_, threshold_));
00252 break;
00253 }
00254 case SAC_LMEDS:
00255 {
00256 ROS_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_LMEDS with a model threshold of %f", getClassName ().c_str (), threshold_);
00257 sac_.reset (new LeastMedianSquares<PointT> (model_, threshold_));
00258 break;
00259 }
00260 case SAC_MSAC:
00261 {
00262 ROS_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_MSAC with a model threshold of %f", getClassName ().c_str (), threshold_);
00263 sac_.reset (new MEstimatorSampleConsensus<PointT> (model_, threshold_));
00264 break;
00265 }
00266 case SAC_RRANSAC:
00267 {
00268 ROS_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_RRANSAC with a model threshold of %f", getClassName ().c_str (), threshold_);
00269 sac_.reset (new RandomizedRandomSampleConsensus<PointT> (model_, threshold_));
00270 break;
00271 }
00272 case SAC_RMSAC:
00273 {
00274 ROS_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_RMSAC with a model threshold of %f", getClassName ().c_str (), threshold_);
00275 sac_.reset (new RandomizedMEstimatorSampleConsensus<PointT> (model_, threshold_));
00276 break;
00277 }
00278 case SAC_MLESAC:
00279 {
00280 ROS_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_MLESAC with a model threshold of %f", getClassName ().c_str (), threshold_);
00281 sac_.reset (new MaximumLikelihoodSampleConsensus<PointT> (model_, threshold_));
00282 break;
00283 }
00284 }
00285
00286 if (sac_->getProbability () != probability_)
00287 {
00288 ROS_DEBUG ("[pcl::%s::initSAC] Setting the desired probability to %f", getClassName ().c_str (), probability_);
00289 sac_->setProbability (probability_);
00290 }
00291 if (max_iterations_ != -1 && sac_->getMaxIterations () != max_iterations_)
00292 {
00293 ROS_DEBUG ("[pcl::%s::initSAC] Setting the maximum number of iterations to %d", getClassName ().c_str (), max_iterations_);
00294 sac_->setMaxIterations (max_iterations_);
00295 }
00296 }
00297
00299 template <typename PointT, typename PointNT> bool
00300 pcl::SACSegmentationFromNormals<PointT, PointNT>::initSACModel (const int model_type)
00301 {
00302
00303 if (input_->points.size () != normals_->points.size ())
00304 {
00305 ROS_ERROR ("[pcl::%s::initSACModel] The number of points inthe input point cloud differs than the number of points in the normals!", getClassName ().c_str ());
00306 return (false);
00307 }
00308
00309 if (model_)
00310 model_.reset ();
00311
00312
00313 switch (model_type)
00314 {
00315 case SACMODEL_CYLINDER:
00316 {
00317 ROS_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_CYLINDER", getClassName ().c_str ());
00318 model_.reset (new SampleConsensusModelCylinder<PointT, PointNT > (input_, *indices_));
00319 typename SampleConsensusModelCylinder<PointT, PointNT>::Ptr model_cylinder = boost::static_pointer_cast<SampleConsensusModelCylinder<PointT, PointNT> > (model_);
00320
00321
00322 model_cylinder->setInputNormals (normals_);
00323 double min_radius, max_radius;
00324 model_cylinder->getRadiusLimits (min_radius, max_radius);
00325 if (radius_min_ != min_radius && radius_max_ != max_radius)
00326 {
00327 ROS_DEBUG ("[pcl::%s::initSACModel] Setting radius limits to %f/%f", getClassName ().c_str (), radius_min_, radius_max_);
00328 model_cylinder->setRadiusLimits (radius_min_, radius_max_);
00329 }
00330 if (distance_weight_ != model_cylinder->getNormalDistanceWeight ())
00331 {
00332 ROS_DEBUG ("[pcl::%s::initSACModel] Setting normal distance weight to %f", getClassName ().c_str (), distance_weight_);
00333 model_cylinder->setNormalDistanceWeight (distance_weight_);
00334 }
00335 if (axis_ != Eigen::Vector3f::Zero () && model_cylinder->getAxis () != axis_)
00336 {
00337 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00338 model_cylinder->setAxis (axis_);
00339 }
00340 if (eps_angle_ != 0.0 && model_cylinder->getEpsAngle () != eps_angle_)
00341 {
00342 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00343 model_cylinder->setEpsAngle (eps_angle_);
00344 }
00345 break;
00346 }
00347 case SACMODEL_NORMAL_PLANE:
00348 {
00349 ROS_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_NORMAL_PLANE", getClassName ().c_str ());
00350 model_.reset (new SampleConsensusModelNormalPlane<PointT, PointNT> (input_, *indices_));
00351 typename SampleConsensusModelNormalPlane<PointT, PointNT>::Ptr model_normals = boost::static_pointer_cast<SampleConsensusModelNormalPlane<PointT, PointNT> > (model_);
00352
00353 model_normals->setInputNormals (normals_);
00354 if (distance_weight_ != model_normals->getNormalDistanceWeight ())
00355 {
00356 ROS_DEBUG ("[pcl::%s::initSACModel] Setting normal distance weight to %f", getClassName ().c_str (), distance_weight_);
00357 model_normals->setNormalDistanceWeight (distance_weight_);
00358 }
00359 if (axis_ != Eigen::Vector3f::Zero () && model_normals->getAxis () != axis_)
00360 {
00361 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00362 model_normals->setAxis (axis_);
00363 }
00364 if (eps_angle_ != 0.0 && model_normals->getEpsAngle () != eps_angle_)
00365 {
00366 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00367 model_normals->setEpsAngle (eps_angle_);
00368 }
00369 break;
00370 }
00371 case SACMODEL_NORMAL_PARALLEL_PLANE:
00372 {
00373 ROS_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_NORMAL_PARALLEL_PLANE", getClassName ().c_str ());
00374 model_.reset (new SampleConsensusModelNormalParallelPlane<PointT, PointNT> (input_, *indices_));
00375 typename SampleConsensusModelNormalParallelPlane<PointT, PointNT>::Ptr model_normals = boost::static_pointer_cast<SampleConsensusModelNormalParallelPlane<PointT, PointNT> > (model_);
00376
00377 model_normals->setInputNormals (normals_);
00378 if (distance_weight_ != model_normals->getNormalDistanceWeight ())
00379 {
00380 ROS_DEBUG ("[pcl::%s::initSACModel] Setting normal distance weight to %f", getClassName ().c_str (), distance_weight_);
00381 model_normals->setNormalDistanceWeight (distance_weight_);
00382 }
00383 if (axis_ != Eigen::Vector3f::Zero () && model_normals->getAxis () != axis_)
00384 {
00385 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00386 model_normals->setAxis (axis_);
00387 }
00388 if (eps_angle_ != 0.0 && model_normals->getEpsAngle () != eps_angle_)
00389 {
00390 ROS_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00391 model_normals->setEpsAngle (eps_angle_);
00392 }
00393 break;
00394 }
00395
00396 default:
00397 {
00398 return (pcl::SACSegmentation<PointT>::initSACModel (model_type));
00399 }
00400 }
00401 return (true);
00402 }
00403
00404 #define PCL_INSTANTIATE_SACSegmentation(T) template class pcl::SACSegmentation<T>;
00405 #define PCL_INSTANTIATE_SACSegmentationFromNormals(T,NT) template class pcl::SACSegmentationFromNormals<T,NT>;
00406
00407 #endif // PCL_SEGMENTATION_IMPL_SAC_SEGMENTATION_H_
00408