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
00037 #include <algorithm>
00038 #include <fstream>
00039
00040 #include <boost/foreach.hpp>
00041 #include <boost/lambda/bind.hpp>
00042 #include <boost/lambda/lambda.hpp>
00043
00044 #include <object_manipulation_msgs/Grasp.h>
00045 #include <object_manipulation_msgs/GraspableObject.h>
00046 #include <household_objects_database_msgs/DatabaseModelPose.h>
00047 #include <geometry_msgs/PoseStamped.h>
00048 #include <tf/transform_datatypes.h>
00049
00050
00051
00052
00053 #include "probabilistic_grasp_planner/probabilistic_planner_tools.h"
00054 #include "probabilistic_grasp_planner/grasp_retriever.h"
00055 #include "probabilistic_grasp_planner/grasp_success_probability_computer.h"
00056 #include "probabilistic_grasp_planner/distribution_evaluator.h"
00057
00058 #include "probabilistic_grasp_planner/probabilistic_grasp_planner.h"
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 namespace probabilistic_grasp_planner {
00079
00080 void ProbabilisticGraspPlanner::plan(const std::string &arm_name,
00081 object_manipulation_msgs::GraspableObject &graspable_object,
00082 std::vector<object_manipulation_msgs::Grasp> &final_grasp_list,
00083 bool visualize_results, bool prune_grasps)
00084 {
00085
00086
00087
00088 bool enable_cluster;
00089 nh_.param("use_cluster",enable_cluster,true);
00090
00091
00092 bool db_only = !enable_cluster;
00093 CompositeProbabilityComputer representation_probability_computer(db_only);
00094
00095
00096
00097 std::vector<ObjectRepresentation> representations;
00098 ROS_INFO("Creating object representations");
00099 populateRepresentationsList(representations, arm_name, graspable_object, enable_cluster);
00100 ROS_INFO("Computing representation probabilities");
00101 representation_probability_computer.computeRepresentationProbabilities(representations);
00102
00103 printRepresentations(representations);
00104
00105
00106
00107
00108
00109
00110
00112 std::vector<GraspWithMetadata> grasps;
00113
00114
00115 if (final_grasp_list.size() > 0)
00116 {
00117 ROS_INFO("Received grasps to test, using those rather than building own list");
00118
00119 appendMetadataToTestGrasps(final_grasp_list, grasps, graspable_object);
00120 }
00121 else
00122 {
00123 BOOST_FOREACH(ObjectRepresentation &representation, representations)
00124 {
00125 if (representation.probability > 0.001)
00126 {
00127 representation.grasp_retriever->getGrasps(grasps);
00128 }
00129 }
00130 }
00131
00132
00133 double recognition_probability(0.0);
00134 double success_probability(0.0);
00135
00136 ROS_INFO("Total grasps %zd",grasps.size());
00137 for (size_t representation_idx=0; representation_idx < representations.size(); representation_idx++)
00138 {
00139 recognition_probability = representations[representation_idx].probability;
00140 std::vector<double> success_probabilities;
00141 ROS_INFO("Analyzing representation %zd", representation_idx);
00142 representations[representation_idx].grasp_success_computer->getProbabilities(grasps, success_probabilities);
00143
00144 for (size_t grasp_idx=0; grasp_idx < grasps.size(); grasp_idx++)
00145 {
00146 success_probability = success_probabilities[grasp_idx];
00147 grasps[grasp_idx].debug_probabilities.push_back
00148 (std::make_pair(representation_idx, std::make_pair(recognition_probability, success_probability)));
00149 grasps[grasp_idx].success_probability += recognition_probability*success_probability;
00150 }
00151 }
00152
00153
00154
00155
00156
00157
00158 BOOST_FOREACH(GraspWithMetadata &grasp, grasps)
00159 {
00160 grasp.grasp_.success_probability = grasp.success_probability;
00161 grasp.success_probability = 0.0;
00162 }
00163
00164
00165
00166
00167
00168 std::sort(grasps.rbegin(), grasps.rend());
00169
00170 ROS_INFO("First round planning returned %zd grasps.", grasps.size());
00171 if (!grasps.empty()) ROS_INFO("Top probability: %f", grasps[0].grasp_.success_probability);
00172 visualizeGrasps(grasps, &debug_preprune_grasp_marker_publisher_, false);
00173
00174 if (prune_grasps)
00175 {
00176
00177 double grasp_probability_threshold;
00178 nh_.param("initial_probability_threshold", grasp_probability_threshold, 0.3);
00179 pruneGraspList(grasps, grasp_probability_threshold);
00180 ROS_INFO(" Pruned to %zd grasps above threshold of %f", grasps.size(), grasp_probability_threshold);
00181 visualizeGrasps(grasps, &debug_precluster_grasp_marker_publisher_, false);
00182
00183
00184 std::vector<GraspWithMetadata> clustered_grasps;
00185 clusterGrasps(grasps, clustered_grasps);
00186 grasps = clustered_grasps;
00187 ROS_INFO(" Clustered to %zd grasps", grasps.size());
00188
00189 int grasps_max;
00190 nh_.param("quantity_threshold", grasps_max, 100);
00191 size_t grasps_max_size = grasps_max;
00192 if (grasps.size() > grasps_max_size)
00193 {
00194 ROS_INFO("Taking top %zd grasps after clustering", grasps_max_size);
00195 grasps.resize(grasps_max_size);
00196 }
00197 visualizeGrasps(grasps, &debug_postprune_grasp_marker_publisher_, false);
00198 }
00199
00200 bool second_pass;
00201 nh_.param("two_pass",second_pass,false);
00202 if (second_pass)
00203 {
00204
00205 ROS_INFO("Reevaluating %zd grasps using expensive computations", grasps.size());
00206
00207 int counter = 0;
00208 BOOST_FOREACH(ObjectRepresentation &representation, representations)
00209 {
00210 ROS_DEBUG(" Evaluating representation %d",counter);
00211 recognition_probability = representation.probability;
00213 BOOST_FOREACH(GraspWithMetadata &grasp, grasps)
00214 {
00215
00216 success_probability = representation.precise_grasp_success_computer->getProbability(grasp);
00217 grasp.success_probability += recognition_probability*success_probability;
00218 }
00219 counter++;
00220 }
00221
00222 BOOST_FOREACH(GraspWithMetadata &grasp, grasps)
00223 {
00224 grasp.grasp_.success_probability = grasp.success_probability;
00225 }
00226
00227 std::sort(grasps.rbegin(), grasps.rend());
00228 ROS_INFO("Second pass done. Top probability: %f", grasps[0].success_probability);
00229 double final_grasp_probability_threshold;
00230 nh_.param("final_probability_threshold",final_grasp_probability_threshold,0.5);
00231 pruneGraspList(grasps, final_grasp_probability_threshold);
00232 ROS_INFO("Pruned to %zd grasps above threshold %f", grasps.size(), final_grasp_probability_threshold);
00233
00234
00235 }
00236
00237 if (visualize_results)
00238 {
00239 if (debug_grasp_marker_publisher_ != NULL) visualizeGrasps(grasps, debug_grasp_marker_publisher_, false);
00240 if (rank_grasp_marker_publisher_ != NULL) visualizeGrasps(grasps, rank_grasp_marker_publisher_, true);
00241 }
00242
00243 visualizeGrasps(grasps, grasp_marker_publisher_, false);
00244
00245
00246 final_grasp_list.clear();
00247 final_grasp_list.reserve(grasps.size());
00248 BOOST_FOREACH(GraspWithMetadata &g, grasps)
00249 {
00250 final_grasp_list.push_back(g.grasp_);
00251 }
00252
00253
00254 }
00255
00256 void ProbabilisticGraspPlanner::pruneGraspList(std::vector<GraspWithMetadata> &grasps, const double threshold)
00257 {
00258 std::vector<GraspWithMetadata>::iterator it=grasps.begin();
00259 int erased_count = 0;
00260 while( it != grasps.end())
00261 {
00262 if (it->grasp_.success_probability < threshold)
00263 {
00264 erased_count++;
00265
00266 it=grasps.erase(it);
00267 }
00268 else{
00269 it++;
00270 }
00271 }
00272
00273 ROS_INFO("Removed %d grasps below threshold",erased_count);
00274 }
00275
00276 void ProbabilisticGraspPlanner::populateRepresentationsList(std::vector<ObjectRepresentation> &representations,
00277 std::string arm_name,
00278 const object_manipulation_msgs::GraspableObject &request_object,
00279 const bool enable_cluster)
00280 {
00281
00282 BOOST_FOREACH(const household_objects_database_msgs::DatabaseModelPose &model_with_score,
00283 request_object.potential_models)
00284 {
00285 representations.push_back( getObjectRepresentationFromDatabaseObject(model_with_score, arm_name) );
00286 }
00287
00288
00289 if (enable_cluster && request_object.cluster.points.size() > 0)
00290 {
00291 representations.push_back(getObjectRepresentationFromCluster(request_object, arm_name));
00292 }
00293 }
00294
00295 ObjectRepresentation ProbabilisticGraspPlanner::getObjectRepresentationFromCluster(
00296 const object_manipulation_msgs::GraspableObject &request_object,
00297 std::string arm_name)
00298 {
00299
00300 ObjectRepresentation representation;
00301
00302
00303 const std::string cluster_planner_service_name = "/plan_point_cluster_grasp";
00304 representation.grasp_retriever.reset(new ClusterPlannerGraspRetriever(nh_, cluster_planner_service_name,
00305 request_object, arm_name));
00306
00307
00308 object_manipulation_msgs::GraspableObject request_object_single_instance;
00309 request_object_single_instance.cluster = request_object.cluster;
00310 representation.object = request_object_single_instance;
00311
00312
00313 int cluster_computer_type;
00314 nh_.param("cluster_computer_type", cluster_computer_type, 1);
00315 std::string cluster_evaluation_service_name;
00316 nh_.param("test_cluster_grasp_srv", cluster_evaluation_service_name, std::string("/evaluate_point_cluster_grasps"));
00317 switch (cluster_computer_type)
00318 {
00319 case 0:
00320 {
00321 ROS_DEBUG("Creating Simple Cluster Computer");
00322 representation.grasp_success_computer.reset(new SimplePointClusterGSPC);
00323 break;
00324 }
00325 case 1:
00326 {
00327 ROS_DEBUG("Creating service caller GSPC");
00328 representation.grasp_success_computer.reset(new GSPCServiceCaller(cluster_evaluation_service_name,
00329 request_object_single_instance));
00330 break;
00331 }
00332 case 2:
00333 {
00334 ROS_DEBUG("Creating Regression Cluster Computer");
00335 shared_ptr<GraspSuccessProbabilityComputer> simple_cluster_computer(new SimplePointClusterGSPC);
00336 std::vector<GraspWithMetadata> grasps;
00337 representation.grasp_retriever->getGrasps(grasps);
00338 double cluster_position_sigma;
00339 double cluster_orientation_concentration;
00340 nh_.param("cluster_regression_position_sigma", cluster_position_sigma, 0.01);
00341 nh_.param("cluster_regression_orientation_concentration", cluster_orientation_concentration, 3.0);
00342 representation.grasp_success_computer.reset(new GSPCWithEstimation(grasps, simple_cluster_computer,
00343 cluster_position_sigma,
00344 cluster_orientation_concentration));
00345 ROS_DEBUG("Regression Params %g %g",cluster_position_sigma, cluster_orientation_concentration);
00346 break;
00347 }
00348 }
00349
00350 representation.precise_grasp_success_computer.reset(new GSPCServiceCaller(cluster_evaluation_service_name,
00351 request_object_single_instance));
00352
00353 return representation;
00354 }
00355
00356 ObjectRepresentation ProbabilisticGraspPlanner::getObjectRepresentationFromDatabaseObject(
00357 const household_objects_database_msgs::DatabaseModelPose &model_with_score,
00358 std::string arm_name)
00359 {
00360
00361 ObjectRepresentation representation;
00362
00363
00364 shared_ptr<DatabaseGraspRetriever> retriever(new DatabaseGraspRetriever(database_, model_with_score,arm_name,true,true));
00365 ROS_INFO("Fetching grasps for model id %d", model_with_score.model_id);
00366 retriever->fetchFromDB();
00367 representation.grasp_retriever = retriever;
00368
00369 double energy_threshold;
00370 nh_.param("db_max_energy_threshold",energy_threshold, 100.0);
00371
00372 std::string graspit_computer_service_name, graspit_computer_robust_service_name;
00373 nh_.param<std::string>("graspit_computer_service_name", graspit_computer_service_name,
00374 "default_graspit_computer_service_name");
00375 nh_.param<std::string>("graspit_computer_robust_service_name", graspit_computer_robust_service_name,
00376 "default_graspit_computer_robust_service_name");
00377
00378
00379 object_manipulation_msgs::GraspableObject request_object_single_instance;
00380 request_object_single_instance.potential_models.push_back(model_with_score);
00381 representation.object = request_object_single_instance;
00382
00383
00384 int db_computer_type;
00385 nh_.param("db_computer_type",db_computer_type,2);
00386 switch (db_computer_type)
00387 {
00388 case 0:
00389 {
00390 ROS_DEBUG("Creating Simple DB Computer");
00391 representation.grasp_success_computer.reset(new SimpleGraspSuccessProbabilityComputer(model_with_score.model_id,
00392 energy_threshold));
00393 break;
00394 }
00395 case 1:
00396 {
00397 ROS_DEBUG("Creating GraspIt DB Computer");
00398 representation.grasp_success_computer.reset( new GSPCServiceCaller(graspit_computer_service_name,
00399 request_object_single_instance) );
00400 break;
00401 }
00402 case 2:
00403 {
00404
00405 shared_ptr<DatabaseGraspRetriever> all_grasps_retriever(new DatabaseGraspRetriever(database_, model_with_score,arm_name,true,false));
00406 all_grasps_retriever->fetchFromDB();
00407
00408 ROS_DEBUG("Creating Regression DB Computer");
00409 shared_ptr<GraspSuccessProbabilityComputer> simple_probability_computer(new
00410 SimpleGraspSuccessProbabilityComputer(model_with_score.model_id, energy_threshold));
00411 std::vector<GraspWithMetadata> grasps;
00412 all_grasps_retriever->getGrasps(grasps);
00413 double db_position_sigma, db_orientation_concentration;
00414 nh_.param("db_regression_position_sigma", db_position_sigma, 0.01);
00415 nh_.param("db_regression_orientation_concentration", db_orientation_concentration, 10.0);
00416 representation.grasp_success_computer.reset(new GSPCWithEstimation(grasps, simple_probability_computer,
00417 db_position_sigma, db_orientation_concentration));
00418 ROS_DEBUG("Regression Params %g %g",db_position_sigma, db_orientation_concentration);
00419 break;
00420 }
00421 case 3:
00422 {
00423 shared_ptr<NormalDistributionEvaluator> distribution_evaluator(new NormalDistributionEvaluator(0.01, 0.174));
00424 shared_ptr<GraspSuccessProbabilityComputer> simple_probability_computer
00425 (new SimpleGraspSuccessProbabilityComputer( model_with_score.model_id, energy_threshold));
00426 representation.grasp_success_computer.reset
00427 (new PositionRobustGraspSuccessProbabilityComputer( database_, model_with_score, simple_probability_computer,
00428 distribution_evaluator, arm_name));
00429 break;
00430 }
00431 case 4:
00432 {
00433 ROS_DEBUG("Creating Robust GraspIt DB Computer");
00434 representation.grasp_success_computer.reset( new GSPCServiceCaller(graspit_computer_robust_service_name,
00435 request_object_single_instance) );
00436 break;
00437 }
00438 }
00439
00440 representation.precise_grasp_success_computer.reset(new GSPCServiceCaller(graspit_computer_robust_service_name,
00441 request_object_single_instance));
00442
00443 return representation;
00444 }
00445
00446 void ProbabilisticGraspPlanner::visualizeGrasps(const std::vector<GraspWithMetadata> &grasps,
00447 object_manipulator::GraspMarkerPublisher *grasp_publisher, bool color_by_rank)
00448 {
00449 grasp_publisher->clearAllMarkers();
00450 size_t sz = grasps.size();
00451 if (sz == 0)
00452 {
00453 return;
00454 }
00455 double best_score = grasps[0].grasp_.success_probability;
00456 for (size_t i=0; i < sz; i++) {
00457 const GraspWithMetadata *grasp = &grasps[i];
00458 std::string ns_append = boost::lexical_cast<std::string>(grasp->model_id_);
00459 grasp_publisher->setNamespaceSuffix(ns_append);
00460
00461
00462
00463 tf::Pose grasp_pose_tf;
00464 tf::poseMsgToTF(grasp->grasp_.grasp_pose, grasp_pose_tf);
00465
00466 tf::Stamped<tf::Pose> grasp_in_world(grasp_pose_tf, grasp->object_pose_.stamp_, grasp->object_pose_.frame_id_);
00467
00468 geometry_msgs::PoseStamped grasp_in_world_msg;
00469 tf::poseStampedTFToMsg(grasp_in_world, grasp_in_world_msg);
00470
00471 unsigned int id = grasp_publisher->addGraspMarker(grasp_in_world_msg);
00472
00473 float colorval;
00474 if (color_by_rank)
00475 {
00476 colorval = i/(1.0*sz);
00477 }
00478 else {
00479 colorval = 1.0 - grasp->grasp_.success_probability / (1.0*best_score);
00480 }
00481 grasp_publisher->colorGraspMarker(id, colorval, 1-colorval, 0.0);
00482 }
00483 }
00484
00485 void ProbabilisticGraspPlanner::printRepresentations(const std::vector<ObjectRepresentation> &representations)
00486 {
00487 ROS_INFO("Object representations:");
00488 BOOST_FOREACH(const ObjectRepresentation &representation, representations)
00489 {
00490 ROS_INFO(" Probability: %f", representation.probability);
00491 if (!representation.object.potential_models.empty())
00492 {
00493 ROS_INFO(" Database object with id %d", representation.object.potential_models[0].model_id);
00494 }
00495 else
00496 {
00497 ROS_INFO(" Cluster with %zu points", representation.object.cluster.points.size());
00498 }
00499 }
00500 }
00501
00502 void ProbabilisticGraspPlanner::printGrasps(const std::vector<GraspWithMetadata> &grasps)
00503 {
00504 BOOST_FOREACH(const GraspWithMetadata &grasp, grasps)
00505 {
00506 ROS_DEBUG_STREAM("Probability: "<< grasp.grasp_.success_probability << " " << grasp.grasp_id_ << " Loc " <<
00507 grasp.grasp_.grasp_pose.position.x << " " <<
00508 grasp.grasp_.grasp_pose.position.y << " " <<
00509 grasp.grasp_.grasp_pose.position.z << " " <<
00510 grasp.grasp_.grasp_pose.orientation.x << " " <<
00511 grasp.grasp_.grasp_pose.orientation.y << " " <<
00512 grasp.grasp_.grasp_pose.orientation.z << " " <<
00513 grasp.grasp_.grasp_pose.orientation.w);
00514 ROS_DEBUG_STREAM("Contributions:");
00515 for (size_t i=0; i < grasp.debug_probabilities.size(); ++i)
00516 {
00517 ROS_DEBUG("%d: %g %g",grasp.debug_probabilities[i].first, grasp.debug_probabilities[i].second.first,
00518 grasp.debug_probabilities[i].second.second);
00519 }
00520 }
00521 }
00522
00523 void
00524 ProbabilisticGraspPlanner::appendMetadataToTestGrasps(std::vector<object_manipulation_msgs::Grasp> &input_list,
00525 std::vector<GraspWithMetadata> &output_list,
00526 const object_manipulation_msgs::GraspableObject &graspable_object)
00527 {
00528
00529 output_list.reserve(output_list.size()+input_list.size());
00530
00531 ROS_INFO("Got %zd grasps to test",input_list.size());
00532 BOOST_FOREACH(object_manipulation_msgs::Grasp &grasp, input_list)
00533 {
00534 GraspWithMetadata grasp_with_metadata;
00535 grasp_with_metadata.grasp_ = grasp;
00536
00537 grasp_with_metadata.model_id_ = -1;
00538 grasp_with_metadata.grasp_id_ = -1;
00539
00540 grasp_with_metadata.object_pose_.setIdentity();
00541 grasp_with_metadata.object_pose_.frame_id_ = graspable_object.reference_frame_id;
00542 grasp_with_metadata.object_pose_.stamp_ = ros::Time(0);
00543
00544 tf::Pose grasp_in_base_frame;
00545 tf::poseMsgToTF(grasp.grasp_pose, grasp_in_base_frame);
00546 double wrist_to_tool_point_offset_ = 0.13;
00547 tf::Pose grasp_to_tool_point(tf::Matrix3x3::getIdentity(),tf::Vector3(wrist_to_tool_point_offset_,0,0));
00549 grasp_with_metadata.tool_point_pose_ = tf::Stamped<tf::Pose>(
00550 grasp_in_base_frame * grasp_to_tool_point, grasp_with_metadata.object_pose_.stamp_,
00551 grasp_with_metadata.object_pose_.frame_id_);
00552
00553 output_list.push_back(grasp_with_metadata);
00554 }
00555 ROS_DEBUG("Created %zd grasps",output_list.size());
00556
00557 }
00558
00559 void ProbabilisticGraspPlanner::clusterGrasps(std::vector<GraspWithMetadata> &input_list,
00560 std::vector<GraspWithMetadata> &cluster_rep_list)
00561 {
00562 ROS_INFO("Clustering %zd grasps",input_list.size());
00563
00564 double clustering_cart_distance_threshold = 0.01;
00565 double clustering_angle_distance_threshold = 0.266;
00566
00567 int clusters = 0;
00568 while (!input_list.empty())
00569 {
00570 GraspWithMetadata *repGrasp = &input_list.front();
00571 repGrasp->grasp_.cluster_rep = true;
00572 cluster_rep_list.push_back(*repGrasp);
00573 input_list.erase(input_list.begin());
00574 ++clusters;
00575
00576 int cloud=0;
00577 std::vector<GraspWithMetadata>::iterator it=input_list.begin();
00578 while (it != input_list.end())
00579 {
00580 double cart_distance, angle_distance;
00581 cluster_rep_list.back().getDistance(*it,cart_distance,angle_distance);
00582 if (cart_distance < clustering_cart_distance_threshold &&
00583 angle_distance < clustering_angle_distance_threshold)
00584 {
00585 ++cloud;
00590
00591 it = input_list.erase(it);
00592 }
00593 else {
00594 ++it;
00595 }
00596 }
00597 ROS_DEBUG("Grouped cluster of size %d",cloud);
00598 }
00599 ROS_INFO("Selected %d cluster rep grasps",clusters);
00600 }
00601
00602 }