00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "jsk_pcl_ros/handle_estimator.h"
00037 #include <pluginlib/class_list_macros.h>
00038 #include <geometry_msgs/PoseArray.h>
00039 #include <geometry_msgs/PoseStamped.h>
00040 #include <eigen_conversions/eigen_msg.h>
00041 #include "jsk_recognition_utils/geo_util.h"
00042
00043 namespace jsk_pcl_ros
00044 {
00045 void HandleEstimator::onInit()
00046 {
00047 ConnectionBasedNodelet::onInit();
00048 output_buf.resize(100);
00049
00050 pnh_->param("gripper_size", gripper_size_, 0.08);
00051 pnh_->param("approach_offset", approach_offset_, 0.1);
00052 pnh_->param("angle_divide_num", angle_divide_num_, 6);
00053 pub_ = advertise<geometry_msgs::PoseArray>(*pnh_, "output", 1);
00054 pub_best_ = advertise<geometry_msgs::PoseStamped>(*pnh_, "output_best", 1);
00055 pub_selected_ = advertise<geometry_msgs::PoseStamped>(*pnh_, "output_selected", 1);
00056
00057 pub_preapproach_ = advertise<geometry_msgs::PoseArray>(*pnh_, "output_preapproach", 1);
00058 pub_selected_preapproach_ = advertise<geometry_msgs::PoseStamped>(*pnh_, "output_selected_preapproach", 1);
00059
00060 onInitPostProcess();
00061 }
00062
00063 void HandleEstimator::subscribe()
00064 {
00065 sub_index_ = pnh_->subscribe<jsk_recognition_msgs::Int32Stamped>("selected_index", 1, boost::bind( &HandleEstimator::selectedIndexCallback, this, _1));
00066 sub_input_.subscribe(*pnh_, "input", 1);
00067 sub_box_.subscribe(*pnh_, "input_box", 1);
00068 sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
00069 sync_->connectInput(sub_input_, sub_box_);
00070 sync_->registerCallback(boost::bind(&HandleEstimator::estimate, this, _1, _2));
00071 }
00072
00073 void HandleEstimator::unsubscribe()
00074 {
00075 sub_index_.shutdown();
00076 sub_input_.unsubscribe();
00077 sub_box_.unsubscribe();
00078 }
00079
00080 void HandleEstimator::estimate(const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
00081 const jsk_recognition_msgs::BoundingBox::ConstPtr& box_msg)
00082 {
00083
00084 std::vector<double> dimensions;
00085 dimensions.push_back(box_msg->dimensions.x);
00086 dimensions.push_back(box_msg->dimensions.y);
00087 dimensions.push_back(box_msg->dimensions.z);
00088 size_t longest_index = 0;
00089 for (size_t i = 1; i < 3; i++) {
00090 if (dimensions[i] > dimensions[longest_index]) {
00091 longest_index = i;
00092 }
00093 }
00094 NODELET_INFO_STREAM("longest index is: " << longest_index);
00095 HandleType handle_type;
00096
00097 if (longest_index == 2) {
00098 if (dimensions[0] < gripper_size_ || dimensions[1] < gripper_size_) {
00099 handle_type = HANDLE_SMALL_ENOUGH_STAND_ON_PLANE;
00100 }
00101 else {
00102 handle_type = NO_HANDLE;
00103 }
00104 }
00105 else {
00106 if (longest_index == 0) {
00107 if (dimensions[1] < gripper_size_ || dimensions[2] < gripper_size_) {
00108 handle_type = HANDLE_SMALL_ENOUGH_LIE_ON_PLANE_X_LONGEST;
00109 }
00110 else {
00111 handle_type = NO_HANDLE;
00112 }
00113 }
00114 else {
00115 if (dimensions[0] < gripper_size_ || dimensions[2] < gripper_size_) {
00116 handle_type = HANDLE_SMALL_ENOUGH_LIE_ON_PLANE_Y_LONGEST;
00117 }
00118 else {
00119 handle_type = NO_HANDLE;
00120 }
00121 }
00122
00123 }
00124 estimateHandle(handle_type, cloud_msg, box_msg);
00125 }
00126
00127 void HandleEstimator::estimateHandle(const HandleType& handle_type,
00128 const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
00129 const jsk_recognition_msgs::BoundingBox::ConstPtr& box_msg)
00130 {
00131 if (handle_type == NO_HANDLE) {
00132 NODELET_ERROR("failed to estimate handle");
00133 }
00134 else if (handle_type == HANDLE_SMALL_ENOUGH_LIE_ON_PLANE_Y_LONGEST) {
00135 handleSmallEnoughLieOnPlane(cloud_msg, box_msg, true);
00136 }
00137 else if (handle_type == HANDLE_SMALL_ENOUGH_LIE_ON_PLANE_X_LONGEST) {
00138 handleSmallEnoughLieOnPlane(cloud_msg, box_msg, false);
00139 }
00140 else if (handle_type == HANDLE_SMALL_ENOUGH_STAND_ON_PLANE) {
00141 handleSmallEnoughStandOnPlane(cloud_msg, box_msg);
00142 }
00143 }
00144
00145 void HandleEstimator::handleSmallEnoughStandOnPlane(
00146 const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
00147 const jsk_recognition_msgs::BoundingBox::ConstPtr& box_msg)
00148 {
00149 geometry_msgs::PoseArray pose_array;
00150 geometry_msgs::PoseArray prepose_array;
00151 pose_array.header = box_msg->header;
00152 prepose_array.header = box_msg->header;
00153 Eigen::Affine3d center;
00154 tf::poseMsgToEigen(box_msg->pose, center);
00155 Eigen::Vector3d z = center.rotation().col(2);
00156 Plane p(Eigen::Vector3f(z[0], z[1], z[2]), 0);
00157 Eigen::Vector3d ray = center.translation().normalized();
00158 Eigen::Vector3d ray_projected;
00159 p.project(ray, ray_projected);
00160 ray_projected.normalize();
00161
00162 Eigen::Matrix3d center_refined_mat;
00163 center_refined_mat.col(0) = ray_projected;
00164 center_refined_mat.col(2) = z;
00165 center_refined_mat.col(1) = z.cross(ray_projected);
00166 Eigen::Affine3d center_refined
00167 = Eigen::Translation3d(center.translation()) * Eigen::Quaterniond(center_refined_mat);
00168
00169 const double angle_margin = 0.2;
00170 const double start_angle = M_PI / 2.0 + angle_margin;
00171 const double end_angle = M_PI + M_PI / 2.0 - angle_margin;
00172 for (size_t i = 0; i < angle_divide_num_; i++) {
00173 const double theta = (end_angle - start_angle) / angle_divide_num_ * i + start_angle;
00174 Eigen::Vector3d offset_vec = Eigen::Vector3d(cos(theta), sin(theta), 0);
00175 Eigen::Vector3d pre_approach_pos
00176 = (center_refined * (approach_offset_ * offset_vec));
00177 Eigen::Matrix3d orientation;
00178 Eigen::Vector3d x_vec
00179 = (center_refined.translation() - pre_approach_pos).normalized();
00180 Eigen::Vector3d y_vec = z.cross(x_vec);
00181
00182 orientation.col(0) = x_vec;
00183 orientation.col(1) = y_vec;
00184 orientation.col(2) = z;
00185
00186 Eigen::Affine3d pre_grasp_pose = Eigen::Translation3d(pre_approach_pos) * Eigen::Quaterniond(orientation);
00187 Eigen::Affine3d grasp_pose = Eigen::Translation3d(center.translation()) * Eigen::Quaterniond(orientation);
00188 geometry_msgs::Pose ros_prepose;
00189 geometry_msgs::Pose ros_pose;
00190 tf::poseEigenToMsg(pre_grasp_pose, ros_prepose);
00191 tf::poseEigenToMsg(grasp_pose, ros_pose);
00192 prepose_array.poses.push_back(ros_prepose);
00193 pose_array.poses.push_back(ros_pose);
00194 }
00195 pub_.publish(pose_array);
00196 pub_preapproach_.publish(prepose_array);
00197 geometry_msgs::PoseStamped best;
00198 best.header = pose_array.header;
00199 best.pose = pose_array.poses[pose_array.poses.size() / 2];
00200 pub_best_.publish(best);
00201
00202 output_buf.push_front(boost::make_tuple(pose_array, prepose_array));
00203 }
00204
00205 void HandleEstimator::handleSmallEnoughLieOnPlane(
00206 const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
00207 const jsk_recognition_msgs::BoundingBox::ConstPtr& box_msg,
00208 bool y_longest)
00209 {
00210 geometry_msgs::PoseArray pose_array;
00211 geometry_msgs::PoseArray prepose_array;
00212 pose_array.header = box_msg->header;
00213 prepose_array.header = box_msg->header;
00214
00215 Eigen::Affine3d center;
00216 tf::poseMsgToEigen(box_msg->pose, center);
00217 const double angle_margin = 0.2;
00218 const double start_angle = angle_margin;
00219 const double end_angle = M_PI - angle_margin;
00220
00221 for (size_t i = 0; i <= angle_divide_num_; i++) {
00222 const double theta = (end_angle - start_angle) / angle_divide_num_ * i + start_angle;
00223
00224 Eigen::Vector3d offset_vec;
00225 if (y_longest) {
00226 offset_vec = Eigen::Vector3d(sin(theta), 0, cos(theta));
00227 }
00228 else {
00229 offset_vec = Eigen::Vector3d(0, cos(theta), sin(theta));
00230 }
00231 Eigen::Vector3d pre_approach_pos
00232 = (center * (approach_offset_ * offset_vec));
00233
00234 Eigen::Matrix3d orientation;
00235 if (y_longest) {
00236 Eigen::Vector3d x_vec
00237 = (center.translation() - pre_approach_pos).normalized();
00238 Eigen::Vector3d z_vec = center.rotation().col(1);
00239 Eigen::Vector3d y_vec = z_vec.cross(x_vec);
00240 orientation.col(0) = x_vec;
00241 orientation.col(1) = y_vec;
00242 orientation.col(2) = z_vec;
00243 }
00244 else {
00245 Eigen::Vector3d x_vec = (center.translation() - pre_approach_pos).normalized();
00246 Eigen::Vector3d z_vec = center.rotation().col(0);
00247 Eigen::Vector3d y_vec = z_vec.cross(x_vec);
00248 orientation.col(0) = x_vec;
00249 orientation.col(1) = y_vec;
00250 orientation.col(2) = z_vec;
00251 }
00252
00253 Eigen::Affine3d pre_grasp_pose = Eigen::Translation3d(pre_approach_pos) * Eigen::Quaterniond(orientation);
00254 Eigen::Affine3d grasp_pose = Eigen::Translation3d(center.translation()) * Eigen::Quaterniond(orientation);
00255 geometry_msgs::Pose ros_prepose, ros_pose;
00256 tf::poseEigenToMsg(pre_grasp_pose, ros_prepose);
00257 tf::poseEigenToMsg(grasp_pose, ros_pose);
00258 pose_array.poses.push_back(ros_pose);
00259 prepose_array.poses.push_back(ros_prepose);
00260 }
00261 pub_.publish(pose_array);
00262 pub_preapproach_.publish(prepose_array);
00263 geometry_msgs::PoseStamped best;
00264 best.header = pose_array.header;
00265 best.pose = pose_array.poses[pose_array.poses.size() / 2];
00266 pub_best_.publish(best);
00267
00268 output_buf.push_front(boost::make_tuple(pose_array, prepose_array));
00269 }
00270
00271 void HandleEstimator::selectedIndexCallback( const jsk_recognition_msgs::Int32StampedConstPtr &index){
00272 boost::circular_buffer<boost::tuple<geometry_msgs::PoseArray, geometry_msgs::PoseArray> >::iterator it = output_buf.begin();
00273 while (it != output_buf.end()) {
00274 geometry_msgs::PoseArray pose_array = it->get<0>();
00275 geometry_msgs::PoseArray prepose_array = it->get<1>();
00276
00277 if(pose_array.header.stamp == index->header.stamp){
00278 geometry_msgs::PoseStamped ps;
00279 ps.header = pose_array.header;
00280 ps.pose = pose_array.poses[index->data];
00281 pub_selected_.publish(ps);
00282
00283 ps.header = prepose_array.header;
00284 ps.pose = prepose_array.poses[index->data];
00285 pub_selected_preapproach_.publish(ps);
00286 break;
00287 }
00288 ++it;
00289 }
00290 }
00291 }
00292
00293 PLUGINLIB_EXPORT_CLASS (jsk_pcl_ros::HandleEstimator, nodelet::Nodelet);