41 #ifndef PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_PLANE_H_
42 #define PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_PLANE_H_
44 #include <pcl/sample_consensus/sac_model_plane.h>
46 #include <pcl/common/eigen.h>
47 #include <pcl/common/concatenate.h>
50 template <
typename Po
intT>
bool
53 if (samples.size () != sample_size_)
55 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::isSampleGood] Wrong number of samples (is %lu, should be %lu)!\n", samples.size (), sample_size_);
70 if ((p1 - p0).cross(p2 - p0).stableNorm() < Eigen::NumTraits<float>::dummy_precision ())
72 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::isSampleGood] Sample points too similar or collinear!\n");
80 template <
typename Po
intT>
bool
82 const Indices &samples, Eigen::VectorXf &model_coefficients)
const
87 if (samples.size () != sample_size_)
89 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::computeModelCoefficients] Invalid set of samples given (%lu)!\n", samples.size ());
97 const Eigen::Vector3f cross = (p1 - p0).cross(p2 - p0);
98 const float crossNorm = cross.stableNorm();
101 if (crossNorm < Eigen::NumTraits<float>::dummy_precision ())
103 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::computeModelCoefficients] Chosen samples are collinear!\n");
109 model_coefficients.resize (model_size_);
110 model_coefficients.template head<3>() = cross / crossNorm;
113 model_coefficients[3] = -1.0f * (model_coefficients.template head<3>().dot (p0));
115 PCL_DEBUG (
"[pcl::SampleConsensusModelPlane::computeModelCoefficients] Model is (%g,%g,%g,%g).\n",
116 model_coefficients[0], model_coefficients[1], model_coefficients[2], model_coefficients[3]);
121 template <
typename Po
intT>
void
123 const Eigen::VectorXf &model_coefficients, std::vector<double> &distances)
const
126 if (!isModelValid (model_coefficients))
128 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::getDistancesToModel] Given model is invalid!\n");
132 distances.resize (indices_->size ());
135 for (std::size_t i = 0; i < indices_->size (); ++i)
143 Eigen::Vector4f pt ((*input_)[(*indices_)[i]].x,
144 (*input_)[(*indices_)[i]].y,
145 (*input_)[(*indices_)[i]].z,
147 distances[i] = std::abs (model_coefficients.dot (pt));
152 template <
typename Po
intT>
void
154 const Eigen::VectorXf &model_coefficients,
const double threshold,
Indices &inliers)
157 if (!isModelValid (model_coefficients))
159 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::selectWithinDistance] Given model is invalid!\n");
164 error_sqr_dists_.clear ();
165 inliers.reserve (indices_->size ());
166 error_sqr_dists_.reserve (indices_->size ());
169 for (std::size_t i = 0; i < indices_->size (); ++i)
173 Eigen::Vector4f pt ((*input_)[(*indices_)[i]].x,
174 (*input_)[(*indices_)[i]].y,
175 (*input_)[(*indices_)[i]].z,
178 float distance = std::abs (model_coefficients.dot (pt));
183 inliers.push_back ((*indices_)[i]);
184 error_sqr_dists_.push_back (
static_cast<double> (
distance));
190 template <
typename Po
intT> std::size_t
192 const Eigen::VectorXf &model_coefficients,
const double threshold)
const
195 if (!isModelValid (model_coefficients))
197 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::countWithinDistance] Given model is invalid!\n");
200 #if defined (__AVX__) && defined (__AVX2__)
201 return countWithinDistanceAVX (model_coefficients, threshold);
202 #elif defined (__SSE__) && defined (__SSE2__) && defined (__SSE4_1__)
203 return countWithinDistanceSSE (model_coefficients, threshold);
205 return countWithinDistanceStandard (model_coefficients, threshold);
210 template <
typename Po
intT> std::size_t
212 const Eigen::VectorXf &model_coefficients,
const double threshold, std::size_t i)
const
214 std::size_t nr_p = 0;
216 for (; i < indices_->size (); ++i)
220 Eigen::Vector4f pt ((*input_)[(*indices_)[i]].x,
221 (*input_)[(*indices_)[i]].y,
222 (*input_)[(*indices_)[i]].z,
224 if (std::abs (model_coefficients.dot (pt)) < threshold)
233 #if defined (__SSE__) && defined (__SSE2__) && defined (__SSE4_1__)
234 template <
typename Po
intT> std::size_t
236 const Eigen::VectorXf &model_coefficients,
const double threshold, std::size_t i)
const
238 std::size_t nr_p = 0;
239 const __m128 a_vec = _mm_set1_ps (model_coefficients[0]);
240 const __m128 b_vec = _mm_set1_ps (model_coefficients[1]);
241 const __m128 c_vec = _mm_set1_ps (model_coefficients[2]);
242 const __m128 d_vec = _mm_set1_ps (model_coefficients[3]);
243 const __m128 threshold_vec = _mm_set1_ps (threshold);
244 const __m128 abs_help = _mm_set1_ps (-0.0F);
245 __m128i res = _mm_set1_epi32(0);
246 for (; (i + 4) <= indices_->size (); i += 4)
248 const __m128 mask = _mm_cmplt_ps (dist4 (i, a_vec, b_vec, c_vec, d_vec, abs_help), threshold_vec);
249 res = _mm_add_epi32 (res, _mm_and_si128 (_mm_set1_epi32 (1), _mm_castps_si128 (mask)));
256 nr_p += _mm_extract_epi32 (res, 0);
257 nr_p += _mm_extract_epi32 (res, 1);
258 nr_p += _mm_extract_epi32 (res, 2);
259 nr_p += _mm_extract_epi32 (res, 3);
262 nr_p += countWithinDistanceStandard(model_coefficients, threshold, i);
268 #if defined (__AVX__) && defined (__AVX2__)
269 template <
typename Po
intT> std::size_t
271 const Eigen::VectorXf &model_coefficients,
const double threshold, std::size_t i)
const
273 std::size_t nr_p = 0;
274 const __m256 a_vec = _mm256_set1_ps (model_coefficients[0]);
275 const __m256 b_vec = _mm256_set1_ps (model_coefficients[1]);
276 const __m256 c_vec = _mm256_set1_ps (model_coefficients[2]);
277 const __m256 d_vec = _mm256_set1_ps (model_coefficients[3]);
278 const __m256 threshold_vec = _mm256_set1_ps (threshold);
279 const __m256 abs_help = _mm256_set1_ps (-0.0F);
280 __m256i res = _mm256_set1_epi32(0);
281 for (; (i + 8) <= indices_->size (); i += 8)
283 const __m256 mask = _mm256_cmp_ps (dist8 (i, a_vec, b_vec, c_vec, d_vec, abs_help), threshold_vec, _CMP_LT_OQ);
284 res = _mm256_add_epi32 (res, _mm256_and_si256 (_mm256_set1_epi32 (1), _mm256_castps_si256 (mask)));
295 nr_p += _mm256_extract_epi32 (res, 0);
296 nr_p += _mm256_extract_epi32 (res, 1);
297 nr_p += _mm256_extract_epi32 (res, 2);
298 nr_p += _mm256_extract_epi32 (res, 3);
299 nr_p += _mm256_extract_epi32 (res, 4);
300 nr_p += _mm256_extract_epi32 (res, 5);
301 nr_p += _mm256_extract_epi32 (res, 6);
302 nr_p += _mm256_extract_epi32 (res, 7);
305 nr_p += countWithinDistanceStandard(model_coefficients, threshold, i);
311 template <
typename Po
intT>
void
313 const Indices &inliers,
const Eigen::VectorXf &model_coefficients, Eigen::VectorXf &optimized_coefficients)
const
316 if (!isModelValid (model_coefficients))
318 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::optimizeModelCoefficients] Given model is invalid!\n");
319 optimized_coefficients = model_coefficients;
324 if (inliers.size () <= sample_size_)
326 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::optimizeModelCoefficients] Not enough inliers found to optimize model coefficients (%lu)! Returning the same coefficients.\n", inliers.size ());
327 optimized_coefficients = model_coefficients;
331 Eigen::Vector4f plane_parameters;
334 EIGEN_ALIGN16 Eigen::Matrix3f covariance_matrix;
335 Eigen::Vector4f xyz_centroid;
339 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::optimizeModelCoefficients] computeMeanAndCovarianceMatrix failed (returned 0) because there are no valid inliers.\n");
340 optimized_coefficients = model_coefficients;
345 EIGEN_ALIGN16 Eigen::Vector3f::Scalar eigen_value;
346 EIGEN_ALIGN16 Eigen::Vector3f eigen_vector;
347 pcl::eigen33 (covariance_matrix, eigen_value, eigen_vector);
350 optimized_coefficients.resize (model_size_);
351 optimized_coefficients[0] = eigen_vector [0];
352 optimized_coefficients[1] = eigen_vector [1];
353 optimized_coefficients[2] = eigen_vector [2];
354 optimized_coefficients[3] = 0.0f;
355 optimized_coefficients[3] = -1.0f * optimized_coefficients.dot (xyz_centroid);
358 if (!isModelValid (optimized_coefficients))
360 optimized_coefficients = model_coefficients;
365 template <
typename Po
intT>
void
367 const Indices &inliers,
const Eigen::VectorXf &model_coefficients,
PointCloud &projected_points,
bool copy_data_fields)
const
370 if (!isModelValid (model_coefficients))
372 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::projectPoints] Given model is invalid!\n");
376 projected_points.
header = input_->header;
377 projected_points.
is_dense = input_->is_dense;
379 Eigen::Vector4f mc (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0.0f);
384 Eigen::Vector4f tmp_mc = model_coefficients;
390 if (copy_data_fields)
393 projected_points.
resize (input_->size ());
394 projected_points.
width = input_->width;
395 projected_points.
height = input_->height;
397 using FieldList =
typename pcl::traits::fieldList<PointT>::type;
399 for (std::size_t i = 0; i < input_->size (); ++i)
404 for (
const auto &inlier : inliers)
407 Eigen::Vector4f p ((*input_)[inlier].x,
412 float distance_to_plane = tmp_mc.dot (p);
415 pp.matrix () = p - mc * distance_to_plane;
421 projected_points.
resize (inliers.size ());
422 projected_points.
width = inliers.size ();
423 projected_points.
height = 1;
425 using FieldList =
typename pcl::traits::fieldList<PointT>::type;
427 for (std::size_t i = 0; i < inliers.size (); ++i)
434 for (std::size_t i = 0; i < inliers.size (); ++i)
437 Eigen::Vector4f p ((*input_)[inliers[i]].x,
438 (*input_)[inliers[i]].y,
439 (*input_)[inliers[i]].z,
442 float distance_to_plane = tmp_mc.dot (p);
445 pp.matrix () = p - mc * distance_to_plane;
451 template <
typename Po
intT>
bool
453 const std::set<index_t> &indices,
const Eigen::VectorXf &model_coefficients,
const double threshold)
const
456 if (!isModelValid (model_coefficients))
458 PCL_ERROR (
"[pcl::SampleConsensusModelPlane::doSamplesVerifyModel] Given model is invalid!\n");
462 for (
const auto &index : indices)
464 Eigen::Vector4f pt ((*input_)[index].x,
468 if (std::abs (model_coefficients.dot (pt)) > threshold)
477 #define PCL_INSTANTIATE_SampleConsensusModelPlane(T) template class PCL_EXPORTS pcl::SampleConsensusModelPlane<T>;
Define methods for centroid estimation and covariance matrix calculus.
PointCloud represents the base class in PCL for storing collections of 3D points.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
void resize(std::size_t count)
Resizes the container to contain count elements.
std::uint32_t width
The point cloud width (if organized as an image-structure).
pcl::PCLHeader header
The point cloud header.
std::uint32_t height
The point cloud height (if organized as an image-structure).
SampleConsensusModelPlane defines a model for 3D plane segmentation.
void optimizeModelCoefficients(const Indices &inliers, const Eigen::VectorXf &model_coefficients, Eigen::VectorXf &optimized_coefficients) const override
Recompute the plane coefficients using the given inlier set and return them to the user.
void getDistancesToModel(const Eigen::VectorXf &model_coefficients, std::vector< double > &distances) const override
Compute all distances from the cloud data to a given plane model.
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 plane model coefficients.
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 plane model.
bool computeModelCoefficients(const Indices &samples, Eigen::VectorXf &model_coefficients) const override
Check whether the given index samples can form a valid plane model, compute the model coefficients fr...
std::size_t countWithinDistanceStandard(const Eigen::VectorXf &model_coefficients, const double threshold, std::size_t i=0) const
This implementation uses no SIMD instructions.
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.
unsigned int computeMeanAndCovarianceMatrix(const pcl::PointCloud< PointT > &cloud, Eigen::Matrix< Scalar, 3, 3 > &covariance_matrix, Eigen::Matrix< Scalar, 4, 1 > ¢roid)
Compute the normalized 3x3 covariance matrix and the centroid of a given set of points in a single lo...
void eigen33(const Matrix &mat, typename Matrix::Scalar &eigenvalue, Vector &eigenvector)
determines the eigenvector and eigenvalue of the smallest eigenvalue of the symmetric positive semi d...
float distance(const PointT &p1, const PointT &p2)
Eigen::Map< Eigen::Vector4f, Eigen::Aligned > Vector4fMap
const Eigen::Map< const Eigen::Vector3f > Vector3fMapConst
IndicesAllocator<> Indices
Type used for indices in PCL.
Helper functor structure for concatenate.