00001
00002
00003
00004 import numpy as np, math
00005
00006 import roslib; roslib.load_manifest('hrl_pr2_lib')
00007 import rospy
00008
00009
00010 from interpolated_ik_motion_planner.ik_utilities import *
00011 from pr2_gripper_reactive_approach.controller_manager import *
00012
00013 class HRLIKUtilities(IKUtilities):
00014
00015
00016
00017 def __init__(self, whicharm, tf_listener = None, wait_for_services = 1):
00018 self.whicharm = whicharm
00019
00020
00021 robot_prefix = rospy.get_param('~robot_prefix', 'pr2')
00022 self.srvroot = '/'+robot_prefix+'_'+whicharm+'_arm_kinematics/'
00023
00024
00025 self.perception_running = rospy.get_param('~collision_aware_ik', 1)
00026
00027 self._ik_service = rospy.ServiceProxy(self.srvroot+'get_ik', GetPositionIK, True)
00028 if self.perception_running:
00029 self._ik_service_with_collision = rospy.ServiceProxy(self.srvroot+'get_constraint_aware_ik', GetConstraintAwarePositionIK, True)
00030
00031 self._fk_service = rospy.ServiceProxy(self.srvroot+'get_fk', GetPositionFK, True
00032 self._query_service = rospy.ServiceProxy(self.srvroot+'get_ik_solver_info', GetKinematicSolverInfo, True)
00033 self._check_state_validity_service = rospy.ServiceProxy('/planning_scene_validity_server/get_state_validity', GetStateValidity, True)
00034
00035
00036 if wait_for_services:
00037 self.check_services_and_get_ik_info()
00038
00039 if tf_listener == None:
00040 rospy.loginfo("ik_utilities: starting up tf_listener")
00041 self.tf_listener = tf.TransformListener()
00042 else:
00043 self.tf_listener = tf_listener
00044
00045 self.marker_pub = rospy.Publisher('interpolation_markers', Marker)
00046
00047
00048 self.error_code_dict = {}
00049 for element in dir(ArmNavigationErrorCodes):
00050 if element[0].isupper():
00051 self.error_code_dict[eval('ArmNavigationErrorCodes.'+element)] = element
00052
00053
00054 start_angles_list = rospy.get_param('~ik_start_angles', [])
00055
00056
00057
00058 if start_angles_list == []:
00059 self.start_angles_list = [[-0.697, 1.002, 0.021, -0.574, 0.286, -0.095, 1.699],
00060 [-1.027, 0.996, 0.034, -0.333, -3.541, -0.892, 1.694],
00061 [0.031, -0.124, -2.105, -1.145, -1.227, -1.191, 2.690],
00062 [0.410, 0.319, -2.231, -0.839, -2.751, -1.763, 5.494],
00063 [0.045, 0.859, 0.059, -0.781, -1.579, -0.891, 7.707],
00064 [0.420, 0.759, 0.014, -1.099, -3.204, -1.907, 8.753],
00065 [-0.504, 1.297, -1.857, -1.553, -4.453, -1.308, 9.572]]
00066 else:
00067 self.start_angles_list = start_angles_list
00068
00069 if whicharm == 'left':
00070 for i in range(len(self.start_angles_list)):
00071 for joint_ind in [0, 2, 4]:
00072 self.start_angles_list[i][joint_ind] *= -1.
00073
00074
00075 self.pose_id_set = 0
00076
00077 rospy.loginfo("ik_utilities: done init")
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 def check_cartesian_path(self, start_pose, end_pose, start_angles, pos_spacing = 0.01, rot_spacing = 0.1, consistent_angle = math.pi/9., collision_aware = 1, collision_check_resolution = 1, steps_before_abort = -1, num_steps = 0, ordered_collision_operations = None, start_from_end = 0, IK_robot_state = None, link_padding = None, use_additional_start_angles = 0, joints_bias = None, bias_radius = 0.0):
00100 if joints_bias is None:
00101 joints_bias = [0.0] * 7
00102
00103 start_angles = self.bias_guess(start_angles, joints_bias, bias_radius)
00104
00105
00106 if num_steps != 0 and num_steps < 2:
00107 num_steps = 2
00108 if collision_check_resolution < 1:
00109 collision_check_resolution = 1
00110 if num_steps == 0 and (pos_spacing <= 0 or rot_spacing <= 0):
00111 rospy.logerr("invalid pos_spacing or rot_spacing")
00112 return ([], [])
00113
00114
00115 (start_pos, start_rot) = self.pose_stamped_to_lists(start_pose, 'base_link')
00116 (end_pos, end_rot) = self.pose_stamped_to_lists(end_pose, 'base_link')
00117 if start_pos == None or end_pos == None:
00118 return (None, None)
00119
00120
00121 steps = self.interpolate_cartesian(start_pos, start_rot, end_pos, end_rot, pos_spacing, rot_spacing, num_steps)
00122
00123
00124 if start_from_end:
00125 steps.reverse()
00126
00127
00128 if use_additional_start_angles:
00129 num_to_use = max(use_additional_start_angles, len(self.start_angles_list))
00130 start_angles_list = [start_angles,] + self.start_angles_list[0:num_to_use]
00131 else:
00132 start_angles_list = [start_angles,]
00133
00134
00135 for (start_angles_ind, start_angles) in enumerate(start_angles_list):
00136 trajectory = []
00137 error_codes = []
00138
00139 if use_additional_start_angles:
00140 rospy.loginfo("start_angles_ind: %d"%start_angles_ind)
00141
00142 for stepind in range(len(steps)):
00143 (pos,rot) = steps[stepind]
00144 pose_stamped = self.lists_to_pose_stamped(pos, rot, 'base_link', 'base_link')
00145
00146
00147 self.draw_pose(pose_stamped, stepind*3+self.pose_id_set*50)
00148 self.pose_id_set = (self.pose_id_set+1)%2
00149
00150
00151 (colliding_solution, error_code) = self.run_ik(pose_stamped, start_angles, self.link_name, collision_aware = 0, IK_robot_state = IK_robot_state)
00152 if not colliding_solution:
00153 rospy.loginfo("non-collision-aware IK solution not found for step %d!"%stepind)
00154 trajectory.append([0.]*7)
00155 error_codes.append(3)
00156
00157 else:
00158
00159 collision_aware_this_step = collision_aware and (stepind % collision_check_resolution == 0 or stepind == len(steps)-1)
00160 if collision_aware_this_step:
00161 (solution, error_code) = self.run_ik(pose_stamped, start_angles, self.link_name, collision_aware, ordered_collision_operations, IK_robot_state = IK_robot_state, link_padding = link_padding)
00162 if not solution:
00163 rospy.loginfo("non-colliding IK solution not found for step %d!"%stepind)
00164 collision_aware_solution_found = 0
00165 solution = colliding_solution
00166 else:
00167 collision_aware_solution_found = 1
00168 else:
00169 solution = colliding_solution
00170
00171 trajectory.append(list(solution))
00172
00173
00174 if stepind == 0 or error_codes[-1] == 3 or self.check_consistent(trajectory[-2], solution, consistent_angle):
00175 if not collision_aware_this_step or collision_aware_solution_found:
00176 error_codes.append(0)
00177 else:
00178 error_codes.append(1)
00179 else:
00180 rospy.loginfo("IK solution not consistent for step %d!"%stepind)
00181 error_codes.append(2)
00182
00183 start_angles = solution
00184 start_angles = self.bias_guess(start_angles, joints_bias, bias_radius)
00185
00186
00187 if error_codes[-1] > 0 and steps_before_abort >= 0 and stepind >= steps_before_abort:
00188 rospy.loginfo("aborting due to too many invalid steps")
00189 trajectory.extend([[0.]*7 for i in range(len(steps)-stepind-1)])
00190 error_codes.extend([4]*(len(steps)-stepind-1))
00191 break
00192
00193
00194 if not any(error_codes):
00195 break
00196
00197 if start_from_end:
00198 trajectory.reverse()
00199 error_codes.reverse()
00200 return (trajectory, error_codes)
00201
00202
00203
00204 def bias_guess(self, q, joints_bias, bias_radius):
00205 if bias_radius == 0.0:
00206 return q
00207 if self.whicharm == 'right':
00208 max_angs = np.array([.69, 1.33, 0.79, 0.0, 1000000.0, 0.0, 1000000.0])
00209 min_angs = np.array([-2.27, -.54, -3.9, -2.34, -1000000.0, -2.15, -1000000.0])
00210 else:
00211 max_angs = np.array([2.27, 1.33, 3.9, 0.0, 1000000.0, 0.0, 1000000.0])
00212 min_angs = np.array([-.69, -.54, -0.79, -2.34, -1000000.0, -2.15, -1000000.0])
00213 q_off = bias_radius * np.array(joints_bias) / np.linalg.norm(joints_bias)
00214 angs = np.array(q) + q_off
00215 for i in range(7):
00216 if angs[i] > max_angs[i]:
00217 angs[i] = max_angs[i]
00218 elif angs[i] < min_angs[i]:
00219 angs[i] = min_angs[i]
00220 return angs.tolist()
00221
00222
00223
00224 def run_biased_ik(self, pose_stamped, joints_bias = [0.]*7,
00225 num_iters=6, init_angs=[0.]*7):
00226 angs = init_angs
00227 has_solution = False
00228 for i in range(num_iters):
00229 (solution, error_code) = self.run_ik(pose_stamped, angs, \
00230 self.link_name)
00231 if solution:
00232 angs = solution
00233 has_solution = True
00234 if i < num_iters - 1:
00235 angs = self.bias_guess(angs, joints_bias, 0.1)
00236 if has_solution:
00237 return angs
00238 else:
00239 return None
00240
00241
00242 class HRLControllerManager(ControllerManager):
00243
00244 def __init__(self, whicharm, tf_listener = None, using_slip_controller = 0, using_slip_detection = 0):
00245 self.whicharm = whicharm
00246
00247 self.using_slip_controller = using_slip_controller
00248 self.using_slip_detection = using_slip_detection
00249
00250 rospy.loginfo("initializing "+whicharm+" controller manager")
00251 rospy.loginfo("controller manager: using_slip_controller:"+str(using_slip_controller))
00252 rospy.loginfo("controller manager: using_slip_detection:"+str(using_slip_detection))
00253
00254
00255 rospy.loginfo("controller manager waiting for pr2_controller_manager services to be there")
00256 load_controller_serv_name = 'pr2_controller_manager/load_controller'
00257 unload_controller_serv_name = 'pr2_controller_manager/unload_controller'
00258 switch_controller_serv_name = 'pr2_controller_manager/switch_controller'
00259 list_controllers_serv_name = 'pr2_controller_manager/list_controllers'
00260 self.wait_for_service(load_controller_serv_name)
00261 self.wait_for_service(unload_controller_serv_name)
00262 self.wait_for_service(switch_controller_serv_name)
00263 self.wait_for_service(list_controllers_serv_name)
00264 self.load_controller_service = \
00265 rospy.ServiceProxy(load_controller_serv_name, LoadController)
00266 self.unload_controller_service = \
00267 rospy.ServiceProxy(unload_controller_serv_name, UnloadController)
00268 self.switch_controller_service = \
00269 rospy.ServiceProxy(switch_controller_serv_name, SwitchController)
00270 self.list_controllers_service = \
00271 rospy.ServiceProxy(list_controllers_serv_name, ListControllers)
00272
00273
00274 self.joint_states_listener = joint_states_listener.LatestJointStates()
00275
00276
00277 joint_trajectory_action_name = whicharm+'_arm_controller/joint_trajectory_action'
00278 self.joint_action_client = \
00279 actionlib.SimpleActionClient(joint_trajectory_action_name, JointTrajectoryAction)
00280
00281
00282 if self.using_slip_controller:
00283 gripper_action_name = whicharm+'_gripper_sensor_controller/gripper_action'
00284 self.gripper_action_client = actionlib.SimpleActionClient(gripper_action_name, Pr2GripperCommandAction)
00285
00286
00287 else:
00288 gripper_action_name = whicharm+'_gripper_controller/gripper_action'
00289 self.gripper_action_client = \
00290 actionlib.SimpleActionClient(gripper_action_name, Pr2GripperCommandAction)
00291
00292
00293 if self.using_slip_detection:
00294 gripper_find_contact_action_name = whicharm+'_gripper_sensor_controller/find_contact'
00295 gripper_grab_action_name = whicharm+'_gripper_sensor_controller/grab'
00296 gripper_event_detector_action_name = whicharm+'_gripper_sensor_controller/event_detector'
00297
00298 self.gripper_find_contact_action_client = actionlib.SimpleActionClient(gripper_find_contact_action_name, \
00299 PR2GripperFindContactAction)
00300 self.gripper_grab_action_client = actionlib.SimpleActionClient(gripper_grab_action_name, \
00301 PR2GripperGrabAction)
00302 self.gripper_event_detector_action_client = actionlib.SimpleActionClient(gripper_event_detector_action_name, \
00303 PR2GripperEventDetectorAction)
00304
00305
00306 self.move_arm_client = None
00307
00308
00309 self.wait_for_action_server(self.joint_action_client, joint_trajectory_action_name)
00310 self.wait_for_action_server(self.gripper_action_client, gripper_action_name)
00311 if self.using_slip_detection:
00312 self.wait_for_action_server(self.gripper_find_contact_action_client, gripper_find_contact_action_name)
00313 self.wait_for_action_server(self.gripper_grab_action_client, gripper_grab_action_name)
00314 self.wait_for_action_server(self.gripper_event_detector_action_client, gripper_event_detector_action_name)
00315
00316
00317 if tf_listener == None:
00318 self.tf_listener = tf.TransformListener()
00319 else:
00320 self.tf_listener = tf_listener
00321
00322
00323 self.use_trajectory_cartesian = rospy.get_param('~use_trajectory_cartesian', 1)
00324 self.use_task_cartesian = rospy.get_param('~use_task_cartesian', 0)
00325 if self.use_trajectory_cartesian and self.use_task_cartesian:
00326 rospy.loginfo("can't use both trajectory and task controllers! Defaulting to task")
00327 self.use_trajectory_cartesian = 0
00328 rospy.loginfo("use_trajectory_cartesian: "+str(self.use_trajectory_cartesian))
00329 rospy.loginfo("use_task_cartesian: "+str(self.use_task_cartesian))
00330
00331
00332 if self.use_trajectory_cartesian:
00333 self.cartesian_controllers = ['_arm_cartesian_pose_controller',
00334 '_arm_cartesian_trajectory_controller']
00335 self.cartesian_controllers = [self.whicharm+x for x in self.cartesian_controllers]
00336 else:
00337 self.cartesian_controllers = [self.whicharm + '_cart']
00338 self.joint_controller = self.whicharm+'_arm_controller'
00339 if self.using_slip_controller:
00340 self.gripper_controller = self.whicharm+'_gripper_sensor_controller'
00341 else:
00342 self.gripper_controller = self.whicharm+'_gripper_controller'
00343
00344
00345 if self.use_trajectory_cartesian:
00346 self.cart_params = JTCartesianParams(self.whicharm)
00347 else:
00348 self.cart_params = JTCartesianTaskParams(self.whicharm, self.use_task_cartesian)
00349
00350
00351 self.joint_params = JointParams(self.whicharm)
00352
00353
00354 rospy.loginfo("loading any unloaded Cartesian controllers")
00355 self.load_cartesian_controllers()
00356 time.sleep(2)
00357 rospy.loginfo("done loading controllers")
00358
00359
00360 if self.use_trajectory_cartesian:
00361 cartesian_check_moving_name = whicharm+'_arm_cartesian_trajectory_controller/check_moving'
00362 cartesian_move_to_name = whicharm+'_arm_cartesian_trajectory_controller/move_to'
00363 cartesian_preempt_name = whicharm+'_arm_cartesian_trajectory_controller/preempt'
00364 self.wait_for_service(cartesian_check_moving_name)
00365 self.wait_for_service(cartesian_move_to_name)
00366 self.wait_for_service(cartesian_preempt_name)
00367 self.cartesian_moving_service = rospy.ServiceProxy(cartesian_check_moving_name, CheckMoving)
00368 self.cartesian_cmd_service = rospy.ServiceProxy(cartesian_move_to_name, MoveToPose)
00369 self.cartesian_preempt_service = rospy.ServiceProxy(cartesian_preempt_name, Empty)
00370 else:
00371 cartesian_cmd_name = whicharm+'_cart/command_pose'
00372 self.cartesian_cmd_pub = rospy.Publisher(cartesian_cmd_name, PoseStamped)
00373
00374
00375 self.cart_params.set_params_to_gentle()
00376 self.reload_cartesian_controllers()
00377
00378
00379 rospy.loginfo("creating IKUtilities class objects")
00380 rospy.set_param("~collision_aware_ik", 0)
00381 if whicharm == 'r':
00382 self.ik_utilities = HRLIKUtilities('right', self.tf_listener)
00383 else:
00384 self.ik_utilities = HRLIKUtilities('left', self.tf_listener)
00385 rospy.loginfo("done creating IKUtilities class objects")
00386
00387
00388 joint_names = ["_shoulder_pan_joint",
00389 "_shoulder_lift_joint",
00390 "_upper_arm_roll_joint",
00391 "_elbow_flex_joint",
00392 "_forearm_roll_joint",
00393 "_wrist_flex_joint",
00394 "_wrist_roll_joint"]
00395 self.joint_names = [whicharm + x for x in joint_names]
00396
00397
00398 if not self.use_trajectory_cartesian:
00399 self.cartesian_command_lock = threading.Lock()
00400 self.cartesian_command_thread_running = False
00401 self.cartesian_desired_pose = self.get_current_wrist_pose_stamped('/base_link')
00402 self.cartesian_command_thread = threading.Thread(target=self.cartesian_command_thread_func)
00403 self.cartesian_command_thread.setDaemon(True)
00404 self.cartesian_command_thread.start()
00405 rospy.loginfo("done with controller_manager init for the %s arm"%whicharm)
00406
00407 def command_interpolated_ik(self, end_pose, start_pose = None, collision_aware = 1, step_size = .02, max_joint_vel = .05, joints_bias = None, bias_radius = 0.0):
00408 self.check_controllers_ok('joint')
00409
00410
00411 current_angles = self.get_current_arm_angles()
00412
00413 if start_pose == None:
00414
00415 (current_trans, current_rot) = self.return_cartesian_pose()
00416
00417
00418 start_pose = create_pose_stamped(current_trans+current_rot)
00419
00420
00421
00422
00423
00424 (trajectory, error_codes) = self.ik_utilities.check_cartesian_path(start_pose, \
00425 end_pose, current_angles, step_size, .1, math.pi/4, collision_aware, \
00426 joints_bias = joints_bias, bias_radius = bias_radius,
00427 steps_before_abort=-1)
00428
00429
00430 if any(error_codes):
00431 rospy.loginfo("can't execute an interpolated IK trajectory to that pose")
00432 return 0
00433 trajectory = np.array(trajectory)[np.where(np.array(error_codes) == 0)].tolist()
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444 self.command_joint_trajectory(trajectory, max_joint_vel)
00445 return 1
00446
00447
00448
00449
00450
00451
00452
00453
00454 def move_cartesian_ik(self, goal_pose, collision_aware = 0, blocking = 1,
00455 step_size = .005, pos_thres = .02, rot_thres = .1,
00456 timeout = rospy.Duration(30.),
00457 settling_time = rospy.Duration(0.25), vel = .15,
00458 joints_bias = None, bias_radius = 0.0):
00459
00460
00461 result = self.command_interpolated_ik(goal_pose, collision_aware = collision_aware, \
00462 step_size = step_size, max_joint_vel = vel, \
00463 joints_bias = joints_bias, \
00464 bias_radius = bias_radius)
00465 if not result:
00466 return "no solution"
00467 if not blocking:
00468 return "sent goal"
00469
00470
00471 joint_action_result = self.wait_joint_trajectory_done(timeout)
00472 if joint_action_result == "timed out":
00473 return "timed out"
00474
00475 if self.check_cartesian_really_done(goal_pose, pos_thres, rot_thres):
00476 return "success"
00477 return "failed"
00478
00479 def move_arm_pose_biased(self, pose_stamped, joints_bias = [0.]*7, max_joint_vel=0.2,
00480 blocking = 1, init_angs=[0.]*7):
00481 init_pos = [pose_stamped.pose.position.x, pose_stamped.pose.position.y,
00482 pose_stamped.pose.position.z]
00483
00484 for i in range(10):
00485 cur_pos = np.array(init_pos) + np.random.uniform(-i * 0.0015, i * 0.0015, 3)
00486 pose_stamped.pose.position.x = cur_pos[0]
00487 pose_stamped.pose.position.y = cur_pos[1]
00488 pose_stamped.pose.position.z = cur_pos[2]
00489 solution = self.ik_utilities.run_biased_ik(pose_stamped, joints_bias,
00490 init_angs=init_angs)
00491 if solution:
00492 break
00493
00494 if not solution:
00495 rospy.logerr("no IK solution found for goal pose!")
00496 return None
00497 else:
00498 result = self.command_joint_trajectory([solution], blocking=blocking,
00499 max_joint_vel=max_joint_vel)
00500 return True