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
00033 #include <stereo_wall_detection/sample_consensus/sac_model_plane.h>
00034 #include <stereo_wall_detection/geometry/nearest.h>
00035
00036 namespace sample_consensus
00037 {
00039
00044 void
00045 SACModelPlane::getSamples (int &iterations, std::vector<int> &samples)
00046 {
00047 samples.resize (3);
00048 double trand = indices_.size () / (RAND_MAX + 1.0);
00049
00050
00051 int idx = (int)(rand () * trand);
00052
00053 samples[0] = indices_.at (idx);
00054
00055
00056 do
00057 {
00058 idx = (int)(rand () * trand);
00059 samples[1] = indices_.at (idx);
00060 iterations++;
00061 } while (samples[1] == samples[0]);
00062 iterations--;
00063
00064 double Dx1, Dy1, Dz1, Dx2, Dy2, Dz2, Dy1Dy2;
00065
00066 Dx1 = cloud_->points[samples[1]].x - cloud_->points[samples[0]].x;
00067 Dy1 = cloud_->points[samples[1]].y - cloud_->points[samples[0]].y;
00068 Dz1 = cloud_->points[samples[1]].z - cloud_->points[samples[0]].z;
00069
00070 int iter = 0;
00071 do
00072 {
00073
00074 do
00075 {
00076 idx = (int)(rand () * trand);
00077 samples[2] = indices_.at (idx);
00078 iterations++;
00079 } while ( (samples[2] == samples[1]) || (samples[2] == samples[0]) );
00080 iterations--;
00081
00082
00083 Dx2 = cloud_->points[samples[2]].x - cloud_->points[samples[0]].x;
00084 Dy2 = cloud_->points[samples[2]].y - cloud_->points[samples[0]].y;
00085 Dz2 = cloud_->points[samples[2]].z - cloud_->points[samples[0]].z;
00086
00087 Dy1Dy2 = Dy1 / Dy2;
00088 iter++;
00089
00090 if (iter > MAX_ITERATIONS_COLLINEAR )
00091 {
00092 ROS_WARN ("[SACModelPlane::getSamples] WARNING: Could not select 3 non collinear points in %d iterations!", MAX_ITERATIONS_COLLINEAR);
00093 break;
00094 }
00095 iterations++;
00096 }
00097
00098 while (((Dx1 / Dx2) == Dy1Dy2) && (Dy1Dy2 == (Dz1 / Dz2)));
00099 iterations--;
00100
00101 return;
00102 }
00103
00105
00113 void
00114 SACModelPlane::selectWithinDistance (const std::vector<double> &model_coefficients, double threshold, std::vector<int> &inliers)
00115 {
00116 int nr_p = 0;
00117 inliers.resize (indices_.size ());
00118
00119
00120 for (unsigned int i = 0; i < indices_.size (); i++)
00121 {
00122
00123
00124 if (fabs (model_coefficients.at (0) * cloud_->points.at (indices_.at (i)).x +
00125 model_coefficients.at (1) * cloud_->points.at (indices_.at (i)).y +
00126 model_coefficients.at (2) * cloud_->points.at (indices_.at (i)).z +
00127 model_coefficients.at (3)) < threshold)
00128 {
00129
00130 inliers[nr_p] = indices_[i];
00131 nr_p++;
00132 }
00133 }
00134 inliers.resize (nr_p);
00135 return;
00136 }
00137
00139
00143 void
00144 SACModelPlane::getDistancesToModel (const std::vector<double> &model_coefficients, std::vector<double> &distances)
00145 {
00146 distances.resize (indices_.size ());
00147
00148
00149 for (unsigned int i = 0; i < indices_.size (); i++)
00150
00151
00152 distances[i] = fabs (model_coefficients.at (0) * cloud_->points.at (indices_[i]).x +
00153 model_coefficients.at (1) * cloud_->points.at (indices_[i]).y +
00154 model_coefficients.at (2) * cloud_->points.at (indices_[i]).z +
00155 model_coefficients.at (3));
00156 return;
00157 }
00158
00160
00165 void
00166 SACModelPlane::projectPoints (const std::vector<int> &inliers, const std::vector<double> &model_coefficients,
00167 sensor_msgs::PointCloud &projected_points)
00168 {
00169
00170 projected_points.points.resize (inliers.size ());
00171 projected_points.set_channels_size (cloud_->get_channels_size ());
00172
00173
00174 for (unsigned int d = 0; d < projected_points.get_channels_size (); d++)
00175 {
00176 projected_points.channels[d].name = cloud_->channels[d].name;
00177 projected_points.channels[d].values.resize (inliers.size ());
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 for (unsigned int i = 0; i < inliers.size (); i++)
00192 {
00193
00194 double distance_to_plane = model_coefficients.at (0) * cloud_->points.at (inliers.at (i)).x +
00195 model_coefficients.at (1) * cloud_->points.at (inliers.at (i)).y +
00196 model_coefficients.at (2) * cloud_->points.at (inliers.at (i)).z +
00197 model_coefficients.at (3) * 1;
00198
00199 projected_points.points[i].x = cloud_->points.at (inliers.at (i)).x - distance_to_plane * model_coefficients.at (0);
00200 projected_points.points[i].y = cloud_->points.at (inliers.at (i)).y - distance_to_plane * model_coefficients.at (1);
00201 projected_points.points[i].z = cloud_->points.at (inliers.at (i)).z - distance_to_plane * model_coefficients.at (2);
00202
00203 for (unsigned int d = 0; d < projected_points.get_channels_size (); d++)
00204 projected_points.channels[d].values[i] = cloud_->channels[d].values[inliers.at (i)];
00205 }
00206 }
00207
00209
00213 void
00214 SACModelPlane::projectPointsInPlace (const std::vector<int> &inliers, const std::vector<double> &model_coefficients)
00215 {
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 for (unsigned int i = 0; i < inliers.size (); i++)
00228 {
00229
00230 double distance_to_plane = model_coefficients.at (0) * cloud_->points.at (inliers.at (i)).x +
00231 model_coefficients.at (1) * cloud_->points.at (inliers.at (i)).y +
00232 model_coefficients.at (2) * cloud_->points.at (inliers.at (i)).z +
00233 model_coefficients.at (3) * 1;
00234
00235 cloud_->points.at (inliers.at (i)).x = cloud_->points.at (inliers.at (i)).x - distance_to_plane * model_coefficients.at (0);
00236 cloud_->points.at (inliers.at (i)).y = cloud_->points.at (inliers.at (i)).y - distance_to_plane * model_coefficients.at (1);
00237 cloud_->points.at (inliers.at (i)).z = cloud_->points.at (inliers.at (i)).z - distance_to_plane * model_coefficients.at (2);
00238 }
00239 }
00240
00242
00247 bool
00248 SACModelPlane::computeModelCoefficients (const std::vector<int> &samples)
00249 {
00250 model_coefficients_.resize (4);
00251 double Dx1, Dy1, Dz1, Dx2, Dy2, Dz2, Dy1Dy2;
00252
00253 Dx1 = cloud_->points.at (samples.at (1)).x - cloud_->points.at (samples.at (0)).x;
00254 Dy1 = cloud_->points.at (samples.at (1)).y - cloud_->points.at (samples.at (0)).y;
00255 Dz1 = cloud_->points.at (samples.at (1)).z - cloud_->points.at (samples.at (0)).z;
00256
00257
00258 Dx2 = cloud_->points.at (samples.at (2)).x - cloud_->points.at (samples.at (0)).x;
00259 Dy2 = cloud_->points.at (samples.at (2)).y - cloud_->points.at (samples.at (0)).y;
00260 Dz2 = cloud_->points.at (samples.at (2)).z - cloud_->points.at (samples.at (0)).z;
00261
00262 Dy1Dy2 = Dy1 / Dy2;
00263 if (((Dx1 / Dx2) == Dy1Dy2) && (Dy1Dy2 == (Dz1 / Dz2)))
00264 return (false);
00265
00266
00267
00268 model_coefficients_[0] = (cloud_->points.at (samples.at (1)).y - cloud_->points.at (samples.at (0)).y) *
00269 (cloud_->points.at (samples.at (2)).z - cloud_->points.at (samples.at (0)).z) -
00270 (cloud_->points.at (samples.at (1)).z - cloud_->points.at (samples.at (0)).z) *
00271 (cloud_->points.at (samples.at (2)).y - cloud_->points.at (samples.at (0)).y);
00272
00273 model_coefficients_[1] = (cloud_->points.at (samples.at (1)).z - cloud_->points.at (samples.at (0)).z) *
00274 (cloud_->points.at (samples.at (2)).x - cloud_->points.at (samples.at (0)).x) -
00275 (cloud_->points.at (samples.at (1)).x - cloud_->points.at (samples.at (0)).x) *
00276 (cloud_->points.at (samples.at (2)).z - cloud_->points.at (samples.at (0)).z);
00277
00278 model_coefficients_[2] = (cloud_->points.at (samples.at (1)).x - cloud_->points.at (samples.at (0)).x) *
00279 (cloud_->points.at (samples.at (2)).y - cloud_->points.at (samples.at (0)).y) -
00280 (cloud_->points.at (samples.at (1)).y - cloud_->points.at (samples.at (0)).y) *
00281 (cloud_->points.at (samples.at (2)).x - cloud_->points.at (samples.at (0)).x);
00282
00283
00284 double n_norm = sqrt (model_coefficients_[0] * model_coefficients_[0] +
00285 model_coefficients_[1] * model_coefficients_[1] +
00286 model_coefficients_[2] * model_coefficients_[2]);
00287 model_coefficients_[0] /= n_norm;
00288 model_coefficients_[1] /= n_norm;
00289 model_coefficients_[2] /= n_norm;
00290
00291
00292 model_coefficients_[3] = -1 * (model_coefficients_[0] * cloud_->points.at (samples.at (0)).x +
00293 model_coefficients_[1] * cloud_->points.at (samples.at (0)).y +
00294 model_coefficients_[2] * cloud_->points.at (samples.at (0)).z);
00295
00296 return (true);
00297 }
00298
00300
00305 void
00306 SACModelPlane::refitModel (const std::vector<int> &inliers, std::vector<double> &refit_coefficients)
00307 {
00308 if (inliers.size () == 0)
00309 {
00310 ROS_ERROR ("[SACModelPlane::RefitModel] Cannot re-fit 0 inliers!");
00311 refit_coefficients = model_coefficients_;
00312 return;
00313 }
00314
00315 Eigen::Vector4d plane_coefficients;
00316 double curvature;
00317
00318
00319 cloud_geometry::nearest::computePointNormal (*cloud_, inliers, plane_coefficients, curvature);
00320
00321 refit_coefficients.resize (4);
00322 for (int d = 0; d < 4; d++)
00323 refit_coefficients[d] = plane_coefficients (d);
00324 }
00325
00327
00331 bool
00332 SACModelPlane::doSamplesVerifyModel (const std::set<int> &indices, double threshold)
00333 {
00334 for (std::set<int>::iterator it = indices.begin (); it != indices.end (); ++it)
00335 if (fabs (model_coefficients_.at (0) * cloud_->points.at (*it).x +
00336 model_coefficients_.at (1) * cloud_->points.at (*it).y +
00337 model_coefficients_.at (2) * cloud_->points.at (*it).z +
00338 model_coefficients_.at (3)) > threshold)
00339 return (false);
00340
00341 return (true);
00342 }
00343 }