00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
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
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
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
00096 point_head_action_client_(POINT_HEAD_ACTION_TOPIC, true)
00097 {
00098
00099 attached_object_pub_ = root_nh_.advertise<mapping_msgs::AttachedCollisionObject>(ATTACHED_COLLISION_TOPIC, 10);
00100
00101
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
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
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
00187 traj_action_client_.client(arm_name);
00188 goal.trajectory.header.stamp = ros::Time::now() + ros::Duration(1.0);
00189
00190
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;
00209 srv.request.rot_spacing = 0.1;
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
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
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
00339
00340 geometry_msgs::Vector3Stamped direction_norm = direction;
00341 direction_norm.vector = normalize(direction.vector);
00342
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
00353 float max_step_size = 0.01;
00354 unsigned int collision_check_resolution = 1;
00355
00356
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
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
00378 if (!seed_joint_position.empty())
00379 {
00380
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
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
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
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
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
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
00662
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
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
00783 tf::Transform end_transform;
00784 if (pre_multiply) end_transform = translate_trans * start_transform;
00785 else end_transform = start_transform * translate_trans;
00786
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
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
00876 geometry_msgs::PoseStamped start_pose_stamped = getGripperPose(arm_name, handDescription().robotFrame(arm_name));
00877
00878
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
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
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
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
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
01140 if(clip_dist == 0 && clip_angle == 0) return desired_pose;
01141
01142
01143 geometry_msgs::PoseStamped current_pose = getGripperPose(arm_name, desired_pose.header.frame_id);
01144
01145
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
01154
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
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
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
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
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
01245 if(ros::Time::now() - begin > timeout)
01246 {
01247 ROS_DEBUG("Timed out when moving to desired Cartesian pose");
01248 break;
01249 }
01250
01251
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
01262 sendCartesianPoseCommand(arm_name, desired_pose, clip_dist, clip_angle);
01263
01264
01265 ros::Duration(timestep).sleep();
01266 }
01267
01268
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
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 }