00001 #include <carl_moveit/common_actions.h>
00002
00003 using namespace std;
00004
00005 CommonActions::CommonActions() :
00006 moveToJointPoseClient("carl_moveit_wrapper/move_to_joint_pose"),
00007 moveToPoseClient("carl_moveit_wrapper/move_to_pose"),
00008 gripperClient("jaco_arm/manipulation/gripper"),
00009 liftClient("carl_moveit_wrapper/common_actions/lift"),
00010 liftServer(n, "carl_moveit_wrapper/common_actions/lift", boost::bind(&CommonActions::liftArm, this, _1), false),
00011 armServer(n, "carl_moveit_wrapper/common_actions/arm_action", boost::bind(&CommonActions::executeArmAction, this, _1), false),
00012 pickupServer(n, "carl_moveit_wrapper/common_actions/pickup", boost::bind(&CommonActions::executePickup, this, _1), false),
00013 storeServer(n, "carl_moveit_wrapper/common_actions/store", boost::bind(&CommonActions::executeStore, this, _1), false),
00014 wipeSurfaceServer(n, "carl_moveit_wrapper/common_actions/wipe_surface", boost::bind(&CommonActions::executeWipeSurface, this, _1), false)
00015 {
00016
00017 homePosition.resize(NUM_JACO_JOINTS);
00018 homePosition[0] = -1.410;
00019 homePosition[1] = 2.975;
00020 homePosition[2] = .868;
00021 homePosition[3] = -2.323;
00022 homePosition[4] = 1.626;
00023 homePosition[5] = 1.393;
00024
00025 defaultRetractPosition.resize(NUM_JACO_JOINTS);
00026 defaultRetractPosition[0] = -2.57;
00027 defaultRetractPosition[1] = 1.39;
00028 defaultRetractPosition[2] = .527;
00029 defaultRetractPosition[3] = -.084;
00030 defaultRetractPosition[4] = .515;
00031 defaultRetractPosition[5] = -1.745;
00032
00033 angularCmdPublisher = n.advertise<wpi_jaco_msgs::AngularCommand>("jaco_arm/angular_cmd", 1);
00034
00035 eraseTrajectoriesClient = n.serviceClient<std_srvs::Empty>("jaco_arm/erase_trajectories");
00036 cartesianPathClient = n.serviceClient<rail_manipulation_msgs::CartesianPath>("carl_moveit_wrapper/cartesian_path");
00037 jacoPosClient = n.serviceClient<wpi_jaco_msgs::GetAngularPosition>("jaco_arm/get_angular_position");
00038 attachClosestObjectClient = n.serviceClient<std_srvs::Empty>("carl_moveit_wrapper/attach_closest_object");
00039 detachObjectsClient = n.serviceClient<std_srvs::Empty>("carl_moveit_wrapper/detach_objects");
00040
00041
00042 liftServer.start();
00043 armServer.start();
00044 pickupServer.start();
00045 storeServer.start();
00046 wipeSurfaceServer.start();
00047 }
00048
00049 void CommonActions::executePickup(const rail_manipulation_msgs::PickupGoalConstPtr &goal)
00050 {
00051 rail_manipulation_msgs::PickupFeedback feedback;
00052 rail_manipulation_msgs::PickupResult result;
00053 stringstream ss;
00054
00055
00056 geometry_msgs::PoseStamped graspPose, approachAnglePose;
00057 graspPose.header.frame_id = "base_footprint";
00058 if (goal->pose.header.frame_id != "base_footprint")
00059 tfListener.transformPose("base_footprint", goal->pose, graspPose);
00060 else
00061 graspPose = goal->pose;
00062
00063 tf::Transform graspTransform;
00064 graspTransform.setOrigin(tf::Vector3(graspPose.pose.position.x, graspPose.pose.position.y, graspPose.pose.position.z));
00065 graspTransform.setRotation(tf::Quaternion(graspPose.pose.orientation.x, graspPose.pose.orientation.y, graspPose.pose.orientation.z, graspPose.pose.orientation.w));
00066 ros::Time now = ros::Time::now();
00067 tfBroadcaster.sendTransform(tf::StampedTransform(graspTransform, now, "base_footprint", "grasp_frame"));
00068 tfListener.waitForTransform("grasp_frame", "base_footprint", now, ros::Duration(5.0));
00069
00070 approachAnglePose.header.frame_id = "grasp_frame";
00071 approachAnglePose.pose.position.x = -0.1;
00072 approachAnglePose.pose.orientation.w = 1.0;
00073
00074
00075 ss.str("");
00076 ss << "Attempting to move gripper to approach angle...";
00077 feedback.message = ss.str();
00078 pickupServer.publishFeedback(feedback);
00079
00080 rail_manipulation_msgs::MoveToPoseGoal approachAngleGoal;
00081 approachAngleGoal.pose = approachAnglePose;
00082 moveToPoseClient.sendGoal(approachAngleGoal);
00083 moveToPoseClient.waitForResult(ros::Duration(30.0));
00084 if (!moveToPoseClient.getResult()->success)
00085 {
00086 ss.str("");
00087 ss << "Moving to approach angle failed for this grasp.";
00088 feedback.message = ss.str();
00089 pickupServer.publishFeedback(feedback);
00090 result.success = false;
00091 pickupServer.setAborted(result, "Unable to move to appraoch angle.");
00092 return;
00093 }
00094
00095
00096 ss.str("");
00097 ss << "Opening gripper...";
00098 feedback.message = ss.str();
00099 pickupServer.publishFeedback(feedback);
00100
00101 rail_manipulation_msgs::GripperGoal gripperGoal;
00102 gripperGoal.close = false;
00103 gripperClient.sendGoal(gripperGoal);
00104 gripperClient.waitForResult(ros::Duration(10.0));
00105 if (!gripperClient.getResult()->success)
00106 {
00107 ROS_INFO("Opening gripper failed.");
00108 result.success = false;
00109 pickupServer.setAborted(result, "Unable to open gripper.");
00110 return;
00111 }
00112
00113
00114 ss.str("");
00115 ss << "Moving along approach angle...";
00116 feedback.message = ss.str();
00117 pickupServer.publishFeedback(feedback);
00118
00119 rail_manipulation_msgs::CartesianPath srv;
00120 geometry_msgs::PoseStamped cartesianPose;
00121 cartesianPose.header.frame_id = "base_footprint";
00122 tfListener.transformPose("base_footprint", graspPose, cartesianPose);
00123 srv.request.waypoints.push_back(cartesianPose);
00124 srv.request.avoidCollisions = false;
00125 if (!cartesianPathClient.call(srv))
00126 {
00127 ROS_INFO("Could not call Jaco Cartesian path service.");
00128 result.success = false;
00129 pickupServer.setAborted(result, "Could not call Jaco Cartesian path service.");
00130 return;
00131 }
00132
00133
00134 ss.str("");
00135 ss << "Closing gripper...";
00136 feedback.message = ss.str();
00137 pickupServer.publishFeedback(feedback);
00138
00139 gripperGoal.close = true;
00140 gripperClient.sendGoal(gripperGoal);
00141 gripperClient.waitForResult(ros::Duration(10.0));
00142 if (!gripperClient.getResult()->success)
00143 {
00144 ROS_INFO("Closing gripper failed.");
00145 result.success = false;
00146 pickupServer.setAborted(result, "Unable to close gripper.");
00147 return;
00148 }
00149
00150
00151 std_srvs::Empty emptySrv;
00152 if (!attachClosestObjectClient.call(emptySrv))
00153 {
00154 ROS_INFO("No scene object to attach...");
00155 }
00156
00157 if (goal->lift)
00158 {
00159
00160 ss.str("");
00161 ss << "Lifting hand...";
00162 feedback.message = ss.str();
00163 pickupServer.publishFeedback(feedback);
00164
00165 rail_manipulation_msgs::LiftGoal liftGoal;
00166 liftClient.sendGoal(liftGoal);
00167 liftClient.waitForResult(ros::Duration(10.0));
00168 }
00169
00170 result.success = true;
00171 pickupServer.setSucceeded(result);
00172 }
00173
00174 void CommonActions::executeStore(const rail_manipulation_msgs::StoreGoalConstPtr &goal)
00175 {
00176 rail_manipulation_msgs::StoreFeedback feedback;
00177 rail_manipulation_msgs::StoreResult result;
00178 stringstream ss;
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 ss.str("");
00195 ss << "Moving gripper above store position...";
00196 feedback.message = ss.str();
00197 storeServer.publishFeedback(feedback);
00198
00199 rail_manipulation_msgs::MoveToPoseGoal approachAngleGoal;
00200 approachAngleGoal.pose = goal->store_pose;
00201 approachAngleGoal.pose.pose.position.z += .1;
00202 moveToPoseClient.sendGoal(approachAngleGoal);
00203 moveToPoseClient.waitForResult(ros::Duration(30.0));
00204 if (!moveToPoseClient.getResult()->success)
00205 {
00206 ss.str("");
00207 ss << "Moving gripper above store position failed.";
00208 feedback.message = ss.str();
00209 storeServer.publishFeedback(feedback);
00210 result.success = false;
00211 storeServer.setAborted(result, "Unable to move gripper above store position.");
00212 return;
00213 }
00214
00215
00216 ss.str("");
00217 ss << "Lowering gripper...";
00218 feedback.message = ss.str();
00219 storeServer.publishFeedback(feedback);
00220
00221 rail_manipulation_msgs::CartesianPath srv;
00222 geometry_msgs::PoseStamped cartesianPose;
00223 approachAngleGoal.pose.pose.position.z -= .1;
00224 cartesianPose.header.frame_id = "base_footprint";
00225 tfListener.transformPose("base_footprint", approachAngleGoal.pose, cartesianPose);
00226 srv.request.waypoints.push_back(cartesianPose);
00227 srv.request.avoidCollisions = false;
00228 if (!cartesianPathClient.call(srv))
00229 {
00230 ROS_INFO("Could not call Jaco Cartesian path service.");
00231 result.success = false;
00232 storeServer.setAborted(result, "Could not call Jaco Cartesian path service.");
00233 return;
00234 }
00235
00236
00237 ss.str("");
00238 ss << "Opening gripper...";
00239 feedback.message = ss.str();
00240 storeServer.publishFeedback(feedback);
00241
00242 rail_manipulation_msgs::GripperGoal gripperGoal;
00243 gripperGoal.close = false;
00244 gripperClient.sendGoal(gripperGoal);
00245 gripperClient.waitForResult(ros::Duration(10.0));
00246 if (!gripperClient.getResult()->success)
00247 {
00248 ROS_INFO("Opening gripper failed.");
00249 result.success = false;
00250 storeServer.setAborted(result, "Unable to open gripper.");
00251 return;
00252 }
00253
00254
00255 std_srvs::Empty emptySrv;
00256 if (!detachObjectsClient.call(emptySrv))
00257 {
00258 ROS_INFO("Couldn't call detach objects service.");
00259 }
00260
00261
00262 ss.str("");
00263 ss << "Raising gripper...";
00264 feedback.message = ss.str();
00265 storeServer.publishFeedback(feedback);
00266
00267 cartesianPose.pose.position.z += .05;
00268 srv.request.waypoints.clear();
00269 srv.request.waypoints.push_back(cartesianPose);
00270 srv.request.avoidCollisions = false;
00271 if (!cartesianPathClient.call(srv))
00272 {
00273 ROS_INFO("Could not call Jaco Cartesian path service.");
00274 result.success = false;
00275 storeServer.setAborted(result, "Could not call Jaco Cartesian path service.");
00276 return;
00277 }
00278
00279 result.success = true;
00280 storeServer.setSucceeded(result);
00281 }
00282
00283 void CommonActions::executeArmAction(const rail_manipulation_msgs::ArmGoalConstPtr &goal)
00284 {
00285 rail_manipulation_msgs::ArmFeedback feedback;
00286 rail_manipulation_msgs::ArmResult result;
00287
00288 switch (goal->action) {
00289 case rail_manipulation_msgs::ArmGoal::READY:
00290 feedback.message = "Readying arm...";
00291 armServer.publishFeedback(feedback);
00292 break;
00293 case rail_manipulation_msgs::ArmGoal::RETRACT:
00294 feedback.message = "Retracting arm...";
00295 armServer.publishFeedback(feedback);
00296 break;
00297 default:
00298 feedback.message = "Executing arm action...";
00299 armServer.publishFeedback(feedback);
00300 break;
00301 }
00302
00303 if (goal->action == rail_manipulation_msgs::ArmGoal::RETRACT)
00304 {
00305 if (isArmRetracted(defaultRetractPosition))
00306 {
00307 feedback.message = "Arm is already retracted.";
00308 armServer.publishFeedback(feedback);
00309
00310 result.success = true;
00311 armServer.setSucceeded(result);
00312 return;
00313 }
00314 }
00315
00316 rail_manipulation_msgs::MoveToJointPoseGoal jointPoseGoal;
00317
00318 vector<float> baseJointPoseGoal;
00319 baseJointPoseGoal.resize(homePosition.size());
00320 for (unsigned int i = 0; i < baseJointPoseGoal.size(); i ++)
00321 {
00322 baseJointPoseGoal[i] = homePosition[i];
00323 }
00324 jointPoseGoal.joints.resize(baseJointPoseGoal.size());
00325 for (unsigned int i = 0; i < jointPoseGoal.joints.size(); i ++)
00326 {
00327 jointPoseGoal.joints[i] = baseJointPoseGoal[i];
00328 }
00329 bool succeeded = false;
00330 int counter = 0;
00331 int attempts = MAX_HOME_ATTEMPTS;
00332 while (!succeeded && counter < attempts)
00333 {
00334 stringstream ss;
00335 ss << "Planning and moving arm to ready position (attempt " << counter + 1 << "/" << attempts << ")";
00336 feedback.message = ss.str();
00337 armServer.publishFeedback(feedback);
00338
00339 ROS_INFO("Ready arm attempt %d", counter);
00340
00341 moveToJointPoseClient.sendGoal(jointPoseGoal);
00342 ROS_INFO("Moving arm to ready position...");
00343 while (!moveToJointPoseClient.getState().isDone())
00344 {
00345 if (armServer.isPreemptRequested() || !ros::ok())
00346 {
00347 ROS_INFO("Ready arm action preempted.");
00348 moveToJointPoseClient.cancelAllGoals();
00349 result.success = false;
00350 armServer.setPreempted(result);
00351 return;
00352 }
00353 }
00354
00355 rail_manipulation_msgs::MoveToJointPoseResultConstPtr readyResult = moveToJointPoseClient.getResult();
00356
00357 succeeded = readyResult->success;
00358 counter ++;
00359
00360
00361 if (!succeeded && counter < attempts)
00362 {
00363 ROS_INFO("Ready arm failed, resampling goal for another attempt...");
00364 for (unsigned int i = 0; i < jointPoseGoal.joints.size(); i ++)
00365 {
00366 jointPoseGoal.joints[i] = baseJointPoseGoal[i] + (rand() % 700 - 350) / 10000;
00367 }
00368 }
00369 }
00370
00371 if (!succeeded)
00372 {
00373 feedback.message = "Failed to ready arm.";
00374 armServer.publishFeedback(feedback);
00375
00376 ROS_INFO("Plan and move to ready position failed.");
00377 result.success = false;
00378 armServer.setSucceeded(result);
00379 return;
00380 }
00381
00382 if (goal->action == rail_manipulation_msgs::ArmGoal::RETRACT)
00383 {
00384 feedback.message = "Moving arm to retracted position...";
00385 armServer.publishFeedback(feedback);
00386
00387 wpi_jaco_msgs::AngularCommand cmd;
00388 cmd.armCommand = true;
00389 cmd.fingerCommand = false;
00390 cmd.position = true;
00391 cmd.repeat = false;
00392 cmd.joints = defaultRetractPosition;
00393 angularCmdPublisher.publish(cmd);
00394 ros::Time startTime = ros::Time::now();
00395 ros::Rate loopRate(30);
00396 bool retracted = false;
00397 while (!retracted)
00398 {
00399
00400 if (armServer.isPreemptRequested() || !ros::ok())
00401 {
00402 ROS_INFO("Ready arm action preempted.");
00403 std_srvs::Empty srv;
00404 if (!eraseTrajectoriesClient.call(srv))
00405 {
00406 ROS_INFO("Could not call erase trajectories service...");
00407 }
00408 result.success = false;
00409 armServer.setPreempted(result);
00410 return;
00411 }
00412
00413
00414 retracted = isArmRetracted(defaultRetractPosition);
00415
00416
00417 ros::Time currentTime = ros::Time::now();
00418 if ((currentTime.toSec() - startTime.toSec()) > 10.0)
00419 {
00420 feedback.message = "Retracting arm timed out.";
00421 armServer.publishFeedback(feedback);
00422
00423 ROS_INFO("Ready arm timed out.");
00424 result.success = false;
00425 armServer.setSucceeded(result);
00426 return;
00427 }
00428 loopRate.sleep();
00429 }
00430 }
00431
00432 switch (goal->action) {
00433 case rail_manipulation_msgs::ArmGoal::READY:
00434 feedback.message = "Ready arm completed.";
00435 armServer.publishFeedback(feedback);
00436 break;
00437 case rail_manipulation_msgs::ArmGoal::RETRACT:
00438 feedback.message = "Retract arm completed.";
00439 armServer.publishFeedback(feedback);
00440 break;
00441 default:
00442 feedback.message = "Arm action completed.";
00443 armServer.publishFeedback(feedback);
00444 break;
00445 }
00446
00447 result.success = succeeded;
00448 armServer.setSucceeded(result);
00449 }
00450
00451 void CommonActions::executeWipeSurface(const carl_moveit::WipeSurfaceGoalConstPtr &goal)
00452 {
00453 carl_moveit::WipeSurfaceFeedback feedback;
00454 carl_moveit::WipeSurfaceResult result;
00455 stringstream ss;
00456
00457
00458 rail_manipulation_msgs::MoveToPoseGoal poseGoal;
00459 poseGoal.pose.header.frame_id = "base_footprint";
00460 poseGoal.pose.pose.position.x = 0.869;
00461 poseGoal.pose.pose.position.y = 0.0;
00462 poseGoal.pose.pose.position.z = goal->height;
00463 poseGoal.pose.pose.orientation.x = -0.605;
00464 poseGoal.pose.pose.orientation.y = 0.271;
00465 poseGoal.pose.pose.orientation.z = 0.699;
00466 poseGoal.pose.pose.orientation.w = 0.267;
00467
00468 moveToPoseClient.sendGoal(poseGoal);
00469 moveToPoseClient.waitForResult(ros::Duration(30.0));
00470 if (!moveToPoseClient.getResult()->success)
00471 {
00472 ss.str("");
00473 ss << "Moving to initial wiping position failed.";
00474 feedback.message = ss.str();
00475 wipeSurfaceServer.publishFeedback(feedback);
00476 result.success = false;
00477 wipeSurfaceServer.setAborted(result, "Unable to move to appraoch angle.");
00478 return;
00479 }
00480
00481
00482 ss.str("");
00483 ss << "Wiping...";
00484 feedback.message = ss.str();
00485 wipeSurfaceServer.publishFeedback(feedback);
00486
00487 rail_manipulation_msgs::CartesianPath srv;
00488 for (unsigned int i = 0; i < 3; i ++)
00489 {
00490 geometry_msgs::PoseStamped pose = poseGoal.pose;
00491
00492
00493
00494
00495
00496
00497
00498
00499 pose.pose.position.y += .15;
00500 srv.request.waypoints.push_back(pose);
00501 pose.pose.position.y -= .15;
00502 pose.pose.position.x += .05;
00503 srv.request.waypoints.push_back(pose);
00504 pose.pose.position.y -= .15;
00505 pose.pose.position.x -= .05;
00506 srv.request.waypoints.push_back(pose);
00507 pose.pose.position.y += .15;
00508 pose.pose.position.x -= .05;
00509 srv.request.waypoints.push_back(pose);
00510 }
00511 ROS_INFO("Waypoints y:");
00512 for (unsigned int i = 0; i < srv.request.waypoints.size(); i ++)
00513 {
00514 ROS_INFO("%f", srv.request.waypoints[i].pose.position.y);
00515 }
00516 srv.request.avoidCollisions = false;
00517 if (!cartesianPathClient.call(srv))
00518 {
00519 ROS_INFO("Could not call Jaco Cartesian path service.");
00520 result.success = false;
00521 wipeSurfaceServer.setAborted(result, "Could not call Jaco Cartesian path service.");
00522 return;
00523 }
00524
00525 ROS_INFO("Wipe surface action completed successfully.");
00526 result.success = true;
00527 wipeSurfaceServer.setSucceeded(result);
00528 }
00529
00530 void CommonActions::liftArm(const rail_manipulation_msgs::LiftGoalConstPtr &goal)
00531 {
00532 rail_manipulation_msgs::LiftResult result;
00533
00534 rail_manipulation_msgs::CartesianPath srv;
00535 tf::StampedTransform currentEefTransform;
00536 tfListener.waitForTransform("jaco_link_eef", "base_footprint", ros::Time::now(), ros::Duration(1.0));
00537 tfListener.lookupTransform("base_footprint", "jaco_link_eef", ros::Time(0), currentEefTransform);
00538 geometry_msgs::PoseStamped liftPose;
00539 liftPose.header.frame_id = "base_footprint";
00540 liftPose.pose.position.x = currentEefTransform.getOrigin().x();
00541 liftPose.pose.position.y = currentEefTransform.getOrigin().y();
00542 liftPose.pose.position.z = currentEefTransform.getOrigin().z() + .1;
00543 liftPose.pose.orientation.x = currentEefTransform.getRotation().x();
00544 liftPose.pose.orientation.y = currentEefTransform.getRotation().y();
00545 liftPose.pose.orientation.z = currentEefTransform.getRotation().z();
00546 liftPose.pose.orientation.w = currentEefTransform.getRotation().w();
00547 srv.request.waypoints.push_back(liftPose);
00548 srv.request.avoidCollisions = false;
00549
00550 if (!cartesianPathClient.call(srv))
00551 {
00552 ROS_INFO("Could not call Jaco Cartesian path service.");
00553 result.success = false;
00554 liftServer.setAborted(result, "Could not call Jaco Cartesian path service.");
00555 return;
00556 }
00557
00558 result.success = srv.response.success;
00559 liftServer.setSucceeded(result);
00560 }
00561
00562 bool CommonActions::isArmRetracted(const vector<float> &retractPos)
00563 {
00564 float dstFromRetract = 0;
00565
00566
00567 wpi_jaco_msgs::GetAngularPosition::Request req;
00568 wpi_jaco_msgs::GetAngularPosition::Response res;
00569 if(!jacoPosClient.call(req, res))
00570 {
00571 ROS_INFO("Could not call Jaco joint position service.");
00572 return false;
00573 }
00574
00575 for (unsigned int i = 0; i < retractPos.size(); i ++)
00576 {
00577 dstFromRetract += fabs(retractPos[i] - res.pos[i]);
00578 }
00579
00580 if (dstFromRetract > 0.175)
00581 return false;
00582 return true;
00583 }
00584
00585 int main(int argc, char **argv)
00586 {
00587 ros::init(argc, argv, "carl_moveit_common_actions");
00588
00589 CommonActions ca;
00590
00591 ros::spin();
00592 }