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 #include "jsk_pcl_ros/edgebased_cube_finder.h"
00037 #include <pcl/kdtree/kdtree_flann.h>
00038 #include <pcl/common/centroid.h>
00039 #include "jsk_recognition_utils/pcl_conversion_util.h"
00040 #include <jsk_recognition_msgs/BoundingBoxArray.h>
00041 #include <geometry_msgs/PoseArray.h>
00042 #include <pcl/filters/extract_indices.h>
00043 #include <visualization_msgs/Marker.h>
00044 #include <eigen_conversions/eigen_msg.h>
00045 #include <pcl/sample_consensus/method_types.h>
00046 #include <pcl/sample_consensus/model_types.h>
00047 #include <pcl/segmentation/sac_segmentation.h>
00048 #include <pcl/common/angles.h>
00049 #include <jsk_recognition_msgs/PolygonArray.h>
00050 #include <jsk_recognition_msgs/ClusterPointIndices.h>
00051 #include <pcl/filters/project_inliers.h>
00052 #include <pcl/surface/convex_hull.h>
00053 #include <pcl_conversions/pcl_conversions.h>
00054
00055 namespace jsk_pcl_ros
00056 {
00057 CubeHypothesis::CubeHypothesis(const IndicesPair& pair,
00058 const CoefficientsPair& coefficients_pair,
00059 const double outlier_threshold):
00060 value_(0.0), indices_pair_(pair), coefficients_pair_(coefficients_pair),
00061 outlier_threshold_(outlier_threshold_)
00062 {
00063
00064 }
00065
00066 CubeHypothesis::~CubeHypothesis()
00067 {
00068 }
00069
00070 void CubeHypothesis::computeCentroid(
00071 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& cloud,
00072 const pcl::PointIndices::Ptr& indices,
00073 Eigen::Vector3f& output)
00074 {
00075 Eigen::Vector4f centroid;
00076
00077 pcl::PointCloud<pcl::PointXYZRGB>::Ptr target_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
00078 pcl::ExtractIndices<pcl::PointXYZRGB> ex;
00079 ex.setInputCloud(cloud);
00080 ex.setIndices(indices);
00081 ex.filter(*target_cloud);
00082 pcl::compute3DCentroid(*target_cloud, centroid);
00083 jsk_recognition_utils::pointFromVectorToVector<Eigen::Vector4f, Eigen::Vector3f>(centroid, output);
00084 }
00085
00086 void CubeHypothesis::getLinePoints(
00087 const jsk_recognition_utils::Line& line,
00088 const pcl::PointCloud<pcl::PointXYZRGB>& cloud,
00089 const pcl::PointIndices::Ptr indices,
00090 jsk_recognition_utils::Vertices& output)
00091 {
00092 pcl::PointCloud<pcl::PointXYZRGB>::Ptr points
00093 (new pcl::PointCloud<pcl::PointXYZRGB>);
00094 pcl::ExtractIndices<pcl::PointXYZRGB> extract;
00095 extract.setInputCloud(cloud.makeShared());
00096 extract.setIndices(indices);
00097 extract.filter(*points);
00098 for (size_t i = 0; i < points->points.size(); i++) {
00099 pcl::PointXYZRGB p = points->points[i];
00100 Eigen::Vector3f p_eigen = p.getVector3fMap();
00101 Eigen::Vector3f foot_point;
00102 line.foot(p_eigen, foot_point);
00103 output.push_back(foot_point);
00104 }
00105 }
00106
00107 jsk_recognition_utils::ConvexPolygon::Ptr CubeHypothesis::buildConvexPolygon(
00108 const jsk_recognition_utils::PointPair& a_edge_pair, const jsk_recognition_utils::PointPair& b_edge_pair)
00109 {
00110 jsk_recognition_utils::Vertices vertices;
00111 vertices.push_back(a_edge_pair.get<0>());
00112 vertices.push_back(a_edge_pair.get<1>());
00113 vertices.push_back(b_edge_pair.get<1>());
00114 vertices.push_back(b_edge_pair.get<0>());
00115 jsk_recognition_utils::ConvexPolygon::Ptr convex (new jsk_recognition_utils::ConvexPolygon(vertices));
00116 return convex;
00117 }
00118
00119 double CubeHypothesis::evaluatePointOnPlanes(
00120 const pcl::PointCloud<pcl::PointXYZRGB>& cloud,
00121 jsk_recognition_utils::ConvexPolygon& polygon_a,
00122 jsk_recognition_utils::ConvexPolygon& polygon_b)
00123 {
00124 std::vector<int> a_indices, b_indices;
00125 for (size_t i = 0; i < cloud.points.size(); i++) {
00126 pcl::PointXYZRGB pcl_point = cloud.points[i];
00127 if (pcl_isfinite(pcl_point.x) &&
00128 pcl_isfinite(pcl_point.y) &&
00129 pcl_isfinite(pcl_point.z)) {
00130 Eigen::Vector3f eigen_point = pcl_point.getVector3fMap();
00131 if (polygon_a.distanceSmallerThan(eigen_point, outlier_threshold_)) {
00132 a_indices.push_back(i);
00133 }
00134 if (polygon_b.distanceSmallerThan(eigen_point, outlier_threshold_)) {
00135 b_indices.push_back(i);
00136 }
00137 }
00138 }
00139
00140 return a_indices.size() + b_indices.size();
00141 }
00142
00143 jsk_recognition_utils::PointPair CubeHypothesis::computeAxisEndPoints(
00144 const jsk_recognition_utils::Line& axis,
00145 const jsk_recognition_utils::PointPair& a_candidates,
00146 const jsk_recognition_utils::PointPair& b_candidates)
00147 {
00148 jsk_recognition_utils::Vertices original_points;
00149 original_points.push_back(a_candidates.get<0>());
00150 original_points.push_back(a_candidates.get<1>());
00151 original_points.push_back(b_candidates.get<0>());
00152 original_points.push_back(b_candidates.get<1>());
00153 for (size_t i = 0; i < original_points.size(); i++) {
00154 Eigen::Vector3f p = original_points[i];
00155 ROS_INFO("[foot_point] [%f, %f, %f]", p[0], p[1], p[2]);
00156 }
00157
00158 jsk_recognition_utils::Vertices foot_points;
00159 for (size_t i = 0; i < original_points.size(); i++) {
00160 Eigen::Vector3f foot_point;
00161 axis.foot(original_points[i], foot_point);
00162 foot_points.push_back(foot_point);
00163 }
00164 double max_alpha = -DBL_MAX;
00165 double min_alpha = DBL_MAX;
00166 Eigen::Vector3f max_alpha_point, min_alpha_point;
00167
00168 for (size_t i = 0; i < foot_points.size(); i++) {
00169 double alpha = axis.computeAlpha(foot_points[i]);
00170 if (alpha > max_alpha) {
00171 max_alpha = alpha;
00172 max_alpha_point = foot_points[i];
00173 }
00174 if (alpha < min_alpha) {
00175 min_alpha = alpha;
00176 min_alpha_point = foot_points[i];
00177 }
00178 }
00179 ROS_INFO("min_alpha_point: [%f, %f, %f]", min_alpha_point[0], min_alpha_point[1], min_alpha_point[2]);
00180 ROS_INFO("max_alpha_point: [%f, %f, %f]", max_alpha_point[0], max_alpha_point[1], max_alpha_point[2]);
00181 return boost::make_tuple(min_alpha_point, max_alpha_point);
00182 }
00183
00184
00185 PlanarCubeHypothesis::PlanarCubeHypothesis(
00186 const IndicesPair& pair, const CoefficientsPair& coefficients_pair, const double outlier_threshold):
00187 CubeHypothesis(pair, coefficients_pair, outlier_threshold)
00188 {
00189
00190 }
00191
00192 DiagnoalCubeHypothesis::DiagnoalCubeHypothesis(
00193 const IndicesPair& pair, const CoefficientsPair& coefficients_pair,
00194 const double outlier_threshold):
00195 CubeHypothesis(pair, coefficients_pair, outlier_threshold), resolution_(10)
00196 {
00197
00198 }
00199
00200 void DiagnoalCubeHypothesis::estimate(
00201 const pcl::PointCloud<pcl::PointXYZRGB>& cloud)
00202 {
00203 const double dt = (M_PI - 2.0 * min_angle_) / resolution_;
00204 jsk_recognition_utils::Line::Ptr line_a
00205 = jsk_recognition_utils::Line::fromCoefficients(coefficients_pair_.get<0>()->values);
00206 jsk_recognition_utils::Line::Ptr line_b
00207 = jsk_recognition_utils::Line::fromCoefficients(coefficients_pair_.get<1>()->values);
00208 if (!line_a->isSameDirection(*line_b)) {
00209 line_b = line_b->flip();
00210 }
00211
00212 const double r2 = line_a->distance(*line_b);
00213 const double r = r2 / 2;
00214 jsk_recognition_utils::Line::Ptr axis = line_a->midLine(*line_b);
00215 Eigen::Vector3f center;
00216 axis->getOrigin(center);
00217 ROS_INFO("line_a:");
00218 line_a->print();
00219 ROS_INFO("line_b:");
00220 line_b->print();
00221 ROS_INFO("axis:");
00222 axis->print();
00223 ROS_INFO("r: %f", r);
00224
00225
00226
00227
00228
00229 Eigen::Vector3f centroid_a, centroid_b;
00230 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_ptr = cloud.makeShared();
00231 computeCentroid(cloud_ptr, indices_pair_.get<0>(), centroid_a);
00232 computeCentroid(cloud_ptr, indices_pair_.get<1>(), centroid_b);
00233 ROS_INFO("centroid_a: [%f, %f, %f]", centroid_a[0], centroid_a[1], centroid_a[2]);
00234 ROS_INFO("centroid_b: [%f, %f, %f]", centroid_b[0], centroid_b[1], centroid_b[2]);
00235 jsk_recognition_utils::Line::Ptr line_a_aligned = axis->parallelLineOnAPoint(centroid_a);
00236 jsk_recognition_utils::Line::Ptr line_b_aligned = axis->parallelLineOnAPoint(centroid_b);
00237 ROS_INFO("line_a_aligned:");
00238 line_a_aligned->print();
00239 ROS_INFO("line_b_aligned:");
00240 line_b_aligned->print();
00241
00242 jsk_recognition_utils::Vertices line_a_points, line_b_points;
00243 getLinePoints(*line_a_aligned, cloud, indices_pair_.get<0>(),
00244 line_a_points);
00245 getLinePoints(*line_b_aligned, cloud, indices_pair_.get<1>(),
00246 line_b_points);
00247 jsk_recognition_utils::PointPair line_a_end_points = line_a->findEndPoints(line_a_points);
00248 jsk_recognition_utils::PointPair line_b_end_points = line_b->findEndPoints(line_b_points);
00249 double max_v = - DBL_MAX;
00250 double max_theta;
00251 jsk_recognition_utils::Line::Ptr max_line_c;
00252 jsk_recognition_utils::PointPair max_line_c_a_points, max_line_c_b_points;
00253 for (size_t i = 0; i < resolution_; i++) {
00254 ROS_INFO("estimate i: %lu", i);
00255 double theta = dt * i + min_angle_;
00256 Eigen::Vector3f point_on_x;
00257 line_a->foot(center, point_on_x);
00258
00259
00260
00261
00262 Eigen::Vector3f ex = (point_on_x - center).normalized();
00263 Eigen::Vector3f ez;
00264 axis->getDirection(ez);
00265 Eigen::Vector3f ey = ez.cross(ex).normalized();
00266
00267 if (center.dot(ey) > 0) {
00268 ex = -ex;
00269 ey = ez.cross(ex).normalized();
00270 }
00271 Eigen::Vector3f point_on_y = center + r * ey;
00272 jsk_recognition_utils::Line::Ptr line_c = axis->parallelLineOnAPoint(point_on_y);
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 Eigen::Vector3f line_c_a_min_point, line_c_a_max_point;
00287 Eigen::Vector3f line_c_b_min_point, line_c_b_max_point;
00288 line_c->foot(line_a_end_points.get<0>(), line_c_a_min_point);
00289 line_c->foot(line_a_end_points.get<1>(), line_c_a_max_point);
00290 line_c->foot(line_b_end_points.get<0>(), line_c_b_min_point);
00291 line_c->foot(line_b_end_points.get<1>(), line_c_b_max_point);
00292 jsk_recognition_utils::PointPair line_c_a_end_points = boost::make_tuple(line_c_a_min_point,
00293 line_c_a_max_point);
00294 jsk_recognition_utils::PointPair line_c_b_end_points = boost::make_tuple(line_c_b_min_point,
00295 line_c_b_max_point);
00296 jsk_recognition_utils::ConvexPolygon::Ptr plane_a = buildConvexPolygon(line_a_end_points,
00297 line_c_a_end_points);
00298 jsk_recognition_utils::ConvexPolygon::Ptr plane_b = buildConvexPolygon(line_b_end_points,
00299 line_c_b_end_points);
00300 double v = evaluatePointOnPlanes(cloud, *plane_a, *plane_b);
00301 if (max_v < v) {
00302 max_v = v;
00303 max_theta = theta;
00304 max_line_c = line_c;
00305 max_line_c_a_points = line_c_a_end_points;
00306 max_line_c_b_points = line_c_b_end_points;
00307 }
00308 }
00309 value_ = max_v;
00310
00311 jsk_recognition_utils::PointPair axis_end_points = computeAxisEndPoints(
00312 *axis,
00313 max_line_c_a_points,
00314 max_line_c_b_points);
00315 ROS_INFO("end_point: [%f, %f, %f]", axis_end_points.get<0>()[0], axis_end_points.get<0>()[1], axis_end_points.get<0>()[2]);
00316 ROS_INFO("end_point: [%f, %f, %f]", axis_end_points.get<1>()[0], axis_end_points.get<1>()[1], axis_end_points.get<1>()[2]);
00317 Eigen::Vector3f midpoint
00318 = (axis_end_points.get<0>() + axis_end_points.get<1>()) / 2.0;
00319 double z_dimension = (axis_end_points.get<0>() - midpoint).norm() * 2;
00320
00321 ROS_INFO("midpoint: [%f, %f, %f]", midpoint[0], midpoint[1], midpoint[2]);
00322 cube_.reset(new jsk_recognition_utils::Cube(midpoint, *line_a_aligned, *line_b_aligned, *max_line_c));
00323 std::vector<double> dimensions = cube_->getDimensions();
00324 dimensions[2] = z_dimension;
00325 cube_->setDimensions(dimensions);
00326 }
00327
00328 int EdgebasedCubeFinder::countInliers(
00329 const pcl::PointCloud<PointT>::Ptr cloud,
00330 const jsk_recognition_utils::ConvexPolygon::Ptr convex)
00331 {
00332 int num = 0;
00333 for (size_t i = 0; i < cloud->points.size(); i++) {
00334 PointT p = cloud->points[i];
00335 if (!std::isnan(p.x) && !std::isnan(p.y) && !std::isnan(p.z)) {
00336 Eigen::Vector3f ep = p.getVector3fMap();
00337 if (convex->distanceSmallerThan(ep, outlier_threshold_)) {
00338 num++;
00339 }
00340 }
00341 }
00342 return num;
00343 }
00344
00345 void EdgebasedCubeFinder::filterBasedOnConvex(
00346 const pcl::PointCloud<PointT>::Ptr cloud,
00347 const std::vector<jsk_recognition_utils::ConvexPolygon::Ptr>& convexes,
00348 std::vector<int>& output_indices)
00349 {
00350
00351 for (size_t i = 0; i < convexes.size(); i++) {
00352 jsk_recognition_utils::ConvexPolygon::Ptr convex = convexes[i];
00353 if (true) {
00354
00355
00356
00357
00358
00359 if (true) {
00360 output_indices.push_back(i);
00361 }
00362 }
00363 }
00364 }
00365
00366 void EdgebasedCubeFinder::configCallback (Config &config, uint32_t level)
00367 {
00368 boost::mutex::scoped_lock lock(mutex_);
00369 outlier_threshold_ = config.outlier_threshold;
00370 min_inliers_ = config.min_inliers;
00371 convex_area_threshold_ = config.convex_area_threshold;
00372 convex_edge_threshold_ = config.convex_edge_threshold;
00373 parallel_edge_distance_min_threshold_ = config.parallel_edge_distance_min_threshold;
00374 parallel_edge_distance_max_threshold_ = config.parallel_edge_distance_max_threshold;
00375 }
00376
00377 void EdgebasedCubeFinder::onInit()
00378 {
00379 ConnectionBasedNodelet::onInit();
00380
00381
00382 srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
00383 dynamic_reconfigure::Server<Config>::CallbackType f =
00384 boost::bind (&EdgebasedCubeFinder::configCallback, this, _1, _2);
00385 srv_->setCallback (f);
00386
00387
00389
00391 pub_ = advertise<jsk_recognition_msgs::BoundingBoxArray>(*pnh_, "output", 1);
00392 pub_pose_array_
00393 = advertise<geometry_msgs::PoseArray>(*pnh_, "output_pose_array", 1);
00394 pub_debug_marker_
00395 = advertise<visualization_msgs::Marker>(*pnh_, "debug_marker", 1);
00396 pub_debug_filtered_cloud_ = advertise<sensor_msgs::PointCloud2>(
00397 *pnh_, "debug_filtered_cloud", 1);
00398 pub_debug_polygons_
00399 = advertise<jsk_recognition_msgs::PolygonArray>(*pnh_, "debug_polygons", 1);
00400 pub_debug_clusers_
00401 = advertise<jsk_recognition_msgs::ClusterPointIndices>(*pnh_, "debug_clusters", 1);
00402
00403 onInitPostProcess();
00404 }
00405
00406 void EdgebasedCubeFinder::subscribe()
00407 {
00409
00411 sub_input_.subscribe(*pnh_, "input", 1);
00412 sub_edges_.subscribe(*pnh_, "input_edges", 1);
00413 sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
00414 sync_->connectInput(sub_input_, sub_edges_);
00415 sync_->registerCallback(boost::bind(
00416 &EdgebasedCubeFinder::estimate, this, _1, _2));
00417 }
00418
00419 void EdgebasedCubeFinder::unsubscribe()
00420 {
00421 sub_input_.unsubscribe();
00422 sub_edges_.unsubscribe();
00423 }
00424
00425 jsk_recognition_utils::Line::Ptr EdgebasedCubeFinder::midLineFromCoefficientsPair(
00426 const CoefficientsPair& pair)
00427 {
00428 pcl::ModelCoefficients::Ptr coefficients_a = pair.get<0>();
00429 pcl::ModelCoefficients::Ptr coefficients_b = pair.get<1>();
00430 jsk_recognition_utils::Line::Ptr line_a = jsk_recognition_utils::Line::fromCoefficients(coefficients_a->values);
00431 jsk_recognition_utils::Line::Ptr line_b = jsk_recognition_utils::Line::fromCoefficients(coefficients_b->values);
00432 return line_a->midLine(*line_b);
00433 }
00434
00435 pcl::PointCloud<EdgebasedCubeFinder::PointT>::Ptr EdgebasedCubeFinder::extractPointCloud(
00436 const pcl::PointCloud<PointT>::Ptr cloud,
00437 const pcl::PointIndices::Ptr indices)
00438 {
00439 pcl::PointCloud<PointT>::Ptr ret (new pcl::PointCloud<PointT>);
00440 pcl::ExtractIndices<PointT> ex;
00441 ex.setInputCloud(cloud);
00442 ex.setIndices(indices);
00443 ex.filter(*ret);
00444 return ret;
00445 }
00446
00447 jsk_recognition_utils::PointPair EdgebasedCubeFinder::minMaxPointOnLine(
00448 const jsk_recognition_utils::Line& line,
00449 const pcl::PointCloud<PointT>::Ptr cloud)
00450 {
00451 jsk_recognition_utils::Vertices points;
00452 for (size_t i = 0; i < cloud->points.size(); i++) {
00453 PointT p = cloud->points[i];
00454 Eigen::Vector3f eigen_p = p.getVector3fMap();
00455 Eigen::Vector3f foot;
00456 line.foot(eigen_p, foot);
00457 points.push_back(foot);
00458 }
00459 return line.findEndPoints(points);
00460 }
00461
00462 jsk_recognition_utils::ConvexPolygon::Ptr EdgebasedCubeFinder::convexFromPairs(
00463 const pcl::PointCloud<PointT>::Ptr cloud,
00464 const CoefficientsPair& coefficients_pair,
00465 const IndicesPair& indices_pair)
00466 {
00467 pcl::ModelCoefficients::Ptr coefficients_a = coefficients_pair.get<0>();
00468 pcl::ModelCoefficients::Ptr coefficients_b = coefficients_pair.get<1>();
00469 pcl::PointIndices::Ptr indices_a = indices_pair.get<0>();
00470 pcl::PointIndices::Ptr indices_b = indices_pair.get<1>();
00471
00472 pcl::PointCloud<PointT>::Ptr cloud_a = extractPointCloud(cloud, indices_a);
00473 pcl::PointCloud<PointT>::Ptr cloud_b = extractPointCloud(cloud, indices_b);
00474
00475 jsk_recognition_utils::Line::Ptr line_a = jsk_recognition_utils::Line::fromCoefficients(coefficients_a->values);
00476 jsk_recognition_utils::Line::Ptr line_b = jsk_recognition_utils::Line::fromCoefficients(coefficients_b->values);
00477 jsk_recognition_utils::PointPair a_min_max = minMaxPointOnLine(*line_a, cloud_a);
00478 jsk_recognition_utils::PointPair b_min_max = minMaxPointOnLine(*line_b, cloud_b);
00479 jsk_recognition_utils::Vertices vertices;
00480 vertices.push_back(a_min_max.get<0>());
00481 vertices.push_back(a_min_max.get<1>());
00482 vertices.push_back(b_min_max.get<1>());
00483 vertices.push_back(b_min_max.get<0>());
00484 jsk_recognition_utils::ConvexPolygon::Ptr ret (new jsk_recognition_utils::ConvexPolygon(vertices));
00485 return ret;
00486 }
00487
00488 void EdgebasedCubeFinder::filterPairsBasedOnParallelEdgeDistances(
00489 const std::vector<IndicesPair>& pairs,
00490 const std::vector<CoefficientsPair>& coefficients_pair,
00491 std::vector<IndicesPair>& filtered_indices_pairs,
00492 std::vector<CoefficientsPair>& filtered_coefficients_pairs)
00493 {
00494 for (size_t i = 0; i < coefficients_pair.size(); i++) {
00495 CoefficientsPair coefficients = coefficients_pair[i];
00496 pcl::ModelCoefficients::Ptr coefficients_a = coefficients_pair[i].get<0>();
00497 pcl::ModelCoefficients::Ptr coefficients_b = coefficients_pair[i].get<1>();
00498 jsk_recognition_utils::Line::Ptr line_a = jsk_recognition_utils::Line::fromCoefficients(coefficients_a->values);
00499 jsk_recognition_utils::Line::Ptr line_b = jsk_recognition_utils::Line::fromCoefficients(coefficients_b->values);
00500
00501
00502 jsk_recognition_utils::Line::Ptr axis = line_a->midLine(*line_b);
00503 Eigen::Vector3f origin_a, origin_b;
00504 line_a->getOrigin(origin_a);
00505 line_b->getOrigin(origin_b);
00506 jsk_recognition_utils::Line::Ptr line_a_aligned = axis->parallelLineOnAPoint(origin_a);
00507 jsk_recognition_utils::Line::Ptr line_b_aligned = axis->parallelLineOnAPoint(origin_b);
00508 Eigen::Vector3f distance_vector;
00509 line_a_aligned->parallelLineNormal(*line_b_aligned, distance_vector);
00510 double distance = distance_vector.norm();
00511
00512 ROS_INFO("d: %f", distance);
00513 if (distance < parallel_edge_distance_max_threshold_ &&
00514 distance > parallel_edge_distance_min_threshold_) {
00515 filtered_indices_pairs.push_back(pairs[i]);
00516 filtered_coefficients_pairs.push_back(coefficients);
00517 }
00518 }
00519 }
00520
00521
00522 pcl::PointIndices::Ptr
00523 EdgebasedCubeFinder::preparePointCloudForRANSAC(
00524 const jsk_recognition_utils::ConvexPolygon::Ptr convex,
00525 const CoefficientsPair& edge_coefficients_pair,
00526 const pcl::PointCloud<PointT>::Ptr cloud)
00527 {
00528
00529 pcl::PointIndices::Ptr indices(new pcl::PointIndices);
00530 jsk_recognition_utils::ConvexPolygon::Ptr magnified_convex = convex->magnify(1.1);
00531 pcl::PointCloud<PointT>::Ptr ret (new pcl::PointCloud<PointT>);
00532 for (size_t i = 0; i < cloud->points.size(); i++) {
00533 PointT p = cloud->points[i];
00534 if (!std::isnan(p.x) && !std::isnan(p.y) && !std::isnan(p.z)) {
00535 Eigen::Vector3f ep = p.getVector3fMap();
00536 Eigen::Vector3f foot;
00537 magnified_convex->projectOnPlane(ep, foot);
00538 if (magnified_convex->isInside(foot) && convex->distanceSmallerThan(ep, outlier_threshold_)) {
00539
00540
00541 indices->indices.push_back(i);
00542 }
00543 }
00544 }
00545 return indices;
00546 }
00547
00548 void EdgebasedCubeFinder::estimateParallelPlane(
00549 const jsk_recognition_utils::ConvexPolygon::Ptr convex,
00550 const pcl::PointCloud<PointT>::Ptr filtered_cloud,
00551 pcl::PointIndices::Ptr output_inliers,
00552 pcl::ModelCoefficients::Ptr output_coefficients)
00553 {
00554 Eigen::Vector3f normal = convex->getNormal();
00555 pcl::SACSegmentation<PointT> seg;
00556 seg.setOptimizeCoefficients (true);
00557 seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE);
00558 seg.setMethodType (pcl::SAC_RANSAC);
00559 seg.setDistanceThreshold (outlier_threshold_);
00560 seg.setInputCloud(filtered_cloud);
00561 seg.setMaxIterations (10000);
00562 seg.setAxis(normal);
00563 seg.setEpsAngle(pcl::deg2rad(10.0));
00564 seg.segment (*output_inliers, *output_coefficients);
00565 }
00566
00567 void EdgebasedCubeFinder::estimatePerpendicularPlane(
00568 const jsk_recognition_utils::ConvexPolygon::Ptr convex,
00569 const CoefficientsPair& edge_coefficients,
00570 const pcl::PointCloud<PointT>::Ptr filtered_cloud,
00571 pcl::PointIndices::Ptr output_inliers,
00572 pcl::ModelCoefficients::Ptr output_coefficients)
00573 {
00574 Eigen::Vector3f normal_a = convex->getNormal();
00575 jsk_recognition_utils::Line::Ptr mid_line = midLineFromCoefficientsPair(edge_coefficients);
00576 Eigen::Vector3f normal_b;
00577 mid_line->getDirection(normal_b);
00578 Eigen::Vector3f normal = normal_a.cross(normal_b);
00579 pcl::SACSegmentation<PointT> seg;
00580 seg.setOptimizeCoefficients (true);
00581 seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE);
00582 seg.setMethodType (pcl::SAC_RANSAC);
00583 seg.setDistanceThreshold (outlier_threshold_);
00584 seg.setInputCloud(filtered_cloud);
00585 seg.setMaxIterations (10000);
00586 seg.setAxis(normal);
00587 seg.setEpsAngle(pcl::deg2rad(5.0));
00588 seg.segment (*output_inliers, *output_coefficients);
00589 }
00590
00591 jsk_recognition_utils::Cube::Ptr EdgebasedCubeFinder::cubeFromIndicesAndCoefficients(
00592 const pcl::PointCloud<EdgebasedCubeFinder::PointT>::Ptr cloud,
00593 const IndicesCoefficientsTriple& indices_coefficients_triple,
00594 pcl::PointCloud<EdgebasedCubeFinder::PointT>::Ptr points_on_edge)
00595 {
00596 Eigen::Vector3f ex, ey, ez;
00597 CoefficientsTriple coefficients_triple
00598 = indices_coefficients_triple.get<1>();
00599 IndicesTriple indices_triple
00600 = indices_coefficients_triple.get<0>();
00601
00602 jsk_recognition_utils::Line::Ptr mid_line
00603 = jsk_recognition_utils::Line::fromCoefficients(coefficients_triple.get<0>()->values);
00604 jsk_recognition_utils::Line::Ptr line_a
00605 = jsk_recognition_utils::Line::fromCoefficients(coefficients_triple.get<1>()->values);
00606 jsk_recognition_utils::Line::Ptr line_b
00607 = jsk_recognition_utils::Line::fromCoefficients(coefficients_triple.get<2>()->values);
00608
00609 if (!mid_line->isSameDirection(*line_a)) {
00610 line_a = line_a->flip();
00611 }
00612 if (!mid_line->isSameDirection(*line_b)) {
00613 line_b = line_b->flip();
00614 }
00615 jsk_recognition_utils::Line::Ptr axis = line_a->midLine(*line_b);
00616
00617 pcl::PointCloud<PointT>::Ptr point_on_a
00618 = extractPointCloud(cloud,
00619 indices_triple.get<1>());
00620 pcl::PointCloud<PointT>::Ptr point_on_b
00621 = extractPointCloud(cloud,
00622 indices_triple.get<2>());
00623 pcl::PointCloud<PointT>::Ptr point_on_c
00624 = extractPointCloud(cloud,
00625 indices_triple.get<0>());
00626 Eigen::Vector4f a_centroid4, b_centroid4, c_centroid4;
00627 Eigen::Vector3f a_centroid, b_centroid, c_centroid;
00628 pcl::compute3DCentroid(*point_on_a, a_centroid4);
00629 pcl::compute3DCentroid(*point_on_b, b_centroid4);
00630 pcl::compute3DCentroid(*point_on_c, c_centroid4);
00631 jsk_recognition_utils::pointFromVectorToVector<Eigen::Vector4f, Eigen::Vector3f>(
00632 a_centroid4, a_centroid);
00633 jsk_recognition_utils::pointFromVectorToVector<Eigen::Vector4f, Eigen::Vector3f>(
00634 b_centroid4, b_centroid);
00635 jsk_recognition_utils::pointFromVectorToVector<Eigen::Vector4f, Eigen::Vector3f>(
00636 c_centroid4, c_centroid);
00637
00638 jsk_recognition_utils::Line::Ptr line_a_aligned = axis->parallelLineOnAPoint(a_centroid);
00639 jsk_recognition_utils::Line::Ptr line_b_aligned = axis->parallelLineOnAPoint(b_centroid);
00640 jsk_recognition_utils::Line::Ptr mid_line_aligned = axis->parallelLineOnAPoint(c_centroid);
00641
00642 pcl::PointCloud<PointT>::Ptr all_points(new pcl::PointCloud<PointT>);
00643 *all_points = *point_on_a + *point_on_b;
00644 *all_points = *all_points + *point_on_c;
00645 *points_on_edge = *all_points;
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 jsk_recognition_utils::PointPair min_max_points = minMaxPointOnLine(*axis, all_points);
00662 PointT min_point, max_point;
00663
00664
00665
00666
00667
00668
00669
00670
00671 Eigen::Vector3f center_point
00672 = (min_max_points.get<0>() + min_max_points.get<1>()) / 2.0;
00673 double z_width = (min_max_points.get<0>() - min_max_points.get<1>()).norm();
00674 mid_line_aligned->getDirection(ez);
00675 mid_line_aligned->parallelLineNormal(*line_a_aligned, ex);
00676 mid_line_aligned->parallelLineNormal(*line_b_aligned, ey);
00677
00678 double x_width = ex.norm();
00679 double y_width = ey.norm();
00680
00681 ex.normalize();
00682 ey.normalize();
00683 ez.normalize();
00684
00685 ROS_INFO("ex: [%f, %f, %f]", ex[0], ex[1], ex[2]);
00686 ROS_INFO("ey: [%f, %f, %f]", ey[0], ey[1], ey[2]);
00687 ROS_INFO("ez: [%f, %f, %f]", ez[0], ez[1], ez[2]);
00688
00689 if (ex.cross(ey).dot(ez) < 0) {
00690 ez = -ez;
00691 }
00692
00693 Eigen::Quaternionf rot = jsk_recognition_utils::rotFrom3Axis(ex, ey, ez);
00694 std::vector<double> dimensions;
00695 dimensions.push_back(x_width);
00696 dimensions.push_back(y_width);
00697 dimensions.push_back(z_width);
00698 jsk_recognition_utils::Cube::Ptr ret (new jsk_recognition_utils::Cube(center_point, rot, dimensions));
00699 return ret;
00700 }
00701
00702 void EdgebasedCubeFinder::estimate(
00703 const sensor_msgs::PointCloud2::ConstPtr& input_cloud,
00704 const jsk_recognition_msgs::ParallelEdgeArray::ConstPtr& input_edges)
00705 {
00706 boost::mutex::scoped_lock lock(mutex_);
00707 pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
00708 pcl::PointCloud<PointT>::Ptr all_filtered_cloud (new pcl::PointCloud<PointT>);
00709 pcl::fromROSMsg(*input_cloud, *cloud);
00710 visualization_msgs::Marker marker;
00711 jsk_recognition_msgs::PolygonArray polygon_array;
00712 geometry_msgs::PoseArray pose_array;
00713 jsk_recognition_msgs::BoundingBoxArray box_array;
00714 box_array.header = input_cloud->header;
00715 pose_array.header = input_cloud->header;
00716 std::vector<jsk_recognition_utils::Cube::Ptr> cubes;
00717 std::vector<pcl::PointIndices::Ptr> candidate_cluster_indices;
00718 for (size_t i = 0; i < input_edges->edge_groups.size(); i++) {
00719 jsk_recognition_msgs::ParallelEdge parallel_edge = input_edges->edge_groups[i];
00720 std::vector<pcl::PointIndices::Ptr> edges
00721 = pcl_conversions::convertToPCLPointIndices(
00722 parallel_edge.cluster_indices);
00723 std::vector<pcl::ModelCoefficients::Ptr> coefficients
00724 = pcl_conversions::convertToPCLModelCoefficients(
00725 parallel_edge.coefficients);
00726 std::vector<IndicesCoefficientsTriple> triples
00727 = tripleIndicesAndCoefficients(edges, coefficients);
00728 std::vector<IndicesCoefficientsTriple> perpendicular_triples
00729 = filterPerpendicularEdgeTriples(triples);
00730 if (perpendicular_triples.size() > 0) {
00731
00732 pcl::PointCloud<PointT>::Ptr points_on_edges(new pcl::PointCloud<PointT>);
00733 pcl_conversions::toPCL(input_cloud->header, points_on_edges->header);
00734 for (size_t j = 0; j < perpendicular_triples.size(); j++) {
00735 pcl::PointCloud<PointT>::Ptr points_on_edge(new pcl::PointCloud<PointT>);
00736 jsk_recognition_utils::Cube::Ptr cube = cubeFromIndicesAndCoefficients(
00737 cloud,
00738 perpendicular_triples[j],
00739 points_on_edge);
00740 *points_on_edges = *points_on_edges + *points_on_edge;
00741 cubes.push_back(cube);
00742 }
00743 pub_debug_filtered_cloud_.publish(points_on_edges);
00744 }
00745 }
00746
00747 if (cubes.size() > 0) {
00748 for (size_t i = 0; i < cubes.size(); i++) {
00749
00750 jsk_recognition_msgs::BoundingBox ros_box = cubes[i]->toROSMsg();
00751 ros_box.header = input_cloud->header;
00752 box_array.boxes.push_back(ros_box);
00753 pose_array.poses.push_back(ros_box.pose);
00754 }
00755 pub_.publish(box_array);
00756 pub_pose_array_.publish(pose_array);
00757 }
00758 }
00759
00760 bool EdgebasedCubeFinder::isPerpendicularVector(
00761 const Eigen::Vector3f& a,
00762 const Eigen::Vector3f& b)
00763 {
00764 double dot = a.normalized().dot(b.normalized());
00765 if (fabs(dot) >= 1.0) {
00766 return false;
00767 }
00768 else {
00769 double theta = fabs(acos(dot));
00770 NODELET_INFO("theta: %f", pcl::rad2deg(theta));
00771 if (fabs(theta - M_PI / 2.0) < pcl::deg2rad(20.0)) {
00772 return true;
00773 }
00774 else {
00775 return false;
00776 }
00777 }
00778 }
00779
00780 EdgebasedCubeFinder::EdgeRelation EdgebasedCubeFinder::perpendicularEdgeTriple(
00781 const jsk_recognition_utils::Line& edge_a,
00782 const jsk_recognition_utils::Line& edge_b,
00783 const jsk_recognition_utils::Line& edge_c)
00784 {
00785 Eigen::Vector3f a_b_normal, a_c_normal;
00786 edge_a.parallelLineNormal(edge_b, a_b_normal);
00787 edge_a.parallelLineNormal(edge_c, a_c_normal);
00788 if (isPerpendicularVector(a_b_normal, a_c_normal)) {
00789 return A_PERPENDICULAR;
00790 }
00791 else {
00792 Eigen::Vector3f b_a_normal, b_c_normal;
00793 edge_b.parallelLineNormal(edge_a, b_a_normal);
00794 edge_b.parallelLineNormal(edge_c, b_c_normal);
00795 if (isPerpendicularVector(b_a_normal, b_c_normal)) {
00796 return B_PERPENDICULAR;
00797 }
00798 else {
00799 Eigen::Vector3f c_a_normal, c_b_normal;
00800 edge_c.parallelLineNormal(edge_a, c_a_normal);
00801 edge_c.parallelLineNormal(edge_b, c_b_normal);
00802 if (isPerpendicularVector(c_a_normal, c_b_normal)) {
00803 return C_PERPENDICULAR;
00804 }
00805 else {
00806 return NOT_PERPENDICULAR;
00807 }
00808 }
00809 }
00810 }
00811
00812 std::vector<IndicesCoefficientsTriple>
00813 EdgebasedCubeFinder::filterPerpendicularEdgeTriples(
00814 const std::vector<IndicesCoefficientsTriple>& triples)
00815 {
00816 std::vector<IndicesCoefficientsTriple> ret;
00817 for (size_t i = 0; i < triples.size(); i++) {
00818 pcl::ModelCoefficients::Ptr a_coefficients
00819 = triples[i].get<1>().get<0>();
00820 pcl::ModelCoefficients::Ptr b_coefficients
00821 = triples[i].get<1>().get<1>();
00822 pcl::ModelCoefficients::Ptr c_coefficients
00823 = triples[i].get<1>().get<2>();
00824 jsk_recognition_utils::Line::Ptr edge_a
00825 = jsk_recognition_utils::Line::fromCoefficients(a_coefficients->values);
00826 jsk_recognition_utils::Line::Ptr edge_b
00827 = jsk_recognition_utils::Line::fromCoefficients(b_coefficients->values);
00828 jsk_recognition_utils::Line::Ptr edge_c
00829 = jsk_recognition_utils::Line::fromCoefficients(c_coefficients->values);
00830
00831 EdgeRelation relation = perpendicularEdgeTriple(*edge_a,
00832 *edge_b,
00833 *edge_c);
00834 if (relation != NOT_PERPENDICULAR) {
00835
00836 if (relation == A_PERPENDICULAR) {
00837 ret.push_back(triples[i]);
00838 }
00839 else if (relation == B_PERPENDICULAR) {
00840 IndicesCoefficientsTriple new_triple
00841 = boost::make_tuple(
00842 boost::make_tuple(triples[i].get<0>().get<1>(),
00843 triples[i].get<0>().get<0>(),
00844 triples[i].get<0>().get<2>()),
00845 boost::make_tuple(
00846 triples[i].get<1>().get<1>(),
00847 triples[i].get<1>().get<0>(),
00848 triples[i].get<1>().get<2>()));
00849 ret.push_back(new_triple);
00850 }
00851 else if (relation == C_PERPENDICULAR) {
00852 IndicesCoefficientsTriple new_triple
00853 = boost::make_tuple(
00854 boost::make_tuple(triples[i].get<0>().get<2>(),
00855 triples[i].get<0>().get<0>(),
00856 triples[i].get<0>().get<1>()),
00857 boost::make_tuple(
00858 triples[i].get<1>().get<2>(),
00859 triples[i].get<1>().get<0>(),
00860 triples[i].get<1>().get<1>()));
00861 ret.push_back(new_triple);
00862 }
00863 }
00864 }
00865 return ret;
00866 }
00867
00868 void EdgebasedCubeFinder::estimate2(
00869 const sensor_msgs::PointCloud2::ConstPtr& input_cloud,
00870 const jsk_recognition_msgs::ParallelEdgeArray::ConstPtr& input_edges)
00871 {
00872 boost::mutex::scoped_lock lock(mutex_);
00873 pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
00874 pcl::PointCloud<PointT>::Ptr all_filtered_cloud (new pcl::PointCloud<PointT>);
00875 pcl::fromROSMsg(*input_cloud, *cloud);
00876 visualization_msgs::Marker marker;
00877 jsk_recognition_msgs::PolygonArray polygon_array;
00878 std::vector<pcl::PointIndices::Ptr> candidate_cluster_indices;
00879
00880 polygon_array.header = input_cloud->header;
00881 marker.pose.orientation.w = 1.0;
00882 marker.color.a = 1.0;
00883 marker.color.r = 1.0;
00884 marker.header = input_cloud->header;
00885 marker.scale.x = 0.01;
00886 marker.type = visualization_msgs::Marker::LINE_LIST;
00887 NODELET_INFO("%lu parallel edge groups", input_edges->edge_groups.size());
00888 geometry_msgs::PoseArray pose_array;
00889 pose_array.header = input_cloud->header;
00890 jsk_recognition_msgs::BoundingBoxArray ros_output;
00891 ros_output.header = input_cloud->header;
00892
00893 for (size_t i = 0; i < input_edges->edge_groups.size(); i++) {
00894 jsk_recognition_msgs::ParallelEdge parallel_edge = input_edges->edge_groups[i];
00895
00896 if (parallel_edge.cluster_indices.size() <= 1) {
00897 NODELET_ERROR("parallel edge group has only %lu edges",
00898 parallel_edge.cluster_indices.size());
00899 continue;
00900 }
00901 NODELET_INFO("%lu parallel edge groups has %lu edges",
00902 i, parallel_edge.cluster_indices.size());
00904
00906 std::vector<pcl::PointIndices::Ptr> edges
00907 = pcl_conversions::convertToPCLPointIndices(
00908 parallel_edge.cluster_indices);
00909 std::vector<pcl::ModelCoefficients::Ptr> coefficients
00910 = pcl_conversions::convertToPCLModelCoefficients(
00911 parallel_edge.coefficients);
00912
00913 std::vector<IndicesPair> pairs = combinateIndices(edges);
00914 std::vector<CoefficientsPair> coefficients_pair
00915 = combinateCoefficients(coefficients);
00916 std::vector<IndicesPair> filtered_indices_pairs;
00917 std::vector<CoefficientsPair> filtered_coefficients_pairs;
00918
00919 filtered_indices_pairs = pairs;
00920 filtered_coefficients_pairs = coefficients_pair;
00921
00922
00923
00924
00925
00926 std::vector<jsk_recognition_utils::ConvexPolygon::Ptr> convexes;
00927 for (size_t j = 0; j < filtered_coefficients_pairs.size(); j++) {
00928 jsk_recognition_utils::ConvexPolygon::Ptr convex
00929 = convexFromPairs(cloud, filtered_coefficients_pairs[j],
00930 pairs[j]);
00931 convexes.push_back(convex);
00932 }
00933 std::vector<int> filtered_indices;
00934 filterBasedOnConvex(cloud, convexes, filtered_indices);
00935
00936 pcl::PointIndices::Ptr filtered_cube_candidate_indices(new pcl::PointIndices);
00937 for (size_t j = 0; j < filtered_indices.size(); j++) {
00938 int index = filtered_indices[j];
00939 jsk_recognition_utils::ConvexPolygon::Ptr target_convex = convexes[index];
00940 IndicesPair target_edge_indices_pair
00941 = filtered_indices_pairs[index];
00942 CoefficientsPair target_edge_coefficients_pair
00943 = filtered_coefficients_pairs[index];
00944
00945
00946 pcl::PointIndices::Ptr filtered_indices
00947 = preparePointCloudForRANSAC(
00948 target_convex, target_edge_coefficients_pair, cloud);
00949
00950
00951 filtered_cube_candidate_indices
00952 = jsk_recognition_utils::addIndices(*filtered_cube_candidate_indices,
00953 *filtered_indices);
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051 }
01052 candidate_cluster_indices.push_back(filtered_cube_candidate_indices);
01053
01054
01055 pcl::PointIndices::Ptr first_inliers(new pcl::PointIndices);
01056 pcl::ModelCoefficients::Ptr first_coefficients(new pcl::ModelCoefficients);
01057 jsk_recognition_utils::ConvexPolygon::Ptr first_polygon
01058 = estimateConvexPolygon(
01059 cloud,
01060 filtered_cube_candidate_indices,
01061 first_coefficients,
01062 first_inliers);
01063 if (first_polygon) {
01064 geometry_msgs::PolygonStamped first_polygon_ros;
01065 first_polygon_ros.polygon = first_polygon->toROSMsg();
01066 first_polygon_ros.header = input_cloud->header;
01067 polygon_array.polygons.push_back(first_polygon_ros);
01068 }
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104 }
01105 pub_.publish(ros_output);
01106 pub_pose_array_.publish(pose_array);
01107 pub_debug_marker_.publish(marker);
01108 sensor_msgs::PointCloud2 ros_cloud;
01109 pcl::toROSMsg(*all_filtered_cloud, ros_cloud);
01110 ros_cloud.header = input_cloud->header;
01111 pub_debug_filtered_cloud_.publish(ros_cloud);
01112 pub_debug_polygons_.publish(polygon_array);
01113
01114
01115 jsk_recognition_msgs::ClusterPointIndices ros_cluster_indices;
01116 ros_cluster_indices.header = input_cloud->header;
01117 for (size_t i = 0; i < candidate_cluster_indices.size(); i++) {
01118 PCLIndicesMsg indices_msg;
01119 indices_msg.header = input_cloud->header;
01120 indices_msg.indices = candidate_cluster_indices[i]->indices;
01121 ros_cluster_indices.cluster_indices.push_back(indices_msg);
01122 }
01123 pub_debug_clusers_.publish(ros_cluster_indices);
01124 }
01125
01126 std::vector<IndicesCoefficientsTriple>
01127 EdgebasedCubeFinder::tripleIndicesAndCoefficients(
01128 const std::vector<pcl::PointIndices::Ptr>& indices,
01129 const std::vector<pcl::ModelCoefficients::Ptr>& coefficients)
01130 {
01131 if (indices.size() != coefficients.size()) {
01132 NODELET_ERROR("size of indices and coefficients are not same");
01133 return std::vector<IndicesCoefficientsTriple>();
01134 }
01135
01136 if (indices.size() <= 2 && coefficients.size() <= 2) {
01137 NODELET_WARN("[EdgebasedCubeFinder::tripleIndicesAndCoefficients] no enough canddiates");
01138 return std::vector<IndicesCoefficientsTriple>();
01139 }
01140 std::vector<IndicesCoefficientsTriple> ret;
01141 for (size_t i = 0; i < indices.size() - 2; i++) {
01142 for (size_t j = i + 1; j < indices.size() - 1; j++) {
01143 for (size_t k = j + 1; k < indices.size(); k++) {
01144 IndicesTriple indices_triple
01145 = boost::make_tuple(indices[i],
01146 indices[j],
01147 indices[k]);
01148 CoefficientsTriple coefficients_triple
01149 = boost::make_tuple(coefficients[i],
01150 coefficients[j],
01151 coefficients[k]);
01152 IndicesCoefficientsTriple indices_coefficients_triple
01153 = boost::make_tuple(indices_triple,
01154 coefficients_triple);
01155 ret.push_back(indices_coefficients_triple);
01156 }
01157 }
01158 }
01159 return ret;
01160 }
01161
01162 jsk_recognition_utils::ConvexPolygon::Ptr EdgebasedCubeFinder::estimateConvexPolygon(
01163 const pcl::PointCloud<PointT>::Ptr cloud,
01164 const pcl::PointIndices::Ptr indices,
01165 pcl::ModelCoefficients::Ptr coefficients,
01166 pcl::PointIndices::Ptr inliers)
01167 {
01169
01171 pcl::SACSegmentation<PointT> seg;
01172 seg.setOptimizeCoefficients (true);
01173 seg.setModelType (pcl::SACMODEL_PLANE);
01174 seg.setMethodType (pcl::SAC_RANSAC);
01175 seg.setInputCloud(cloud);
01176 seg.setIndices(indices);
01177 seg.setDistanceThreshold(0.003);
01178 seg.segment(*inliers, *coefficients);
01180
01182 if (inliers->indices.size() > 0) {
01183 return jsk_recognition_utils::convexFromCoefficientsAndInliers<PointT>(
01184 cloud, inliers, coefficients);
01185 }
01186 else {
01187 return jsk_recognition_utils::ConvexPolygon::Ptr();
01188 }
01189 }
01190
01191 std::vector<IndicesPair> EdgebasedCubeFinder::combinateIndices(
01192 const std::vector<pcl::PointIndices::Ptr>& indices)
01193 {
01194 std::vector<IndicesPair> ret;
01195 for(size_t i = 0; i < indices.size() - 1; i++) {
01196 for (size_t j = i + 1; j < indices.size(); j++) {
01197 IndicesPair pair = boost::make_tuple(indices[i],
01198 indices[j]);
01199 ret.push_back(pair);
01200 }
01201 }
01202 return ret;
01203 }
01204
01205 std::vector<CoefficientsPair> EdgebasedCubeFinder::combinateCoefficients(
01206 const std::vector<pcl::ModelCoefficients::Ptr>& coefficients)
01207 {
01208 std::vector<CoefficientsPair> ret;
01209 for(size_t i = 0; i < coefficients.size() - 1; i++) {
01210 for (size_t j = i + 1; j < coefficients.size(); j++) {
01211 CoefficientsPair pair = boost::make_tuple(coefficients[i],
01212 coefficients[j]);
01213 ret.push_back(pair);
01214 }
01215 }
01216 return ret;
01217 }
01218 }
01219
01220 #include <pluginlib/class_list_macros.h>
01221 PLUGINLIB_EXPORT_CLASS (jsk_pcl_ros::EdgebasedCubeFinder, nodelet::Nodelet);
01222