Example #1
0
 def load(self):
     '''
     Loads up the settings from gado.conf and instantiates objects for:
         
         The Scanner
         The Robot
         The Webcam
     '''
     
     self.load_settings()
     
     self.scanner = Scanner(**self.s)
     self.robot = Robot(**self.s)
     self.camera = Webcam(**self.s)
Example #2
0
 def load(self):
     settings = import_settings()
     self.scanner = Scanner(**settings)
     self.robot = Robot(**settings)
     #self.connect()
     self.camera = Webcam(**settings)
Example #3
0
class GadoSystem():
    
    def __init__(self, q_in, q_out, recovered=False):
        self.q_in = q_in
        self.q_out = q_out
        settings = import_settings()
        if 'wizard_run' in settings:
            print 'gado_sys\twizard_run in settings %s' % (settings['wizard_run'])
        if not settings:
            print "gado_sys\tNo pre-existing settings detected"
            export_settings(**DEFAULT_SETTINGS)
            if not recovered: add_to_queue(self.q_out, messages.LAUNCH_WIZARD)
        elif 'wizard_run' in settings and int(settings['wizard_run']) == 0:
            print "gado_sys\tThe wizard was never run (at least to completion)"
            if not recovered: add_to_queue(self.q_out, messages.LAUNCH_WIZARD)
        else:
            if not recovered: add_to_queue(self.q_out, messages.READY)
        
        self.tk = Tk
        self.db = DBFactory(**settings).get_db()
        self.dbi = DBInterface(self.db)
        
        '''
        print 'gado_sys\tattempting to get webcam options'
        try:
            print 'gado_sys\t%s' % (self.camera.options())
        except:
            print 'gado_sys\tcamera options failed'
        
        print 'gado_sys\tattempting to call dumb()'
        print 'gado_sys\t%s' % (self.camera.dumb())
        '''
        self._load_settings(**settings)
        
        self.selected_set = None
        self.started = False
        
        #set the settings to the default
        self._armPosition = 0
        self._actuatorPosition = 0
    
    def _load_settings(self, image_path='images\\', **kargs):
        self.image_path = image_path
        
    def load(self):
        settings = import_settings()
        self.scanner = Scanner(**settings)
        self.robot = Robot(**settings)
        #self.connect()
        self.camera = Webcam(**settings)
    
    def mainloop(self):
        dbi = self.dbi
        q = self.q_out
        robot = self.robot
        
        #add_to_queue(q, messages.READY)
        
        while True:
            expecting_return = False
            try:
                msg = fetch_from_queue(self.q_in)
                if msg:
                    print "gado_sys\tfetched message from queue", msg
                if msg[0] == messages.ADD_ARTIFACT_SET_LIST:
                    expecting_return = True
                    i = dbi.add_artifact_set(**msg[1])
                    add_to_queue(q, messages.RETURN, i)
                
                elif msg[0] == messages.ARTIFACT_SET_LIST:
                    expecting_return = True
                    i = dbi.artifact_set_list()
                    add_to_queue(q, messages.RETURN, i)
                
                elif msg[0] == messages.DELETE_ARTIFACT_SET_LIST:
                    expecting_return = False
                    dbi.delete_artifact_set(msg[1])
                
                elif msg[0] == messages.DROP:
                    expecting_return = False
                    success = robot.dropActuator()
                    add_to_queue(q, messages.RETURN, success)
                
                elif msg[0] == messages.LIFT:
                    expecting_return = False
                    robot.lift()
                    
                elif msg[0] == messages.MOVE_DOWN:
                    expecting_return = True
                    stroke = self.robot.move_actuator(up = False)
                    add_to_queue(q, messages.RETURN, stroke)
                    
                elif msg[0] == messages.MOVE_UP:
                    expecting_return = True
                    stroke = self.robot.move_actuator(up = True)
                    add_to_queue(q, messages.RETURN, stroke)
                    
                elif msg[0] == messages.MOVE_LEFT:
                    expecting_return = True
                    degree = self.robot.move_arm(clockwise=False)
                    add_to_queue(q, messages.RETURN, degree)
                
                elif msg[0] == messages.MOVE_RIGHT:
                    expecting_return = True
                    degree = self.robot.move_arm(clockwise=True)
                    add_to_queue(q, messages.RETURN, degree)
                
                elif msg[0] == messages.RELOAD_SETTINGS:
                    expecting_return = False
                    settings = import_settings()
                    self.robot.updateSettings(**settings)
                    del self.camera
                    self.camera = Webcam(**settings)
                    del self.scanner
                    self.scanner = Scanner(**settings)
                    self._load_settings(**settings)
                
                elif msg[0] == messages.RESET:
                    expecting_return = False
                    self.robot.reset()
                
                elif msg[0] == messages.ROBOT_CONNECT:
                    expecting_return = True
                    success = self.connect()
                    add_to_queue(q, messages.RETURN, robot.connected())
                
                elif msg[0] == messages.SCANNER_CONNECT:
                    expecting_return = True
                    try: del self.scanner
                    except: pass
                    self.scanner = Scanner(**import_settings())
                    add_to_queue(q, messages.RETURN, self.scanner.connected())
                
                elif msg[0] == messages.SCANNER_PICTURE:
                    expecting_return = True
                    self.scanner.scanImage(DEFAULT_SCANNED_IMAGE)
                    add_to_queue(q, messages.RETURN, DEFAULT_SCANNED_IMAGE)

                elif msg[0] == messages.SET_SELECTED_ARTIFACT_SET:
                    expecting_return = True
                    self.selected_set = msg[1]

                elif msg[0] == messages.START:
                    expecting_return = False
                    self.start()
                
                elif msg[0] == messages.WEBCAM_LISTING:
                    print 'gado_sys\tWEBCAM_LISTING'
                    expecting_return = True
                    #self.camera = Webcam()
                    opts = self.camera.options()
                    print 'gado_sys\tWEBCAM_LISTING - %s' % opts
                    add_to_queue(q, messages.RETURN, opts)
                
                elif msg[0] == messages.WEBCAM_CONNECT:
                    print 'gado_sys\tWEBCAM_CONNECT switch made it'
                    expecting_return = True
                    if self.camera:
                        print 'gado_sys\tCamera already exists'
                        if self.camera.connected():
                            print 'gado_sys\tAlready connected to the webcam'
                            add_to_queue(q, messages.RETURN, self.camera.connected())
                            return
                        else: self.camera.disconnect()
                    self.camera = Webcam()
                    print 'gado_sys\tself.camera.connected() %s' % self.camera.connected()
                    add_to_queue(q, messages.RETURN, self.camera.connected())

                elif msg[0] == messages.WEBCAM_PICTURE:
                    expecting_return = True
                    self.camera.savePicture(DEFAULT_CAMERA_IMAGE)
                    add_to_queue(q, messages.RETURN, DEFAULT_CAMERA_IMAGE)
                    
                elif msg[0] == messages.WEIGHTED_ARTIFACT_SET_LIST:
                    expecting_return = True
                    li = self.dbi.weighted_artifact_set_list()
                    add_to_queue(q, messages.RETURN, arguments=li)
                elif msg[0] == messages.MAIN_ABANDON_SHIP:
                    add_to_queue(q, messages.GUI_LISTENER_DIE)
                    add_to_queue(self.q_in, messages.MAIN_ABANDON_SHIP)
                    return
                elif msg[0] == messages.STOP or msg[0] == messages.LAST_ARTIFACT or msg[0] == messages.RESET:
                    # These commands are only relevant if the robot is already running.
                    expecting_return = False
                    pass
                elif msg[0] == messages.GIVE_ME_A_ROBOT:
                    add_to_queue(q, messages.RETURN, self.robot)
                else:
                    # add it back to the in queue, was somebody else waiting for that message?
                    add_to_queue(self.q_in, msg[0], (msg[1] if len(msg) > 1 else None))
            except:
                print "EXCEPTION GENERATED"
                raise
                if expecting_return:
                    add_to_queue(q, messages.RETURN)
    
    def set_seletcted_set(self, set_id):
        self.selected_set = None
    
    def _sanity_checks(self):
        print 'gado_sys\tin sanity checks'
        if self.started:
            add_to_queue(self.q_out, messages.DISPLAY_ERROR,
                'The scanning process has already started')
            return False
        
        _a = 'a'
        self.started = id(_a)
        
        if not self.selected_set:
            print 'gado_sys\tfailed sanity check on selected_set'
            add_to_queue(self.q_out, messages.DISPLAY_ERROR,
                'Please select an artifact set from the dropdown.')
            self.started = False
            return False
        
        if not self.robot.connected():
            print 'gado_sys\tfailed sanity check on robot.connected()'
            #tkMessageBox.showerror("Initialization Error",
            #    "Lost connection to the robot, please try restarting.")
            self.connect()
            if not self.robot.connected():
                print "gado_sys\tCOMPLETELY FAILED ON robot.connected()"
                add_to_queue(self.q_out, messages.DISPLAY_ERROR,
                    'Unable to connect to the robot. Try pressing the reset button and then unplugging it and replugging it.')
                self.started = False
                return False
        
        add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Connected to the Gado')
        self.robot.reset()
        
        if not self.scanner.connected():
            print 'gado_sys\tfailed sanity check on scanner.connected(), retrying'
            try: del self.scanner
            except: pass
            self.scanner = Scanner(**import_settings())
            if not self.scanner.connected():
                print 'gado_sys\tfailed sanity check on scanner.connected()'
                #tkMessageBox.showerror("Initialization Error",
                #    "Lost connection to the scanner, please try restarting.")
                self.started = False
                add_to_queue(self.q_out, messages.DISPLAY_ERROR,
                    'Unable to connect to the scanner. Try unplugging it and replugging it. You may need to restart this application or run the setup wizard again.')
                return False
        add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Connected to the scanner')
        
        if not self.camera.connected():
            print 'gado_sys\tfailed sanity check on camera.connected()'
            add_to_queue(self.q_out, messages.DISPLAY_ERROR,
                'Unable to connect to the scanner. Try unplugging it and replugging it. You may need to restart this application or run the setup wizard again.')
            self.started = False
            return False
        add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Connected to the webcam')
        
        self.robot._moveActuator(self.robot.actuator_up_value)
        time.sleep(2)
        
        if self.started != id(_a):
            add_to_queue(self.q_out, messages.DISPLAY_ERROR, 'An unknown error has occurred. Try restarting this application')
            self.started = False
            return False
        
        add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Ready to begin scanning')
        
        return True
    
    def _checkMessages(self):
        '''
        Controls the gado loop
        
        Returns True if the process should continue
        Returns False if the process should after the current loop
        Resets and raises an error if things need to stop.
        
        '''
        if self.q_in.empty():
            return True
        msg = fetch_from_queue(self.q_in)
        if msg[0] == messages.STOP:
            add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Robot stopped.')
            self.started = False
            self.robot.stop()
            raise Exception('STOP CALLED')
        elif msg[0] == messages.RESET:
            self.robot.reset()
            add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Robot reset')
            raise Exception('RESET CALLED')
        elif msg[0] == messages.LAST_ARTIFACT:
            return False
        elif msg[0] == messages.START:
            add_to_queue(self.q_out, messages.DISPLAY_INFO, 'The robot is already running. If it is not, then please restart this application.')
        elif msg[0] == messages.SYSTEM_ABANDON_SHIP:
            self.robot.stop()
            add_to_queue(self.q_in, msg[0])
            raise Exception('Application Terminating')
        else:
            add_to_queue(self.q_out, msg[0], (msg[1] if len(msg) > 1 else None))
        return True
    
    def start(self):
        '''
        Starts the scanning process for the current in pile
        '''
        #Come back and make the sanity checks real
        if not self._sanity_checks():
            return False
        
        #The actual looping should be happening here, instead of in Robot.py
        #Robot.py should just run the loop once and all conditions/vars will be stored here
        #self.robotThread = RobotThread(self.robot)
        print "gado_sys\tchecking for messages"
        self._checkMessages()
        print 'gado_sys\tattempting to save picture'
        
        # Sometimes it gets left behind, get rid of it
        try: os.remove(DEFAULT_CAMERA_IMAGE)
        except: pass
        self.camera.savePicture(DEFAULT_CAMERA_IMAGE)
        self._checkMessages()
        print "gado_sys\tattempting to check for barcode"
        completed = check_for_barcode(DEFAULT_CAMERA_IMAGE)
        
        print 'gado_sys\timage_path %s' % self.image_path
        
        while not completed:
            # New Artifact!
            print "gado_sys\tattempting to add an artifact"
            completed = self._checkMessages() & completed
            artifact_info = new_artifact(self.dbi, self.selected_set)
            
            front_fn = artifact_info['front_path']
            back_fn = artifact_info['back_path']
            
            print 'gado_sys\trenaming webcam image to %s' % back_fn
            move(DEFAULT_CAMERA_IMAGE, back_fn)
            #os.rename(DEFAULT_CAMERA_IMAGE, back_fn)
            add_to_queue(self.q_out, messages.SET_WEBCAM_PICTURE, back_fn)
            
            print "gado_sys\tattempting to add an image"
            image_id = self.dbi.add_image(artifact_id, back_fn, False)
            
            print "gado_sys\tattempting to go pick up an object"
            completed = self._checkMessages() & completed
            self.robot.pickUpObject()
            
            print "gado_sys\tattempting to move object to scanner"
            completed = self._checkMessages() & completed
            self.robot.scanObject()
            
            print "gado_sys\tattempting to scan"
            completed = self._checkMessages() & completed
            
            # Sometimes it gets left behind :(
            try: os.remove(DEFAULT_SCANNED_IMAGE)
            except: pass
            self.scanner.scanImage(DEFAULT_SCANNED_IMAGE)
            
            print 'gado_sys\trenaming scanned images to %s' % front_fn
            move(DEFAULT_SCANNED_IMAGE, front_fn)
            #os.rename(DEFAULT_SCANNED_IMAGE, front_fn)
            add_to_queue(self.q_out, messages.SET_SCANNER_PICTURE, front_fn)
            image_id = self.dbi.add_image(artifact_id, front_fn, True)
            
            completed = self._checkMessages() & completed
            self.robot.moveToOut()
            self.camera.savePicture(DEFAULT_CAMERA_IMAGE)
            completed = check_for_barcode(DEFAULT_CAMERA_IMAGE)
        self.started = False
        print "Done with robot loop"
    
    def connect(self):
        '''
        Connect to the Gado.
        
        If a port is specified in the settings, then try to connect to it
        Otherwise scan through ports attempting to connect to the Robot
        '''
        settings = import_settings()
        if 'gado_port' in settings:
            success = self.robot.connect(settings['gado_port'])
            if success:
                return True
        return _connect(self.robot)

    
    def disconnect(self):
        '''
        I'm not sure why we would want to disconnect the robot
        '''
        return True
    
    def _capture_webcam(self):
        '''
        Captures a backside view of the next image in queue
        '''
        image = None
        return image
    
    def _check_barcode(self, image):
        '''
        Checks for a barcode within image
        '''
        return True
    
    def _scan_image(self):
        '''
        Instructs the scanner to scan the image
        This does not transfer the image to the computer yet
        '''
        pass
    
    def _transfer_image(self):
        pass
