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 import time, serial
00034 import serial
00035
00036 class FTSensor:
00037 """
00038 Instantiate to poll the force/torque sensor of your choice.
00039 Must continually poll, running anything else in the same
00040 process will result in many failed reads and/or incorrect
00041 values!
00042 """
00043 def __init__(self, dev, baudrate=19200):
00044 print 'FTSensor: opening serial port (baudrate =', baudrate, ')'
00045 self.ftcon = serial.Serial(dev,timeout=0.1)
00046 print 'FTSensor: setting properties'
00047 self.ftcon.setBaudrate(baudrate)
00048 self.ftcon.setParity('N')
00049 self.ftcon.setStopbits(1)
00050 self.ftcon.open()
00051
00052
00053 count = 0
00054 self.reset_time = None
00055 self.reset()
00056 while not self._start_query():
00057 rospy.logwarn('FTSensor: resetting')
00058 count = count + 1
00059 self.reset()
00060 if count == 10:
00061 rospy.logfatal('FTSensor.__init__: Too many resets. Try manually restarting FT sensors.')
00062
00063
00064 self.last_value = []
00065
00066 def read(self):
00067 '''
00068 Try to return a fresh reading *always*
00069 '''
00070 current_value = self.last_value
00071 while current_value == self.last_value:
00072 t = self.ftcon.read(19)
00073
00074 if len(t) < 1 or ord(t[0]) != 0 or len(t) < 10:
00075
00076
00077 print 'exiting due to if len(t) < 1 or ord(t[0]) != 0 or len(t) < 10'
00078 print 't is', t
00079 exit()
00080 while not self._start_query():
00081
00082 print 'exiting due to not self._start_query()'
00083 print 't is', t
00084 exit()
00085 break
00086 else:
00087 current_value = t
00088
00089
00090 self.last_value = current_value
00091 return current_value
00092
00093 def read_ft(self):
00094 f = binary_to_ft(self.read())
00095
00096 if abs(f[0]) > 500.0:
00097 exit()
00098 return f
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 def _start_query( self ):
00132 self.ftcon.write('QS\r')
00133 t = self.ftcon.read(5)
00134 if 5 == len(t):
00135 st = 'QS: '
00136 for i in range(5):
00137 st += str(ord(t[i])) + '\t'
00138 return True
00139 else:
00140 return False
00141
00142
00143 def _stop_query(self):
00144 self.ftcon.write('\r')
00145 self.ftcon.flushInput()
00146 self.ftcon.flush()
00147 t = self.ftcon.readlines(3)
00148
00149
00150 def reset(self):
00151 ctime = time.time()
00152 if self.reset_time != None:
00153 if ctime - self.reset_time < 2:
00154 self.reset_time = ctime
00155 return
00156 self.reset_time = ctime
00157 print 'FTSensor.reset(): Resetting at time', time.ctime()
00158
00159 self._stop_query()
00160 self.ftcon.write('CD B\r')
00161 t = self.ftcon.readlines(2)
00162
00163 self.ftcon.write('SA 16\r')
00164 t = self.ftcon.readlines(2)
00165
00166 self.ftcon.write('SF\r')
00167 t = self.ftcon.readlines(2)
00168
00169 self.ftcon.write('CF\r')
00170 t = self.ftcon.readlines(2)
00171
00172
00173
00174 self.ftcon.write('CD R\r')
00175 t = self.ftcon.readlines(2)
00176
00177 self.ftcon.write('CF 1\r')
00178 t = self.ftcon.readlines(2)
00179
00180 self.ftcon.write('SF\r')
00181 t = self.ftcon.readlines(2)
00182
00183 self._zero_bias()
00184 self.ftcon.write('SZ\r')
00185 t = self.ftcon.readlines(2)
00186
00187
00188
00189
00190 def _zero_bias(self):
00191 """Don't use, now biased in software"""
00192 self.ftcon.write('SZ\r')
00193 t = self.ftcon.readlines(4)
00194
00195
00196
00197 def binary_to_ft( raw_binary ):
00198 counts_per_force = 192
00199 counts_per_torque = 10560
00200
00201
00202
00203
00204 Fx = ord(raw_binary[1])*65536+ord(raw_binary[2])*256+ord(raw_binary[3])
00205 Fy = ord(raw_binary[4])*65536+ord(raw_binary[5])*256+ord(raw_binary[6])
00206 Fz = ord(raw_binary[7])*65536+ord(raw_binary[8])*256+ord(raw_binary[9])
00207 Tx = ord(raw_binary[10])*65536+ord(raw_binary[11])*256+ord(raw_binary[12])
00208 Ty = ord(raw_binary[13])*65536+ord(raw_binary[14])*256+ord(raw_binary[15])
00209 Tz = ord(raw_binary[16])*65536+ord(raw_binary[17])*256+ord(raw_binary[18])
00210
00211 _temp_val = []
00212 for c,list in zip([counts_per_force, counts_per_torque], [[Fx,Fy,Fz], [Tx,Ty,Tz]]):
00213 for val in list:
00214 if val > 8388607:
00215 val -= 16777216
00216 val /= float(c)
00217 _temp_val.append(val)
00218
00219 Fx = _temp_val[0]
00220 Fy = _temp_val[1]
00221 Fz = -_temp_val[2]
00222 Tx = _temp_val[3]
00223 Ty = _temp_val[4]
00224 Tz = _temp_val[5]
00225
00226 return [Fx,Fy,Fz,Tx,Ty,Tz]
00227
00228
00229 if __name__ == '__main__':
00230 import optparse
00231 p = optparse.OptionParser()
00232 p.add_option('--mode', action='store', default='run', type='string',
00233 dest='mode', help='either "test" or "run"')
00234 p.add_option('--name', action='store', default='ft1', type='string',
00235 dest='name', help='name of sensor')
00236 p.add_option('--path', action='store', default='/dev/robot/fingerFT1', type = 'string',
00237 dest='path', help='path to force torque device in (linux)')
00238 p.add_option('--baudrate', action='store', default=19200, type = 'int',
00239 dest='baudrate',
00240 help='baudrate that force torque boxes are running at (VERY IMPORTANT!)')
00241 opt, args = p.parse_args()
00242 print 'FTSensor: Reading from', opt.path
00243
00244 if opt.mode == 'run':
00245 import roslib; roslib.load_manifest('force_torque')
00246 import rospy
00247 import hrl_lib.rutils as ru
00248 from force_torque.srv import *
00249 import numpy as np
00250 import time
00251
00252 node_name = 'FT_poller_' + opt.name
00253 service_name = 'FTRelay_' + opt.name + '_set_ft'
00254
00255 rospy.init_node(node_name)
00256 print node_name + ': waiting for service', service_name
00257 rospy.wait_for_service(service_name)
00258 ft_server_set_ft = rospy.ServiceProxy(service_name, StringService)
00259 ftsensor = FTSensor(opt.path, baudrate=opt.baudrate)
00260
00261 times = []
00262 print node_name + ': Retrieving sensor data and sending to FTRelay on service', service_name
00263
00264 while not rospy.is_shutdown():
00265 v = ftsensor.read()
00266
00267
00268 t = rospy.get_time()
00269
00270 try:
00271 ft_server_set_ft(v, t)
00272 except rospy.ServiceException, e:
00273 print "Service call failed %s" % e
00274
00275 print 'rospy is not shutdown', not rospy.is_shutdown()
00276
00277
00278
00279
00280
00281
00282 if opt.mode == 'test':
00283 print 'testing...'
00284 import numpy as np
00285
00286
00287 print 'Testing', opt.path
00288 sensor1 = FTSensor(opt.path, opt.baudrate)
00289
00290 tlist = []
00291 for i in range(200):
00292 t0 = time.time()
00293 v1 = sensor1.read_ft()
00294 t1 = time.time()
00295 tlist.append(t1 - t0)
00296 print np.linalg.norm(v1)
00297
00298
00299
00300