pyHand_api.py
Go to the documentation of this file.
00001 #  pyHand_api.py
00002 #  
00003 #  ~~~~~~~~~~~~
00004 #  
00005 #
00006 #  pyHand_api based on pyHand_api.py from Barrett Technology Hand Communications
00007 #  
00008 #  ~~~~~~~~~~~~
00009 #  
00010 # Software License Agreement (BSD License)
00011 #
00012 # Copyright (c) 2014, Robotnik Automation SLL
00013 # All rights reserved.
00014 #
00015 # Redistribution and use in source and binary forms, with or without
00016 # modification, are permitted provided that the following conditions
00017 # are met:
00018 #
00019 #  * Redistributions of source code must retain the above copyright
00020 #    notice, this list of conditions and the following disclaimer.
00021 #  * Redistributions in binary form must reproduce the above
00022 #    copyright notice, this list of conditions and the following
00023 #    disclaimer in the documentation and/or other materials provided
00024 #    with the distribution.
00025 #  * Neither the name of Robotnik Automation SSL nor the names of its
00026 #    contributors may be used to endorse or promote products derived
00027 #    from this software without specific prior written permission.
00028 #
00029 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00030 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00031 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00032 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00033 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00034 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00035 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00036 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00037 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00038 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00039 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00040 # POSSIBILITY OF SUCH DAMAGE.
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 # CAN MSG IDs
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 #==========================CAN_STUFF=======================================
00086 
00087 # Class pyHand based on library pyHand_api.py
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                 # initialize self.PCAN bus
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         #============================INIT_STUFF==================================
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                         #Reset Can bus
00190                         self.can_reset()
00191                         time.sleep(0.025)
00192                         # wake up pucks by setting the STAT(5) property to READY(2)
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                         #write 13 to the command property (CMD-29) of each of the pucks.
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                         
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         #============================SET_AND_GET_STUFF=========================
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         #def write_msg(self, msgID, data, delay=.015):
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                 #self.write_msg(msgID, data)
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                 #self.write_msg(msgID, data)
00343                 return self.send_msg(msgID, data)
00344 
00345 
00346         # TODO: Allow a "GET" from a group.
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                 #time.sleep(0.005)
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               # 4-bit Product Identifier
00501                 data[1] = int(role/2**6)%2==1   # Internal Thermistor Bit
00502                 data[2] = int(role/2**7)%2==1   # 20 MHz (vs 32 MHz)
00503                 data[3] = int(role/2**8)%2==1   # Is there a Dig+Ser Motor Encoder?
00504                 data[4] = int(role/2**9)%2==1   # Is there a Hall Motor Encoder?
00505                 data[5] = int(role/2**10)%2==1  # Is there an Enc Motor Encoder?
00506                 data[6] = int(role/2**11)%2==1  # Is there a Strain Gauge?
00507                 data[7] = int(role/2**12)%2==1  # IMU for Force-Torque Sensor
00508                 data[8] = int(role/2**13)%2==1  # Optical Motor Encoder
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         # I'm sorry that this method is so unbearably long, but it won't compile otherwise because of circular imports TT_TT
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                 # Set universal puck properties. (taterDefs[])
00563                 # if virtID in range(1,8)
00564                 #     self.set_property(puckID, TIE, 0)
00565                 #     self.set_property(puckID, ACCEL, 100)
00566                 #     self.set_property(puckID, AP, 0)
00567                 #     self.set_property(puckID, CT, 4096)
00568                 #     self.set_property(puckID, OT, 0)
00569                 #     self.set_property(puckID, CTS, 4096)
00570                 #     self.set_property(puckID, DP, 0)
00571                 #     self.set_property(puckID, MV, 100)
00572                 #     self.set_property(puckID, MCV, 100)
00573                 #     self.set_property(puckID, MOV, 100)
00574                 #     self.set_property(puckID, OT, 0)
00575                 #     self.set_property(puckID, HOLD, 0)
00576                 #     self.set_property(puckID, TSTOP, 0)
00577                 #     self.set_property(puckID, OTEMP, 60)
00578                 #     self.set_property(puckID, PTEMP, 0)
00579                 #     self.set_property(puckID, DS, -256)
00580                 #     self.set_property(puckID, KP, 2000)
00581                 #     self.set_property(puckID, KD, 8000)
00582                 #     self.set_property(puckID, KI, 0)
00583                         #wamDefaultMT has yet to be implemented correctly. The interns coding this don't really care about the WAM, so this will be put off until someone does.
00584                 
00585                 #Set Barrett Hand Defaults
00586                 is_280 = self.get_property(puckID, HALLH)==7 #Identifier for 280 version
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                         #self.set_property(puckID, AP, 0)
00597                         #self.save_property(puckID, AP)
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         #============================MOVING_STUFF================================
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         # TODO: Ensure that TSTOP > 0. Otherwise, this may be an infinite loop.
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         #============================INCREMENTALLY_MOVE_STUFF========================
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         #===========================NON_TRIVIAL FUNCTIONS=============================
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                 # Set TACT(106) to top10 mode (1)
01080                 self.set_property(msgID, TACT, TACT_10) 
01081                 self.write_msg(msgID, [TACT]) #GET TACT
01082                 read_result=self.PCAN.Read(PCAN_USBBUS1)
01083                 self.check_error(self.PCAN,read_result[0],"reading top ten tactile values")
01084                 #output is mapped to here.
01085                 output = read_result[1].DATA 
01086                 #parsing this output
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                                 #print 'sensor = %d, count = %d'%(sensor, count)
01094                                 topVals[sensor] = data[count]
01095                                 count+=1
01096                         top10 = top10/2
01097                         # Each bit represents one of the top 10 pressures for purposes of efficiency. top10 has the last bit sliced
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                 # Set TACT(106) to full mode (2)
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                 #First set TSTOP to 0.
01180                 self.set_property(puckID, TSTOP, 0)
01181                 #Set Velocity
01182                 self.set_property(puckID, V, velocity)
01183                 #Set mode to allow the puck to move.
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                 # Reads a can msg
01290                 msg = self.read_msg()
01291                 
01292                 # No read messages
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                         #print 'process_can_messages: CAN ID = %x'%can_id
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                         #print 'F1'
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                         #print 'F2'
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                         #print 'F3 = %f, %f'%(self.motor_positions[FINGER3]['position'][0], self.motor_positions[FINGER3]['position'][1])
01346                         #print 'F3'
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                         #print 'SPREAD = %f, %f'%(self.motor_positions[SPREAD]['position'][0], self.motor_positions[SPREAD]['position'][1])
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                         #print 'Motor Temp S'
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                         #print 'Motor Temp S'
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                         #print 'index = %d, data[0] = %x'%(index_, data[0])
01475                         # Get the bits and then unpack them.
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                 #print 'Return OK : %s'%(tactileVals)
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         #==========================ANGLE_CONVERSIONS=========================
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                 


bhand_controller
Author(s): Román Navarro , Jorge Ariño
autogenerated on Sun Oct 5 2014 22:24:40