class CalibrationScreen(QtGui.QWidget): """ The main window in this application. """ def __init__(self, cfgfile, port): QtGui.QWidget.__init__(self, None) self.config_file = cfgfile self.config = furious.config.parse_config(self.config_file) self.board = FuriousBoard() if not port: port = self.board.probe() if not port: QtGui.QMessageBox.information(self, "Error", "Unable to detect a Furious board.", QtGui.QMessageBox.Ok) QtGui.qApp.exit(1) # For some reason, the app doesn't exit immediately after the call # to qApp.exit() above, so this next line is needed for a clean # shutdown. exit(1) self.board.open(port) if not self.board.is_ready(): QtGui.QMessageBox.information( self, "Error", "Unable to connect to Furious board on %s." % port, QtGui.QMessageBox.Ok) QtGui.qApp.exit(1) quitBtn = QtGui.QPushButton("Quit") self.connect(quitBtn, QtCore.SIGNAL('clicked()'), QtGui.qApp, QtCore.SLOT('quit()')) saveBtn = QtGui.QPushButton("Save") self.connect(saveBtn, QtCore.SIGNAL('clicked()'), self.saveConfig) buttons = QtGui.QHBoxLayout() buttons.addWidget(saveBtn) buttons.addWidget(quitBtn) layout = QtGui.QVBoxLayout() statusLbl = QtGui.QLabel("Connected on %s" % port) layout.addWidget(statusLbl) for sname in self.config['servo']: servo = self.config['servo'][sname] sc = ServoControl(self, sname, servo) layout.addWidget(sc) layout.addLayout(buttons) self.setLayout(layout) def __del__(self): self.board.close() def updateBoardState(self, servo_id, val): self.board.servos[int(servo_id)] = val self.board.update() def saveConfig(self): furious.config.save_config(self.config, self.config_file) QtGui.QMessageBox.information( self, "Message", "Your configuration has been saved to %s." % self.config_file, QtGui.QMessageBox.Ok)
class CalibrationScreen(QtGui.QWidget): """ The main window in this application. """ def __init__(self, cfgfile, port): QtGui.QWidget.__init__(self, None) self.config_file = cfgfile self.config = furious.config.parse_config(self.config_file) self.board = FuriousBoard() if not port: port = self.board.probe() if not port: QtGui.QMessageBox.information( self, "Error", "Unable to detect a Furious board.", QtGui.QMessageBox.Ok ) QtGui.qApp.exit(1) # For some reason, the app doesn't exit immediately after the call # to qApp.exit() above, so this next line is needed for a clean # shutdown. exit(1) self.board.open(port) if not self.board.is_ready(): QtGui.QMessageBox.information( self, "Error", "Unable to connect to Furious board on %s." % port, QtGui.QMessageBox.Ok ) QtGui.qApp.exit(1) quitBtn = QtGui.QPushButton("Quit") self.connect(quitBtn, QtCore.SIGNAL('clicked()'), QtGui.qApp, QtCore.SLOT('quit()')) saveBtn = QtGui.QPushButton("Save") self.connect(saveBtn, QtCore.SIGNAL('clicked()'), self.saveConfig) buttons = QtGui.QHBoxLayout() buttons.addWidget(saveBtn) buttons.addWidget(quitBtn) layout = QtGui.QVBoxLayout() statusLbl = QtGui.QLabel("Connected on %s" % port) layout.addWidget(statusLbl) for sname in self.config['servo']: servo = self.config['servo'][sname] sc = ServoControl(self, sname, servo) layout.addWidget(sc) layout.addLayout(buttons) self.setLayout(layout) def __del__(self): self.board.close() def updateBoardState(self, servo_id, val): self.board.servos[int(servo_id)] = val self.board.update() def saveConfig(self): furious.config.save_config(self.config, self.config_file) QtGui.QMessageBox.information( self, "Message", "Your configuration has been saved to %s." % self.config_file, QtGui.QMessageBox.Ok )
class FuriousDriver(object): """ This is the high-level class that encapsulates the devices from L{furious.devices} and translates raw values from the Furious board into units that are meaningful to humans. """ def __init__(self, config_file=None): """ The constructor does some default configuration, but the driver usually needs to load a config file via L{load_config} to be fully initialized. """ self._board = FuriousBoard() self._servos = {} self._odometer = Odometer(self._board) self._logic_batt = Battery(self._board, port=7) self._motor_batt = Battery(self._board, port=6) self._dbg = None # Observer object for debug messages if config_file: self.load_config(config_file) ### configuration ### def load_config(self, filename): """ Configures the robot according to the settings in the given configuration file. @param filename: a filename containing configuration settings @type filename: string @return: None """ # parse_config() takes care of the messiness of reading and cleaning # up the config file. config = parse_config(filename) for key in config: if key == "servo": for servo_name in config[key]: servo = config[key][servo_name] id = servo[0] min = servo[1] center = servo[2] max = servo[3] self._servos[servo_name] = Servo(self._board, id, min, center, max) elif key == "odometer": self._odometer = Odometer(self._board, config[key]) # TODO: add battery level customizations ### connecting, disconnecting, etc ### def connect(self, port): """ Attempts to establish a serial connection to the Furious board on the specified port (eg, "/dev/ttyACM0"). """ self._board.open(port) time.sleep(0.5) self.refresh() time.sleep(0.5) self.refresh() def disconnect(self): """ Immediately stops all servos and closes the board's serial connection. """ cmd = self.stop() self._board.close() return cmd def probe(self): """ Probes the computer for a Furious board and returns the port that has one attached to it. Returns None if no board can be found. Note that this does not connect the driver to the board; use L{open()} for that. """ return self._board.probe() def is_ready(self): """ Returns true if the robot is ready to accept commands. """ return self._board.is_ready() ### communicating with the board ### def stop(self): """ Immediately stops all servos. Good for emergencies and when you reach your goal (or the end of your program). @return: the serial command string that was sent on this update, for debugging purposes """ for i in range(len(self._board.servos)): self._board.servos[i] = 0 return self.refresh() def refresh(self): """ Sends all pending commands to and receives all updates from the board. @return: the serial command string that was sent on this update, for debugging purposes """ # Update the board sent = "" try: sent = self._board.update() # Handle the case when a read or write is interrupted. except OSError, e: self.stop() if e.errno != errno.EINTR: # if not interrupted system call raise e # propagate the exception except select.error, e: self.stop() if e[0] != errno.EINTR: raise e