plane_reasoner_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 
39 
40 namespace jsk_pcl_ros_utils
41 {
43  {
45  // Diagnostics
47  DiagnosticNodelet::onInit();
49 
51  // Dynamic Reconfigure
53  srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
54  dynamic_reconfigure::Server<Config>::CallbackType f =
55  boost::bind (
56  &PlaneReasoner::configCallback, this, _1, _2);
57  srv_->setCallback (f);
58 
60  // Publishers
63  = advertise<jsk_recognition_msgs::ClusterPointIndices>(*pnh_, "output/vertical/inliers", 1);
65  = advertise<jsk_recognition_msgs::ModelCoefficientsArray>(*pnh_, "output/vertical/coefficients", 1);
67  = advertise<jsk_recognition_msgs::PolygonArray>(*pnh_, "output/vertical/polygons", 1);
69  = advertise<jsk_recognition_msgs::ClusterPointIndices>(*pnh_, "output/horizontal/inliers", 1);
71  = advertise<jsk_recognition_msgs::ModelCoefficientsArray>(*pnh_, "output/horizontal/coefficients", 1);
73  = advertise<jsk_recognition_msgs::PolygonArray>(*pnh_, "output/horizontal/polygons", 1);
74 
75  onInitPostProcess();
76  }
77 
79  // message_filters::Synchronizer needs to be called reset
80  // before message_filters::Subscriber is freed.
81  // Calling reset fixes the following error on shutdown of the nodelet:
82  // terminate called after throwing an instance of
83  // 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >'
84  // what(): boost: mutex lock failed in pthread_mutex_lock: Invalid argument
85  // Also see https://github.com/ros/ros_comm/issues/720 .
86  sync_.reset();
87  }
88 
90  {
92  // Subscribers
94  sub_input_.subscribe(*pnh_, "input", 1);
95  sub_inliers_.subscribe(*pnh_, "input_inliers", 1);
96  sub_coefficients_.subscribe(*pnh_, "input_coefficients", 1);
97  sub_polygons_.subscribe(*pnh_, "input_polygons", 1);
98  sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
99  sync_->connectInput(sub_input_, sub_inliers_,
101  sync_->registerCallback(boost::bind(&PlaneReasoner::reason,
102  this, _1, _2, _3, _4));
103  }
104 
106  {
111  }
112 
113 
114  void PlaneReasoner::configCallback(Config &config, uint32_t level)
115  {
116  boost::mutex::scoped_lock lock(mutex_);
117  global_frame_id_ = config.global_frame_id;
118  horizontal_angular_threshold_ = config.horizontal_angular_threshold;
119  vertical_angular_threshold_ = config.vertical_angular_threshold;
120  }
121 
123  const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
124  const jsk_recognition_msgs::ClusterPointIndices::ConstPtr& inliers_msg,
125  const jsk_recognition_msgs::ModelCoefficientsArray::ConstPtr& coefficients_msg,
126  const jsk_recognition_msgs::PolygonArray::ConstPtr& polygons_msg)
127  {
128  boost::mutex::scoped_lock lock(mutex_);
129  // Check the size of the array messages first
130  if ((inliers_msg->cluster_indices.size()
131  != coefficients_msg->coefficients.size()) ||
132  (inliers_msg->cluster_indices.size()
133  != polygons_msg->polygons.size())) {
134  NODELET_FATAL("the size of inliers, coefficients and polygons are not same");
135  return;
136  }
137  vital_checker_->poke();
138  pcl::PointCloud<PointT>::Ptr input_cloud (new pcl::PointCloud<PointT>);
139  pcl::fromROSMsg(*cloud_msg, *input_cloud);
140 
141  // convert ROS msg to PCL/jsk_pcl messages
142  std::vector<pcl::PointIndices::Ptr> inliers
143  = pcl_conversions::convertToPCLPointIndices(inliers_msg->cluster_indices);
144  std::vector<pcl::ModelCoefficients::Ptr> coefficients
146  coefficients_msg->coefficients);
147  std::vector<jsk_recognition_utils::Plane::Ptr> planes = jsk_recognition_utils::convertToPlanes(coefficients);
148  std::vector<geometry_msgs::PolygonStamped> polygons = polygons_msg->polygons;
149  std::vector<PlaneInfoContainer> plane_infos
150  = packInfo(inliers, coefficients, planes, polygons);
151  std::vector<PlaneInfoContainer> horizontal_planes
152  = filterHorizontalPlanes(plane_infos);
153  std::vector<PlaneInfoContainer> vertical_planes
154  = filterVerticalPlanes(plane_infos);
155  publishPlaneInfo(vertical_planes,
156  cloud_msg->header,
157  input_cloud,
161  publishPlaneInfo(horizontal_planes,
162  cloud_msg->header,
163  input_cloud,
167  }
168 
170  std::vector<PlaneInfoContainer>& containers,
171  const std_msgs::Header& header,
172  pcl::PointCloud<PointT>::Ptr cloud,
173  ros::Publisher& pub_inlier,
174  ros::Publisher& pub_coefficients,
175  ros::Publisher& pub_polygons)
176  {
177  std::vector<pcl::PointIndices::Ptr> inliers;
178  std::vector<pcl::ModelCoefficients::Ptr> coefficients;
179  std::vector<geometry_msgs::PolygonStamped> polygons;
180  for (size_t i = 0; i < containers.size(); i++) {
181  inliers.push_back(containers[i].get<0>());
182  coefficients.push_back(containers[i].get<1>());
183  polygons.push_back(containers[i].get<3>());
184  }
185  jsk_recognition_msgs::ClusterPointIndices ros_indices;
186  jsk_recognition_msgs::ModelCoefficientsArray ros_coefficients;
187  jsk_recognition_msgs::PolygonArray ros_polygons;
188  ros_indices.header = header;
189  ros_coefficients.header = header;
190  ros_polygons.header = header;
191  ros_indices.cluster_indices = pcl_conversions::convertToROSPointIndices(
192  inliers, header);
193  ros_coefficients.coefficients
195  coefficients, header);
196  ros_polygons.polygons = polygons;
197  pub_inlier.publish(ros_indices);
198  pub_coefficients.publish(ros_coefficients);
199  pub_polygons.publish(ros_polygons);
200  }
201 
202  std::vector<PlaneInfoContainer>
204  double reference_angle,
205  double thrshold,
206  std::vector<PlaneInfoContainer>& infos)
207  {
208 
209  std::vector<PlaneInfoContainer> ret;
210  for (size_t i = 0; i < infos.size(); i++) {
211  PlaneInfoContainer plane_info = infos[i];
213  plane_info.get<3>().header.frame_id,
214  plane_info.get<3>().header.stamp)) {
216  tf_listener_->lookupTransform(plane_info.get<3>().header.frame_id, global_frame_id_,
217 
218  plane_info.get<3>().header.stamp,
219  transform);
220  Eigen::Affine3d eigen_transform;
221  tf::transformTFToEigen(transform, eigen_transform);
222  Eigen::Affine3f eigen_transform_3f;
223  Eigen::Vector3d up_d = (eigen_transform.rotation() * Eigen::Vector3d(0, 0, 1));
224  Eigen::Vector3f up;
225  jsk_recognition_utils::pointFromVectorToVector<Eigen::Vector3d, Eigen::Vector3f>(up_d, up);
226  jsk_recognition_utils::Plane::Ptr plane = plane_info.get<2>();
227  double angle = plane->angle(up);
228  // ROS_INFO("axis: [%f, %f, %f]", up[0], up[1], up[2]);
229  // ROS_INFO("plane: [%f, %f, %f, %f]", plane_info.get<1>()->values[0], plane_info.get<1>()->values[1], plane_info.get<1>()->values[2], plane_info.get<1>()->values[3]);
230  // ROS_INFO("angle: %f", angle);
231  if (fabs(angle - reference_angle) < thrshold) {
232  ret.push_back(plane_info);
233  }
234  }
235  }
236  return ret;
237  }
238 
239  std::vector<PlaneInfoContainer>
241  std::vector<PlaneInfoContainer>& infos)
242  {
244  0,
246  infos);
247  }
248 
249  std::vector<PlaneInfoContainer>
251  std::vector<PlaneInfoContainer>& infos)
252  {
254  M_PI / 2.0,
256  infos);
257  }
258 
259  std::vector<PlaneInfoContainer>
261  std::vector<pcl::PointIndices::Ptr>& inliers,
262  std::vector<pcl::ModelCoefficients::Ptr>& coefficients,
263  std::vector<jsk_recognition_utils::Plane::Ptr>& planes,
264  std::vector<geometry_msgs::PolygonStamped>& polygons)
265  {
266  std::vector<PlaneInfoContainer> ret;
267  for (size_t i = 0; i < inliers.size(); i++) {
268  ret.push_back(boost::make_tuple<pcl::PointIndices::Ptr,
269  pcl::ModelCoefficients::Ptr,
270  jsk_recognition_utils::Plane::Ptr>(inliers[i], coefficients[i],
271  planes[i], polygons[i]));
272  }
273  return ret;
274  }
275 
276 
277 }
278 
jsk_pcl_ros_utils
Definition: add_point_indices.h:51
polygons
polygons
jsk_pcl_ros_utils::PlaneReasoner::pub_horizontal_polygons_
ros::Publisher pub_horizontal_polygons_
Definition: plane_reasoner.h:174
NODELET_FATAL
#define NODELET_FATAL(...)
jsk_pcl_ros_utils::PlaneReasoner::sub_polygons_
message_filters::Subscriber< jsk_recognition_msgs::PolygonArray > sub_polygons_
Definition: plane_reasoner.h:165
PLUGINLIB_EXPORT_CLASS
PLUGINLIB_EXPORT_CLASS(jsk_pcl_ros_utils::PlaneReasoner, nodelet::Nodelet)
plane_reasoner.h
jsk_pcl_ros_utils::PlaneReasoner::sub_coefficients_
message_filters::Subscriber< jsk_recognition_msgs::ModelCoefficientsArray > sub_coefficients_
Definition: plane_reasoner.h:164
ros::Publisher
pcl_conversions::convertToPCLModelCoefficients
std::vector< pcl::ModelCoefficients::Ptr > convertToPCLModelCoefficients(const std::vector< PCLModelCoefficientMsg > &coefficients)
jsk_pcl_ros_utils::PlaneReasoner::vertical_angular_threshold_
double vertical_angular_threshold_
Definition: plane_reasoner.h:183
boost::shared_ptr
angle
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
i
int i
jsk_pcl_ros_utils::PlaneReasoner::filterVerticalPlanes
virtual std::vector< PlaneInfoContainer > filterVerticalPlanes(std::vector< PlaneInfoContainer > &infos)
Definition: plane_reasoner_nodelet.cpp:282
jsk_pcl_ros_utils::PlaneReasoner::pub_vertical_coefficients_
ros::Publisher pub_vertical_coefficients_
Definition: plane_reasoner.h:170
lock
lock
jsk_recognition_utils::convertToPlanes
std::vector< Plane::Ptr > convertToPlanes(std::vector< pcl::ModelCoefficients::Ptr >)
jsk_pcl_ros_utils::PlaneInfoContainer
boost::tuple< pcl::PointIndices::Ptr, pcl::ModelCoefficients::Ptr, jsk_recognition_utils::Plane::Ptr, geometry_msgs::PolygonStamped > PlaneInfoContainer
Definition: plane_reasoner.h:93
transform
template Halfspace< double > transform(const Halfspace< double > &a, const Transform3< double > &tf)
pcl_conversions::convertToPCLPointIndices
std::vector< pcl::PointIndices::Ptr > convertToPCLPointIndices(const std::vector< PCLIndicesMsg > &cluster_indices)
tf::StampedTransform
pcl::fromROSMsg
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
jsk_pcl_ros_utils::PlaneReasoner::sync_
boost::shared_ptr< message_filters::Synchronizer< SyncPolicy > > sync_
Definition: plane_reasoner.h:166
jsk_pcl_ros_utils::PlaneReasoner::pub_vertical_inliers_
ros::Publisher pub_vertical_inliers_
Definition: plane_reasoner.h:169
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
jsk_pcl_ros_utils::PlaneReasoner::pub_horizontal_coefficients_
ros::Publisher pub_horizontal_coefficients_
Definition: plane_reasoner.h:173
message_filters::Subscriber::unsubscribe
void unsubscribe()
sample_camera_info_and_pointcloud_publisher.cloud
cloud
Definition: sample_camera_info_and_pointcloud_publisher.py:30
jsk_pcl_ros_utils::PlaneReasoner::filterPlanesAroundAngle
virtual std::vector< PlaneInfoContainer > filterPlanesAroundAngle(double reference_angle, double thrshold, std::vector< PlaneInfoContainer > &infos)
Definition: plane_reasoner_nodelet.cpp:235
jsk_pcl_ros_utils::PlaneReasoner::subscribe
virtual void subscribe()
Definition: plane_reasoner_nodelet.cpp:121
jsk_pcl_ros_utils::PlaneReasoner::horizontal_angular_threshold_
double horizontal_angular_threshold_
Definition: plane_reasoner.h:182
jsk_pcl_ros_utils::PlaneReasoner::configCallback
virtual void configCallback(Config &config, uint32_t level)
Definition: plane_reasoner_nodelet.cpp:146
class_list_macros.h
jsk_pcl_ros_utils::PlaneReasoner
Definition: plane_reasoner.h:95
jsk_pcl_ros_utils::PlaneReasoner::onInit
virtual void onInit()
Definition: plane_reasoner_nodelet.cpp:74
tf_eigen.h
tf::transformTFToEigen
void transformTFToEigen(const tf::Transform &t, Eigen::Affine3f &eigen)
tf::Transformer::canTransform
bool canTransform(const std::string &target_frame, const ros::Time &target_time, const std::string &source_frame, const ros::Time &source_time, const std::string &fixed_frame, std::string *error_msg=NULL) const
jsk_pcl_ros_utils::PlaneReasoner::srv_
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
Definition: plane_reasoner.h:167
jsk_pcl_ros_utils::PlaneReasoner::pub_vertical_polygons_
ros::Publisher pub_vertical_polygons_
Definition: plane_reasoner.h:171
pcl_conversions::convertToROSModelCoefficients
std::vector< PCLModelCoefficientMsg > convertToROSModelCoefficients(const std::vector< pcl::ModelCoefficients::Ptr > &coefficients, const std_msgs::Header &header)
pcl_conversion_util.h
jsk_pcl_ros_utils::PlaneReasoner::reason
virtual void reason(const sensor_msgs::PointCloud2::ConstPtr &cloud_msg, const jsk_recognition_msgs::ClusterPointIndices::ConstPtr &inliers_msg, const jsk_recognition_msgs::ModelCoefficientsArray::ConstPtr &coefficients_msg, const jsk_recognition_msgs::PolygonArray::ConstPtr &polygons_msg)
Definition: plane_reasoner_nodelet.cpp:154
message_filters::Subscriber::subscribe
void subscribe()
jsk_pcl_ros_utils::PlaneReasoner::pub_horizontal_inliers_
ros::Publisher pub_horizontal_inliers_
Definition: plane_reasoner.h:172
f
f
nodelet::Nodelet
jsk_pcl_ros_utils::PlaneReasoner::global_frame_id_
std::string global_frame_id_
Definition: plane_reasoner.h:181
jsk_pcl_ros_utils::PlaneReasoner::publishPlaneInfo
virtual void publishPlaneInfo(std::vector< PlaneInfoContainer > &containers, const std_msgs::Header &header, pcl::PointCloud< PointT >::Ptr cloud, ros::Publisher &pub_inlier, ros::Publisher &pub_coefficients, ros::Publisher &pub_polygons)
Definition: plane_reasoner_nodelet.cpp:201
jsk_pcl_ros_utils::PlaneReasoner::~PlaneReasoner
virtual ~PlaneReasoner()
Definition: plane_reasoner_nodelet.cpp:110
jsk_pcl_ros_utils::PlaneReasoner::unsubscribe
virtual void unsubscribe()
Definition: plane_reasoner_nodelet.cpp:137
jsk_pcl_ros_utils::PlaneReasoner::packInfo
virtual std::vector< PlaneInfoContainer > packInfo(std::vector< pcl::PointIndices::Ptr > &inliers, std::vector< pcl::ModelCoefficients::Ptr > &coefficients, std::vector< jsk_recognition_utils::Plane::Ptr > &planes, std::vector< geometry_msgs::PolygonStamped > &polygons)
Definition: plane_reasoner_nodelet.cpp:292
coefficients
coefficients
jsk_pcl_ros_utils::PlaneReasoner::sub_input_
message_filters::Subscriber< sensor_msgs::PointCloud2 > sub_input_
Definition: plane_reasoner.h:162
jsk_pcl_ros_utils::PlaneReasoner::mutex_
boost::mutex mutex_
Definition: plane_reasoner.h:176
jsk_pcl_ros_utils::PlaneReasoner::filterHorizontalPlanes
virtual std::vector< PlaneInfoContainer > filterHorizontalPlanes(std::vector< PlaneInfoContainer > &infos)
Definition: plane_reasoner_nodelet.cpp:272
jsk_recognition_utils::TfListenerSingleton::getInstance
static tf::TransformListener * getInstance()
tf::Transformer::lookupTransform
void lookupTransform(const std::string &target_frame, const ros::Time &target_time, const std::string &source_frame, const ros::Time &source_time, const std::string &fixed_frame, StampedTransform &transform) const
jsk_pcl_ros_utils::PlaneReasoner::sub_inliers_
message_filters::Subscriber< jsk_recognition_msgs::ClusterPointIndices > sub_inliers_
Definition: plane_reasoner.h:163
header
header
pcl_conversions::convertToROSPointIndices
std::vector< PCLIndicesMsg > convertToROSPointIndices(const std::vector< pcl::PointIndices > cluster_indices, const std_msgs::Header &header)
config
config
jsk_pcl_ros_utils::PlaneReasoner::tf_listener_
tf::TransformListener * tf_listener_
Definition: plane_reasoner.h:168


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