handle_estimator_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 
38 #include <geometry_msgs/PoseArray.h>
39 #include <geometry_msgs/PoseStamped.h>
42 
43 namespace jsk_pcl_ros
44 {
46  {
47  ConnectionBasedNodelet::onInit();
48  output_buf.resize(100);
49 
50  pnh_->param("gripper_size", gripper_size_, 0.08); // defaults to pr2 gripper size
51  pnh_->param("approach_offset", approach_offset_, 0.1); // default to 10 cm
52  pnh_->param("angle_divide_num", angle_divide_num_, 6); // even will be better
53  pub_ = advertise<geometry_msgs::PoseArray>(*pnh_, "output", 1);
54  pub_best_ = advertise<geometry_msgs::PoseStamped>(*pnh_, "output_best", 1);
55  pub_selected_ = advertise<geometry_msgs::PoseStamped>(*pnh_, "output_selected", 1);
56 
57  pub_preapproach_ = advertise<geometry_msgs::PoseArray>(*pnh_, "output_preapproach", 1);
58  pub_selected_preapproach_ = advertise<geometry_msgs::PoseStamped>(*pnh_, "output_selected_preapproach", 1);
59 
60  onInitPostProcess();
61  }
62 
64  // message_filters::Synchronizer needs to be called reset
65  // before message_filters::Subscriber is freed.
66  // Calling reset fixes the following error on shutdown of the nodelet:
67  // terminate called after throwing an instance of
68  // 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >'
69  // what(): boost: mutex lock failed in pthread_mutex_lock: Invalid argument
70  // Also see https://github.com/ros/ros_comm/issues/720 .
71  sync_.reset();
72  }
73 
74 
76  {
77  sub_index_ = pnh_->subscribe<jsk_recognition_msgs::Int32Stamped>("selected_index", 1, boost::bind( &HandleEstimator::selectedIndexCallback, this, _1));
78  sub_input_.subscribe(*pnh_, "input", 1);
79  sub_box_.subscribe(*pnh_, "input_box", 1);
80  sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
81  sync_->connectInput(sub_input_, sub_box_);
82  sync_->registerCallback(boost::bind(&HandleEstimator::estimate, this, _1, _2));
83  }
84 
86  {
90  }
91 
92  void HandleEstimator::estimate(const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
93  const jsk_recognition_msgs::BoundingBox::ConstPtr& box_msg)
94  {
95  // pack dimensions into vector
96  std::vector<double> dimensions;
97  dimensions.push_back(box_msg->dimensions.x);
98  dimensions.push_back(box_msg->dimensions.y);
99  dimensions.push_back(box_msg->dimensions.z);
100  size_t longest_index = 0;
101  for (size_t i = 1; i < 3; i++) {
102  if (dimensions[i] > dimensions[longest_index]) {
103  longest_index = i;
104  }
105  }
106  NODELET_INFO_STREAM("longest index is: " << longest_index);
107  HandleType handle_type;
108  // detect the handle type
109  if (longest_index == 2) {
110  if (dimensions[0] < gripper_size_ || dimensions[1] < gripper_size_) {
112  }
113  else {
114  handle_type = NO_HANDLE;
115  }
116  }
117  else {
118  if (longest_index == 0) {
119  if (dimensions[1] < gripper_size_ || dimensions[2] < gripper_size_) {
121  }
122  else {
123  handle_type = NO_HANDLE;
124  }
125  }
126  else { // 1
127  if (dimensions[0] < gripper_size_ || dimensions[2] < gripper_size_) {
129  }
130  else {
131  handle_type = NO_HANDLE;
132  }
133  }
134 
135  }
136  estimateHandle(handle_type, cloud_msg, box_msg);
137  }
138 
139  void HandleEstimator::estimateHandle(const HandleType& handle_type,
140  const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
141  const jsk_recognition_msgs::BoundingBox::ConstPtr& box_msg)
142  {
143  if (handle_type == NO_HANDLE) {
144  NODELET_ERROR("failed to estimate handle");
145  }
146  else if (handle_type == HANDLE_SMALL_ENOUGH_LIE_ON_PLANE_Y_LONGEST) {
147  handleSmallEnoughLieOnPlane(cloud_msg, box_msg, true);
148  }
149  else if (handle_type == HANDLE_SMALL_ENOUGH_LIE_ON_PLANE_X_LONGEST) {
150  handleSmallEnoughLieOnPlane(cloud_msg, box_msg, false);
151  }
152  else if (handle_type == HANDLE_SMALL_ENOUGH_STAND_ON_PLANE) {
153  handleSmallEnoughStandOnPlane(cloud_msg, box_msg);
154  }
155  }
156 
158  const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
159  const jsk_recognition_msgs::BoundingBox::ConstPtr& box_msg)
160  {
161  geometry_msgs::PoseArray pose_array;
162  geometry_msgs::PoseArray prepose_array;
163  pose_array.header = box_msg->header;
164  prepose_array.header = box_msg->header;
165  Eigen::Affine3d center;
166  tf::poseMsgToEigen(box_msg->pose, center);
167  Eigen::Vector3d z = center.rotation().col(2);
168  Plane p(Eigen::Vector3f(z[0], z[1], z[2]), 0);
169  Eigen::Vector3d ray = center.translation().normalized();
170  Eigen::Vector3d ray_projected;
171  p.project(ray, ray_projected);
172  ray_projected.normalize();
173 
174  Eigen::Matrix3d center_refined_mat;
175  center_refined_mat.col(0) = ray_projected;
176  center_refined_mat.col(2) = z;
177  center_refined_mat.col(1) = z.cross(ray_projected);
178  Eigen::Affine3d center_refined
179  = Eigen::Translation3d(center.translation()) * Eigen::Quaterniond(center_refined_mat);
180 
181  const double angle_margin = 0.2;
182  const double start_angle = M_PI / 2.0 + angle_margin;
183  const double end_angle = M_PI + M_PI / 2.0 - angle_margin;
184  for (size_t i = 0; i < angle_divide_num_; i++) {
185  const double theta = (end_angle - start_angle) / angle_divide_num_ * i + start_angle;
186  Eigen::Vector3d offset_vec = Eigen::Vector3d(cos(theta), sin(theta), 0);
187  Eigen::Vector3d pre_approach_pos
188  = (center_refined * (approach_offset_ * offset_vec));
189  Eigen::Matrix3d orientation;
190  Eigen::Vector3d x_vec
191  = (center_refined.translation() - pre_approach_pos).normalized();
192  Eigen::Vector3d y_vec = z.cross(x_vec);
193 
194  orientation.col(0) = x_vec;
195  orientation.col(1) = y_vec;
196  orientation.col(2) = z;
197 
198  Eigen::Affine3d pre_grasp_pose = Eigen::Translation3d(pre_approach_pos) * Eigen::Quaterniond(orientation);
199  Eigen::Affine3d grasp_pose = Eigen::Translation3d(center.translation()) * Eigen::Quaterniond(orientation);
200  geometry_msgs::Pose ros_prepose;
201  geometry_msgs::Pose ros_pose;
202  tf::poseEigenToMsg(pre_grasp_pose, ros_prepose);
203  tf::poseEigenToMsg(grasp_pose, ros_pose);
204  prepose_array.poses.push_back(ros_prepose);
205  pose_array.poses.push_back(ros_pose);
206  }
207  pub_.publish(pose_array);
208  pub_preapproach_.publish(prepose_array);
209  geometry_msgs::PoseStamped best;
210  best.header = pose_array.header;
211  best.pose = pose_array.poses[pose_array.poses.size() / 2];
212  pub_best_.publish(best);
213 
214  output_buf.push_front(boost::make_tuple(pose_array, prepose_array));
215  }
216 
218  const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
219  const jsk_recognition_msgs::BoundingBox::ConstPtr& box_msg,
220  bool y_longest)
221  {
222  geometry_msgs::PoseArray pose_array;
223  geometry_msgs::PoseArray prepose_array;
224  pose_array.header = box_msg->header;
225  prepose_array.header = box_msg->header;
226  // center
227  Eigen::Affine3d center;
228  tf::poseMsgToEigen(box_msg->pose, center);
229  const double angle_margin = 0.2;
230  const double start_angle = angle_margin;
231  const double end_angle = M_PI - angle_margin;
232 
233  for (size_t i = 0; i <= angle_divide_num_; i++) { // angle_divide_num samples
234  const double theta = (end_angle - start_angle) / angle_divide_num_ * i + start_angle;
235  // x-z plane
236  Eigen::Vector3d offset_vec;
237  if (y_longest) {
238  offset_vec = Eigen::Vector3d(sin(theta), 0, cos(theta));
239  }
240  else {
241  offset_vec = Eigen::Vector3d(0, cos(theta), sin(theta));
242  }
243  Eigen::Vector3d pre_approach_pos
244  = (center * (approach_offset_ * offset_vec));
245  // compute unit vectors to construct orientation
246  Eigen::Matrix3d orientation;
247  if (y_longest) {
248  Eigen::Vector3d x_vec
249  = (center.translation() - pre_approach_pos).normalized();
250  Eigen::Vector3d z_vec = center.rotation().col(1);
251  Eigen::Vector3d y_vec = z_vec.cross(x_vec);
252  orientation.col(0) = x_vec;
253  orientation.col(1) = y_vec;
254  orientation.col(2) = z_vec;
255  }
256  else {
257  Eigen::Vector3d x_vec = (center.translation() - pre_approach_pos).normalized();
258  Eigen::Vector3d z_vec = center.rotation().col(0);
259  Eigen::Vector3d y_vec = z_vec.cross(x_vec);
260  orientation.col(0) = x_vec;
261  orientation.col(1) = y_vec;
262  orientation.col(2) = z_vec;
263  }
264 
265  Eigen::Affine3d pre_grasp_pose = Eigen::Translation3d(pre_approach_pos) * Eigen::Quaterniond(orientation);
266  Eigen::Affine3d grasp_pose = Eigen::Translation3d(center.translation()) * Eigen::Quaterniond(orientation);
267  geometry_msgs::Pose ros_prepose, ros_pose;
268  tf::poseEigenToMsg(pre_grasp_pose, ros_prepose);
269  tf::poseEigenToMsg(grasp_pose, ros_pose);
270  pose_array.poses.push_back(ros_pose);
271  prepose_array.poses.push_back(ros_prepose);
272  }
273  pub_.publish(pose_array);
274  pub_preapproach_.publish(prepose_array);
275  geometry_msgs::PoseStamped best;
276  best.header = pose_array.header;
277  best.pose = pose_array.poses[pose_array.poses.size() / 2];
278  pub_best_.publish(best);
279 
280  output_buf.push_front(boost::make_tuple(pose_array, prepose_array));
281  }
282 
283  void HandleEstimator::selectedIndexCallback( const jsk_recognition_msgs::Int32StampedConstPtr &index){
284  boost::circular_buffer<boost::tuple<geometry_msgs::PoseArray, geometry_msgs::PoseArray> >::iterator it = output_buf.begin();
285  while (it != output_buf.end()) {
286  geometry_msgs::PoseArray pose_array = it->get<0>();
287  geometry_msgs::PoseArray prepose_array = it->get<1>();
288 
289  if(pose_array.header.stamp == index->header.stamp){
290  geometry_msgs::PoseStamped ps;
291  ps.header = pose_array.header;
292  ps.pose = pose_array.poses[index->data];
294 
295  ps.header = prepose_array.header;
296  ps.pose = prepose_array.poses[index->data];
298  break;
299  }
300  ++it;
301  }
302  }
303 }
304 
tf::poseMsgToEigen
void poseMsgToEigen(const geometry_msgs::Pose &m, Eigen::Affine3d &e)
jsk_pcl_ros::HandleEstimator::estimate
virtual void estimate(const sensor_msgs::PointCloud2::ConstPtr &cloud_msg, const jsk_recognition_msgs::BoundingBox::ConstPtr &box_msg)
Definition: handle_estimator_nodelet.cpp:124
jsk_pcl_ros::HandleEstimator::handleSmallEnoughStandOnPlane
virtual void handleSmallEnoughStandOnPlane(const sensor_msgs::PointCloud2::ConstPtr &cloud_msg, const jsk_recognition_msgs::BoundingBox::ConstPtr &box_msg)
Definition: handle_estimator_nodelet.cpp:189
NODELET_ERROR
#define NODELET_ERROR(...)
i
int i
jsk_pcl_ros::HandleEstimator::HANDLE_SMALL_ENOUGH_LIE_ON_PLANE_X_LONGEST
@ HANDLE_SMALL_ENOUGH_LIE_ON_PLANE_X_LONGEST
Definition: handle_estimator.h:132
jsk_pcl_ros::HandleEstimator::pub_preapproach_
ros::Publisher pub_preapproach_
Definition: handle_estimator.h:156
PLUGINLIB_EXPORT_CLASS
PLUGINLIB_EXPORT_CLASS(jsk_pcl_ros::HandleEstimator, nodelet::Nodelet)
box_msg
jsk_recognition_msgs::BoundingBoxArray::ConstPtr box_msg
p
p
M_PI
#define M_PI
jsk_pcl_ros::HandleEstimator::handleSmallEnoughLieOnPlane
virtual void handleSmallEnoughLieOnPlane(const sensor_msgs::PointCloud2::ConstPtr &cloud_msg, const jsk_recognition_msgs::BoundingBox::ConstPtr &box_msg, bool y_longest)
Definition: handle_estimator_nodelet.cpp:249
theta
int theta
geo_util.h
jsk_pcl_ros::HandleEstimator::~HandleEstimator
virtual ~HandleEstimator()
Definition: handle_estimator_nodelet.cpp:95
ros::Subscriber::shutdown
void shutdown()
jsk_pcl_ros::HandleEstimator::pub_selected_preapproach_
ros::Publisher pub_selected_preapproach_
Definition: handle_estimator.h:156
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
sin
double sin()
message_filters::Subscriber::unsubscribe
void unsubscribe()
jsk_pcl_ros::HandleEstimator::approach_offset_
double approach_offset_
Definition: handle_estimator.h:163
jsk_pcl_ros::HandleEstimator::HandleType
HandleType
Definition: handle_estimator.h:127
class_list_macros.h
jsk_pcl_ros::HandleEstimator::sub_box_
message_filters::Subscriber< jsk_recognition_msgs::BoundingBox > sub_box_
Definition: handle_estimator.h:160
jsk_pcl_ros
Definition: add_color_from_image.h:51
jsk_pcl_ros::HandleEstimator::onInit
virtual void onInit()
Definition: handle_estimator_nodelet.cpp:77
eigen_msg.h
jsk_pcl_ros::HandleEstimator::subscribe
virtual void subscribe()
Definition: handle_estimator_nodelet.cpp:107
jsk_pcl_ros::HandleEstimator::pub_
ros::Publisher pub_
Definition: handle_estimator.h:156
jsk_pcl_ros::HandleEstimator::selectedIndexCallback
virtual void selectedIndexCallback(const jsk_recognition_msgs::Int32StampedConstPtr &index)
Definition: handle_estimator_nodelet.cpp:315
tf::poseEigenToMsg
void poseEigenToMsg(const Eigen::Affine3d &e, geometry_msgs::Pose &m)
jsk_pcl_ros::HandleEstimator::sub_input_
message_filters::Subscriber< sensor_msgs::PointCloud2 > sub_input_
Definition: handle_estimator.h:159
jsk_pcl_ros::HandleEstimator::NO_HANDLE
@ NO_HANDLE
Definition: handle_estimator.h:129
message_filters::Subscriber::subscribe
void subscribe()
jsk_pcl_ros::HandleEstimator::angle_divide_num_
int angle_divide_num_
Definition: handle_estimator.h:164
jsk_pcl_ros::HandleEstimator::HANDLE_SMALL_ENOUGH_LIE_ON_PLANE_Y_LONGEST
@ HANDLE_SMALL_ENOUGH_LIE_ON_PLANE_Y_LONGEST
Definition: handle_estimator.h:131
jsk_pcl_ros::HandleEstimator::HANDLE_SMALL_ENOUGH_STAND_ON_PLANE
@ HANDLE_SMALL_ENOUGH_STAND_ON_PLANE
Definition: handle_estimator.h:130
nodelet::Nodelet
jsk_pcl_ros::HandleEstimator::gripper_size_
double gripper_size_
Definition: handle_estimator.h:162
jsk_pcl_ros::HandleEstimator::unsubscribe
virtual void unsubscribe()
Definition: handle_estimator_nodelet.cpp:117
cos
double cos()
index
unsigned int index
jsk_pcl_ros::HandleEstimator::pub_selected_
ros::Publisher pub_selected_
Definition: handle_estimator.h:156
jsk_pcl_ros::HandleEstimator::pub_best_
ros::Publisher pub_best_
Definition: handle_estimator.h:156
jsk_pcl_ros::HandleEstimator::sync_
boost::shared_ptr< message_filters::Synchronizer< SyncPolicy > > sync_
Definition: handle_estimator.h:158
NODELET_INFO_STREAM
#define NODELET_INFO_STREAM(...)
jsk_pcl_ros::HandleEstimator::sub_index_
ros::Subscriber sub_index_
Definition: handle_estimator.h:157
handle_estimator.h
jsk_pcl_ros::HandleEstimator::estimateHandle
virtual void estimateHandle(const HandleType &handle_type, const sensor_msgs::PointCloud2::ConstPtr &cloud_msg, const jsk_recognition_msgs::BoundingBox::ConstPtr &box_msg)
Definition: handle_estimator_nodelet.cpp:171
jsk_pcl_ros::HandleEstimator::output_buf
boost::circular_buffer< boost::tuple< geometry_msgs::PoseArray, geometry_msgs::PoseArray > > output_buf
Definition: handle_estimator.h:165
jsk_pcl_ros::HandleEstimator
Definition: handle_estimator.h:90
attention_pose_set.z
z
Definition: attention_pose_set.py:20


jsk_pcl_ros
Author(s): Yohei Kakiuchi
autogenerated on Tue Jan 7 2025 04:05:44