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