mechanism_interface.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 *  Copyright (c) 2009, Willow Garage, Inc.
00004 *  All rights reserved.
00005 *
00006 *  Redistribution and use in source and binary forms, with or without
00007 *  modification, are permitted provided that the following conditions
00008 *  are met:
00009 *
00010 *   * Redistributions of source code must retain the above copyright
00011 *     notice, this list of conditions and the following disclaimer.
00012 *   * Redistributions in binary form must reproduce the above
00013 *     copyright notice, this list of conditions and the following
00014 *     disclaimer in the documentation and/or other materials provided
00015 *     with the distribution.
00016 *   * Neither the name of the Willow Garage nor the names of its
00017 *     contributors may be used to endorse or promote products derived
00018 *     from this software without specific prior written permission.
00019 *
00020 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 *  POSSIBILITY OF SUCH DAMAGE.
00032 *********************************************************************/
00033 
00034 #include "object_manipulator/tools/mechanism_interface.h"
00035 #include "object_manipulator/tools/hand_description.h"
00036 #include "object_manipulator/tools/exceptions.h"
00037 
00038 namespace object_manipulator {
00039 
00040 static const std::string IK_SERVICE_SUFFIX = "/constraint_aware_ik";
00041 static const std::string FK_SERVICE_SUFFIX = "/get_fk";
00042 static const std::string INTERPOLATED_IK_SERVICE_SUFFIX = "/interpolated_ik";
00043 static const std::string INTERPOLATED_IK_SET_PARAMS_SERVICE_SUFFIX = "/interpolated_ik_set_params";
00044 static const std::string IK_QUERY_SERVICE_SUFFIX = "/get_ik_solver_info";
00045 static const std::string GRASP_STATUS_SUFFIX = "/grasp_status";
00046 
00047 static const std::string CHECK_STATE_VALIDITY_NAME = "environment_server/get_state_validity";
00048 static const std::string NORMALIZE_SERVICE_NAME = "trajectory_filter_unnormalizer/filter_trajectory";
00049 
00050 static const std::string REACTIVE_GRASP_ACTION_SUFFIX = "/reactive_grasp";
00051 static const std::string REACTIVE_LIFT_ACTION_SUFFIX = "/reactive_lift";
00052 static const std::string REACTIVE_PLACE_ACTION_SUFFIX = "/reactive_place";
00053 static const std::string MOVE_ARM_ACTION_SUFFIX = "/move_arm";
00054 static const std::string TRAJECTORY_ACTION_SUFFIX = "/joint_trajectory";
00055 static const std::string HAND_POSTURE_ACTION_SUFFIX = "/hand_posture_execution";
00056 
00057 static const std::string SWITCH_CONTROLLER_SERVICE_NAME = "/switch_controller";
00058 static const std::string LIST_CONTROLLERS_SERVICE_NAME = "/list_controllers";
00059 static const std::string CARTESIAN_COMMAND_SUFFIX = "/cart/command_pose";
00060 
00061 static const std::string MOVE_ARM_PLANNER_ID = "SBLkConfig1";
00062 static const std::string MOVE_ARM_PLANNER_SERVICE_NAME = "ompl_planning/plan_kinematic_path";
00063 static const std::string MOVE_ARM_CONSTRAINED_PLANNER_SERVICE_NAME = "ompl_planning/plan_kinematic_path";
00064 
00065 static const std::string ATTACHED_COLLISION_TOPIC="attached_collision_object";
00066 
00067 static const std::string POINT_HEAD_ACTION_TOPIC = "/head_traj_controller/point_head_action";
00068 
00069 static const double OBJECT_POSITION_TOLERANCE_X = 0.02;
00070 static const double OBJECT_POSITION_TOLERANCE_Y = 0.02;
00071 static const double OBJECT_POSITION_TOLERANCE_Z = 0.02;
00072 
00073 MechanismInterface::MechanismInterface() :
00074   root_nh_(""),priv_nh_("~"),
00075 
00076   //------------------- multi arm service clients -----------------------
00077   ik_query_client_("", IK_QUERY_SERVICE_SUFFIX, true),
00078   ik_service_client_("", IK_SERVICE_SUFFIX, true),
00079   fk_service_client_("",FK_SERVICE_SUFFIX,true),
00080   interpolated_ik_service_client_("", INTERPOLATED_IK_SERVICE_SUFFIX, true),
00081   interpolated_ik_set_params_client_("", INTERPOLATED_IK_SET_PARAMS_SERVICE_SUFFIX, true),
00082   grasp_status_client_("", GRASP_STATUS_SUFFIX, true),
00083   //------------------- simple service clients -----------------------
00084   check_state_validity_client_(CHECK_STATE_VALIDITY_NAME),
00085   joint_trajectory_normalizer_service_(NORMALIZE_SERVICE_NAME),
00086   switch_controller_service_(SWITCH_CONTROLLER_SERVICE_NAME),
00087   list_controllers_service_(LIST_CONTROLLERS_SERVICE_NAME),
00088   //-------------------- multi arm action clients -----------------------
00089   reactive_grasp_action_client_("", REACTIVE_GRASP_ACTION_SUFFIX, true, true),
00090   reactive_lift_action_client_("", REACTIVE_LIFT_ACTION_SUFFIX, true, true),
00091   reactive_place_action_client_("", REACTIVE_PLACE_ACTION_SUFFIX, true, true),
00092   move_arm_action_client_("", MOVE_ARM_ACTION_SUFFIX, true, true),
00093   traj_action_client_("", TRAJECTORY_ACTION_SUFFIX, true, true),
00094   hand_posture_client_("", HAND_POSTURE_ACTION_SUFFIX, true, true),
00095   //-------------------- head action client -----------------------
00096   point_head_action_client_(POINT_HEAD_ACTION_TOPIC, true)
00097 {
00098   //collision map publishing topic
00099   attached_object_pub_ = root_nh_.advertise<mapping_msgs::AttachedCollisionObject>(ATTACHED_COLLISION_TOPIC, 10);
00100 
00101   //Cartesian pose command publishing topics
00102   right_cartesian_pub_ = root_nh_.advertise<geometry_msgs::PoseStamped>(std::string("right_arm")+
00103                                                                         CARTESIAN_COMMAND_SUFFIX, 100);
00104   left_cartesian_pub_ = root_nh_.advertise<geometry_msgs::PoseStamped>(std::string("left_arm")+
00105                                                                        CARTESIAN_COMMAND_SUFFIX, 100);
00106 
00107   //controller names
00108   priv_nh_.param<std::string>("right_cartesian_controller", right_cartesian_controller_, "r_cart");
00109   priv_nh_.param<std::string>("left_cartesian_controller", left_cartesian_controller_, "l_cart");
00110   priv_nh_.param<std::string>("right_joint_controller", right_joint_controller_, "r_arm_controller");
00111   priv_nh_.param<std::string>("left_joint_controller", left_joint_controller_, "l_arm_controller");
00112 }
00113 
00117 std::vector<std::string> MechanismInterface::getJointNames(std::string arm_name)
00118 {
00119   kinematics_msgs::GetKinematicSolverInfo::Request query_request;
00120   kinematics_msgs::GetKinematicSolverInfo::Response query_response;
00121   if ( !ik_query_client_.client(arm_name).call(query_request, query_response) )
00122   {
00123     ROS_ERROR("Failed to call ik information query");
00124     throw MechanismException("Failed to call ik information query");
00125   }
00126   return query_response.kinematic_solver_info.joint_names;
00127 }
00128 
00129 void MechanismInterface::attemptTrajectory(std::string arm_name,
00130                                            const std::vector< std::vector<double> > &positions,
00131                                            bool unnormalize,
00132                                            float time_per_segment)
00133 {
00134   trajectory_msgs::JointTrajectory trajectory;
00135   trajectory.header.frame_id = handDescription().robotFrame(arm_name);
00136   trajectory.header.stamp = ros::Time::now() + ros::Duration(1.0);
00137   trajectory.joint_names = getJointNames(arm_name);
00138   float current_time = 0;
00139   for (size_t i=0; i<positions.size(); i++)
00140   {
00141     current_time += time_per_segment;
00142     if (positions[i].size() != trajectory.joint_names.size())
00143     {
00144       ROS_ERROR("Mechanism interface: requested trajectory does not have enough joint values");
00145       throw MechanismException("Mechanism interface: requested trajectory does not have enough joint values");
00146     }
00147     trajectory_msgs::JointTrajectoryPoint point;
00148     point.positions = positions[i];
00149     point.time_from_start = ros::Duration(current_time);
00150     trajectory.points.push_back(point);
00151   }
00152   attemptTrajectory(arm_name, trajectory, unnormalize);
00153 }
00154 
00155 void MechanismInterface::attemptTrajectory(std::string arm_name,
00156                                            const trajectory_msgs::JointTrajectory &trajectory,
00157                                            bool unnormalize)
00158 {
00159   if (trajectory.points.empty())
00160   {
00161     ROS_ERROR("attemptTrajectory called with empty trajectory");
00162     throw MechanismException("attemptTrajectory called with empty trajectory");
00163   }
00164 
00165   //make sure joint controllers are running
00166   if(!checkController(right_joint_controller_) || !checkController(left_joint_controller_))
00167      switchToJoint();
00168 
00169   pr2_controllers_msgs::JointTrajectoryGoal goal;
00170   if (unnormalize)
00171   {
00172     motion_planning_msgs::FilterJointTrajectory service_call;
00173     service_call.request.trajectory = trajectory;
00174     service_call.request.allowed_time = ros::Duration(2.0);
00175     if ( !joint_trajectory_normalizer_service_.client().call(service_call) )
00176     {
00177       ROS_ERROR("Mechanism interface: joint trajectory normalizer service call failed");
00178       throw MechanismException("joint trajectory normalizer service call failed");
00179     }
00180     goal.trajectory = service_call.response.trajectory;
00181   }
00182   else
00183   {
00184     goal.trajectory = trajectory;
00185   }
00186   //force it to wait for client here, so that the duration below is not wasted
00187   traj_action_client_.client(arm_name);
00188   goal.trajectory.header.stamp = ros::Time::now() + ros::Duration(1.0);
00189 
00190   //wait 5 seconds more that the whole trajectory is supposed to take
00191   ros::Duration timeout = ros::Duration(1.0) + trajectory.points.back().time_from_start + ros::Duration(5.0);
00192   traj_action_client_.client(arm_name).sendGoal(goal);
00193   if ( !traj_action_client_.client(arm_name).waitForResult(timeout) )
00194   {
00195     ROS_ERROR("  Trajectory timed out");
00196     throw MechanismException("trajectory timed out");
00197   }
00198 }
00199 
00200 void MechanismInterface::setInterpolatedIKParams(std::string arm_name, int num_steps,
00201                                                  int collision_check_resolution, bool start_from_end)
00202 {
00203   interpolated_ik_motion_planner::SetInterpolatedIKMotionPlanParams srv;
00204   srv.request.num_steps = num_steps;
00205   srv.request.consistent_angle = M_PI/6;
00206   srv.request.collision_check_resolution = collision_check_resolution;
00207   srv.request.steps_before_abort = -1;
00208   srv.request.pos_spacing = 0.01; //ignored if num_steps !=0
00209   srv.request.rot_spacing = 0.1;  //ignored if num_steps !=0
00210   srv.request.collision_aware = true;
00211   srv.request.start_from_end = start_from_end;
00212   if (!interpolated_ik_set_params_client_.client(arm_name).call(srv))
00213   {
00214     ROS_ERROR("Failed to set Interpolated IK server parameters");
00215     throw MechanismException("Failed to set Interpolated IK server parameters");
00216   }
00217 }
00218 
00219 bool MechanismInterface::moveArmToPose(std::string arm_name, const geometry_msgs::PoseStamped &desired_pose,
00220                                        const motion_planning_msgs::OrderedCollisionOperations &collision_operations,
00221                                        const std::vector<motion_planning_msgs::LinkPadding> &link_padding)
00222 {
00223   kinematics_msgs::GetConstraintAwarePositionIK::Response ik_response;
00224   if(!getIKForPose(arm_name, desired_pose,ik_response, collision_operations, link_padding))
00225     return false;
00226   if(!attemptMoveArmToGoal(arm_name, ik_response.solution.joint_state.position, collision_operations, link_padding))
00227     return false;
00228   return true;
00229 }
00230 
00231 bool MechanismInterface::getFK(std::string arm_name,
00232                                std::vector<double> positions,
00233                                geometry_msgs::PoseStamped &pose_stamped)
00234 {
00235  // define the service messages
00236  kinematics_msgs::GetPositionFK::Request  fk_request;
00237  kinematics_msgs::GetPositionFK::Response fk_response;
00238  fk_request.header.frame_id = pose_stamped.header.frame_id;
00239  fk_request.header.stamp = pose_stamped.header.stamp;
00240  fk_request.fk_link_names.resize(1);
00241  fk_request.fk_link_names[0] = handDescription().gripperFrame(arm_name);
00242  fk_request.robot_state.joint_state.position = positions;
00243  fk_request.robot_state.joint_state.name = getJointNames(arm_name);
00244  if( !fk_service_client_.client(arm_name).call(fk_request,fk_response) )
00245    {
00246      ROS_ERROR("FK Service Call failed altogether");
00247      throw MechanismException("FK Service Call failed altogether");
00248    }
00249  if (fk_response.error_code.val != fk_response.error_code.SUCCESS)
00250    {
00251     ROS_ERROR("Get FK failed with error code %d", fk_response.error_code.val);
00252     return false;
00253    }
00254  pose_stamped = fk_response.pose_stamped[0];
00255  return true;
00256 }
00257 
00258 bool MechanismInterface::getIKForPose(std::string arm_name, const geometry_msgs::PoseStamped &desired_pose,
00259                                       kinematics_msgs::GetConstraintAwarePositionIK::Response& ik_response,
00260                                       const motion_planning_msgs::OrderedCollisionOperations &collision_operations,
00261                                       const std::vector<motion_planning_msgs::LinkPadding> &link_padding)
00262 {
00263   //call collision-aware ik
00264   kinematics_msgs::GetConstraintAwarePositionIK::Request ik_request;
00265   ik_request.ik_request.ik_link_name = handDescription().gripperFrame(arm_name);
00266   ik_request.ik_request.pose_stamped.pose = desired_pose.pose;
00267   ik_request.ik_request.pose_stamped.header.stamp = desired_pose.header.stamp;
00268   ik_request.ik_request.pose_stamped.header.frame_id = desired_pose.header.frame_id;
00269   ik_request.ik_request.ik_seed_state.joint_state.name = getJointNames(arm_name);
00270   ik_request.ik_request.ik_seed_state.joint_state.position.resize(5, 0.0);
00271   ik_request.ordered_collision_operations = collision_operations;
00272   ik_request.link_padding = link_padding;
00273   ik_request.timeout = ros::Duration(2.0);
00274   if( !ik_service_client_.client(arm_name).call(ik_request,ik_response) )
00275   {
00276     ROS_ERROR("IK Service Call failed altogether");
00277     throw MechanismException("IK Service Call failed altogether");
00278   }
00279   if (ik_response.error_code.val != ik_response.error_code.SUCCESS)
00280   {
00281     ROS_ERROR("Get IK failed with error code %d", ik_response.error_code.val);
00282     return false;
00283   }
00284   return true;
00285 }
00286 
00287 bool MechanismInterface::checkStateValidity(std::string arm_name, const std::vector<double> &joint_values,
00288                                           const motion_planning_msgs::OrderedCollisionOperations &collision_operations,
00289                                             const std::vector<motion_planning_msgs::LinkPadding> &link_padding)
00290 {
00291   planning_environment_msgs::GetStateValidity::Request req;
00292   planning_environment_msgs::GetStateValidity::Response res;
00293 
00294   req.robot_state.joint_state.name = getJointNames(arm_name);
00295   req.robot_state.joint_state.position = joint_values;
00296   if ( req.robot_state.joint_state.name.size() != joint_values.size() )
00297   {
00298     throw MechanismException("Wrong number of joint values for checkStateValidity");
00299   }
00300   req.robot_state.joint_state.header.stamp = ros::Time::now();
00301   req.check_collisions = true;
00302   req.ordered_collision_operations = collision_operations;
00303   req.link_padding = link_padding;
00304 
00305   if(!check_state_validity_client_.client().call(req,res))
00306   {
00307     throw MechanismException("Call to check state validity client failed");
00308   }
00309 
00310   if (res.error_code.val == res.error_code.SUCCESS) return true;
00311   return false;
00312 }
00313 
00326 int MechanismInterface::getInterpolatedIK(std::string arm_name,
00327                                           geometry_msgs::PoseStamped start_pose,
00328                                           geometry_msgs::Vector3Stamped direction,
00329                                           float desired_trajectory_length,
00330                                           const std::vector<double> &seed_joint_position,
00331                                           const sensor_msgs::JointState &joint_state,
00332                                           const motion_planning_msgs::OrderedCollisionOperations &collision_operations,
00333                                           const std::vector<motion_planning_msgs::LinkPadding> &link_padding,
00334                                           bool reverse_trajectory,
00335                                           trajectory_msgs::JointTrajectory &trajectory,
00336                                           float &actual_trajectory_length)
00337 {
00338   //first compute the desired end pose
00339   //make sure the input is normalized
00340   geometry_msgs::Vector3Stamped direction_norm = direction;
00341   direction_norm.vector = normalize(direction.vector);
00342   //multiply by the length
00343   desired_trajectory_length = fabs(desired_trajectory_length);
00344   direction_norm.vector.x *= desired_trajectory_length;
00345   direction_norm.vector.y *= desired_trajectory_length;
00346   direction_norm.vector.z *= desired_trajectory_length;
00347   ROS_INFO("translate from %f, %f , %f with vec: %f, %f, %f", start_pose.pose.position.x, start_pose.pose.position.y, start_pose.pose.position.z, direction_norm.vector.x,  direction_norm.vector.y,  direction_norm.vector.z);
00348 
00349   geometry_msgs::PoseStamped end_pose = translateGripperPose(direction_norm, start_pose, arm_name);
00350 
00351   ROS_INFO("computed end pose: %f, %f, %f", end_pose.pose.position.x, end_pose.pose.position.y, end_pose.pose.position.z);
00352   //hard-coded for now
00353   float max_step_size = 0.01;
00354   unsigned int collision_check_resolution = 1;
00355 
00356   //compute the number of steps
00357   unsigned int num_steps = (unsigned int)ceil(desired_trajectory_length / fabs(max_step_size));
00358   float actual_step_size = desired_trajectory_length / num_steps;
00359 
00360   ROS_INFO("Trajectory details: length %f, requested num steps: %d, actual step size: %f",
00361            desired_trajectory_length, num_steps, actual_step_size);
00362 
00363   if (reverse_trajectory)
00364   {
00365     std::swap(start_pose, end_pose);
00366   }
00367 
00368   //recall that here we setting the numbre of points in trajectory, which is steps+1
00369   setInterpolatedIKParams(arm_name, num_steps+1, collision_check_resolution, reverse_trajectory);
00370 
00371   motion_planning_msgs::RobotState start_state;
00372   start_state.multi_dof_joint_state.child_frame_ids.push_back(handDescription().gripperFrame(arm_name));
00373   start_state.multi_dof_joint_state.poses.push_back(start_pose.pose);
00374   start_state.multi_dof_joint_state.frame_ids.push_back(start_pose.header.frame_id);
00375   start_state.multi_dof_joint_state.stamp = ros::Time::now();
00376 
00377   //pass the seeds for the IK, if any
00378   if (!seed_joint_position.empty())
00379   {
00380     //we are silently assuming that the values passed in match out joint names for IK
00381     start_state.joint_state.name = getJointNames(arm_name);
00382     if (seed_joint_position.size() != start_state.joint_state.name.size())
00383     {
00384       ROS_ERROR("Interpolated IK request: seed_joint_position does not match joint names");
00385       throw MechanismException("Interpolated IK request: seed_joint_position does not match joint names");
00386     }
00387     start_state.joint_state.position = seed_joint_position;
00388   }
00389 
00390   //pass the desired values of non-planned joints, if any
00391   for (size_t i=0; i<joint_state.name.size(); i++)
00392   {
00393     start_state.joint_state.name.push_back(joint_state.name[i]);
00394     start_state.joint_state.position.push_back(joint_state.position[i]);
00395   }
00396 
00397   motion_planning_msgs::PositionConstraint position_constraint;
00398   motion_planning_msgs::OrientationConstraint orientation_constraint;
00399   motion_planning_msgs::poseStampedToPositionOrientationConstraints(end_pose, handDescription().gripperFrame(arm_name),
00400                                                                     position_constraint,
00401                                                                     orientation_constraint);
00402   motion_planning_msgs::Constraints goal_constraints;
00403   goal_constraints.position_constraints.push_back(position_constraint);
00404   goal_constraints.orientation_constraints.push_back(orientation_constraint);
00405 
00406   motion_planning_msgs::GetMotionPlan motion_plan;
00407   motion_plan.request.motion_plan_request.start_state = start_state;
00408   motion_plan.request.motion_plan_request.goal_constraints = goal_constraints;
00409   motion_plan.request.motion_plan_request.ordered_collision_operations = collision_operations;
00410 
00411   //pass the dynamic link padding, if any
00412   motion_plan.request.motion_plan_request.link_padding = link_padding;
00413 
00414   if ( !interpolated_ik_service_client_.client(arm_name).call(motion_plan) )
00415   {
00416     ROS_ERROR("  Call to Interpolated IK service failed");
00417     throw MechanismException("Call to Interpolated IK service failed");
00418   }
00419 
00420   trajectory.points.clear();
00421   trajectory.joint_names = motion_plan.response.trajectory.joint_trajectory.joint_names;
00422 
00423   if (motion_plan.response.trajectory_error_codes.empty())
00424   {
00425     ROS_ERROR("  Interpolated IK: empty trajectory received");
00426     throw MechanismException("Interpolated IK: empty trajectory received");
00427   }
00428 
00429   int error_code = motion_planning_msgs::ArmNavigationErrorCodes::SUCCESS;
00430   if (!reverse_trajectory)
00431   {
00432     for (size_t i=0; i<motion_plan.response.trajectory_error_codes.size(); i++)
00433     {
00434       if ( motion_plan.response.trajectory_error_codes[i].val == motion_plan.response.trajectory_error_codes[i].SUCCESS )
00435       {
00436         trajectory.points.push_back( motion_plan.response.trajectory.joint_trajectory.points[i] );
00437       }
00438       else
00439       {
00440         ROS_DEBUG("  Interpolated IK failed on step %d (forward towards %d) with error code %d",
00441                  (int) i,
00442                  (int) motion_plan.response.trajectory_error_codes.size() - 1,
00443                  motion_plan.response.trajectory_error_codes[i].val);
00444         error_code = motion_plan.response.trajectory_error_codes[i].val;
00445         break;
00446       }
00447     }
00448   }
00449   else
00450   {
00451     size_t first_success = 0;
00452     while ( first_success < motion_plan.response.trajectory_error_codes.size() &&
00453             motion_plan.response.trajectory_error_codes[first_success].val !=
00454             motion_plan.response.trajectory_error_codes[first_success].SUCCESS ) first_success ++;
00455     if (first_success != 0)
00456     {
00457       ROS_DEBUG("  Interpolation failed on step %d (backwards from %d) with error code %d",
00458                (int) first_success - 1,
00459                (int) motion_plan.response.trajectory_error_codes.size() - 1,
00460                motion_plan.response.trajectory_error_codes[first_success - 1].val);
00461       error_code = motion_plan.response.trajectory_error_codes[first_success - 1].val;
00462     }
00463     else
00464     {
00465       ROS_DEBUG("  Interpolation trajectory complete (backwards from %d points)",
00466                (int) motion_plan.response.trajectory_error_codes.size());
00467 
00468     }
00469     for (size_t i=first_success; i < motion_plan.response.trajectory_error_codes.size(); i++)
00470     {
00471       if ( motion_plan.response.trajectory_error_codes[i].val == motion_plan.response.trajectory_error_codes[i].SUCCESS )
00472       {
00473         trajectory.points.push_back( motion_plan.response.trajectory.joint_trajectory.points[i] );
00474       }
00475       else
00476       {
00477         ROS_ERROR("  Interpolated IK: unexpected behavior for error codes: step %d has error code %d",
00478                   (int) i, motion_plan.response.trajectory_error_codes[i].val);
00479         throw MechanismException("Interpolated IK: unexpected behavior for error codes");
00480       }
00481     }
00482   }
00483 
00484   if (!trajectory.points.empty()) actual_trajectory_length = actual_step_size * (trajectory.points.size()-1);
00485   else actual_trajectory_length = 0.0;
00486   return error_code;
00487 }
00488 
00489 bool MechanismInterface::attemptMoveArmToGoal(std::string arm_name, const std::vector<double> &desired_joint_values,
00490                                            const motion_planning_msgs::OrderedCollisionOperations &collision_operations,
00491                                               const std::vector<motion_planning_msgs::LinkPadding> &link_padding)
00492 {
00493   //make sure joint controllers are running
00494   if(!checkController(right_joint_controller_) || !checkController(left_joint_controller_))
00495      switchToJoint();
00496 
00497   int num_tries = 0;
00498   int max_tries = 5;
00499   move_arm_msgs::MoveArmGoal move_arm_goal;
00500 
00501   move_arm_goal.motion_plan_request.group_name = handDescription().armGroup(arm_name);
00502   move_arm_goal.motion_plan_request.num_planning_attempts = 1;
00503   move_arm_goal.motion_plan_request.allowed_planning_time = ros::Duration(5.0);
00504   move_arm_goal.motion_plan_request.planner_id = MOVE_ARM_PLANNER_ID;
00505   move_arm_goal.planner_service_name = MOVE_ARM_PLANNER_SERVICE_NAME;
00506   //move_arm_goal.disable_collision_monitoring = true;
00507   move_arm_goal.motion_plan_request.ordered_collision_operations = collision_operations;
00508   move_arm_goal.motion_plan_request.link_padding = link_padding;
00509 
00510   std::vector<std::string> joint_names = getJointNames(arm_name);
00511   move_arm_goal.motion_plan_request.goal_constraints.joint_constraints.resize(joint_names.size());
00512   for(unsigned int i = 0; i < desired_joint_values.size(); i++)
00513   {
00514     move_arm_goal.motion_plan_request.goal_constraints.joint_constraints[i].joint_name = joint_names.at(i);
00515     move_arm_goal.motion_plan_request.goal_constraints.joint_constraints[i].position = desired_joint_values[i];
00516     move_arm_goal.motion_plan_request.goal_constraints.joint_constraints[i].tolerance_below = .08;
00517     move_arm_goal.motion_plan_request.goal_constraints.joint_constraints[i].tolerance_above = .08;
00518   }
00519 
00520   bool success = false;
00521   motion_planning_msgs::ArmNavigationErrorCodes error_code;
00522   while(num_tries < max_tries)
00523   {
00524     move_arm_action_client_.client(arm_name).sendGoal(move_arm_goal);
00525     bool withinWait = move_arm_action_client_.client(arm_name).waitForResult(ros::Duration(60.0));
00526     if(!withinWait)
00527     {
00528       move_arm_action_client_.client(arm_name).cancelGoal();
00529       ROS_DEBUG("   Move arm goal could not be achieved by move_arm in the allowed duration");
00530       success = false;
00531       num_tries++;
00532       move_arm_msgs::MoveArmResult move_arm_result = *move_arm_action_client_.client(arm_name).getResult();
00533       error_code.val = error_code.TIMED_OUT;
00534       modifyMoveArmGoal(move_arm_goal,error_code,move_arm_result.contacts);
00535       continue;
00536     }
00537     actionlib::SimpleClientGoalState state = move_arm_action_client_.client(arm_name).getState();
00538     if(state == actionlib::SimpleClientGoalState::SUCCEEDED)
00539     {
00540       ROS_DEBUG("  Move arm: position was successfully achieved");
00541       success = true;
00542       break;
00543     }
00544     else
00545     {
00546       move_arm_msgs::MoveArmResult move_arm_result = *move_arm_action_client_.client(arm_name).getResult();
00547       ROS_DEBUG("   Move arm: non-success state was reached. Reason: %s",
00548                (motion_planning_msgs::armNavigationErrorCodeToString(move_arm_result.error_code)).c_str());
00549       ROS_DEBUG("   num_tries: %d, max_tries: %d",num_tries,max_tries);
00550       success = false;
00551       num_tries++;
00552       error_code = move_arm_result.error_code;
00553       modifyMoveArmGoal(move_arm_goal,error_code,move_arm_result.contacts);
00554       continue;
00555     }
00556   }
00558   if (!success && error_code.val == error_code.START_STATE_IN_COLLISION)
00559   {
00560     throw MoveArmStuckException();
00561   }
00562   return success;
00563 }
00564 
00565 
00566 void MechanismInterface::modifyMoveArmGoal(move_arm_msgs::MoveArmGoal &move_arm_goal,
00567                                            motion_planning_msgs::ArmNavigationErrorCodes &error_code,
00568                                            std::vector<planning_environment_msgs::ContactInformation> &contact_info_)
00569 {
00570   double allowed_penetration_depth = 0.03;
00571   if(error_code.val == error_code.START_STATE_IN_COLLISION)
00572   {
00573     std::vector<motion_planning_msgs::AllowedContactSpecification> allowed_contacts;
00574     for(unsigned int i=0; i < contact_info_.size(); i++)
00575     {
00576       if(contact_info_[i].depth < allowed_penetration_depth)
00577       {
00578         motion_planning_msgs::AllowedContactSpecification allowed_contact_tmp;
00579         allowed_contact_tmp.shape.type = allowed_contact_tmp.shape.BOX;
00580         allowed_contact_tmp.shape.dimensions.resize(3);
00581         allowed_contact_tmp.shape.dimensions[0] = 0.03;
00582         allowed_contact_tmp.shape.dimensions[1] = 0.03;
00583         allowed_contact_tmp.shape.dimensions[2] = 0.03;
00584         allowed_contact_tmp.pose_stamped.pose.position = contact_info_[i].position;
00585         allowed_contact_tmp.pose_stamped.pose.orientation.x = 0.0;
00586         allowed_contact_tmp.pose_stamped.pose.orientation.y = 0.0;
00587         allowed_contact_tmp.pose_stamped.pose.orientation.z = 0.0;
00588         allowed_contact_tmp.pose_stamped.pose.orientation.w = 1.0;
00589         allowed_contact_tmp.pose_stamped.header.stamp = ros::Time::now();
00590         allowed_contact_tmp.pose_stamped.header.frame_id = contact_info_[i].header.frame_id;
00591         allowed_contact_tmp.link_names.push_back(contact_info_[i].contact_body_1);
00592         allowed_contact_tmp.penetration_depth = allowed_penetration_depth;
00593         allowed_contacts.push_back(allowed_contact_tmp);
00594         ROS_DEBUG("Added allowed contact region: %d",i);
00595         ROS_DEBUG("Position                    : (%f,%f,%f)",contact_info_[i].position.x,
00596                  contact_info_[i].position.y,contact_info_[i].position.z);
00597         ROS_DEBUG("Frame id                    : %s",contact_info_[i].header.frame_id.c_str());
00598         ROS_DEBUG("Depth                       : %f",allowed_penetration_depth);
00599         ROS_DEBUG("Link                        : %s",contact_info_[i].contact_body_1.c_str());
00600         ROS_DEBUG(" ");
00601       }
00602     }
00603     ROS_DEBUG("Added %d allowed contact regions",(int)allowed_contacts.size());
00604     move_arm_goal.motion_plan_request.allowed_contacts = allowed_contacts;
00605   }
00606 }
00607 
00608 
00609 bool MechanismInterface::moveArmConstrained(std::string arm_name, const geometry_msgs::PoseStamped &commanded_pose,
00610                                             const motion_planning_msgs::OrderedCollisionOperations &collision_operations,
00611                                             const std::vector<motion_planning_msgs::LinkPadding> &link_padding,
00612                                             const motion_planning_msgs::Constraints &path_constraints,
00613                                             const double &redundancy,
00614                                             const bool &compute_viable_command_pose)
00615 {
00616 
00617   //make sure joint controllers are running
00618   if(!checkController(right_joint_controller_) || !checkController(left_joint_controller_))
00619      switchToJoint();
00620 
00621   int num_tries = 0;
00622   int max_tries = 1;
00623 
00624   move_arm_msgs::MoveArmGoal move_arm_goal;
00625   move_arm_goal.motion_plan_request.group_name = handDescription().armGroup(arm_name)+"_cartesian";
00626   move_arm_goal.motion_plan_request.num_planning_attempts = 1;
00627   move_arm_goal.motion_plan_request.allowed_planning_time = ros::Duration(5.0);
00628   move_arm_goal.motion_plan_request.planner_id = MOVE_ARM_PLANNER_ID;
00629   move_arm_goal.planner_service_name = MOVE_ARM_CONSTRAINED_PLANNER_SERVICE_NAME;
00630   move_arm_goal.motion_plan_request.ordered_collision_operations = collision_operations;
00631   move_arm_goal.motion_plan_request.link_padding = link_padding;
00632 
00633   move_arm_goal.motion_plan_request.goal_constraints.position_constraints.resize(1);
00634   move_arm_goal.motion_plan_request.goal_constraints.position_constraints[0].header.frame_id =
00635     commanded_pose.header.frame_id;
00636   move_arm_goal.motion_plan_request.goal_constraints.position_constraints[0].link_name =
00637     handDescription().gripperFrame(arm_name);
00638   move_arm_goal.motion_plan_request.goal_constraints.position_constraints[0].position = commanded_pose.pose.position;
00639   move_arm_goal.motion_plan_request.goal_constraints.position_constraints[0].constraint_region_shape.type =
00640     geometric_shapes_msgs::Shape::BOX;
00641   move_arm_goal.motion_plan_request.goal_constraints.position_constraints[0].
00642     constraint_region_shape.dimensions.push_back(OBJECT_POSITION_TOLERANCE_X);
00643   move_arm_goal.motion_plan_request.goal_constraints.position_constraints[0].
00644     constraint_region_shape.dimensions.push_back(OBJECT_POSITION_TOLERANCE_Y);
00645   move_arm_goal.motion_plan_request.goal_constraints.position_constraints[0].
00646     constraint_region_shape.dimensions.push_back(OBJECT_POSITION_TOLERANCE_Z);
00647   move_arm_goal.motion_plan_request.goal_constraints.position_constraints[0].constraint_region_orientation.w = 1.0;
00648   move_arm_goal.motion_plan_request.goal_constraints.position_constraints[0].weight = 1.0;
00649 
00650   move_arm_goal.motion_plan_request.goal_constraints.orientation_constraints.resize(1);
00651   move_arm_goal.motion_plan_request.goal_constraints.orientation_constraints[0] =
00652     path_constraints.orientation_constraints[0];
00653   move_arm_goal.motion_plan_request.goal_constraints.orientation_constraints[0].header.stamp = ros::Time::now();
00654 
00655   btQuaternion orientation;
00656   tf::quaternionMsgToTF(commanded_pose.pose.orientation,orientation);
00657   geometry_msgs::PoseStamped desired_pose = commanded_pose;
00658   desired_pose.pose.position = move_arm_goal.motion_plan_request.goal_constraints.position_constraints[0].position;
00659   desired_pose.header.stamp = ros::Time::now();
00660 
00661   // TODO - this should really happen through the constraint
00662   // Currently its hard-coded for keeping objects level
00663   if(compute_viable_command_pose && path_constraints.orientation_constraints.size())
00664   {
00665     bool get_ik = false;
00666     for(unsigned int i=0; i < 360; i++)
00667     {
00668       double rotation_yaw = i*M_PI/360.0;
00669       ROS_DEBUG("Trying to find suitable goal orientation with yaw rotation: %f",rotation_yaw);
00670       btQuaternion orientation_yaw;
00671       orientation_yaw.setRPY(0.0,0.0,rotation_yaw);
00672       orientation_yaw *= orientation;
00673       geometry_msgs::Quaternion quaternion;
00674       tf::quaternionTFToMsg(orientation_yaw,quaternion);
00675       desired_pose.pose.orientation = quaternion;
00676       desired_pose.header.stamp = ros::Time::now();
00677       kinematics_msgs::GetConstraintAwarePositionIK::Response ik_response;
00678       if(getIKForPose(arm_name,desired_pose,ik_response, collision_operations, link_padding))
00679       {
00680         get_ik = true;
00681         break;
00682       }
00683     }
00684     if(!get_ik)
00685       return false;
00686   }
00687 
00688   move_arm_goal.motion_plan_request.path_constraints.orientation_constraints.resize(1);
00689   move_arm_goal.motion_plan_request.path_constraints.orientation_constraints[0] =
00690     move_arm_goal.motion_plan_request.goal_constraints.orientation_constraints[0];
00691   move_arm_goal.disable_ik = true;
00692 
00693   move_arm_goal.motion_plan_request.goal_constraints.joint_constraints.resize(1);
00694   move_arm_goal.motion_plan_request.goal_constraints.joint_constraints[0].joint_name = (getJointNames(arm_name))[2];
00695   move_arm_goal.motion_plan_request.goal_constraints.joint_constraints[0].position = redundancy;
00696   move_arm_goal.motion_plan_request.goal_constraints.joint_constraints[0].tolerance_below = M_PI;
00697   move_arm_goal.motion_plan_request.goal_constraints.joint_constraints[0].tolerance_above = M_PI;
00698 
00699   bool success = false;
00700   while(num_tries < max_tries)
00701   {
00702     move_arm_action_client_.client(arm_name).sendGoal(move_arm_goal);
00703     bool withinWait = move_arm_action_client_.client(arm_name).waitForResult(ros::Duration(60.0));
00704     if(!withinWait)
00705     {
00706       move_arm_action_client_.client(arm_name).cancelGoal();
00707       ROS_DEBUG("  Move arm goal could not be achieved by move_arm in the allowed duration");
00708       success = false;
00709       num_tries++;
00710       move_arm_msgs::MoveArmResult move_arm_result = *move_arm_action_client_.client(arm_name).getResult();
00711       motion_planning_msgs::ArmNavigationErrorCodes error_code;
00712       error_code.val = error_code.TIMED_OUT;
00713       modifyMoveArmGoal(move_arm_goal,error_code,move_arm_result.contacts);
00714       continue;
00715     }
00716     actionlib::SimpleClientGoalState state = move_arm_action_client_.client(arm_name).getState();
00717     if(state == actionlib::SimpleClientGoalState::SUCCEEDED)
00718     {
00719       ROS_DEBUG("  Move arm: position was successfully achieved");
00720       success = true;
00721       break;
00722     }
00723     else
00724     {
00725       move_arm_msgs::MoveArmResult move_arm_result = *move_arm_action_client_.client(arm_name).getResult();
00726       ROS_DEBUG("Move arm: non-success state was reached. Reason: %s",
00727                (motion_planning_msgs::armNavigationErrorCodeToString(move_arm_result.error_code)).c_str());
00728       ROS_DEBUG("num_tries: %d, max_tries: %d",num_tries,max_tries);
00729       success = false;
00730       num_tries++;
00731       modifyMoveArmGoal(move_arm_goal,move_arm_result.error_code,move_arm_result.contacts);
00732       continue;
00733     }
00734   }
00735   return success;
00736 }
00737 
00749 geometry_msgs::PoseStamped MechanismInterface::translateGripperPose(geometry_msgs::Vector3Stamped translation,
00750                                                                     geometry_msgs::PoseStamped start_pose,
00751                                                                     std::string arm_name)
00752 {
00753 
00754    ROS_INFO("translate Gripper Pose 1");
00755   bool pre_multiply;
00756   if (translation.header.frame_id == handDescription().gripperFrame(arm_name))
00757   {
00758     pre_multiply=false;
00759   }
00760   else if (translation.header.frame_id == handDescription().robotFrame(arm_name))
00761   {
00762     pre_multiply=true;
00763   }
00764   else
00765   {
00766     throw MechanismException(std::string("Gripper translations (such as for lift or approach) can only be specified in "
00767                                      "either the gripper frame or the robot frame. This one was specified in frame ") +
00768                              translation.header.frame_id);
00769   }
00770 
00771 
00772   //go to robot frame first
00773   geometry_msgs::PoseStamped start_pose_robot_frame = transformPose(handDescription().robotFrame(arm_name), start_pose);
00774   tf::StampedTransform start_transform;
00775   tf::poseMsgToTF(start_pose_robot_frame.pose, start_transform);
00776 
00777   btVector3 vec;
00778   tf::vector3MsgToTF(translation.vector, vec);
00779   tf::StampedTransform translate_trans;
00780   translate_trans.setIdentity();
00781   translate_trans.setOrigin(vec);
00782   //compute the translated pose
00783   tf::Transform end_transform;
00784   if (pre_multiply) end_transform = translate_trans * start_transform;
00785   else end_transform = start_transform * translate_trans;
00786   //prepare the results
00787   geometry_msgs::PoseStamped translated_pose;
00788   tf::poseTFToMsg(end_transform, translated_pose.pose);
00789   translated_pose.header.frame_id = handDescription().robotFrame(arm_name);
00790   translated_pose.header.stamp = ros::Time(0);
00791 
00792   //return the result in the requested frame
00793   translated_pose = transformPose(start_pose.header.frame_id, translated_pose);
00794   return translated_pose;
00795 }
00796 
00798 geometry_msgs::PoseStamped MechanismInterface::getGripperPose(std::string arm_name, std::string frame_id)
00799 {
00800   tf::StampedTransform gripper_transform;
00801   try
00802   {
00803     listener_.lookupTransform(frame_id, handDescription().gripperFrame(arm_name), ros::Time(0), gripper_transform);
00804   }
00805   catch (tf::TransformException ex)
00806   {
00807     ROS_ERROR("Mechanism interface: failed to get tf transform for wrist roll link; tf exception %s", ex.what());
00808     throw MechanismException(std::string("failed to get tf transform for wrist roll link; tf exception: ") +
00809                              std::string(ex.what()) );
00810   }
00811   geometry_msgs::PoseStamped gripper_pose;
00812   tf::poseTFToMsg(gripper_transform, gripper_pose.pose);
00813   gripper_pose.header.frame_id = frame_id;
00814   gripper_pose.header.stamp = ros::Time::now();
00815   return gripper_pose;
00816 }
00817 
00818 void MechanismInterface::transformPointCloud(std::string target_frame,
00819                                              const sensor_msgs::PointCloud &cloud_in,
00820                                              sensor_msgs::PointCloud &cloud_out)
00821 {
00822   try
00823   {
00824     listener_.transformPointCloud(target_frame, cloud_in, cloud_out);
00825   }
00826   catch (tf::TransformException ex)
00827   {
00828     ROS_ERROR("Mechanism interface: failed to cloud into %s frame; exception: %s", target_frame.c_str(),
00829               ex.what());
00830     throw MechanismException(std::string("failed to transform cloud into frame ") + target_frame +
00831                              std::string("; tf exception: ") + std::string(ex.what()) );
00832   }
00833 }
00834 
00835 void MechanismInterface::convertGraspableObjectComponentsToFrame(object_manipulation_msgs::GraspableObject &object,
00836                                                                  std::string frame_id)
00837 {
00838   if (!object.cluster.points.empty())
00839   {
00840     transformPointCloud(frame_id, object.cluster, object.cluster);
00841   }
00842   for (size_t i=0; i<object.potential_models.size(); i++)
00843   {
00844     object.potential_models[i].pose = transformPose(frame_id, object.potential_models[i].pose);
00845   }
00846   object.reference_frame_id = frame_id;
00847 }
00848 
00849 geometry_msgs::PoseStamped MechanismInterface::transformPose(const std::string target_frame,
00850                                                              const geometry_msgs::PoseStamped &stamped_in)
00851 {
00852   geometry_msgs::PoseStamped stamped_out;
00853   try
00854   {
00855     listener_.transformPose(target_frame, stamped_in, stamped_out);
00856   }
00857   catch (tf::TransformException ex)
00858   {
00859     ROS_ERROR("Mechanism interface: failed to transform pose into %s frame; exception: %s", target_frame.c_str(),
00860               ex.what());
00861     throw MechanismException(std::string("failed to transform pose into frame ") + target_frame +
00862                              std::string("; tf exception: ") + std::string(ex.what()) );
00863   }
00864   return stamped_out;
00865 }
00866 
00869 bool MechanismInterface::translateGripper(std::string arm_name, const geometry_msgs::Vector3Stamped &direction,
00870                                           motion_planning_msgs::OrderedCollisionOperations ord,
00871                                           const std::vector<motion_planning_msgs::LinkPadding> &link_padding,
00872                                           float requested_distance, float min_distance,
00873                                           float &actual_distance)
00874 {
00875   //get the current gripper pose in the robot frame
00876   geometry_msgs::PoseStamped start_pose_stamped = getGripperPose(arm_name, handDescription().robotFrame(arm_name));
00877 
00878   //compute the interpolated trajectory
00879   trajectory_msgs::JointTrajectory traj;
00880   std::vector<double> empty;
00881   sensor_msgs::JointState empty_state;
00882   getInterpolatedIK(arm_name,
00883                     start_pose_stamped, direction, requested_distance,
00884                     empty, empty_state, ord, link_padding, false, traj, actual_distance);
00885 
00886   if (min_distance > 0 && actual_distance < min_distance)
00887   {
00888     ROS_DEBUG("Mechanism interface: interpolated IK trajectory covers %f distance, but at least %f requested",
00889              actual_distance, min_distance);
00890     actual_distance = 0;
00891     return false;
00892   }
00893 
00894   if (traj.points.empty())
00895   {
00896     ROS_DEBUG("Mechanism interface: translate gripper trajectory is empty");
00897     actual_distance = false;
00898     return false;
00899   }
00900 
00901   //execute the normalized interpolated trajectory
00902   attemptTrajectory(arm_name, traj, true);
00903   return true;
00904 }
00905 
00909 geometry_msgs::PoseStamped MechanismInterface::getObjectPoseForGrasp(std::string arm_name,
00910                                                                      const geometry_msgs::Pose &grasp_pose)
00911 
00912 {
00913   //get the current pose of the gripper in base link coordinate frame
00914   tf::StampedTransform wrist_transform;
00915   try
00916   {
00917     listener_.lookupTransform("base_link",handDescription().gripperFrame(arm_name),
00918                               ros::Time(0), wrist_transform);
00919   }
00920   catch (tf::TransformException ex)
00921   {
00922     ROS_ERROR("Mechanism interface: failed to get tf transform for wrist roll link");
00923     throw MechanismException(std::string("failed to get tf transform for wrist roll link; tf exception: ") +
00924                              std::string(ex.what()) );
00925   }
00926 
00927   //multiply by inverse of grasp pose
00928   tf::Transform grasp_transform;
00929   tf::poseMsgToTF(grasp_pose, grasp_transform);
00930 
00931   tf::Transform object_transform;
00932   object_transform = wrist_transform * grasp_transform.inverse();
00933 
00934   //prepare the result
00935   geometry_msgs::PoseStamped object_pose;
00936   tf::poseTFToMsg(object_transform, object_pose.pose);
00937   object_pose.header.frame_id = "base_link";
00938   object_pose.header.stamp = ros::Time::now();
00939   return object_pose;
00940 }
00941 
00942 void MechanismInterface::attachObjectToGripper(std::string arm_name, std::string collision_object_name)
00943 {
00944   mapping_msgs::AttachedCollisionObject obj;
00945   obj.object.header.stamp = ros::Time::now();
00946   obj.object.header.frame_id = handDescription().robotFrame(arm_name);
00947   obj.object.operation.operation = mapping_msgs::CollisionObjectOperation::ATTACH_AND_REMOVE_AS_OBJECT;
00948   obj.object.id = collision_object_name;
00949   obj.link_name = handDescription().attachLinkName(arm_name);
00950   obj.touch_links = handDescription().gripperTouchLinkNames(arm_name);
00951   attached_object_pub_.publish(obj);
00952 }
00953 
00954 void MechanismInterface::detachAndAddBackObjectsAttachedToGripper(std::string arm_name,
00955                                                                   std::string collision_object_name)
00956 {
00957   mapping_msgs::AttachedCollisionObject att;
00958   att.object.header.stamp = ros::Time::now();
00959   att.object.header.frame_id = handDescription().robotFrame(arm_name);
00960   att.link_name = handDescription().attachLinkName(arm_name);
00961   att.object.id = collision_object_name;
00962   att.object.operation.operation = mapping_msgs::CollisionObjectOperation::DETACH_AND_ADD_AS_OBJECT;
00963   attached_object_pub_.publish(att);
00964 }
00965 
00966 void MechanismInterface::handPostureGraspAction(std::string arm_name,
00967                                                 const object_manipulation_msgs::Grasp &grasp, int goal)
00968 {
00969   object_manipulation_msgs::GraspHandPostureExecutionGoal posture_goal;
00970   posture_goal.grasp = grasp;
00971   posture_goal.goal = goal;
00972   hand_posture_client_.client(arm_name).sendGoal(posture_goal);
00973   bool withinWait = hand_posture_client_.client(arm_name).waitForResult(ros::Duration(10.0));
00974   if(!withinWait)
00975   {
00976     hand_posture_client_.client(arm_name).cancelGoal();
00977     ROS_ERROR("Hand posture controller timed out on goal (%d)", goal);
00978     throw MechanismException("Hand posture controller timed out");
00979   }
00980   actionlib::SimpleClientGoalState state = hand_posture_client_.client(arm_name).getState();
00981   if(state != actionlib::SimpleClientGoalState::SUCCEEDED)
00982   {
00983     ROS_ERROR("Hand posture controller failed on goal (%d)", goal);
00984     throw MechanismException("Hand posture controller failed");
00985   }
00986   ROS_DEBUG("Hand posture controller successfully achieved goal %d", goal);
00987 }
00988 
00989 bool MechanismInterface::graspPostureQuery(std::string arm_name)
00990 {
00991   object_manipulation_msgs::GraspStatus query;
00992   if (!grasp_status_client_.client(arm_name).call(query))
00993   {
00994     ROS_ERROR("Grasp posture query call failed");
00995     throw MechanismException("Grasp posture query call failed");
00996   }
00997   return query.response.is_hand_occupied;
00998 }
00999 
01000 bool MechanismInterface::pointHeadAction(const geometry_msgs::PointStamped &target, std::string pointing_frame)
01001 {
01002   pr2_controllers_msgs::PointHeadGoal goal;
01003   goal.target = target;
01004   goal.pointing_axis.x = 0;
01005   goal.pointing_axis.y = 0;
01006   goal.pointing_axis.z = 1;
01007   goal.pointing_frame = pointing_frame;
01008   goal.min_duration = ros::Duration(1.0);
01009   goal.max_velocity = 1.0;
01010 
01011   point_head_action_client_.client().sendGoal(goal);
01012   point_head_action_client_.client().waitForResult( ros::Duration(3.0) );
01013 
01014   if (point_head_action_client_.client().getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
01015   {
01016     ROS_DEBUG("Successfully moved head.");
01017     return true;
01018   }
01019   else
01020   {
01021     ROS_ERROR("Head movement failed or timed out.");
01022     return false;
01023   }
01024 
01025 }
01026 
01027 bool MechanismInterface::callSwitchControllers(std::vector<std::string> start_controllers,
01028                                                std::vector<std::string> stop_controllers)
01029 {
01030   pr2_mechanism_msgs::SwitchController srv;
01031   srv.request.start_controllers = start_controllers;
01032   srv.request.stop_controllers = stop_controllers;
01033   srv.request.strictness = srv.request.STRICT;
01034   if ( !switch_controller_service_.client().call(srv) )
01035   {
01036     ROS_ERROR("Mechanism interface: switch controller service call failed");
01037     throw MechanismException("switch controller service call failed");
01038   }
01039   if(!srv.response.ok) return false;
01040   return true;
01041 }
01042 
01043 bool MechanismInterface::switchControllers(std::string start_controller, std::string stop_controller)
01044 {
01045   ROS_DEBUG("Switching controller %s for %s", start_controller.c_str(), stop_controller.c_str());
01046   std::vector<std::string> start_controllers;
01047   std::vector<std::string> stop_controllers;
01048   start_controllers.push_back(start_controller);
01049   stop_controllers.push_back(stop_controller);
01050   bool success = callSwitchControllers(start_controllers, stop_controllers);
01051   if(success)
01052   {
01053     bool start_running = checkController(start_controller);
01054     bool stop_running = checkController(stop_controller);
01055     if(start_running && !stop_running) return true;
01056     ROS_ERROR("switching %s to %s failed even though it returned success",
01057               stop_controller.c_str(), start_controller.c_str());
01058     return false;
01059   }
01060   else
01061   {
01062     ROS_ERROR("switching %s to %s failed", stop_controller.c_str(), start_controller.c_str());
01063     return false;
01064   }
01065 }
01066 
01067 bool MechanismInterface::checkController(std::string controller)
01068 {
01069   return true;
01070 }
01071 
01072 bool MechanismInterface::startController(std::string controller)
01073 {
01074   ROS_DEBUG("Starting controller %s", controller.c_str());
01075   std::vector<std::string> start_controllers;
01076   std::vector<std::string> stop_controllers;
01077   start_controllers.push_back(controller);
01078   bool success = callSwitchControllers(start_controllers, stop_controllers);
01079   if(success)
01080   {
01081     bool running = checkController(controller);
01082     if(running) return true;
01083     ROS_ERROR("starting controller %s failed even though it returned success", controller.c_str());
01084     return false;
01085   }
01086   else
01087   {
01088     ROS_ERROR("starting controller %s failed", controller.c_str());
01089     return false;
01090   }
01091 }
01092 
01093 bool MechanismInterface::stopController(std::string controller)
01094 {
01095   ROS_DEBUG("Stopping controller %s", controller.c_str());
01096   std::vector<std::string> start_controllers;
01097   std::vector<std::string> stop_controllers;
01098   stop_controllers.push_back(controller);
01099   bool success = callSwitchControllers(start_controllers, stop_controllers);
01100   if(success)
01101   {
01102     bool running = checkController(controller);
01103     if(running)
01104     {
01105       ROS_ERROR("stopping controller %s failed even though it returned success", controller.c_str());
01106       return false;
01107     }
01108     return true;
01109   }
01110   else
01111   {
01112     ROS_ERROR("stopping controller %s failed", controller.c_str());
01113     return false;
01114   }
01115 }
01116 
01117 bool MechanismInterface::switchToCartesian()
01118 {
01119   bool result = switchControllers(right_cartesian_controller_, right_joint_controller_);
01120   if(!result) return false;
01121   result = switchControllers(left_cartesian_controller_, left_joint_controller_);
01122   if(!result) return false;
01123   return true;
01124 }
01125 
01126 bool MechanismInterface::switchToJoint()
01127 {
01128   bool result = switchControllers(right_joint_controller_, right_cartesian_controller_);
01129   if(!result) return false;
01130   result = switchControllers(left_joint_controller_, left_cartesian_controller_);
01131   if(!result) return false;
01132   return true;
01133 }
01134 
01135 geometry_msgs::PoseStamped MechanismInterface::clipDesiredPose(std::string arm_name,
01136                                                                const geometry_msgs::PoseStamped &desired_pose,
01137                                                                double clip_dist, double clip_angle)
01138 {
01139   //no clipping desired
01140   if(clip_dist == 0 && clip_angle == 0) return desired_pose;
01141 
01142   //Get the current gripper pose
01143   geometry_msgs::PoseStamped current_pose = getGripperPose(arm_name, desired_pose.header.frame_id);
01144 
01145   //Get the position and angle dists between current and desired
01146   Eigen::eigen2_Transform3d current_trans, desired_trans;
01147   double pos_dist, angle;
01148   Eigen::Vector3d axis, direction;
01149   tf::poseMsgToEigen(current_pose.pose, current_trans);
01150   tf::poseMsgToEigen(desired_pose.pose, desired_trans);
01151   positionAndAngleDist(current_trans, desired_trans, pos_dist, angle, axis, direction);
01152 
01153   //Clip the desired pose to be at most clip_dist and the desired angle to be at most clip_angle (proportional)
01154   //from the current
01155   double pos_fraction, angle_fraction;
01156   double pos_change, angle_change;
01157   pos_fraction = fabs(angle / clip_angle);
01158   angle_fraction = fabs(pos_dist / clip_dist);
01159   if(pos_fraction <=1 && angle_fraction <=1){
01160     return desired_pose;
01161   }
01162   double fraction = pos_fraction;
01163   if(angle_fraction > pos_fraction) fraction = angle_fraction;
01164   pos_change = pos_dist / fraction;
01165   angle_change = angle / fraction;
01166 
01167   Eigen::eigen2_Transform3d clipped_trans;
01168   clipped_trans = current_trans;
01169   Eigen::Vector3d scaled_direction;
01170   scaled_direction = direction * pos_change;
01171   Eigen::eigen2_Translation3d translation(scaled_direction);
01172   clipped_trans = clipped_trans * translation;
01173   Eigen::eigen2_AngleAxis<double> angle_axis(angle_change, axis);
01174   clipped_trans = clipped_trans * angle_axis;
01175   geometry_msgs::PoseStamped clipped_pose;
01176   tf::poseEigenToMsg(clipped_trans, clipped_pose.pose);
01177   clipped_pose.header = desired_pose.header;
01178   return clipped_pose;
01179 }
01180 
01181 void MechanismInterface::poseDists(geometry_msgs::Pose start, geometry_msgs::Pose end, double &pos_dist, double &angle)
01182 {
01183   Eigen::eigen2_Transform3d start_trans, end_trans;
01184   tf::poseMsgToEigen(start, start_trans);
01185   tf::poseMsgToEigen(end, end_trans);
01186   Eigen::Vector3d axis, direction;
01187   positionAndAngleDist(start_trans, end_trans, pos_dist, angle, axis, direction);
01188 }
01189 
01190 void MechanismInterface::positionAndAngleDist(Eigen::eigen2_Transform3d start, Eigen::eigen2_Transform3d end,
01191                                               double &pos_dist,
01192                                               double &angle, Eigen::Vector3d &axis, Eigen::Vector3d &direction)
01193 {
01194   //trans = end to start = global to start * end to global
01195   Eigen::eigen2_Transform3d trans;
01196   trans = start.inverse() * end;
01197   Eigen::eigen2_AngleAxis<double> angle_axis;
01198   angle_axis = trans.rotation();
01199   angle = angle_axis.angle();
01200   axis = angle_axis.axis();
01201   direction = trans.translation();
01202   pos_dist = sqrt(direction.dot(direction));
01203   if(pos_dist) direction *= 1/pos_dist;
01204 }
01205 
01206 int MechanismInterface::translateGripperCartesian(std::string arm_name, const geometry_msgs::Vector3Stamped &direction,
01207                                                   ros::Duration timeout, double dist_tol = .01, double angle_tol = .09,
01208                                                 double clip_dist = .02, double clip_angle = .16, double timestep = 0.1)
01209 {
01210   geometry_msgs::PoseStamped current_pose = getGripperPose(arm_name, direction.header.frame_id);
01211   geometry_msgs::PoseStamped desired_pose = translateGripperPose(direction, current_pose, arm_name);
01212   int result = moveArmToPoseCartesian(arm_name, desired_pose, timeout, dist_tol, angle_tol,
01213                                       clip_dist, clip_angle, timestep);
01214   return result;
01215 }
01216 
01217 //returns 0 if an error occurred, 1 if it got there, -1 if it timed out
01218 int MechanismInterface::moveArmToPoseCartesian(std::string arm_name, const geometry_msgs::PoseStamped &desired_pose,
01219                                                ros::Duration timeout, double dist_tol = .015, double angle_tol = .09,
01220                                                double clip_dist = .02, double clip_angle = .16, double timestep = 0.1)
01221 {
01222   bool success = false;
01223 
01224   //Switch to Cartesian controllers
01225   for(int tries=0; tries<3; tries++)
01226   {
01227     success = switchToCartesian();
01228     if(success) break;
01229     ros::Duration(1.0).sleep();
01230   }
01231   if(!success)
01232   {
01233     ROS_ERROR("Tries exceeded when trying to switch to Cartesian control!");
01234     return 0;
01235   }
01236 
01237   //Move towards the desired pose until we get there within our tolerance or until time runs out
01238   ros::Time begin = ros::Time::now();
01239   int reached_target = -1;
01240   geometry_msgs::PoseStamped current_pose = getGripperPose(arm_name, desired_pose.header.frame_id);
01241 
01242   while(1)
01243   {
01244     //stop if we're out of time
01245     if(ros::Time::now() - begin > timeout)
01246     {
01247       ROS_DEBUG("Timed out when moving to desired Cartesian pose");
01248       break;
01249     }
01250 
01251     //stop if we're within our tolerances
01252     current_pose = getGripperPose(arm_name, desired_pose.header.frame_id);
01253     double pos_dist, angle_dist;
01254     poseDists(current_pose.pose, desired_pose.pose, pos_dist, angle_dist);
01255     if(pos_dist <= dist_tol && angle_dist <= angle_tol)
01256     {
01257       reached_target = 1;
01258       break;
01259     }
01260 
01261     //clip the desired pose and send it out
01262     sendCartesianPoseCommand(arm_name, desired_pose, clip_dist, clip_angle);
01263 
01264     //sleep until the next timestep
01265     ros::Duration(timestep).sleep();
01266   }
01267 
01268   //Switch back to joint control
01269   success = false;
01270   for(int tries=0; tries<3; tries++)
01271   {
01272     success = switchToJoint();
01273     if(success) break;
01274     ros::Duration(1.0).sleep();
01275   }
01276   if(!success)
01277   {
01278     ROS_ERROR("Tries exceeding when trying to switch back to joint control!");
01279     return 0;
01280   }
01281   return reached_target;
01282 }
01283 
01284 void MechanismInterface::sendCartesianPoseCommand(std::string arm_name, geometry_msgs::PoseStamped desired_pose,
01285                                                   double clip_dist = 0, double clip_angle = 0)
01286 {
01287   //geometry_msgs::PoseStamped clipped_pose = desired_pose;
01288   geometry_msgs::PoseStamped clipped_pose = clipDesiredPose(arm_name, desired_pose, clip_dist, clip_angle);
01289   if(arm_name.compare("right_arm") == 0)
01290   {
01291     right_cartesian_pub_.publish(clipped_pose);
01292   }
01293   else if(arm_name.compare("left_arm") == 0)
01294   {
01295     left_cartesian_pub_.publish(clipped_pose);
01296   }
01297   else
01298   {
01299     ROS_ERROR("arm_name '%s' not recognized", arm_name.c_str());
01300   }
01301 }
01302 
01303 std::vector<motion_planning_msgs::LinkPadding>
01304 MechanismInterface::fingertipPadding(std::string arm_name, double pad)
01305 {
01306   std::vector<motion_planning_msgs::LinkPadding> padding_vec;
01307   motion_planning_msgs::LinkPadding padding;
01308   padding.padding = pad;
01309   std::vector<std::string> links = handDescription().fingertipLinks(arm_name);
01310   for (size_t i=0; i<links.size(); i++)
01311   {
01312     padding.link_name = links[i];
01313     padding_vec.push_back(padding);
01314   }
01315   return padding_vec;
01316 }
01317 
01318 std::vector<motion_planning_msgs::LinkPadding>
01319 MechanismInterface::gripperPadding(std::string arm_name, double pad)
01320 {
01321   std::vector<motion_planning_msgs::LinkPadding> padding_vec;
01322   motion_planning_msgs::LinkPadding padding;
01323   padding.padding = pad;
01324   std::vector<std::string> links = handDescription().gripperTouchLinkNames(arm_name);
01325   for (size_t i=0; i<links.size(); i++)
01326   {
01327     padding.link_name = links[i];
01328     padding_vec.push_back(padding);
01329   }
01330   return padding_vec;
01331 }
01332 
01333 } //namespace object_manipulator
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


katana_object_manipulator
Author(s): Henning Deeken
autogenerated on Thu Jan 3 2013 14:44:43