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 #include "pcl/io/pcd_io.h"
00047 #include "pcl/point_types.h"
00048
00049 #include <sensor_msgs/point_cloud_conversion.h>
00050
00051 #include <visualization_msgs/Marker.h>
00052 #include <visualization_msgs/MarkerArray.h>
00053
00054 #include <object_manipulation_msgs/GraspPlanning.h>
00055 #include <object_manipulation_msgs/ManipulationResult.h>
00056 #include <object_manipulation_msgs/FindClusterBoundingBox.h>
00057 #include <object_manipulator/tools/service_action_wrappers.h>
00058
00059 #include <dynamic_reconfigure/server.h>
00060 #include "pr2_grasp_adjust/EstimateConfig.h"
00061 #include "pr2_grasp_adjust/GraspAdjustAction.h"
00062
00063 #include <actionlib/server/simple_action_server.h>
00064
00065
00066
00067 #include <iostream>
00068 #include <fstream>
00069 #include <queue>
00070
00071 #include "gripper_model.h"
00072 #include "helpers.h"
00073 #include "grasp_adjust.h"
00074
00075 #include <pcl/ModelCoefficients.h>
00076 #include <pcl/features/normal_3d.h>
00077 #include <pcl/filters/extract_indices.h>
00078 #include <pcl/filters/passthrough.h>
00079 #include "pcl/filters/voxel_grid.h"
00080 #include <pcl/sample_consensus/method_types.h>
00081 #include <pcl/sample_consensus/model_types.h>
00082 #include <pcl/segmentation/sac_segmentation.h>
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 typedef pcl::PointXYZRGBNormal PointT;
00095
00096 const int GLOBAL_SEARCH = pr2_grasp_adjust::Estimate_global_search;
00097 const int LOCAL_SEARCH = pr2_grasp_adjust::Estimate_local_search;
00098 const int SINGLE_POSE = pr2_grasp_adjust::Estimate_single_pose;
00099
00100
00101 std::ofstream outputFile;
00102
00103 class GraspAdjustActionServer{
00104
00105 ros::NodeHandle nh_, nh_pvt_;
00106 ros::Subscriber sub_as_;
00107 ros::Publisher pub_cloud_, pub_cloud_roi_, pub_marker_, pub_marker_array_;
00108
00109 std::string input_topic_;
00110 std::string output_topic_;
00111
00112 tf::TransformListener listener_;
00113 tf::TransformBroadcaster broadcaster_;
00114
00115 sensor_msgs::PointCloud2 cloud_msg_;
00116 geometry_msgs::PoseStamped seed_ps_;
00117
00118 ros::Time now_;
00119
00120 GraspAdjust grasp_adjust_;
00121
00122 actionlib::SimpleActionServer<pr2_grasp_adjust::GraspAdjustAction> as_;
00123
00124
00125
00126 std::string action_name_;
00127
00128
00129
00130
00131
00132 typedef pr2_grasp_adjust::EstimateConfig Config;
00133 dynamic_reconfigure::Server<Config> dyn_srv;
00134 dynamic_reconfigure::Server<Config>::CallbackType dyn_cb;
00135
00136
00137
00138
00139 public:
00143 GraspAdjustActionServer(char* argv[]):
00144 nh_("/"),
00145 nh_pvt_("~"),
00146 output_topic_("/cloud_out"),
00147 as_(nh_, ros::this_node::getName(), boost::bind(&GraspAdjustActionServer::executeCB, this, _1), false),
00148 action_name_(ros::this_node::getName()),
00149 dyn_srv(ros::NodeHandle("~config"))
00150 {
00151
00152 pub_cloud_ = nh_.advertise<sensor_msgs::PointCloud2>(output_topic_, 1);
00153 pub_cloud_roi_ = nh_.advertise<sensor_msgs::PointCloud2>("/roi_snapshot", 1);
00154
00155
00156 pub_marker_ = nh_.advertise<visualization_msgs::Marker>("/markers", 20);
00157 pub_marker_array_ = nh_.advertise<visualization_msgs::MarkerArray>("/markers_array", 20);
00158
00159 grasp_adjust_.pub_cloud_ = &pub_cloud_;
00160 grasp_adjust_.pub_cloud_roi_ = &pub_cloud_roi_;
00161 grasp_adjust_.pub_marker_ = &pub_marker_;
00162 grasp_adjust_.pub_marker_array_ = &pub_marker_array_;
00163 grasp_adjust_.listener_ = &listener_;
00164 grasp_adjust_.broadcaster_ = &broadcaster_;
00165
00166
00167 dyn_cb = boost::bind( &GraspAdjustActionServer::dynamicCallback, this, _1, _2 );
00168 dyn_srv.setCallback(dyn_cb);
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 as_.start();
00179
00180 ROS_INFO("Grasp adjust action server: Finished constructor!");
00181 }
00182
00183 private:
00184
00185 void executeCB(const pr2_grasp_adjust::GraspAdjustGoalConstPtr &goal)
00186 {
00187
00188 if (!as_.isActive())
00189 return;
00190
00191 pr2_grasp_adjust::GraspAdjustResult result;
00192
00193 ROS_INFO("Received action request!");
00194 bool success = false;
00195
00196 pcl::PointCloud<pcl::PointXYZ> cloudXYZ;
00197 pcl::fromROSMsg(goal->cloud, cloudXYZ);
00198
00199 pcl::PointCloud<PointT>::Ptr cloudT(new pcl::PointCloud<PointT>());
00200 prepareCloud(cloudXYZ, *cloudT);
00201
00202 PointT seed_point = cloudT->points[goal->seed_index];
00203
00204 tf::Vector3 seed_normal(seed_point.normal[0], seed_point.normal[1], seed_point.normal[2]);
00205 seed_normal *= -1.0;
00206
00207
00208 std::vector<geometry_msgs::PoseStamped> start_poses;
00209 double start_dist = .01;
00210
00211
00212 start_poses.push_back(generateAlignedPose(goal->pose_stamped, seed_normal, tf::Vector3(1, 0, 0)));
00213 start_poses.push_back(generateAlignedPose(goal->pose_stamped, seed_normal, tf::Vector3(0, 1, 0)));
00214
00215 pcl::PointCloud<PointT>::Ptr cloud_filtered(new pcl::PointCloud<PointT>());
00216
00217 pcl::VoxelGrid<PointT > sor;
00218 sor.setInputCloud (cloudT);
00219 sor.setLeafSize (0.003, 0.003, 0.003);
00220 sor.filter (*cloud_filtered);
00221 grasp_adjust_.setInputCloud(*cloud_filtered);
00222
00223 std::priority_queue<GripperModel, std::vector<GripperModel>, GripperModel::compareModels> ranked_poses;
00224
00225
00226 for(size_t start_pose_ind=0; start_pose_ind < start_poses.size(); start_pose_ind++)
00227 {
00228 int mode = GLOBAL_SEARCH;
00229 int value = grasp_adjust_.findGrasps(start_poses[start_pose_ind], &ranked_poses, mode, cloudT->header.frame_id);
00230 success = success || (value == object_manipulation_msgs::ManipulationResult::SUCCESS);
00231 }
00232
00233 if (as_.isPreemptRequested() || !ros::ok())
00234 {
00235 ROS_INFO("%s: Preempted", action_name_.c_str());
00236
00237 as_.setPreempted();
00238 success = false;
00239 }
00240
00241 ROS_INFO("Globally, found %d valid poses!", (int)ranked_poses.size());
00242 while(success && !ranked_poses.empty())
00243 {
00244 GripperModel model = ranked_poses.top();
00245 ranked_poses.pop();
00246 ROS_INFO("Pose with score %.3f", model.score_);
00247 geometry_msgs::PoseStamped ps;
00248 model.toPoseStamped(ps);
00249 model.publishModel(pub_marker_array_, "grasp_adjust_action", 0, ros::Duration(), model.score_*model.score_);
00250
00251 result.grasp_poses.push_back(ps);
00252 result.gripper_openings.push_back(1);
00253 result.grasp_scores.push_back(model.score_);
00254
00255 }
00256
00257 if(success)
00258 {
00259 ROS_INFO("%s: Succeeded", action_name_.c_str());
00260 as_.setSucceeded(result);
00261 }
00262 else
00263 {
00264 ROS_INFO("%s: Failed", action_name_.c_str());
00265 as_.setAborted();
00266 }
00267 }
00268
00274 bool graspAdjustCallback( pr2_grasp_adjust::GraspAdjust::Request &req,
00275 pr2_grasp_adjust::GraspAdjust::Response &res )
00276 {
00277
00278 int mode = req.search_mode;
00279 res.result.value = grasp_adjust_.findGrasps(req.grasp_pose, &(res.grasp_poses), &(res.pose_scores), mode);
00280
00281 ROS_INFO("pr2_grasp_adjust::grasp_adjust returned %d", res.result.value);
00282
00283 return true;
00284 }
00285
00291 void setupGraspPlanning(object_manipulation_msgs::GraspPlanning::Request &req, pcl::PointCloud<PointT> &cloud)
00292 {
00293 pcl::PointCloud<pcl::PointXYZ> cloud_in;
00294
00295 sensor_msgs::PointCloud2 cloud_msg;
00296
00297 sensor_msgs::convertPointCloudToPointCloud2(req.target.cluster, cloud_msg);
00298 ROS_INFO("Cloud_in in frame %s, reference frame %s!", cloud_msg.header.frame_id.c_str(), req.target.reference_frame_id.c_str());
00299
00300 pcl::fromROSMsg(cloud_msg, cloud_in);
00301
00302 prepareCloud(cloud_in, cloud);
00303 }
00304
00305 void prepareCloud(pcl::PointCloud<pcl::PointXYZ> cloud_in, pcl::PointCloud<PointT> &cloud)
00306 {
00307
00308
00309 pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr tree (new pcl::KdTreeFLANN<pcl::PointXYZ> ());
00310 pcl::NormalEstimation<pcl::PointXYZ, PointT> ne;
00311 ne.setSearchMethod (tree);
00312 ne.setInputCloud (boost::make_shared<pcl::PointCloud<pcl::PointXYZ> >(cloud_in));
00313 ne.setKSearch (15);
00314 ne.compute (cloud);
00315 for(unsigned int i = 0; i < cloud_in.size(); i++){
00316 cloud.points[i].x = cloud_in.points[i].x;
00317 cloud.points[i].y = cloud_in.points[i].y;
00318 cloud.points[i].z = cloud_in.points[i].z;
00319 }
00320 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());
00321
00322 if(pub_cloud_.getNumSubscribers() > 0)
00323 {
00324 sensor_msgs::PointCloud2 cloud_out;
00325 pcl::toROSMsg(cloud, cloud_out);
00326 pub_cloud_.publish(cloud_out);
00327 }
00328
00329 grasp_adjust_.setInputCloud(cloud);
00330 ROS_INFO("Finished preparing cloud!");
00331 }
00332
00333
00334
00338 void dynamicCallback(Config &new_config, uint32_t id)
00339 {
00340
00341 char status[256] = "\0";
00342
00343 switch(id)
00344 {
00345 case(-1):
00346 break;
00347 case(0):
00348 printf("Reconfigure GUI connected to me!\n");
00349 new_config = grasp_adjust_.config_;
00350 break;
00351 default:
00352 ROS_INFO("Dynamic reconfigure did something, variable id %d.", id);
00353 }
00354 grasp_adjust_.config_ = new_config;
00355 new_config.status = status;
00356 }
00357 };
00358
00359
00360
00361
00362 int main (int argc, char* argv[])
00363 {
00364 ros::init(argc, argv, "grasp_adjust_action_server_node");
00365 GraspAdjustActionServer server(argv);
00366 ros::spin();
00367 return (0);
00368 }
00369