36 #define BOOST_PARAMETER_MAX_ARITY 7 
   39 #include <pcl/features/normal_3d.h> 
   40 #include <pcl/kdtree/kdtree_flann.h> 
   41 #include <pcl/common/transforms.h> 
   42 #include <pcl/filters/passthrough.h> 
   50 inline float NORM(
float vx, 
float vy, 
float vz){
return sqrt(vx*vx+vy*vy+vz*vz);}
 
   54   void HintedHandleEstimator::onInit()
 
   56     DiagnosticNodelet::onInit();
 
   57     pub_pose_ = advertise<geometry_msgs::PoseStamped>(
 
   58                                                       *pnh_, 
"handle_pose", 1);
 
   59     pub_length_ = advertise<std_msgs::Float64>(
 
   60                                                *pnh_, 
"handle_length", 1);
 
   61     pub_handle_ = advertise<jsk_recognition_msgs::SimpleHandle>(
 
   63     pub_debug_marker_ = advertise<visualization_msgs::Marker>(*pnh_, 
"debug_marker", 1);
 
   64     pub_debug_marker_array_ = advertise<visualization_msgs::MarkerArray>(*pnh_, 
"debug_marker_array", 1);
 
   66     pnh_->param(
"finger_l", handle.finger_l, 0.03);
 
   67     pnh_->param(
"finger_d", handle.finger_d, 0.02);
 
   68     pnh_->param(
"finger_w", handle.finger_w, 0.01);
 
   69     pnh_->param(
"arm_l", handle.arm_l, 0.05);
 
   70     pnh_->param(
"arm_d", handle.arm_d, 0.02);
 
   71     pnh_->param(
"arm_w", handle.arm_w, 0.1);
 
   75   HintedHandleEstimator::~HintedHandleEstimator() {
 
   86   void HintedHandleEstimator::subscribe()
 
   88     sub_cloud_.subscribe(*pnh_, 
"cloud", 1);
 
   89     sub_point_.subscribe(*pnh_, 
"point", 1); 
 
   90     sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
 
   91     sync_->connectInput(sub_cloud_, sub_point_);
 
   92     sync_->registerCallback(boost::bind(&HintedHandleEstimator::estimate, 
this, 
_1, 
_2));
 
   95   void HintedHandleEstimator::unsubscribe()
 
   97     sub_cloud_.unsubscribe();
 
   98     sub_point_.unsubscribe();
 
  101   void HintedHandleEstimator::estimate(
 
  102     const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
 
  103     const geometry_msgs::PointStampedConstPtr &point_msg)
 
  106     pcl::PointCloud<pcl::PointXYZ>::Ptr 
cloud(
new pcl::PointCloud<pcl::PointXYZ>);
 
  107     pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(
new pcl::PointCloud<pcl::Normal>);
 
  108     pcl::PassThrough<pcl::PointXYZ> pass;
 
  110     std::vector<int> pointIdxNKNSearch(
K);
 
  111     std::vector<float> pointNKNSquaredDistance(
K);
 
  112     pcl::search::KdTree<pcl::PointXYZ>::Ptr kd_tree(
new pcl::search::KdTree<pcl::PointXYZ>);
 
  115     geometry_msgs::PointStamped transed_point;
 
  119       listener_.waitForTransform(
cloud->header.frame_id, point_msg->header.frame_id, 
now, 
ros::Duration(1.0));
 
  120       listener_.transformPoint(
cloud->header.frame_id, 
now, *point_msg, point_msg->header.frame_id, transed_point);
 
  127     pcl::PointXYZ searchPoint;
 
  128     searchPoint.x = transed_point.point.x;
 
  129     searchPoint.y = transed_point.point.y;
 
  130     searchPoint.z = transed_point.point.z;
 
  133     pass.setInputCloud(
cloud);
 
  134     pass.setFilterFieldName(
"x");
 
  135     pass.setFilterLimits(searchPoint.x - 3*handle.arm_w, searchPoint.x + 3*handle.arm_w);
 
  137     pass.setInputCloud(
cloud);
 
  138     pass.setFilterFieldName(
"y");
 
  139     pass.setFilterLimits(searchPoint.y - 3*handle.arm_w, searchPoint.y + 3*handle.arm_w);
 
  141     pass.setInputCloud(
cloud);
 
  142     pass.setFilterFieldName(
"z");
 
  143     pass.setFilterLimits(searchPoint.z - 3*handle.arm_w, searchPoint.z + 3*handle.arm_w);
 
  146     if(
cloud->points.size() < 10){
 
  151       pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
 
  152       ne.setInputCloud(
cloud);
 
  153       ne.setSearchMethod(kd_tree);
 
  154       ne.setRadiusSearch(0.02);
 
  155       ne.setViewPoint(0, 0, 0);
 
  156       ne.compute(*cloud_normals);
 
  161     if(! (kd_tree->nearestKSearch (searchPoint, 
K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)){
 
  165     float x = 
cloud->points[pointIdxNKNSearch[0]].x;
 
  166     float y = 
cloud->points[pointIdxNKNSearch[0]].y;
 
  167     float z = 
cloud->points[pointIdxNKNSearch[0]].z;
 
  168     float v_x = cloud_normals->points[pointIdxNKNSearch[0]].normal_x;
 
  169     float v_y = cloud_normals->points[pointIdxNKNSearch[0]].normal_y;
 
  170     float v_z = cloud_normals->points[pointIdxNKNSearch[0]].normal_z;
 
  171     double theta = acos(v_x);
 
  175     double min_theta_index = 0;
 
  176     double min_width = 100;
 
  178     visualization_msgs::Marker debug_hand_marker;
 
  179     debug_hand_marker.header = cloud_msg->header;
 
  180     debug_hand_marker.ns = 
string(
"debug_grasp");
 
  181     debug_hand_marker.id = 0;
 
  182     debug_hand_marker.type = visualization_msgs::Marker::LINE_LIST;
 
  183     debug_hand_marker.pose.orientation.w = 1;
 
  184     debug_hand_marker.scale.x=0.003;
 
  187     for(
double theta_=0; theta_<3.14/2; 
 
  192       geometry_msgs::Pose pose_respected_to_tf;
 
  193       pose_respected_to_tf.position.x = 
x;
 
  194       pose_respected_to_tf.position.y = 
y;
 
  195       pose_respected_to_tf.position.z = 
z;
 
  196       pose_respected_to_tf.orientation.x = temp_qua.getX();
 
  197       pose_respected_to_tf.orientation.y = temp_qua.getY();
 
  198       pose_respected_to_tf.orientation.z = temp_qua.getZ();
 
  199       pose_respected_to_tf.orientation.w = temp_qua.
getW();
 
  200       Eigen::Affine3d box_pose_respected_to_cloud_eigend;
 
  202       Eigen::Affine3d box_pose_respected_to_cloud_eigend_inversed
 
  203         = box_pose_respected_to_cloud_eigend.inverse();
 
  204       Eigen::Matrix4f box_pose_respected_to_cloud_eigen_inversed_matrixf;
 
  205       Eigen::Matrix4d box_pose_respected_to_cloud_eigen_inversed_matrixd
 
  206         = box_pose_respected_to_cloud_eigend_inversed.matrix();
 
  207       jsk_recognition_utils::convertMatrix4<Eigen::Matrix4d, Eigen::Matrix4f>(
 
  208                                                                     box_pose_respected_to_cloud_eigen_inversed_matrixd,
 
  209                                                                     box_pose_respected_to_cloud_eigen_inversed_matrixf);
 
  210       Eigen::Affine3f offset = Eigen::Affine3f(box_pose_respected_to_cloud_eigen_inversed_matrixf);
 
  211       pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud(
new pcl::PointCloud<pcl::PointXYZ>);
 
  212       pcl::transformPointCloud(*
cloud, *output_cloud, offset);
 
  214       pcl::PassThrough<pcl::PointXYZ> pass;
 
  215       pcl::PointCloud<pcl::PointXYZ>::Ptr points_z(
new pcl::PointCloud<pcl::PointXYZ>), points_yz(
new pcl::PointCloud<pcl::PointXYZ>), points_xyz(
new pcl::PointCloud<pcl::PointXYZ>);
 
  216       pass.setInputCloud(output_cloud);
 
  217       pass.setFilterFieldName(
"y");
 
  218       pass.setFilterLimits(-handle.arm_w*2, handle.arm_w*2);
 
  219       pass.filter(*points_z);
 
  220       pass.setInputCloud(points_z);
 
  221       pass.setFilterFieldName(
"z");
 
  222       pass.setFilterLimits(-handle.finger_d, handle.finger_d);
 
  223       pass.filter(*points_yz);
 
  224       pass.setInputCloud(points_yz);
 
  225       pass.setFilterFieldName(
"x");
 
  226       pass.setFilterLimits(-(handle.arm_l-handle.finger_l), handle.finger_l);
 
  227       pass.filter(*points_xyz);
 
  228       pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
 
  230         points_xyz->points[
index].x = points_xyz->points[
index].z = 0;
 
  232       if(points_xyz->points.size() == 0){
ROS_INFO(
"points are empty");
return;}
 
  233       kdtree.setInputCloud(points_xyz);
 
  234       std::vector<int> pointIdxRadiusSearch;
 
  235       std::vector<float> pointRadiusSquaredDistance;
 
  236       pcl::PointXYZ search_point_tree;
 
  237       search_point_tree.x=search_point_tree.y=search_point_tree.z=0;
 
  238       if( kdtree.radiusSearch(search_point_tree, 10, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0 ){
 
  239         double before_w=10, temp_w;
 
  241           temp_w =
sqrt(pointRadiusSquaredDistance[
index]);
 
  242           if(temp_w - before_w > handle.finger_w*2){
 
  247         if(before_w < min_width){
 
  248           min_theta_index = theta_;
 
  249           min_width = before_w;
 
  254         geometry_msgs::Point temp_point;
 
  255         std_msgs::ColorRGBA temp_color;
 
  256         temp_color.r=0; temp_color.g=0; temp_color.b=1; temp_color.a=1;
 
  257         temp_point.x=
x-temp_mat.
getColumn(1)[0] * before_w;
 
  258         temp_point.y=
y-temp_mat.
getColumn(1)[1] * before_w;
 
  259         temp_point.z=
z-temp_mat.
getColumn(1)[2] * before_w;
 
  260         debug_hand_marker.points.push_back(temp_point);
 
  261         debug_hand_marker.colors.push_back(temp_color);
 
  262         temp_point.x+=2*temp_mat.
getColumn(1)[0] * before_w;
 
  263         temp_point.y+=2*temp_mat.
getColumn(1)[1] * before_w;
 
  264         temp_point.z+=2*temp_mat.
getColumn(1)[2] * before_w;
 
  265         debug_hand_marker.points.push_back(temp_point);
 
  266         debug_hand_marker.colors.push_back(temp_color);
 
  269     geometry_msgs::PoseStamped handle_pose_stamped;
 
  270     handle_pose_stamped.header = cloud_msg->header;
 
  271     handle_pose_stamped.pose.position.x = 
x;
 
  272     handle_pose_stamped.pose.position.y = 
y;
 
  273     handle_pose_stamped.pose.position.z = 
z;
 
  274     handle_pose_stamped.pose.orientation.x = min_qua.getX();
 
  275     handle_pose_stamped.pose.orientation.y = min_qua.getY();
 
  276     handle_pose_stamped.pose.orientation.z = min_qua.getZ();
 
  277     handle_pose_stamped.pose.orientation.w = min_qua.
getW();
 
  278     std_msgs::Float64 min_width_msg;
 
  279     min_width_msg.data = min_width;
 
  281     pub_debug_marker_.publish(debug_hand_marker);
 
  283     jsk_recognition_msgs::SimpleHandle simple_handle;
 
  284     simple_handle.header = handle_pose_stamped.header;
 
  285     simple_handle.pose = handle_pose_stamped.pose;
 
  286     simple_handle.handle_width = min_width;
 
  287     pub_handle_.publish(simple_handle);