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 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 from pcan_python.pcan_library import *
00044 
00045 
00046 from puck_properties_consts import*
00047 from ctypes import *
00048 import time
00049 
00050 BASE_TYPE = 0
00051 TIP_TYPE = 1
00052 SPREAD_TYPE = 2
00053 BASE_LIMIT = 140.0
00054 TIP_LIMIT = 48.0
00055 SPREAD_LIMIT = 180.0
00056 
00057 HAND_GROUP = 0x405
00058 
00059 
00060 F1_POSITION = 0x563
00061 F2_POSITION = 0x583
00062 F3_POSITION = 0x5A3
00063 SPREAD_POSITION = 0x5C3
00064 F1_STRAIN       = 0x566
00065 F2_STRAIN       = 0x586
00066 F3_STRAIN       = 0x5A6
00067 STRAIN_ID   = 0x99
00068 F1_MOTOR_TEMP   = 0x566
00069 F2_MOTOR_TEMP   = 0x586
00070 F3_MOTOR_TEMP   = 0x5A6
00071 SPREAD_MOTOR_TEMP       = 0x5C6
00072 MOTOR_TEMP_ID   = 0x89
00073 F1_MOTOR_THERM  = 0x566
00074 F2_MOTOR_THERM  = 0x586
00075 F3_MOTOR_THERM  = 0x5A6
00076 SPREAD_MOTOR_THERM      = 0x5C6
00077 MOTOR_THERM_ID   = 0x94
00078 F1_TACT = 0x569
00079 F2_TACT = 0x589
00080 F3_TACT = 0x5A9
00081 PALM_TACT = 0x5C9
00082 TACT_ID = 0x40
00083 
00084 
00085 
00086 
00087 
00088 class pyHand:
00089         
00090         def __init__(self, port = '/dev/pcan32'):
00091                 '''
00092                 Creates a PCANBasic object
00093 
00094                         @param port: CAN port used to communicate with the hand
00095                         @type connection: string
00096                 '''
00097                 
00098                 self.PCAN = PCANBasic(port)
00099                 
00100                 self.motor_positions = {FINGER1: {'encoder': [0, 0], 'position': [0.0, 0.0]}, FINGER2: {'encoder': [0, 0], 'position': [0.0, 0.0]}, FINGER3: {'encoder': [0, 0], 'position': [0.0, 0.0]},
00101                 SPREAD: {'encoder': [0, 0], 'position': [0.0, 0.0]}}
00102                 self.strain = {FINGER1: 0, FINGER2: 0, FINGER3: 0}
00103                 self.temp = {FINGER1:{ 'temp': 0.0, 'therm': 0.0}, FINGER2: { 'temp': 0.0, 'therm': 0.0}, FINGER3: { 'temp': 0.0, 'therm': 0.0},
00104                  SPREAD: { 'temp': 0.0, 'therm': 0.0}}
00105                 self.tactile_sensor = {FINGER1: {'values': range(0,24), 'data': range(0,5)}, FINGER2: {'values': range(0,24), 'data': range(0,5)}, 
00106                 FINGER3: {'values': range(0,24), 'data': range(0,5)}, SPREAD: {'values': range(0,24), 'data': range(0,5)}}
00107                 
00108         def check_error(self, connection,result,location_of_error):
00109                 '''
00110                 Checks error on the CAN Bus.
00111 
00112                         @param connection: The connection on which the CAN is talking. For example, PCANBasic()
00113                         @type connection: PCANBasic
00114                         @param result: The number corresponding to the error returned.
00115                         @type resulr: int
00116                         @param location_of_error: A description of where the error occurred.
00117                         @type location_of_error: str
00118                 '''
00119                 if result == PCAN_ERROR_OK:
00120                         pass
00121                 else:
00122                         raise Exception("Error Number: " + hex(result) + " while attempting to " + str(location_of_error) + "\n" + connection.GetErrorText(result)[1])
00123 
00124         def enum(self):
00125                 '''
00126                 Finds and returns all of the pucks that are attached to the bus.
00127 
00128                         @rtype: Array[]
00129                         @return: An array containing the pucks attached to the bus.
00130                 '''
00131                 pucks = []
00132                 for i in range(32):
00133                         try:
00134                                 self.get_property(i,1)
00135                                 pucks.append(i)
00136                         except:
00137                                 pass
00138                 return pucks
00139 
00140         def can_reset(self):
00141                 '''
00142                 Resets the CAN connection.
00143                 Note that this may cause a loss of data, but may also clear unwanted data. Utilize as needed.
00144                 '''
00145                 reset_result=self.PCAN.Reset(PCAN_USBBUS1)
00146                 try:
00147                         self.check_error(self.PCAN,reset_result,"reset")
00148                 except:
00149                         return False
00150                 time.sleep(0.025)
00151                 return True
00152 
00153         def can_status(self):
00154                 '''
00155                 Returns the status of the CAN connection as specified in PCANBasic's GetStatus method.
00156                 '''
00157                 status_result=self.PCAN.GetStatus(PCAN_USBBUS1)
00158                 time.sleep(0.025)
00159                 return status_result
00160 
00161         def can_init(self):
00162                 '''
00163                 Initializes the CAN connection. Note that this does not initialize the hand itself.
00164                 '''
00165                 
00166                 init_result=self.PCAN.Initialize(PCAN_USBBUS1, PCAN_BAUD_1M)
00167                 self.check_error(self.PCAN,init_result,"initialize")
00168                 time.sleep(0.025)
00169 
00170         def can_uninit(self):
00171                 '''
00172                 Uninitializes the CAN connection. Rarely used.
00173                 '''
00174                 uninit_result=self.PCAN.Uninitialize(PCAN_USBBUS1)
00175                 self.check_error(self.PCAN,uninit_result,"uninitialize")
00176                 
00177         
00178                 
00179         def initialize(self):
00180                 '''
00181                 Wakes up pucks and initializes the CAN.
00182                 This function must be implemented at the beginning of a program for this library to properly work.
00183 
00184                         @rtype: ROLE
00185                         @return: First finger's ROLE property if initialization is successful. Otherwise it returns False.
00186                 '''
00187                 try:
00188                         self.can_init()
00189                         
00190                         self.can_reset()
00191                         time.sleep(0.025)
00192                         
00193                         self.set_property(0x400, 5, 2)
00194                         time.sleep(1)
00195                         self.can_reset()
00196                         
00197                         return True
00198                 except:
00199                         return False
00200 
00201         def init_hand(self):
00202                 '''
00203                 Initialize all pucks in the hand.
00204 
00205                         @rtype: Boolean
00206                         @return: Succesfully Initialized Hand?
00207                 '''
00208                 try:
00209                         
00210                         self.init_finger(FINGER1)
00211                         self.init_finger(FINGER2)
00212                         self.init_finger(FINGER3)
00213                         time.sleep(3)
00214                         self.init_finger(SPREAD)
00215                         time.sleep(2)
00216                         
00217                         
00218                         self.get_property(FINGER1, ROLE)
00219                         return True
00220                 except:
00221                         
00222                         
00223                         return False
00224 
00225         def init_finger(self, msgID):
00226                 '''
00227                 Sends a command to the puck to wake up the motor attatched to the puck.
00228 
00229                         @param msgID: The id of the finger to initialize.
00230                         @type msgID: int
00231                 '''
00232                 self.set_property(msgID, CMD, CMD_HI)
00233 
00234         
00235 
00236         def read_msg(self):
00237                 '''
00238                 Read a general message from PCAN_USBBUS1
00239                 Typically, msg[1] (where msg is the thing returned), contains the pertinent information.
00240 
00241                         @rtype: (TPCANStatus, TPCANMsg, TPCANTimestamp)
00242                         @return: A tuple containing the status, message, and timestamp.
00243                 '''
00244                 return self.PCAN.Read(PCAN_USBBUS1)
00245 
00246         
00247         
00248         def write_msg(self, msgID, data, delay=.002):
00249                 '''
00250                 Send a general message to PCAN_USBBUS1. This can be a get, set, or even garbage.
00251 
00252                         @param msgID: The puck or group to which the message will be sent.
00253                         @type msgID: int
00254                         @param data: The array containing the data for the TPCANMsg.
00255                         @type data: Array[]
00256                         @param delay: The time delay to wait for the message to be written.
00257                         @type delay: float
00258                         @rtype: TPCANStatus
00259                         @return: Status of the self.PCAN bus.
00260                 '''
00261                 msg = TPCANMsg()
00262                 msg.ID = msgID
00263                 msg.LEN = len(data)
00264                 msg.MSGTYPE = PCAN_MESSAGE_STANDARD
00265                 for j in range(0, len(data)):
00266                         msg.DATA[j] = data[j]
00267                 stat = self.PCAN.Write(PCAN_USBBUS1, msg)
00268                 self.check_error(self.PCAN,stat,"write")
00269                 time.sleep(delay)
00270                 return stat
00271         
00272         
00273         def send_msg(self, msgID, data):
00274                 '''
00275                         Send a general message to PCAN_USBBUS1. This can be a get, set, or even garbage.
00276                         It does not apply any sleep
00277                         
00278                         @param msgID: The puck or group to which the message will be sent.
00279                         @type msgID: int
00280                         @param data: The array containing the data for the TPCANMsg.
00281                         @type data: Array[]
00282                         
00283                         @return the return status after writing in the bus
00284                 '''
00285                 msg = TPCANMsg()
00286                 msg.ID = msgID
00287                 msg.LEN = len(data)
00288                 msg.MSGTYPE = PCAN_MESSAGE_STANDARD
00289                 for j in range(0, len(data)):
00290                         msg.DATA[j] = data[j]
00291                 stat = self.PCAN.Write(PCAN_USBBUS1, msg)
00292                 self.check_error(self.PCAN,stat,"write")
00293                 
00294                 return stat
00295 
00296         def set_property(self, msgID, propID, value):
00297                 '''
00298                 Set property to a given value.
00299 
00300                         @param msgID: The puck or group whose property will be set.
00301                         @type msgID: int
00302                         @param propID: The number corresponding to the property to be set.
00303                         @type propID: int
00304                         @param value: The value to which the property will be set.
00305                         @type value: int
00306                 '''
00307                 is32bits = [48, 50, 52, 54, 56, 58, 66, 68, 74, 88, 96, 98]
00308                 if propID in is32bits:
00309                         self.set_32(msgID, propID, value)
00310                 else:
00311                         self.set_16(msgID, propID, value)
00312                         
00313         def set_32(self, msgID, propID, value):
00314                 '''
00315                 Set property to a given value for a 32 bit property.
00316                 Avoid usage of this method. Use self.set_property instead.
00317 
00318                         @param msgID: The puck or group whose property will be set.
00319                         @type msgID: int
00320                         @param propID: The number corresponding to the property to be set.
00321                         @type propID: int
00322                         @param value: The value to which the property will be set.
00323                         @type value: int
00324                 '''
00325                 data = [0x80+propID, 0, value%0x100, int(value/0x100)%0x100, int(value/0x10000)%0x100, int(value/0x1000000)]
00326                 
00327                 return self.send_msg(msgID, data)
00328 
00329         def set_16(self, msgID, propID, value):
00330                 '''
00331                 Set property to a given value for a 16 bit property.
00332                 Avoid usage of this method. Use self.set_property instead.
00333                 
00334                         @param msgID: The puck or group whose property will be set.
00335                         @type msgID: int
00336                         @param propID: The number corresponding to the property to be set.
00337                         @type propID: int
00338                         @param value: The value to which the property will be set.
00339                         @type value: int
00340                 '''
00341                 data = [0x80+propID, 0, value%256, int(value/256)]
00342                 
00343                 return self.send_msg(msgID, data)
00344 
00345 
00346         
00347         def get_property(self, msgID, propID):
00348                 '''
00349                 Get property from pucks in msgID.
00350 
00351                         @param msgID: The puck whose property will be read from.
00352                         @type msgID: int
00353                         @param propID: The property be read from.
00354                         @type propID: int
00355                         @rtype: int
00356                         @return: The value held in the property.
00357                 '''
00358                 is32bits = [48, 50, 52, 54, 56, 58, 66, 68, 74, 88, 96, 98]
00359                 if propID in is32bits:
00360                         return self.get_32(msgID, propID)
00361                 else:
00362                         if propID == TACT:
00363                                 return self.get_tact(msgID)
00364                         return self.get_16(msgID, propID)
00365 
00366 
00367         def get_32(self, msgID, propID):
00368                 '''
00369                 Gets a 32 bit property. Please use get_property instead of this method where applicable.
00370 
00371                         @param msgID: The puck whose property will be read from.
00372                         @type msgID: int
00373                         @param propID: The property be read from.
00374                         @type propID: int
00375                         @rtype: int
00376                         @return: The value held in the property.
00377                 '''
00378                 self.write_msg(msgID, [propID])
00379                 time.sleep(0.005)
00380                 read_result = self.PCAN.Read(PCAN_USBBUS1)
00381                 self.check_error(self.PCAN, read_result[0], "read")
00382                 data = read_result[1].DATA
00383                 value = (0x1000000 * data[5]) + (0x0010000 * data[4]) + (0x0000100 * data[3]) + (0x0000001 * data[2])
00384                 return value
00385 
00386 
00387         def get_16(self, msgID, propID):
00388                 '''
00389                 Gets a 16 bit property. Please use get_property instead of this method where applicable.
00390                 
00391                         @param msgID: The puck whose property will be read from.
00392                         @type msgID: int
00393                         @param propID: The property be read from.
00394                         @type propID: int
00395                         @rtype: int
00396                         @return: The value held in the property.
00397                 '''
00398                 self.write_msg(msgID, [propID])
00399                 time.sleep(0.005)
00400                 
00401                 read_result = self.PCAN.Read(PCAN_USBBUS1)
00402                 self.check_error(self.PCAN, read_result[0], "read")
00403                 data = read_result[1].DATA
00404                 value =(0x0000100 * data[3]) + (0x0000001 * data[2])
00405                 return value
00406 
00407                 
00408         def save_property(self, msgID, propID):
00409                 '''
00410                 Save a property.
00411 
00412                         @param msgID: The puck or group to have its property saved.
00413                         @type msgID: int
00414                         @param propID: The property to be saved.
00415                         @type propID: int
00416                 '''
00417                 self.set_property(msgID, SAVE, propID)
00418 
00419 
00420         def load_property(self, msgID, propID):
00421                 '''
00422                 Load a property's value for puck's flash memory.
00423 
00424                         @param msgID: The puck or group to have its property loaded.
00425                         @type msgID: int
00426                         @param propID: The property to be loaded.
00427                         @type propID: int
00428                 '''
00429                 self.set_property(msgID, LOAD, propID)
00430                 
00431         def get_prop_quick(self, msgID,propID,speed):
00432                 '''
00433                 Gets a property timed at a certain rate.
00434 
00435                         @param msgID: The puck or group to have its property gotten.
00436                         @type msgID: int
00437                         @param propID: The property to be saved.
00438                         @type propID: int
00439                         @param speed: The time delay for the get.
00440                         @type speed: float
00441                 '''
00442                 self.write_msg(msgID, [propID],speed)
00443                 read_result=self.read_msg_resilient(msgID,propID)
00444                 self.check_error(self.PCAN, read_result[0], "read")
00445                 data = read_result[1].DATA
00446                 value = (0x1000000 * data[5]) + (0x0010000 * data[4]) + (0x0000100 * data[3]) + (0x0000001 * data[2])
00447                 return value
00448 
00449         def read_msg_resilient(self, expect_puck,expect_prop,max_recurse=10,counter=0):
00450                 '''
00451                 Reads message given the puckID and the propertyID. 
00452                 It will read as normal, until it gets some expected output from the puck.
00453 
00454                         @param expect_puck: The puck to read from.
00455                         @type expect_puck: int
00456                         @param expect_prop: The property read from.
00457                         @type expect_prop: int
00458                         @param max_recurse: The most number of times to repeat the get.
00459                         @type max_recurse: int
00460                         @param counter: Used internally. Do not set.
00461                         @type counter: int
00462                         @rtype: int
00463                         @return: The value held in the property of the given puck.
00464                 '''
00465                 counter+=1
00466                 response=self.PCAN.Read(PCAN_USBBUS1)
00467                 received_prop=response[1].DATA[0]-128
00468                 received_puck=(response[1].ID-1024)>>5
00469                 
00470                 if (received_prop==expect_prop) and (received_puck==expect_puck):
00471                         return response
00472                 else:
00473                         print "a"
00474                         if counter<max_recurse:
00475                                 return self.read_msg_resilient(expect_puck,expect_prop,counter=counter)
00476                         else:
00477                                 raise Exception("Missed message")
00478 
00479         def get_role(self, msgID):
00480                 '''
00481                 Read from ROLE property and return something that makes sense.
00482                 Returns an array of holding the following data:
00483 
00484                 [4-bit Product Identifier,
00485                 Internal Thermistor,
00486                 20 MHz (vs 32 MHz),
00487                 Hall Motor Encoder,
00488                 Enc Motor Encoder,
00489                 Strain Gauge,
00490                 IMU for Force-Torque Sensor,
00491                 Optical Motor Encoder]
00492 
00493                         @param msgID: The puck to get the ROLE from.
00494                         @type msgID: int
00495                         @rtype: Array[int,bool,bool,bool,bool,bool,bool,bool]
00496                         @return: An array holding the above values.
00497                 '''
00498                 role = self.get_property(msgID, 1)
00499                 data= [0,0,0,0,0,0,0,0,0]
00500                 data[0] = role%16               
00501                 data[1] = int(role/2**6)%2==1   
00502                 data[2] = int(role/2**7)%2==1   
00503                 data[3] = int(role/2**8)%2==1   
00504                 data[4] = int(role/2**9)%2==1   
00505                 data[5] = int(role/2**10)%2==1  
00506                 data[6] = int(role/2**11)%2==1  
00507                 data[7] = int(role/2**12)%2==1  
00508                 data[8] = int(role/2**13)%2==1  
00509                 return data
00510 
00511         def get_mode(self, msgID):
00512                 '''
00513                 Read from MODE property, and return a tuple with the number corresponding to the mode, along with
00514                 the string name of the mode.
00515 
00516                         @param msgID: The puck from which to get the mode.
00517                         @type msgID: int
00518                         @rtype: Tuple(int, str)
00519                         @return: A tuple with the number and name of the mode.
00520                 '''
00521                 m = self.get_property(msgID, MODE)
00522                 if m==MODE_IDLE:
00523                         return (MODE_IDLE, "IDLE")
00524                 elif m==MODE_TORQUE:
00525                         return (MODE_TORQUE, "TORQUE")
00526                 elif m==MODE_PID:
00527                         return (MODE_PID, "PID")
00528                 elif m==MODE_VEL:
00529                         return (MODE_VEL, "VEL")
00530                 elif m==MODE_TRAP:
00531                         return (MODE_TRAP, "TRAP")
00532                 else:
00533                         print "Invalid get_mode() operation: "+str(m)
00534                         return (m, "???")
00535 
00536         def set_mode(self, msgID, value):
00537                 '''
00538                 Set the mode property using either strings or numbers.
00539 
00540                         @param msgID: The puck or group to set the mode.
00541                         @type msgID: int
00542                         @param value: The value to which the mode should be set.
00543                         @type value: int
00544                 '''
00545                 modes = {"IDLE":MODE_IDLE, "TORQUE":MODE_TORQUE, "PID":MODE_PID, "VEL":MODE_VEL, "TRAP":MODE_TRAP}
00546                 m = value
00547                 if m in modes:
00548                         m = modes[m]
00549                 self.set_property(msgID, MODE, m)
00550                 
00551         
00552         def set_puck_like(self, puckID, virtID):
00553                 '''
00554                 Set the puck to have all the default properties of the indicated puck ID.
00555 
00556                         @param puckID: The original puck to change.
00557                         @type puckID: int
00558                         @param virtID: The ID of the puck to load defaults from.
00559                         @type virtID: int
00560                 '''
00561                 self.set_property(puckID, MODE, MODE_IDLE)
00562                 
00563                 
00564                 
00565                 
00566                 
00567                 
00568                 
00569                 
00570                 
00571                 
00572                 
00573                 
00574                 
00575                 
00576                 
00577                 
00578                 
00579                 
00580                 
00581                 
00582                 
00583                         
00584                 
00585                 
00586                 is_280 = self.get_property(puckID, HALLH)==7 
00587                 if virtID in [FINGER1, FINGER2, FINGER3, SPREAD]:
00588                         self.set_property(puckID, JIDX, virtID-3)
00589                         self.save_property(puckID, JIDX)
00590                         self.set_property(puckID, PIDX, virtID-10)
00591                         self.save_property(puckID, PIDX)
00592                         self.set_property(puckID, TIE, 0)
00593                         self.save_property(puckID, TIE)
00594                         self.set_property(puckID, ACCEL, 200)
00595                         self.save_property(puckID, ACCEL)
00596                         
00597                         
00598                         self.set_property(puckID, OT, 0)
00599                         self.save_property(puckID, OT)
00600                         self.set_property(puckID, CTS, 4096)
00601                         self.save_property(puckID, CTS)
00602                         self.set_property(puckID, MT, 2200)
00603                         self.save_property(puckID, MT)
00604                         self.set_property(puckID, MCV, 200)
00605                         self.save_property(puckID, MCV)
00606                         self.set_property(puckID, MOV, 200)
00607                         self.save_property(puckID, MOV)
00608                         self.set_property(puckID, OTEMP, 60)
00609                         self.save_property(puckID, OTEMP)
00610                         self.set_property(puckID, PTEMP, 0)
00611                         self.save_property(puckID, PTEMP)
00612                         self.set_property(puckID, POLES, 6)
00613                         self.save_property(puckID, POLES)
00614                         self.set_property(puckID, IKCOR, 102)
00615                         self.save_property(puckID, IKCOR)
00616                         self.set_property(puckID, IOFF, 0)
00617                         self.save_property(puckID, IOFF)
00618                         self.set_property(puckID, IVEL, -75)
00619                         self.save_property(puckID, IVEL)
00620                         self.set_property(puckID, DS, 25600)
00621                         self.save_property(puckID, DS)
00622                         self.set_property(puckID, KI, 0)
00623                         self.save_property(puckID, KI)
00624                         self.set_property(puckID, IPNM, 20000)
00625                         self.save_property(puckID, IPNM)
00626                         self.set_property(puckID, GRPA, 0)
00627                         self.save_property(puckID, GRPA)
00628                         self.set_property(puckID, GRPB, 7)
00629                         self.save_property(puckID, GRPB)
00630                         self.set_property(puckID, GRPC, 5)
00631                         self.save_property(puckID, GRPC)
00632                         self.set_property(puckID, IKI, 204)
00633                         self.save_property(puckID, IKI)
00634                         self.set_property(puckID, IKP, 500)
00635                         self.save_property(puckID, IKP)
00636                         if virtID == SPREAD:
00637                                 self.set_property(puckID, CT, 35950)
00638                                 self.save_property(puckID, CT)
00639                                 self.set_property(puckID, DP, 17975)
00640                                 self.save_property(puckID, DP)
00641                                 self.set_property(puckID, MV, 50)
00642                                 self.save_property(puckID, MV)
00643                                 self.set_property(puckID, HSG, 0)
00644                                 self.save_property(puckID, HSG)
00645                                 self.set_property(puckID, LSG, 0)
00646                                 self.save_property(puckID, LSG)
00647                                 self.set_property(puckID, HOLD, 1)
00648                                 self.save_property(puckID, HOLD)
00649                                 self.set_property(puckID, TSTOP, 150)
00650                                 self.save_property(puckID, TSTOP)
00651                                 self.set_property(puckID, KP, 1000)
00652                                 self.save_property(puckID, KP)
00653                                 self.set_property(puckID, KD, 10000)
00654                                 self.save_property(puckID, KD)
00655                         else:
00656                                 self.set_property(puckID, CT, 195000)
00657                                 self.save_property(puckID, CT)
00658                                 self.set_property(puckID, DP, 45000)
00659                                 self.save_property(puckID, DP)
00660                                 self.set_property(puckID, MV, 200)
00661                                 self.save_property(puckID, MV)
00662                                 self.set_property(puckID, HSG, 0)
00663                                 self.save_property(puckID, HSG)
00664                                 self.set_property(puckID, LSG, 0)
00665                                 self.save_property(puckID, LSG)
00666                                 self.set_property(puckID, HOLD, 0)
00667                                 self.save_property(puckID, HOLD)
00668                                 self.set_property(puckID, TSTOP, 50)
00669                                 self.save_property(puckID, TSTOP)
00670                                 self.set_property(puckID, KP, 500)
00671                                 self.save_property(puckID, KP)
00672                                 self.set_property(puckID, KD, 2500)
00673                                 self.save_property(puckID, KD)
00674                 else:
00675                         print "Invalid Puck Id for Hand"
00676                 
00677         
00678 
00679         def set_hand_targets(self, f1_target, f2_target, f3_target, sp_target):
00680                 '''
00681                 Given fingers and spread target values, move the hand to that position.
00682                 Will mainly be used to load user-defined hand positions.
00683                 Takes Barrett Units as inputs.
00684 
00685                         @param f1_target: The position (in encoder ticks) for finger 1 to move to.
00686                         @type f1_target: int
00687                         @param f2_target: The position for finger 2 to move to.
00688                         @type f2_target: int
00689                         @param f3_target: The position for finger 3 to move to.
00690                         @type f3_target: int
00691                         @param sp_target: The position for spread to move to.
00692                         @type sp_target: int
00693                 '''
00694                 self.set_property(FINGER1, DP, f1_target)
00695                 self.set_property(FINGER2, DP, f2_target)
00696                 self.set_property(FINGER3, DP, f3_target)
00697                 tar = self.get_position(SPREAD)
00698                 self.set_property(SPREAD, DP, tar)
00699                 self.set_property(0x405, CMD, CMD_MOVE)
00700                 time.sleep(2)
00701                 self.set_property(SPREAD, DP, sp_target)
00702                 self.set_property(SPREAD, CMD, CMD_MOVE)
00703                 time.sleep(1)
00704 
00705         def move_to(self, puckID, target, autowait=True):
00706                 '''
00707                 Move the motor to a specific position.
00708 
00709                         @param puckID: The puck to move.
00710                         @type puckID: int
00711                         @param target: The end position to move to.
00712                         @type target: int
00713                         @param autowait: Does the program wait until the motor is done moving?
00714                         @type autowait: bool
00715                 '''
00716                 self.set_property(puckID, M, target)
00717                 if autowait:
00718                         self.wait_done_moving([puckID])
00719 
00720         def done_moving(self, motors_to_check=ALL_FINGERS):
00721                 '''
00722                 Checks a given list of motors once to see if they have stopped moving, and if so, it returns true
00723 
00724                         @param motors_to_check: A list of motors to check.
00725                         @type motors_to_check: Array[*int]
00726                         @rtype: bool
00727                         @return: Whether or not the motors are done moving.
00728                 '''
00729                 for FINGER in motors_to_check:
00730                         if (self.get_mode(FINGER)[1]!="IDLE" and (self.get_mode(FINGER)[1]!="PID" or self.get_property(FINGER,77)==0)):
00731                                 return False
00732                 return True
00733 
00734         
00735         def wait_done_moving(self, motors_to_check=ALL_FINGERS):
00736                 '''
00737                 Waits until the given list of motors have all stopped moving.
00738 
00739                         @param motors_to_check: A list of motors to wait for.
00740                         @type motors_to_check: Array[*int]
00741                 '''
00742                 while(not self.done_moving(motors_to_check)):
00743                         time.sleep(0.025)
00744 
00745         def detect_breakaway(self, finger):
00746                 '''
00747 
00748                         @return: True if the finger has broken away, False if it hasn't
00749                 '''
00750                 tup = self.get_packed_position(finger)
00751                 ratio = tup[0]/tup[1]
00752                 return (ratio>3)
00753 
00754         def open_grasp(self):
00755                 '''
00756                 Opens all fingers to the position encoded by Open Target (OT)
00757                 '''
00758                 self.set_property(0x405, TSTOP, 50)
00759                 self.set_property(SPREAD, TSTOP, 150)
00760 
00761                 open_target=self.get_property(FINGER1,OT)
00762                 self.set_property(FINGER1,DP,open_target)
00763                 
00764                 open_target=self.get_property(FINGER2,OT)
00765                 self.set_property(FINGER2,DP,open_target)
00766                 
00767                 open_target=self.get_property(FINGER3,OT)
00768                 self.set_property(FINGER3,DP,open_target)
00769 
00770                 spread_stay=self.get_position(SPREAD)
00771                 self.set_property(SPREAD,DP,spread_stay)
00772                 
00773                 self.set_property(0x405,CMD,CMD_MOVE)
00774                 self.wait_done_moving(GRASP)
00775 
00776         def close_grasp(self):
00777                 '''
00778                 Closes all fingers to the position encoded by Close Target (CT).
00779                 '''
00780                 self.set_property(0x405, TSTOP, 50)
00781                 self.set_property(SPREAD, TSTOP, 150)
00782 
00783                 close_target=self.get_property(FINGER1,CT)
00784                 self.set_property(FINGER1,DP,close_target)
00785 
00786                 close_target=self.get_property(FINGER2,CT)
00787                 self.set_property(FINGER2,DP,close_target)
00788 
00789                 close_target=self.get_property(FINGER3,CT)
00790                 self.set_property(FINGER3,DP,close_target)
00791 
00792                 spread_stay=self.get_position(SPREAD)
00793                 self.set_property(SPREAD,DP,spread_stay)
00794 
00795                 self.set_property(0x405,CMD,CMD_MOVE)
00796                 self.wait_done_moving(GRASP)
00797                 
00798         def open_spread(self):
00799                 '''
00800                 Open spread to position determined by Open Target (OT).
00801                 '''
00802                 self.set_property(SPREAD, TSTOP, 150)
00803                 self.set_property(SPREAD, CMD, CMD_OPEN)
00804                 self.wait_done_moving([SPREAD])
00805 
00806         def close_spread(self):
00807                 '''
00808                 Close spread to position determined by Close Target (CT).
00809                 '''
00810                 self.set_property(SPREAD, CMD, CMD_CLOSE)
00811                 self.wait_done_moving([SPREAD])
00812 
00813         def open_finger(self, puckID, autowait=True):
00814                 '''
00815                 Open finger and wait for completion.
00816 
00817                         @param puckID: Finger to be opened.
00818                         @type puckID: int
00819                         @param autowait: calls wait_done_moving if True. Defaults to True.
00820                         @type autowait: bool
00821                 '''
00822                 if puckID in [FINGER1, FINGER2, FINGER3]:
00823                         self.set_property(puckID, TSTOP, 50)
00824                 if puckID == SPREAD:
00825                         self.set_property(puckID, TSTOP, 150)
00826                 self.set_property(puckID, CMD, CMD_OPEN)
00827                 if autowait:
00828                         self.wait_done_moving([puckID])
00829 
00830         def close_finger(self, puckID, autowait=True):
00831                 '''
00832                 Close finger and wait for completion.
00833 
00834                 @param puckID: Finger to be closed.
00835                 @type puckID: int
00836                 @param autowait: calls wait_done_moving if True. Defaults to True.
00837                 @type autowait: bool
00838                 '''
00839                 if puckID in [FINGER1, FINGER2, FINGER3]:
00840                         self.set_property(puckID, TSTOP, 50)
00841                 if puckID == SPREAD:
00842                         self.set_property(puckID, TSTOP, 150)
00843                 self.set_property(puckID, CMD, CMD_CLOSE)
00844                 if autowait:
00845                         self.wait_done_moving([puckID])
00846 
00847         def move_grasp(self, position = -1):
00848                 '''
00849                 Moves all fingers to input argument or default position (50).
00850 
00851                         @param position: position of fingers. Defaults to -1. Valid position range is from 0-195,000 encoder counts.
00852                         @type position: int
00853                 '''
00854                 default = self.get_position(SPREAD)
00855                 self.set_property(SPREAD, DP, default)
00856                 if(position != -1):
00857                         self.set_property(FINGER1, DP, position)
00858                         self.set_property(FINGER2, DP, position)
00859                         self.set_property(FINGER3, DP, position)        
00860                 self.move()
00861 
00862         def move(self):
00863                 '''
00864                 Moves all fingers/spread to their default.
00865                 '''
00866                 self.set_property(0x405, CMD, CMD_MOVE)
00867                 self.wait_done_moving(GRASP)
00868 
00869         def open_all(self):
00870                 '''
00871                 Opens every fingers at once. Mainly used in DEMO. WARNING: can be dangerous because it may cause fingers to collide if the hand is in an unknown position.
00872                 '''
00873                 open_target = self.get_property(FINGER1, OT)
00874                 self.set_property(FINGER1, DP, open_target)
00875                 open_target = self.get_property(FINGER2, OT)
00876                 self.set_property(FINGER2, DP, open_target)
00877                 open_target = self.get_property(FINGER3, OT)
00878                 self.set_property(FINGER3, DP, open_target)
00879                 open_target = self.get_property(SPREAD, OT)
00880                 self.set_property(SPREAD, DP, open_target)
00881                 self.move()
00882 
00883         def close_all(self):
00884                 '''
00885                 Closes every finger at once. Mainly for use in DEMO. WARNING: can be dangerous because it may cause fingers to collide if the hand is in an unknown position.
00886                 '''
00887                 close_target = self.get_property(FINGER1, CT)
00888                 self.set_property(FINGER1, DP, close_target)
00889                 close_target = self.get_property(FINGER2, CT)
00890                 self.set_property(FINGER2, DP, close_target)
00891                 close_target = self.get_property(FINGER3, CT)
00892                 self.set_property(FINGER3, DP, close_target)
00893                 close_target = self.get_property(SPREAD, CT)
00894                 self.set_property(SPREAD, DP, close_target)
00895                 self.move()
00896 
00897         
00898                 
00899         def open_grasp_step(self, step=0):
00900                 '''
00901                 Open grasp by input increment.
00902 
00903                         @param step: size of increment in encoder counts. Defaults to 0.
00904                         @type step: int
00905                 '''
00906                 self.open_finger_step(FINGER1, step, False)
00907                 self.open_finger_step(FINGER2, step, False)
00908                 self.open_finger_step(FINGER3, step, False)
00909                 self.wait_done_moving(GRASP)
00910 
00911         def close_grasp_step(self, step=0):
00912                 '''
00913                 Close grasp by input decrement.
00914 
00915                         @param step: size of decrement in encoder counts. Defaults to 0.
00916                         @type step: int
00917                 '''
00918                 self.close_finger_step(FINGER1, step, False)
00919                 self.close_finger_step(FINGER2, step, False)
00920                 self.close_finger_step(FINGER3, step, False)
00921                 self.wait_done_moving(GRASP)
00922 
00923         def open_spread_step(self, step=-1):
00924                 '''
00925                 Open spread by input increment.
00926 
00927                         @param step: size of increment in encoder counts. Defaults to -1.
00928                         @type step: int
00929                 '''
00930                 if step == -1:
00931                         step = self.get_property(SPREAD, 60)
00932                 self.open_finger_step(SPREAD, step)
00933                 
00934         def close_spread_step(self, step=-1):
00935                 '''
00936                 Close spread by input decrement.
00937 
00938                         @param step: size of decrement in encoder counts. Defaults to -1.
00939                         @type step: int 
00940                 '''
00941                 if step == -1:
00942                         step = self.get_property(SPREAD, 60)
00943                 self.close_finger_step(SPREAD, step)
00944 
00945         def open_finger_step(self, puckID, step=-1, autowait=True):
00946                 '''
00947                 Open finger by input increment.
00948 
00949                         @param puckID: Finger to be opened.
00950                         @type puckID: int
00951                         @param step: size of increment in encoder counts. Defaults to -1.
00952                         @type step: int
00953                         @param autowait: calls wait_done_moving if True. Defaults to True.
00954                         @type autowait: bool
00955                 '''
00956                 if step == -1:
00957                         step = self.get_property(puckID, 60)
00958                 self.set_property(puckID, DS, step)
00959                 self.set_property(puckID, CMD, CMD_IO)
00960                 if autowait:
00961                         self.wait_done_moving([puckID])
00962 
00963         def close_finger_step(self, puckID, step=-1, autowait=True):
00964                 '''
00965                 Close finger by input decrement.
00966 
00967                         @param puckID: Finger to be closed.
00968                         @type puckID: int
00969                         @param step: size of decrement in encoder counts. Defaults to -1.
00970                         @type step: int
00971                         @param autowait: calls wait_done_moving if True. Defaults to True.
00972                         @type autowait: bool
00973                 '''
00974                 if step == -1:
00975                         step = self.get_property(puckID, 60)
00976                 self.set_property(puckID, DS, step)
00977                 self.set_property(puckID, CMD, CMD_IC)
00978                 if autowait:
00979                         self.wait_done_moving([puckID])
00980 
00981         
00982         def get_full_pos_packet(msgID):
00983                         self.write_msg(msgID, [P])
00984                         read_result=self.PCAN.Read(PCAN_USBBUS1)
00985                         return read_result
00986                         
00987         def get_velocity(self, msgID):
00988                 '''
00989                 Returns velocity values of finger when in motion. Mostly returns garbage. It's used to help tell when finger is stopped or near to it.
00990 
00991                         @param msgID: The puck or group to get velocity.
00992                         @type msgID: int
00993                         @rtype: float
00994                         @return: A (garbage) value representing the approximate velocity of the finger.
00995                 '''     
00996                 packet1=self.get_full_pos_packet(msgID)
00997                 packet2=self.get_full_pos_packet(msgID)
00998                 
00999                 error1=packet1[0]
01000                 error2=packet2[0]
01001 
01002                 msg1=packet1[1]
01003                 msg2=packet2[1]
01004 
01005                 data1=msg1.DATA 
01006                 data2=msg2.DATA
01007 
01008                 time1=packet1[2]
01009                 time2=packet2[2]
01010                 
01011                 stamp1=time1.micros + 1000 * time1.millis + 0xFFFFFFFF * 1000 * time1.millis_overflow
01012                 stamp2=time2.micros + 1000 * time2.millis + 0xFFFFFFFF * 1000 * time2.millis_overflow
01013 
01014                 delta=(stamp2-stamp1)/1000000.0
01015                 
01016                 self.check_error(self.PCAN,error1,"reading position for fake get_velocity")
01017                 self.check_error(self.PCAN,error2,"reading position for fake get_velocity")
01018 
01019                 val1=(0x0000100 * data1[3]) + (0x0000001 * data1[2])
01020                 val2=(0x0000100 * data2[3]) + (0x0000001 * data2[2])
01021                 
01022                 return (val2-val1)/delta
01023 
01024         def get_temp(self, msgID):
01025                 '''
01026                 Gets temperature value for all pucks in msgID.
01027 
01028                         @param msgID: The puck or group to get temp.
01029                         @type msgID: int
01030                         @rtype: int
01031                         @return: The value of the TEMP property.
01032                 '''
01033                 return self.temp[msgID]['temp']
01034                 
01035                 
01036         def read_temp(self, msgID):
01037                 '''
01038                 Sends a message to get the temperature value for all pucks in msgID.
01039 
01040                         @param msgID: The puck or group to get temp.
01041                         @type msgID: int
01042                         @rtype: int
01043                         @return: The value of the TEMP property.
01044                 '''
01045                 return self.send_msg(msgID, [TEMP])
01046 
01047         def get_therm(self, msgID):
01048                 '''
01049                 Gets motor temperature value for all pucks in msgID. 
01050 
01051                         @param msgID: The puck or group to get motor temperature.
01052                         @text msgID: int
01053                         @rtype: int
01054                         @return: The value of the THERM property.
01055                 '''
01056                 return self.temp[msgID]['therm']
01057         
01058         def read_therm(self, msgID):
01059                 '''
01060                 Gets motor temperature value for all pucks in msgID. 
01061 
01062                         @param msgID: The puck or group to get motor temperature.
01063                         @text msgID: int
01064                         @rtype: int
01065                         @return: The value of the THERM property.
01066                 '''
01067                 return self.send_msg(msgID, [THERM])
01068 
01069         def get_top_tact(self, msgID):
01070                 '''
01071                 Unpack the top10 values from TACT.
01072                 Returns a dictionary with 10 items like (sensor number):(tact value).
01073 
01074                         @param msgID: The puck or group to get top 10 tactile data.
01075                         @type msgID: int
01076                         @rtype: Dictionary{sensorID:value}
01077                         @return topVals: Dictionary of the top 10 tactile array sensor values. 
01078                 '''
01079                 
01080                 self.set_property(msgID, TACT, TACT_10) 
01081                 self.write_msg(msgID, [TACT]) 
01082                 read_result=self.PCAN.Read(PCAN_USBBUS1)
01083                 self.check_error(self.PCAN,read_result[0],"reading top ten tactile values")
01084                 
01085                 output = read_result[1].DATA 
01086                 
01087                 top10 = output[0] * 0x10000 + output[1] * 0x100 + output[2] * 0x1
01088                 topVals = {}
01089                 data = [output[3]/(0x10), output[3]%(0x10), output[4]/(0x10), output[4]%(0x10), output[5]/(0x10), output[5]%(0x10)]
01090                 count=0
01091                 for sensor in range(0, 24):
01092                         if top10%2 == 1:
01093                                 
01094                                 topVals[sensor] = data[count]
01095                                 count+=1
01096                         top10 = top10/2
01097                         
01098                 return topVals
01099 
01100         def read_full_tact(self, msgID):
01101                 '''
01102                         Read all tactile sensors
01103                 '''
01104                 return self.set_property(msgID, TACT, TACT_FULL) 
01105 
01106         def get_full_tact(self, msgID):
01107                 '''
01108                 Unpack all tactile sensor values in an array.
01109 
01110                         @param msgID: The puck or group to get full tactile array sensor data.
01111                         @type msgID: int
01112                         @rtype: Array[*data]
01113                         @return: An array containing the tactile data from a given puck.
01114                 '''
01115                 
01116                 '''self.set_property(msgID, TACT, TACT_FULL) 
01117                 #self.write_msg(msgID, [TACT])
01118                 output = [0,0,0,0,0]
01119                 read_result = self.PCAN.Read(PCAN_USBBUS1)
01120                 self.check_error(self.PCAN,read_result[0],"reading full tactile data")
01121                 read_result2 = self.PCAN.Read(PCAN_USBBUS1)
01122                 self.check_error(self.PCAN,read_result2[0],"reading full tactile data")
01123                 read_result3 = self.PCAN.Read(PCAN_USBBUS1)
01124                 self.check_error(self.PCAN,read_result3[0],"reading full tactile data")
01125                 read_result4 = self.PCAN.Read(PCAN_USBBUS1)
01126                 self.check_error(self.PCAN,read_result4[0],"reading full tactile data")
01127                 read_result5 = self.PCAN.Read(PCAN_USBBUS1)
01128                 self.check_error(self.PCAN,read_result5[0],"reading full tactile data")
01129                 
01130                 output[0] = read_result[1].DATA
01131                 output[1] = read_result2[1].DATA
01132                 output[2] = read_result3[1].DATA
01133                 output[3] = read_result4[1].DATA
01134                 output[4] = read_result5[1].DATA
01135                 
01136                 #print 'Init: ID1 = %x,  ID2 = %x,  ID3 = %x,  ID4 = %x,  ID5 = %x'%(read_result[1].ID, read_result2[1].ID, read_result3[1].ID, read_result4[1].ID, read_result5[1].ID)
01137                 tactileVals = range(0,24)
01138                 index_ = 0
01139                 for data in output:
01140                         index_ = int(data[0]/16) * 5
01141                         #print 'index = %d, data[0] = %x'%(index_, data[0])
01142                         # Get the bits and then unpack them.
01143                         tactileVals[index_ + 0] = round(((data[0]%0x10)*0x100 + data[1])/256.0,2)
01144                         tactileVals[index_ + 1] = round((data[2]*0x10 + int(data[3]/0x10))/256.0,2)
01145                         tactileVals[index_ + 2] = round(((data[3]%0x10)*0x100 + data[4])/256.0,2)
01146                         tactileVals[index_ + 3] = round((data[5]*0x10 + int(data[6]/0x10))/256.0,2)
01147                         if index_ != 20:
01148                                 tactileVals[index_ + 4] = round(((data[6]%0x10)*0x100 + data[7])/256.0,2)
01149                 #print 'Return OK : %s'%(tactileVals)
01150                 return tactileVals'''
01151                 
01152                 return self.tactile_sensor[msgID]['values']
01153 
01154 
01155         def get_tact(self, msgID, topOrFull="TOP10"):
01156                 '''
01157                 Obtain and interpret tactile sensor data.
01158 
01159                         @param msgID: The puck or group to get full or top 10 tactile array sensor data.
01160                         @type msgID: int
01161                         @param topOrFull: To get full data, enter "FULL". To get the top 10 values, enter "TOP10". Or anything else, really.
01162                         @type topOrFull: str
01163                         @return 
01164                 '''
01165                 if topOrFull == "FULL":
01166                         return self.get_full_tact(msgID)
01167                 else:
01168                         return self.get_top_tact(msgID)
01169 
01170         def set_velocity(self, puckID, velocity):
01171                 '''
01172                 Set the velocity and make the motor move.
01173 
01174                         @param puckID: The ID of the puck to set the velocity of.
01175                         @type puckID: int
01176                         @param velocity: The velocity (in cts/ms) of the motor.
01177                         @type velocity: int
01178                 '''
01179                 
01180                 self.set_property(puckID, TSTOP, 0)
01181                 
01182                 self.set_property(puckID, V, velocity)
01183                 
01184                 self.set_property(puckID, MODE, MODE_VEL)
01185 
01186 
01187         def get_strain(self, msgID):
01188                 '''
01189                 Gets the fingertip torque sensor value. 
01190 
01191                         @param msgID: The puck or group to get fingertip torque sensor data. 
01192                         @type msgID: int
01193                         @rtype: int
01194                         @return: Strain Gauge Reading
01195                 '''
01196                 return self.strain[msgID]
01197         
01198         
01199         def read_strain(self, msgID):
01200                 '''
01201                 Sends the message to get the fingertip torque sensor value. 
01202 
01203                         @param msgID: The puck or group to get fingertip torque sensor data. 
01204                         @type msgID: int
01205                         @rtype: int
01206                         @return: CAN status
01207                 '''
01208                 return self.send_msg(msgID, [SG])
01209                 
01210         
01211 
01212         def onescomp(self, binstr):
01213                 return ''.join('1' if b=='0' else '0' for b in binstr)
01214 
01215         def twoscomp(self, number):
01216                 binstr= bin(number)[2:]
01217                 a= bin(int(self.onescomp(binstr),2)+1)[2:]
01218                 return -1*int(a,2)
01219 
01220         def get_position(self, msgID, depth=0):
01221                 '''
01222                 Get packed position data and return it.
01223 
01224                         @param msgID: The puck or group to get position data.
01225                         @type msgID: int
01226                         @rtype: int
01227 
01228                         @param depth: number of times get message was retried.
01229                         
01230                         @return: The position of the finger in encoder counts.
01231                 '''
01232                 if depth!=0:
01233                         self.write_msg(msgID, [P],.009)
01234                 read_result=self.PCAN.Read(PCAN_USBBUS1)
01235                 try:
01236                         self.check_error(self.PCAN,read_result[0],"getting position data")
01237                         received_puck=(read_result[1].ID-1024)>>5
01238                         if received_puck!=msgID:
01239                                 raise Exception("Did not read expected MSGID")
01240                 except:
01241                         if depth>10:
01242                                 raise Exception("Failure to get position data.")
01243                         else:
01244                                 return self.get_position(msgID, depth+1)
01245 
01246                 output = read_result[1].DATA
01247                 temp=(output[0]-0x80)*0x10000 + output[1] * 0x100 + output[2]
01248 
01249                 if (temp & 0b1000000000000000000000): 
01250                         return self.twoscomp(temp)
01251                 else:
01252                         return temp
01253 
01254         def get_packed_position(self, msgID):
01255                 '''
01256                 Get packed position data and return both P and JP.
01257 
01258                         @param msgID: The puck or group to get position data.
01259                         @type msgID: int
01260                         @rtype: (int, int)
01261 
01262                         @return: The position and joint position of the finger in encoder counts.
01263                                          Position in radians
01264                 '''
01265                 
01266                 return  self.motor_positions[msgID]['position']
01267         
01268         
01269         def read_packed_position(self, msgID):
01270                 '''
01271                 Get packed position data and return both P and JP.
01272 
01273                         @param msgID: The puck or group to get position data.
01274                         @type msgID: int
01275                         @rtype: (int, int)
01276 
01277                         @return: sends a msg to read the position.
01278                 '''
01279                 
01280                 return self.send_msg(msgID, [P])
01281                 
01282         
01283         def process_can_messages(self):
01284                 ''' 
01285                         Reads and process all the msgs in the bus
01286                         Depending on the CAN id, it'll use different methods
01287                 '''
01288                 ret = 0
01289                 
01290                 msg = self.read_msg()
01291                 
01292                 
01293                 if msg[0] != PCAN_ERROR_OK:
01294                         ret = -1
01295                 
01296                 while msg[0] == PCAN_ERROR_OK:
01297                         
01298                         can_id = msg[1].ID
01299                         
01300                         
01301                         if can_id in [F1_POSITION, F2_POSITION, F3_POSITION, SPREAD_POSITION]:
01302                                 self.process_packed_position(msg[1])
01303                         elif can_id in [F1_STRAIN, F2_STRAIN, F3_STRAIN] and msg[1].DATA[0] == STRAIN_ID:
01304                                 self.process_strain(msg[1])
01305                         elif can_id in [F1_MOTOR_TEMP, F2_MOTOR_TEMP, F3_MOTOR_TEMP, SPREAD_MOTOR_TEMP] and msg[1].DATA[0] == MOTOR_TEMP_ID:
01306                                 self.process_motor_temp(msg[1])
01307                         elif can_id in [F1_MOTOR_THERM, F2_MOTOR_THERM, F3_MOTOR_THERM, SPREAD_MOTOR_THERM] and msg[1].DATA[0] == MOTOR_THERM_ID:
01308                                 self.process_motor_therm(msg[1])
01309                         elif can_id in [F1_TACT, F2_TACT, F3_TACT, PALM_TACT]:
01310                                 self.process_full_tact(msg[1])
01311                                 
01312                         msg = self.read_msg()
01313                         
01314                 return ret
01315         
01316         def process_packed_position(self, msg):
01317                 '''
01318                         Process the CAN msgs and saves the position depending on the MSG ID
01319                 '''
01320                 data = msg.DATA
01321                 pos = (data[0]-0x80)*0x10000 + data[1]*0x100 + data[2]
01322                 jpos= (data[3]-0x80)*0x10000 + data[4]*0x100 + data[5]
01323                 pos = self.twoscomp(pos) if pos & 0b1000000000000000000000 else pos
01324                 jpos= self.twoscomp(jpos) if jpos & 0b1000000000000000000000 else jpos
01325                 
01326                 if msg.ID == F1_POSITION:
01327                         self.motor_positions[FINGER1]['encoder'][0] = pos
01328                         self.motor_positions[FINGER1]['encoder'][1] = jpos
01329                         self.motor_positions[FINGER1]['position'][0] = self.enc_to_rad(pos, BASE_TYPE)
01330                         self.motor_positions[FINGER1]['position'][1] = self.enc_to_rad(jpos, BASE_TYPE)
01331                         
01332                         
01333                 elif msg.ID == F2_POSITION:
01334                         self.motor_positions[FINGER2]['encoder'][0] = pos
01335                         self.motor_positions[FINGER2]['encoder'][1] = jpos
01336                         self.motor_positions[FINGER2]['position'][0] = self.enc_to_rad(pos, BASE_TYPE)
01337                         self.motor_positions[FINGER2]['position'][1] = self.enc_to_rad(jpos, BASE_TYPE)
01338                         
01339                         
01340                 elif msg.ID == F3_POSITION:
01341                         self.motor_positions[FINGER3]['encoder'][0] = pos
01342                         self.motor_positions[FINGER3]['encoder'][1] = jpos
01343                         self.motor_positions[FINGER3]['position'][0] = self.enc_to_rad(pos, BASE_TYPE)
01344                         self.motor_positions[FINGER3]['position'][1] = self.enc_to_rad(jpos, BASE_TYPE)
01345                         
01346                         
01347                         
01348                 elif msg.ID == SPREAD_POSITION:
01349                         self.motor_positions[SPREAD]['encoder'][0] = pos
01350                         self.motor_positions[SPREAD]['encoder'][1] = jpos
01351                         self.motor_positions[SPREAD]['position'][0] = self.enc_to_rad(pos, SPREAD_TYPE)
01352                         self.motor_positions[SPREAD]['position'][1] = self.enc_to_rad(jpos, SPREAD_TYPE)
01353                         
01354                         
01355         
01356         def process_strain(self, msg):
01357                 '''
01358                         Process the msg and extract the strain value depending on the CAN ID
01359                 '''
01360                 data = msg.DATA
01361                 value =(0x0000100 * data[3]) + (0x0000001 * data[2])
01362                 
01363                 if msg.ID == F1_STRAIN:
01364                         self.strain[FINGER1] = value
01365                 if msg.ID == F2_STRAIN:
01366                         self.strain[FINGER2] = value
01367                 if msg.ID == F3_STRAIN:
01368                         self.strain[FINGER3] = value
01369         
01370         def process_motor_temp(self, msg):
01371                 '''
01372                         Process the msg and extract the temperature of the motor puck on the CAN ID
01373                 '''
01374                 data = msg.DATA
01375                 value =(0x0000100 * data[3]) + (0x0000001 * data[2])
01376                 
01377                 if msg.ID == F1_MOTOR_TEMP:
01378                         self.temp[FINGER1]['temp'] = value
01379                         
01380                 if msg.ID == F2_MOTOR_TEMP:
01381                         self.temp[FINGER2]['temp'] = value
01382                         
01383                 if msg.ID == F3_MOTOR_TEMP:
01384                         self.temp[FINGER3]['temp'] = value
01385                         
01386                 if msg.ID == SPREAD_MOTOR_TEMP:
01387                         self.temp[SPREAD]['temp'] = value
01388                         
01389                         
01390         def process_motor_therm(self, msg):
01391                 '''
01392                         Process the msg and extract the temperature of the motor on the CAN ID
01393                 '''
01394                 data = msg.DATA
01395                 value =(0x0000100 * data[3]) + (0x0000001 * data[2])
01396                 
01397                 if msg.ID == F1_MOTOR_THERM:
01398                         self.temp[FINGER1]['therm'] = value
01399                         
01400                 if msg.ID == F2_MOTOR_THERM:
01401                         self.temp[FINGER2]['therm'] = value
01402                         
01403                 if msg.ID == F3_MOTOR_THERM:
01404                         self.temp[FINGER3]['therm'] = value
01405                         
01406                 if msg.ID == SPREAD_MOTOR_THERM:
01407                         self.temp[SPREAD]['therm'] = value
01408                         
01409         
01410         def process_full_tact(self, msg):
01411                 '''
01412                         Process and saves all the messages containing the tactile information
01413                 '''
01414                 
01415                 data = msg.DATA
01416                 
01417                 if msg.ID == F1_TACT:
01418                         if data[0] >= 0x00 and data[0] < 0x10:
01419                                 self.tactile_sensor[FINGER1]['data'][0] = data                  
01420                         if data[0] >= 0x10 and data[0] < 0x20:
01421                                 self.tactile_sensor[FINGER1]['data'][1] = data
01422                         if data[0] >= 0x20 and data[0] < 0x30:
01423                                 self.tactile_sensor[FINGER1]['data'][2] = data
01424                         if data[0] >= 0x30 and data[0] < 0x40:
01425                                 self.tactile_sensor[FINGER1]['data'][3] = data
01426                         if data[0] >= 0x40:
01427                                 self.tactile_sensor[FINGER1]['data'][4] = data
01428                                 self.tactile_sensor[FINGER1]['values'] = self.process_tactile_data(self.tactile_sensor[FINGER1]['data'])
01429                 if msg.ID == F2_TACT:
01430                         if data[0] >= 0x00 and data[0] < 0x10:
01431                                 self.tactile_sensor[FINGER2]['data'][0] = data                  
01432                         if data[0] >= 0x10 and data[0] < 0x20:
01433                                 self.tactile_sensor[FINGER2]['data'][1] = data
01434                         if data[0] >= 0x20 and data[0] < 0x30:
01435                                 self.tactile_sensor[FINGER2]['data'][2] = data
01436                         if data[0] >= 0x30 and data[0] < 0x40:
01437                                 self.tactile_sensor[FINGER2]['data'][3] = data
01438                         if data[0] >= 0x40:
01439                                 self.tactile_sensor[FINGER2]['data'][4] = data
01440                                 self.tactile_sensor[FINGER2]['values'] = self.process_tactile_data(self.tactile_sensor[FINGER2]['data'])
01441                 if msg.ID == F3_TACT:
01442                         if data[0] >= 0x00 and data[0] < 0x10:
01443                                 self.tactile_sensor[FINGER3]['data'][0] = data                  
01444                         if data[0] >= 0x10 and data[0] < 0x20:
01445                                 self.tactile_sensor[FINGER3]['data'][1] = data
01446                         if data[0] >= 0x20 and data[0] < 0x30:
01447                                 self.tactile_sensor[FINGER3]['data'][2] = data
01448                         if data[0] >= 0x30 and data[0] < 0x40:
01449                                 self.tactile_sensor[FINGER3]['data'][3] = data
01450                         if data[0] >= 0x40:
01451                                 self.tactile_sensor[FINGER3]['data'][4] = data
01452                                 self.tactile_sensor[FINGER3]['values'] = self.process_tactile_data(self.tactile_sensor[FINGER3]['data'])
01453                 if msg.ID == PALM_TACT:
01454                         if data[0] >= 0x00 and data[0] < 0x10:
01455                                 self.tactile_sensor[SPREAD]['data'][0] = data                   
01456                         if data[0] >= 0x10 and data[0] < 0x20:
01457                                 self.tactile_sensor[SPREAD]['data'][1] = data
01458                         if data[0] >= 0x20 and data[0] < 0x30:
01459                                 self.tactile_sensor[SPREAD]['data'][2] = data
01460                         if data[0] >= 0x30 and data[0] < 0x40:
01461                                 self.tactile_sensor[SPREAD]['data'][3] = data
01462                         if data[0] >= 0x40:
01463                                 self.tactile_sensor[SPREAD]['data'][4] = data
01464                                 self.tactile_sensor[SPREAD]['values'] = self.process_tactile_data(self.tactile_sensor[SPREAD]['data'])
01465                                 
01466         def process_tactile_data(self, data_array):
01467                 '''
01468                         Process the array of data and returns a tactile array
01469                 '''
01470                 tactileVals = range(0,24)
01471                 index_ = 0
01472                 for data in data_array:
01473                         index_ = int(data[0]/16) * 5
01474                         
01475                         
01476                         tactileVals[index_ + 0] = round(((data[0]%0x10)*0x100 + data[1])/256.0,2)
01477                         tactileVals[index_ + 1] = round((data[2]*0x10 + int(data[3]/0x10))/256.0,2)
01478                         tactileVals[index_ + 2] = round(((data[3]%0x10)*0x100 + data[4])/256.0,2)
01479                         tactileVals[index_ + 3] = round((data[5]*0x10 + int(data[6]/0x10))/256.0,2)
01480                         if index_ != 20:
01481                                 tactileVals[index_ + 4] = round(((data[6]%0x10)*0x100 + data[7])/256.0,2)
01482                 
01483                 return tactileVals
01484         
01485                 
01486         def new_temp_mail(self, fingers_to_change):
01487                 former_mailbox_c={}
01488                 for finger in fingers_to_change:
01489                         former_mailbox_c[finger]=self.get_property(finger,GRPC)
01490                         self.set_property(finger,GRPC,12)
01491                 return former_mailbox_c
01492 
01493         def revert_temp_mail(self, fingers_to_change,former):
01494                 for finger in fingers_to_change:
01495                         former_mailbox_value=former[finger]
01496                         self.set_property(finger,GRPC,former_mailbox_value)
01497         
01498 
01499         def enc_to_per(self, enc):
01500                 '''
01501                 Given an angle in encoder counts, return the percentage of the angle that represents.
01502 
01503                         @param enc: Encoder counts.
01504                         @type enc: int
01505                         @return: Percentage
01506                         @rtype: float
01507                 '''
01508                 per = enc/1950.0
01509                 return round(per, 2)
01510 
01511         def enc_to_rad(self, enc, type = BASE_TYPE):
01512                 '''
01513                 Given an angle in encoder counts, return the radian measure of the angle that represents.
01514 
01515                         @param enc: Encoder counts.
01516                         @type enc: int
01517                         @return: Radians
01518                         @rtype: float
01519                 '''
01520                 motion_limit = BASE_LIMIT
01521                 tics = MAX_ENCODER_TICKS
01522                 
01523                 if type == TIP_TYPE:
01524                         motion_limit = TIP_LIMIT
01525                         tics = MAX_FINGERTIP_TICKS
01526                 elif type == SPREAD_TYPE:
01527                         motion_limit = SPREAD_LIMIT
01528                         tics = MAX_SPREAD_TICKS
01529                                 
01530                 PI = 3.141592653589
01531                 rad = enc * (motion_limit*PI/180)/tics
01532                 return round(rad,2)
01533 
01534         def enc_to_deg(self, enc):
01535                 '''
01536                 Given an angle in encoder counts, return the degree measure of the angle that represents.
01537 
01538                         @param enc: Encoder counts.
01539                         @type enc: int
01540                         @return: Degrees
01541                         @rtype: float
01542                 '''
01543                 deg = enc * 140/MAX_ENCODER_TICKS
01544                 return round(deg,2)
01545 
01546         def per_to_enc(self, per):
01547                 '''
01548                 Given a percentage of an angle, return it in encoder counts.
01549 
01550                         @param per: Percentage
01551                         @type per: float
01552                         @return: Encoder counts
01553                         @rtype: int
01554                 '''
01555                 enc = per * 1950.0
01556                 return int(enc)
01557 
01558         def rad_to_enc(self, rad, type = BASE_TYPE):
01559                 '''
01560                 Given the readian measure of an angle, return it in encoder counts.
01561 
01562                         @param rad: Radians
01563                         @type rad: float
01564                         @return: Encoder counts
01565                         @rtype: int
01566                 '''
01567                 motion_limit = BASE_LIMIT
01568                 tics = MAX_ENCODER_TICKS
01569                 
01570                 if type == TIP_TYPE:
01571                         motion_limit = TIP_LIMIT
01572                         tics = MAX_FINGERTIP_TICKS
01573                 elif type == SPREAD_TYPE:
01574                         motion_limit = SPREAD_LIMIT
01575                         tics = MAX_SPREAD_TICKS
01576                         
01577                 PI = 3.141592653589
01578                 enc = rad / ((motion_limit*PI/180)/tics)
01579                 return int(enc)
01580 
01581         def deg_to_enc(self, deg):
01582 
01583                 '''
01584                 Given a degree measure of an angle, return it in encoder counts.
01585 
01586                         @param deg: Degrees
01587                         @type deg: float
01588                         @return: Encoder counts
01589                         @rtype: int
01590                 '''
01591                 enc = deg * 195000.0/140
01592                 return int(enc)
01593         
01594         def clean_read_buffer(self):
01595                 
01596                 result_ = self.read_msg()
01597                         
01598                 while result_[0] == 0:
01599                         result_ = self.read_msg()
01600