00001
00002 import roslib
00003 roslib.load_manifest('pr2_omni_teleop')
00004
00005 import rospy
00006 import tf
00007 import math
00008 import actionlib
00009 import tf.transformations as tr
00010 import numpy as np
00011 import hrl_lib.tf_utils as tfu
00012 import coefficients as coeff
00013
00014
00015 from geometry_msgs.msg import PoseStamped
00016 from geometry_msgs.msg import Wrench
00017 from geometry_msgs.msg import Twist
00018 from phantom_omni.msg import PhantomButtonEvent
00019 from teleop_controllers.msg import JTTeleopControllerState
00020 from actionlib_msgs.msg import *
00021 from pr2_controllers_msgs.msg import *
00022 from pr2_msgs.msg import AccelerometerState
00023
00024
00025 class ForceFeedbackFilter:
00026
00027 def __init__(self, wrench_topic, dest_frame, wrench_frame, force_feedback_topic, tflistener, kp_name, kd_name):
00028 self.wrench_frame = wrench_frame
00029 self.dest_frame = dest_frame
00030 self.tflistener = tflistener
00031 self.omni_fb = rospy.Publisher(force_feedback_topic, Wrench)
00032
00033
00034 self.filtered_fb = rospy.Publisher('/test_filtered_fb', Wrench)
00035
00036
00037 rospy.Subscriber(wrench_topic, JTTeleopControllerState, self.wrench_callback)
00038 self.enable = False
00039 self.FIR = coeff.coefficients
00040 self.history = np.matrix(np.zeros((3,17)))
00041 self.prev_time = rospy.Time.now().nsecs*1e-9
00042 self.prev_dt = 0.0
00043 self.omni_max_limit = np.array([5., 5., 5.])
00044 self.omni_min_limit = np.array([-5., -5., -5.])
00045 self.kp = rospy.get_param(kp_name)
00046 self.kd = rospy.get_param(kd_name)
00047 self.force_scaling = -0.025
00048 self.force_old = np.zeros(3)
00049
00050 def set_force_scaling(self, scalar):
00051 self.force_scaling = -1.*scalar
00052
00053 def set_enable(self, v):
00054 self.enable = v
00055
00056 def wrench_callback(self, state):
00057
00058 x_err = np.matrix([state.x_err.linear.x, state.x_err.linear.y, state.x_err.linear.z]).T
00059 x_dot = np.matrix([state.xd.linear.x, state.xd.linear.y, state.xd.linear.z]).T
00060 feedback = -1.0*self.kp*x_err-self.kd*x_dot
00061
00062
00063
00064 wr_ee = [feedback[0,0], feedback[1,0], feedback[2,0]]
00065
00066
00067 shift_right = np.array(self.history[:,0:self.FIR.size-1])
00068 new_col = np.array(wr_ee).reshape((3,1))
00069 self.history = np.matrix(np.hstack((new_col, shift_right)))
00070 wr_ee_filt = self.history*self.FIR
00071
00072
00073 df_R_ee = tfu.rotate(self.dest_frame, 'torso_lift_link', self.tflistener) * \
00074 tfu.rotate('torso_lift_link', self.wrench_frame, self.tflistener)
00075 wr_df = self.force_scaling*np.array(tr.translation_from_matrix(df_R_ee * tfu.translation_matrix([wr_ee_filt[0,0], wr_ee_filt[1,0], wr_ee_filt[2,0]])))
00076
00077
00078 wr_df = np.where(wr_df>self.omni_max_limit, self.omni_max_limit, wr_df)
00079 wr_df = np.where(wr_df<self.omni_min_limit, self.omni_min_limit, wr_df)
00080
00081 wr = Wrench()
00082 wr.force.x = wr_df[0,0]
00083 wr.force.y = wr_df[1,0]
00084 wr.force.z = wr_df[2,0]
00085
00086
00087 if self.enable == False:
00088 self.filtered_fb.publish(wr)
00089
00090 if self.enable == True:
00091 self.omni_fb.publish(wr)
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 class FF_PR2Teleop:
00104 def __init__(self):
00105 rospy.init_node('pr2_omni_force_feedback')
00106 self.tfbroadcast = tf.TransformBroadcaster()
00107
00108 self.tflistener = tf.TransformListener()
00109
00110
00111
00112
00113
00114
00115
00116 self.right_feedback = ForceFeedbackFilter(wrench_topic = '/r_cart/state',
00117 dest_frame = '/omni2_sensable',
00118 wrench_frame = '/r_gripper_tool_frame',
00119 force_feedback_topic = 'omni2_force_feedback',
00120 tflistener = self.tflistener,
00121 kp_name = '/r_cart/cart_gains/trans/p',
00122 kd_name = '/r_cart/cart_gains/trans/d')
00123 rospy.Subscriber('omni1_button', PhantomButtonEvent, self.omni_safety_lock_cb)
00124 rospy.Subscriber('omni2_button', PhantomButtonEvent, self.omni_safety_lock_cb)
00125
00126 def omni_safety_lock_cb(self, msg):
00127 if msg.grey_button == 1 and msg.white_button == 1:
00128 self.set_state(not self.enabled)
00129
00130 def set_state(self, s):
00131 self.enabled = s
00132 if self.enabled:
00133 rospy.loginfo('control ENABLED.')
00134
00135 self.right_feedback.set_enable(True)
00136 else:
00137 rospy.loginfo('control disabled. Follow potential well to pose of arm.')
00138
00139 self.right_feedback.set_enable(False)
00140
00141 def run(self):
00142 rate = rospy.Rate(100.0)
00143 rospy.loginfo('running...')
00144 rospy.spin()
00145
00146 if __name__ == '__main__':
00147
00148
00149 o = FF_PR2Teleop()
00150 o.run()
00151
00152
00153
00154