plane_concatenator_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/or 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 #define BOOST_PARAMETER_MAX_ARITY 7
37 #include <pcl/kdtree/kdtree_flann.h>
38 #include <pcl/sample_consensus/method_types.h>
39 #include <pcl/sample_consensus/model_types.h>
40 #include <pcl/segmentation/sac_segmentation.h>
43 
44 namespace jsk_pcl_ros_utils
45 {
47  {
48  DiagnosticNodelet::onInit();
49  pcl::console::setVerbosityLevel(pcl::console::L_ALWAYS);
50  srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
51  dynamic_reconfigure::Server<Config>::CallbackType f =
52  boost::bind (
54  srv_->setCallback (f);
55 
56  pub_indices_ = advertise<jsk_recognition_msgs::ClusterPointIndices>(
57  *pnh_, "output/indices", 1);
58  pub_polygon_ = advertise<jsk_recognition_msgs::PolygonArray>(
59  *pnh_, "output/polygons", 1);
60  pub_coefficients_ = advertise<jsk_recognition_msgs::ModelCoefficientsArray>(
61  *pnh_, "output/coefficients", 1);
62 
63  onInitPostProcess();
64  }
65 
67  // message_filters::Synchronizer needs to be called reset
68  // before message_filters::Subscriber is freed.
69  // Calling reset fixes the following error on shutdown of the nodelet:
70  // terminate called after throwing an instance of
71  // 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >'
72  // what(): boost: mutex lock failed in pthread_mutex_lock: Invalid argument
73  // Also see https://github.com/ros/ros_comm/issues/720 .
74  sync_.reset();
75  }
76 
78  {
79  sub_cloud_.subscribe(*pnh_, "input", 1);
80  sub_indices_.subscribe(*pnh_, "input/indices", 1);
81  sub_polygon_.subscribe(*pnh_, "input/polygons", 1);
82  sub_coefficients_.subscribe(*pnh_, "input/coefficients", 1);
83  sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> > (100);
84  sync_->connectInput(sub_cloud_, sub_indices_,
86  sync_->registerCallback(boost::bind(&PlaneConcatenator::concatenate, this,
87  _1, _2, _3, _4));
88  }
89 
91  {
96  }
97 
99  const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
100  const jsk_recognition_msgs::ClusterPointIndices::ConstPtr& indices_msg,
101  const jsk_recognition_msgs::PolygonArray::ConstPtr& polygon_array_msg,
102  const jsk_recognition_msgs::ModelCoefficientsArray::ConstPtr& coefficients_array_msg)
103  {
104  boost::mutex::scoped_lock lock(mutex_);
105  vital_checker_->poke();
106 
107  size_t nr_cluster = polygon_array_msg->polygons.size();
108  pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
109  pcl::fromROSMsg(*cloud_msg, *cloud);
110  // first convert to polygon instance
111  std::vector<pcl::ModelCoefficients::Ptr> all_coefficients
113  coefficients_array_msg->coefficients);
114  std::vector<pcl::PointIndices::Ptr> all_indices
115  = pcl_conversions::convertToPCLPointIndices(indices_msg->cluster_indices);
116  std::vector<pcl::PointCloud<PointT>::Ptr> all_clouds
117  = jsk_recognition_utils::convertToPointCloudArray<PointT>(cloud, all_indices);
118  std::vector<jsk_recognition_utils::Plane::Ptr> planes
119  = jsk_recognition_utils::convertToPlanes(all_coefficients);
120  // build connection map
122  for (size_t i = 0; i < nr_cluster; i++) {
123  connection_map[i] = std::vector<int>();
124  connection_map[i].push_back(i);
125  // build kdtree
126  pcl::KdTreeFLANN<PointT> kdtree;
127  pcl::PointCloud<PointT>::Ptr focused_cloud = all_clouds[i];
128  kdtree.setInputCloud(focused_cloud);
129  // look up near polygon
130  jsk_recognition_utils::Plane::Ptr focused_plane = planes[i];
131  for (size_t j = i + 1; j < nr_cluster; j++) {
132  jsk_recognition_utils::Plane::Ptr target_plane = planes[j];
133  if (focused_plane->angle(*target_plane) < connect_angular_threshold_) {
134  // second, check distance
135  bool is_near_enough = isNearPointCloud(kdtree, all_clouds[j], target_plane);
136  if (is_near_enough) {
137  connection_map[i].push_back(j);
138  }
139  }
140  }
141  }
142  std::vector<std::set<int> > cloud_sets;
143  jsk_recognition_utils::buildAllGroupsSetFromGraphMap(connection_map, cloud_sets);
144  // build new indices
145  std::vector<pcl::PointIndices::Ptr> new_indices;
146  std::vector<pcl::ModelCoefficients::Ptr> new_coefficients;
147  for (size_t i = 0; i < cloud_sets.size(); i++) {
148  pcl::PointIndices::Ptr new_one_indices (new pcl::PointIndices);
149  new_coefficients.push_back(all_coefficients[*cloud_sets[i].begin()]);
150  for (std::set<int>::iterator it = cloud_sets[i].begin();
151  it != cloud_sets[i].end();
152  ++it) {
153  new_one_indices = jsk_recognition_utils::addIndices(*new_one_indices, *all_indices[*it]);
154  }
155  if (new_one_indices->indices.size() > min_size_) {
156  new_indices.push_back(new_one_indices);
157  }
158  }
159 
160  // refinement
161  std::vector<pcl::ModelCoefficients::Ptr> new_refined_coefficients;
162  for (size_t i = 0; i < new_indices.size(); i++) {
163  pcl::ModelCoefficients::Ptr refined_coefficients
164  = refinement(cloud, new_indices[i], new_coefficients[i]);
165  new_refined_coefficients.push_back(refined_coefficients);
166  }
167 
168  // publish
169  jsk_recognition_msgs::ClusterPointIndices new_ros_indices;
170  jsk_recognition_msgs::ModelCoefficientsArray new_ros_coefficients;
171  jsk_recognition_msgs::PolygonArray new_ros_polygons;
172  new_ros_indices.header = cloud_msg->header;
173  new_ros_coefficients.header = cloud_msg->header;
174  new_ros_polygons.header = cloud_msg->header;
175  for (size_t i = 0; i < new_indices.size(); i++) {
177  = jsk_recognition_utils::convexFromCoefficientsAndInliers<PointT>(
178  cloud, new_indices[i], new_refined_coefficients[i]);
179  if (convex->area() > min_area_ && convex->area() < max_area_) {
180  geometry_msgs::PolygonStamped polygon;
181  polygon.polygon = convex->toROSMsg();
182  polygon.header = cloud_msg->header;
183  new_ros_polygons.polygons.push_back(polygon);
184  pcl_msgs::PointIndices ros_indices;
185  ros_indices.header = cloud_msg->header;
186  ros_indices.indices = new_indices[i]->indices;
187  new_ros_indices.cluster_indices.push_back(ros_indices);
188  pcl_msgs::ModelCoefficients ros_coefficients;
189  ros_coefficients.header = cloud_msg->header;
190  ros_coefficients.values = new_refined_coefficients[i]->values;
191  new_ros_coefficients.coefficients.push_back(ros_coefficients);
192  }
193  }
194 
195  // new_ros_indices.cluster_indices
196  // = pcl_conversions::convertToROSPointIndices(new_indices, cloud_msg->header);
197  // new_ros_coefficients.coefficients
198  // = pcl_conversions::convertToROSModelCoefficients(
199  // new_refined_coefficients, cloud_msg->header);
200 
201  pub_indices_.publish(new_ros_indices);
202  pub_polygon_.publish(new_ros_polygons);
203  pub_coefficients_.publish(new_ros_coefficients);
204  }
205 
206  pcl::ModelCoefficients::Ptr PlaneConcatenator::refinement(
207  pcl::PointCloud<PointT>::Ptr cloud,
208  pcl::PointIndices::Ptr indices,
209  pcl::ModelCoefficients::Ptr original_coefficients)
210  {
211  pcl::SACSegmentation<PointT> seg;
212  seg.setOptimizeCoefficients (true);
213  seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE);
214  seg.setMethodType (pcl::SAC_RANSAC);
215  seg.setDistanceThreshold (ransac_refinement_outlier_threshold_);
216 
217  seg.setInputCloud(cloud);
218 
219  seg.setIndices(indices);
220  seg.setMaxIterations (ransac_refinement_max_iteration_);
221  Eigen::Vector3f normal (original_coefficients->values[0],
222  original_coefficients->values[1],
223  original_coefficients->values[2]);
224  seg.setAxis(normal);
225  // seg.setInputNormals(cloud);
226  // seg.setDistanceFromOrigin(original_coefficients->values[3]);
227  // seg.setEpsDist(ransac_refinement_eps_distance_);
228  seg.setEpsAngle(ransac_refinement_eps_angle_);
229  pcl::PointIndices::Ptr refined_inliers (new pcl::PointIndices);
230  pcl::ModelCoefficients::Ptr refined_coefficients(new pcl::ModelCoefficients);
231  seg.segment(*refined_inliers, *refined_coefficients);
232  if (refined_inliers->indices.size() > 0) {
233  pcl::ModelCoefficients::Ptr fixed_refined_coefficients(new pcl::ModelCoefficients);
234  forceToDirectOrigin(refined_coefficients, fixed_refined_coefficients);
235  return fixed_refined_coefficients;
236  }
237  else {
238  return original_coefficients;
239  }
240  }
241 
243  pcl::KdTreeFLANN<PointT>& kdtree,
244  pcl::PointCloud<PointT>::Ptr cloud,
246  {
247  pcl::PointCloud<PointT>::ConstPtr input_cloud = kdtree.getInputCloud();
248  for (size_t i = 0; i < cloud->points.size(); i++) {
249  PointT p = cloud->points[i];
250  std::vector<int> k_indices;
251  std::vector<float> k_sqr_distances;
252  if (kdtree.radiusSearch(p, connect_distance_threshold_,
253  k_indices, k_sqr_distances, 1) > 0) {
254  // Decompose distance into pependicular distance and parallel distance
255  const PointT near_p = input_cloud->points[k_indices[0]];
256  Eigen::Affine3f plane_coordinates = target_plane->coordinates();
257  Eigen::Vector3f plane_local_p = plane_coordinates.inverse() * p.getVector3fMap();
258  Eigen::Vector3f plane_local_near_p = plane_coordinates.inverse() * near_p.getVector3fMap();
259  Eigen::Vector3f plane_local_diff = plane_local_near_p - plane_local_p;
260  double perpendicular_distance = std::abs(plane_local_diff[2]);
261  if (perpendicular_distance < connect_perpendicular_distance_threshold_) {
262  return true;
263  }
264  }
265  }
266  return false;
267  }
268 
270  Config &config, uint32_t level)
271  {
272  boost::mutex::scoped_lock lock(mutex_);
273  connect_angular_threshold_ = config.connect_angular_threshold;
274  connect_distance_threshold_ = config.connect_distance_threshold;
275  connect_perpendicular_distance_threshold_ = config.connect_perpendicular_distance_threshold;
276  ransac_refinement_max_iteration_ = config.ransac_refinement_max_iteration;
278  = config.ransac_refinement_outlier_threshold;
279  ransac_refinement_eps_angle_ = config.ransac_refinement_eps_angle;
280  min_size_ = config.min_size;
281  min_area_ = config.min_area;
282  max_area_ = config.max_area;
283  }
284 
286  const pcl::ModelCoefficients::Ptr& coefficients,
287  pcl::ModelCoefficients::Ptr& output_coefficients)
288  {
290 
291  Eigen::Vector3f p = plane.getPointOnPlane();
292  Eigen::Vector3f n = plane.getNormal();
293  if (p.dot(n) < 0) {
294  output_coefficients = coefficients;
295  }
296  else {
297  jsk_recognition_utils::Plane flip = plane.flip();
298  flip.toCoefficients(output_coefficients->values);
299  }
300  }
301 }
302 
jsk_pcl_ros_utils::PlaneConcatenator::sub_coefficients_
message_filters::Subscriber< jsk_recognition_msgs::ModelCoefficientsArray > sub_coefficients_
Definition: plane_concatenator.h:163
jsk_pcl_ros_utils
Definition: add_point_indices.h:51
jsk_recognition_utils::IntegerGraphMap
std::map< int, std::vector< int > > IntegerGraphMap
jsk_pcl_ros_utils::PlaneConcatenator::mutex_
boost::mutex mutex_
Definition: plane_concatenator.h:165
jsk_pcl_ros_utils::PlaneConcatenator::sub_polygon_
message_filters::Subscriber< jsk_recognition_msgs::PolygonArray > sub_polygon_
Definition: plane_concatenator.h:162
jsk_pcl_ros_utils::PlaneConcatenator::pub_indices_
ros::Publisher pub_indices_
Definition: plane_concatenator.h:167
_2
boost::arg< 2 > _2
pcl_conversions::convertToPCLModelCoefficients
std::vector< pcl::ModelCoefficients::Ptr > convertToPCLModelCoefficients(const std::vector< PCLModelCoefficientMsg > &coefficients)
jsk_pcl_ros_utils::PlaneConcatenator::connect_distance_threshold_
double connect_distance_threshold_
Definition: plane_concatenator.h:174
_3
boost::arg< 3 > _3
boost::shared_ptr
i
int i
jsk_pcl_ros_utils::PlaneConcatenator::connect_angular_threshold_
double connect_angular_threshold_
Definition: plane_concatenator.h:173
p
p
lock
lock
PLUGINLIB_EXPORT_CLASS
PLUGINLIB_EXPORT_CLASS(jsk_pcl_ros_utils::PlaneConcatenator, nodelet::Nodelet)
plane_concatenator.h
jsk_recognition_utils::convertToPlanes
std::vector< Plane::Ptr > convertToPlanes(std::vector< pcl::ModelCoefficients::Ptr >)
jsk_pcl_ros_utils::PlaneConcatenator::unsubscribe
virtual void unsubscribe()
Definition: plane_concatenator_nodelet.cpp:90
jsk_pcl_ros_utils::PlaneConcatenator::configCallback
virtual void configCallback(Config &config, uint32_t level)
Definition: plane_concatenator_nodelet.cpp:269
jsk_pcl_ros_utils::PlaneConcatenator::onInit
virtual void onInit()
Definition: plane_concatenator_nodelet.cpp:46
pcl_conversions::convertToPCLPointIndices
std::vector< pcl::PointIndices::Ptr > convertToPCLPointIndices(const std::vector< PCLIndicesMsg > &cluster_indices)
pcl::fromROSMsg
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
message_filters::Subscriber::unsubscribe
void unsubscribe()
sample_camera_info_and_pointcloud_publisher.cloud
cloud
Definition: sample_camera_info_and_pointcloud_publisher.py:30
class_list_macros.h
jsk_pcl_ros_utils::PlaneConcatenator::connect_perpendicular_distance_threshold_
double connect_perpendicular_distance_threshold_
Definition: plane_concatenator.h:175
jsk_recognition_utils::Plane::getPointOnPlane
virtual Eigen::Vector3f getPointOnPlane()
jsk_pcl_ros_utils::PlaneConcatenator::pub_coefficients_
ros::Publisher pub_coefficients_
Definition: plane_concatenator.h:169
jsk_pcl_ros_utils::PlaneConcatenator::PointT
pcl::PointXYZRGB PointT
Definition: plane_concatenator.h:124
jsk_pcl_ros_utils::PlaneConcatenator::refinement
virtual pcl::ModelCoefficients::Ptr refinement(pcl::PointCloud< PointT >::Ptr cloud, pcl::PointIndices::Ptr indices, pcl::ModelCoefficients::Ptr original_coefficients)
Definition: plane_concatenator_nodelet.cpp:206
jsk_pcl_ros_utils::PlaneConcatenator::pub_polygon_
ros::Publisher pub_polygon_
Definition: plane_concatenator.h:168
jsk_pcl_ros_utils::PlaneConcatenator::concatenate
virtual void concatenate(const sensor_msgs::PointCloud2::ConstPtr &cloud_msg, const jsk_recognition_msgs::ClusterPointIndices::ConstPtr &indices_msg, const jsk_recognition_msgs::PolygonArray::ConstPtr &polygon_array_msg, const jsk_recognition_msgs::ModelCoefficientsArray::ConstPtr &coefficients_array_msg)
Definition: plane_concatenator_nodelet.cpp:98
_1
boost::arg< 1 > _1
jsk_pcl_ros_utils::PlaneConcatenator::srv_
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
Definition: plane_concatenator.h:166
jsk_recognition_utils::Plane::toCoefficients
virtual std::vector< float > toCoefficients()
jsk_pcl_ros_utils::PlaneConcatenator::sync_
boost::shared_ptr< message_filters::Synchronizer< SyncPolicy > > sync_
Definition: plane_concatenator.h:164
pcl_conversion_util.h
jsk_pcl_ros_utils::PlaneConcatenator::min_size_
int min_size_
Definition: plane_concatenator.h:180
jsk_pcl_ros_utils::PlaneConcatenator::forceToDirectOrigin
virtual void forceToDirectOrigin(const pcl::ModelCoefficients::Ptr &coefficients, pcl::ModelCoefficients::Ptr &output_coefficients)
Definition: plane_concatenator_nodelet.cpp:285
jsk_pcl_ros_utils::PlaneConcatenator::sub_cloud_
message_filters::Subscriber< sensor_msgs::PointCloud2 > sub_cloud_
Definition: plane_concatenator.h:160
message_filters::Subscriber::subscribe
void subscribe()
jsk_pcl_ros_utils::PlaneConcatenator::~PlaneConcatenator
virtual ~PlaneConcatenator()
Definition: plane_concatenator_nodelet.cpp:66
f
f
jsk_recognition_utils::addIndices
pcl::PointIndices::Ptr addIndices(const pcl::PointIndices &a, const pcl::PointIndices &b)
nodelet::Nodelet
jsk_pcl_ros_utils::PlaneConcatenator::min_area_
double min_area_
Definition: plane_concatenator.h:181
jsk_recognition_utils::Plane::flip
virtual Plane flip()
pcl_util.h
jsk_pcl_ros_utils::PlaneConcatenator
Definition: plane_concatenator.h:87
_4
boost::arg< 4 > _4
coefficients
coefficients
jsk_pcl_ros_utils::PlaneConcatenator::subscribe
virtual void subscribe()
Definition: plane_concatenator_nodelet.cpp:77
jsk_pcl_ros_utils::PlaneConcatenator::ransac_refinement_max_iteration_
int ransac_refinement_max_iteration_
Definition: plane_concatenator.h:176
jsk_pcl_ros_utils::PlaneConcatenator::ransac_refinement_eps_angle_
double ransac_refinement_eps_angle_
Definition: plane_concatenator.h:179
jsk_recognition_utils::Plane
jsk_recognition_utils::buildAllGroupsSetFromGraphMap
void buildAllGroupsSetFromGraphMap(IntegerGraphMap graph_map, std::vector< std::set< int > > &output_sets)
jsk_pcl_ros_utils::PlaneConcatenator::Config
PlaneConcatenatorConfig Config
Definition: plane_concatenator.h:123
jsk_pcl_ros_utils::PlaneConcatenator::ransac_refinement_outlier_threshold_
double ransac_refinement_outlier_threshold_
Definition: plane_concatenator.h:177
config
config
jsk_pcl_ros_utils::PlaneConcatenator::isNearPointCloud
virtual bool isNearPointCloud(pcl::KdTreeFLANN< PointT > &kdtree, pcl::PointCloud< PointT >::Ptr cloud, jsk_recognition_utils::Plane::Ptr target_plane)
Definition: plane_concatenator_nodelet.cpp:242
jsk_pcl_ros_utils::PlaneConcatenator::sub_indices_
message_filters::Subscriber< jsk_recognition_msgs::ClusterPointIndices > sub_indices_
Definition: plane_concatenator.h:161
jsk_pcl_ros_utils::PlaneConcatenator::max_area_
double max_area_
Definition: plane_concatenator.h:182
jsk_recognition_utils::Plane::getNormal
virtual Eigen::Vector3f getNormal()


jsk_pcl_ros_utils
Author(s): Yohei Kakiuchi
autogenerated on Fri May 16 2025 03:11:43