Go to the documentation of this file.00001 #include <ros/ros.h>
00002
00003 #include <tf/transform_listener.h>
00004 #include <actionlib/client/simple_action_client.h>
00005 #include <tabletop_object_detector/TabletopDetection.h>
00006 #include <tabletop_collision_map_processing/TabletopCollisionMapProcessing.h>
00007 #include <object_manipulation_msgs/PickupAction.h>
00008 #include <object_manipulation_msgs/PlaceAction.h>
00009 #include <object_manipulation_msgs/ManipulationResult.h>
00010 #include <arm_navigation_msgs/MoveArmAction.h>
00011 #include <std_srvs/Empty.h>
00012
00013 static const double TABLE_HEIGHT = 0.28;
00014
00015 tf::TransformListener *tf_listener;
00016
00017
00018 static const size_t NUM_JOINTS = 5;
00019
00020 bool move_to_joint_goal(std::vector<arm_navigation_msgs::JointConstraint> joint_constraints,
00021 actionlib::SimpleActionClient<arm_navigation_msgs::MoveArmAction> &move_arm) {
00022
00023 arm_navigation_msgs::MoveArmGoal goal;
00024
00025 goal.motion_plan_request.group_name = "arm";
00026 goal.motion_plan_request.num_planning_attempts = 1;
00027 goal.motion_plan_request.allowed_planning_time = ros::Duration(5.0);
00028
00029 goal.motion_plan_request.planner_id = std::string("");
00030 goal.planner_service_name = std::string("ompl_planning/plan_kinematic_path");
00031
00032 goal.motion_plan_request.goal_constraints.joint_constraints = joint_constraints;
00033
00034
00035 bool finished_within_time = false;
00036 move_arm.sendGoal(goal);
00037 finished_within_time = move_arm.waitForResult(ros::Duration(40.0));
00038 if (!finished_within_time)
00039 {
00040 move_arm.cancelGoal();
00041 ROS_INFO("Timed out achieving goal!");
00042 return false;
00043 }
00044 else
00045 {
00046 actionlib::SimpleClientGoalState state = move_arm.getState();
00047 bool success = (state == actionlib::SimpleClientGoalState::SUCCEEDED);
00048 if (success)
00049 ROS_INFO("Action finished: %s",state.toString().c_str());
00050 else
00051 ROS_INFO("Action failed: %s",state.toString().c_str());
00052
00053 return success;
00054 }
00055 }
00056
00057
00061 bool nearest_object(std::vector<object_manipulation_msgs::GraspableObject>& objects, geometry_msgs::PointStamped& reference_point, int& object_ind)
00062 {
00063 geometry_msgs::PointStamped point;
00064
00065
00066 tf_listener->transformPoint("/base_link", reference_point, point);
00067
00068
00069 double nearest_dist = 1e6;
00070 int nearest_object_ind = -1;
00071
00072 for (size_t i = 0; i < objects.size(); ++i)
00073 {
00074 sensor_msgs::PointCloud cloud;
00075 tf_listener->transformPointCloud("/base_link", objects[i].cluster, cloud);
00076
00077
00078 float x = 0.0, y = 0.0, z = 0.0;
00079 for (size_t j = 0; j < cloud.points.size(); ++j)
00080 {
00081 x += cloud.points[j].x;
00082 y += cloud.points[j].y;
00083 z += cloud.points[j].z;
00084 }
00085 x /= cloud.points.size();
00086 y /= cloud.points.size();
00087 z /= cloud.points.size();
00088
00089 double dist = sqrt(pow(x - point.point.x, 2.0) + pow(y - point.point.y, 2.0) + pow(z - point.point.z, 2.0));
00090 if (dist < nearest_dist)
00091 {
00092 nearest_dist = dist;
00093 nearest_object_ind = i;
00094 }
00095 }
00096
00097 if (nearest_object_ind > -1)
00098 {
00099 ROS_INFO("nearest object ind: %d (distance: %f)", nearest_object_ind, nearest_dist);
00100 object_ind = nearest_object_ind;
00101 return true;
00102 } else
00103 {
00104 ROS_ERROR("No nearby objects. Unable to select grasp target");
00105 return false;
00106 }
00107 }
00108
00109 int main(int argc, char **argv)
00110 {
00111
00112 ros::init(argc, argv, "pick_and_place_app");
00113 ros::NodeHandle nh;
00114
00115
00116 const std::string OBJECT_DETECTION_SERVICE_NAME = "/object_detection";
00117 const std::string COLLISION_PROCESSING_SERVICE_NAME = "/tabletop_collision_map_processing/tabletop_collision_map_processing";
00118 const std::string PICKUP_ACTION_NAME = "/object_manipulator/object_manipulator_pickup";
00119 const std::string PLACE_ACTION_NAME = "/object_manipulator/object_manipulator_place";
00120 const std::string MOVE_ARM_ACTION_NAME = "/move_arm";
00121 const std::string COLLIDER_RESET_SERVICE_NAME = "/collider_node/reset";
00122
00123
00124 tf_listener = new tf::TransformListener();
00125
00126
00127 ros::ServiceClient object_detection_srv;
00128 ros::ServiceClient collision_processing_srv;
00129 ros::ServiceClient collider_reset_srv;
00130 actionlib::SimpleActionClient<object_manipulation_msgs::PickupAction>
00131 pickup_client(PICKUP_ACTION_NAME, true);
00132 actionlib::SimpleActionClient<object_manipulation_msgs::PlaceAction>
00133 place_client(PLACE_ACTION_NAME, true);
00134 actionlib::SimpleActionClient<arm_navigation_msgs::MoveArmAction> move_arm(MOVE_ARM_ACTION_NAME, true);
00135
00136
00137 while ( !ros::service::waitForService(OBJECT_DETECTION_SERVICE_NAME,
00138 ros::Duration(2.0)) && nh.ok() )
00139 {
00140 ROS_INFO("Waiting for object detection service to come up");
00141 }
00142 if (!nh.ok()) exit(0);
00143 object_detection_srv =
00144 nh.serviceClient<tabletop_object_detector::TabletopDetection>
00145 (OBJECT_DETECTION_SERVICE_NAME, true);
00146
00147
00148 while (!ros::service::waitForService(COLLISION_PROCESSING_SERVICE_NAME, ros::Duration(2.0)) && nh.ok())
00149 {
00150 ROS_INFO("Waiting for collision processing service to come up");
00151 }
00152 if (!nh.ok())
00153 exit(0);
00154 collision_processing_srv = nh.serviceClient<tabletop_collision_map_processing::TabletopCollisionMapProcessing>(
00155 COLLISION_PROCESSING_SERVICE_NAME, true);
00156
00157
00158 while (!ros::service::waitForService(COLLIDER_RESET_SERVICE_NAME, ros::Duration(2.0)) && nh.ok())
00159 {
00160 ROS_INFO("Waiting for collider reset service to come up");
00161 }
00162 if (!nh.ok())
00163 exit(0);
00164 collider_reset_srv = nh.serviceClient<std_srvs::Empty>(
00165 COLLIDER_RESET_SERVICE_NAME, true);
00166
00167
00168 while(!pickup_client.waitForServer(ros::Duration(2.0)) && nh.ok())
00169 {
00170 ROS_INFO_STREAM("Waiting for action client " << PICKUP_ACTION_NAME);
00171 }
00172 if (!nh.ok()) exit(0);
00173
00174
00175 while(!place_client.waitForServer(ros::Duration(2.0)) && nh.ok())
00176 {
00177 ROS_INFO_STREAM("Waiting for action client " << PLACE_ACTION_NAME);
00178 }
00179 if (!nh.ok()) exit(0);
00180
00181
00182 while(!move_arm.waitForServer(ros::Duration(2.0)) && nh.ok())
00183 {
00184 ROS_INFO_STREAM("Waiting for action client " << MOVE_ARM_ACTION_NAME);
00185 }
00186 if (!nh.ok()) exit(0);
00187
00188
00189
00190
00191
00192
00193 ROS_INFO("Clearing collision map");
00194 std_srvs::Empty empty;
00195 if (!collider_reset_srv.call(empty))
00196 {
00197 ROS_ERROR("Collider reset service failed");
00198 return -1;
00199 }
00200 ros::Duration(5.0).sleep();
00201
00202
00203 std::vector<std::string> names(NUM_JOINTS);
00204 names[0] = "katana_motor1_pan_joint";
00205 names[1] = "katana_motor2_lift_joint";
00206 names[2] = "katana_motor3_lift_joint";
00207 names[3] = "katana_motor4_lift_joint";
00208 names[4] = "katana_motor5_wrist_roll_joint";
00209
00210
00211 std::vector<arm_navigation_msgs::JointConstraint> joint_constraints(NUM_JOINTS);
00212
00213 for (size_t i = 0; i < NUM_JOINTS; ++i)
00214 {
00215 joint_constraints[i].joint_name = names[i];
00216 joint_constraints[i].tolerance_below = 0.1;
00217 joint_constraints[i].tolerance_above = 0.1;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227 joint_constraints[0].position = 0.0;
00228 joint_constraints[1].position = 2.13549384276445;
00229 joint_constraints[2].position = -2.1556486321117725;
00230 joint_constraints[3].position = -1.971949347057968;
00231 joint_constraints[4].position = 0.0;
00232
00233 ROS_INFO("Moving arm away");
00234 bool success;
00235 success = move_to_joint_goal(joint_constraints, move_arm);
00236 if (!success)
00237 return -1;
00238
00239 ros::Duration(2.0).sleep();
00240
00241
00242 ROS_INFO("Clearing collision map");
00243 if (!collider_reset_srv.call(empty))
00244 {
00245 ROS_ERROR("Collider reset service failed");
00246 return -1;
00247 }
00248 ros::Duration(5.0).sleep();
00249
00250
00251 ROS_INFO("Calling tabletop detector");
00252 tabletop_object_detector::TabletopDetection detection_call;
00253
00254
00255 detection_call.request.return_clusters = true;
00256
00257 detection_call.request.return_models = false;
00258 if (!object_detection_srv.call(detection_call))
00259 {
00260 ROS_ERROR("Tabletop detection service failed");
00261 return -1;
00262 }
00263 if (detection_call.response.detection.result !=
00264 detection_call.response.detection.SUCCESS)
00265 {
00266 ROS_ERROR("Tabletop detection returned error code %d",
00267 detection_call.response.detection.result);
00268 return -1;
00269 }
00270 if (detection_call.response.detection.clusters.empty() &&
00271 detection_call.response.detection.models.empty() )
00272 {
00273 ROS_ERROR("The tabletop detector detected the table, but found no objects");
00274 return -1;
00275 }
00276
00277
00278
00279 ROS_INFO("Calling collision map processing");
00280 tabletop_collision_map_processing::TabletopCollisionMapProcessing
00281 processing_call;
00282
00283 processing_call.request.detection_result = detection_call.response.detection;
00284
00285
00286 processing_call.request.reset_collision_models = true;
00287 processing_call.request.reset_attached_models = true;
00288
00289
00290
00291
00292 processing_call.request.desired_frame = "katana_base_link";
00293 if (!collision_processing_srv.call(processing_call))
00294 {
00295 ROS_ERROR("Collision map processing service failed");
00296 return -1;
00297 }
00298
00299 if (processing_call.response.graspable_objects.empty())
00300 {
00301 ROS_ERROR("Collision map processing returned no graspable objects");
00302 return -1;
00303 }
00304
00305
00306
00307 geometry_msgs::PointStamped pickup_point;
00308 pickup_point.header.frame_id = "/base_footprint";
00309 pickup_point.point.x = 0.25;
00310 pickup_point.point.y = -0.15;
00311 pickup_point.point.z = TABLE_HEIGHT;
00312
00313
00314 ROS_INFO("Calling the pickup action");
00315 object_manipulation_msgs::PickupGoal pickup_goal;
00316
00317 int object_to_pick_ind;
00318
00319 if (!nearest_object(processing_call.response.graspable_objects, pickup_point, object_to_pick_ind))
00320 return -1;
00321 pickup_goal.target = processing_call.response.graspable_objects[object_to_pick_ind];
00322
00323
00324
00325 pickup_goal.collision_object_name =
00326 processing_call.response.collision_object_names.at(object_to_pick_ind);
00327
00328
00329 pickup_goal.collision_support_surface_name =
00330 processing_call.response.collision_support_surface_name;
00331
00332 pickup_goal.arm_name = "arm";
00333 pickup_goal.allow_gripper_support_collision = true;
00334
00335
00336
00337
00338
00339 geometry_msgs::Vector3Stamped direction;
00340 direction.header.stamp = ros::Time::now();
00341 direction.header.frame_id = "katana_base_link";
00342 direction.vector.x = 0;
00343 direction.vector.y = 0;
00344 direction.vector.z = 1;
00345 pickup_goal.lift.direction = direction;
00346
00347 pickup_goal.lift.desired_distance = 0.1;
00348 pickup_goal.lift.min_distance = 0.05;
00349
00350 pickup_goal.use_reactive_lift = false;
00351 pickup_goal.use_reactive_execution = false;
00352
00353 pickup_client.sendGoal(pickup_goal);
00354 while (!pickup_client.waitForResult(ros::Duration(10.0)))
00355 {
00356 ROS_INFO("Waiting for the pickup action...");
00357 if (!nh.ok())
00358 return -1;
00359 }
00360 object_manipulation_msgs::PickupResult pickup_result = *(pickup_client.getResult());
00361 if (pickup_client.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
00362 {
00363 ROS_INFO("Pickup succeeded.");
00364 } else
00365 {
00366 ROS_ERROR("The pickup action has failed with result code %d",
00367 pickup_result.manipulation_result.value);
00368 return -1;
00369 }
00370
00371
00372 geometry_msgs::PoseStamped pickup_location;
00373
00374
00375 pickup_location.header =
00376 processing_call.response.graspable_objects.at(object_to_pick_ind).cluster.header;
00377
00378 pickup_location.pose.orientation.w = 1;
00379
00380
00381 geometry_msgs::PoseStamped place_location = pickup_location;
00382 place_location.header.stamp = ros::Time::now();
00383 place_location.pose.position.y += 0.3;
00384
00385
00386 ROS_INFO("Calling the place action");
00387 object_manipulation_msgs::PlaceGoal place_goal;
00388
00389 place_goal.place_locations.push_back(place_location);
00390
00391
00392 place_goal.collision_object_name =
00393 processing_call.response.collision_object_names.at(object_to_pick_ind);
00394 place_goal.collision_support_surface_name =
00395 processing_call.response.collision_support_surface_name;
00396
00397
00398 place_goal.grasp = pickup_result.grasp;
00399
00400 place_goal.arm_name = "arm";
00401
00402
00403 place_goal.place_padding = 0.02;
00404
00405 place_goal.desired_retreat_distance = 0.1;
00406 place_goal.min_retreat_distance = 0.05;
00407
00408
00409 direction.header.stamp = ros::Time::now();
00410 direction.header.frame_id = "katana_base_link";
00411 direction.vector.x = 0;
00412 direction.vector.y = 0;
00413 direction.vector.z = -1;
00414 place_goal.approach.direction = direction;
00415
00416 place_goal.approach.desired_distance = 0.1;
00417 place_goal.approach.min_distance = 0.05;
00418
00419 place_goal.use_reactive_place = false;
00420
00421 place_client.sendGoal(place_goal);
00422 while (!place_client.waitForResult(ros::Duration(10.0)))
00423 {
00424 ROS_INFO("Waiting for the place action...");
00425 if (!nh.ok())
00426 return -1;
00427 }
00428 object_manipulation_msgs::PlaceResult place_result =
00429 *(place_client.getResult());
00430 if (place_client.getState() != actionlib::SimpleClientGoalState::SUCCEEDED)
00431 {
00432 if (place_result.manipulation_result.value == object_manipulation_msgs::ManipulationResult::RETREAT_FAILED)
00433 {
00434 ROS_WARN("Place failed with error RETREAT_FAILED, ignoring! This may lead to collision with the object we just placed!");
00435 } else {
00436 ROS_ERROR("Place failed with error code %d",
00437 place_result.manipulation_result.value);
00438 return -1;
00439 }
00440 }
00441
00442 ros::Duration(2.0).sleep();
00443
00444
00445 ROS_INFO("Clearing collision map");
00446 if (!collider_reset_srv.call(empty))
00447 {
00448 ROS_ERROR("Collider reset service failed");
00449 return -1;
00450 }
00451 ros::Duration(5.0).sleep();
00452
00453
00454 ROS_INFO("Moving arm away");
00455 success = move_to_joint_goal(joint_constraints, move_arm);
00456 if (!success)
00457 return -1;
00458
00459
00460 ROS_INFO("Success! Object moved.");
00461 return 0;
00462 }