38 #ifndef PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_CIRCLE_H_
39 #define PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_CIRCLE_H_
43 #include <unsupported/Eigen/NonLinearOptimization>
46 template <
typename Po
intT>
bool
50 Eigen::Array2d p0 (input_->points[samples[0]].x, input_->points[samples[0]].y);
51 Eigen::Array2d p1 (input_->points[samples[1]].x, input_->points[samples[1]].y);
52 Eigen::Array2d p2 (input_->points[samples[2]].x, input_->points[samples[2]].y);
59 Eigen::Array2d dy1dy2 = p1 / p2;
61 return (dy1dy2[0] != dy1dy2[1]);
65 template <
typename Po
intT>
bool
69 if (samples.size () != 3)
71 PCL_ERROR (
"[pcl::SampleConsensusModelCircle2D::computeModelCoefficients] Invalid set of samples given (%zu)!\n", samples.size ());
75 model_coefficients.resize (3);
77 Eigen::Vector2d p0 (input_->points[samples[0]].x, input_->points[samples[0]].y);
78 Eigen::Vector2d p1 (input_->points[samples[1]].x, input_->points[samples[1]].y);
79 Eigen::Vector2d p2 (input_->points[samples[2]].x, input_->points[samples[2]].y);
81 Eigen::Vector2d u = (p0 + p1) / 2.0;
82 Eigen::Vector2d v = (p1 + p2) / 2.0;
84 Eigen::Vector2d p1p0dif = p1 - p0;
85 Eigen::Vector2d p2p1dif = p2 - p1;
86 Eigen::Vector2d uvdif = u - v;
88 Eigen::Vector2d m (- p1p0dif[0] / p1p0dif[1], - p2p1dif[0] / p2p1dif[1]);
91 model_coefficients[0] =
static_cast<float> ((m[0] * u[0] - m[1] * v[0] - uvdif[1] ) / (m[0] - m[1]));
92 model_coefficients[1] =
static_cast<float> ((m[0] * m[1] * uvdif[0] + m[0] * v[1] - m[1] * u[1]) / (m[0] - m[1]));
95 model_coefficients[2] =
static_cast<float> (
sqrt ((model_coefficients[0] - p0[0]) * (model_coefficients[0] - p0[0]) +
96 (model_coefficients[1] - p0[1]) * (model_coefficients[1] - p0[1])));
101 template <
typename Po
intT>
void
105 if (!isModelValid (model_coefficients))
110 distances.resize (indices_->size ());
113 for (
size_t i = 0; i < indices_->size (); ++i)
116 distances[i] = fabsf (sqrtf (
117 ( input_->points[(*indices_)[i]].x - model_coefficients[0] ) *
118 ( input_->points[(*indices_)[i]].x - model_coefficients[0] ) +
120 ( input_->points[(*indices_)[i]].y - model_coefficients[1] ) *
121 ( input_->points[(*indices_)[i]].y - model_coefficients[1] )
122 ) - model_coefficients[2]);
126 template <
typename Po
intT>
void
128 const Eigen::VectorXf &model_coefficients,
const double threshold,
129 std::vector<int> &inliers)
132 if (!isModelValid (model_coefficients))
138 inliers.resize (indices_->size ());
141 for (
size_t i = 0; i < indices_->size (); ++i)
145 float distance = fabsf (sqrtf (
146 ( input_->points[(*indices_)[i]].x - model_coefficients[0] ) *
147 ( input_->points[(*indices_)[i]].x - model_coefficients[0] ) +
149 ( input_->points[(*indices_)[i]].y - model_coefficients[1] ) *
150 ( input_->points[(*indices_)[i]].y - model_coefficients[1] )
151 ) - model_coefficients[2]);
152 if (distance < threshold)
155 inliers[nr_p] = (*indices_)[i];
159 inliers.resize (nr_p);
163 template <
typename Po
intT>
int
165 const Eigen::VectorXf &model_coefficients,
const double threshold)
168 if (!isModelValid (model_coefficients))
173 for (
size_t i = 0; i < indices_->size (); ++i)
177 float distance = fabsf (sqrtf (
178 ( input_->points[(*indices_)[i]].x - model_coefficients[0] ) *
179 ( input_->points[(*indices_)[i]].x - model_coefficients[0] ) +
181 ( input_->points[(*indices_)[i]].y - model_coefficients[1] ) *
182 ( input_->points[(*indices_)[i]].y - model_coefficients[1] )
183 ) - model_coefficients[2]);
184 if (distance < threshold)
191 template <
typename Po
intT>
void
193 const std::vector<int> &inliers,
const Eigen::VectorXf &model_coefficients, Eigen::VectorXf &optimized_coefficients)
195 optimized_coefficients = model_coefficients;
198 if (model_coefficients.size () != 3)
200 PCL_ERROR (
"[pcl::SampleConsensusModelCircle2D::optimizeModelCoefficients] Invalid number of model coefficients given (%zu)!\n", model_coefficients.size ());
205 if (inliers.size () <= 3)
207 PCL_ERROR (
"[pcl::SampleConsensusModelCircle2D::optimizeModelCoefficients] Not enough inliers found to support a model (%zu)! Returning the same coefficients.\n", inliers.size ());
211 tmp_inliers_ = &inliers;
213 OptimizationFunctor functor (static_cast<int> (inliers.size ()),
this);
214 Eigen::NumericalDiff<OptimizationFunctor> num_diff (functor);
215 Eigen::LevenbergMarquardt<Eigen::NumericalDiff<OptimizationFunctor>,
float> lm (num_diff);
216 int info = lm.minimize (optimized_coefficients);
219 PCL_DEBUG (
"[pcl::SampleConsensusModelCircle2D::optimizeModelCoefficients] LM solver finished with exit code %i, having a residual norm of %g. \nInitial solution: %g %g %g \nFinal solution: %g %g %g\n",
220 info, lm.fvec.norm (), model_coefficients[0], model_coefficients[1], model_coefficients[2], optimized_coefficients[0], optimized_coefficients[1], optimized_coefficients[2]);
224 template <
typename Po
intT>
void
226 const std::vector<int> &inliers,
const Eigen::VectorXf &model_coefficients,
227 PointCloud &projected_points,
bool copy_data_fields)
230 if (model_coefficients.size () != 3)
232 PCL_ERROR (
"[pcl::SampleConsensusModelCircle2D::projectPoints] Invalid number of model coefficients given (%zu)!\n", model_coefficients.size ());
236 projected_points.
header = input_->header;
237 projected_points.
is_dense = input_->is_dense;
240 if (copy_data_fields)
243 projected_points.
points.resize (input_->points.size ());
244 projected_points.
width = input_->width;
245 projected_points.
height = input_->height;
249 for (
size_t i = 0; i < projected_points.
points.size (); ++i)
254 for (
size_t i = 0; i < inliers.size (); ++i)
256 float dx = input_->points[inliers[i]].x - model_coefficients[0];
257 float dy = input_->points[inliers[i]].y - model_coefficients[1];
258 float a = sqrtf ( (model_coefficients[2] * model_coefficients[2]) / (dx * dx + dy * dy) );
260 projected_points.
points[inliers[i]].x = a * dx + model_coefficients[0];
261 projected_points.
points[inliers[i]].y = a * dy + model_coefficients[1];
267 projected_points.
points.resize (inliers.size ());
268 projected_points.
width =
static_cast<uint32_t
> (inliers.size ());
269 projected_points.
height = 1;
273 for (
size_t i = 0; i < inliers.size (); ++i)
278 for (
size_t i = 0; i < inliers.size (); ++i)
280 float dx = input_->points[inliers[i]].x - model_coefficients[0];
281 float dy = input_->points[inliers[i]].y - model_coefficients[1];
282 float a = sqrtf ( (model_coefficients[2] * model_coefficients[2]) / (dx * dx + dy * dy) );
284 projected_points.
points[i].x = a * dx + model_coefficients[0];
285 projected_points.
points[i].y = a * dy + model_coefficients[1];
291 template <
typename Po
intT>
bool
293 const std::set<int> &indices,
const Eigen::VectorXf &model_coefficients,
const double threshold)
296 if (model_coefficients.size () != 3)
298 PCL_ERROR (
"[pcl::SampleConsensusModelCircle2D::doSamplesVerifyModel] Invalid number of model coefficients given (%zu)!\n", model_coefficients.size ());
302 for (std::set<int>::const_iterator it = indices.begin (); it != indices.end (); ++it)
306 ( input_->points[*it].x - model_coefficients[0] ) *
307 ( input_->points[*it].x - model_coefficients[0] ) +
308 ( input_->points[*it].y - model_coefficients[1] ) *
309 ( input_->points[*it].y - model_coefficients[1] )
310 ) - model_coefficients[2]) > threshold)
317 template <
typename Po
intT>
bool
321 if (model_coefficients.size () != 3)
323 PCL_ERROR (
"[pcl::SampleConsensusModelCircle2D::isModelValid] Invalid number of model coefficients given (%zu)!\n", model_coefficients.size ());
327 if (radius_min_ != -std::numeric_limits<double>::max() && model_coefficients[2] < radius_min_)
329 if (radius_max_ != std::numeric_limits<double>::max() && model_coefficients[2] > radius_max_)
335 #define PCL_INSTANTIATE_SampleConsensusModelCircle2D(T) template class PCL_EXPORTS pcl::SampleConsensusModelCircle2D<T>;
337 #endif // PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_CIRCLE_H_