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
00036
00037
00038 #include <ros/ros.h>
00039
00040 #include <tf/tf.h>
00041 #include <tf/transform_listener.h>
00042 #include <tf/transform_broadcaster.h>
00043
00044 #include <boost/bind.hpp>
00045
00046
00047 #include <std_msgs/String.h>
00048 #include <sensor_msgs/point_cloud_conversion.h>
00049
00050 #include <visualization_msgs/Marker.h>
00051 #include <visualization_msgs/MarkerArray.h>
00052
00053 #include <object_manipulation_msgs/GraspPlanning.h>
00054 #include <object_manipulation_msgs/ManipulationResult.h>
00055 #include <object_manipulation_msgs/FindClusterBoundingBox.h>
00056 #include <object_manipulator/tools/service_action_wrappers.h>
00057
00058 #include <dynamic_reconfigure/server.h>
00059 #include "pr2_grasp_adjust/EstimateConfig.h"
00060
00061 #include <object_manipulation_msgs/GraspPlanningAction.h>
00062
00063 #include <actionlib/server/simple_action_server.h>
00064
00065 #include <iostream>
00066 #include <fstream>
00067 #include <queue>
00068
00069 #include "gripper_model.h"
00070 #include "helpers.h"
00071 #include "grasp_adjust.h"
00072
00073 #include "pcl/io/pcd_io.h"
00074 #include "pcl/point_types.h"
00075 #include <pcl/ModelCoefficients.h>
00076 #include <pcl/features/normal_3d.h>
00077 #include <pcl/features/normal_3d_omp.h>
00078 #include <pcl/filters/extract_indices.h>
00079 #include <pcl/filters/passthrough.h>
00080 #include "pcl/filters/voxel_grid.h"
00081 #include <pcl/sample_consensus/method_types.h>
00082 #include <pcl/sample_consensus/model_types.h>
00083 #include <pcl/segmentation/sac_segmentation.h>
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 typedef pcl::PointXYZRGBNormal PointT;
00096
00097 const int GLOBAL_SEARCH = pr2_grasp_adjust::Estimate_global_search;
00098 const int LOCAL_SEARCH = pr2_grasp_adjust::Estimate_local_search;
00099 const int SINGLE_POSE = pr2_grasp_adjust::Estimate_single_pose;
00100
00101
00102 std::ofstream outputFile;
00103
00104
00105
00106 class GraspAdjustActionServer{
00107
00108 ros::NodeHandle nh_, nh_pvt_;
00109 ros::Subscriber sub_as_;
00110 ros::Publisher pub_cloud_, pub_cloud_roi_, pub_marker_, pub_marker_array_;
00111 ros::Publisher pub_im_status_;
00112
00113 std::string input_topic_;
00114 std::string output_topic_;
00115
00116 tf::TransformListener tfl_;
00117 tf::TransformBroadcaster tfb_;
00118
00119 sensor_msgs::PointCloud2 cloud_msg_;
00120 geometry_msgs::PoseStamped seed_ps_;
00121
00122 ros::Time now_;
00123
00124 GraspAdjust grasp_adjust_;
00125
00126
00127 actionlib::SimpleActionServer<object_manipulation_msgs::GraspPlanningAction> as_;
00128
00129
00130
00131 std::string action_name_;
00132
00133
00134 typedef pr2_grasp_adjust::EstimateConfig Config;
00135 dynamic_reconfigure::Server<Config> dyn_srv;
00136 dynamic_reconfigure::Server<Config>::CallbackType dyn_cb;
00137
00138
00139
00140
00141
00142 public:
00146 GraspAdjustActionServer(char* argv[]):
00147 nh_("/"),
00148 nh_pvt_("~"),
00149 output_topic_("/cloud_out"),
00150 as_(nh_, ros::this_node::getName(), boost::bind(&GraspAdjustActionServer::executeCB, this, _1), false),
00151 action_name_(ros::this_node::getName()),
00152 dyn_srv(ros::NodeHandle("~config"))
00153 {
00154
00155 pub_cloud_ = nh_.advertise<sensor_msgs::PointCloud2>(output_topic_, 1);
00156 pub_cloud_roi_ = nh_.advertise<sensor_msgs::PointCloud2>("/roi_snapshot", 1);
00157
00158
00159 pub_marker_ = nh_.advertise<visualization_msgs::Marker>("/markers", 50);
00160 pub_marker_array_ = nh_.advertise<visualization_msgs::MarkerArray>("/markers_array", 50);
00161
00162
00163 pub_im_status_ = nh_.advertise<std_msgs::String>("interactive_manipulation_status", 1);
00164
00165 grasp_adjust_.pub_cloud_ = &pub_cloud_;
00166 grasp_adjust_.pub_cloud_roi_ = &pub_cloud_roi_;
00167 grasp_adjust_.pub_marker_ = &pub_marker_;
00168 grasp_adjust_.pub_marker_array_ = &pub_marker_array_;
00169 grasp_adjust_.listener_ = &tfl_;
00170 grasp_adjust_.broadcaster_ = &tfb_;
00171
00172
00173 dyn_cb = boost::bind( &GraspAdjustActionServer::dynamicCallback, this, _1, _2 );
00174 dyn_srv.setCallback(dyn_cb);
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 as_.start();
00185
00186 ROS_INFO("Grasp adjust action server: Finished constructor!");
00187 }
00188
00189 private:
00190
00191
00192 void executeCB(const object_manipulation_msgs::GraspPlanningGoalConstPtr &goal)
00193 {
00194
00195
00196 if (!as_.isActive())
00197 return;
00198
00199 std_msgs::String status;
00200 status.data = "Running grasp planning action!";
00201 pub_im_status_.publish(status);
00202
00203
00204 object_manipulation_msgs::GraspPlanningResult result;
00205
00206 ROS_INFO("Received action request, cloud with %d points!", goal->target.region.cloud.width * goal->target.region.cloud.height);
00207
00208
00209
00210 bool success = false;
00211
00212 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
00213 pcl::PointCloud<PointT>::Ptr cloudT(new pcl::PointCloud<PointT>());
00214 pcl::PointCloud<PointT>::Ptr cloud_filtered(new pcl::PointCloud<PointT>());
00215 pcl::fromROSMsg(goal->target.region.cloud, *cloud);
00216 cloud->header.stamp = ros::Time(0);
00217 pcl::copyPointCloud(*cloud, *cloudT);
00218 pcl::copyPointCloud(*cloud, *cloud_filtered);
00219 ROS_ASSERT(cloudT->points.size() == cloud_filtered->points.size());
00220
00221
00222
00223
00224
00225
00226
00227 pcl::VoxelGrid<PointT > vox;
00228 vox.setInputCloud (cloudT);
00229 vox.setLeafSize (0.003, 0.003, 0.003);
00230 vox.setFilterFieldName("z");
00231 vox.setFilterLimits(-100, 100);
00232 vox.filter (*cloud_filtered);
00233
00234 ROS_INFO("Down-sampled cloud has %d points!", (int)cloud_filtered->points.size());
00235
00236
00237
00238
00239 pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT> ());
00240 pcl::NormalEstimationOMP<PointT, PointT> ne;
00241 ne.setSearchMethod (tree);
00242 ne.setInputCloud (cloud_filtered);
00243 ne.setKSearch (12);
00244 ne.compute (*cloud_filtered);
00245 ROS_INFO("Cloud in frame %s has %d points, stamp %f!",
00246 cloud_filtered->header.frame_id.c_str(),
00247 (int)cloud_filtered->size(),
00248 cloud_filtered->header.stamp.toSec());
00249
00250 if(pub_cloud_.getNumSubscribers() > 0)
00251 {
00252 sensor_msgs::PointCloud2 cloud_out;
00253 pcl::toROSMsg(*cloud_filtered, cloud_out);
00254 pub_cloud_.publish(cloud_out);
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 std::vector<geometry_msgs::PoseStamped> start_poses;
00264
00265
00266
00267 if(goal->grasps_to_evaluate.empty())
00268 {
00269 geometry_msgs::Vector3Stamped seed_normal;
00270 seed_normal.header.frame_id = "/base_link";
00271 seed_normal.header.stamp = cloud->header.stamp;
00272 seed_normal.vector = object_manipulator::msg::createVector3Msg(0,0,-1);
00273 tfl_.transformVector(cloud_filtered->header.frame_id, seed_normal, seed_normal);
00274
00275 geometry_msgs::Vector3Stamped forward;
00276 forward.header.frame_id = "/base_link";
00277 forward.header.stamp = cloud->header.stamp;
00278 forward.vector = object_manipulator::msg::createVector3Msg(1,0,0);
00279 tfl_.transformVector(cloud_filtered->header.frame_id, forward, forward);
00280
00281 geometry_msgs::Vector3Stamped right;
00282 right.header.frame_id = "/base_link";
00283 right.header.stamp = cloud->header.stamp;
00284 right.vector = object_manipulator::msg::createVector3Msg(0,-1,0);
00285 tfl_.transformVector(cloud_filtered->header.frame_id, right, right);
00286
00287
00288
00289
00290 }
00291 else
00292 {
00293 for(unsigned int i = 0; i < goal->grasps_to_evaluate.size(); i++)
00294 {
00295 start_poses.push_back(
00296 object_manipulator::msg::createPoseStampedMsg( goal->grasps_to_evaluate[i].grasp_pose,
00297 goal->target.reference_frame_id, ros::Time(0)));
00298 }
00299 }
00300
00301 grasp_adjust_.setInputCloud(*cloud_filtered);
00302
00303 std::priority_queue<GripperModel, std::vector<GripperModel>, GripperModel::compareModels> ranked_poses;
00304
00305
00306 for(size_t start_pose_ind=0; start_pose_ind < start_poses.size(); start_pose_ind++)
00307 {
00308 int mode = GLOBAL_SEARCH;
00309 int value = grasp_adjust_.findGrasps(start_poses[start_pose_ind], &ranked_poses, mode, goal->target.reference_frame_id);
00310 success = success || (value == object_manipulation_msgs::GraspPlanningErrorCode::SUCCESS);
00311 }
00312
00313 if (as_.isPreemptRequested() || !ros::ok())
00314 {
00315 ROS_INFO("%s: Preempted", action_name_.c_str());
00316
00317 as_.setPreempted();
00318 success = false;
00319 }
00320 if(success)
00321 {
00322 result.error_code.value = object_manipulation_msgs::GraspPlanningErrorCode::SUCCESS;
00323 }
00324
00325 ROS_INFO("Globally, found %d valid poses!", (int)ranked_poses.size());
00326 while(success && !ranked_poses.empty())
00327 {
00328 GripperModel model = ranked_poses.top();
00329 ranked_poses.pop();
00330 ROS_INFO("Pose with score %.3f", model.score_);
00331 geometry_msgs::PoseStamped ps;
00332 model.toPoseStamped(ps);
00333 model.publishModel(pub_marker_array_, "grasp_adjust_action", 0, ros::Duration(), model.score_*model.score_);
00334
00335 object_manipulation_msgs::Grasp grasp;
00336
00337 grasp.grasp_pose = ps.pose;
00338 grasp.min_approach_distance = 0.05;
00339 grasp.desired_approach_distance = 0.07;
00340 grasp.success_probability = model.score_;
00341
00342 result.grasps.push_back(grasp);
00343
00344 }
00345
00346
00347
00348 if(success)
00349 {
00350 ROS_INFO("%s: Succeeded", action_name_.c_str());
00351 status.data = "Found a grasp!";
00352 pub_im_status_.publish(status);
00353 as_.setSucceeded(result);
00354 }
00355 else
00356 {
00357 ROS_INFO("%s: Failed", action_name_.c_str());
00358 status.data = "Didn't find a grasp; keeping previous pose.";
00359 pub_im_status_.publish(status);
00360 as_.setAborted();
00361 }
00362 }
00363
00369 bool graspAdjustCallback( pr2_grasp_adjust::GraspAdjust::Request &req,
00370 pr2_grasp_adjust::GraspAdjust::Response &res )
00371 {
00372
00373 int mode = req.search_mode;
00374 res.result.value = grasp_adjust_.findGrasps(req.grasp_pose, &(res.grasp_poses), &(res.pose_scores), mode);
00375
00376 ROS_INFO("pr2_grasp_adjust::grasp_adjust returned %d", res.result.value);
00377
00378 return true;
00379 }
00380
00386 void setupGraspPlanning(object_manipulation_msgs::GraspPlanning::Request &req, pcl::PointCloud<PointT> &cloud)
00387 {
00388 pcl::PointCloud<pcl::PointXYZ> cloud_in;
00389
00390 sensor_msgs::PointCloud2 cloud_msg;
00391
00392 sensor_msgs::convertPointCloudToPointCloud2(req.target.cluster, cloud_msg);
00393 ROS_INFO("Cloud_in in frame %s, reference frame %s!", cloud_msg.header.frame_id.c_str(), req.target.reference_frame_id.c_str());
00394
00395 pcl::fromROSMsg(cloud_msg, cloud_in);
00396
00397 prepareCloud(cloud_in, cloud);
00398 }
00399
00400 void prepareCloud(pcl::PointCloud<pcl::PointXYZ> cloud_in, pcl::PointCloud<PointT> &cloud)
00401 {
00402
00403
00404 pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
00405 pcl::NormalEstimation<pcl::PointXYZ, PointT> ne;
00406 ne.setSearchMethod (tree);
00407 ne.setInputCloud (boost::make_shared<pcl::PointCloud<pcl::PointXYZ> >(cloud_in));
00408 ne.setKSearch (15);
00409 ne.compute (cloud);
00410 for(unsigned int i = 0; i < cloud_in.size(); i++){
00411 cloud.points[i].x = cloud_in.points[i].x;
00412 cloud.points[i].y = cloud_in.points[i].y;
00413 cloud.points[i].z = cloud_in.points[i].z;
00414 }
00415 ROS_INFO("Cloud_out in frame %s has %d points, stamp %f!", cloud.header.frame_id.c_str(), (int)cloud.size(), cloud.header.stamp.toSec());
00416
00417 if(pub_cloud_.getNumSubscribers() > 0)
00418 {
00419 sensor_msgs::PointCloud2 cloud_out;
00420 pcl::toROSMsg(cloud, cloud_out);
00421 pub_cloud_.publish(cloud_out);
00422 }
00423
00424 grasp_adjust_.setInputCloud(cloud);
00425 ROS_INFO("Finished preparing cloud!");
00426 }
00427
00428
00429
00433 void dynamicCallback(Config &new_config, uint32_t id)
00434 {
00435
00436 char status[256] = "\0";
00437
00438 switch(id)
00439 {
00440 case(-1):
00441 break;
00442 case(0):
00443 printf("Reconfigure GUI connected to me!\n");
00444 new_config = grasp_adjust_.config_;
00445 break;
00446 default:
00447 ROS_INFO("Dynamic reconfigure did something, variable id %d.", id);
00448 }
00449 grasp_adjust_.config_ = new_config;
00450 new_config.status = status;
00451 }
00452 };
00453
00454
00455
00456
00457 int main (int argc, char* argv[])
00458 {
00459 ros::init(argc, argv, "grasp_adjust_action_server_node");
00460 GraspAdjustActionServer server(argv);
00461 ros::spin();
00462 return (0);
00463 }
00464