00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 import serial, time, sys, thread
00034 from ax12 import *
00035 from struct import unpack
00036
00037
00038 class ArbotiXException(Exception):
00039 pass
00040
00041
00042 class ArbotiX:
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 def __init__(self, port="/dev/ttyUSB0", baud=115200, timeout=0.1, open_port=True):
00055 self._mutex = thread.allocate_lock()
00056 self._ser = serial.Serial()
00057
00058 self._ser.port = port
00059 self._ser.baudrate = baud
00060 self._ser.timeout = timeout
00061
00062 if open_port:
00063 self._ser.open()
00064
00065
00066 self.error = 0
00067
00068 def __write__(self, msg):
00069 try:
00070 self._ser.write(msg)
00071 except serial.SerialException as e:
00072 self._mutex.release()
00073 raise ArbotiXException(e)
00074
00075 def openPort(self):
00076 self._ser.close()
00077 try:
00078 self._ser.open()
00079 except serial.SerialException as e:
00080 raise ArbotiXException(e)
00081
00082 def closePort(self):
00083 self._ser.close()
00084
00085
00086
00087
00088
00089
00090 def getPacket(self, mode, id=-1, leng=-1, error=-1, params = None):
00091 try:
00092 d = self._ser.read()
00093 except Exception as e:
00094 print e
00095 return None
00096
00097 if d == '':
00098 return None
00099
00100
00101 if mode == 0:
00102 if ord(d) == 0xff:
00103 return self.getPacket(1)
00104 else:
00105 return self.getPacket(0)
00106 elif mode == 1:
00107 if ord(d) == 0xff:
00108 return self.getPacket(2)
00109 else:
00110 return self.getPacket(0)
00111 elif mode == 2:
00112 if d != 0xff:
00113 return self.getPacket(3, ord(d))
00114 else:
00115 return self.getPacket(0)
00116 elif mode == 3:
00117 return self.getPacket(4, id, ord(d))
00118 elif mode == 4:
00119 self.error = ord(d)
00120 if leng == 2:
00121 return self.getPacket(6, id, leng, ord(d), list())
00122 else:
00123 return self.getPacket(5, id, leng, ord(d), list())
00124 elif mode == 5:
00125 params.append(ord(d))
00126 if len(params) + 2 == leng:
00127 return self.getPacket(6, id, leng, error, params)
00128 else:
00129 return self.getPacket(5, id, leng, error, params)
00130 elif mode == 6:
00131 checksum = id + leng + error + sum(params) + ord(d)
00132 if checksum % 256 != 255:
00133 return None
00134 return params
00135
00136 return None
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 def execute(self, index, ins, params, ret=True):
00150 values = None
00151 self._mutex.acquire()
00152 try:
00153 self._ser.flushInput()
00154 except Exception as e:
00155 print e
00156 length = 2 + len(params)
00157 checksum = 255 - ((index + length + ins + sum(params))%256)
00158 self.__write__(chr(0xFF)+chr(0xFF)+chr(index)+chr(length)+chr(ins))
00159 for val in params:
00160 self.__write__(chr(val))
00161 self.__write__(chr(checksum))
00162 if ret:
00163 values = self.getPacket(0)
00164 self._mutex.release()
00165 return values
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 def read(self, index, start, length):
00177 values = self.execute(index, AX_READ_DATA, [start, length])
00178 if values == None:
00179 return -1
00180 else:
00181 return values
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 def write(self, index, start, values):
00193 self.execute(index, AX_WRITE_DATA, [start] + values)
00194 return self.error
00195
00196
00197
00198
00199
00200
00201
00202 def syncWrite(self, start, values):
00203 output = list()
00204 for i in values:
00205 output = output + i
00206 length = len(output) + 4
00207 lbytes = len(values[0])-1
00208 self._mutex.acquire()
00209 try:
00210 self._ser.flushInput()
00211 except:
00212 pass
00213 self.__write__(chr(0xFF)+chr(0xFF)+chr(254)+chr(length)+chr(AX_SYNC_WRITE))
00214 self.__write__(chr(start))
00215 self.__write__(chr(lbytes))
00216 for i in output:
00217 self.__write__(chr(i))
00218 checksum = 255 - ((254 + length + AX_SYNC_WRITE + start + lbytes + sum(output))%256)
00219 self.__write__(chr(checksum))
00220 self._mutex.release()
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 def syncRead(self, servos, start, length):
00232 return self.execute(0xFE, AX_SYNC_READ, [start, length] + servos )
00233
00234
00235
00236
00237
00238
00239
00240
00241 def setBaud(self, index, baud):
00242 return self.write(index, P_BAUD_RATE, [baud, ])
00243
00244
00245
00246
00247
00248
00249 def getReturnLevel(self, index):
00250 try:
00251 return int(self.read(index, P_RETURN_LEVEL, 1)[0])
00252 except:
00253 return -1
00254
00255
00256
00257
00258
00259
00260
00261
00262 def setReturnLevel(self, index, value):
00263 return self.write(index, P_RETURN_LEVEL, [value])
00264
00265
00266
00267
00268
00269
00270 def enableTorque(self, index):
00271 return self.write(index, P_TORQUE_ENABLE, [1])
00272
00273
00274
00275
00276
00277
00278 def disableTorque(self, index):
00279 return self.write(index, P_TORQUE_ENABLE, [0])
00280
00281
00282
00283
00284
00285
00286
00287
00288 def setLed(self, index, value):
00289 return self.write(index, P_LED, [value])
00290
00291
00292
00293
00294
00295
00296
00297
00298 def setPosition(self, index, value):
00299 return self.write(index, P_GOAL_POSITION_L, [value%256, value>>8])
00300
00301
00302
00303
00304
00305
00306
00307
00308 def setSpeed(self, index, value):
00309 return self.write(index, P_GOAL_SPEED_L, [value%256, value>>8])
00310
00311
00312
00313
00314
00315
00316 def getPosition(self, index):
00317 values = self.read(index, P_PRESENT_POSITION_L, 2)
00318 try:
00319 return int(values[0]) + (int(values[1])<<8)
00320 except:
00321 return -1
00322
00323
00324
00325
00326
00327
00328 def getSpeed(self, index):
00329 values = self.read(index, P_PRESENT_SPEED_L, 2)
00330 try:
00331 return int(values[0]) + (int(values[1])<<8)
00332 except:
00333 return -1
00334
00335
00336
00337
00338
00339
00340 def getGoalSpeed(self, index):
00341 values = self.read(index, P_GOAL_SPEED_L, 2)
00342 try:
00343 return int(values[0]) + (int(values[1])<<8)
00344 except:
00345 return -1
00346
00347
00348
00349
00350
00351
00352 def getVoltage(self, index):
00353 try:
00354 return int(self.read(index, P_PRESENT_VOLTAGE, 1)[0])/10.0
00355 except:
00356 return -1
00357
00358
00359
00360
00361
00362
00363 def getTemperature(self, index):
00364 try:
00365 return int(self.read(index, P_PRESENT_TEMPERATURE, 1)[0])
00366 except:
00367 return -1
00368
00369
00370
00371
00372
00373
00374 def isMoving(self, index):
00375 try:
00376 d = self.read(index, P_MOVING, 1)[0]
00377 except:
00378 return True
00379 return d != 0
00380
00381
00382
00383
00384 def enableWheelMode(self, index):
00385 self.write(index, P_CCW_ANGLE_LIMIT_L, [0,0])
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 def disableWheelMode(self, index, resolution=10):
00396 resolution = (2 ** resolution) - 1
00397 self.write(index, P_CCW_ANGLE_LIMIT_L, [resolution%256,resolution>>8])
00398
00399
00400 FORWARD = 0
00401
00402 BACKWARD = 1
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 def setWheelSpeed(self, index, direction, speed):
00414 if speed > 1023:
00415 speed = 1023
00416 if direction == self.FORWARD:
00417
00418 self.write(index, P_GOAL_SPEED_L, [speed%256, speed>>8])
00419 else:
00420
00421 speed += 1024
00422 self.write(index, P_GOAL_SPEED_L, [speed%256, speed>>8])
00423
00424
00425
00426
00427
00428 LOW = 0
00429
00430 HIGH = 0xff
00431
00432 INPUT = 0
00433
00434 OUTPUT = 0xff
00435
00436
00437
00438
00439 REG_DIGITAL_IN0 = 5
00440 REG_DIGITAL_IN1 = 6
00441 REG_DIGITAL_IN2 = 7
00442 REG_DIGITAL_IN3 = 8
00443
00444 REG_RESCAN = 15
00445
00446
00447
00448 ANA_BASE = 18
00449
00450
00451 SERVO_BASE = 26
00452
00453 REG_DIGITAL_OUT0 = 47
00454
00455
00456 def rescan(self):
00457 self.write(253, self.REG_RESCAN, [1,])
00458
00459
00460
00461
00462
00463
00464
00465
00466 def getAnalog(self, index, leng=1):
00467 try:
00468 val = self.read(253, self.ANA_BASE+int(index), leng)
00469 return sum(val[i] << (i * 8) for i in range(leng))
00470 except:
00471 return -1
00472
00473
00474
00475
00476
00477
00478 def getDigital(self, index):
00479 try:
00480 if index < 32:
00481 x = self.read(253, self.REG_DIGITAL_IN0 + int(index/8), 1)[0]
00482 else:
00483 return -1
00484 except:
00485 return -1
00486 if x & (2**(index%8)):
00487 return 255
00488 else:
00489 return 0
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 def setDigital(self, index, value, direction=0xff):
00501 if index > 31: return -1
00502 if value == 0 and direction > 0:
00503 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [1])
00504 elif value > 0 and direction > 0:
00505 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [3])
00506 elif value > 0 and direction == 0:
00507 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [2])
00508 else:
00509 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [0])
00510 return 0
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 def setServo(self, index, value):
00521 if index > 7: return -1
00522 if value != 0 and (value < 500 or value > 2500):
00523 print "ArbotiX Error: Servo value out of range:", value
00524 else:
00525 self.write(253, self._SERVO_BASE + 2*index, [value%256, value>>8])
00526 return 0
00527