From 035a14af9d10a9295398156ab4bec22651e76291 Mon Sep 17 00:00:00 2001 From: Antoine Lima Date: Wed, 2 Jan 2019 02:23:05 +0100 Subject: [PATCH] Goal detection --- babyfut.py | 17 +++-- core/input.py | 168 ++++++++++++++++++++++++++++++++++++------------- core/player.py | 4 +- ui/mainwin.py | 5 -- 4 files changed, 135 insertions(+), 59 deletions(-) diff --git a/babyfut.py b/babyfut.py index 049bba0..521b446 100644 --- a/babyfut.py +++ b/babyfut.py @@ -28,20 +28,18 @@ def getMainWin(): ON_RASP = os.uname()[1] == 'raspberrypi' IMG_PATH = getContent('img') -SIDE = None if __name__=='__main__': __package__ = 'Babyfut' from Babyfut.ui.mainwin import MainWin from Babyfut.modules import GameModule from Babyfut.core.player import Side - from Babyfut.core.input import GPIOThread + from Babyfut.core.input import Input from Babyfut.core.downloader import Downloader from Babyfut.core.database import Database from Babyfut.core.replay import Replay as ReplayThread try: - SIDE = Side.Left #logging.basicConfig(filename='babyfoot.log', level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG) @@ -56,9 +54,10 @@ if __name__=='__main__': threadReplay.start() myapp.dispatchMessage({'replayThread': threadReplay}, toType=GameModule) - threadGPIO = GPIOThread() - threadGPIO.rfidReceived.connect(myapp.rfidHandler) - threadGPIO.start() + input = Input() + input.rfidReceived.connect(lambda side: myapp.dispatchMessage({'rfid': rfid, 'source': side})) + input.goalDetected.connect(lambda side: myapp.dispatchMessage({'goal': True, 'source': side})) + input.start() threadDownloader = Downloader.instance() threadDownloader.start() @@ -66,18 +65,16 @@ if __name__=='__main__': myapp.show() app.exec_() - threadDownloader.stop() - threadGPIO.stop() if ReplayThread.isCamAvailable(): threadReplay.stop() threadReplay.join() - threadGPIO.join() + input.stop() + threadDownloader.stop() threadDownloader.join() finally: - GPIOThread.clean() Database.instance().close() for f in glob.glob(join(IMG_PATH, '*')): os.remove(f) diff --git a/core/input.py b/core/input.py index 70f993e..f39bc59 100644 --- a/core/input.py +++ b/core/input.py @@ -7,18 +7,34 @@ import logging import time from threading import Thread -import pyautogui # PyPi library from PyQt5.QtCore import QObject, pyqtSignal from Babyfut.babyfut import ON_RASP from Babyfut.core.player import Side +from Babyfut.core.settings import Settings if ON_RASP: import RPi.GPIO as GPIO from pirc522 import RFID # PyPi library + import pyautogui # PyPi library + +class Input(QObject): + ''' + Defines pins. Uses BCM pin identifiers + ''' + + _RFIDPins = { + 'pin_rst': 25, + 'pin_ce' : 8, + 'pin_irq': 24 + } + + _GoalPins = { + 'pin_trig': 4, + 'pin_echo': 16 + } -class GPIOThread(Thread, QObject): _keyButtonBindings = { 26: 'up', 22: 'left', @@ -28,36 +44,75 @@ class GPIOThread(Thread, QObject): 18: 'escape' } - rfidReceived = pyqtSignal(str) + rfidReceived = pyqtSignal(Side, str) + goalDetected = pyqtSignal(Side) def __init__(self): - Thread.__init__(self) QObject.__init__(self) - self.continueRunning = True - self.lastRFIDReception = 0 - + if ON_RASP: - self.rf_reader = RFID(pin_rst=25, pin_ce=8, pin_irq=24, pin_mode=GPIO.BCM) - GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) - - for pin in GPIOThread._keyButtonBindings.keys(): - print(pin) + for pin in Input._keyButtonBindings.keys(): GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) - GPIO.add_event_detect(pin, GPIO.RISING, callback=self.handleButtonPress) + GPIO.add_event_detect(pin, GPIO.RISING, callback=self._handleButtonPress) + + self.side = Side.Left if Settings['app.side']=='left' else Side.Right + print(self.side) + self.rfidThread = RFIDThread(self, **Input._RFIDPins) + self.goalThread = GoalThread(self, **Input._GoalPins) + + def start(self): + self.rfidThread.start() + self.goalThread.start() + + def stop(self): + self.rfidThread.stop(); self.rfidThread.join() + self.goalThread.stop(); self.goalThread.join() + + def _handleButtonPress(self, button_pin): + if button_pin not in Input._keyButtonBindings.keys(): + logging.warn('Unknown button pin: {}'.format(button_pin)) + else: + key = Input._keyButtonBindings[button_pin] + logging.debug('Sending {} as {}'.format(button_pin, key)) + pyautogui.press(key) + +class GPIOThread(Thread): + def __init__(self): + Thread.__init__(self) + self._running = True + + def running(self): + return self._running + + def start(self): + Thread.start(self) + + def stop(self): + self._running = False + + def clean(self): + GPIO.cleanup() + +class RFIDThread(GPIOThread): + def __init__(self, parent, **pins): + GPIOThread.__init__(self) + self.parent = parent + self.lastRFIDReception = 0 + self.rf_reader = RFID(**pins, pin_mode=GPIO.BCM) + print(self.rf_reader.pin_rst, self.rf_reader.pin_ce, self.rf_reader.pin_irq) def run(self): - if ON_RASP: - try: - while self.continueRunning: - self.rf_reader.wait_for_tag() - (error, tag_type) = self.rf_reader.request() - if not error: - self.handleRFID() - finally: - self.clean() - - def handleRFID(self): + try: + while self.running(): + self.rf_reader.wait_for_tag() + (error, tag_type) = self.rf_reader.request() + if not error: + self._handleRFID() + finally: + self.clean() + + def _handleRFID(self): (error, id) = self.rf_reader.anticoll() if not error: # Prevent RFID "spam" (one second removal delay) @@ -65,30 +120,59 @@ class GPIOThread(Thread, QObject): if self.lastRFIDReception!=0 and abs(self.lastRFIDReception-now)>1: self.lastRFIDReception = 0 receivedRFID = ':'.join([str(x) for x in id]) - self.rfidReceived.emit(receivedRFID) + self.input.emit(self.parent.side, receivedRFID) logging.debug('Received RFID: {}'.format(receivedRFID)) else: self.lastRFIDReception = now - def handleButtonPress(self, button_pin): - if button_pin not in GPIOThread._keyButtonBindings.keys(): - logging.warn('Unknown button pin: {}'.format(button_pin)) - else: - key = GPIOThread._keyButtonBindings[button_pin] - logging.debug('Sending {} as {}'.format(button_pin, key)) - pyautogui.press(key) - def stop(self): - self.continueRunning = False - # Falsely trigger the rfid reader to stop it waiting - if ON_RASP: - self.rf_reader.irq.set() + GPIOThread.stop(self) + + # Falsely trigger the rfid reader to stop it from waiting + self.rf_reader.irq.set() def clean(self): - GPIOThread.clean() + GPIOThread.clean(self) self.rf_reader.cleanup() - @staticmethod - def clean(): - if ON_RASP: - GPIO.cleanup() +class GoalThread(GPIOThread): + def __init__(self, parent, pin_trig, pin_echo): + GPIOThread.__init__(self) + self.parent = parent + self.pin_trig = pin_trig + self.pin_echo = pin_echo + + GPIO.setmode(GPIO.BCM) + GPIO.setup (self.pin_echo, GPIO.IN) + GPIO.setup (self.pin_trig, GPIO.OUT) + GPIO.output(self.pin_trig, GPIO.LOW) + print(self.pin_trig, pin_echo) + + def run(self): + try: + # Waiting for sensor to settle + time.sleep(2) + + while self.running(): + # Trigger a scan + GPIO.output(self.pin_trig, GPIO.HIGH) + time.sleep(0.00001) + GPIO.output(self.pin_trig, GPIO.LOW) + + # Read the echo + while self.running() and GPIO.input(self.pin_echo)==0: + pulse_start_time = time.time() + while self.running() and GPIO.input(self.pin_echo)==1: + pulse_end_time = time.time() + + if self.running(): + pulse_duration = pulse_end_time - pulse_start_time + distance = round(pulse_duration * 17150, 2) + self._handle_dist(distance) + finally: + self.clean() + + def _handle_dist(self, dist): + logging.debug('Distance: {}cm'.format(dist)) + if dist<3: + self.parent.goalDetected.emit(self.parent.side) diff --git a/core/player.py b/core/player.py index fd0f82d..0ce7657 100644 --- a/core/player.py +++ b/core/player.py @@ -63,8 +63,8 @@ class Player(QObject): _placeholder_pic_path = ':ui/img/placeholder_head.jpg' - def __init__(self, id, rfid, fname, lname, pic_path, stats): def __init__(self, id, rfid, fname, lname, pic_path, stats=None): + QObject.__init__(self) self.id = id self.rfid = rfid self.fname = fname @@ -94,7 +94,6 @@ class Player(QObject): return player - def displayImg(self, container_widget): @staticmethod def _loadFromDB(rfid): db = Database.instance() @@ -132,6 +131,7 @@ class Player(QObject): return Player._loadFromDB(rfid) + def displayImg(self, container_widget): self.pic_container = container_widget if self.pic_path.startswith('http'): diff --git a/ui/mainwin.py b/ui/mainwin.py index b63c23e..11d0d74 100644 --- a/ui/mainwin.py +++ b/ui/mainwin.py @@ -80,11 +80,6 @@ class MainWin(QtWidgets.QMainWindow): for modIdx in modulesIdx: self.modules[modIdx].other(**msg) - - @pyqtSlot(str) - def rfidHandler(self, rfid): - side = Side.Left if Settings['app.side']=='left' else Side.Right - self.dispatchMessage({'rfid': rfid, 'source': side}) def _loadSettings(self): if Settings['ui.fullscreen']: -- GitLab