Example #4
0
class GadoSystem():
    
    def __init__(self, q_in, q_out, recovered=False):
        
        #Instantiate the logger
        loggerObj = Logger(self.__class__.__name__)
        self.logger = loggerObj.getLoggerInstance()
        
        self.logger.info("Initializing the Gado System...")
        
        #Load up both queues
        self.q_in = q_in
        self.q_out = q_out
        
        #Grab the settings from gado.conf (If it exists) and place them into
        #a local object so that they can be used here
        self.load_settings()
        
        #If there are no settings (because there is no gado.conf)
        if not self.s:
            #Grab the default settings and load them into a newly created gado.conf
            export_settings(**default_settings())
            
            #Load those default settings to a local object
            self.load_settings()
            
            #Because there is no gado.conf, we're going to need to launch
            #the configuration wizard so that the user can enter their
            #personal settings
            add_to_queue(self.q_out, messages.LAUNCH_WIZARD)
            
            print 'gado_sys\tasked to launch the wizard'
        
        #Even if we do have a gado.conf file, the wizard has never been run
        #so it needs to get launched for the user's personal preferences
        elif 'wizard_run' in self.s and int(self.s['wizard_run']) == 0:
            add_to_queue(self.q_out, messages.LAUNCH_WIZARD)
            print 'gado_sys\tasked to launch the wizard2'
        
        #If this is the first time the logic thread has been run,
        #tell the gui thread that the system is ready for interactions
        else:
            print 'gado_sys\tnot asked for a wizard'
            if not recovered: add_to_queue(self.q_out, messages.READY)
        
        #Get an instance of the database and the database interface
        self.db = DBFactory(**self.s).get_db()
        self.dbi = DBInterface(self.db)
        
        #Init local vars
        self.selected_set = None
        self.started = False
    
    def load_settings(self):
        '''
        Function which attempts to import the settings stored in gado.conf
        
        If there is no gado.conf (or it is empty) then the settings object
        defaults to None
        '''
    
        s = import_settings()
        if s:
            s['scanned_image'] = '%s.%s' % (s['temp_scanned_image'],
                    s['image_front_filetype'].strip('.'))
            s['webcam_image'] = '%s.%s' % (s['temp_webcam_image'],
                    s['image_back_filetype'].strip('.'))
        
        self.s = s
    
    def load(self):
        '''
        Loads up the settings from gado.conf and instantiates objects for:
            
            The Scanner
            The Robot
            The Webcam
        '''
        
        self.load_settings()
        
        self.scanner = Scanner(**self.s)
        self.robot = Robot(**self.s)
        self.camera = Webcam(**self.s)
    
    def mainloop(self):
        '''
        Repeating loop that constantly checks to see if the in-queue (the Gui) has any new
        messages for the system
        
        A Series of if/elses is then used to determine the appropriate action to take for
        each message received
        '''
    
        #Set database interface, the system-to-gui queue and the robot as local vars
        dbi = self.dbi
        q = self.q_out
        robot = self.robot
        
        #add_to_queue(q, messages.READY)
        
        #Loop until told to stop
        while True:
            expecting_return = False
            try:
                #Grab a message from the gui-to-system queue (if on exists)
                msg = fetch_from_queue(self.q_in)
                
                #Add an new artifact set to the local database
                if msg[0] == messages.ADD_ARTIFACT_SET_LIST:
                    i = dbi.add_artifact_set(**msg[1])
                
                #Grab the full lits of artifact sets and pass it back
                #using the system-to-gui queue
                elif msg[0] == messages.ARTIFACT_SET_LIST:
                    expecting_return = messages.ARTIFACT_SET_LIST
                    i = dbi.artifact_set_list()
                    add_to_queue(q, messages.ARTIFACT_SET_LIST, i)
                
                #Delete a specified artifact set
                elif msg[0] == messages.DELETE_ARTIFACT_SET_LIST:
                    dbi.delete_artifact_set(msg[1])
                
                #Grab the user's settings and either update the settings for
                #the robot, scanner and webcam; or reinstantiate those objects
                #with the new setttings
                elif msg[0] == messages.RELOAD_SETTINGS:
                    settings = import_settings()
                    self.s = settings
                    
                    self.robot.updateSettings(**settings)
                    
                    del self.camera
                    self.camera = Webcam(**settings)
                    
                    del self.scanner
                    self.scanner = Scanner(**settings)
                    
                    self._load_settings(**settings)
                
                #Restart the robot
                elif msg[0] == messages.RESET:
                    self.robot.reset()
                
                #Attempt to connect to the robot (via serial port)
                #Pass back to Gui whether or not it was sucessfull
                elif msg[0] == messages.ROBOT_CONNECT:
                    expecting_return = messages.ROBOT_CONNECT
                    success = self.connect()
                    self.logger.info('ROBOT_CONNECT: %s' % success)
                    add_to_queue(q, messages.ROBOT_CONNECT, robot.connected())
                
                #Delete the current scanner object (if it exists)
                #and instantiate a new one
                #
                #Pass back to Gui whether or not this was sucessfull
                elif msg[0] == messages.SCANNER_CONNECT:
                    expecting_return = messages.SCANNER_CONNECT
                    try: del self.scanner
                    except:
                        self.logger.exception("Exception while connecting to scanner")
                        pass
                    self.scanner = Scanner(**import_settings())
                    add_to_queue(q, messages.SCANNER_CONNECT, self.scanner.connected())
                
                elif msg[0] == messages.SCANNER_CONNECTED:
                    add_to_queue(q, messages.SCANNER_CONNECTED, self.scanner.connected())
                    
                #Scan an inmage using the scanner
                elif msg[0] == messages.SCANNER_PICTURE:
                    expecting_return = messages.SCANNER_PICTURE
                    self.scanner.scanImage(self.s['scanned_image'])
                    add_to_queue(q, messages.SCANNER_PICTURE, self.s['scanned_image'])

                #Set the passed in artifact set as the currently selected
                elif msg[0] == messages.SET_SELECTED_ARTIFACT_SET:
                    self.selected_set = msg[1]

                #Starts the robot's overall procedure for moving/scanning artifacts
                elif msg[0] == messages.START:
                    self.start()
                
                #Grabs a list of available webcams and returns them to the Gui thread
                elif msg[0] == messages.WEBCAM_LISTING:
                    self.logger.debug('WEBCAM_LISTING')
                    expecting_return = messages.WEBCAM_LISTING
                    
                    opts = self.camera.options()
                    self.logger.debug('WEBCAM_LISTING - %s' % opts)
                    add_to_queue(q, messages.WEBCAM_LISTING, opts)
                
                #Attempt to connect to the selected webcam
                elif msg[0] == messages.WEBCAM_CONNECT:
                    self.logger.debug('WEBCAM_CONNECT switch made it')
                    expecting_return = messages.WEBCAM_CONNECT
                    
                    #If the webcam object exists
                    if self.camera:
                        self.logger.info('Camera already exists')
                        #And it is connected
                        if self.camera.connected():
                            self.logger.info('Already connected to the webcam')
                            
                            #Relay that information back to the Gui thread
                            add_to_queue(q, messages.WEBCAM_CONNECT, self.camera.connected())
                            return
                        #Otherwise, disconnect
                        else: self.camera.disconnect()
                        
                    #Reinstantiate the webcam object with the user settings
                    self.camera = Webcam(**import_settings())
                    
                    #Connect to webcam and let the Gui thread know if it was sucessfull
                    self.logger.info('self.camera.connected() %s' % self.camera.connected())
                    add_to_queue(q, messages.WEBCAM_CONNECT, self.camera.connected())
                
                elif msg[0] == messages.WEBCAM_CONNECTED:
                    add_to_queue(q, messages.WEBCAM_CONNECTED, self.camera.connected())
                    
                #Take a picture using the currently connected webcam
                elif msg[0] == messages.WEBCAM_PICTURE:
                    expecting_return = messages.WEBCAM_PICTURE
                    
                    #Save the picture as the temp image name
                    self.camera.savePicture(self.s['webcam_image'])
                    
                    #Pass that name back to the Gui thread
                    add_to_queue(q, messages.WEBCAM_PICTURE, self.s['webcam_image'])
                    
                #Grab a list of artifact sets, with weights so we can figure out the most
                #recently used
                elif msg[0] == messages.WEIGHTED_ARTIFACT_SET_LIST:
                    expecting_return = messages.WEIGHTED_ARTIFACT_SET_LIST
                    li = self.dbi.weighted_artifact_set_list()
                    add_to_queue(q, messages.WEIGHTED_ARTIFACT_SET_LIST, arguments=li)
                
                #Kill the program!!!
                elif msg[0] == messages.MAIN_ABANDON_SHIP:
                    add_to_queue(q, messages.GUI_LISTENER_DIE)
                    add_to_queue(self.q_in, messages.MAIN_ABANDON_SHIP)
                    return
                
                elif msg[0] == messages.STOP or msg[0] == messages.LAST_ARTIFACT or msg[0] == messages.RESET:
                    # These commands are only relevant if the robot is already running.
                    pass
                
                #Pass the robot object to the Gui thread
                elif msg[0] == messages.GIVE_ME_A_ROBOT:
                    add_to_queue(q, messages.GIVE_ME_A_ROBOT, self.robot)
                else:
                    # add it back to the in queue, was somebody else waiting for that message?
                    add_to_queue(self.q_in, msg[0], (msg[1] if len(msg) > 1 else None))
            
            #Something went horribly wrong, if the Gui thread is expecting a response,
            #Tell it things went poorly
            except:
                self.logger.exception("EXCEPTION GENERATED")
                #raise
                if expecting_return:
                    add_to_queue(q, expecting_return)
    
    
    def _sanity_checks(self):
        '''
        Runs a series of checks on the connected peripherals and other components
        of the Gado system
        
        If any of these tests fail, then the Gui thread is notified as to what didn't work so
        the user can take appropriate action
        
        If all the tests pass, then the system is ready to proceed with the scanning process
        '''
        
        self.logger.debug('in sanity checks')
        
        #If the scanning process has started, and a user attempts to start it again
        #Tell the gui to display a message stating that
        if self.started:
            add_to_queue(self.q_out, messages.DISPLAY_ERROR,
                'The scanning process has already started')
            return False
        
        _a = 'a'
        self.started = id(_a)
        
        #User did not select an artifact set from the dropdown
        if not self.selected_set:
            self.logger.error('failed sanity check on selected_set')
            add_to_queue(self.q_out, messages.DISPLAY_ERROR,
                'Please select an artifact set from the dropdown.')
            self.started = False
            return False
        
        #Robot is not currently connected
        if not self.robot.connected():
            self.logger.error('failed sanity check on robot.connected()')
            
            #Try and connect
            self.connect()
            
            #If that failed, let the Gui know so it can tell the user
            if not self.robot.connected():
                self.logger.error("COMPLETELY FAILED ON robot.connected()")
                add_to_queue(self.q_out, messages.DISPLAY_ERROR,
                    'Unable to connect to the robot. Try pressing the reset button and then unplugging it and replugging it.')
                self.started = False
                return False
        
        #Otherwise, let the user know that the connection was successfull
        add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Connected to the Gado')
        
        #Reset the robot to its initial location
        self.robot.reset()
        
        #If the scanner is not currently connected
        if not self.scanner.connected():
            self.logger.error('failed sanity check on scanner.connected(), retrying')
            
            #Delete the scanner object (if any)
            try: del self.scanner
            except:
                self.logger.exception("Error while connecting to scanner")
                pass
            
            #Reinstantiate the object with the user settings
            self.scanner = Scanner(**import_settings())
            
            #If the scanner is still not connected to the system
            if not self.scanner.connected():
                self.logger.error('failed sanity check on scanner.connected()')
                
                #Let the Gui thread know that the scanner could not be found
                self.started = False
                add_to_queue(self.q_out, messages.DISPLAY_ERROR,
                    'Unable to connect to the scanner. Try unplugging it and replugging it. You may need to restart this application or run the setup wizard again.')
                return False
        
        #Let the Gui thread know that the scanner was found so it can alert the user
        add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Connected to the scanner')
        
        #Webcam is not currently connected
        if not self.camera.connected():
            
            #Attempt to connect to it
            self.camera.connect()
            
            #If that fails
            if not self.camera.connected():
                self.logger.error('failed sanity check on camera.connected()')
                
                #Let the Gui thread know that it is not connected so it can alert the user
                add_to_queue(self.q_out, messages.DISPLAY_ERROR,
                    'Unable to connect to the webcam. Try unplugging it and replugging it. You may need to restart this application or run the setup wizard again.')
                self.started = False
                return False
            
        #Let the Gui thread know that the webcam is connected
        add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Connected to the webcam')
        
        #Move the robot's actuator up to its starting position
        self.robot._moveActuator(self.robot.actuator_up_value)
        
        #Allow some time for the movement to happen
        time.sleep(2)
        
        #Something strange happened, let the Gui thread know
        if self.started != id(_a):
            add_to_queue(self.q_out, messages.DISPLAY_ERROR, 'An unknown error has occurred. Try restarting this application')
            self.started = False
            return False
        
        #Sanity checks all passed, let the Gui thread know that the system is ready to proceed
        add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Ready to begin scanning')
        
        return True
    
    def _checkMessages(self):
        '''
        Controls the gado loop
        
        Returns True if the process should continue
        Returns False if the process should after the current loop
        Resets and raises an error if things need to stop.
        
        '''
        if self.q_in.empty():
            return True
        msg = fetch_from_queue(self.q_in)
        
        #Stop the robot
        if msg[0] == messages.STOP:
            add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Robot stopped.')
            self.started = False
            self.robot.stop()
            raise Exception('STOP CALLED')
        
        #Reset the robot
        elif msg[0] == messages.RESET:
            self.robot.reset()
            add_to_queue(self.q_out, messages.SET_STATUS_TEXT, 'Robot reset')
            raise Exception('RESET CALLED')
        
        #This is the last artifact being scanned, stopped after it is finished
        elif msg[0] == messages.LAST_ARTIFACT:
            return False
        
        #Start the robot's procedure
        elif msg[0] == messages.START:
            add_to_queue(self.q_out, messages.DISPLAY_INFO, 'The robot is already running. If it is not, then please restart this application.')
        
        #Kill everything
        elif msg[0] == messages.SYSTEM_ABANDON_SHIP:
            self.robot.stop()
            add_to_queue(self.q_in, msg[0])
            raise Exception('Application Terminating')
        else:
            add_to_queue(self.q_out, msg[0], (msg[1] if len(msg) > 1 else None))
        return True
    
    def start(self):
        '''
        Starts the scanning process for the current in pile
        '''
        #Come back and make the sanity checks real
        if not self._sanity_checks():
            return False
        
        #The actual looping should be happening here, instead of in Robot.py
        #Robot.py should just run the loop once and all conditions/vars will be stored here

        self.logger.debug("checking for messages")
        self._checkMessages()
        self.logger.info('attempting to save picture')
        
        # Sometimes it gets left behind, get rid of it
        try:
            t_webcam_image = self.s['webcam_image']
        except:
            self.logger.exception("Exception while starting the robot")
            pass
        try:
            t_scanner_image = self.s['scanned_image']
        except:
            self.logger.exception("Exception while starting the robot")
            pass
        
        try: os.remove(t_webcam_image)
        except:
            self.logger.exception("Exception while starting the robot")
            pass
        
        #Take picture of back of artifact
        self.camera.savePicture(t_webcam_image)
        self._checkMessages()
        
        self.logger.info("attempting to check for barcode")
        
        #Check to see if we have reached the end of the input pile
        completed = check_for_barcode(t_webcam_image, '')
        
        #While we still have artifacts in the in pile that need to be digitized
        while not completed:
            # New Artifact!
            self.logger.info("attempting to add an artifact")
            completed = self._checkMessages() & completed
            
            #Create a new artifact within the currently selected set
            artifact_info = new_artifact(self.dbi, self.selected_set)
            
            #Set the paths for the front and back images
            front_fn = artifact_info['front_path']
            back_fn = artifact_info['back_path']
            
            self.logger.debug('renaming webcam image to %s' % back_fn)
            
            #Move the temp webcam image to it's permanent location
            move(t_webcam_image, back_fn)
            
            #Pass the webcam's captured image back to the Gui thread so that it can be displayed
            add_to_queue(self.q_out, messages.SET_WEBCAM_PICTURE, back_fn)
            
            self.logger.info("attempting to go pick up an object")
            completed = self._checkMessages() & completed
            
            #Pick up a single artifact from the in pile
            self.robot.pickUpObject()
            time.sleep(5)
            
            self.logger.info("attempting to move object to scanner")
            completed = self._checkMessages() & completed
            
            #Using the scanner, capture an image of that artifact
            self.robot.scanObject()
            self.robot._vacuumOn(False)
            
            completed = self._checkMessages() & completed
            
            # Sometimes it gets left behind :(
            try: os.remove(t_scanner_image)
            except:
                self.logger.exception("Couldn't remove image file - this is usually not a problem")
            
            #Do the actual scanning of the artifact
            self.scanner.scanImage(t_scanner_image)
            
            self.logger.debug('renaming scanned images to %s' % front_fn)
            
            #Move scanned image to its permament location
            move(t_scanner_image, front_fn)
            
            #Pass the scanned image back to the Gui thread so that it can be displayed
            add_to_queue(self.q_out, messages.SET_SCANNER_PICTURE, front_fn)
            
            completed = self._checkMessages() & completed
            
            #Rotate the robot's arm to over the out pile
            self.robot.moveToOut()
            
            #Take a picture of the back of the next artifact and check to make sure it's not
            #the end of the current in pile
            self.camera.savePicture(t_webcam_image)
            completed = check_for_barcode(t_webcam_image, '')
        
        #Finished
        self.started = False
        self.logger.debug("Done with robot loop")
    
    def connect(self):
        '''
        Connect to the Gado.
        
        If a port is specified in the settings, then try to connect to it
        Otherwise scan through ports attempting to connect to the Robot
        '''
        settings = import_settings()
        
        if 'gado_port' in settings:
            success = self.robot.connect(self.s.get('gado_port'))
            
            if success:
                return True
            
        return _connect(self.robot)
Example #5
0
 def load(self):
     self.load_settings()
     
     self.scanner = Scanner(**self.s)
     self.robot = Robot(**self.s)
     self.camera = Webcam(**self.s)