edgebased_cube_finder_nodelet.cpp
Go to the documentation of this file.
1 // -*- mode: c++ -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2014, JSK Lab
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/o2r other materials provided
17  * with the distribution.
18  * * Neither the name of the JSK Lab nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 
37 #include <pcl/kdtree/kdtree_flann.h>
38 #include <pcl/common/centroid.h>
40 #include <jsk_recognition_msgs/BoundingBoxArray.h>
41 #include <geometry_msgs/PoseArray.h>
42 #include <pcl/filters/extract_indices.h>
43 #include <visualization_msgs/Marker.h>
45 #include <pcl/sample_consensus/method_types.h>
46 #include <pcl/sample_consensus/model_types.h>
47 #include <pcl/segmentation/sac_segmentation.h>
48 #include <pcl/common/angles.h>
49 #include <jsk_recognition_msgs/PolygonArray.h>
50 #include <jsk_recognition_msgs/ClusterPointIndices.h>
51 #include <pcl/filters/project_inliers.h>
52 #include <pcl/surface/convex_hull.h>
54 
55 namespace jsk_pcl_ros
56 {
58  const CoefficientsPair& coefficients_pair,
59  const double outlier_threshold):
60  value_(0.0), indices_pair_(pair), coefficients_pair_(coefficients_pair),
61  outlier_threshold_(outlier_threshold_)
62  {
63 
64  }
65 
67  {
68  }
69 
71  const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& cloud,
72  const pcl::PointIndices::Ptr& indices,
73  Eigen::Vector3f& output)
74  {
75  Eigen::Vector4f centroid;
76  //pcl::compute3DCentroid(cloud, indices.indices, centroid);
77  pcl::PointCloud<pcl::PointXYZRGB>::Ptr target_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
78  pcl::ExtractIndices<pcl::PointXYZRGB> ex;
79  ex.setInputCloud(cloud);
80  ex.setIndices(indices);
81  ex.filter(*target_cloud);
82  pcl::compute3DCentroid(*target_cloud, centroid);
83  jsk_recognition_utils::pointFromVectorToVector<Eigen::Vector4f, Eigen::Vector3f>(centroid, output);
84  }
85 
88  const pcl::PointCloud<pcl::PointXYZRGB>& cloud,
89  const pcl::PointIndices::Ptr indices,
91  {
92  pcl::PointCloud<pcl::PointXYZRGB>::Ptr points
93  (new pcl::PointCloud<pcl::PointXYZRGB>);
94  pcl::ExtractIndices<pcl::PointXYZRGB> extract;
95  extract.setInputCloud(cloud.makeShared());
96  extract.setIndices(indices);
97  extract.filter(*points);
98  for (size_t i = 0; i < points->points.size(); i++) {
99  pcl::PointXYZRGB p = points->points[i];
100  Eigen::Vector3f p_eigen = p.getVector3fMap();
101  Eigen::Vector3f foot_point;
102  line.foot(p_eigen, foot_point);
103  output.push_back(foot_point);
104  }
105  }
106 
108  const jsk_recognition_utils::PointPair& a_edge_pair, const jsk_recognition_utils::PointPair& b_edge_pair)
109  {
111  vertices.push_back(a_edge_pair.get<0>());
112  vertices.push_back(a_edge_pair.get<1>());
113  vertices.push_back(b_edge_pair.get<1>());
114  vertices.push_back(b_edge_pair.get<0>());
116  return convex;
117  }
118 
120  const pcl::PointCloud<pcl::PointXYZRGB>& cloud,
123  {
124  std::vector<int> a_indices, b_indices;
125  for (size_t i = 0; i < cloud.points.size(); i++) {
126  pcl::PointXYZRGB pcl_point = cloud.points[i];
127  if (pcl_isfinite(pcl_point.x) &&
128  pcl_isfinite(pcl_point.y) &&
129  pcl_isfinite(pcl_point.z)) { // we don't care nan points
130  Eigen::Vector3f eigen_point = pcl_point.getVector3fMap();
131  if (polygon_a.distanceSmallerThan(eigen_point, outlier_threshold_)) {
132  a_indices.push_back(i);
133  }
134  if (polygon_b.distanceSmallerThan(eigen_point, outlier_threshold_)) {
135  b_indices.push_back(i);
136  }
137  }
138  }
139  // ...the number of points...?
140  return a_indices.size() + b_indices.size();
141  }
142 
144  const jsk_recognition_utils::Line& axis,
145  const jsk_recognition_utils::PointPair& a_candidates,
146  const jsk_recognition_utils::PointPair& b_candidates)
147  {
148  jsk_recognition_utils::Vertices original_points;
149  original_points.push_back(a_candidates.get<0>());
150  original_points.push_back(a_candidates.get<1>());
151  original_points.push_back(b_candidates.get<0>());
152  original_points.push_back(b_candidates.get<1>());
153  for (size_t i = 0; i < original_points.size(); i++) {
154  Eigen::Vector3f p = original_points[i];
155  ROS_INFO("[foot_point] [%f, %f, %f]", p[0], p[1], p[2]);
156  }
157 
159  for (size_t i = 0; i < original_points.size(); i++) {
160  Eigen::Vector3f foot_point;
161  axis.foot(original_points[i], foot_point);
162  foot_points.push_back(foot_point);
163  }
164  double max_alpha = -DBL_MAX;
165  double min_alpha = DBL_MAX;
166  Eigen::Vector3f max_alpha_point, min_alpha_point;
167 
168  for (size_t i = 0; i < foot_points.size(); i++) {
169  double alpha = axis.computeAlpha(foot_points[i]);
170  if (alpha > max_alpha) {
171  max_alpha = alpha;
172  max_alpha_point = foot_points[i];
173  }
174  if (alpha < min_alpha) {
175  min_alpha = alpha;
176  min_alpha_point = foot_points[i];
177  }
178  }
179  ROS_INFO("min_alpha_point: [%f, %f, %f]", min_alpha_point[0], min_alpha_point[1], min_alpha_point[2]);
180  ROS_INFO("max_alpha_point: [%f, %f, %f]", max_alpha_point[0], max_alpha_point[1], max_alpha_point[2]);
181  return boost::make_tuple(min_alpha_point, max_alpha_point);
182  }
183 
184 
186  const IndicesPair& pair, const CoefficientsPair& coefficients_pair, const double outlier_threshold):
187  CubeHypothesis(pair, coefficients_pair, outlier_threshold)
188  {
189 
190  }
191 
193  const IndicesPair& pair, const CoefficientsPair& coefficients_pair,
194  const double outlier_threshold):
195  CubeHypothesis(pair, coefficients_pair, outlier_threshold), resolution_(10)
196  {
197 
198  }
199 
201  const pcl::PointCloud<pcl::PointXYZRGB>& cloud)
202  {
203  const double dt = (M_PI - 2.0 * min_angle_) / resolution_;
208  if (!line_a->isSameDirection(*line_b)) {
209  line_b = line_b->flip();
210  }
211 
212  const double r2 = line_a->distance(*line_b);
213  const double r = r2 / 2;
214  jsk_recognition_utils::Line::Ptr axis = line_a->midLine(*line_b);
215  Eigen::Vector3f center;
216  axis->getOrigin(center);
217  ROS_INFO("line_a:");
218  line_a->print();
219  ROS_INFO("line_b:");
220  line_b->print();
221  ROS_INFO("axis:");
222  axis->print();
223  ROS_INFO("r: %f", r);
224 
225  // before evaluation, we fix line_a and line_b to be parallel
226  // against line_c and axis.
227  // in order to align line_a and line_b, we compute centroids of the points
228  // on line_a and line_b and rotate the lines around the points.
229  Eigen::Vector3f centroid_a, centroid_b;
230  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_ptr = cloud.makeShared();
231  computeCentroid(cloud_ptr, indices_pair_.get<0>(), centroid_a);
232  computeCentroid(cloud_ptr, indices_pair_.get<1>(), centroid_b);
233  ROS_INFO("centroid_a: [%f, %f, %f]", centroid_a[0], centroid_a[1], centroid_a[2]);
234  ROS_INFO("centroid_b: [%f, %f, %f]", centroid_b[0], centroid_b[1], centroid_b[2]);
235  jsk_recognition_utils::Line::Ptr line_a_aligned = axis->parallelLineOnAPoint(centroid_a);
236  jsk_recognition_utils::Line::Ptr line_b_aligned = axis->parallelLineOnAPoint(centroid_b);
237  ROS_INFO("line_a_aligned:");
238  line_a_aligned->print();
239  ROS_INFO("line_b_aligned:");
240  line_b_aligned->print();
241 
242  jsk_recognition_utils::Vertices line_a_points, line_b_points;
243  getLinePoints(*line_a_aligned, cloud, indices_pair_.get<0>(),
244  line_a_points);
245  getLinePoints(*line_b_aligned, cloud, indices_pair_.get<1>(),
246  line_b_points);
247  jsk_recognition_utils::PointPair line_a_end_points = line_a->findEndPoints(line_a_points);
248  jsk_recognition_utils::PointPair line_b_end_points = line_b->findEndPoints(line_b_points);
249  double max_v = - DBL_MAX;
250  double max_theta;
252  jsk_recognition_utils::PointPair max_line_c_a_points, max_line_c_b_points;
253  for (size_t i = 0; i < resolution_; i++) {
254  ROS_INFO("estimate i: %lu", i);
255  double theta = dt * i + min_angle_;
256  Eigen::Vector3f point_on_x;
257  line_a->foot(center, point_on_x);
258  // 2D local cooridnate: r * cos(theta), r * sin(theta)
259  // convert it according to axis
260  // x // (point_on_x - center)
261  // z // axis
262  Eigen::Vector3f ex = (point_on_x - center).normalized();
263  Eigen::Vector3f ez;
264  axis->getDirection(ez);
265  Eigen::Vector3f ey = ez.cross(ex).normalized();
266  // ey should direct to origin. If not, ex should be flipped
267  if (center.dot(ey) > 0) {
268  ex = -ex;
269  ey = ez.cross(ex).normalized();
270  }
271  Eigen::Vector3f point_on_y = center + r * ey;
272  jsk_recognition_utils::Line::Ptr line_c = axis->parallelLineOnAPoint(point_on_y);
273  // line_a, b, c are almost parallel and these 3 lines make
274  // 2 planes.
275  // ------------------------ line_a
276  // / A /
277  // ----------------------- line_c
278  // \ B \
279  // ----------------------- line_b
280 
281  // in order to evaluate plane A, first we exract the points
282  // which have distance |line_a - line_c| + margin from line_c.
283  // Second, For all those points, count all the points whose distance from
284  // plane A is smaller than margin.
285  // Thrid, we compute the area of the plane A and normalize the value.
286  Eigen::Vector3f line_c_a_min_point, line_c_a_max_point;
287  Eigen::Vector3f line_c_b_min_point, line_c_b_max_point;
288  line_c->foot(line_a_end_points.get<0>(), line_c_a_min_point);
289  line_c->foot(line_a_end_points.get<1>(), line_c_a_max_point);
290  line_c->foot(line_b_end_points.get<0>(), line_c_b_min_point);
291  line_c->foot(line_b_end_points.get<1>(), line_c_b_max_point);
292  jsk_recognition_utils::PointPair line_c_a_end_points = boost::make_tuple(line_c_a_min_point,
293  line_c_a_max_point);
294  jsk_recognition_utils::PointPair line_c_b_end_points = boost::make_tuple(line_c_b_min_point,
295  line_c_b_max_point);
297  line_c_a_end_points);
299  line_c_b_end_points);
300  double v = evaluatePointOnPlanes(cloud, *plane_a, *plane_b);
301  if (max_v < v) {
302  max_v = v;
303  max_theta = theta;
304  max_line_c = line_c;
305  max_line_c_a_points = line_c_a_end_points;
306  max_line_c_b_points = line_c_b_end_points;
307  }
308  }
309  value_ = max_v;
310  // estimate centroid
312  *axis,
313  max_line_c_a_points,
314  max_line_c_b_points);
315  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]);
316  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]);
317  Eigen::Vector3f midpoint
318  = (axis_end_points.get<0>() + axis_end_points.get<1>()) / 2.0;
319  double z_dimension = (axis_end_points.get<0>() - midpoint).norm() * 2;
320  // compute cube
321  ROS_INFO("midpoint: [%f, %f, %f]", midpoint[0], midpoint[1], midpoint[2]);
322  cube_.reset(new jsk_recognition_utils::Cube(midpoint, *line_a_aligned, *line_b_aligned, *max_line_c));
323  std::vector<double> dimensions = cube_->getDimensions();
324  dimensions[2] = z_dimension;
325  cube_->setDimensions(dimensions);
326  }
327 
329  const pcl::PointCloud<PointT>::Ptr cloud,
331  {
332  int num = 0;
333  for (size_t i = 0; i < cloud->points.size(); i++) {
334  PointT p = cloud->points[i];
335  if (!std::isnan(p.x) && !std::isnan(p.y) && !std::isnan(p.z)) {
336  Eigen::Vector3f ep = p.getVector3fMap();
337  if (convex->distanceSmallerThan(ep, outlier_threshold_)) {
338  num++;
339  }
340  }
341  }
342  return num;
343  }
344 
346  const pcl::PointCloud<PointT>::Ptr cloud,
347  const std::vector<jsk_recognition_utils::ConvexPolygon::Ptr>& convexes,
348  std::vector<int>& output_indices)
349  {
350 
351  for (size_t i = 0; i < convexes.size(); i++) {
352  jsk_recognition_utils::ConvexPolygon::Ptr convex = convexes[i];
353  if (true) {
354  // if (convex->area() > convex_area_threshold_ &&
355  // convex->allEdgesLongerThan(convex_edge_threshold_)) {
356  //int inliers = countInliers(cloud, convex);
357  //ROS_INFO("inliers: %d", inliers);
358  //if (inliers > min_inliers_) {
359  if (true) {
360  output_indices.push_back(i);
361  }
362  }
363  }
364  }
365 
366  void EdgebasedCubeFinder::configCallback (Config &config, uint32_t level)
367  {
368  boost::mutex::scoped_lock lock(mutex_);
369  outlier_threshold_ = config.outlier_threshold;
370  min_inliers_ = config.min_inliers;
371  convex_area_threshold_ = config.convex_area_threshold;
372  convex_edge_threshold_ = config.convex_edge_threshold;
373  parallel_edge_distance_min_threshold_ = config.parallel_edge_distance_min_threshold;
374  parallel_edge_distance_max_threshold_ = config.parallel_edge_distance_max_threshold;
375  }
376 
378  {
379  ConnectionBasedNodelet::onInit();
380 
381 
382  srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
383  dynamic_reconfigure::Server<Config>::CallbackType f =
384  boost::bind (&EdgebasedCubeFinder::configCallback, this, _1, _2);
385  srv_->setCallback (f);
386 
387 
389  // publishers
391  pub_ = advertise<jsk_recognition_msgs::BoundingBoxArray>(*pnh_, "output", 1);
392  pub_pose_array_
393  = advertise<geometry_msgs::PoseArray>(*pnh_, "output_pose_array", 1);
394  pub_debug_marker_
395  = advertise<visualization_msgs::Marker>(*pnh_, "debug_marker", 1);
396  pub_debug_filtered_cloud_ = advertise<sensor_msgs::PointCloud2>(
397  *pnh_, "debug_filtered_cloud", 1);
398  pub_debug_polygons_
399  = advertise<jsk_recognition_msgs::PolygonArray>(*pnh_, "debug_polygons", 1);
400  pub_debug_clusers_
401  = advertise<jsk_recognition_msgs::ClusterPointIndices>(*pnh_, "debug_clusters", 1);
402 
403  onInitPostProcess();
404  }
405 
407  {
409  // subscription
411  sub_input_.subscribe(*pnh_, "input", 1);
412  sub_edges_.subscribe(*pnh_, "input_edges", 1);
413  sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
414  sync_->connectInput(sub_input_, sub_edges_);
415  sync_->registerCallback(boost::bind(
416  &EdgebasedCubeFinder::estimate, this, _1, _2));
417  }
418 
420  {
421  sub_input_.unsubscribe();
422  sub_edges_.unsubscribe();
423  }
424 
426  const CoefficientsPair& pair)
427  {
428  pcl::ModelCoefficients::Ptr coefficients_a = pair.get<0>();
429  pcl::ModelCoefficients::Ptr coefficients_b = pair.get<1>();
432  return line_a->midLine(*line_b);
433  }
434 
435  pcl::PointCloud<EdgebasedCubeFinder::PointT>::Ptr EdgebasedCubeFinder::extractPointCloud(
436  const pcl::PointCloud<PointT>::Ptr cloud,
437  const pcl::PointIndices::Ptr indices)
438  {
439  pcl::PointCloud<PointT>::Ptr ret (new pcl::PointCloud<PointT>);
440  pcl::ExtractIndices<PointT> ex;
441  ex.setInputCloud(cloud);
442  ex.setIndices(indices);
443  ex.filter(*ret);
444  return ret;
445  }
446 
449  const pcl::PointCloud<PointT>::Ptr cloud)
450  {
452  for (size_t i = 0; i < cloud->points.size(); i++) {
453  PointT p = cloud->points[i];
454  Eigen::Vector3f eigen_p = p.getVector3fMap();
455  Eigen::Vector3f foot;
456  line.foot(eigen_p, foot);
457  points.push_back(foot);
458  }
459  return line.findEndPoints(points);
460  }
461 
463  const pcl::PointCloud<PointT>::Ptr cloud,
464  const CoefficientsPair& coefficients_pair,
465  const IndicesPair& indices_pair)
466  {
467  pcl::ModelCoefficients::Ptr coefficients_a = coefficients_pair.get<0>();
468  pcl::ModelCoefficients::Ptr coefficients_b = coefficients_pair.get<1>();
469  pcl::PointIndices::Ptr indices_a = indices_pair.get<0>();
470  pcl::PointIndices::Ptr indices_b = indices_pair.get<1>();
471 
472  pcl::PointCloud<PointT>::Ptr cloud_a = extractPointCloud(cloud, indices_a);
473  pcl::PointCloud<PointT>::Ptr cloud_b = extractPointCloud(cloud, indices_b);
474 
477  jsk_recognition_utils::PointPair a_min_max = minMaxPointOnLine(*line_a, cloud_a);
478  jsk_recognition_utils::PointPair b_min_max = minMaxPointOnLine(*line_b, cloud_b);
480  vertices.push_back(a_min_max.get<0>());
481  vertices.push_back(a_min_max.get<1>());
482  vertices.push_back(b_min_max.get<1>());
483  vertices.push_back(b_min_max.get<0>());
485  return ret;
486  }
487 
489  const std::vector<IndicesPair>& pairs,
490  const std::vector<CoefficientsPair>& coefficients_pair,
491  std::vector<IndicesPair>& filtered_indices_pairs,
492  std::vector<CoefficientsPair>& filtered_coefficients_pairs)
493  {
494  for (size_t i = 0; i < coefficients_pair.size(); i++) {
495  CoefficientsPair coefficients = coefficients_pair[i];
496  pcl::ModelCoefficients::Ptr coefficients_a = coefficients_pair[i].get<0>();
497  pcl::ModelCoefficients::Ptr coefficients_b = coefficients_pair[i].get<1>();
500 
501  // force to align two lines
502  jsk_recognition_utils::Line::Ptr axis = line_a->midLine(*line_b);
503  Eigen::Vector3f origin_a, origin_b;
504  line_a->getOrigin(origin_a);
505  line_b->getOrigin(origin_b);
506  jsk_recognition_utils::Line::Ptr line_a_aligned = axis->parallelLineOnAPoint(origin_a);
507  jsk_recognition_utils::Line::Ptr line_b_aligned = axis->parallelLineOnAPoint(origin_b);
508  Eigen::Vector3f distance_vector;
509  line_a_aligned->parallelLineNormal(*line_b_aligned, distance_vector);
510  double distance = distance_vector.norm();
511  //double distance = line_a_aligned->distance(*line_b_aligned);
512  ROS_INFO("d: %f", distance);
513  if (distance < parallel_edge_distance_max_threshold_ &&
514  distance > parallel_edge_distance_min_threshold_) {
515  filtered_indices_pairs.push_back(pairs[i]);
516  filtered_coefficients_pairs.push_back(coefficients);
517  }
518  }
519  }
520 
521  //pcl::PointCloud<EdgebasedCubeFinder::PointT>::Ptr
522  pcl::PointIndices::Ptr
525  const CoefficientsPair& edge_coefficients_pair,
526  const pcl::PointCloud<PointT>::Ptr cloud)
527  {
528  // extract the points which can be projected onto the convex.
529  pcl::PointIndices::Ptr indices(new pcl::PointIndices);
530  jsk_recognition_utils::ConvexPolygon::Ptr magnified_convex = convex->magnify(1.1);
531  pcl::PointCloud<PointT>::Ptr ret (new pcl::PointCloud<PointT>);
532  for (size_t i = 0; i < cloud->points.size(); i++) {
533  PointT p = cloud->points[i];
534  if (!std::isnan(p.x) && !std::isnan(p.y) && !std::isnan(p.z)) {
535  Eigen::Vector3f ep = p.getVector3fMap();
536  Eigen::Vector3f foot;
537  magnified_convex->projectOnPlane(ep, foot);
538  if (magnified_convex->isInside(foot) && convex->distanceSmallerThan(ep, outlier_threshold_)) {
539  //if (magnified_convex->isInside(foot) && (ep - foot).norm()) {
540  //NODELET_INFO("distance: %f", (ep - foot).norm());
541  indices->indices.push_back(i);
542  }
543  }
544  }
545  return indices;
546  }
547 
550  const pcl::PointCloud<PointT>::Ptr filtered_cloud,
551  pcl::PointIndices::Ptr output_inliers,
552  pcl::ModelCoefficients::Ptr output_coefficients)
553  {
554  Eigen::Vector3f normal = convex->getNormal();
555  pcl::SACSegmentation<PointT> seg;
556  seg.setOptimizeCoefficients (true);
557  seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE);
558  seg.setMethodType (pcl::SAC_RANSAC);
559  seg.setDistanceThreshold (outlier_threshold_);
560  seg.setInputCloud(filtered_cloud);
561  seg.setMaxIterations (10000);
562  seg.setAxis(normal);
563  seg.setEpsAngle(pcl::deg2rad(10.0));
564  seg.segment (*output_inliers, *output_coefficients);
565  }
566 
569  const CoefficientsPair& edge_coefficients,
570  const pcl::PointCloud<PointT>::Ptr filtered_cloud,
571  pcl::PointIndices::Ptr output_inliers,
572  pcl::ModelCoefficients::Ptr output_coefficients)
573  {
574  Eigen::Vector3f normal_a = convex->getNormal();
575  jsk_recognition_utils::Line::Ptr mid_line = midLineFromCoefficientsPair(edge_coefficients);
576  Eigen::Vector3f normal_b;
577  mid_line->getDirection(normal_b);
578  Eigen::Vector3f normal = normal_a.cross(normal_b);
579  pcl::SACSegmentation<PointT> seg;
580  seg.setOptimizeCoefficients (true);
581  seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE);
582  seg.setMethodType (pcl::SAC_RANSAC);
583  seg.setDistanceThreshold (outlier_threshold_);
584  seg.setInputCloud(filtered_cloud);
585  seg.setMaxIterations (10000);
586  seg.setAxis(normal);
587  seg.setEpsAngle(pcl::deg2rad(5.0));
588  seg.segment (*output_inliers, *output_coefficients);
589  }
590 
592  const pcl::PointCloud<EdgebasedCubeFinder::PointT>::Ptr cloud,
593  const IndicesCoefficientsTriple& indices_coefficients_triple,
594  pcl::PointCloud<EdgebasedCubeFinder::PointT>::Ptr points_on_edge)
595  {
596  Eigen::Vector3f ex, ey, ez;
597  CoefficientsTriple coefficients_triple
598  = indices_coefficients_triple.get<1>();
599  IndicesTriple indices_triple
600  = indices_coefficients_triple.get<0>();
601  // do we need to align lines...??
603  = jsk_recognition_utils::Line::fromCoefficients(coefficients_triple.get<0>()->values);
605  = jsk_recognition_utils::Line::fromCoefficients(coefficients_triple.get<1>()->values);
607  = jsk_recognition_utils::Line::fromCoefficients(coefficients_triple.get<2>()->values);
608  // force to align
609  if (!mid_line->isSameDirection(*line_a)) {
610  line_a = line_a->flip();
611  }
612  if (!mid_line->isSameDirection(*line_b)) {
613  line_b = line_b->flip();
614  }
615  jsk_recognition_utils::Line::Ptr axis = line_a->midLine(*line_b);
616 
617  pcl::PointCloud<PointT>::Ptr point_on_a
618  = extractPointCloud(cloud,
619  indices_triple.get<1>());
620  pcl::PointCloud<PointT>::Ptr point_on_b
621  = extractPointCloud(cloud,
622  indices_triple.get<2>());
623  pcl::PointCloud<PointT>::Ptr point_on_c
624  = extractPointCloud(cloud,
625  indices_triple.get<0>());
626  Eigen::Vector4f a_centroid4, b_centroid4, c_centroid4;
627  Eigen::Vector3f a_centroid, b_centroid, c_centroid;
628  pcl::compute3DCentroid(*point_on_a, a_centroid4);
629  pcl::compute3DCentroid(*point_on_b, b_centroid4);
630  pcl::compute3DCentroid(*point_on_c, c_centroid4);
631  jsk_recognition_utils::pointFromVectorToVector<Eigen::Vector4f, Eigen::Vector3f>(
632  a_centroid4, a_centroid);
633  jsk_recognition_utils::pointFromVectorToVector<Eigen::Vector4f, Eigen::Vector3f>(
634  b_centroid4, b_centroid);
635  jsk_recognition_utils::pointFromVectorToVector<Eigen::Vector4f, Eigen::Vector3f>(
636  c_centroid4, c_centroid);
637 
638  jsk_recognition_utils::Line::Ptr line_a_aligned = axis->parallelLineOnAPoint(a_centroid);
639  jsk_recognition_utils::Line::Ptr line_b_aligned = axis->parallelLineOnAPoint(b_centroid);
640  jsk_recognition_utils::Line::Ptr mid_line_aligned = axis->parallelLineOnAPoint(c_centroid);
641  //Line::Ptr axis_aligned = axis->parallelLineOnAPoint(c_centroid);
642  pcl::PointCloud<PointT>::Ptr all_points(new pcl::PointCloud<PointT>);
643  *all_points = *point_on_a + *point_on_b;
644  *all_points = *all_points + *point_on_c;
645  *points_on_edge = *all_points;
646 
647  // PointT a_centroid_p, b_centroid_p, c_centroid_p;
648  // a_centroid_p.x = a_centroid[0];
649  // a_centroid_p.y = a_centroid[1];
650  // a_centroid_p.z = a_centroid[2];
651  // b_centroid_p.x = b_centroid[0];
652  // b_centroid_p.y = b_centroid[1];
653  // b_centroid_p.z = b_centroid[2];
654  // c_centroid_p.x = c_centroid[0];
655  // c_centroid_p.y = c_centroid[1];
656  // c_centroid_p.z = c_centroid[2];
657  // points_on_edge->points.push_back(a_centroid_p);
658  // points_on_edge->points.push_back(b_centroid_p);
659  // points_on_edge->points.push_back(c_centroid_p);
660 
661  jsk_recognition_utils::PointPair min_max_points = minMaxPointOnLine(*axis, all_points);
662  PointT min_point, max_point;
663  // min_point.x = min_max_points.get<0>()[0];
664  // min_point.y = min_max_points.get<0>()[1];
665  // min_point.z = min_max_points.get<0>()[2];
666  // max_point.x = min_max_points.get<1>()[0];
667  // max_point.y = min_max_points.get<1>()[1];
668  // max_point.z = min_max_points.get<1>()[2];
669  // points_on_edge->points.push_back(min_point);
670  // points_on_edge->points.push_back(max_point);
671  Eigen::Vector3f center_point
672  = (min_max_points.get<0>() + min_max_points.get<1>()) / 2.0;
673  double z_width = (min_max_points.get<0>() - min_max_points.get<1>()).norm();
674  mid_line_aligned->getDirection(ez);
675  mid_line_aligned->parallelLineNormal(*line_a_aligned, ex);
676  mid_line_aligned->parallelLineNormal(*line_b_aligned, ey);
677 
678  double x_width = ex.norm();
679  double y_width = ey.norm();
680 
681  ex.normalize();
682  ey.normalize();
683  ez.normalize();
684 
685  ROS_INFO("ex: [%f, %f, %f]", ex[0], ex[1], ex[2]);
686  ROS_INFO("ey: [%f, %f, %f]", ey[0], ey[1], ey[2]);
687  ROS_INFO("ez: [%f, %f, %f]", ez[0], ez[1], ez[2]);
688 
689  if (ex.cross(ey).dot(ez) < 0) {
690  ez = -ez;
691  }
692 
693  Eigen::Quaternionf rot = jsk_recognition_utils::rotFrom3Axis(ex, ey, ez);
694  std::vector<double> dimensions;
695  dimensions.push_back(x_width);
696  dimensions.push_back(y_width);
697  dimensions.push_back(z_width);
698  jsk_recognition_utils::Cube::Ptr ret (new jsk_recognition_utils::Cube(center_point, rot, dimensions));
699  return ret;
700  }
701 
703  const sensor_msgs::PointCloud2::ConstPtr& input_cloud,
704  const jsk_recognition_msgs::ParallelEdgeArray::ConstPtr& input_edges)
705  {
706  boost::mutex::scoped_lock lock(mutex_);
707  pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
708  pcl::PointCloud<PointT>::Ptr all_filtered_cloud (new pcl::PointCloud<PointT>);
709  pcl::fromROSMsg(*input_cloud, *cloud);
710  visualization_msgs::Marker marker;
711  jsk_recognition_msgs::PolygonArray polygon_array;
712  geometry_msgs::PoseArray pose_array;
713  jsk_recognition_msgs::BoundingBoxArray box_array;
714  box_array.header = input_cloud->header;
715  pose_array.header = input_cloud->header;
716  std::vector<jsk_recognition_utils::Cube::Ptr> cubes;
717  std::vector<pcl::PointIndices::Ptr> candidate_cluster_indices;
718  for (size_t i = 0; i < input_edges->edge_groups.size(); i++) {
719  jsk_recognition_msgs::ParallelEdge parallel_edge = input_edges->edge_groups[i];
720  std::vector<pcl::PointIndices::Ptr> edges
722  parallel_edge.cluster_indices);
723  std::vector<pcl::ModelCoefficients::Ptr> coefficients
725  parallel_edge.coefficients);
726  std::vector<IndicesCoefficientsTriple> triples
727  = tripleIndicesAndCoefficients(edges, coefficients);
728  std::vector<IndicesCoefficientsTriple> perpendicular_triples
729  = filterPerpendicularEdgeTriples(triples);
730  if (perpendicular_triples.size() > 0) {
731  // buildup cube instance...
732  pcl::PointCloud<PointT>::Ptr points_on_edges(new pcl::PointCloud<PointT>);
733  pcl_conversions::toPCL(input_cloud->header, points_on_edges->header);
734  for (size_t j = 0; j < perpendicular_triples.size(); j++) {
735  pcl::PointCloud<PointT>::Ptr points_on_edge(new pcl::PointCloud<PointT>);
736  jsk_recognition_utils::Cube::Ptr cube = cubeFromIndicesAndCoefficients(
737  cloud,
738  perpendicular_triples[j],
739  points_on_edge);
740  *points_on_edges = *points_on_edges + *points_on_edge;
741  cubes.push_back(cube);
742  }
743  pub_debug_filtered_cloud_.publish(points_on_edges);
744  }
745  }
746 
747  if (cubes.size() > 0) {
748  for (size_t i = 0; i < cubes.size(); i++) {
749  // publish cubes
750  jsk_recognition_msgs::BoundingBox ros_box = cubes[i]->toROSMsg();
751  ros_box.header = input_cloud->header;
752  box_array.boxes.push_back(ros_box);
753  pose_array.poses.push_back(ros_box.pose);
754  }
755  pub_.publish(box_array);
756  pub_pose_array_.publish(pose_array);
757  }
758  }
759 
761  const Eigen::Vector3f& a,
762  const Eigen::Vector3f& b)
763  {
764  double dot = a.normalized().dot(b.normalized());
765  if (fabs(dot) >= 1.0) {
766  return false;
767  }
768  else {
769  double theta = fabs(acos(dot));
770  NODELET_INFO("theta: %f", pcl::rad2deg(theta));
771  if (fabs(theta - M_PI / 2.0) < pcl::deg2rad(20.0)) {
772  return true;
773  }
774  else {
775  return false;
776  }
777  }
778  }
779 
781  const jsk_recognition_utils::Line& edge_a,
782  const jsk_recognition_utils::Line& edge_b,
783  const jsk_recognition_utils::Line& edge_c)
784  {
785  Eigen::Vector3f a_b_normal, a_c_normal;
786  edge_a.parallelLineNormal(edge_b, a_b_normal);
787  edge_a.parallelLineNormal(edge_c, a_c_normal);
788  if (isPerpendicularVector(a_b_normal, a_c_normal)) {
789  return A_PERPENDICULAR;
790  }
791  else {
792  Eigen::Vector3f b_a_normal, b_c_normal;
793  edge_b.parallelLineNormal(edge_a, b_a_normal);
794  edge_b.parallelLineNormal(edge_c, b_c_normal);
795  if (isPerpendicularVector(b_a_normal, b_c_normal)) {
796  return B_PERPENDICULAR;
797  }
798  else {
799  Eigen::Vector3f c_a_normal, c_b_normal;
800  edge_c.parallelLineNormal(edge_a, c_a_normal);
801  edge_c.parallelLineNormal(edge_b, c_b_normal);
802  if (isPerpendicularVector(c_a_normal, c_b_normal)) {
803  return C_PERPENDICULAR;
804  }
805  else {
806  return NOT_PERPENDICULAR;
807  }
808  }
809  }
810  }
811 
812  std::vector<IndicesCoefficientsTriple>
814  const std::vector<IndicesCoefficientsTriple>& triples)
815  {
816  std::vector<IndicesCoefficientsTriple> ret;
817  for (size_t i = 0; i < triples.size(); i++) {
818  pcl::ModelCoefficients::Ptr a_coefficients
819  = triples[i].get<1>().get<0>();
820  pcl::ModelCoefficients::Ptr b_coefficients
821  = triples[i].get<1>().get<1>();
822  pcl::ModelCoefficients::Ptr c_coefficients
823  = triples[i].get<1>().get<2>();
825  = jsk_recognition_utils::Line::fromCoefficients(a_coefficients->values);
827  = jsk_recognition_utils::Line::fromCoefficients(b_coefficients->values);
829  = jsk_recognition_utils::Line::fromCoefficients(c_coefficients->values);
830  // check if these three are perpendicular or not
831  EdgeRelation relation = perpendicularEdgeTriple(*edge_a,
832  *edge_b,
833  *edge_c);
834  if (relation != NOT_PERPENDICULAR) {
835  // rearrange
836  if (relation == A_PERPENDICULAR) {
837  ret.push_back(triples[i]);
838  }
839  else if (relation == B_PERPENDICULAR) {
840  IndicesCoefficientsTriple new_triple
841  = boost::make_tuple(
842  boost::make_tuple(triples[i].get<0>().get<1>(),
843  triples[i].get<0>().get<0>(),
844  triples[i].get<0>().get<2>()),
845  boost::make_tuple(
846  triples[i].get<1>().get<1>(),
847  triples[i].get<1>().get<0>(),
848  triples[i].get<1>().get<2>()));
849  ret.push_back(new_triple);
850  }
851  else if (relation == C_PERPENDICULAR) {
852  IndicesCoefficientsTriple new_triple
853  = boost::make_tuple(
854  boost::make_tuple(triples[i].get<0>().get<2>(),
855  triples[i].get<0>().get<0>(),
856  triples[i].get<0>().get<1>()),
857  boost::make_tuple(
858  triples[i].get<1>().get<2>(),
859  triples[i].get<1>().get<0>(),
860  triples[i].get<1>().get<1>()));
861  ret.push_back(new_triple);
862  }
863  }
864  }
865  return ret;
866  }
867 
869  const sensor_msgs::PointCloud2::ConstPtr& input_cloud,
870  const jsk_recognition_msgs::ParallelEdgeArray::ConstPtr& input_edges)
871  {
872  boost::mutex::scoped_lock lock(mutex_);
873  pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
874  pcl::PointCloud<PointT>::Ptr all_filtered_cloud (new pcl::PointCloud<PointT>);
875  pcl::fromROSMsg(*input_cloud, *cloud);
876  visualization_msgs::Marker marker;
877  jsk_recognition_msgs::PolygonArray polygon_array;
878  std::vector<pcl::PointIndices::Ptr> candidate_cluster_indices;
879 
880  polygon_array.header = input_cloud->header;
881  marker.pose.orientation.w = 1.0;
882  marker.color.a = 1.0;
883  marker.color.r = 1.0;
884  marker.header = input_cloud->header;
885  marker.scale.x = 0.01;
886  marker.type = visualization_msgs::Marker::LINE_LIST;
887  NODELET_INFO("%lu parallel edge groups", input_edges->edge_groups.size());
888  geometry_msgs::PoseArray pose_array;
889  pose_array.header = input_cloud->header;
890  jsk_recognition_msgs::BoundingBoxArray ros_output;
891  ros_output.header = input_cloud->header;
892 
893  for (size_t i = 0; i < input_edges->edge_groups.size(); i++) {
894  jsk_recognition_msgs::ParallelEdge parallel_edge = input_edges->edge_groups[i];
895 
896  if (parallel_edge.cluster_indices.size() <= 1) {
897  NODELET_ERROR("parallel edge group has only %lu edges",
898  parallel_edge.cluster_indices.size());
899  continue;
900  }
901  NODELET_INFO("%lu parallel edge groups has %lu edges",
902  i, parallel_edge.cluster_indices.size());
904  // first convert all the pcl_msgs/PointIndices to pcl::PointIndices
906  std::vector<pcl::PointIndices::Ptr> edges
908  parallel_edge.cluster_indices);
909  std::vector<pcl::ModelCoefficients::Ptr> coefficients
911  parallel_edge.coefficients);
912 
913  std::vector<IndicesPair> pairs = combinateIndices(edges);
914  std::vector<CoefficientsPair> coefficients_pair
915  = combinateCoefficients(coefficients);
916  std::vector<IndicesPair> filtered_indices_pairs;
917  std::vector<CoefficientsPair> filtered_coefficients_pairs;
918 
919  filtered_indices_pairs = pairs;
920  filtered_coefficients_pairs = coefficients_pair;
921  // filterPairsBasedOnParallelEdgeDistances(
922  // pairs, coefficients_pair,
923  // filtered_indices_pairs, filtered_coefficients_pairs);
924 
925  // convex based filtering...
926  std::vector<jsk_recognition_utils::ConvexPolygon::Ptr> convexes;
927  for (size_t j = 0; j < filtered_coefficients_pairs.size(); j++) {
929  = convexFromPairs(cloud, filtered_coefficients_pairs[j],
930  pairs[j]);
931  convexes.push_back(convex);
932  }
933  std::vector<int> filtered_indices;
934  filterBasedOnConvex(cloud, convexes, filtered_indices);
935 
936  pcl::PointIndices::Ptr filtered_cube_candidate_indices(new pcl::PointIndices);
937  for (size_t j = 0; j < filtered_indices.size(); j++) {
938  int index = filtered_indices[j];
939  jsk_recognition_utils::ConvexPolygon::Ptr target_convex = convexes[index];
940  IndicesPair target_edge_indices_pair
941  = filtered_indices_pairs[index];
942  CoefficientsPair target_edge_coefficients_pair
943  = filtered_coefficients_pairs[index];
944  // 1. roughly segment the points around the plane
945  //pcl::PointCloud<PointT>::Ptr filtered_cloud
946  pcl::PointIndices::Ptr filtered_indices
947  = preparePointCloudForRANSAC(
948  target_convex, target_edge_coefficients_pair, cloud);
949  // *filtered_cube_candidate_indices
950  // = *filtered_indices + *filtered_cube_candidate_indices;
951  filtered_cube_candidate_indices
952  = jsk_recognition_utils::addIndices(*filtered_cube_candidate_indices,
953  *filtered_indices);
954 
955  // ROS_INFO("%lu -> %lu", cloud->points.size(), filtered_cloud->points.size());
956  // *all_filtered_cloud = *all_filtered_cloud + *filtered_cloud;
957  // // 2. estimate a plane parallel to the convex using RANSAC
958  // pcl::ModelCoefficients::Ptr
959  // parallel_plane_coefficients (new pcl::ModelCoefficients);
960  // pcl::PointIndices::Ptr
961  // parallel_plane_inliers (new pcl::PointIndices);
962 
963  // estimateParallelPlane(target_convex, filtered_cloud,
964  // parallel_plane_inliers,
965  // parallel_plane_coefficients);
966  // if (parallel_plane_inliers->indices.size() > 0) {
967  // jsk_recognition_utils::ConvexPolygon::Ptr parallel_convex
968  // = jsk_recognition_utils::convexFromCoefficientsAndInliers<PointT>(
969  // filtered_cloud,
970  // parallel_plane_inliers,
971  // parallel_plane_coefficients);
972  // if (parallel_convex) {
973  // pcl::ModelCoefficients::Ptr
974  // perpendicular_plane_coefficients (new pcl::ModelCoefficients);
975  // pcl::PointIndices::Ptr
976  // perpendicular_plane_inliers (new pcl::PointIndices);
977  // estimatePerpendicularPlane(parallel_convex,
978  // target_edge_coefficients_pair,
979  // filtered_cloud,
980  // perpendicular_plane_inliers,
981  // perpendicular_plane_coefficients);
982  // if (perpendicular_plane_inliers->indices.size() > 0) {
983  // jsk_recognition_utils::ConvexPolygon::Ptr perpendicular_convex
984  // = jsk_recognition_utils::convexFromCoefficientsAndInliers<PointT>(
985  // filtered_cloud,
986  // perpendicular_plane_inliers,
987  // perpendicular_plane_coefficients);
988  // if (perpendicular_convex) {
989  // if (perpendicular_convex->angle(*parallel_convex) < pcl::deg2rad(10.0)) {
990  // geometry_msgs::PolygonStamped ros_polygon;
991  // ros_polygon.header = input_cloud->header;
992  // ros_polygon.polygon = parallel_convex->toROSMsg();
993  // polygon_array.polygons.push_back(ros_polygon);
994  // geometry_msgs::PolygonStamped ros_polygon2;
995  // ros_polygon2.header = input_cloud->header;
996  // ros_polygon2.polygon = perpendicular_convex->toROSMsg();
997  // polygon_array.polygons.push_back(ros_polygon2);
998  // }
999  // }
1000  // }
1001  // }
1002  // }
1003  // if (parallel_plane) {
1004  // // 3. estimate a plane perpendicular to the convex using RANSAC
1005  // pcl::ModelCoefficients::Ptr perpendicular_plane
1006  // = estimatePerpendicularPlane(convex, filtered_cloud);
1007  // if (perpendicular_plane) {
1008  // // success to estimate, it's cube
1009  // Cube::Ptr cube
1010  // = makeupCubeResult();
1011  // cubes.push_back(cube);
1012  // }
1013  // else {
1014  // // failed to estimate perpendicular plane
1015  // ROS_INFO("failed to estimate perpendicular plane");
1016  // }
1017  // }
1018  // else {
1019  // // failed to estimate parallel plane
1020  // ROS_INFO("failed to estimate parallel plane");
1021  // }
1022 // }
1023 
1024  // for (size_t j = 0; j < filtered_indices.size(); j++) {
1025  // int pair_index = filtered_indices[j];
1026  // jsk_recognition_utils::ConvexPolygon::Ptr convex = convexes[filtered_indices[j]];
1027 
1028  // Vertices vs = convex->getVertices();
1029  // for (size_t k = 0; k < vs.size(); k++) {
1030  // Eigen::Vector3f A, B;
1031  // Eigen::Vector3d Ad, Bd;
1032  // A = vs[k];
1033  // if (k + 1 != vs.size()) {
1034  // B = vs[k + 1];
1035  // }
1036  // else {
1037  // B = vs[0];
1038  // }
1039  // geometry_msgs::Point AP, BP;
1040  // convertEigenVector(A, Ad);
1041  // convertEigenVector(B, Bd);
1042  // tf::pointEigenToMsg(Ad, AP);
1043  // tf::pointEigenToMsg(Bd, BP);
1044  // marker.points.push_back(AP);
1045  // marker.points.push_back(BP);
1046  // std_msgs::ColorRGBA green;
1047  // green.a = 1.0; green.g = 1.0;
1048  // marker.colors.push_back(green);
1049  // marker.colors.push_back(green);
1050  // }
1051  }
1052  candidate_cluster_indices.push_back(filtered_cube_candidate_indices);
1053 
1054  // estimate cube
1055  pcl::PointIndices::Ptr first_inliers(new pcl::PointIndices);
1056  pcl::ModelCoefficients::Ptr first_coefficients(new pcl::ModelCoefficients);
1058  = estimateConvexPolygon(
1059  cloud,
1060  filtered_cube_candidate_indices,
1061  first_coefficients,
1062  first_inliers);
1063  if (first_polygon) {
1064  geometry_msgs::PolygonStamped first_polygon_ros;
1065  first_polygon_ros.polygon = first_polygon->toROSMsg();
1066  first_polygon_ros.header = input_cloud->header;
1067  polygon_array.polygons.push_back(first_polygon_ros);
1068  }
1069  // std::vector<CubeHypothesis::Ptr> hypothesis_list;
1070  // NODELET_INFO("building hypothesis");
1071  // NODELET_INFO("pair size: %lu", pairs.size());
1072  // for (size_t j = 0; j < pairs.size(); j++) {
1073  // NODELET_INFO("j -> %lu", j);
1074  // IndicesPair pair = pairs[j];
1075  // CoefficientsPair cpair = coefficients_pair[j];
1076  // PlanarCubeHypothesis::Ptr
1077  // planar_hypothesis (new PlanarCubeHypothesis(
1078  // pair, cpair, outlier_threshold_));
1079  // DiagnoalCubeHypothesis::Ptr
1080  // diagnoal_hypothesis (new DiagnoalCubeHypothesis(
1081  // pair, cpair, outlier_threshold_));
1082  // //hypothesis_list.push_back(planar_hypothesis);
1083  // hypothesis_list.push_back(diagnoal_hypothesis);
1084  // }
1085  // NODELET_INFO("estimating hypothesis");
1086  // for (size_t j = 0; j < hypothesis_list.size(); j++) {
1087  // hypothesis_list[j]->estimate(*cloud);
1088  // }
1089  // // find max evaluated
1090  // NODELET_INFO("find max hypothesis");
1091  // CubeHypothesis::Ptr max_hypothesis;
1092  // double max_eval = -DBL_MAX;
1093  // for (size_t i = 0; i < hypothesis_list.size(); i++) {
1094  // if (max_eval < hypothesis_list[i]->getValue()) {
1095  // max_eval = hypothesis_list[i]->getValue();
1096  // max_hypothesis = hypothesis_list[i];
1097  // }
1098  // }
1099  // NODELET_INFO("convert to ros msg");
1100  // BoundingBox msg = max_hypothesis->getCube()->toROSMsg();
1101  // msg.header = input_cloud->header;
1102  // ros_output.boxes.push_back(msg);
1103  // pose_array.poses.push_back(msg.pose);
1104  }
1105  pub_.publish(ros_output);
1106  pub_pose_array_.publish(pose_array);
1107  pub_debug_marker_.publish(marker);
1108  sensor_msgs::PointCloud2 ros_cloud;
1109  pcl::toROSMsg(*all_filtered_cloud, ros_cloud);
1110  ros_cloud.header = input_cloud->header;
1111  pub_debug_filtered_cloud_.publish(ros_cloud);
1112  pub_debug_polygons_.publish(polygon_array);
1113 
1114  // convert std::vector<pcl::PointIndices::Ptr> to ClusterPointIndices
1115  jsk_recognition_msgs::ClusterPointIndices ros_cluster_indices;
1116  ros_cluster_indices.header = input_cloud->header;
1117  for (size_t i = 0; i < candidate_cluster_indices.size(); i++) {
1118  PCLIndicesMsg indices_msg;
1119  indices_msg.header = input_cloud->header;
1120  indices_msg.indices = candidate_cluster_indices[i]->indices;
1121  ros_cluster_indices.cluster_indices.push_back(indices_msg);
1122  }
1123  pub_debug_clusers_.publish(ros_cluster_indices);
1124  }
1125 
1126  std::vector<IndicesCoefficientsTriple>
1128  const std::vector<pcl::PointIndices::Ptr>& indices,
1129  const std::vector<pcl::ModelCoefficients::Ptr>& coefficients)
1130  {
1131  if (indices.size() != coefficients.size()) {
1132  NODELET_ERROR("size of indices and coefficients are not same");
1133  return std::vector<IndicesCoefficientsTriple>();
1134  }
1135 
1136  if (indices.size() <= 2 && coefficients.size() <= 2) {
1137  NODELET_WARN("[EdgebasedCubeFinder::tripleIndicesAndCoefficients] no enough canddiates");
1138  return std::vector<IndicesCoefficientsTriple>();
1139  }
1140  std::vector<IndicesCoefficientsTriple> ret;
1141  for (size_t i = 0; i < indices.size() - 2; i++) {
1142  for (size_t j = i + 1; j < indices.size() - 1; j++) {
1143  for (size_t k = j + 1; k < indices.size(); k++) {
1144  IndicesTriple indices_triple
1145  = boost::make_tuple(indices[i],
1146  indices[j],
1147  indices[k]);
1148  CoefficientsTriple coefficients_triple
1149  = boost::make_tuple(coefficients[i],
1150  coefficients[j],
1151  coefficients[k]);
1152  IndicesCoefficientsTriple indices_coefficients_triple
1153  = boost::make_tuple(indices_triple,
1154  coefficients_triple);
1155  ret.push_back(indices_coefficients_triple);
1156  }
1157  }
1158  }
1159  return ret;
1160  }
1161 
1163  const pcl::PointCloud<PointT>::Ptr cloud,
1164  const pcl::PointIndices::Ptr indices,
1165  pcl::ModelCoefficients::Ptr coefficients,
1166  pcl::PointIndices::Ptr inliers)
1167  {
1169  // RANSAC
1171  pcl::SACSegmentation<PointT> seg;
1172  seg.setOptimizeCoefficients (true);
1173  seg.setModelType (pcl::SACMODEL_PLANE);
1174  seg.setMethodType (pcl::SAC_RANSAC);
1175  seg.setInputCloud(cloud);
1176  seg.setIndices(indices);
1177  seg.setDistanceThreshold(0.003);
1178  seg.segment(*inliers, *coefficients);
1180  // project points to the plane
1182  if (inliers->indices.size() > 0) {
1183  return jsk_recognition_utils::convexFromCoefficientsAndInliers<PointT>(
1184  cloud, inliers, coefficients);
1185  }
1186  else {
1188  }
1189  }
1190 
1191  std::vector<IndicesPair> EdgebasedCubeFinder::combinateIndices(
1192  const std::vector<pcl::PointIndices::Ptr>& indices)
1193  {
1194  std::vector<IndicesPair> ret;
1195  for(size_t i = 0; i < indices.size() - 1; i++) {
1196  for (size_t j = i + 1; j < indices.size(); j++) {
1197  IndicesPair pair = boost::make_tuple(indices[i],
1198  indices[j]);
1199  ret.push_back(pair);
1200  }
1201  }
1202  return ret;
1203  }
1204 
1205  std::vector<CoefficientsPair> EdgebasedCubeFinder::combinateCoefficients(
1206  const std::vector<pcl::ModelCoefficients::Ptr>& coefficients)
1207  {
1208  std::vector<CoefficientsPair> ret;
1209  for(size_t i = 0; i < coefficients.size() - 1; i++) {
1210  for (size_t j = i + 1; j < coefficients.size(); j++) {
1211  CoefficientsPair pair = boost::make_tuple(coefficients[i],
1212  coefficients[j]);
1213  ret.push_back(pair);
1214  }
1215  }
1216  return ret;
1217  }
1218 }
1219 
1222 
virtual void getLinePoints(const jsk_recognition_utils::Line &line, const pcl::PointCloud< pcl::PointXYZRGB > &cloud, const pcl::PointIndices::Ptr indices, jsk_recognition_utils::Vertices &output)
virtual jsk_recognition_utils::ConvexPolygon::Ptr convexFromPairs(const pcl::PointCloud< PointT >::Ptr cloud, const CoefficientsPair &coefficients_pair, const IndicesPair &indices_pair)
num
virtual EdgeRelation perpendicularEdgeTriple(const jsk_recognition_utils::Line &edge_a, const jsk_recognition_utils::Line &edge_b, const jsk_recognition_utils::Line &edge_c)
bool distanceSmallerThan(const Eigen::Vector3f &p, double distance_threshold)
#define NODELET_ERROR(...)
virtual void foot(const Eigen::Vector3f &point, Eigen::Vector3f &output) const
#define NODELET_WARN(...)
virtual jsk_recognition_utils::PointPair computeAxisEndPoints(const jsk_recognition_utils::Line &axis, const jsk_recognition_utils::PointPair &a_candidates, const jsk_recognition_utils::PointPair &b_candidates)
virtual double computeAlpha(const Point &p) const
virtual std::vector< CoefficientsPair > combinateCoefficients(const std::vector< pcl::ModelCoefficients::Ptr > &coefficients)
virtual void configCallback(Config &config, uint32_t level)
boost::tuple< pcl::ModelCoefficients::Ptr, pcl::ModelCoefficients::Ptr > CoefficientsPair
virtual void filterBasedOnConvex(const pcl::PointCloud< PointT >::Ptr cloud, const std::vector< jsk_recognition_utils::ConvexPolygon::Ptr > &convexes, std::vector< int > &output_indices)
DiagnoalCubeHypothesis(const IndicesPair &pair, const CoefficientsPair &coefficients_pair, const double outlier_threshold)
virtual void estimateParallelPlane(const jsk_recognition_utils::ConvexPolygon::Ptr convex, const pcl::PointCloud< PointT >::Ptr filtered_cloud, pcl::PointIndices::Ptr output_inliers, pcl::ModelCoefficients::Ptr output_coefficients)
boost::shared_ptr< ConvexPolygon > Ptr
std::vector< pcl::ModelCoefficients::Ptr > convertToPCLModelCoefficients(const std::vector< PCLModelCoefficientMsg > &coefficients)
virtual jsk_recognition_utils::ConvexPolygon::Ptr buildConvexPolygon(const jsk_recognition_utils::PointPair &a_edge_pair, const jsk_recognition_utils::PointPair &b_edge_pair)
alpha
boost::tuple< pcl::ModelCoefficients::Ptr, pcl::ModelCoefficients::Ptr, pcl::ModelCoefficients::Ptr > CoefficientsTriple
virtual double evaluatePointOnPlanes(const pcl::PointCloud< pcl::PointXYZRGB > &cloud, jsk_recognition_utils::ConvexPolygon &polygon_a, jsk_recognition_utils::ConvexPolygon &polygon_b)
coefficients
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
virtual std::vector< IndicesCoefficientsTriple > filterPerpendicularEdgeTriples(const std::vector< IndicesCoefficientsTriple > &triples)
virtual jsk_recognition_utils::PointPair minMaxPointOnLine(const jsk_recognition_utils::Line &line, const pcl::PointCloud< PointT >::Ptr cloud)
virtual PointPair findEndPoints(const Vertices &points) const
virtual jsk_recognition_utils::Line::Ptr midLineFromCoefficientsPair(const CoefficientsPair &pair)
T dot(T *pf1, T *pf2, int length)
virtual void estimatePerpendicularPlane(const jsk_recognition_utils::ConvexPolygon::Ptr convex, const CoefficientsPair &edge_coefficients, const pcl::PointCloud< PointT >::Ptr filtered_cloud, pcl::PointIndices::Ptr output_inliers, pcl::ModelCoefficients::Ptr output_coefficients)
std::vector< pcl::PointIndices::Ptr > convertToPCLPointIndices(const std::vector< PCLIndicesMsg > &cluster_indices)
virtual jsk_recognition_utils::ConvexPolygon::Ptr estimateConvexPolygon(const pcl::PointCloud< PointT >::Ptr cloud, const pcl::PointIndices::Ptr indices, pcl::ModelCoefficients::Ptr coefficients, pcl::PointIndices::Ptr inliers)
boost::tuple< pcl::PointIndices::Ptr, pcl::PointIndices::Ptr > IndicesPair
PlanarCubeHypothesis(const IndicesPair &pair, const CoefficientsPair &coefficients_pair, const double outlier_threshold)
virtual pcl::PointIndices::Ptr preparePointCloudForRANSAC(const jsk_recognition_utils::ConvexPolygon::Ptr convex, const CoefficientsPair &edge_coefficients_pair, const pcl::PointCloud< PointT >::Ptr cloud)
void toPCL(const pcl_msgs::PointIndices &pi, pcl::PointIndices &pcl_pi)
TFSIMD_FORCE_INLINE Vector3 normalized() const
virtual void estimate2(const sensor_msgs::PointCloud2::ConstPtr &input_cloud, const jsk_recognition_msgs::ParallelEdgeArray::ConstPtr &input_edges)
virtual std::vector< IndicesPair > combinateIndices(const std::vector< pcl::PointIndices::Ptr > &indices)
unsigned int index
Eigen::Quaternionf rotFrom3Axis(const Eigen::Vector3f &ex, const Eigen::Vector3f &ey, const Eigen::Vector3f &ez)
virtual void filterPairsBasedOnParallelEdgeDistances(const std::vector< IndicesPair > &pairs, const std::vector< CoefficientsPair > &coefficients_pair, std::vector< IndicesPair > &filtered_indices_pairs, std::vector< CoefficientsPair > &filtered_coefficients_pairs)
#define M_PI
virtual void estimate(const pcl::PointCloud< pcl::PointXYZRGB > &cloud)
#define ROS_INFO(...)
jsk_pcl_ros::EdgebasedCubeFinderConfig Config
virtual pcl::PointCloud< PointT >::Ptr extractPointCloud(const pcl::PointCloud< PointT >::Ptr cloud, const pcl::PointIndices::Ptr indices)
std::vector< int > addIndices(const std::vector< int > &a, const std::vector< int > &b)
virtual std::vector< IndicesCoefficientsTriple > tripleIndicesAndCoefficients(const std::vector< pcl::PointIndices::Ptr > &indices, const std::vector< pcl::ModelCoefficients::Ptr > &coefficients)
rot
const CoefficientsPair coefficients_pair_
void toROSMsg(const pcl::PointCloud< T > &pcl_cloud, sensor_msgs::PointCloud2 &cloud)
virtual jsk_recognition_utils::Cube::Ptr cubeFromIndicesAndCoefficients(const pcl::PointCloud< PointT >::Ptr cloud, const IndicesCoefficientsTriple &indices_coefficients_triple, pcl::PointCloud< EdgebasedCubeFinder::PointT >::Ptr points_on_edge)
static Ptr fromCoefficients(const std::vector< float > &coefficients)
std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f > > Vertices
#define NODELET_INFO(...)
PLUGINLIB_EXPORT_CLASS(jsk_pcl_ros::EdgebasedCubeFinder, nodelet::Nodelet)
INLINE Rall1d< T, V, S > acos(const Rall1d< T, V, S > &x)
virtual void computeCentroid(const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &cloud, const pcl::PointIndices::Ptr &indices, Eigen::Vector3f &output)
p
boost::tuple< Point, Point > PointPair
boost::tuple< IndicesTriple, CoefficientsTriple > IndicesCoefficientsTriple
GLfloat v[8][3]
boost::tuple< pcl::PointIndices::Ptr, pcl::PointIndices::Ptr, pcl::PointIndices::Ptr > IndicesTriple
int theta
CubeHypothesis(const IndicesPair &pair, const CoefficientsPair &coefficients_pair, const double outlier_threshold)
virtual void estimate(const sensor_msgs::PointCloud2::ConstPtr &input_cloud, const jsk_recognition_msgs::ParallelEdgeArray::ConstPtr &input_edges)
boost::mutex mutex_
pcl::PointIndices PCLIndicesMsg
cloud
jsk_recognition_utils::Cube::Ptr cube_
Cube cube(Eigen::Vector3f(1, 0, 0), Eigen::Quaternionf(0.108755, 0.088921, 0.108755, 0.984092), Eigen::Vector3f(0.3, 0.3, 0.3))
virtual bool isPerpendicularVector(const Eigen::Vector3f &a, const Eigen::Vector3f &b)
double distance(const urdf::Pose &transform)
virtual void parallelLineNormal(const Line &other, Eigen::Vector3f &output) const
virtual int countInliers(const pcl::PointCloud< PointT >::Ptr cloud, const jsk_recognition_utils::ConvexPolygon::Ptr convex)


jsk_pcl_ros
Author(s): Yohei Kakiuchi
autogenerated on Mon May 3 2021 03:03:46