manipulation.cpp
Go to the documentation of this file.
00001 #include <ros/ros.h>
00002 
00003 #include <actionlib/client/simple_action_client.h>
00004 #include <tabletop_object_detector/TabletopDetection.h>
00005 #include <tabletop_collision_map_processing/TabletopCollisionMapProcessing.h>
00006 #include <object_manipulation_msgs/PickupAction.h>
00007 #include <object_manipulation_msgs/PlaceAction.h>
00008 
00009 //for pointing the head
00010 #include <pr2_controllers_msgs/PointHeadAction.h>
00011 
00012 //for convenience, so we can point the head at the table
00013 //copied from the following tutorial:
00014 // http://www.ros.org/wiki/pr2_controllers/Tutorials/Moving%20the%20Head
00015 class RobotHead
00016 {
00017 private:
00018   actionlib::SimpleActionClient<pr2_controllers_msgs::PointHeadAction>* point_head_client_;
00019 
00020 public:
00022   RobotHead()
00023   {
00024     //Initialize the client for the Action interface to the head controller
00025     point_head_client_ = new actionlib::SimpleActionClient<pr2_controllers_msgs::PointHeadAction>
00026       ("/head_traj_controller/point_head_action", true);
00027 
00028     //wait for head controller action server to come up 
00029     while(!point_head_client_->waitForServer(ros::Duration(5.0))){
00030       ROS_INFO("Waiting for the point_head_action server to come up");
00031     }
00032   }
00033 
00034   ~RobotHead()
00035   {
00036     delete point_head_client_;
00037   }
00038 
00040   void lookAt(std::string frame_id, double x, double y, double z)
00041   {
00042     //the goal message we will be sending
00043     pr2_controllers_msgs::PointHeadGoal goal;
00044 
00045     //the target point, expressed in the requested frame
00046     geometry_msgs::PointStamped point;
00047     point.header.frame_id = frame_id;
00048     point.point.x = x; point.point.y = y; point.point.z = z;
00049     goal.target = point;
00050 
00051     //we are pointing the high-def camera frame 
00052     //(pointing_axis defaults to X-axis)
00053     goal.pointing_frame = "high_def_frame";
00054 
00055     //take at least 0.5 seconds to get there
00056     goal.min_duration = ros::Duration(0.5);
00057 
00058     //and go no faster than 1 rad/s
00059     goal.max_velocity = 1.0;
00060 
00061     //send the goal
00062     point_head_client_->sendGoal(goal);
00063 
00064     //wait for it to get there (abort after 2 secs to prevent getting stuck)
00065     point_head_client_->waitForResult(ros::Duration(2));
00066   }
00067 };
00068 
00069 int main(int argc, char **argv)
00070 {
00071   //initialize the ROS node
00072   ros::init(argc, argv, "pick_and_place_app");
00073   ros::NodeHandle nh;
00074 
00075   //set service and action names
00076   const std::string OBJECT_DETECTION_SERVICE_NAME = 
00077     "/object_detection";
00078   const std::string COLLISION_PROCESSING_SERVICE_NAME = 
00079     "/tabletop_collision_map_processing/tabletop_collision_map_processing";
00080   const std::string PICKUP_ACTION_NAME = 
00081     "/object_manipulator/object_manipulator_pickup";
00082   const std::string PLACE_ACTION_NAME = 
00083     "/object_manipulator/object_manipulator_place";
00084 
00085   //create service and action clients
00086   ros::ServiceClient object_detection_srv;
00087   ros::ServiceClient collision_processing_srv;
00088   actionlib::SimpleActionClient<object_manipulation_msgs::PickupAction> 
00089     pickup_client(PICKUP_ACTION_NAME, true);
00090   actionlib::SimpleActionClient<object_manipulation_msgs::PlaceAction> 
00091     place_client(PLACE_ACTION_NAME, true);
00092 
00093   //wait for detection client
00094   while ( !ros::service::waitForService(OBJECT_DETECTION_SERVICE_NAME, 
00095                                         ros::Duration(2.0)) && nh.ok() ) 
00096   {
00097     ROS_INFO("Waiting for object detection service to come up");
00098   }
00099   if (!nh.ok()) exit(0);
00100   object_detection_srv = 
00101     nh.serviceClient<tabletop_object_detector::TabletopDetection>
00102     (OBJECT_DETECTION_SERVICE_NAME, true);
00103 
00104   //wait for collision map processing client
00105   while ( !ros::service::waitForService(COLLISION_PROCESSING_SERVICE_NAME, 
00106                                         ros::Duration(2.0)) && nh.ok() ) 
00107   {
00108     ROS_INFO("Waiting for collision processing service to come up");
00109   }
00110   if (!nh.ok()) exit(0);
00111   collision_processing_srv = 
00112     nh.serviceClient
00113     <tabletop_collision_map_processing::TabletopCollisionMapProcessing>
00114     (COLLISION_PROCESSING_SERVICE_NAME, true);
00115 
00116   //wait for pickup client
00117   while(!pickup_client.waitForServer(ros::Duration(2.0)) && nh.ok())
00118   {
00119     ROS_INFO_STREAM("Waiting for action client " << PICKUP_ACTION_NAME);
00120   }
00121   if (!nh.ok()) exit(0);  
00122 
00123   //wait for place client
00124   while(!place_client.waitForServer(ros::Duration(2.0)) && nh.ok())
00125   {
00126     ROS_INFO_STREAM("Waiting for action client " << PLACE_ACTION_NAME);
00127   }
00128   if (!nh.ok()) exit(0);    
00129 
00130   //look at the table
00131   RobotHead head;
00132   head.lookAt("base_link", 1.0, 0.0, 0.5);
00133 
00134   //call the tabletop detection
00135   ROS_INFO("Calling tabletop detector");
00136   tabletop_object_detector::TabletopDetection detection_call;
00137   //we want recognized database objects returned
00138   //set this to false if you are using the pipeline without the database
00139   detection_call.request.return_clusters = true;
00140   //we want the individual object point clouds returned as well
00141   detection_call.request.return_models = true;
00142   detection_call.request.num_models = 1;
00143   if (!object_detection_srv.call(detection_call))
00144   {
00145     ROS_ERROR("Tabletop detection service failed");
00146     return -1;
00147   }
00148   if (detection_call.response.detection.result != 
00149       detection_call.response.detection.SUCCESS)
00150   {
00151     ROS_ERROR("Tabletop detection returned error code %d", 
00152               detection_call.response.detection.result);
00153     return -1;
00154   }
00155   if (detection_call.response.detection.clusters.empty() && 
00156       detection_call.response.detection.models.empty() )
00157   {
00158     ROS_ERROR("The tabletop detector detected the table, "
00159               "but found no objects");
00160     return -1;
00161   }
00162 
00163 
00164   //call collision map processing
00165   ROS_INFO("Calling collision map processing");
00166   tabletop_collision_map_processing::TabletopCollisionMapProcessing 
00167     processing_call;
00168   //pass the result of the tabletop detection 
00169   processing_call.request.detection_result = 
00170     detection_call.response.detection;
00171   //ask for the existing map and collision models to be reset
00172   processing_call.request.reset_collision_models = true;
00173   processing_call.request.reset_attached_models = true;
00174   //ask for the results to be returned in base link frame
00175   processing_call.request.desired_frame = "base_link";
00176   if (!collision_processing_srv.call(processing_call))
00177   {
00178     ROS_ERROR("Collision map processing service failed");
00179     return -1;
00180   }
00181   //the collision map processor returns instances of graspable objects
00182   if (processing_call.response.graspable_objects.empty())
00183   {
00184     ROS_ERROR("Collision map processing returned no graspable objects");
00185     return -1;
00186   }
00187 
00188 
00189 
00190   //call object pickup
00191   ROS_INFO("Calling the pickup action");
00192   object_manipulation_msgs::PickupGoal pickup_goal;
00193   //pass one of the graspable objects returned 
00194   //by the collision map processor
00195   pickup_goal.target = processing_call.response.graspable_objects.at(0);
00196   //pass the name that the object has in the collision environment
00197   //this name was also returned by the collision map processor
00198   pickup_goal.collision_object_name = 
00199     processing_call.response.collision_object_names.at(0);
00200   //pass the collision name of the table, also returned by the collision 
00201   //map processor
00202   pickup_goal.collision_support_surface_name = 
00203     processing_call.response.collision_support_surface_name;
00204   //pick up the object with the right arm
00205   pickup_goal.arm_name = "right_arm";
00206   //we will be lifting the object along the "vertical" direction
00207   //which is along the z axis in the base_link frame
00208   geometry_msgs::Vector3Stamped direction;
00209   direction.header.stamp = ros::Time::now();
00210   direction.header.frame_id = "base_link";
00211   direction.vector.x = 0;
00212   direction.vector.y = 0;
00213   direction.vector.z = 1;
00214   pickup_goal.lift.direction = direction;
00215   //request a vertical lift of 10cm after grasping the object
00216   pickup_goal.lift.desired_distance = 0.1;
00217   pickup_goal.lift.min_distance = 0.05;
00218   //do not use tactile-based grasping or tactile-based lift
00219   pickup_goal.use_reactive_lift = false;
00220   pickup_goal.use_reactive_execution = false;
00221   //send the goal
00222   pickup_client.sendGoal(pickup_goal);
00223   while (!pickup_client.waitForResult(ros::Duration(10.0)))
00224   {
00225     ROS_INFO("Waiting for the pickup action...");
00226   }
00227   object_manipulation_msgs::PickupResult pickup_result = 
00228     *(pickup_client.getResult());
00229   if (pickup_client.getState() != actionlib::SimpleClientGoalState::SUCCEEDED)
00230   {
00231     ROS_ERROR("The pickup action has failed with result code %d", 
00232               pickup_result.manipulation_result.value);
00233     return -1;
00234   }
00235 
00236 
00237   //create a place location, offset by 10 cm from the pickup location
00238   geometry_msgs::PoseStamped place_location;
00239   place_location.header.frame_id = processing_call.response.graspable_objects.at(0).reference_frame_id; 
00240   //identity pose
00241   place_location.pose.orientation.w = 1;  
00242   place_location.header.stamp = ros::Time::now();
00243   place_location.pose.position.x += 0.1;
00244 
00245 
00246 
00247   //put the object down
00248   ROS_INFO("Calling the place action");
00249   object_manipulation_msgs::PlaceGoal place_goal;
00250   //place at the prepared location
00251   place_goal.place_locations.push_back(place_location);
00252   //the collision names of both the objects and the table
00253   //same as in the pickup action
00254   place_goal.collision_object_name = 
00255     processing_call.response.collision_object_names.at(0); 
00256   place_goal.collision_support_surface_name = 
00257     processing_call.response.collision_support_surface_name;
00258   //information about which grasp was executed on the object, 
00259   //returned by the pickup action
00260   place_goal.grasp = pickup_result.grasp;
00261   //use the right rm to place
00262   place_goal.arm_name = "right_arm";
00263   //padding used when determining if the requested place location
00264   //would bring the object in collision with the environment
00265   place_goal.place_padding = 0.02;
00266   //how much the gripper should retreat after placing the object
00267   place_goal.desired_retreat_distance = 0.1;
00268   place_goal.min_retreat_distance = 0.05;
00269   //we will be putting down the object along the "vertical" direction
00270   //which is along the z axis in the base_link frame
00271   direction.header.stamp = ros::Time::now();
00272   direction.header.frame_id = "base_link";
00273   direction.vector.x = 0;
00274   direction.vector.y = 0;
00275   direction.vector.z = -1;
00276   place_goal.approach.direction = direction;
00277   //request a vertical put down motion of 10cm before placing the object 
00278   place_goal.approach.desired_distance = 0.1;
00279   place_goal.approach.min_distance = 0.05;
00280   //we are not using tactile based placing
00281   place_goal.use_reactive_place = false;
00282   //send the goal
00283   place_client.sendGoal(place_goal);
00284   while (!place_client.waitForResult(ros::Duration(10.0)))
00285   {
00286     ROS_INFO("Waiting for the place action...");
00287   }
00288   object_manipulation_msgs::PlaceResult place_result = 
00289     *(place_client.getResult());
00290   if (place_client.getState() != 
00291       actionlib::SimpleClientGoalState::SUCCEEDED)
00292   {
00293     ROS_ERROR("Place failed with error code %d", 
00294               place_result.manipulation_result.value);
00295     return -1;
00296   }
00297 
00298   //success!
00299   ROS_INFO("Success! Object moved.");
00300   return 0;
00301 }


pr2_pick_and_place_tutorial
Author(s): Matei Ciocarlie
autogenerated on Fri Jan 3 2014 12:10:35