57 from serial.serialutil
import SerialException, SerialTimeoutException
63 MotorNames = [
'left_front',
'right_front',
'left_rear',
'right_rear']
65 -------------------------------------------------------------------------------" 73 fd = sys.stdin.fileno()
74 self.
oldterm = termios.tcgetattr(fd)
75 self.
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
81 fd = sys.stdin.fileno()
82 termios.tcsetattr(fd, termios.TCSAFLUSH, self.
oldterm)
83 fcntl.fcntl(fd, fcntl.F_SETFL, self.
oldflags)
85 def setNonBlocking(self):
86 fd = sys.stdin.fileno()
87 newattr = termios.tcgetattr(fd)
88 newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
89 termios.tcsetattr(fd, termios.TCSANOW, newattr)
90 fcntl.fcntl(fd, fcntl.F_SETFL, self.
oldflags | os.O_NONBLOCK)
108 def open(self, dev, baud, fnChipSelect=None):
119 def readVersion(self, addr):
120 return "1.5.6 firmwareXYZ" 122 def readMainBatterySettings(self, addr):
125 def readLogicBatterySettings(self, addr):
126 raise SerialTimeoutException(
'bogus')
128 def readEncoderMode(self, addr):
131 def readM1Pidq(self, addr):
132 return (0x00010000, 0x00008000, 0x00004000, 10000)
134 def readM2Pidq(self, addr):
135 return (0x00010000, 0x00008000, 0x00004000, 10000)
137 def readErrorState(self, addr):
140 def readTemperature(self, addr):
143 def readMainBattery(self, addr):
146 def readLogicBattery(self, addr):
149 def readCurrents(self, addr):
152 def readM1Speed(self, addr):
153 if not self.m1_speed.has_key(addr):
154 self.m1_speed[addr] = 0
155 return (self.m1_speed[addr], 0x00)
157 def readM2Speed(self, addr):
158 if not self.m2_speed.has_key(addr):
159 self.m2_speed[addr] = 0
160 return (self.m2_speed[addr], 0x00)
162 def setM1Speed(self, addr, speed):
163 self.m1_speed[addr] = speed
165 def setM2Speed(self, addr, speed):
166 self.m2_speed[addr] = speed
168 def readM1Encoder(self, addr):
169 if not self.m1_encoder.has_key(addr):
170 self.m1_encoder[addr] = random.randint(0, 1000000)
171 return (self.m1_encoder[addr], 0)
173 def readM2Encoder(self, addr):
174 if not self.m2_encoder.has_key(addr):
175 self.m2_encoder[addr] = random.randint(0, 1000000)
176 return (self.m2_encoder[addr], 0x02)
178 def resetEncoderCnts(self, addr):
179 self.m1_encoder[addr] = 0
180 self.m2_encoder[addr] = 0
188 def __init__(self, kwargs):
193 'front': {
'addr': SysConf.MotorCtlrAddrFront,
'name':
'front'},
194 'rear': {
'addr': SysConf.MotorCtlrAddrRear,
'name':
'rear'}
197 self.
motorKeys = [
'left_front',
'right_front',
'left_rear',
'right_rear']
200 {
'ctlr_key':
'front',
'motor_index': 0,
'name':
'left_front'},
202 {
'ctlr_key':
'front',
'motor_index': 1,
'name':
'right_front'},
204 {
'ctlr_key':
'rear',
'motor_index': 0,
'name':
'left_rear'},
206 {
'ctlr_key':
'rear',
'motor_index': 1,
'name':
'right_rear'},
209 def run(self, keepalive):
210 motorkey = self.
kwargs[
'motor']
211 goalspeed = self.
kwargs[
'speed']
215 print "*** Laelaps %s(%d) motor speed=%d test ***" % \
216 (motorkey, self.motorKeys.index(motorkey), goalspeed)
223 motorctlr = RoboClaw.RoboClaw()
226 device = SysConf.MotorCtlrDevName
227 baud = SysConf.MotorCtlrBaudRate
229 print "Open motor controller serial interface %s@%d" % (device, baud)
231 motorctlr.open(device, baud,
None)
232 except RoboClaw.RoboClawException
as inst:
233 print 'Error:', inst.message
236 if motorctlr.isOpen():
238 mi = self.
motorInfo[motorkey][
'motor_index']
241 setSpeed = motorctlr.setM1Speed
242 readSpeed = motorctlr.readM1Speed
243 readEncoder = motorctlr.readM1Encoder
245 setSpeed = motorctlr.setM2Speed
246 readSpeed = motorctlr.readM2Speed
247 readEncoder = motorctlr.readM2Encoder
249 motorctlr.resetEncoderCnts(addr)
252 setSpeed(addr, goalspeed)
253 except RoboClaw.RoboClawException
as inst:
254 print "Failed to set speed" 258 print "Press any key to abort" 266 while kb.getchar()
is None:
268 curspeed, status = readSpeed(addr)
269 curenc, status = readEncoder(addr)
270 print "%5d. %10d %14d\r" % (n, curspeed, curenc),
275 except RoboClaw.RoboClawException
as inst:
287 except RoboClaw.RoboClawException
as inst:
288 print "Failed to stop" 301 self.
m_wd = WatchDog.WatchDog()
305 if not self.m_wd.open(SysConf.SensorDevName):
306 print 'Error: Failed to open connection to watchdog subprocessor.' 307 print ' Continuing...' 311 self.m_wd.cmdGetFwVersion()
314 ret = self.m_wd.cmdReadEnables()
315 if ret[
'rc'] !=
'ok':
316 print 'Error: Failed to read enable lines.' 317 print ' Continuing...' 320 if ret[
'enables'][
'motor_ctlr_en']:
321 print "Warning: Motor controllers already enabled - may be in use." 326 ret = self.m_wd.cmdEnableMotorCtlrs(
True)
327 if ret[
'rc'] !=
'ok':
328 print 'Error: Failed to enable motor controllers.' 329 print ' Continuing...' 334 print "Motor controllers enabled." 337 if self.m_wd.isOpen():
338 self.m_wd.cmdPetTheDog()
342 ret = self.m_wd.cmdEnableMotorCtlrs(
False)
343 if ret[
'rc'] ==
'ok':
344 print "Motor controllers disabled." 382 self.
_Argv0 = os.path.basename(__file__)
392 print "%s: Error: %s" % (self.
_Argv0, emsg)
394 print "%s: Error" % (self.
_Argv0)
395 print "Try '%s --help' for more information." % (self.
_Argv0)
401 usage: %s [OPTIONS] MOTOR SPEED 404 Run Laelaps speed test. 406 Options and arguments: 407 --fake : Run diagnostics on fake hardware." 408 -h, --help : Display this help and exit. 410 MOTOR : Motor name/id to test. One of: 411 left_front right_front left_rear right_rear 414 SPEED : Signed qpps speed of motor, with positive being forwards. 417 On success, 0. An exit status of 128 indicates usage 434 self.
_Argv0 = os.path.basename(kwargs.get(
'argv0', __file__))
437 kwargs[
'debug'] =
False 438 kwargs[
'fake'] =
False 442 opts, args = getopt.getopt(argv[1:],
"f?h",
443 [
'help',
'fake',
''])
444 except getopt.error, msg:
446 for opt, optarg
in opts:
447 if opt
in (
'-f',
'--fake'):
448 kwargs[
'fake'] =
True 449 elif opt
in (
'-h',
'--help',
'-?'):
460 kwargs[
'motor'] =
None 463 if (i >= 0)
and (i < len(MotorNames)):
464 kwargs[
'motor'] = MotorNames[i]
467 i = MotorNames.index(args[0])
468 kwargs[
'motor'] = args[0]
472 if kwargs[
'motor']
is None:
477 kwargs[
'speed'] = int(args[1])
492 def run(self, argv=None, **kwargs):
513 if __name__ ==
'__main__':
515 sys.exit( app.run() );
def printUsageErr(self, emsg)
Print usage error.
Laelaps diagnositcs application class.
msg
error message attribute
def __init__(self)
Constructor.
def getOptions(self, argv=None, kwargs)
Get command-line options.
def __init__(self, msg)
Constructor.
def printUsage(self)
Print Command-Line Usage Message.
def run(self, argv=None, kwargs)
Run application.
Unit test command-line exception class.