RobotNavigator.cpp
Go to the documentation of this file.
00001 /*
00002  * RobotNavigator.cpp
00003  *
00004  *  Created on: Oct 18, 2012
00005  *      Author: jnicho
00006  */
00007 
00008 #include <object_manipulation_tools/robot_navigators/RobotNavigator.h>
00009 #include <boost/foreach.hpp>
00010 #include <object_manipulation_tools/manipulation_utils/Utilities.h>
00011 
00012 /* continue modifications in move arm
00013  *
00014  */
00015 std::string RobotNavigator::NODE_NAME = "robot_pick_place";
00016 std::string RobotNavigator::NAVIGATOR_NAMESPACE = "navigator";
00017 std::string RobotNavigator::MARKER_ARM_LINK = "arm_links";
00018 std::string RobotNavigator::MARKER_ATTACHED_OBJECT = "attached_object";
00019 std::string RobotNavigator::VISUALIZATION_TOPIC = "visualization_markers";
00020 
00021 const tf::Transform RobotNavigator::PLACE_RECTIFICATION_TF = tf::Transform(
00022                 tf::Quaternion(tf::Vector3(1.0f,0.0f,0.0f),M_PI),tf::Vector3(0.0f,0.0f,0.0f));
00023 
00024 // global variables
00025 const double GRAP_ACTION_TIMEOUT = 4.0f;
00026 
00027 void RobotNavigator::fetchParameters(std::string nameSpace)
00028 {
00029         ros::NodeHandle nh;
00030         using namespace RobotNavigatorParameters;
00031 
00032         ros::param::param(nameSpace + "/" + PARAM_NAME_ARM_GROUP,arm_group_name_,DEFAULT_ARM_GROUP);
00033         ros::param::param(nameSpace + "/" + PARAM_NAME_GRIPPER_GROUP,gripper_group_name_,DEFAULT_GRIPPER_GROUP);
00034         ros::param::param(nameSpace + "/" + PARAM_NAME_WRIST_LINK,wrist_link_name_,DEFAULT_WRIST_LINK);
00035         ros::param::param(nameSpace + "/" + PARAM_NAME_GRIPPER_LINK,gripper_link_name_,DEFAULT_GRIPPER_LINK);
00036         ros::param::param(nameSpace + "/" + PARAM_NAME_GRASP_ACTION_SERVICE,grasp_action_service_,DEFAULT_GRASP_ACTION_SERVICE );
00037         ros::param::param(nameSpace + "/" + PARAM_NAME_TRAJECTORY_ACTION_SERVICE,trajectory_action_service_,DEFAULT_TRAJECTORY_ACTION_SERVICE);
00038         ros::param::param(nameSpace + "/" + PARAM_NAME_PATH_PLANNER_SERVICE,path_planner_service_,DEFAULT_PATH_PLANNER_SERVICE);
00039         ros::param::param(nameSpace + "/" + PARAM_NAME_TRAJECTORY_FILTER_SERVICE,trajectory_filter_service_,DEFAULT_TRAJECTORY_FILTER_SERVICE);
00040         ros::param::param(nameSpace + "/" + PARAM_NAME_SEGMENTATION_SERVICE,segmentation_service_,DEFAULT_SEGMENTATION_SERVICE);
00041         ros::param::param(nameSpace + "/" + PARAM_NAME_RECOGNITION_SERVICE,recognition_service_,DEFAULT_RECOGNITION_SERVICE);
00042         ros::param::param(nameSpace + "/" + PARAM_NAME_GRASP_PLANNING_SERVICE,grasp_planning_service_,DEFAULT_GRASP_PLANNING_SERVICE);
00043         ros::param::param(nameSpace + "/" + PARAM_NAME_MESH_DATABASE_SERVICE,mesh_database_service_,DEFAULT_MESH_DATABASE_SERVICE);
00044         ros::param::param(nameSpace + "/" + PARAM_NAME_MODEL_DATABASE_SERVICE,model_database_service_,DEFAULT_MODEL_DATABASE_SERVICE);
00045         ros::param::param(nameSpace + "/" + PARAM_NAME_PLANNING_SCENE_SERVICE,planning_scene_service_,DEFAULT_PLANNING_SCENE_SERVICE);
00046         ros::param::param(nameSpace + "/" + PARAM_NAME_IK_PLUGING,ik_plugin_name_,DEFAULT_IK_PLUGING);
00047         ros::param::param(nameSpace + "/" + PARAM_NAME_JOINT_STATES_TOPIC,joint_states_topic_,DEFAULT_JOINT_STATES_TOPIC);
00048 
00049         ros::param::param(nameSpace + "/" + PARAM_PICK_APPROACH_DISTANCE,pick_approach_distance_,DF_PICK_APPROACH_DISTANCE);
00050         ros::param::param(nameSpace + "/" + PARAM_PLACE_APPROACH_DISTANCE,place_approach_distance_,DF_PLACE_APPROACH_DISTANCE);
00051         ros::param::param(nameSpace + "/" + PARAM_PLACE_RETREAT_DISTANCE,place_retreat_distance_,DF_PLACE_RETREAT_DISTANCE);
00052 }
00053 
00054 RobotNavigator::RobotNavigator()
00055 : cm_("robot_description"),
00056   current_robot_state_(NULL),
00057   pick_approach_distance_(RobotNavigatorParameters::DF_PICK_APPROACH_DISTANCE),
00058   place_approach_distance_(RobotNavigatorParameters::DF_PLACE_APPROACH_DISTANCE),
00059   place_retreat_distance_(RobotNavigatorParameters::DF_PLACE_RETREAT_DISTANCE)
00060 
00061 {
00062         ros::NodeHandle nh;
00063 
00064         // initializing name spaces global strings
00065         NODE_NAME = ros::this_node::getName();
00066         NAVIGATOR_NAMESPACE = NODE_NAME + "/" + NAVIGATOR_NAMESPACE;
00067         VISUALIZATION_TOPIC = NODE_NAME + "/" + VISUALIZATION_TOPIC;
00068 }
00069 
00070 RobotNavigator::~RobotNavigator()
00071 {
00072 
00073 }
00074 
00075 void RobotNavigator::setup()
00076 {
00077         ros::NodeHandle nh;
00078         std::string nodeName = ros::this_node::getName();
00079 
00080         ROS_INFO_STREAM(NODE_NAME<<": Loading ros parameters");
00081 
00082         // getting ros parametets
00083         fetchParameters(NAVIGATOR_NAMESPACE);
00084 
00085         ROS_INFO_STREAM(NODE_NAME<<": Setting up execution Monitors");
00086         // setting up execution monitors
00087         {
00088                 joint_state_recorder_.reset(new JointStateTrajectoryRecorder(joint_states_topic_));
00089                 arm_controller_handler_.reset(new FollowJointTrajectoryControllerHandler(arm_group_name_,trajectory_action_service_));
00090                 gripper_controller_handler_.reset(new GraspPoseControllerHandler(gripper_group_name_,grasp_action_service_));
00091 
00092                 trajectory_execution_monitor_.addTrajectoryRecorder(joint_state_recorder_);
00093                 trajectory_execution_monitor_.addTrajectoryControllerHandler(arm_controller_handler_);
00094                 trajectory_execution_monitor_.addTrajectoryControllerHandler(gripper_controller_handler_);
00095         }
00096 
00097         ROS_INFO_STREAM(NODE_NAME<<": Setting up Service Clients");
00098     // setting up service clients, this is configuration specific
00099         {
00100                 // perception
00101                 seg_srv_ = nh.serviceClient<tabletop_object_detector::TabletopSegmentation>(segmentation_service_, true);
00102                 rec_srv_ = nh.serviceClient<tabletop_object_detector::TabletopObjectRecognition>(
00103                                 recognition_service_, true);
00104                 object_database_model_mesh_client_ = nh.serviceClient<household_objects_database_msgs::GetModelMesh>(
00105                                 mesh_database_service_, true);
00106                 object_database_model_description_client_ = nh.serviceClient<household_objects_database_msgs::GetModelDescription>(
00107                                 model_database_service_, true);
00108 
00109                 // path and grasp plannig
00110                 grasp_planning_client = nh.serviceClient<object_manipulation_msgs::GraspPlanning>(grasp_planning_service_, false);
00111                 planning_service_client_ = nh.serviceClient<arm_navigation_msgs::GetMotionPlan>(path_planner_service_);
00112 
00113                 // arm trajectory filter service
00114                 trajectory_filter_service_client_ = nh.serviceClient<arm_navigation_msgs::FilterJointTrajectoryWithConstraints>(trajectory_filter_service_);
00115                 ROS_INFO_STREAM(NODE_NAME<<": Waiting for trajectory filter service");
00116                 trajectory_filter_service_client_.waitForExistence();
00117                 ROS_INFO_STREAM(NODE_NAME<<": Trajectory filter service connected");
00118 
00119                 // planing scene
00120                 ROS_INFO_STREAM(NODE_NAME <<": Waiting for " + planning_scene_service_ + " service");
00121                 ros::service::waitForService(planning_scene_service_);
00122                 set_planning_scene_diff_client_ = nh.serviceClient<arm_navigation_msgs::SetPlanningSceneDiff>(planning_scene_service_);
00123         }
00124 
00125         // will use grasp execution client to request pre-grasp action since the default gripper controller handler
00126         // ignores this step.
00127         ROS_INFO_STREAM(NODE_NAME << ": Setting up Service Action Clients");
00128         {
00129                 grasp_exec_action_client_ =
00130                                 boost::make_shared< GraspActionServerClient >(grasp_action_service_,true);
00131                 while(!grasp_exec_action_client_->waitForServer(ros::Duration(0.5)))
00132                 {
00133                         ROS_INFO_STREAM(NODE_NAME << "Waiting for action service "<< grasp_action_service_);
00134                 }
00135                 ROS_INFO_STREAM(NODE_NAME<<" : Connected to action service "<<grasp_action_service_);
00136         }
00137 
00138         ROS_INFO_STREAM(NODE_NAME<<": Setting up ros publishers");
00139         {
00140                 // setting up ros publishers
00141                 marker_publisher_ = nh.advertise<visualization_msgs::Marker> (VISUALIZATION_TOPIC, 128);
00142                 attached_object_publisher_ = nh.advertise<arm_navigation_msgs::AttachedCollisionObject> ("attached_collision_object_alternate", 1);
00143 
00144                 // setting up timer obj
00145                 marker_pub_timer_ = nh.createTimer(ros::Duration(0.4f),&RobotNavigator::callbackPublishMarkers,this);
00146 
00147                 ROS_INFO_STREAM(NODE_NAME<<": Setting up dynamic libraries");
00148 
00149                 // others
00150                 grasp_tester_ = GraspTesterPtr(new GraspSequenceValidator(&cm_, ik_plugin_name_));
00151                 place_tester_ = PlaceSequencePtr(new PlaceSequenceValidator(&cm_, ik_plugin_name_));
00152 
00153                 trajectories_finished_function_ = boost::bind(&RobotNavigator::trajectoryFinishedCallback, this, true,_1);
00154                 grasp_action_finished_function_ = boost::bind(&RobotNavigator::trajectoryFinishedCallback, this, false,_1);
00155                 ROS_INFO_STREAM(NODE_NAME<<": Finished setup");
00156         }
00157 
00158         ROS_INFO_STREAM(NODE_NAME<<" Setting up grasp planning data");
00159         {
00160                 // storing grasp pickup goal to be used later during pick move sequence execution
00161                 grasp_pickup_goal_.arm_name = arm_group_name_;
00162                 grasp_pickup_goal_.lift.direction.header.frame_id = cm_.getWorldFrameId();
00163                 grasp_pickup_goal_.lift.direction.vector.z = 1.0;
00164                 grasp_pickup_goal_.lift.desired_distance = pick_approach_distance_;
00165                 grasp_pickup_goal_.lift.min_distance = pick_approach_distance_;
00166                 grasp_pickup_goal_.lift.direction.header.frame_id = cm_.getWorldFrameId();
00167                 grasp_pickup_goal_.allow_gripper_support_collision = true;
00168                 grasp_pickup_goal_.collision_support_surface_name = "table";
00169 
00170                 // populate grasp place goal
00171                 grasp_place_goal_.arm_name = arm_group_name_;
00172                 grasp_place_goal_.desired_retreat_distance = place_retreat_distance_;
00173                 grasp_place_goal_.min_retreat_distance = place_retreat_distance_;
00174                 grasp_place_goal_.approach.desired_distance = place_approach_distance_;
00175                 grasp_place_goal_.approach.min_distance = place_approach_distance_;
00176                 grasp_place_goal_.approach.direction.header.frame_id = cm_.getWorldFrameId();
00177                 grasp_place_goal_.approach.direction.vector.x = 0.0;
00178                 grasp_place_goal_.approach.direction.vector.y = 0.0;
00179                 grasp_place_goal_.approach.direction.vector.z = -1.0;
00180                 grasp_place_goal_.allow_gripper_support_collision = true;
00181                 grasp_place_goal_.collision_support_surface_name = "table";
00182                 grasp_place_goal_.place_padding = .02;
00183         }
00184 }
00185 
00186 bool RobotNavigator::trajectoryFinishedCallback(bool storeLastTraj,TrajectoryExecutionDataVector tedv)
00187 {
00188         ROS_INFO_STREAM(NODE_NAME<<":Trajectory execution result flag: "<<tedv.back().result_);
00189 
00190         // combining trajectory state flags;
00191         trajectories_succeeded_ = (tedv.back().result_ == SUCCEEDED
00192                                                           || tedv.back().result_ == HANDLER_REPORTS_FAILURE_BUT_OK
00193                                                           || tedv.back().result_ == HANDLER_REPORTS_FAILURE_BUT_CLOSE_ENOUGH);
00194 
00195         if(storeLastTraj)
00196         {
00197                 if(tedv.size()==0)
00198                 {
00199                         ROS_ERROR_STREAM(NODE_NAME <<": trajectory finished callback received empty vector");
00200                 }
00201                 else
00202                 {
00203                         ROS_INFO_STREAM(NODE_NAME<<": trajectory finished callback storing last trajectory");
00204                         last_trajectory_execution_data_vector_ = tedv;
00205                 }
00206         }
00207         else
00208         {
00209                 ROS_INFO_STREAM(NODE_NAME<<": trajectory finished callback will not store last trajectory");
00210         }
00211 
00212 
00213         ROS_INFO_STREAM(NODE_NAME<<": Trajectory finished callback notifying all awaiting threads");
00214         execution_completed_.notify_all();
00215         return true;
00216 }
00217 
00218 void RobotNavigator::revertPlanningScene()
00219 {
00220 
00221   if(current_robot_state_ != NULL)
00222   {
00223     cm_.revertPlanningScene(current_robot_state_);
00224     current_robot_state_ = NULL;
00225   }
00226   last_mpr_id_ = 0;
00227   max_mpr_id_ = 0;
00228   max_trajectory_id_ = 0;
00229 }
00230 
00231 std::vector<std::string> RobotNavigator::getJointNames(const std::string& group) {
00232   if(cm_.getKinematicModel()->getModelGroup(group) == NULL) {
00233     std::vector<std::string> names;
00234     return names;
00235   }
00236   return cm_.getKinematicModel()->getModelGroup(group)->getJointModelNames();
00237 }
00238 
00239 void RobotNavigator::updateCurrentJointStateToLastTrajectoryPoint(const trajectory_msgs::JointTrajectory& traj)
00240 {
00241   if(traj.points.size() == 0)
00242   {
00243     ROS_ERROR_STREAM(NODE_NAME<<": No points in trajectory for setting current state");
00244     return;
00245   }
00246 
00247   std::map<std::string, double> joint_vals;
00248   for(unsigned int i = 0; i < traj.joint_names.size(); i++)
00249   {
00250     joint_vals[traj.joint_names[i]] = traj.points.back().positions[i];
00251   }
00252 
00253   current_robot_state_->setKinematicState(joint_vals);
00254 }
00255 
00256 bool RobotNavigator::updateChangesToPlanningScene()
00257 {
00258   ros::WallTime start_time = ros::WallTime::now();
00259   arm_navigation_msgs::SetPlanningSceneDiff::Request planning_scene_req;
00260   arm_navigation_msgs::SetPlanningSceneDiff::Response planning_scene_res;
00261 
00262   revertPlanningScene();
00263 
00264   planning_scene_req.planning_scene_diff = planning_scene_diff_;
00265 
00266   ROS_DEBUG_STREAM(NODE_NAME<<": Getting and setting planning scene");
00267 
00268   if(!set_planning_scene_diff_client_.call(planning_scene_req, planning_scene_res))
00269   {
00270     ROS_WARN_STREAM(NODE_NAME<<": Can't get planning scene");
00271     return false;
00272   }
00273 
00274   current_planning_scene_ = planning_scene_res.planning_scene;
00275   current_robot_state_ = cm_.setPlanningScene(current_planning_scene_);
00276 
00277   if(current_robot_state_ == NULL)
00278   {
00279     ROS_WARN_STREAM(NODE_NAME<<": Problems setting robot kinematic state");
00280     return false;
00281   }
00282 
00283   // Change time stamp to avoid saving sim time.
00284   current_planning_scene_.robot_state.joint_state.header.stamp = ros::Time(ros::WallTime::now().toSec());
00285   ROS_INFO_STREAM(NODE_NAME<<": Setting took " << (ros::WallTime::now()-start_time).toSec());
00286   planning_scene_duration_ += ros::WallTime::now()-start_time;
00287   return true;
00288 }
00289 
00290 bool RobotNavigator::moveArm(const std::string& group_name,const std::vector<double>& joint_positions)
00291 {
00292 
00293   // requesting path plan
00294   ros::WallTime start_time = ros::WallTime::now();
00295   arm_navigation_msgs::GetMotionPlan::Request plan_req;
00296   arm_navigation_msgs::GetMotionPlan::Response plan_res;
00297 
00298   plan_req.motion_plan_request.allowed_planning_time = ros::Duration(20.0f);
00299   plan_req.motion_plan_request.group_name = group_name;
00300 
00301   planning_environment::convertKinematicStateToRobotState(*current_robot_state_,
00302                                                           ros::Time::now(),
00303                                                           cm_.getWorldFrameId(),
00304                                                           plan_req.motion_plan_request.start_state);
00305 
00306   std::vector<std::string> joint_names = getJointNames(group_name);
00307   std::vector<arm_navigation_msgs::JointConstraint>& joint_constraints =  plan_req.motion_plan_request.goal_constraints.joint_constraints;
00308 
00309   joint_constraints.resize(joint_names.size());
00310   for(unsigned int i = 0; i < joint_names.size(); i++)
00311   {
00312     joint_constraints[i].joint_name = joint_names[i];
00313     joint_constraints[i].position = joint_positions[i];
00314     joint_constraints[i].tolerance_above = 0.2f;
00315     joint_constraints[i].tolerance_below = 0.2f;
00316   }
00317 
00318   if(!planning_service_client_.call(plan_req, plan_res))
00319   {
00320     ROS_WARN_STREAM(NODE_NAME<<": Planner service call failed");
00321     return false;
00322   }
00323 
00324   if(plan_res.error_code.val != plan_res.error_code.SUCCESS)
00325   {
00326     ROS_WARN_STREAM(NODE_NAME<<": Planner failed, error code:"<<plan_res.error_code.val);
00327     return false;
00328   }
00329 
00330   motion_planning_duration_ += ros::WallTime::now()-start_time;
00331   start_time = ros::WallTime::now();
00332 
00333   last_mpr_id_ = max_mpr_id_;
00334   max_mpr_id_++;
00335 
00336   // requesting planned trajectory filtering
00337   arm_navigation_msgs::FilterJointTrajectoryWithConstraints::Request filter_req;
00338   arm_navigation_msgs::FilterJointTrajectoryWithConstraints::Response filter_res;
00339 
00340   filter_req.trajectory = plan_res.trajectory.joint_trajectory;
00341   filter_req.start_state = plan_req.motion_plan_request.start_state;
00342   filter_req.group_name = group_name;
00343   filter_req.goal_constraints = plan_req.motion_plan_request.goal_constraints;
00344   filter_req.allowed_time = ros::Duration(4.0);
00345 
00346   if(!trajectory_filter_service_client_.call(filter_req, filter_res)) {
00347     ROS_WARN_STREAM(NODE_NAME<<": Filter service call failed");
00348     return false;
00349   }
00350 
00351   if(filter_res.error_code.val != filter_res.error_code.SUCCESS) {
00352     ROS_WARN_STREAM(NODE_NAME<<": Filter failed");
00353     return false;
00354   }
00355   trajectory_filtering_duration_ += ros::WallTime::now()-start_time;
00356 
00357   // requesting trajectory execution action
00358   trajectories_succeeded_ = false;
00359   TrajectoryExecutionRequest ter;
00360   ter.group_name_ = group_name;
00361   ter.controller_name_ = arm_controller_handler_->getControllerName();
00362   ter.trajectory_ = filter_res.trajectory;
00363   ter.test_for_close_enough_ = false;
00364   ter.failure_time_factor_ = 1000;
00365   ter.max_joint_distance_ = .01;
00366 
00367   std::vector<TrajectoryExecutionRequest> ter_reqs;
00368   ter_reqs.push_back(ter);
00369 
00370   ros::WallTime start_execution = ros::WallTime::now();
00371 
00372   ROS_INFO_STREAM("Arm Trajectory in progress");
00373   trajectory_execution_monitor_.executeTrajectories(ter_reqs,trajectories_finished_function_);
00374 
00375   boost::unique_lock<boost::mutex> lock(execution_mutex_);
00376   execution_completed_.wait(lock);
00377   execution_duration_ += (ros::WallTime::now()-start_execution);
00378 
00379   arm_navigation_msgs::ArmNavigationErrorCodes error_code;
00380   if(trajectories_succeeded_)
00381   {
00382     error_code.val = error_code.SUCCESS;
00383     ROS_INFO_STREAM("Trajectory execution has succeeded");
00384   }
00385   else
00386   {
00387     error_code.val = error_code.PLANNING_FAILED;
00388     ROS_ERROR_STREAM("Trajectory execution has failed");
00389   }
00390 
00391   return trajectories_succeeded_;
00392 }
00393 
00394 bool RobotNavigator::validateJointTrajectory(trajectory_msgs::JointTrajectory &jt)
00395 {
00396         const ros::Duration timeIncrement(1.0f);
00397         ros::Duration currentTime = timeIncrement ;
00398 
00399         for(unsigned int i = 0; i < jt.points.size(); i++)
00400         {
00401                 trajectory_msgs::JointTrajectoryPoint &p = jt.points[i];
00402                 if(p.positions.size() == 0)
00403                 {
00404                         return false; // should at least have position values
00405                 }
00406 
00407                 if(p.velocities.size() == 0)
00408                 {
00409                         p.velocities = std::vector<double>(jt.joint_names.size(),0.0f);
00410                 }
00411 
00412                 if(p.accelerations.size() == 0)
00413                 {
00414                         p.accelerations = std::vector<double>(jt.joint_names.size(),0.0f);
00415                 }
00416 
00417                 p.time_from_start = currentTime;
00418                 currentTime = currentTime+ timeIncrement;
00419         }
00420 
00421         return true;
00422 }
00423 
00424 void RobotNavigator::printJointTrajectory(const trajectory_msgs::JointTrajectory &jt)
00425 {
00426 
00427         ROS_INFO_STREAM(NODE_NAME<<": Total joint points: "<<jt.points.size()<<", total joints "<<jt.joint_names.size());
00428         std::stringstream ss;
00429         for(unsigned int j = 0; j < jt.points.size(); j++)
00430         {
00431                 ROS_INFO_STREAM(NODE_NAME<<": joint point time: "<<jt.points[j].time_from_start.toSec());
00432                 for(unsigned int i = 0;i < jt.joint_names.size(); i++)
00433                 {
00434                         ss<<NODE_NAME<<": joint "<<jt.joint_names[i]<<", pos: ";
00435                         if(jt.points[j].positions.size() == 0)
00436                         {
00437                                 ss<<"NAN";
00438                         }
00439                         else
00440                         {
00441                                 ss<<jt.points[j].positions[i];
00442                         }
00443 
00444                         ss<<", vel: ";
00445                         if(jt.points[j].velocities.size() == 0)
00446                         {
00447                                 ss<<"NAN";
00448                         }
00449                         else
00450                         {
00451                                 ss<<jt.points[j].velocities[i];
00452                         }
00453 
00454                         ss<<", acc: ";
00455                         if(jt.points[j].velocities.size() == 0)
00456                         {
00457                                 ss<<"NAN";
00458                         }
00459                         else
00460                         {
00461                                 ss<<jt.points[j].accelerations[i];
00462                         }
00463 
00464                         ROS_INFO_STREAM(ss.str());
00465                         ss.str("");
00466                 }
00467         }
00468 }
00469 
00470 bool RobotNavigator::performTrajectoryFiltering(const std::string& group_name,trajectory_msgs::JointTrajectory& jt)
00471 {
00472   arm_navigation_msgs::FilterJointTrajectoryWithConstraints::Request filter_req;
00473   arm_navigation_msgs::FilterJointTrajectoryWithConstraints::Response filter_res;
00474 
00475   ROS_INFO_STREAM(NODE_NAME<<": Performing fast filter trajectory");
00476   ROS_INFO_STREAM(NODE_NAME<<": Incoming number of joints: " << jt.joint_names.size());
00477   ROS_INFO_STREAM(NODE_NAME<<": Incoming number of points: " << jt.points.size());
00478 
00479   std::map<std::string, double> jvals;
00480   for(unsigned int i = 0; i < jt.joint_names.size(); i++)
00481   {
00482     jvals[jt.joint_names[i]] = jt.points[0].positions[i];
00483 
00484 //    ROS_INFO_STREAM(NODE_NAME<<": Populating joint names: " << jt.joint_names[i]
00485 //                    << ", jvals: " << jvals[jt.joint_names[i]]
00486 //                    << ", jt.points: " << jt.points[0].positions[i]);
00487   }
00488 
00489   planning_models::KinematicState state(*current_robot_state_);
00490   state.setKinematicState(jvals);
00491 
00492   filter_req.trajectory = jt;
00493   planning_environment::convertKinematicStateToRobotState(state,ros::Time::now(),
00494                   cm_.getWorldFrameId(),filter_req.start_state);
00495   filter_req.group_name = group_name;
00496 
00497   if(!trajectory_filter_service_client_.call(filter_req, filter_res))
00498   {
00499     ROS_WARN_STREAM(NODE_NAME<<": Fast Filter service call failed");
00500     return true;
00501   }
00502 
00503   if (filter_res.trajectory.points.size() != 0)
00504   {
00505       jt = filter_res.trajectory;
00506   }
00507   else
00508   {
00509       ROS_WARN_STREAM(NODE_NAME<<": Filter returned an empty trajectory (ignoring for now)");
00510   }
00511 
00512 
00513   return true;
00514 }
00515 
00516 bool RobotNavigator::moveArmToSide()
00517 {
00518     updateChangesToPlanningScene();
00519 
00520         std::vector<double> joint_angles;
00521         joint_angles.push_back(-1.0410828590393066);
00522         joint_angles.push_back(0.46065822721369176);
00523         joint_angles.push_back(2.4644586717834467);
00524         joint_angles.push_back(0.49449136755439443);
00525         joint_angles.push_back(-0.2900361153401066);
00526         joint_angles.push_back(1.4113548618662812);
00527         joint_angles.push_back(2.3286899342716625);
00528 
00529     return moveArm(arm_group_name_,joint_angles);
00530 }
00531 
00532 void RobotNavigator::addDetectedTableToLocalPlanningScene(const tabletop_object_detector::Table &table)
00533 {
00534   arm_navigation_msgs::CollisionObject table_object;
00535   table_object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::ADD;
00536   table_object.shapes.resize(1);
00537   table_object.shapes[0].type = arm_navigation_msgs::Shape::BOX;
00538   table_object.shapes[0].dimensions.resize(3);
00539   table_object.shapes[0].dimensions[0] = fabs(table.x_max-table.x_min);
00540   table_object.shapes[0].dimensions[1] = fabs(table.y_max-table.y_min);
00541   table_object.shapes[0].dimensions[2] = 0.01;
00542   table_object.id = "table";
00543 
00544   // finding table transform in world coordinates
00545   geometry_msgs::PoseStamped table_world;
00546   cm_.convertPoseGivenWorldTransform(*current_robot_state_,
00547                                      cm_.getWorldFrameId(),
00548                                      table.pose.header,
00549                                      table.pose.pose,
00550                                      table_world);
00551 
00552   table_object.header = table_world.header;
00553 
00554   //set the origin of the table object in the middle of the table
00555   tf::Transform table_trans;
00556   tf::poseMsgToTF(table_world.pose, table_trans);
00557   tf::Transform table_translation;
00558   table_translation.setIdentity();
00559   table_translation.setOrigin( tf::Vector3( (table.x_min + table.x_max)/2.0, (table.y_min + table.y_max)/2.0, 0.0) );
00560   table_trans = table_trans * table_translation;
00561   table_object.poses.resize(1);
00562   tf::poseTFToMsg(table_trans, table_object.poses[0]);
00563 
00564 
00565   ROS_INFO_STREAM(NODE_NAME<<": Table location is " << table_object.poses[0].position.x << " "
00566                   << table_object.poses[0].position.y << " "
00567                   << table_object.poses[0].position.z);
00568 
00569   // saving results from table object
00570   planning_scene_diff_.collision_objects.push_back(table_object);
00571   table_ = table_object;
00572 }
00573 
00574 void RobotNavigator::addDetectedObjectToLocalPlanningScene(arm_navigation_msgs::CollisionObject &obj)
00575 {
00576   obj.operation.operation = arm_navigation_msgs::CollisionObjectOperation::ADD;
00577   planning_scene_diff_.collision_objects.push_back(obj);
00578 }
00579 
00580 void RobotNavigator::addDetectedObjectToLocalPlanningScene(const household_objects_database_msgs::DatabaseModelPoseList& model)
00581 {
00582   arm_navigation_msgs::CollisionObject obj;
00583   obj.id = makeCollisionObjectNameFromModelId(model.model_list[0].model_id);
00584 
00585   // finding pose of object in world coordinates
00586   geometry_msgs::PoseStamped obj_world;
00587   cm_.convertPoseGivenWorldTransform(*current_robot_state_,
00588                                      cm_.getWorldFrameId(),
00589                                      model.model_list[0].pose.header,
00590                                      model.model_list[0].pose.pose,
00591                                      obj_world);
00592 
00593   obj.operation.operation = arm_navigation_msgs::CollisionObjectOperation::ADD;
00594   getMeshFromDatabasePose(model.model_list[0],obj,obj_world);
00595 
00596   ROS_INFO_STREAM(NODE_NAME<<": Pushing back " << obj.id << " frame " << obj.header.frame_id);
00597   planning_scene_diff_.collision_objects.push_back(obj);
00598 }
00599 
00600 bool RobotNavigator::performSegmentation()
00601 {
00602         //  ===================================== saving current time stamp =====================================
00603         ros::WallTime start  = ros::WallTime::now();
00604 
00605         //  ===================================== clearing results from last call =====================================
00606         planning_scene_diff_.collision_objects.clear();
00607         recognized_obj_pose_map_.clear();
00608 
00609         //  ===================================== calling service =====================================
00610         tabletop_object_detector::TabletopSegmentation segmentation_srv;
00611         bool success = seg_srv_.call(segmentation_srv);
00612 
00613         // printing timing
00614         ros::WallTime after_seg = ros::WallTime::now();
00615         ROS_INFO_STREAM(NODE_NAME<<": Seg took " << (after_seg-start).toSec());
00616 
00617         // ===================================== checking results ========================================
00618         if (!success)
00619         {
00620                 ROS_ERROR_STREAM(NODE_NAME<<": Call to segmentation service failed");
00621                 return false;
00622         }
00623 
00624         if (segmentation_srv.response.result != segmentation_srv.response.SUCCESS)
00625         {
00626                 ROS_ERROR_STREAM(NODE_NAME<<": Segmentation service returned error "<< segmentation_srv.response.result);
00627                 return false;
00628         }
00629 
00630         if(segmentation_srv.response.clusters.size() == 0)
00631         {
00632                 ROS_ERROR_STREAM(NODE_NAME<<": Tabletop segmentation returned 0 clusters, exiting");
00633                 return false;
00634         }
00635 
00636         //  ===================================== storing results =====================================
00637         segmentation_results_ = segmentation_srv.response;
00638         segmented_clusters_ = segmentation_srv.response.clusters;
00639 
00640         //  ===================================== updating local planning scene =====================================
00641         addDetectedTableToLocalPlanningScene(segmentation_srv.response.table);
00642 
00643         // ===================================== printing completion info message =====================================
00644         ROS_INFO_STREAM(NODE_NAME<<": Segmentation service succeeded. Detected "<<(int)segmentation_srv.response.clusters.size()<<" clusters");
00645 
00646         return true;
00647 }
00648 
00649 bool RobotNavigator::performRecognition()
00650 {
00651         //  ===================================== saving current time stamp =====================================
00652         ros::WallTime start = ros::WallTime::now();
00653 
00654         //  ===================================== clearing results from last call =====================================
00655         planning_scene_diff_.collision_objects.clear();
00656         recognized_obj_pose_map_.clear();
00657 
00658         //  ===================================== calling service =====================================
00659         tabletop_object_detector::TabletopObjectRecognition recognition_srv;
00660         recognition_srv.request.table = segmentation_results_.table;
00661         recognition_srv.request.clusters = segmented_clusters_;
00662         recognition_srv.request.num_models = 1;
00663         recognition_srv.request.perform_fit_merge = false;
00664 
00665         bool success = rec_srv_.call(recognition_srv);
00666 
00667         // ===================================== checking results ========================================
00668         if (!success)
00669         {
00670                 ROS_ERROR_STREAM(NODE_NAME<<": Call to recognition service " <<recognition_service_.c_str()<<" failed.");
00671                 return false;
00672         }
00673 
00674     if(recognition_srv.response.models.size() == 0)
00675     {
00676         ROS_ERROR_STREAM(NODE_NAME<<": Recognition found no objects");
00677         return false;
00678     }
00679 
00680         //  ===================================== storing results =====================================
00681     recognized_models_ = recognition_srv.response.models;
00682 
00683 
00684     //  ===================================== calling service =====================================
00685     household_objects_database_msgs::GetModelDescription::Request des_req;
00686     household_objects_database_msgs::GetModelDescription::Response des_res;
00687     des_req.model_id = recognized_models_[0].model_list[0].model_id;
00688 
00689     success = object_database_model_description_client_.call(des_req, des_res);
00690 
00691         // ===================================== checking results ========================================
00692         if(!success)
00693         {
00694                 ROS_WARN_STREAM(NODE_NAME<<": Call to objects database for getModelDescription failed");
00695                 return false;
00696         }
00697 
00698         if(des_res.return_code.code != des_res.return_code.SUCCESS)
00699         {
00700                 ROS_WARN_STREAM(NODE_NAME<<":Object database gave non-success code "
00701                                 << des_res.return_code.code
00702                                 << " for model id "
00703                                 << des_req.model_id);
00704                 return false;
00705         }
00706 
00707         //  ===================================== storing results =====================================
00708         recognized_model_description_ = des_res;
00709 
00710         //  ===================================== updating local planning scene =====================================
00711     addDetectedObjectToLocalPlanningScene(recognition_srv.response.models[0]);
00712 
00713         // ===================================== printing completion info message =====================================
00714     ROS_INFO_STREAM(NODE_NAME<<": Recognition took " << (ros::WallTime::now()-start));
00715     ROS_INFO_STREAM(NODE_NAME<<": Got " << recognition_srv.response.models.size() << " models");
00716     recognized_models_ = recognition_srv.response.models;
00717         std::stringstream stdout;
00718         stdout<<"\nRetrieved models:";
00719     BOOST_FOREACH(household_objects_database_msgs::DatabaseModelPose model,recognition_srv.response.models[0].model_list)
00720     {
00721         stdout<<"\n\tModel id: "<<model.model_id;
00722         stdout<<"\n\tPose frame id: "<<model.pose.header.frame_id;
00723         stdout<<"\n\tdetector name: "<<model.detector_name;
00724         stdout<<"\n";
00725     }
00726     ROS_INFO_STREAM(stdout.str());
00727     ROS_INFO_STREAM(NODE_NAME<<" model database service returned description with name: "<<des_res.name);
00728 
00729         return true;
00730 }
00731 
00732 bool RobotNavigator::getMeshFromDatabasePose(const household_objects_database_msgs::DatabaseModelPose &model_pose,
00733                              arm_navigation_msgs::CollisionObject& obj,
00734                              const geometry_msgs::PoseStamped& pose)
00735 {
00736   household_objects_database_msgs::GetModelMesh::Request req;
00737   household_objects_database_msgs::GetModelMesh::Response res;
00738 
00739   req.model_id = model_pose.model_id;
00740   if(!object_database_model_mesh_client_.call(req, res))
00741   {
00742     ROS_WARN_STREAM(NODE_NAME<<": Call to objects database for getMesh failed");
00743     return false;
00744   }
00745 
00746   if(res.return_code.code != res.return_code.SUCCESS)
00747   {
00748     ROS_WARN_STREAM(NODE_NAME<<": Object database gave non-success code " << res.return_code.code << " for model id " << req.model_id);
00749     return false;
00750   }
00751 
00752   obj.header = pose.header;
00753   obj.poses.resize(1);
00754   obj.shapes.resize(1);
00755 
00756   recognized_obj_pose_map_[obj.id] = pose;
00757 
00758   bool use_cylinder = true;
00759 
00760   if(use_cylinder)
00761   {
00762     tf::Transform pose_tf;
00763     tf::poseMsgToTF(pose.pose, pose_tf);
00764 
00765     shapes::Shape* shape = planning_environment::constructObject(res.mesh);
00766     bodies::Body* body = bodies::createBodyFromShape(shape);
00767     body->setPose(pose_tf);
00768 
00769     bodies::BoundingCylinder cyl;
00770     body->computeBoundingCylinder(cyl);
00771 
00772     obj.shapes[0].type = arm_navigation_msgs::Shape::CYLINDER;
00773     obj.shapes[0].dimensions.resize(2);
00774     obj.shapes[0].dimensions[0] = cyl.radius;
00775     obj.shapes[0].dimensions[1] = cyl.length;
00776     tf::poseTFToMsg(cyl.pose, obj.poses[0]);
00777   }
00778   else
00779   {
00780     obj.shapes.resize(1);
00781     obj.shapes[0].type = arm_navigation_msgs::Shape::MESH;
00782     obj.shapes[0] = res.mesh;
00783     obj.poses[0] = pose.pose;
00784   }
00785   return true;
00786 }
00787 
00788 bool RobotNavigator::performPickGraspPlanning()
00789 {
00790         //  ===================================== saving current time stamp =====================================
00791         ros::WallTime start_time = ros::WallTime::now();
00792 
00793         //  ===================================== clearing results from last call =====================================
00794         grasp_pickup_goal_.target.potential_models.clear();
00795         grasp_candidates_.clear();
00796 
00797         //  ===================================== calling service =====================================
00798         // checking available recognized models
00799         if((recognized_models_.size() == 0) || (recognized_models_[0].model_list.size() == 0))
00800         {
00801           return false;
00802         }
00803 
00804         // populating grasp plan request/response
00805         household_objects_database_msgs::DatabaseModelPose modelPose = recognized_models_[0].model_list[0];
00806         object_manipulation_msgs::GraspPlanning::Request request;
00807         object_manipulation_msgs::GraspPlanning::Response response;
00808         std::string modelId = makeCollisionObjectNameFromModelId(modelPose.model_id);
00809 
00810         //modelPose.pose = geometry_msgs::PoseStamped();
00811         //modelPose.pose.pose.orientation.w = 1.0;
00812         modelPose.pose = recognized_obj_pose_map_[modelId];
00813         modelPose.pose.header.frame_id = recognized_model_description_.name; // should be updated during recognition stage
00814         modelPose.pose.header.stamp = ros::Time::now();
00815         request.arm_name = arm_group_name_;
00816         request.target.potential_models.push_back(modelPose);
00817         //request.target.reference_frame_id = segmented_clusters_[0].header.frame_id;
00818         request.target.cluster = segmented_clusters_[0];
00819         request.target.reference_frame_id = segmentation_results_.table.pose.header.frame_id;
00820 
00821         bool success = grasp_planning_client.call(request, response);
00822 
00823         // ===================================== checking results ========================================
00824         if(!success)
00825         {
00826                 ROS_WARN_STREAM(NODE_NAME<<": grasp planning call unsuccessful, exiting");
00827                 return false;
00828         }
00829 
00830         if(response.error_code.value != response.error_code.SUCCESS)
00831         {
00832                 ROS_WARN_STREAM(NODE_NAME<<": grasp planning call returned error code, exiting " << response.error_code.value);
00833                 return false;
00834         }
00835 
00836         if(response.grasps.size() == 0)
00837         {
00838                 ROS_WARN_STREAM(NODE_NAME<<": No grasps returned in response");
00839                 return false;
00840         }
00841         else
00842         {
00843                 ROS_INFO_STREAM(NODE_NAME<<": Grasp Planner Srcv returned "<<response.grasps.size()<<" grasp candidates");
00844         }
00845 
00846         //TODO - actually deal with the different cases here, especially for the cluster planner
00847         if(request.target.reference_frame_id != recognized_model_description_.name ||
00848                   request.target.reference_frame_id != modelPose.pose.header.frame_id)
00849         {
00850           ROS_WARN_STREAM("Cluster does not match recognition");
00851         }
00852 
00853         //  ===================================== storing results =====================================
00854         /* Storing grasp candidates:
00855          *      Grasp poses return by the service define the location of the tcp in terms of the world.
00856          *      However, planning is done with the assumption that the grasp indicate the location
00857          *      of the wrist relative to the object.
00858          */
00859         grasp_candidates_.assign(response.grasps.begin(),response.grasps.end());
00860 
00861         //  =====================================  grasp planning for pick move ==================================
00862         // instantiating needed transforms and poses
00863         tf::Transform object_in_world_tf;
00864         tf::StampedTransform wristInGripperTcp = tf::StampedTransform();
00865         tf::Transform object_in_world_inverse_tf;
00866 
00867         // populating transforms
00868         tf::poseMsgToTF(modelPose.pose.pose, object_in_world_tf);
00869         object_in_world_inverse_tf = object_in_world_tf.inverse();
00870         _TfListener.lookupTransform(gripper_link_name_,wrist_link_name_,ros::Time(0),wristInGripperTcp);
00871 
00872         // applying transformation to grasp pose so that the arm wrist relative to the object is obtained
00873         for(unsigned int i = 0; i < grasp_candidates_.size(); i++)
00874         {
00875                 tf::Transform grasp_in_world_tf;
00876                 tf::poseMsgToTF(grasp_candidates_[i].grasp_pose, grasp_in_world_tf);
00877                 tf::poseTFToMsg(object_in_world_inverse_tf*(grasp_in_world_tf*wristInGripperTcp),
00878                           grasp_candidates_[i].grasp_pose);
00879         }
00880 
00881         // updating grasp pickup goal data
00882         grasp_pickup_goal_.arm_name = arm_group_name_;
00883         grasp_pickup_goal_.collision_object_name = modelId;
00884         grasp_pickup_goal_.lift.direction.header.frame_id = cm_.getWorldFrameId();
00885         grasp_pickup_goal_.target.reference_frame_id = modelId;
00886         grasp_pickup_goal_.target.cluster = segmented_clusters_[0];
00887         grasp_pickup_goal_.target.potential_models.push_back(modelPose);
00888 
00889         // generating grasp pick sequence
00890         updateChangesToPlanningScene();
00891         grasp_pick_sequence_.clear();
00892         std::vector<object_manipulation_msgs::Grasp> valid_grasps;
00893         if(!createPickMoveSequence(grasp_pickup_goal_,grasp_candidates_,grasp_pick_sequence_,valid_grasps))
00894         {
00895                 ROS_ERROR_STREAM(NODE_NAME<<": Failed to create valid grasp pick sequence");
00896                 return false;
00897         }
00898         grasp_candidates_.assign(valid_grasps.begin(),valid_grasps.end());
00899         return true;
00900 }
00901 
00902 bool RobotNavigator::performPlaceGraspPlanning()
00903 {
00904         using namespace manipulation_utils;
00905 
00906         //      updating grasp place goal data
00907         grasp_place_goal_.arm_name = arm_group_name_;
00908         grasp_place_goal_.approach.direction.header.frame_id = cm_.getWorldFrameId();
00909         grasp_place_goal_.collision_object_name = "attached_"+current_grasped_object_name_[arm_group_name_];
00910 
00911         // creating candidate grasp place poses
00912         std::vector<geometry_msgs::PoseStamped> placePoses;
00913         if(!createCandidateGoalPoses(placePoses))
00914         {
00915                 ROS_ERROR_STREAM(NODE_NAME<<": Could not create valid place poses");
00916                 return false;
00917         }
00918 
00919         // finding valid grasp place sequence
00920         updateChangesToPlanningScene();
00921         bool found_valid = false;
00922         geometry_msgs::Pose valid_grasp_place_pose; // will keep only valid grasp pick sequence which grasp yields a valid place sequence;
00923         std::vector<object_manipulation_msgs::Grasp> valid_grasps;
00924         std::vector<object_manipulator::GraspExecutionInfo> valid_pick_sequence;
00925         std::vector<object_manipulator::PlaceExecutionInfo> valid_place_sequence;
00926 
00927         // finding pose of wrist relative to object
00928         tf::StampedTransform wrist_in_tcp_tf, wrist_in_obj_tf;// wrist pose relative to gripper
00929         _TfListener.lookupTransform(gripper_link_name_,wrist_link_name_,ros::Time(0),wrist_in_tcp_tf);
00930         for(std::size_t i = 0; i < grasp_candidates_.size(); i++)
00931         {
00932                 // storing tcp to object pose in grasp place goal
00933                 tf::poseMsgToTF(grasp_candidates_[i].grasp_pose,wrist_in_obj_tf);
00934                 tf::poseTFToMsg(wrist_in_obj_tf*(wrist_in_tcp_tf.inverse()),grasp_place_goal_.grasp.grasp_pose);
00935                 manipulation_utils::rectifyPoseZDirection(grasp_place_goal_.grasp.grasp_pose,
00936                                 PLACE_RECTIFICATION_TF,grasp_place_goal_.grasp.grasp_pose);
00937                 if(createPlaceMoveSequence(grasp_place_goal_,placePoses,valid_place_sequence))
00938                 {
00939                         if(!found_valid)
00940                         {
00941                                 // storing first valid
00942                                 grasp_place_sequence_.assign(valid_place_sequence.begin(),valid_place_sequence.end());
00943                                 valid_grasp_place_pose = grasp_place_goal_.grasp.grasp_pose;
00944                         }
00945 
00946                         found_valid = true;
00947                         valid_grasps.push_back(grasp_candidates_[i]);
00948                         valid_pick_sequence.push_back(grasp_pick_sequence_[i]);
00949 
00950                 }
00951         }
00952 
00953         if(!found_valid)
00954         {
00955                 ROS_ERROR_STREAM(NODE_NAME<<": Failed to create valid grasp place sequence");
00956                 return false;
00957         }
00958         else
00959         {
00960                 // storing valid pick sequences
00961                 grasp_candidates_.assign(valid_grasps.begin(),valid_grasps.end());
00962                 grasp_pick_sequence_.assign(valid_pick_sequence.begin(),valid_pick_sequence.end());
00963                 grasp_place_goal_.grasp.grasp_pose = valid_grasp_place_pose;
00964         }
00965 
00966 
00967         //  ===================================== updating local planning scene =====================================
00968         // updating gripper (not sure if this is necessary)
00969         tf::Transform first_grasp_in_world_tf;
00970         tf::poseMsgToTF(grasp_candidates_[0].grasp_pose, first_grasp_in_world_tf);
00971         planning_models::KinematicState state(*current_robot_state_);
00972         state.updateKinematicStateWithLinkAt(gripper_link_name_, first_grasp_in_world_tf);
00973 
00974         return true;
00975 }
00976 
00977 bool RobotNavigator::performGraspPlanning()
00978 {
00979 
00980         return performPickGraspPlanning() && performPlaceGraspPlanning();
00981 //      //  ===================================== saving current time stamp =====================================
00982 //      ros::WallTime start_time = ros::WallTime::now();
00983 //
00984 //      //  ===================================== clearing results from last call =====================================
00985 //      grasp_pickup_goal_.target.potential_models.clear();
00986 //      grasp_candidates_.clear();
00987 //
00988 //      //  ===================================== calling service =====================================
00989 //      // checking available recognized models
00990 //      if((recognized_models_.size() == 0) || (recognized_models_[0].model_list.size() == 0))
00991 //      {
00992 //        return false;
00993 //      }
00994 //
00995 //      // populating grasp plan request/response
00996 //      household_objects_database_msgs::DatabaseModelPose modelPose = recognized_models_[0].model_list[0];
00997 //      object_manipulation_msgs::GraspPlanning::Request request;
00998 //      object_manipulation_msgs::GraspPlanning::Response response;
00999 //      std::string modelId = makeCollisionObjectNameFromModelId(modelPose.model_id);
01000 //
01001 //      //modelPose.pose = geometry_msgs::PoseStamped();
01002 //      //modelPose.pose.pose.orientation.w = 1.0;
01003 //      modelPose.pose = recognized_obj_pose_map_[modelId];
01004 //      modelPose.pose.header.frame_id = recognized_model_description_.name; // should be updated during recognition stage
01005 //      modelPose.pose.header.stamp = ros::Time::now();
01006 //      request.arm_name = arm_group_name_;
01007 //      request.target.potential_models.push_back(modelPose);
01008 //      request.target.reference_frame_id = segmented_clusters_[0].header.frame_id;
01009 //      request.target.cluster = segmented_clusters_[0];
01010 //
01011 //      bool success = grasp_planning_client.call(request, response);
01012 //
01013 //      // ===================================== checking results ========================================
01014 //      if(!success)
01015 //      {
01016 //              ROS_WARN_STREAM(NODE_NAME<<": grasp planning call unsuccessful, exiting");
01017 //              return false;
01018 //      }
01019 //
01020 //      if(response.error_code.value != response.error_code.SUCCESS)
01021 //      {
01022 //              ROS_WARN_STREAM(NODE_NAME<<": grasp planning call returned error code, exiting " << response.error_code.value);
01023 //              return false;
01024 //      }
01025 //
01026 //      if(response.grasps.size() == 0)
01027 //      {
01028 //              ROS_WARN_STREAM(NODE_NAME<<": No grasps returned in response");
01029 //              return false;
01030 //      }
01031 //
01032 //      //TODO - actually deal with the different cases here, especially for the cluster planner
01033 //      if(request.target.reference_frame_id != recognized_model_description_.name ||
01034 //                request.target.reference_frame_id != modelPose.pose.header.frame_id)
01035 //      {
01036 //        ROS_WARN_STREAM("Cluster does not match recognition");
01037 //      }
01038 //
01039 //      //  ===================================== storing results =====================================
01040 //      /* Storing grasp candidates:
01041 //       *      Grasp poses return by the service define the location of the tcp in terms of the world.
01042 //       *      However, planning is done with the assumption that the grasp indicate the location
01043 //       *      of the wrist relative to the object.
01044 //       */
01045 //      grasp_candidates_.assign(response.grasps.begin(),response.grasps.end());
01046 //
01047 //      //  =====================================  grasp planning for pick move ==================================
01048 //      // instantiating needed transforms and poses
01049 //      tf::Transform object_in_world_tf;
01050 //      tf::StampedTransform wristInGripperTcp = tf::StampedTransform();
01051 //      tf::Transform object_in_world_inverse_tf;
01052 //
01053 //      // populating transforms
01054 //      tf::poseMsgToTF(modelPose.pose.pose, object_in_world_tf);
01055 //      object_in_world_inverse_tf = object_in_world_tf.inverse();
01056 //      _TfListener.lookupTransform(gripper_link_name_,wrist_link_name_,ros::Time(0),wristInGripperTcp);
01057 //
01058 //      // applying transformation to grasp pose so that the arm wrist relative to the object is obtained
01059 //      for(unsigned int i = 0; i < grasp_candidates_.size(); i++)
01060 //      {
01061 //              tf::Transform grasp_in_world_tf;
01062 //              tf::poseMsgToTF(grasp_candidates_[i].grasp_pose, grasp_in_world_tf);
01063 //              tf::poseTFToMsg(object_in_world_inverse_tf*(grasp_in_world_tf*wristInGripperTcp),
01064 //                        grasp_candidates_[i].grasp_pose);
01065 //      }
01066 //
01067 //      // updating grasp pickup goal data
01068 //      grasp_pickup_goal_.arm_name = arm_group_name_;
01069 //      grasp_pickup_goal_.collision_object_name = modelId;
01070 //      grasp_pickup_goal_.lift.direction.header.frame_id = cm_.getWorldFrameId();
01071 //      grasp_pickup_goal_.target.reference_frame_id = modelId;
01072 //      grasp_pickup_goal_.target.cluster = segmented_clusters_[0];
01073 //      grasp_pickup_goal_.target.potential_models.push_back(modelPose);
01074 //
01075 //      // generating grasp pick sequence
01076 //      updateChangesToPlanningScene();
01077 //      grasp_pick_sequence_.clear();
01078 //      std::vector<object_manipulation_msgs::Grasp> valid_grasps;
01079 //      if(!createPickMoveSequence(grasp_pickup_goal_,grasp_candidates_,grasp_pick_sequence_,valid_grasps))
01080 //      {
01081 //              ROS_ERROR_STREAM(NODE_NAME<<": Failed to create valid grasp pick sequence");
01082 //              return false;
01083 //      }
01084 //      grasp_candidates_.assign(valid_grasps.begin(),valid_grasps.end());
01085 //
01086 //
01087 //      //  ==================================  grasp planning for place move ================================
01088 //      //      updating grasp place goal data
01089 //      grasp_place_goal_.arm_name = arm_group_name_;
01090 //      grasp_place_goal_.approach.direction.header.frame_id = cm_.getWorldFrameId();
01091 //      grasp_place_goal_.collision_object_name = "attached_"+current_grasped_object_name_[arm_group_name_];
01092 //
01093 //      // creating candidate grasp place poses
01094 //      std::vector<geometry_msgs::PoseStamped> placePoses;
01095 //      if(!createCandidateGoalPoses(placePoses))
01096 //      {
01097 //              ROS_ERROR_STREAM(NODE_NAME<<": Could not create valid place poses");
01098 //              return false;
01099 //      }
01100 //
01101 //      // finding valid grasp place sequence
01102 //      updateChangesToPlanningScene();
01103 //      bool found_valid = false;
01104 //      valid_grasps.clear(); // will keep only valid grasp pick sequence which grasp yields a valid place sequence;
01105 //      geometry_msgs::Pose valid_grasp_place_pose;
01106 //      std::vector<object_manipulator::GraspExecutionInfo> valid_pick_sequence;
01107 //      std::vector<object_manipulator::PlaceExecutionInfo> valid_place_sequence;
01108 //
01109 //      // finding pose of wrist relative to object
01110 //      tf::StampedTransform wrist_in_tcp_tf, wrist_in_obj_tf;// wrist pose relative to gripper
01111 //      _TfListener.lookupTransform(gripper_link_name_,wrist_link_name_,ros::Time(0),wrist_in_tcp_tf);
01112 //      for(std::size_t i = 0; i < grasp_candidates_.size(); i++)
01113 //      {
01114 //              tf::poseMsgToTF(grasp_candidates_[i].grasp_pose,wrist_in_obj_tf);
01115 //              tf::poseTFToMsg(wrist_in_obj_tf*(wrist_in_tcp_tf.inverse()),grasp_place_goal_.grasp.grasp_pose);
01116 //              if(createPlaceMoveSequence(grasp_place_goal_,placePoses,valid_place_sequence))
01117 //              {
01118 //                      if(!found_valid)
01119 //                      {
01120 //                              // storing first valid
01121 //                              grasp_place_sequence_.assign(valid_place_sequence.begin(),valid_place_sequence.end());
01122 //                              valid_grasp_place_pose = grasp_place_goal_.grasp.grasp_pose;
01123 //                      }
01124 //
01125 //                      found_valid = true;
01126 //                      valid_grasps.push_back(grasp_candidates_[i]);
01127 //                      valid_pick_sequence.push_back(grasp_pick_sequence_[i]);
01128 //                      grasp_place_goal_.grasp.grasp_pose = valid_grasp_place_pose;
01129 //              }
01130 //      }
01131 //
01132 //      if(!found_valid)
01133 //      {
01134 //              ROS_ERROR_STREAM(NODE_NAME<<": Failed to create valid grasp place sequence");
01135 //              return false;
01136 //      }
01137 //      else
01138 //      {
01139 //              // storing valid pick sequences
01140 //              grasp_candidates_.assign(valid_grasps.begin(),valid_grasps.end());
01141 //              grasp_pick_sequence_.assign(valid_pick_sequence.begin(),valid_pick_sequence.end());
01142 //      }
01143 //
01144 //
01145 //      //  ===================================== updating local planning scene =====================================
01146 //      // updating gripper (not sure if this is necessary)
01147 //      tf::Transform first_grasp_in_world_tf;
01148 //      tf::poseMsgToTF(response.grasps[0].grasp_pose, first_grasp_in_world_tf);
01149 //      planning_models::KinematicState state(*current_robot_state_);
01150 //      state.updateKinematicStateWithLinkAt(gripper_link_name_, first_grasp_in_world_tf);
01151 //
01152 //      // ===================================== printing completion info message =====================================
01153 //      ROS_INFO_STREAM(NODE_NAME<<": Grasp is " << response.grasps[0].grasp_pose.position.x << " "
01154 //                        << response.grasps[0].grasp_pose.position.y << " "
01155 //                        << response.grasps[0].grasp_pose.position.z);
01156 //
01157 //      return true;
01158 }
01159 
01160 bool RobotNavigator::createPickMoveSequence(
01161                 const object_manipulation_msgs::PickupGoal &pickupGoal,
01162                 const std::vector<object_manipulation_msgs::Grasp> &grasps_candidates,
01163                 std::vector<object_manipulator::GraspExecutionInfo> &grasp_sequence,
01164                 std::vector<object_manipulation_msgs::Grasp> &valid_grasps)
01165 {
01166         // results data
01167         std::vector<object_manipulator::GraspExecutionInfo> candidate_sequence;
01168 
01169     ROS_INFO_STREAM(NODE_NAME<<": Evaluating grasps with grasp tester");
01170         planning_models::KinematicState kinematicState(*current_robot_state_);
01171         grasp_tester_->setPlanningSceneState(&kinematicState);
01172         grasp_tester_->testGrasps(pickupGoal,grasps_candidates,candidate_sequence,true);
01173 
01174         // keeping successful grasp candidates
01175         bool found_valid = false;
01176         for(std::size_t i = 0; i < candidate_sequence.size(); i++)
01177         {
01178                 if(candidate_sequence[i].result_.result_code == object_manipulation_msgs::GraspResult::SUCCESS)
01179                 {
01180                         grasp_sequence.push_back(candidate_sequence[i]);
01181                         valid_grasps.push_back(grasp_candidates_[i]);
01182                         found_valid = true;
01183                 }
01184         }
01185 
01186     ROS_INFO_STREAM(NODE_NAME<<": Returned "<< grasp_sequence.size() <<" grasps candidates ");
01187     return found_valid;
01188 }
01189 
01190 bool RobotNavigator::createPlaceMoveSequence(const object_manipulation_msgs::PlaceGoal &placeGoal,
01191                                 const std::vector<geometry_msgs::PoseStamped> &place_poses,
01192                                 std::vector<object_manipulator::PlaceExecutionInfo> &place_sequence)
01193 {
01194         // result data
01195         std::vector<object_manipulator::PlaceExecutionInfo> candidate_sequence;
01196 
01197         // find transform of wrist relative to the gripper's tcp
01198         tf::StampedTransform gripperTcpToWrist = tf::StampedTransform();
01199         planning_models::KinematicState state(*current_robot_state_);
01200         _TfListener.lookupTransform(gripper_link_name_,wrist_link_name_,ros::Time(0),gripperTcpToWrist);
01201         place_tester_->setTcpToWristTransform(gripperTcpToWrist);
01202         place_tester_->setPlanningSceneState(&state);
01203         place_tester_->testPlaces(placeGoal, place_poses, candidate_sequence, true);
01204 
01205         // keeping successful place candidates
01206         bool found_valid = false;
01207         std::vector<object_manipulator::PlaceExecutionInfo>::iterator i;
01208         for(i = candidate_sequence.begin(); i != candidate_sequence.end();i++)
01209         {
01210                 if(i->result_.result_code == object_manipulation_msgs::PlaceLocationResult::SUCCESS)
01211                 {
01212                         place_sequence.push_back(*i);
01213                         found_valid = true;
01214                 }
01215         }
01216 
01217         return found_valid;
01218 }
01219 
01220 bool RobotNavigator::moveArmThroughPickSequence()
01221 {
01222 
01223         using namespace manipulation_utils;
01224         // pushing local changes to planning scene
01225         updateChangesToPlanningScene();
01226 
01227         // grasp planning
01228         bool success = performGraspPlanning();
01229         if(!success)
01230         {
01231                 ROS_INFO_STREAM(NODE_NAME<<": Grasp Pick attempt aborted");
01232                 return false;
01233         }
01234 
01235         // transform for recalculation of results more than one grasp attempt is made
01236         tf::StampedTransform wrist_in_tcp_tf;// wrist pose relative to gripper
01237         tf::Transform wrist_in_obj_tf;
01238         _TfListener.lookupTransform(gripper_link_name_,wrist_link_name_,ros::Time(0),wrist_in_tcp_tf);
01239 
01240         // try each successful grasp
01241         success = false;
01242         int counter = 0; // index to grasp array
01243         BOOST_FOREACH(object_manipulator::GraspExecutionInfo graspMoves,grasp_pick_sequence_)
01244         {
01245                 ROS_INFO_STREAM(NODE_NAME<<": Attempting Grasp Pick sequence");
01246                 success = attemptGraspSequence(arm_group_name_,graspMoves);
01247                 if(!success)
01248                 {
01249                         if(++counter == (int)grasp_pick_sequence_.size()) return false; // no more valid sequences
01250 
01251                         tf::poseMsgToTF(grasp_candidates_[counter].grasp_pose,wrist_in_obj_tf);
01252                         tf::poseTFToMsg(wrist_in_obj_tf*(wrist_in_tcp_tf.inverse()),grasp_place_goal_.grasp.grasp_pose);
01253                         manipulation_utils::rectifyPoseZDirection(grasp_place_goal_.grasp.grasp_pose,
01254                                                         PLACE_RECTIFICATION_TF,grasp_place_goal_.grasp.grasp_pose);
01255 
01256                         // recomputing candidate grasp place poses
01257                         std::vector<geometry_msgs::PoseStamped> placePoses;
01258                         if(!createCandidateGoalPoses(placePoses) || !createPlaceMoveSequence(grasp_place_goal_,placePoses,grasp_place_sequence_))
01259                         {
01260                                 ROS_ERROR_STREAM(NODE_NAME<<": Could not grasp place solution for current grasp pick");
01261                                 return false;
01262                         }
01263 
01264                         ROS_INFO_STREAM(NODE_NAME<<": Grasp pick move failed, try next");
01265                         //return false;
01266                         continue;
01267                 }
01268                 else
01269                 {
01270                   ROS_INFO_STREAM(NODE_NAME<<": Grasp pick move succeeded");
01271                 }
01272 
01273                 // updating attached object marker pose
01274                 if(hasMarker(MARKER_ATTACHED_OBJECT))
01275                 {
01276                         visualization_msgs::Marker &m = getMarker(MARKER_ATTACHED_OBJECT);
01277                         tf::poseTFToMsg(wrist_in_obj_tf.inverse(),m.pose);
01278                         m.header.frame_id = gripper_link_name_;
01279                         addMarker(MARKER_ATTACHED_OBJECT,m);
01280                 }
01281 
01282                 counter++;
01283         }
01284 
01285         return success;
01286 }
01287 
01288 bool RobotNavigator::moveArmThroughPlaceSequence()
01289 {
01290         // resetting scene
01291         updateChangesToPlanningScene();
01292 
01293         // starting timer
01294         ros::WallTime start_time = ros::WallTime::now();
01295 
01296         // checking grasp
01297         if(!object_in_hand_map_[arm_group_name_])
01298         {
01299                 ROS_WARN_STREAM(NODE_NAME<<": No object in hand reported, continuing");
01300                 //return false;
01301         }
01302 
01303 //      updating grasp place data
01304         grasp_place_goal_.collision_object_name = "attached_"+current_grasped_object_name_[arm_group_name_];
01305 
01306         // try each place sequence candidate
01307         bool success = false;
01308         BOOST_FOREACH(object_manipulator::PlaceExecutionInfo placeMove,grasp_place_sequence_)
01309         {
01310                 success = attemptPlaceSequence(arm_group_name_,placeMove);
01311                 if(success)
01312                 {
01313                         ROS_INFO_STREAM(NODE_NAME<<": Grasp place move succeeded");
01314                 }
01315                 else
01316                 {
01317                         ROS_ERROR_STREAM(NODE_NAME<<"Grasp place move failed, , trying next");
01318                         //return false;
01319                         continue;
01320                 }
01321 
01322                 break;
01323         }
01324 
01325         return success;
01326 }
01327 
01328 void RobotNavigator::addMarker(std::string name,visualization_msgs::Marker &marker)
01329 {
01330         if(marker_map_.count(name) > 0)
01331         {
01332                 marker.id = marker_map_[name].id;
01333                 marker_map_[name] = marker;
01334         }
01335         else
01336         {
01337                 marker.id = marker_map_.size();
01338                 marker_map_.insert(std::make_pair(name,marker));
01339         }
01340 }
01341 
01342 void RobotNavigator::addMarker(std::string name,visualization_msgs::MarkerArray &markers)
01343 {
01344         std::stringstream nameStream;
01345         for(unsigned int i = 0; i < markers.markers.size(); i++)
01346         {
01347                 nameStream<<name<<i;
01348                 addMarker(nameStream.str(),markers.markers[i]);
01349                 nameStream.str("");
01350         }
01351 }
01352 
01353 bool RobotNavigator::hasMarker(std::string name)
01354 {
01355         if(marker_map_.count(name) > 0)
01356         {
01357                 return true;
01358         }
01359         else
01360         {
01361                 return false;
01362         }
01363 }
01364 
01365 visualization_msgs::Marker& RobotNavigator::getMarker(std::string name)
01366 {
01367         return marker_map_[name];
01368 }
01369 
01370 void RobotNavigator::callbackPublishMarkers(const ros::TimerEvent &evnt)
01371 {
01372         for(std::map<std::string,visualization_msgs::Marker>::iterator i = marker_map_.begin(); i != marker_map_.end(); i++)
01373         {
01374                 visualization_msgs::Marker &m = i->second;
01375                 m.header.stamp = ros::Time::now();
01376                 marker_publisher_.publish(m);
01377         }
01378 }
01379 
01380 void RobotNavigator::attachCollisionObjectCallback(const std::string& group_name)
01381 {
01382   attachCollisionObject(group_name,
01383                         current_grasped_object_name_[group_name],
01384                         current_grasp_map_[group_name]);
01385   object_in_hand_map_[group_name] = true;
01386 }
01387 
01388 void RobotNavigator::detachCollisionObjectCallback(const std::string& group_name)
01389 {
01390   detachCollisionObject(group_name,
01391                         current_place_location_,
01392                         current_grasp_map_[group_name]);
01393   object_in_hand_map_[group_name] = false;
01394   current_grasped_object_name_.erase(group_name);
01395   current_grasp_map_.erase(group_name);
01396 }
01397 
01398 bool RobotNavigator::attemptGraspSequence(const std::string& group_name,
01399                           const object_manipulator::GraspExecutionInfo& gei,
01400                           bool performRecoveryMove)
01401 {
01402 
01403   std::vector<std::string> segment_names;
01404   std::vector< boost::function<bool(TrajectoryExecutionDataVector)> > callbacks;
01405 
01406   // commanding gripper release
01407   std::vector<TrajectoryExecutionRequest> ter_reqs;
01408   TrajectoryExecutionRequest gripper_ter;
01409   gripper_ter.group_name_ = gripper_group_name_;
01410   gripper_ter.controller_name_ = grasp_action_service_;
01411   gripper_ter.trajectory_ = getGripperTrajectory(object_manipulation_msgs::GraspHandPostureExecutionGoal::RELEASE);
01412   gripper_ter.failure_ok_ = false;
01413   gripper_ter.test_for_close_enough_ = false;
01414   //gripper_ter.monitor_overshoot_ = false;
01415   ter_reqs.push_back(gripper_ter);
01416 
01417   ros::WallTime start_execution = ros::WallTime::now();
01418   ROS_INFO_STREAM(NODE_NAME << ": Gripper Release trajectory in progress");
01419   //trajectory_execution_monitor_.executeTrajectories(ter_reqs,trajectories_finished_function_);
01420   trajectory_execution_monitor_.executeTrajectories(ter_reqs,grasp_action_finished_function_);
01421   {
01422     boost::unique_lock<boost::mutex> lock(execution_mutex_);
01423     execution_completed_.wait(lock);
01424   }
01425 
01426   execution_duration_ += (ros::WallTime::now()-start_execution);
01427   ROS_INFO_STREAM( NODE_NAME << ": Gripper Release trajectory completed");
01428   ter_reqs.clear();
01429 
01430   // moving arm from current configuration to pre-grasp configuration
01431   updateCurrentJointStateToLastTrajectoryPoint(last_trajectory_execution_data_vector_.back().recorded_trajectory_);
01432   ROS_INFO_STREAM(NODE_NAME << ": Moving arm to beginning of pick trajectory");
01433   if(!moveArm(group_name, gei.approach_trajectory_.points[0].positions))
01434   {
01435     return false;
01436   }
01437   ROS_INFO_STREAM(NODE_NAME << ": Move completed");
01438   trajectories_succeeded_ = false;
01439 
01440   // setting up gripper pre-grasp
01441   gripper_ter.trajectory_ = getGripperTrajectory(object_manipulation_msgs::GraspHandPostureExecutionGoal::PRE_GRASP);
01442   validateJointTrajectory(gripper_ter.trajectory_);
01443   ter_reqs.push_back(gripper_ter);
01444   segment_names.push_back("Pre-grasp");
01445   callbacks.push_back(grasp_action_finished_function_);
01446 
01447   // setting up approach move
01448   TrajectoryExecutionRequest arm_ter;
01449   arm_ter.group_name_ = group_name;
01450   arm_ter.controller_name_ = arm_controller_handler_->getControllerName();
01451   arm_ter.trajectory_ = gei.approach_trajectory_;
01452   validateJointTrajectory(arm_ter.trajectory_);
01453   performTrajectoryFiltering(arm_ter.group_name_, arm_ter.trajectory_);
01454   arm_ter.test_for_close_enough_ = false;
01455   arm_ter.monitor_overshoot_ = false;
01456   arm_ter.min_overshoot_time_ = ros::Duration(0.0f);
01457   arm_ter.max_overshoot_time_ = ros::Duration(5.0f);
01458   arm_ter.failure_ok_ = false;
01459   arm_ter.max_joint_distance_ = .1;
01460   arm_ter.failure_time_factor_ = 1000;
01461   arm_ter.callback_function_ = boost::bind(&RobotNavigator::attachCollisionObjectCallback, this, _1);
01462   ter_reqs.push_back(arm_ter);
01463   segment_names.push_back("Approach");
01464   callbacks.push_back(trajectories_finished_function_);
01465 
01466   // setting up gripper grasp
01467   gripper_ter.trajectory_ = getGripperTrajectory(object_manipulation_msgs::GraspHandPostureExecutionGoal::GRASP);
01468   validateJointTrajectory(gripper_ter.trajectory_);
01469   ter_reqs.push_back(gripper_ter);
01470   segment_names.push_back("Grasp");
01471   callbacks.push_back(grasp_action_finished_function_);
01472 
01473   // updating attached  marker operation
01474   if(hasMarker(MARKER_ATTACHED_OBJECT))
01475   {
01476           visualization_msgs::Marker &m = getMarker(MARKER_ATTACHED_OBJECT);
01477           m.action = visualization_msgs::Marker::ADD;
01478           addMarker(MARKER_ATTACHED_OBJECT,m);
01479   }
01480 
01481   //setting up lift move
01482   arm_ter.trajectory_ = gei.lift_trajectory_;
01483   validateJointTrajectory(arm_ter.trajectory_);
01484   performTrajectoryFiltering(group_name, arm_ter.trajectory_);
01485   arm_ter.callback_function_ = NULL;
01486   ter_reqs.push_back(arm_ter);
01487   segment_names.push_back("Lift");
01488   callbacks.push_back(trajectories_finished_function_);
01489 
01490   /*
01491    * executing all trajectories
01492    * currently this is the only way to execute multiple trajectories in sequence, since the executeTrajectories
01493    * method can only handle a single trajectory at a time.
01494    */
01495   start_execution = ros::WallTime::now();
01496   ROS_INFO_STREAM(" Starting Execution of trajectories");
01497   for(unsigned int i = 0;i < ter_reqs.size(); i++)
01498   {
01499           std::vector<TrajectoryExecutionRequest> tempRequest;
01500           tempRequest.push_back(ter_reqs[i]);
01501           ROS_INFO_STREAM("\t- "<<segment_names[i] <<" trajectory in progress");
01502 //        trajectory_execution_monitor_.executeTrajectories(tempRequest,
01503 //                                                                                                              trajectories_finished_function_);
01504           trajectory_execution_monitor_.executeTrajectories(tempRequest,callbacks[i]);
01505           {
01506                   boost::unique_lock<boost::mutex> lock(execution_mutex_);
01507                   execution_completed_.wait(lock);
01508 
01509                   if(trajectories_succeeded_)
01510                   {
01511                           ROS_INFO_STREAM("\t- "<<segment_names[i] <<" trajectory completed");
01512                   }
01513                   else
01514                   {
01515                           ROS_ERROR_STREAM("\t- "<<segment_names[i] <<" trajectory interrupted, aborting pick move sequence");
01516                           break;
01517                   }
01518           }
01519 
01520   }
01521 
01522   // moving arm to start of approach move and commanding a grasp release
01523   if(!trajectories_succeeded_ && performRecoveryMove)
01524   {
01525           updateCurrentJointStateToLastTrajectoryPoint(last_trajectory_execution_data_vector_.back().recorded_trajectory_);
01526 
01527           // moving arm back to start of pick move
01528           ROS_WARN_STREAM(" Starting recovery move");
01529           ROS_WARN_STREAM("\t- Moving arm to beginning of approach move trajectory");
01530           if(!moveArm(group_name, gei.approach_trajectory_.points[0].positions))
01531           {
01532                   ROS_ERROR_STREAM("\t-"<< "Move start pose failed, aborting recovery move");
01533                   return false;
01534           }
01535 
01536           // request gripper release command
01537           object_manipulation_msgs::GraspHandPostureExecutionGoal graspGoal;
01538           graspGoal.goal = object_manipulation_msgs::GraspHandPostureExecutionGoal::RELEASE;
01539           ROS_WARN_STREAM("\t- Requesting grasp release");
01540           grasp_exec_action_client_->sendGoal(graspGoal);
01541           if(!grasp_exec_action_client_->waitForResult(ros::Duration(2.0f)))
01542           {
01543                   ROS_ERROR_STREAM(" Release request timeout, aborting recovery move");
01544           }
01545 
01546           ROS_WARN_STREAM(" Completed recovery move");
01547           return false;
01548   }
01549 
01550   ROS_INFO_STREAM("Finished executing all trajectories");
01551   execution_duration_ += (ros::WallTime::now()-start_execution);
01552   return trajectories_succeeded_ ;
01553 }
01554 
01555 bool RobotNavigator::attemptPlaceSequence(const std::string& group_name,
01556                           const object_manipulator::PlaceExecutionInfo& pei) {
01557   std::vector<TrajectoryExecutionRequest> ter_reqs;
01558 
01559   // moving arm to beginning of place move
01560   if(!moveArm(group_name,pei.descend_trajectory_.points[0].positions))
01561   {
01562     return false;
01563   }
01564 
01565   trajectories_succeeded_ = false;
01566   std::vector<std::string> segment_names;
01567   std::vector<boost::function<bool(TrajectoryExecutionDataVector)> > callbacks;
01568 
01569   // setting up descend move
01570   TrajectoryExecutionRequest arm_ter;
01571   arm_ter.group_name_ = group_name;
01572   arm_ter.controller_name_ = arm_controller_handler_->getControllerName();
01573   arm_ter.trajectory_ = pei.descend_trajectory_;
01574   validateJointTrajectory(arm_ter.trajectory_);
01575   performTrajectoryFiltering(group_name, arm_ter.trajectory_);
01576   arm_ter.failure_ok_ = false;
01577   arm_ter.monitor_overshoot_ = false;
01578   arm_ter.min_overshoot_time_ = ros::Duration(0.0f);
01579   arm_ter.max_overshoot_time_ = ros::Duration(5.0f);
01580   arm_ter.max_joint_distance_ = .1;
01581   arm_ter.failure_time_factor_ = 1000;
01582   arm_ter.callback_function_ = boost::bind(&RobotNavigator::detachCollisionObjectCallback, this, _1);
01583   ter_reqs.push_back(arm_ter);
01584   segment_names.push_back("Descend");
01585   callbacks.push_back(trajectories_finished_function_);
01586 
01587   // setting up  gripper release
01588   TrajectoryExecutionRequest gripper_ter;
01589   gripper_ter.group_name_ = gripper_group_name_;
01590   gripper_ter.controller_name_ = grasp_action_service_;
01591   gripper_ter.trajectory_ = getGripperTrajectory(object_manipulation_msgs::GraspHandPostureExecutionGoal::RELEASE);
01592   validateJointTrajectory(gripper_ter.trajectory_);
01593   gripper_ter.failure_ok_ = true;
01594   gripper_ter.test_for_close_enough_ = false;
01595   ter_reqs.push_back(gripper_ter);
01596   segment_names.push_back("Release");
01597   callbacks.push_back(grasp_action_finished_function_);
01598 
01599   // updating attached object marker operation
01600   if(hasMarker(MARKER_ATTACHED_OBJECT))
01601   {
01602           visualization_msgs::Marker &m = getMarker(MARKER_ATTACHED_OBJECT);
01603           m.action = visualization_msgs::Marker::DELETE;
01604           addMarker(MARKER_ATTACHED_OBJECT,m);
01605   }
01606 
01607   //do the retreat
01608   arm_ter.trajectory_ = pei.retreat_trajectory_;
01609   validateJointTrajectory(arm_ter.trajectory_);
01610   performTrajectoryFiltering(group_name, arm_ter.trajectory_);
01611   arm_ter.callback_function_ = 0;
01612   ter_reqs.push_back(arm_ter);
01613   segment_names.push_back("Retreat");
01614   callbacks.push_back(trajectories_finished_function_);
01615 
01616   /*
01617    * executing all trajectories
01618    * currently this is the only way to execute multiple trajectories in sequence, since the executeTrajectories
01619    * method can only handle a single trajectory at a time.
01620    */
01621   ros::WallTime start_execution = ros::WallTime::now();
01622   ROS_INFO_STREAM( NODE_NAME <<": Starting Execution of trajectories");
01623   for(unsigned int i = 0;i < ter_reqs.size(); i++)
01624   {
01625           std::vector<TrajectoryExecutionRequest> tempRequest;
01626           tempRequest.push_back(ter_reqs[i]);
01627 
01628           ROS_INFO_STREAM("\t"<< "- "<<segment_names[i] <<" trajectory in progress");
01629           trajectory_execution_monitor_.executeTrajectories(tempRequest,callbacks[i]);
01630 
01631           {
01632                   boost::unique_lock<boost::mutex> lock(execution_mutex_);
01633                   execution_completed_.wait(lock);
01634 
01635                   if(trajectories_succeeded_)
01636                   {
01637                           ROS_INFO_STREAM("\t"<< "- "<<segment_names[i] <<" trajectory completed");
01638                   }
01639                   else
01640                   {
01641                           ROS_INFO_STREAM("\t"<< "- "<<segment_names[i] <<" trajectory interrupted, aborting place sequence");
01642                           break;
01643                   }
01644           }
01645   }
01646   ROS_INFO_STREAM(NODE_NAME <<"Finished executing all trajectories");
01647 
01648   execution_duration_ += (ros::WallTime::now()-start_execution);
01649   return trajectories_succeeded_;
01650 }
01651 
01652 trajectory_msgs::JointTrajectory RobotNavigator::getGripperTrajectory(int graspMove)
01653 {
01654   trajectory_msgs::JointTrajectoryPoint jp;
01655   trajectory_msgs::JointTrajectory gt;
01656 
01657   gt.joint_names.push_back("j");
01658   gt.points.resize(1);
01659   gt.points[0].positions.resize(1, .1);
01660   gt.points[0].positions[0] = (double) graspMove;
01661 
01662   return gt;
01663 }
01664 
01665 bool RobotNavigator::attachCollisionObject(const std::string& group_name,
01666                            const std::string& collision_object_name,
01667                            const object_manipulation_msgs::Grasp& grasp) {
01668 
01669   // removing object from planning scene first if it is found
01670   arm_navigation_msgs::AttachedCollisionObject att;
01671   bool found = false;
01672   for(std::vector<arm_navigation_msgs::CollisionObject>::iterator it = planning_scene_diff_.collision_objects.begin();
01673       it != planning_scene_diff_.collision_objects.end();
01674       it++)
01675   {
01676 
01677     if((*it).id == collision_object_name)
01678     {
01679       found = true;
01680       att.object = (*it);
01681       planning_scene_diff_.collision_objects.erase(it);
01682       break;
01683     }
01684   }
01685 
01686   if(!found)
01687   {
01688     ROS_ERROR_STREAM("No object with id " << collision_object_name);
01689     return false;
01690   }
01691 
01692   att.link_name = gripper_link_name_;
01693   att.touch_links.push_back(gripper_group_name_);
01694 
01695   planning_models::KinematicState state(*current_robot_state_);
01696   tf::Transform t;
01697   tf::poseMsgToTF(grasp.grasp_pose, t);
01698 
01699   std::map<std::string, double> grasp_vals;
01700   for(unsigned int i = 0; i < grasp.grasp_posture.name.size(); i ++)
01701   {
01702      grasp_vals[grasp.grasp_posture.name[i]] = grasp.grasp_posture.position[i];
01703   }
01704   state.setKinematicState(grasp_vals);
01705 
01706   tf::Transform obj_pose;
01707   tf::poseMsgToTF(recognized_obj_pose_map_[collision_object_name].pose, obj_pose);// store object pose in world coordinates
01708 
01709   //assumes that the grasp is in the object frame
01710   tf::Transform grasp_pose = obj_pose*t;
01711 
01712   // //need to do this second, otherwise it gets wiped out
01713   state.updateKinematicStateWithLinkAt(gripper_link_name_, grasp_pose);
01714 
01715   geometry_msgs::PoseStamped ps;
01716   //now we need to get the object pose in terms of the gripper
01717   cm_.convertPoseGivenWorldTransform(state,
01718                                      att.link_name,
01719                                      att.object.header,
01720                                      att.object.poses[0],
01721                                      ps);
01722 
01723   att.object.id = "attached_"+att.object.id;
01724   att.object.header = ps.header;
01725   att.object.poses[0] = ps.pose;
01726 
01727   ROS_INFO_STREAM("object pose is relative to " + gripper_link_name_ + ": "
01728                   << ps.pose.position.x << " "
01729                   << ps.pose.position.y << " "
01730                   << ps.pose.position.z);
01731 
01732   ROS_INFO_STREAM("Attaching  " << att.object.id << " mode " << att.object.operation.operation);
01733   planning_scene_diff_.attached_collision_objects.push_back(att);
01734 
01735   attached_object_publisher_.publish(att);
01736   return true;
01737 }
01738 
01739 bool RobotNavigator::detachCollisionObject(const std::string& group_name,
01740                            const geometry_msgs::PoseStamped& place_pose,
01741                            const object_manipulation_msgs::Grasp& grasp) {
01742 
01743   ROS_INFO_STREAM("Place pose is " << place_pose.header.frame_id);
01744 
01745   planning_models::KinematicState state(*current_robot_state_);
01746   tf::Transform place_pose_tf;
01747   tf::poseMsgToTF(place_pose.pose, place_pose_tf);
01748 
01749   tf::Transform grasp_trans;
01750   tf::poseMsgToTF(grasp.grasp_pose, grasp_trans);
01751 
01752   place_pose_tf = place_pose_tf*grasp_trans;
01753 
01754   state.updateKinematicStateWithLinkAt(gripper_link_name_,
01755                                        place_pose_tf);
01756 
01757   if(planning_scene_diff_.attached_collision_objects.size() == 0) {
01758     ROS_ERROR_STREAM("No attached bodies in scene");
01759     return false;
01760   }
01761 
01762   arm_navigation_msgs::CollisionObject& obj =  planning_scene_diff_.attached_collision_objects.front().object;
01763   const planning_models::KinematicState::AttachedBodyState* att = state.getAttachedBodyState(obj.id);
01764   if(att == NULL) {
01765     ROS_ERROR_STREAM("No attached body model " << obj.id << " in attached");
01766     return false;
01767   }
01768 
01769   arm_navigation_msgs::AttachedCollisionObject att_publish;
01770   att_publish.object.id = obj.id;
01771   att_publish.object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::REMOVE;
01772   attached_object_publisher_.publish(att_publish);
01773 
01774   obj.header.frame_id = cm_.getWorldFrameId();
01775   tf::poseTFToMsg(att->getGlobalCollisionBodyTransforms()[0], obj.poses[0]);
01776   obj.id = current_grasped_object_name_[group_name];
01777   planning_scene_diff_.collision_objects.push_back(obj);
01778   planning_scene_diff_.attached_collision_objects.clear();
01779   return true;
01780 }
01781 
01782 void RobotNavigator::collisionObjToMarker(const arm_navigation_msgs::CollisionObject &obj,visualization_msgs::Marker &marker)
01783 {
01784         // only converts to a sphere marker for now
01785         const arm_navigation_msgs::Shape &shape = obj.shapes[0];
01786 
01787         switch(shape.type)
01788         {
01789                 case arm_navigation_msgs::Shape::SPHERE:
01790 
01791                         marker.header.frame_id = obj.header.frame_id;
01792                         marker.type = visualization_msgs::Marker::SPHERE;
01793                         marker.pose = obj.poses[0];
01794                         marker.scale.x = 2*shape.dimensions[0];// 2 x radius
01795                         marker.scale.y =2*shape.dimensions[0];
01796                         marker.scale.z =2*shape.dimensions[0];
01797                         marker.color.a = 1.0;
01798                         marker.color.r = 0.0;
01799                         marker.color.g = 1.0;
01800                         marker.color.b = 0.0;
01801 
01802                         break;
01803 
01804                 default:
01805 
01806                         break;
01807 
01808         }
01809 
01810 }
01811 
01812 void RobotNavigator::startCycleTimer()
01813 {
01814   execution_duration_ = ros::WallDuration(0.0);
01815   perception_duration_ = ros::WallDuration(0.0);
01816   planning_scene_duration_ = ros::WallDuration(0.0);
01817   motion_planning_duration_ = ros::WallDuration(0.0);
01818   trajectory_filtering_duration_ = ros::WallDuration(0.0);
01819   grasp_planning_duration_ = ros::WallDuration(0.0);
01820   cycle_start_time_ = ros::WallTime::now();
01821 }
01822 
01823 void RobotNavigator::printTiming()
01824 {
01825     ros::WallDuration dur = ros::WallTime::now()-cycle_start_time_;
01826     ROS_INFO_STREAM("Cycle took " << dur.toSec() << " processing " << (dur-execution_duration_).toSec() << " execution " << execution_duration_.toSec());
01827     ROS_INFO_STREAM("Perception " << perception_duration_.toSec());
01828     ROS_INFO_STREAM("Planning scene " << planning_scene_duration_.toSec());
01829     ROS_INFO_STREAM("Planning time " << motion_planning_duration_.toSec());
01830     ROS_INFO_STREAM("Filtering time " << trajectory_filtering_duration_.toSec());
01831     ROS_INFO_STREAM("Grasp planning time " << grasp_planning_duration_.toSec());
01832   }
01833 
01834 std::string RobotNavigator::makeCollisionObjectNameFromModelId(unsigned int model_id)
01835 {
01836   std::stringstream object_id;
01837   object_id << "object_" << model_id;
01838   return object_id.str();
01839 }
01840 
01841 const arm_navigation_msgs::CollisionObject* RobotNavigator::getCollisionObject(unsigned int model_id)
01842 {
01843     std::string name = makeCollisionObjectNameFromModelId(model_id);
01844     for(unsigned int i = 0; i < planning_scene_diff_.collision_objects.size(); i++) {
01845       if(planning_scene_diff_.collision_objects[i].id == name) return &(planning_scene_diff_.collision_objects[i]);
01846     }
01847     return NULL;
01848 }
01849 
01850 void RobotNavigator::run()
01851 {
01852         ros::NodeHandle nh;
01853         ros::AsyncSpinner spinner(4);
01854         spinner.start();
01855         srand(time(NULL));
01856 
01857         setup();// full setup
01858 
01859         if(!moveArmToSide())
01860         {
01861                 ROS_WARN_STREAM(NODE_NAME << ": Side moved failed");
01862         }
01863 
01864         while(ros::ok())
01865         {
01866             startCycleTimer();
01867 
01868 
01869                 ROS_INFO_STREAM(NODE_NAME + ": Segmentation stage started");
01870                 if(!performSegmentation())
01871                 {
01872                   ROS_WARN_STREAM(NODE_NAME<<": Segmentation stage failed");
01873                   continue;
01874                 }
01875                 ROS_INFO_STREAM(NODE_NAME << " Segmentation stage completed");
01876 
01877                 ROS_INFO_STREAM(NODE_NAME << ": Recognition stage started");
01878                 if(!performRecognition())
01879                 {
01880                   ROS_WARN_STREAM(NODE_NAME << ": Recognition stage failed");
01881                   continue;
01882                 }
01883                 else
01884                 {
01885                         ROS_INFO_STREAM(NODE_NAME << ": Recognition stage completed");
01886                 }
01887 
01888                 ROS_INFO_STREAM(NODE_NAME << ": Grasp Pickup stage started");
01889                 if(!moveArmThroughPickSequence())
01890                 {
01891                   ROS_WARN_STREAM(NODE_NAME << ": Grasp Pickup stage failed");
01892                   moveArmToSide();
01893                   continue;
01894                 }
01895                 else
01896                 {
01897                         ROS_INFO_STREAM(NODE_NAME << ": Grasp Pickup stage completed");
01898                 }
01899 
01900                 ROS_INFO_STREAM(NODE_NAME + ": Grasp Place stage started");
01901                 if(!moveArmThroughPlaceSequence())
01902                 {
01903                         ROS_WARN_STREAM(NODE_NAME << ": Grasp Place stage failed");
01904                         moveArmToSide();
01905                         continue;
01906                 }
01907                 else
01908                 {
01909                         ROS_INFO_STREAM(NODE_NAME << ": Grasp Place stage completed");
01910                 }
01911 
01912                 if(!moveArmToSide())
01913                 {
01914                         ROS_WARN_STREAM(NODE_NAME << ": Side moved failed");
01915                 }
01916 
01917 
01918             printTiming();
01919           }
01920 }
01921 
01922 
01923 


object_manipulation_tools
Author(s): Jnicho
autogenerated on Mon Oct 6 2014 00:56:17