Пример #1
0
class Listener(QWidget):
    def __init__(self, core_file_name):
        super(Listener, self).__init__()
        self.core_file_name = core_file_name

        self.setup_ui()
        self.setup_timers()

        port = SERIAL_PORT
        self.serial = serial.Serial(port, BAUDE_RATE, timeout=0)
        self.incoming_data = []

        self.imu = IMU(PLATFORM_SPECIFIC_QUOTIENTS['stm'])
        self.stroke = Stroke()
        self.selector = Selector(self.core_file_name)

        self.acceleration_filter = AperiodicFilter(ACCELERATION_TIME_CONST)

        self.stroke.widget = self.display
        self.stroke.on_done = self.get_stroke

        self.previous_time = None

        self.data_buffer = ''

        self.init_selector()


    def setup_ui(self):
        self.resize(500, 500)
        self.out = QLabel(self)
        self.out.setMinimumHeight(100)
        font = QFont()
        font.setPixelSize(80)
        self.out.setFont(font)
        self.grid = QGridLayout(self)
        self.display = StrokeWidget()
        self.letter_selector = QComboBox()
        self.grid.addWidget(self.display, 0, 0, 1, 1)
        self.grid.addWidget(self.letter_selector, 1, 0, 1, 1)
        self.grid.addWidget(self.out, 2, 0, 1, 1)

    def setup_timers(self):
        self.serial_timer = QTimer()
        self.serial_timer.setInterval(SERIAL_INTERVAL)
        self.serial_timer.timeout.connect(self.get_data)
        self.serial_timer.start()

        self.process_timer = QTimer()
        self.process_timer.setInterval(PROCESS_INTERVAL)
        self.process_timer.timeout.connect(self.process)
        self.process_timer.start()

        self.display_timer = QTimer()
        self.display_timer.setInterval(DISPLAY_TIMEOUT)
        self.display_timer.setSingleShot(True)
        self.display_timer.timeout.connect(self.set_background)


    def init_selector(self):
        sel_lines = self.selector.letters_dict.keys()
        sel_lines.insert(0, 'new strokes')
        sel_lines.insert(0, 'free run')
        self.letter_selector.addItems(sel_lines)
        self.letter_selector.currentIndexChanged.connect(self.set_background)

    def set_background(self):
        letter = str(self.letter_selector.currentText())
        self.display.set_background(self.core_file_name, letter)

    def store_stroke(self, key, stroke, existing=True):
        file_name = '{key}{time}.txt'.format(key=key, time=int(time()))
        file_path = os.path.join(LEARNED_FOLDER, file_name)
        np.savetxt(file_path, stroke)
        if existing:
            self.display.set_background(self.core_file_name, key, color='g')
            self.display_timer.start()        

    def get_stroke(self, data):
        stroke = data['stroke']
        dimention = data['dimention']
        if dimention < MIN_DIMENTION:
            print 'too small'
            return

        letter = str(self.letter_selector.currentText())
        if letter == 'new strokes':
            self.store_stroke('_', stroke, existing=False)
            print 'recorded'

        try:
            letters = self.selector.check_stroke(stroke)
        except: #TODO: check unify_stroke
            return

        if letters:
            self.out.setText(self.out.text()+letters[0])

        if letter == 'free run' and letters:
            self.store_stroke(letters[0], stroke)
        elif letter in letters:
            self.store_stroke(letter, stroke)

    def process(self):
        local_data_storage = deepcopy(self.incoming_data)
        self.incoming_data = []

        for data in local_data_storage:
            if self.previous_time is None:
                self.previous_time = data[0]
                continue

            data[0], self.previous_time = data[0] - self.previous_time, data[0]

            if data[0] < MAX_DATA_TIMELAPSE:
                self.imu.calc(data)
                gyro = np.linalg.norm(np.array([data[7:]]))
                accel = self.imu.get_global_acceleration()

                accel = self.acceleration_filter.set_input(accel, data[0])

                accel_magnitude = np.linalg.norm(accel)

                if accel_magnitude > ACCELERATION_RESET:
                    self.execute_spell()

                Yr = self.imu.get_y_direction()

                self.stroke.set_data(Yr, gyro)

                self.stroke.process_size(data[0], accel)

        self.setVisible(not self.imu.in_calibration)

    def execute_spell(self):
        self.out.setText('')

    def get_data(self):
        try:
            self.data_buffer += self.serial.read(self.serial.inWaiting())
            if self.data_buffer == '':
                return
            data_pieces = self.data_buffer.split(BUFFER_DELIMITER)

            # Put incomplete piece back to the buffer
            self.data_buffer = data_pieces.pop(-1)

            # If there are no complete data pieces - return from function
            if not data_pieces:
                return

            # Else - get the last of the pieces and discard the rest
            line = data_pieces[-1]

            result = [float(d) for d in line.split()]
            if len(result) != 9:
                raise ValueError('Nine pieces of data should be provided.')
            new_line = [time()] + result
            self.incoming_data.append(new_line)
        except KeyboardInterrupt:
            raise
        except Exception as e:
            # Something went wrong... nobody cares.
            print e