snapit_nodelet.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2013, JSK Lab
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/o2r other materials provided
16  * with the distribution.
17  * * Neither the name of the JSK Lab nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 #include "jsk_pcl_ros/snapit.h"
37 #include <geometry_msgs/PolygonStamped.h>
38 #include <Eigen/StdVector>
39 #include <pcl/ModelCoefficients.h>
40 #include <pcl/filters/project_inliers.h>
41 #include <pcl/filters/extract_indices.h>
42 #include <pcl/sample_consensus/method_types.h>
43 #include <pcl/sample_consensus/model_types.h>
44 #include <pcl/segmentation/sac_segmentation.h>
45 #include <pcl/common/distances.h>
46 #include <pcl/features/normal_3d.h>
47 #include <pcl/surface/concave_hull.h>
48 #include <pcl/common/centroid.h>
49 #include <visualization_msgs/Marker.h>
54 #include <visualization_msgs/MarkerArray.h>
55 #include <algorithm>
56 
57 namespace jsk_pcl_ros
58 {
60  {
61  DiagnosticNodelet::onInit();
63  pnh_->param("use_service", use_service_, false);
64  polygon_aligned_pub_ = advertise<geometry_msgs::PoseStamped>(
65  *pnh_, "output/plane_aligned", 1);
66  convex_aligned_pub_ = advertise<geometry_msgs::PoseStamped>(
67  *pnh_, "output/convex_aligned", 1);
68  convex_aligned_pose_array_pub_ = advertise<geometry_msgs::PoseArray>(
69  *pnh_, "output/convex_aligned_pose_array", 1);
70  if (use_service_) {
71  subscribe();
72  align_footstep_srv_ = pnh_->advertiseService(
73  "align_footstep", &SnapIt::footstepAlignServiceCallback, this);
74  }
76  }
77 
79  {
80  sub_polygons_.subscribe(*pnh_, "input/polygons", 1);
81  sub_coefficients_.subscribe(*pnh_, "input/polygon_coefficients", 1);
83  = boost::make_shared<message_filters::Synchronizer<SyncPolygonPolicy> >(100);
85  sync_polygon_->registerCallback(
86  boost::bind(&SnapIt::polygonCallback, this, _1, _2));
87  polygon_align_sub_ = pnh_->subscribe("input/plane_align", 1,
89  convex_align_sub_ = pnh_->subscribe("input/convex_align", 1,
91  convex_align_polygon_sub_ = pnh_->subscribe(
92  "input/convex_align_polygon", 1,
94  }
95 
97  {
98  if (!use_service_) {
103  }
104  polygons_.reset();
105  }
106 
108  const jsk_recognition_msgs::PolygonArray::ConstPtr& polygon_msg,
109  const jsk_recognition_msgs::ModelCoefficientsArray::ConstPtr& coefficients_msg)
110  {
111  boost::mutex::scoped_lock lock(mutex_);
112  vital_checker_->poke();
113  polygons_ = polygon_msg;
114  }
115 
117  const geometry_msgs::PoseStamped::ConstPtr& pose_msg)
118  {
119  boost::mutex::scoped_lock lock(mutex_);
120  if (!polygons_) {
121  NODELET_ERROR("no polygon is ready");
122  polygon_aligned_pub_.publish(pose_msg);
123  return;
124  }
125  std::vector<jsk_recognition_utils::ConvexPolygon::Ptr> convexes
126  = createConvexes(pose_msg->header.frame_id,
127  pose_msg->header.stamp,
128  polygons_);
129  Eigen::Affine3d pose_eigend;
130  Eigen::Affine3f pose_eigen;
131  tf::poseMsgToEigen(pose_msg->pose, pose_eigend);
132  convertEigenAffine3(pose_eigend, pose_eigen);
133  Eigen::Vector3f pose_point(pose_eigen.translation());
134  double min_distance = DBL_MAX;
136  for (size_t i = 0; i < convexes.size(); i++) {
137  jsk_recognition_utils::ConvexPolygon::Ptr convex = convexes[i];
138  double d = convex->distanceToPoint(pose_point);
139  if (d < min_distance) {
140  min_convex = convex;
141  min_distance = d;
142  }
143  }
144 
145  if (min_convex) {
146  geometry_msgs::PoseStamped aligned_pose = alignPose(pose_eigen, min_convex);
147  aligned_pose.header = pose_msg->header;
148  polygon_aligned_pub_.publish(aligned_pose);
149  }
150  else {
151  polygon_aligned_pub_.publish(pose_msg);
152  }
153  }
154 
156  jsk_recognition_msgs::SnapFootstep::Request& req,
157  jsk_recognition_msgs::SnapFootstep::Response& res)
158  {
159  boost::mutex::scoped_lock lock(mutex_);
160  jsk_footstep_msgs::FootstepArray input_footsteps = req.input;
161  res.output.header = input_footsteps.header;
162  std::vector<jsk_recognition_utils::ConvexPolygon::Ptr> convexes
163  = createConvexes(input_footsteps.header.frame_id,
164  input_footsteps.header.stamp,
165  polygons_);
166  for (size_t i = 0; i < input_footsteps.footsteps.size(); i++) {
167  jsk_footstep_msgs::Footstep footstep = input_footsteps.footsteps[i];
168  Eigen::Affine3d pose_eigend;
169  Eigen::Affine3f pose_eigen;
170  tf::poseMsgToEigen(footstep.pose, pose_eigen);
171  Eigen::Vector3f pose_point(pose_eigen.translation());
172  int min_index = findNearestConvex(pose_point, convexes);
173  jsk_footstep_msgs::Footstep aligned_footstep;
174  if (min_index != -1) {
175  jsk_recognition_utils::ConvexPolygon::Ptr min_convex = convexes[min_index];
176  geometry_msgs::PoseStamped aligned_pose = alignPose(pose_eigen, min_convex);
177  aligned_footstep.pose = aligned_pose.pose;
178  }
179  else {
180  aligned_footstep.pose = footstep.pose;
181  //convex_aligned_pub_.publish(pose_msg); // shoud we publish this?
182  }
183  aligned_footstep.leg = footstep.leg;
184  aligned_footstep.dimensions = footstep.dimensions;
185  aligned_footstep.duration = footstep.duration;
186  aligned_footstep.footstep_group = footstep.footstep_group;
187  res.output.footsteps.push_back(aligned_footstep);
188  }
189  return true;
190  }
191 
193  const geometry_msgs::PolygonStamped::ConstPtr& poly_msg)
194  {
195  boost::mutex::scoped_lock lock(mutex_);
196  geometry_msgs::PoseArray pose_array;
197  pose_array.header = poly_msg->header;
198  if (!polygons_) {
199  NODELET_ERROR("no polygon is ready");
200  return;
201  }
202  std::vector<jsk_recognition_utils::ConvexPolygon::Ptr> convexes
203  = createConvexes(poly_msg->header.frame_id,
204  poly_msg->header.stamp,
205  polygons_);
206  for (size_t i = 0; i < poly_msg->polygon.points.size(); i++) {
207  geometry_msgs::Point32 p = poly_msg->polygon.points[i];
208  Eigen::Vector3f pose_point(p.x, p.y, p.z);
209  int min_index = findNearestConvex(pose_point, convexes);
210  if (min_index == -1) {
211  NODELET_ERROR("cannot project onto convex");
212  return;
213  }
214  else {
215  jsk_recognition_utils::ConvexPolygon::Ptr min_convex = convexes[min_index];
216  Eigen::Affine3f pose_eigen = Eigen::Affine3f::Identity();
217  pose_eigen.translate(pose_point);
218  geometry_msgs::PoseStamped aligned_pose = alignPose(pose_eigen, min_convex);
219  aligned_pose.header = poly_msg->header;
220  pose_array.poses.push_back(aligned_pose.pose);
221  }
222  }
224  }
225 
227  const Eigen::Vector3f& pose_point,
228  const std::vector<jsk_recognition_utils::ConvexPolygon::Ptr>& convexes)
229  {
230  int min_index = -1;
231  double min_distance = DBL_MAX;
233  for (size_t i = 0; i < convexes.size(); i++) {
234  jsk_recognition_utils::ConvexPolygon::Ptr convex = convexes[i];
235  if (convex->isProjectableInside(pose_point)) {
236  double d = convex->distanceToPoint(pose_point);
237  if (d < min_distance) {
238  min_distance = d;
239  min_convex = convex;
240  min_index = i;
241  }
242  }
243  }
244  return min_index;
245  }
246 
248  const geometry_msgs::PoseStamped::ConstPtr& pose_msg)
249  {
250  boost::mutex::scoped_lock lock(mutex_);
251  if (!polygons_) {
252  NODELET_ERROR("no polygon is ready");
253  convex_aligned_pub_.publish(pose_msg);
254  return;
255  }
256  std::vector<jsk_recognition_utils::ConvexPolygon::Ptr> convexes
257  = createConvexes(pose_msg->header.frame_id,
258  pose_msg->header.stamp,
259  polygons_);
260  Eigen::Affine3d pose_eigend;
261  Eigen::Affine3f pose_eigen;
262  tf::poseMsgToEigen(pose_msg->pose, pose_eigend);
263  convertEigenAffine3(pose_eigend, pose_eigen);
264  Eigen::Vector3f pose_point(pose_eigen.translation());
265  int min_index = findNearestConvex(pose_point, convexes);
266  if (min_index != -1) {
267  jsk_recognition_utils::ConvexPolygon::Ptr min_convex = convexes[min_index];
268  geometry_msgs::PoseStamped aligned_pose = alignPose(pose_eigen, min_convex);
269  aligned_pose.header = pose_msg->header;
270  convex_aligned_pub_.publish(aligned_pose);
271  }
272  else {
273  convex_aligned_pub_.publish(pose_msg); // shoud we publish this?
274  }
275  }
276 
277  geometry_msgs::PoseStamped SnapIt::alignPose(
278  Eigen::Affine3f& pose, jsk_recognition_utils::ConvexPolygon::Ptr convex)
279  {
280  Eigen::Affine3f aligned_pose(pose);
281  Eigen::Vector3f original_point(pose.translation());
282  Eigen::Vector3f projected_point;
283  convex->project(original_point, projected_point);
284 
285  Eigen::Vector3f normal = convex->getNormal();
286  Eigen::Vector3f old_normal;
287  old_normal[0] = pose(0, 2);
288  old_normal[1] = pose(1, 2);
289  old_normal[2] = pose(2, 2);
290  Eigen::Quaternionf rot;
291  if (normal.dot(old_normal) < 0) {
292  normal = - normal;
293  }
294  rot.setFromTwoVectors(old_normal, normal);
295  aligned_pose = aligned_pose * rot;
296  aligned_pose.translation() = projected_point;
297  Eigen::Affine3d aligned_posed;
298  convertEigenAffine3(aligned_pose, aligned_posed);
299  geometry_msgs::PoseStamped ret;
300  tf::poseEigenToMsg(aligned_posed, ret.pose);
301  return ret;
302  }
303 
304  std::vector<jsk_recognition_utils::ConvexPolygon::Ptr> SnapIt::createConvexes(
305  const std::string& frame_id, const ros::Time& stamp,
306  jsk_recognition_msgs::PolygonArray::ConstPtr polygons)
307  {
308  std::vector<jsk_recognition_utils::ConvexPolygon::Ptr> result;
309  try
310  {
311  for (size_t i = 0; i < polygons->polygons.size(); i++) {
312  geometry_msgs::PolygonStamped polygon = polygons->polygons[i];
314 
316  tf_listener_,
317  polygon.header.frame_id, frame_id, stamp, ros::Duration(5.0));
318  for (size_t j = 0; j < polygon.polygon.points.size(); j++) {
319  Eigen::Vector4d p;
320  p[0] = polygon.polygon.points[j].x;
321  p[1] = polygon.polygon.points[j].y;
322  p[2] = polygon.polygon.points[j].z;
323  p[3] = 1;
324  Eigen::Affine3d eigen_transform;
325  tf::transformTFToEigen(transform, eigen_transform);
326  Eigen::Vector4d transformed_pointd = eigen_transform.inverse() * p;
327  Eigen::Vector3f transformed_point;
328  transformed_point[0] = transformed_pointd[0];
329  transformed_point[1] = transformed_pointd[1];
330  transformed_point[2] = transformed_pointd[2];
331  vertices.push_back(transformed_point);
332  }
333  std::reverse(vertices.begin(), vertices.end());
335  result.push_back(convex);
336  }
337  }
338  catch (tf2::ConnectivityException &e)
339  {
340  NODELET_ERROR("Transform error: %s", e.what());
341  }
343  {
344  NODELET_ERROR("Transform error: %s", e.what());
345  }
346  catch (tf2::ExtrapolationException &e)
347  {
348  NODELET_ERROR("Transform error: %s", e.what());
349  }
350  return result;
351  }
352 }
353 
d
ros::ServiceServer align_footstep_srv_
Definition: snapit.h:108
message_filters::Subscriber< jsk_recognition_msgs::PolygonArray > sub_polygons_
Definition: snapit.h:97
#define NODELET_ERROR(...)
void publish(const boost::shared_ptr< M > &message) const
void transformTFToEigen(const tf::Transform &t, Eigen::Affine3d &e)
virtual void unsubscribe()
void poseEigenToMsg(const Eigen::Affine3d &e, geometry_msgs::Pose &m)
virtual void subscribe()
void poseMsgToEigen(const geometry_msgs::Pose &m, Eigen::Affine3d &e)
tf::StampedTransform lookupTransformWithDuration(tf::TransformListener *listener, const std::string &to_frame, const std::string &from_frame, const ros::Time &stamp, ros::Duration duration)
virtual geometry_msgs::PoseStamped alignPose(Eigen::Affine3f &pose, jsk_recognition_utils::ConvexPolygon::Ptr convex)
virtual void polygonCallback(const jsk_recognition_msgs::PolygonArray::ConstPtr &polygon_msg, const jsk_recognition_msgs::ModelCoefficientsArray::ConstPtr &coefficients_msg)
int min_index
PLUGINLIB_EXPORT_CLASS(jsk_pcl_ros::SnapIt, nodelet::Nodelet)
tf::TransformListener * tf_listener_
Definition: snapit.h:96
result
virtual void onInit()
virtual void convexAlignPolygonCallback(const geometry_msgs::PolygonStamped::ConstPtr &poly_msg)
jsk_recognition_msgs::PolygonArray::ConstPtr polygons_
Definition: snapit.h:109
ros::Publisher convex_aligned_pose_array_pub_
Definition: snapit.h:102
virtual void polygonAlignCallback(const geometry_msgs::PoseStamped::ConstPtr &pose_msg)
boost::shared_ptr< ros::NodeHandle > pnh_
void convertEigenAffine3(const Eigen::Affine3d &from, Eigen::Affine3f &to)
virtual bool footstepAlignServiceCallback(jsk_recognition_msgs::SnapFootstep::Request &req, jsk_recognition_msgs::SnapFootstep::Response &res)
ros::Subscriber polygon_align_sub_
Definition: snapit.h:104
virtual int findNearestConvex(const Eigen::Vector3f &pose_point, const std::vector< jsk_recognition_utils::ConvexPolygon::Ptr > &convexes)
rot
jsk_topic_tools::VitalChecker::Ptr vital_checker_
std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f > > Vertices
void subscribe(ros::NodeHandle &nh, const std::string &topic, uint32_t queue_size, const ros::TransportHints &transport_hints=ros::TransportHints(), ros::CallbackQueueInterface *callback_queue=0)
ros::Publisher polygon_aligned_pub_
Definition: snapit.h:100
p
ros::Subscriber convex_align_sub_
Definition: snapit.h:105
ros::Subscriber convex_align_polygon_sub_
Definition: snapit.h:106
message_filters::Subscriber< jsk_recognition_msgs::ModelCoefficientsArray > sub_coefficients_
Definition: snapit.h:98
boost::mutex mutex_
Definition: snapit.h:110
static tf::TransformListener * getInstance()
virtual std::vector< jsk_recognition_utils::ConvexPolygon::Ptr > createConvexes(const std::string &frame_id, const ros::Time &stamp, jsk_recognition_msgs::PolygonArray::ConstPtr polygons)
virtual void convexAlignCallback(const geometry_msgs::PoseStamped::ConstPtr &pose_msg)
ros::Publisher convex_aligned_pub_
Definition: snapit.h:101
boost::shared_ptr< message_filters::Synchronizer< SyncPolygonPolicy > > sync_polygon_
Definition: snapit.h:99


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