Go to the documentation of this file.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
00036 #include <door_handle_detector/sample_consensus/sac_model_line.h>
00037 #include <door_handle_detector/geometry/point.h>
00038 #include <door_handle_detector/geometry/nearest.h>
00039 #include <Eigen/Eigenvalues>
00040
00041 namespace sample_consensus
00042 {
00044
00049 void
00050 SACModelLine::getSamples (int &iterations, std::vector<int> &samples)
00051 {
00052 samples.resize (2);
00053 double trand = indices_.size () / (RAND_MAX + 1.0);
00054
00055
00056 int idx = (int)(rand () * trand);
00057
00058 samples[0] = indices_.at (idx);
00059
00060
00061 int iter = 0;
00062 do
00063 {
00064 idx = (int)(rand () * trand);
00065 samples[1] = indices_.at (idx);
00066 iter++;
00067
00068 if (iter > MAX_ITERATIONS_UNIQUE)
00069 {
00070 ROS_WARN ("[SACModelLine::getSamples] WARNING: Could not select 2 unique points in %d iterations!", MAX_ITERATIONS_UNIQUE);
00071 break;
00072 }
00073 iterations++;
00074 } while (samples[1] == samples[0]);
00075 iterations--;
00076 return;
00077 }
00078
00080
00087 void
00088 SACModelLine::selectWithinDistance (const std::vector<double> &model_coefficients, double threshold, std::vector<int> &inliers)
00089 {
00090 double sqr_threshold = threshold * threshold;
00091
00092 int nr_p = 0;
00093 inliers.resize (indices_.size ());
00094
00095
00096 geometry_msgs::Point32 p3, p4;
00097 p3.x = model_coefficients.at (3) - model_coefficients.at (0);
00098 p3.y = model_coefficients.at (4) - model_coefficients.at (1);
00099 p3.z = model_coefficients.at (5) - model_coefficients.at (2);
00100
00101
00102 for (unsigned int i = 0; i < indices_.size (); i++)
00103 {
00104
00105
00106
00107
00108
00109
00110
00111 p4.x = model_coefficients.at (3) - cloud_->points.at (indices_.at (i)).x;
00112 p4.y = model_coefficients.at (4) - cloud_->points.at (indices_.at (i)).y;
00113 p4.z = model_coefficients.at (5) - cloud_->points.at (indices_.at (i)).z;
00114
00115
00116
00117
00118 geometry_msgs::Point32 c = cloud_geometry::cross (p4, p3);
00119 double sqr_distance = (c.x * c.x + c.y * c.y + c.z * c.z) / (p3.x * p3.x + p3.y * p3.y + p3.z * p3.z);
00120
00121 if (sqr_distance < sqr_threshold)
00122 {
00123
00124 inliers[nr_p] = indices_[i];
00125 nr_p++;
00126 }
00127 }
00128 inliers.resize (nr_p);
00129 return;
00130 }
00131
00133
00137 void
00138 SACModelLine::getDistancesToModel (const std::vector<double> &model_coefficients, std::vector<double> &distances)
00139 {
00140 distances.resize (indices_.size ());
00141
00142
00143 geometry_msgs::Point32 p3, p4;
00144 p3.x = model_coefficients.at (3) - model_coefficients.at (0);
00145 p3.y = model_coefficients.at (4) - model_coefficients.at (1);
00146 p3.z = model_coefficients.at (5) - model_coefficients.at (2);
00147
00148
00149 for (unsigned int i = 0; i < indices_.size (); i++)
00150 {
00151
00152
00153 p4.x = model_coefficients.at (3) - cloud_->points.at (indices_.at (i)).x;
00154 p4.y = model_coefficients.at (4) - cloud_->points.at (indices_.at (i)).y;
00155 p4.z = model_coefficients.at (5) - cloud_->points.at (indices_.at (i)).z;
00156
00157 geometry_msgs::Point32 c = cloud_geometry::cross (p4, p3);
00158 distances[i] = sqrt (c.x * c.x + c.y * c.y + c.z * c.z) / (p3.x * p3.x + p3.y * p3.y + p3.z * p3.z);
00159 }
00160 return;
00161 }
00162
00164
00169 void
00170 SACModelLine::projectPoints (const std::vector<int> &inliers, const std::vector<double> &model_coefficients,
00171 sensor_msgs::PointCloud &projected_points)
00172 {
00173
00174 projected_points.points.resize (inliers.size ());
00175 projected_points.channels.resize (cloud_->channels.size ());
00176
00177
00178 for (unsigned int d = 0; d < projected_points.channels.size (); d++)
00179 {
00180 projected_points.channels[d].name = cloud_->channels[d].name;
00181 projected_points.channels[d].values.resize (inliers.size ());
00182 }
00183
00184
00185 geometry_msgs::Point32 p21;
00186 p21.x = model_coefficients.at (3) - model_coefficients.at (0);
00187 p21.y = model_coefficients.at (4) - model_coefficients.at (1);
00188 p21.z = model_coefficients.at (5) - model_coefficients.at (2);
00189
00190
00191 for (unsigned int i = 0; i < inliers.size (); i++)
00192 {
00193
00194 double k = ( cloud_->points.at (inliers.at (i)).x * p21.x + cloud_->points.at (inliers.at (i)).y * p21.y + cloud_->points.at (inliers.at (i)).z * p21.z -
00195 (model_coefficients_[0] * p21.x + model_coefficients_[1] * p21.y + model_coefficients_[2] * p21.z)
00196 ) / (p21.x * p21.x + p21.y * p21.y + p21.z * p21.z);
00197
00198 projected_points.points[i].x = model_coefficients_.at (0) + k * p21.x;
00199 projected_points.points[i].y = model_coefficients_.at (1) + k * p21.y;
00200 projected_points.points[i].z = model_coefficients_.at (2) + k * p21.z;
00201
00202 for (unsigned int d = 0; d < projected_points.channels.size (); d++)
00203 projected_points.channels[d].values[i] = cloud_->channels[d].values[inliers.at (i)];
00204 }
00205 }
00206
00208
00212 void
00213 SACModelLine::projectPointsInPlace (const std::vector<int> &inliers, const std::vector<double> &model_coefficients)
00214 {
00215
00216 geometry_msgs::Point32 p21;
00217 p21.x = model_coefficients.at (3) - model_coefficients.at (0);
00218 p21.y = model_coefficients.at (4) - model_coefficients.at (1);
00219 p21.z = model_coefficients.at (5) - model_coefficients.at (2);
00220
00221
00222 for (unsigned int i = 0; i < inliers.size (); i++)
00223 {
00224
00225 double k = ( cloud_->points.at (inliers.at (i)).x * p21.x + cloud_->points.at (inliers.at (i)).y * p21.y + cloud_->points.at (inliers.at (i)).z * p21.z -
00226 (model_coefficients_[0] * p21.x + model_coefficients_[1] * p21.y + model_coefficients_[2] * p21.z)
00227 ) / (p21.x * p21.x + p21.y * p21.y + p21.z * p21.z);
00228
00229 cloud_->points.at (inliers.at (i)).x = model_coefficients_.at (0) + k * p21.x;
00230 cloud_->points.at (inliers.at (i)).y = model_coefficients_.at (1) + k * p21.y;
00231 cloud_->points.at (inliers.at (i)).z = model_coefficients_.at (2) + k * p21.z;
00232 }
00233 }
00234
00236
00241 bool
00242 SACModelLine::computeModelCoefficients (const std::vector<int> &samples)
00243 {
00244 model_coefficients_.resize (6);
00245 model_coefficients_[0] = cloud_->points.at (samples.at (0)).x;
00246 model_coefficients_[1] = cloud_->points.at (samples.at (0)).y;
00247 model_coefficients_[2] = cloud_->points.at (samples.at (0)).z;
00248 model_coefficients_[3] = cloud_->points.at (samples.at (1)).x;
00249 model_coefficients_[4] = cloud_->points.at (samples.at (1)).y;
00250 model_coefficients_[5] = cloud_->points.at (samples.at (1)).z;
00251
00252 return (true);
00253 }
00254
00256
00261 void
00262 SACModelLine::refitModel (const std::vector<int> &inliers, std::vector<double> &refit_coefficients)
00263 {
00264 if (inliers.size () == 0)
00265 {
00266 ROS_ERROR ("[SACModelLine::RefitModel] Cannot re-fit 0 inliers!");
00267 refit_coefficients = model_coefficients_;
00268 return;
00269 }
00270
00271 refit_coefficients.resize (6);
00272
00273
00274 geometry_msgs::Point32 centroid;
00275
00276 Eigen::Matrix3d covariance_matrix;
00277 cloud_geometry::nearest::computeCovarianceMatrix (*cloud_, inliers, covariance_matrix, centroid);
00278
00279 refit_coefficients[0] = centroid.x;
00280 refit_coefficients[1] = centroid.y;
00281 refit_coefficients[2] = centroid.z;
00282
00283
00284
00285 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> ei_symm (covariance_matrix);
00286 Eigen::Vector3d eigen_values = ei_symm.eigenvalues ();
00287 Eigen::Matrix3d eigen_vectors = ei_symm.eigenvectors ();
00288
00289 refit_coefficients[3] = eigen_vectors (0, 2) + refit_coefficients[0];
00290 refit_coefficients[4] = eigen_vectors (1, 2) + refit_coefficients[1];
00291 refit_coefficients[5] = eigen_vectors (2, 2) + refit_coefficients[2];
00292 }
00293
00295
00299 bool
00300 SACModelLine::doSamplesVerifyModel (const std::set<int> &indices, double threshold)
00301 {
00302 double sqr_threshold = threshold * threshold;
00303 for (std::set<int>::iterator it = indices.begin (); it != indices.end (); ++it)
00304 {
00305 geometry_msgs::Point32 p3, p4;
00306 p3.x = model_coefficients_.at (3) - model_coefficients_.at (0);
00307 p3.y = model_coefficients_.at (4) - model_coefficients_.at (1);
00308 p3.z = model_coefficients_.at (5) - model_coefficients_.at (2);
00309
00310 p4.x = model_coefficients_.at (3) - cloud_->points.at (*it).x;
00311 p4.y = model_coefficients_.at (4) - cloud_->points.at (*it).y;
00312 p4.z = model_coefficients_.at (5) - cloud_->points.at (*it).z;
00313
00314 geometry_msgs::Point32 c = cloud_geometry::cross (p4, p3);
00315 double sqr_distance = (c.x * c.x + c.y * c.y + c.z * c.z) / (p3.x * p3.x + p3.y * p3.y + p3.z * p3.z);
00316
00317 if (sqr_distance < sqr_threshold)
00318 return (false);
00319 }
00320 return (true);
00321 }
00322 }