00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 import roslib
00025 roslib.load_manifest("hrl_haptic_mpc")
00026 import rospy
00027 import tf
00028
00029 import hrl_lib.util as ut
00030 import hrl_lib.transforms as tr
00031
00032 import epc_skin_math as esm
00033
00034 import hrl_haptic_manipulation_in_clutter_msgs.msg as haptic_msgs
00035 import hrl_haptic_manipulation_in_clutter_srvs.srv as haptic_srvs
00036 import geometry_msgs.msg
00037 import std_msgs.msg
00038 import hrl_msgs.msg
00039
00040
00041 import multiarray_to_matrix
00042 import haptic_mpc_util
00043
00044 import numpy as np
00045 import threading
00046 import copy
00047 import itertools as it
00048 import sys
00049 import math
00050 import signal
00051
00052
00053
00054
00055 class MPCData():
00056 def __init__(self, q, x_h, x_g, dist_g, goal_posture,
00057 q_h_orient, q_g_orient,
00058 position_weight, orient_weight, posture_weight, force_weight,
00059 force_reduction_goal,
00060 control_point_joint_num,
00061 Kc_l, Rc_l, Jc_l, Je,
00062 delta_f_min, delta_f_max,
00063 phi_curr, K_j,
00064 loc_l, n_l, f_l, f_n,
00065 jerk_opt_weight, max_force_mag,
00066 jep, time_step, stop):
00067
00068 self.q = q
00069 self.x_h = x_h
00070 self.x_g = x_g
00071 self.dist_g = dist_g
00072 self.goal_posture = goal_posture
00073 self.q_h_orient = q_h_orient
00074 self.q_g_orient = q_g_orient
00075 self.position_weight = position_weight
00076 self.orient_weight = orient_weight
00077 self.posture_weight = posture_weight
00078 self.force_weight = force_weight
00079 self.force_reduction_goal = force_reduction_goal
00080 self.control_point_joint_num = control_point_joint_num
00081 self.Kc_l = Kc_l
00082 self.Rc_l = Rc_l
00083 self.Jc_l = Jc_l
00084 self.Je = Je
00085 self.delta_f_min = delta_f_min
00086 self.delta_f_max = delta_f_max
00087 self.phi_curr = phi_curr
00088 self.K_j = K_j
00089 self.loc_l = loc_l
00090 self.n_l = n_l
00091 self.f_l = f_l
00092 self.f_n = f_n
00093 self.jerk_opt_weight = jerk_opt_weight
00094 self.max_force_mag = max_force_mag
00095 self.jep = jep
00096 self.time_step = time_step
00097 self.stop = stop
00098
00099
00100 def __str__(self):
00101 string = ""
00102 string += "MPC Data Structure:"
00103 string += "\nq: \t\t%s" % str(self.q)
00104 string += "\nx_h: \t\t%s" % str(self.x_h)
00105 string += "\nx_g: \t\t%s" % str(self.x_g)
00106 string += "\ndist_g: \t\t%s" % str(self.dist_g)
00107 string += "\nq_h_orient: \t\t%s" % str(self.q_h_orient)
00108 string += "\nq_g_orient: \t\t%s" % str(self.q_g_orient)
00109 string += "\nposition_weight: \t\t%s" % str(self.position_weight)
00110 string += "\norient_weight: \t\t%s" % str(self.orient_weight)
00111 string += "\ncontrol_point_joint_num: \t\t%s" % str(self.control_point_joint_num)
00112 string += "\nKc_l: \t\t%s" % str(self.Kc_l)
00113 string += "\nRc_l: \t\t%s" % str(self.Rc_l)
00114 string += "\nJc_l: \t\t%s" % str(self.Jc_l)
00115 string += "\nJe: \t\t%s" % str(self.Je)
00116 string += "\ndelta_f_min: \t\t%s" % str(self.delta_f_min)
00117 string += "\ndelta_f_max: \t\t%s" % str(self.delta_f_max)
00118 string += "\nphi_curr: \t\t%s" % str(self.phi_curr)
00119 string += "\nK_j: \t\t%s" % str(self.K_j)
00120 string += "\nloc_l: \t\t%s" % str(self.loc_l)
00121 string += "\nn_l: \t\t%s" % str(self.n_l)
00122 string += "\nf_l: \t\t%s" % str(self.f_l)
00123 string += "\nf_n: \t\t%s" % str(self.f_n)
00124 string += "\njerk_opt_weight: \t\t%s" % str(self.jerk_opt_weight)
00125 string += "\nmax_force_mag: \t\t%s" % str(self.max_force_mag)
00126 string += "\njep: \t\t%s" % str(self.jep)
00127 string += "\ntime_step: \t\t%s" % str(self.time_step)
00128 string += "\nstop: \t\t%s" % str(self.stop)
00129 return string
00130
00131
00132 class HapticMPC():
00133
00134
00135
00136 def __init__(self, opt, node_name="haptic_mpc"):
00137 rospy.loginfo("Initialising Haptic MPC")
00138 self.opt = opt
00139
00140 self.state_lock = threading.RLock()
00141 self.goal_lock = threading.RLock()
00142 self.monitor_lock = threading.RLock()
00143 self.gain_lock = threading.RLock()
00144 self.posture_lock = threading.RLock()
00145 self.mpc_data = None
00146 self.msg = None
00147
00148
00149 self.last_msg_time = None
00150 self.timeout = 0.50
00151 self.waiting_to_resume = False
00152 self.waiting_for_no_errors = False
00153 self.mpc_state = None
00154 self.mpc_error = None
00155
00156 self.joint_names = []
00157 self.joint_angles = []
00158 self.desired_joint_angles = []
00159 self.joint_velocities = []
00160 self.joint_stiffness = []
00161 self.joint_damping = []
00162
00163 self.end_effector_pos = None
00164 self.end_effector_orient_quat = None
00165
00166 self.skin_data = []
00167 self.Jc = []
00168 self.Je = []
00169
00170 self.time_step = 0.01
00171
00172
00173 self.goal_pos = None
00174 self.goal_orient_quat = None
00175 self.goal_posture = None
00176
00177
00178 self.orient_weight = 1.0
00179 self.pos_weight = 1.0
00180 self.posture_weight = 0.0
00181
00182 self.position_step = 0.01
00183 self.orient_step = np.radians(0.4)
00184 self.posture_step = np.radians(0.5)
00185
00186 self.deadzone_distance = 0.005
00187 self.deadzone_angle = 10.0
00188 self.currently_in_deadzone = False
00189
00190 self.mpc_enabled = True
00191
00192
00193 self.ma_to_m = multiarray_to_matrix.MultiArrayConverter()
00194
00195
00196 def initControlParametersFromServer(self):
00197 base_path = '/haptic_mpc'
00198 control_path = '/control_params'
00199
00200 rospy.loginfo("HapticMPC: Initialising controller parameters from server. Path: %s" % (base_path+control_path))
00201
00202
00203 self.allowable_contact_force = rospy.get_param(base_path + control_path + '/allowable_contact_force')
00204 self.max_delta_force_mag = rospy.get_param(base_path + control_path + '/max_delta_force_mag')
00205 self.stopping_force = rospy.get_param(base_path + control_path + '/stopping_force')
00206
00207 self.goal_velocity_for_hand = rospy.get_param(base_path + control_path + '/goal_velocity_for_hand')
00208 self.deadzone_distance = rospy.get_param(base_path + control_path + '/deadzone_distance')
00209 self.deadzone_angle = rospy.get_param(base_path + control_path + '/deadzone_angle')
00210
00211
00212 self.static_contact_stiffness_estimate = rospy.get_param(base_path + control_path + '/static_contact_stiffness_estimate')
00213 self.estimate_contact_stiffness = rospy.get_param(base_path + control_path + '/estimate_contact_stiffness')
00214
00215 self.orient_weight = rospy.get_param(base_path + control_path + '/orientation_weight')
00216 self.pos_weight = rospy.get_param(base_path + control_path + '/position_weight')
00217 self.posture_weight = rospy.get_param(base_path + control_path + '/posture_weight')
00218 self.force_weight = rospy.get_param(base_path + control_path + '/force_reduction_weight')
00219 self.jerk_opt_weight = rospy.get_param(base_path + control_path + '/jerk_opt_weight')
00220 self.mpc_weights_pub.publish(std_msgs.msg.Header(), self.pos_weight, self.orient_weight, self.posture_weight)
00221
00222
00223 self.max_theta_step = rospy.get_param(base_path + control_path + '/posture_step_size')
00224 self.theta_step_scale = rospy.get_param(base_path + control_path + '/posture_step_scale')
00225
00226 self.force_reduction_goal = rospy.get_param(base_path + control_path + '/force_reduction_goal')
00227
00228 self.frequency = rospy.get_param(base_path + control_path + '/frequency')
00229
00230
00231
00232
00233 def initRobot(self):
00234 base_path = '/haptic_mpc'
00235
00236 rospy.loginfo("Haptic MPC: Waiting for joint limit parameters to be set")
00237 while rospy.has_param(base_path + '/joint_limits/max') == False or rospy.has_param(base_path + '/joint_limits/min') == False:
00238 rospy.sleep(2.0)
00239 rospy.loginfo("Haptic MPC: Got joint limits, continuing")
00240 self.joint_limits_max = np.radians(rospy.get_param(base_path + '/joint_limits/max'))
00241 self.joint_limits_min = np.radians(rospy.get_param(base_path + '/joint_limits/min'))
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 def getSkinData(self):
00270 with self.state_lock:
00271 skin_data = copy.copy(self.skin_data)
00272 return skin_data
00273
00274
00275
00276 def getJointAngles(self):
00277 with self.state_lock:
00278 joint_angles = copy.copy(self.joint_angles)
00279 return joint_angles
00280
00281
00282
00283 def getDesiredJointAngles(self):
00284 with self.state_lock:
00285 desired_joint_angles = copy.copy(self.desired_joint_angles)
00286 return desired_joint_angles
00287
00288
00289
00290 def getJointStiffness(self):
00291 with self.state_lock:
00292 joint_stiffness = copy.copy(self.joint_stiffness)
00293 return joint_stiffness
00294
00295
00296
00297 def getMPCData(self):
00298 with lock:
00299 return copy.copy(self.mpc_data)
00300
00301
00302
00303
00304 def initMPCData(self):
00305
00306
00307 with self.state_lock:
00308 q = copy.copy(self.joint_angles)
00309 q_des = copy.copy(self.desired_joint_angles)
00310 Jc = copy.copy(self.Jc)
00311 skin_data = copy.copy(self.skin_data)
00312 ee_pos = copy.copy(self.end_effector_pos)
00313 ee_orient_quat = copy.copy(self.end_effector_orient_quat)
00314 joint_stiffness = copy.copy(self.joint_stiffness)
00315 Je = copy.copy(self.Je)
00316
00317
00318 with self.goal_lock:
00319 goal_pos = copy.copy(self.goal_pos)
00320 goal_orient_quat = copy.copy(self.goal_orient_quat)
00321
00322 with self.posture_lock:
00323 goal_posture = copy.copy(self.goal_posture)
00324
00325 n_l = haptic_mpc_util.getNormals(skin_data)
00326 f_l = haptic_mpc_util.getValues(skin_data)
00327 loc_l = haptic_mpc_util.getLocations(skin_data)
00328
00329
00330 k_default = self.static_contact_stiffness_estimate
00331 dist_g = self.time_step * self.goal_velocity_for_hand
00332
00333
00334 Kc_l = self.contactStiffnessMatrix(n_l, k_default)
00335 Rc_l = self.contactForceTransformationMatrix(n_l)
00336
00337
00338
00339 tmp_l = [R_ci * f_ci for R_ci, f_ci in it.izip(Rc_l, f_l)]
00340 f_n = np.matrix([tmp_i[0,0] for tmp_i in tmp_l]).T
00341
00342 delta_f_min, delta_f_max = self.deltaForceBounds(f_n,
00343 max_pushing_force = self.allowable_contact_force,
00344 max_pulling_force = self.allowable_contact_force,
00345 max_pushing_force_increase = self.max_delta_force_mag,
00346 max_pushing_force_decrease = self.max_delta_force_mag,
00347 min_decrease_when_over_max_force = 0.,
00348 max_decrease_when_over_max_force = 10.0)
00349
00350 q_des_matrix = (np.matrix(q_des)[0:len(q_des)]).T
00351
00352 K_j = np.diag(joint_stiffness)
00353
00354 if len(Je) >= 1:
00355 Je = Je[0]
00356
00357
00358 with self.gain_lock:
00359 orient_weight = self.orient_weight
00360 position_weight = self.pos_weight
00361 posture_weight = self.posture_weight
00362 planar = False
00363
00364
00365
00366
00367 x_h = ee_pos
00368 x_g = goal_pos
00369 if x_g == None:
00370 x_g = x_h
00371
00372
00373 q_h_orient = ee_orient_quat
00374 q_g_orient = goal_orient_quat
00375 if q_g_orient == None:
00376 q_g_orient = q_h_orient
00377
00378
00379 if goal_posture == None:
00380 goal_posture = q
00381
00382 dist_goal_2D = np.linalg.norm((x_g - x_h)[0:2])
00383 dist_goal_3D = np.linalg.norm(x_g - x_h)
00384
00385
00386
00387 dist_goal = dist_goal_3D
00388
00389 angle_error = ut.quat_angle(q_h_orient, q_g_orient)
00390
00391 jerk_opt_weight = self.jerk_opt_weight
00392
00393 if orient_weight != 0:
00394 proportional_ball_radius = 0.1
00395 proportional_ball_dist_slope = 1.0
00396 if dist_goal < proportional_ball_radius:
00397 position_weight = position_weight * dist_goal/ (proportional_ball_radius * proportional_ball_dist_slope)
00398
00399 jerk_opt_weight = max(jerk_opt_weight * position_weight * 2, jerk_opt_weight)
00400
00401 proportional_ball_angle = math.radians(30)
00402 proportional_ball_angle_slope = 1.
00403 if angle_error < proportional_ball_angle:
00404 orient_weight = orient_weight * angle_error/ (proportional_ball_angle * proportional_ball_angle_slope)
00405
00406
00407
00408 mpc_data = MPCData( q=q,
00409 x_h = x_h,
00410 x_g = x_g,
00411 dist_g = dist_g,
00412 goal_posture = goal_posture,
00413 q_h_orient = q_h_orient,
00414 q_g_orient = q_g_orient,
00415 position_weight = position_weight,
00416 orient_weight = orient_weight,
00417 posture_weight = posture_weight,
00418 force_weight = 0.0005,
00419 force_reduction_goal = self.force_reduction_goal,
00420 control_point_joint_num = len(q),
00421 Kc_l = Kc_l,
00422 Rc_l = Rc_l,
00423 Jc_l = Jc,
00424 Je = Je,
00425 delta_f_min = delta_f_min,
00426 delta_f_max = delta_f_max,
00427 phi_curr = q_des_matrix,
00428 K_j = K_j,
00429 loc_l = loc_l,
00430 n_l = n_l,
00431 f_l = f_l,
00432 f_n = f_n,
00433 jerk_opt_weight = jerk_opt_weight,
00434 max_force_mag = self.allowable_contact_force,
00435 jep = q_des,
00436 time_step = self.time_step,
00437 stop = False)
00438 return mpc_data
00439
00440
00441
00442 def updateWeightsCallback(self, msg):
00443 with self.gain_lock:
00444 rospy.loginfo("Updating MPC weights. Pos: %s, Orient: %s, Posture: %s" % (str(msg.position_weight), str(msg.orient_weight), str(msg.posture_weight)))
00445 self.pos_weight = msg.position_weight
00446 self.orient_weight = msg.orient_weight
00447 self.posture_weight = msg.posture_weight
00448 self.mpc_weights_pub.publish(msg)
00449
00450
00451
00452 def goalPoseCallback(self, msg):
00453 with self.goal_lock:
00454 self.goal_pos = np.matrix([[msg.pose.position.x], [msg.pose.position.y], [msg.pose.position.z]])
00455 self.goal_orient_quat = [msg.pose.orientation.x, msg.pose.orientation.y, msg.pose.orientation.z, msg.pose.orientation.w]
00456
00457
00458
00459
00460 def goalPostureCallback(self, msg):
00461 with self.posture_lock:
00462 self.goal_posture = msg.data
00463
00464
00465
00466
00467 def mpcMonitorCallback(self, msg):
00468 with self.monitor_lock:
00469 self.mpc_state = msg.state
00470 self.mpc_error = msg.error
00471
00472
00473
00474 def robotStateCallback(self, msg):
00475 with self.state_lock:
00476 self.last_msg_time = rospy.Time.now()
00477
00478 self.msg = msg
00479 self.joint_names = msg.joint_names
00480 self.joint_angles = list(msg.joint_angles)
00481 self.desired_joint_angles = list(msg.desired_joint_angles)
00482 self.joint_velocities= list(msg.joint_velocities)
00483 self.joint_stiffness = list(msg.joint_stiffness)
00484 self.joint_damping = list(msg.joint_damping)
00485
00486 self.end_effector_pos = np.matrix([[msg.hand_pose.position.x], [msg.hand_pose.position.y], [msg.hand_pose.position.z]])
00487 self.end_effector_orient_quat = [msg.hand_pose.orientation.x, msg.hand_pose.orientation.y, msg.hand_pose.orientation.z, msg.hand_pose.orientation.w]
00488
00489 self.skin_data = msg.skins
00490
00491 self.Je = self.ma_to_m.multiArrayToMatrixList(msg.end_effector_jacobian)
00492 self.Jc = self.ma_to_m.multiArrayToMatrixList(msg.contact_jacobians)
00493
00494
00495
00496
00497
00498
00499 def goalOrientationInQuat(self, q_h_orient, q_g_orient, max_ang_step):
00500
00501 if not q_g_orient:
00502 q_g_orient = q_h_orient
00503
00504 ang = ut.quat_angle(q_h_orient, q_g_orient)
00505 ang_mag = abs(ang)
00506 step_fraction = 0.1
00507 if step_fraction * ang_mag > max_ang_step:
00508
00509 step_fraction = max_ang_step / ang_mag
00510
00511 interp_q_goal = tr.tft.quaternion_slerp(q_h_orient, q_g_orient, step_fraction)
00512 delta_q_des = tr.tft.quaternion_multiply(interp_q_goal, tr.tft.quaternion_inverse(q_h_orient))
00513
00514 return np.matrix(delta_q_des[0:3]).T
00515
00516
00517
00518
00519
00520 def goalMotionForHand(self, x_h, x_g, dist_g):
00521
00522 if x_g == None or x_g.size == 0:
00523 x_g = x_h
00524
00525 err = x_g - x_h
00526 err_mag = np.linalg.norm(err)
00527
00528
00529
00530
00531
00532 scale = 15.0
00533 if err_mag > dist_g * scale:
00534 delta_x_g = dist_g * (err/err_mag)
00535 else:
00536 delta_x_g = err/scale
00537
00538 return delta_x_g
00539
00540
00541
00542
00543
00544 def goalDeltaPosture(self, goal_posture, current_posture, max_theta_step, num_steps_scale):
00545 assert max_theta_step >= 0
00546 assert num_steps_scale >= 0
00547
00548 delta_theta_des = np.matrix(goal_posture).T - np.matrix(current_posture).T
00549
00550
00551
00552
00553
00554 for i in range(len(delta_theta_des)):
00555 theta = delta_theta_des[i]
00556
00557 if abs(theta) > num_steps_scale * max_theta_step:
00558 theta = max_theta_step * theta/abs(theta)
00559 else:
00560 theta = theta/num_steps_scale
00561
00562
00563 delta_theta_des[i] = theta
00564
00565 return delta_theta_des
00566
00567
00568
00569
00570
00571
00572 def deltaQpJepGen(self, mpc_dat):
00573
00574 if mpc_dat == None:
00575 return None
00576
00577
00578 dist_to_goal = np.linalg.norm(mpc_dat.x_h - mpc_dat.x_g)
00579 ang_to_goal = np.degrees(ut.quat_angle(mpc_dat.q_h_orient, mpc_dat.q_g_orient))
00580 dist_g = mpc_dat.dist_g
00581 ang_dist_g = self.orient_step
00582
00583
00584 in_deadzone = False
00585
00586 if (mpc_dat.orient_weight > 0.0 and mpc_dat.position_weight > 0.0):
00587 if abs(dist_to_goal) < self.deadzone_distance and abs(ang_to_goal) < self.deadzone_angle:
00588 in_deadzone = True
00589 elif mpc_dat.position_weight > 0.0:
00590 if abs(dist_to_goal) < self.deadzone_distance:
00591 in_deadzone = True
00592 elif mpc_dat.orient_weight > 0.0:
00593 if abs(ang_to_goal) < self.deadzone_angle:
00594 in_deadzone = True
00595
00596
00597 if in_deadzone:
00598 dist_g = 0.0
00599 ang_dist_g = 0.0
00600 if self.currently_in_deadzone == False:
00601 rospy.loginfo("MPC is in deadzone: pos %s (%s); orient %s (%s)" % (str(dist_to_goal), str(self.deadzone_distance), str(ang_to_goal), str(self.deadzone_angle) ))
00602 self.currently_in_deadzone = True
00603
00604
00605 if len(mpc_dat.loc_l) == 0:
00606 return [0.0] * len(self.joint_angles)
00607
00608 else:
00609 self.currently_in_deadzone = False
00610
00611
00612 delta_pos_g = self.goalMotionForHand(mpc_dat.x_h,
00613 mpc_dat.x_g,
00614 dist_g)
00615
00616
00617 delta_orient_g = self.goalOrientationInQuat(mpc_dat.q_h_orient,
00618 mpc_dat.q_g_orient,
00619 ang_dist_g)
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 delta_x_g = np.vstack( (delta_pos_g, delta_orient_g) )
00651
00652 J_h = mpc_dat.Je
00653 T_quat = 0.5 * (mpc_dat.q_h_orient[3]
00654 * np.matrix(np.eye(3))
00655 - haptic_mpc_util.getSkewMatrix(mpc_dat.q_h_orient[0:3]))
00656
00657 J_h[3:] = T_quat*J_h[3:]
00658
00659 J_h[0:3] = J_h[0:3]
00660 J_h[3:] = J_h[3:]
00661
00662
00663
00664
00665
00666 if delta_x_g.shape[0] == 3:
00667 mpc_dat.force_weight = 0.0005
00668 elif delta_x_g.shape[0] == 6:
00669 mpc_dat.force_weight = 0.005
00670
00671 n_joints = mpc_dat.K_j.shape[0]
00672 J_h[:, mpc_dat.control_point_joint_num:] = 0.
00673 J_h = np.matrix(J_h[:,0:n_joints])
00674
00675
00676
00677 q_diff = np.array(mpc_dat.jep) - np.array(mpc_dat.q)
00678 max_q_diff = np.max(np.abs(q_diff))
00679 if max_q_diff > 15.0:
00680
00681 rospy.loginfo("JEPs too far from current position - resetting them to current position")
00682 self.publishDesiredJointAngles(self.getJointAngles())
00683 return None
00684
00685
00686 delta_theta_des = self.goalDeltaPosture(mpc_dat.goal_posture, mpc_dat.q, self.max_theta_step, self.theta_step_scale)
00687 if len(delta_theta_des) > n_joints:
00688 delta_theta_des = delta_theta_des[0:n_joints]
00689
00690
00691
00692
00693 cost_quadratic_matrices, cost_linear_matrices, \
00694 constraint_matrices, \
00695 constraint_vectors, lb, ub = esm.convert_to_qp_posture(J_h,
00696 mpc_dat.Jc_l,
00697 mpc_dat.K_j,
00698 mpc_dat.Kc_l,
00699 mpc_dat.Rc_l,
00700 mpc_dat.delta_f_min,
00701 mpc_dat.delta_f_max,
00702 mpc_dat.phi_curr,
00703 delta_x_g, mpc_dat.f_n, mpc_dat.q,
00704 self.joint_limits_min,
00705 self.joint_limits_max,
00706 mpc_dat.jerk_opt_weight,
00707 mpc_dat.max_force_mag,
00708 delta_theta_des,
00709 mpc_dat.posture_weight,
00710 mpc_dat.position_weight,
00711 mpc_dat.orient_weight,
00712 mpc_dat.force_weight,
00713 mpc_dat.force_reduction_goal)
00714
00715
00716
00717 lb = lb[0:n_joints]
00718 ub = ub[0:n_joints]
00719
00720 delta_phi_opt, opt_error, feasible = esm.solve_qp(cost_quadratic_matrices,
00721 cost_linear_matrices,
00722 constraint_matrices,
00723 constraint_vectors,
00724 lb, ub,
00725 debug_qp=False)
00726
00727
00728 mpc_dat.jep[0:n_joints] = (mpc_dat.phi_curr[0:n_joints] + delta_phi_opt).A1
00729 delta_phi = np.zeros(len(self.joint_names))
00730 delta_phi[0:n_joints] = delta_phi_opt.T
00731
00732
00733
00734
00735
00736
00737
00738 return delta_phi
00739
00740
00741
00742
00743
00744
00745 def contactStiffnessMatrix(self, n_l, k_default, k_est_min=100.0, k_est_max=100000.0):
00746
00747
00748
00749
00750 Kc_l = []
00751 for n_ci in it.izip(n_l):
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 n_ci = np.nan_to_num(n_ci)
00774 K_ci = k_default * np.outer(n_ci, n_ci)
00775
00776 Kc_l.append(np.matrix(K_ci))
00777 return Kc_l
00778
00779
00780
00781
00782 def contactForceTransformationMatrix(self, n_l):
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 Rc_l = []
00801 for n_ci in n_l:
00802
00803
00804 R_ci = np.matrix(np.zeros((1,3)))
00805 R_ci[:] = n_ci[:].T
00806 Rc_l.append(R_ci)
00807 return Rc_l
00808
00809
00810
00811
00812 def deltaForceBounds(self, f_n,
00813 max_pushing_force, max_pulling_force,
00814 max_pushing_force_increase, max_pushing_force_decrease,
00815 min_decrease_when_over_max_force,
00816 max_decrease_when_over_max_force):
00817
00818
00819
00820 assert (max_pushing_force >= 0.0), "delta_f_bounds: max_pushing_force = %f < 0.0" % max_pushing_force
00821 assert (max_pushing_force_increase >= 0.0), "delta_f_bounds: max_pushing_force_increase = %f < 0.0" % max_pushing_force_increase
00822 assert (max_pushing_force_decrease >= 0.0), "delta_f_bounds: max_pushing_force_decrease = %f < 0.0" % max_pushing_force_decrease
00823 assert (max_pulling_force >= 0.0), "delta_f_bounds: max_pulling_force = %f < 0.0" % max_pulling_force
00824 assert (min_decrease_when_over_max_force >= 0.0), "delta_f_bounds: min_decrease_when_over_max_force = %f < 0.0" % min_decrease_when_over_max_force
00825 assert (max_decrease_when_over_max_force >= 0.0), "delta_f_bounds: max_decrease_when_over_max_force = %f < 0.0" % max_decrease_when_over_max_force
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838 n = f_n.shape[0]
00839 f_max = max_pushing_force * np.matrix(np.ones((n,1)))
00840 delta_f_max = f_max - f_n
00841
00842
00843
00844 delta_f_max = np.minimum(delta_f_max,
00845 max_pushing_force_increase * np.matrix(np.ones((n,1))))
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 f_min = -max_pulling_force * np.matrix(np.ones((n,1)))
00856 delta_f_min = f_min - f_n
00857
00858
00859 delta_f_min = np.maximum(delta_f_min,
00860 -max_pushing_force_decrease * np.matrix(np.ones((n,1))))
00861
00862
00863
00864 delta_f_min[np.where(delta_f_min<=0)]=-10000
00865
00866
00867 over_max = f_n > max_pushing_force
00868 if over_max.any():
00869
00870 delta_f_max[over_max] = -min_decrease_when_over_max_force
00871 delta_f_min[over_max] = -max_decrease_when_over_max_force
00872
00873 return delta_f_min, delta_f_max
00874
00875
00876
00877 def publishDeltaControlValues(self, ctrl_data):
00878 msg = hrl_msgs.msg.FloatArrayBare()
00879 msg.data = ctrl_data
00880 self.delta_q_des_pub.publish(msg)
00881
00882
00883
00884 def publishDesiredJointAngles(self, ctrl_data):
00885 msg = hrl_msgs.msg.FloatArrayBare()
00886 msg.data = ctrl_data
00887 self.q_des_pub.publish(msg)
00888
00889
00890 def updateController(self):
00891
00892 if not self.mpc_enabled:
00893 return
00894
00895
00896 with self.state_lock:
00897 time_since_last_msg = rospy.Time.now() - self.last_msg_time
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 with self.monitor_lock:
00914 mpc_state = copy.copy(self.mpc_state)
00915 mpc_error = copy.copy(self.mpc_error)
00916
00917 if mpc_error != None and len(mpc_error) > 0:
00918 if self.waiting_for_no_errors == False:
00919 rospy.logwarn("HapticMPC: MPC monitor detected error conditions. Stopping control effort.\nState:\n%s\nErrors:\n%s" % (str(mpc_state), str(mpc_error)))
00920 self.waiting_for_no_errors = True
00921 return
00922 else:
00923 if self.waiting_for_no_errors == True:
00924 self.waiting_for_no_errors = False
00925 rospy.logwarn("HapticMPC: MPC resumed control - errors cleared.")
00926
00927
00928 mpc_data = self.initMPCData()
00929 desired_joint_pos = self.deltaQpJepGen(mpc_data)
00930 if desired_joint_pos == None:
00931 desired_joint_pos = [0.0] * len(self.joint_angles)
00932 self.publishDeltaControlValues(desired_joint_pos)
00933
00934
00935
00936 def initComms(self, node_name):
00937 rospy.init_node(node_name)
00938 self.robot_state_sub = rospy.Subscriber("/haptic_mpc/robot_state", haptic_msgs.RobotHapticState, self.robotStateCallback)
00939 self.goal_pose_sub = rospy.Subscriber("/haptic_mpc/traj_pose", geometry_msgs.msg.PoseStamped, self.goalPoseCallback)
00940 self.goal_posture_sub = rospy.Subscriber("/haptic_mpc/goal_posture", hrl_msgs.msg.FloatArray, self.goalPostureCallback)
00941
00942 self.delta_q_des_pub= rospy.Publisher("/haptic_mpc/delta_q_des", hrl_msgs.msg.FloatArrayBare)
00943 self.q_des_pub = rospy.Publisher("/haptic_mpc/q_des", hrl_msgs.msg.FloatArrayBare)
00944
00945 self.mpc_monitor_sub = rospy.Subscriber("/haptic_mpc/mpc_state", haptic_msgs.HapticMpcState, self.mpcMonitorCallback)
00946
00947 self.mpc_weights_sub = rospy.Subscriber("haptic_mpc/weights", haptic_msgs.HapticMpcWeights, self.updateWeightsCallback)
00948 self.mpc_weights_pub = rospy.Publisher("haptic_mpc/current_weights", haptic_msgs.HapticMpcWeights, latch=True)
00949
00950 self.enable_mpc_srv = rospy.Service("/haptic_mpc/enable_mpc", haptic_srvs.EnableHapticMPC, self.enableHapticMPC)
00951
00952
00953 def enableHapticMPC(req):
00954 if req.new_state == "enabled":
00955 self.mpc_enabled = True
00956 else:
00957 self.mpc_enabled = False
00958
00959 return haptic_srvs.EnableHapticMPCResponse(self.mpc_state)
00960
00961
00962
00963 def signal_handler(self, signal, frame):
00964 print 'Ctrl+C pressed - exiting'
00965 sys.exit(0)
00966
00967
00968
00969 def start(self):
00970 signal.signal(signal.SIGINT, self.signal_handler)
00971
00972 self.initRobot()
00973 self.initComms("haptic_mpc")
00974 rospy.sleep(1.0)
00975 self.initControlParametersFromServer()
00976
00977 r = rospy.Rate(self.frequency)
00978 self.time_step = 1.0/self.frequency
00979
00980 rospy.loginfo("HapticMPC: Waiting for Robot Haptic State message")
00981 while not self.getJointAngles():
00982 r.sleep()
00983 rospy.loginfo("HapticMPC: Got Robot Haptic State message")
00984
00985 rospy.loginfo("HapticMPC: Resetting desired joint angles to current position")
00986 self.publishDesiredJointAngles(self.getJointAngles())
00987
00988
00989 rospy.loginfo("HapticMPC: Starting MPC")
00990 while not rospy.is_shutdown():
00991 self.updateController()
00992
00993 r.sleep()
00994
00995 if __name__== "__main__":
00996 import optparse
00997 p = optparse.OptionParser()
00998 haptic_mpc_util.initialiseOptParser(p)
00999 opt = haptic_mpc_util.getValidInput(p)
01000
01001 mpc_controller = HapticMPC(opt, "haptic_mpc")
01002 mpc_controller.start()
01003