diff --git a/config/machine_settings/defaults.ini b/config/machine_settings/defaults.ini index 38347cc..c5ca5f5 100644 --- a/config/machine_settings/defaults.ini +++ b/config/machine_settings/defaults.ini @@ -9,9 +9,9 @@ exposure_time: 10000 ; vertical_crop_resolution: 2048 ; rotate_90_clockwise times: 0 ; auto_white_balance: off -; balance_red: 1.0 -; balance_green: 1.0 -; balance_blue: 1.0 +balance_red: 1.66 +balance_green: 1.0 +balance_blue: 1.12 [vision_saver] time_format: %Y-%m-%d_%H-%M-%S @@ -43,5 +43,7 @@ port: COM1 baudrate: 9600 [vision] -detection_threshold: 0.3 +detection_threshold: 0.5 +neural_network: hs3-20000 + ; recipes_path: ./config/vision_test_recipes diff --git a/config/vision/labels/labels.pbtxt b/config/vision/labels/labels.pbtxt index 66912e7..5cc99f0 100644 --- a/config/vision/labels/labels.pbtxt +++ b/config/vision/labels/labels.pbtxt @@ -1,15 +1,10 @@ item { id: 1 name: 'hs-ok' - color: '0x00ff00' + color: '0x000000' } item { id: 2 name: 'hs-ko' color: '0xff0000' } -item { - id: 3 - name: 'hs-empty' - color: '0x0000ff' -} diff --git a/config/vision/recipes/1.ini b/config/vision/recipes/1.ini index bee1461..a68160e 100644 --- a/config/vision/recipes/1.ini +++ b/config/vision/recipes/1.ini @@ -1,8 +1,8 @@ # LIEBHER RUBBER FLANGE [general] -name: RICETTA 1 -instruction: APPORRE I SEGNI CON IL PENNARELLO COME INDICATO IN FIGURA +name: TERMORESTRINGENTE +instruction: CONTROLLARE PRESENZA TERMORESTRINGENTE # POINTS FORMAT: # point_name: point_center point_size fill_color border_color border_thickness shape @@ -20,15 +20,9 @@ instruction: APPORRE I SEGNI CON IL PENNARELLO COME INDICATO IN FIGURA # name: X,Y S 0xAARRGGBB 0xAARRGGBB T TEXT [markers] -cross: 1100,1100 100,100 0x000000ff 0xff0000ff 25 cross -center: 1100,1100 2050,2050 0x0000ff00 0xff0000ff 50 ellipse [zones] -p1: 610,550 200 hs-ok # TOP LEFT WHITE POINT -p2: 1790,1290 200 hs-ok # RIGHT SIDE WHITE POINT -p3: 350,1190 200 hs-ok # LEFT SIDE BLUE POINT +p1: 800,850 300,100 hs-ok # HEATSINK PRESENT [labels] -p1: 510,825 100 0xffffffff 0xff000000 10 BIANCO -p2: 1690,1565 100 0xffffffff 0xff000000 10 BIANCO -p3: 250,1465 100 0xff0000ff 0xff000000 10 BLU +p1: 500,600 120 0xffffffff 0xff000000 4 TERMORESTRINGENTE diff --git a/config/vision/recipes/2.ini b/config/vision/recipes/2.ini deleted file mode 100644 index 31e321a..0000000 --- a/config/vision/recipes/2.ini +++ /dev/null @@ -1,34 +0,0 @@ -# LIEBHER RUBBER FLANGE - -[general] -name: RICETTA 2 -instruction: APPORRE I SEGNI CON IL PENNARELLO COME INDICATO IN FIGURA - -# POINTS FORMAT: -# point_name: point_center point_size fill_color border_color border_thickness shape -# EXAMPLE: -# name: X,Y W,H 0xAARRGGBB 0xAARRGGBB T SHAPE CLASS -# ZONES FORMAT: -# region_name: region_center region_margin class -# margin can be a box (XM*2,YM*2) or a radius (R) -# EXAMPLES: -# name: X,Y XM,YM T SHAPE CLASS -# name: X,Y R T SHAPE CLASS -# LABELS FORMAT: -# label_name: label_start_location font_size fill_color border_color border_thickness text -# EXAMPLE: -# name: X,Y S 0xAARRGGBB 0xAARRGGBB T TEXT - -[markers] -cross: 1100,1100 100,100 0x000000ff 0xff0000ff 25 cross -center: 1100,1100 2050,2050 0x0000ff00 0xff0000ff 50 ellipse - -[zones] -p1: 610,550 200 hs-ok # TOP LEFT WHITE POINT -p2: 1790,1290 200 hs-ok # RIGHT SIDE WHITE POINT -p3: 350,1190 200 hs-ok # LEFT SIDE BLUE POINT - -[labels] -p1: 510,825 100 0xffffffff 0xff000000 10 BIANCO -p2: 1690,1565 100 0xffffffff 0xff000000 10 BIANCO -p3: 250,1465 100 0xff0000ff 0xff000000 10 BLU diff --git a/designer.sh b/designer.sh new file mode 100755 index 0000000..cdefbd8 --- /dev/null +++ b/designer.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cd "$(dirname "$0")" +source "./venv/bin/activate" || source "./venv/Scripts/activate" || : +"$(python3 -c "import sys; print(sys.path[-1])")/qt5_applications/Qt/bin/designer" diff --git a/diagnostic.sh b/diagnostic.sh deleted file mode 100755 index eb19971..0000000 --- a/diagnostic.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -e -./simulate.sh --diagnostic $* diff --git a/simulate.sh b/simulate.sh index e9be8f9..3406f97 100755 --- a/simulate.sh +++ b/simulate.sh @@ -13,12 +13,17 @@ export QT_NO_INFO_OUTPUT=1 export QT_NO_WARNING_OUTPUT=0 # export QT_QPA_PLATFORM=${XDG_SESSION_TYPE} python -B -u "./src/main.py" \ +--auto-accept-test-admin-permission \ --auto-login-admin \ --auto-select \ +--debugger-workaround \ --no-edgetpu \ --no-gpu \ --panel \ +--sim-camera \ +--sim-modbus \ --sim-os-label-printer \ +--sim-serial \ --style windows \ $* 2> >(sed $'s/.*/\e[31m&\e[m/' >&2) # & # --about \ @@ -34,9 +39,6 @@ $* 2> >(sed $'s/.*/\e[31m&\e[m/' >&2) # & # --no-tflite \ # --recipes-management \ # --sim-archiver \ -# --sim-camera \ -# --sim-modbus \ -# --sim-serial \ # --sim-vision \ # --steps-management \ # --users-management \ diff --git a/src/components/galaxy_camera.py b/src/components/galaxy_camera.py index 319d110..46c38fe 100644 --- a/src/components/galaxy_camera.py +++ b/src/components/galaxy_camera.py @@ -122,6 +122,7 @@ class GalaxyCamera(Component): img_path = next(self.sim_imgs) self.log.debug(f"loading image {img_path}") frame = cv2.cvtColor(cv2.imread(str(img_path)), cv2.COLOR_BGR2RGB) + QThread.msleep(1000) else: self.camera.TriggerSoftware.send_command() frame = self.camera.data_stream[0].get_image() diff --git a/src/components/multicomp_730424.py b/src/components/multicomp_730424.py new file mode 100644 index 0000000..80851b9 --- /dev/null +++ b/src/components/multicomp_730424.py @@ -0,0 +1,33 @@ +import sys + +if "--sim-multimeter" in sys.argv: + from components.dummies.serial import serial +else: + import serial + +from PyQt5.QtWidgets import QMessageBox + +from .component import Component + + +class SerialMultimeter(Component): + def __init__(self, config=None, name=None): + super().__init__(config=config, name=name, threaded=False) + + def write(self, command): + try: + conn = serial.Serial( + self.address, + baudrate=self.baudrate, + stopbits=self.stopbits, + parity=self.parity, + bytesize=self.bytesize, + ) + conn.write(bytes(command, encoding="ascii")) + conn.close() + except serial.serialutil.SerialException as e: + QMessageBox.critical( + None, + "Errore Connessione Multimetro", + "Non e stato possibile connettersi al multimetro digitale.\n Verificare che lo strumento sia acceso e collegato\nErrore: " + str(e) + ) diff --git a/src/components/vision.py b/src/components/vision.py index 20823e8..5290881 100644 --- a/src/components/vision.py +++ b/src/components/vision.py @@ -11,6 +11,7 @@ from PyQt5.QtCore import (QFileSystemWatcher, QLineF, QMutex, QPointF, QRectF, Qt, QThread, pyqtSignal) from PyQt5.QtGui import (QBrush, QColor, QFont, QImage, QPainter, QPainterPath, QPen, QPixmap) +from PyQt5.QtWidgets import QApplication from .component import Component from .consumer import Consumer @@ -70,6 +71,10 @@ class Vision(Component): self.vision_consumer.moveToThread(self.vision_consumer_thread) self.vision_consumer_thread.started.connect(self.vision_consumer.start) self.vision_consumer_thread.start() + if "--debugger-workaround" in sys.argv: + QApplication.processEvents() + QThread.msleep(1000) + QApplication.processEvents() self.vision_consumer.wait_ready() # RENDER THREAD self.render_consumer = Consumer(work=self.render_consumer_work, work_fifo=True, drop_fifo=True, work_maxlen=1, name="render_consumer", paused=False) @@ -78,6 +83,10 @@ class Vision(Component): self.render_consumer.moveToThread(self.render_consumer_thread) self.render_consumer_thread.started.connect(self.render_consumer.start) self.render_consumer_thread.start() + if "--debugger-workaround" in sys.argv: + QApplication.processEvents() + QThread.msleep(1000) + QApplication.processEvents() self.render_consumer.wait_ready() # CONNECT CONSUMERS self.vision_consumer.out.connect(self.process_vision_consumed) @@ -275,6 +284,8 @@ class Vision(Component): "none", ]: model_name = sorted([d for d in os.listdir(self.models_dir) if os.path.isdir(self.models_dir / d)], reverse=True)[0] + else: + model_name = model self.log.info(f"loading neural network: {model_name!r}") self.loading_model_signal.emit({"status": "loading"}) self.lock.lock() @@ -433,6 +444,7 @@ class Vision(Component): min_distance = sys.maxsize closest_zone = None for zone_name, zone in self.zones.items(): + distance = self.get_distance(detection["center"], zone["center"]) if zone["shape"] == "rect": if self.zone_detection_filter_mode == "center_inside": outside_zone = any([ @@ -458,13 +470,14 @@ class Vision(Component): else: raise NotImplementedError(f"invalid zone_detection_filter_mode: {self.zone_detection_filter_mode!r}") elif zone["shape"] == "ellipse": # it's a circle - distance = self.get_distance(detection["center"], zone["center"]) if self.zone_detection_filter_mode == "center_inside": outside_zone = distance > zone["size"][0] / 2 elif self.zone_detection_filter_mode == "box_inside": outside_zone = distance + max(detection["size"]) / 2 > zone["size"][0] / 2 elif self.zone_detection_filter_mode == "box_touches": outside_zone = distance - max(detection["size"]) / 2 > zone["size"][0] / 2 + else: + raise NotImplementedError(f"invalid zone_detection_filter_mode: {self.zone_detection_filter_mode!r}") else: raise NotImplementedError(f"invalid zone shape: {zone['shape']!r}") if not outside_zone and distance < min_distance: diff --git a/src/main.py b/src/main.py index 4c4d31f..9609961 100644 --- a/src/main.py +++ b/src/main.py @@ -101,6 +101,10 @@ try: component = self.components[component_name] thread.started.connect(component.start) thread.start() + if "--debugger-workaround" in sys.argv: + QApplication.processEvents() + QThread.msleep(1000) + QApplication.processEvents() if component_name == "vision": component.wait_ready(timeout=60) else: diff --git a/src/test/multicomp.py b/src/test/multicomp.py new file mode 100644 index 0000000..c06d821 --- /dev/null +++ b/src/test/multicomp.py @@ -0,0 +1,29 @@ +import time + +import serial + +conn = serial.Serial( + "/dev/ttyUSB0", + baudrate=115200, + stopbits=serial.STOPBITS_ONE, + parity=serial.PARITY_NONE, + bytesize=serial.EIGHTBITS, + timeout=1 +) + +cmd_list = (("*IDN?\n", True), # QUERY ID + ("CONF:RES 500\n", False), # SET RESISTANCE MEASURE, 500 Ohm range + ("MEAS?\n", True), # GET MEASURE + ("MEAS?\n", True), # GET MEASURE + ("MEAS?\n", True)) # GET MEASURE + +for cmditem in cmd_list: + cmd, expect_response = cmditem + conn.write(bytes(cmd, encoding="ascii")) + if expect_response: + response = conn.readline() + print(f"{cmd} RESPONSE: " + response.decode("ascii")) + else: + print(f"{cmd}") + time.sleep(1) +conn.close() diff --git a/src/ui/test_admin_permission/test_admin_permission.py b/src/ui/test_admin_permission/test_admin_permission.py index ccff315..ab8ad6e 100644 --- a/src/ui/test_admin_permission/test_admin_permission.py +++ b/src/ui/test_admin_permission/test_admin_permission.py @@ -20,7 +20,7 @@ class Test_Admin_Permission(Widget): self.continue_b.clicked.connect(self.verify) self.cancel_b.clicked.connect(self.cancel) # TESTING - if "--test" in sys.argv: + if "--auto-accept-test-admin-permission" in sys.argv or "--test" in sys.argv: self.password_le.setText("123123") self.test_timer = QTimer() self.test_timer.setSingleShot(True) diff --git a/src/ui/test_admin_permission/test_admin_permission.ui b/src/ui/test_admin_permission/test_admin_permission.ui index 1d4d08b..5bcb7ed 100644 --- a/src/ui/test_admin_permission/test_admin_permission.ui +++ b/src/ui/test_admin_permission/test_admin_permission.ui @@ -1,57 +1,60 @@ - Admin permission - - - - 0 - 0 - 422 - 139 - - - - Admin permission - - - - - - Annulla - - - - - - - Continua - - - - - - - QLineEdit::Password - - - password - - - - - - - - - - - - + Admin permission + + + + 0 + 0 + 422 + 139 + + + + Admin permission + + + + + + Annulla + - - password_le - continue_b - cancel_b - - - + + + + + Continua + + + true + + + + + + + QLineEdit::Password + + + password + + + + + + + - + + + + + + + password_le + continue_b + cancel_b + + + diff --git a/src/ui/test_test/test_test.py b/src/ui/test_test/test_test.py index 10912c5..8a6d482 100644 --- a/src/ui/test_test/test_test.py +++ b/src/ui/test_test/test_test.py @@ -86,10 +86,12 @@ class Test_Test(Widget): data = self.last if self.last is not None else {} else: data = data[-data_usable.index(True) - 1] - if not override: - result_ok = data.get("results", {}).get("ok", None) - else: + if fail: + result_ok = False + elif override: result_ok = True + else: + result_ok = data.get("results", {}).get("ok", None) self.last = { **data, "overridden": override, @@ -100,11 +102,10 @@ class Test_Test(Widget): self.ok_counter = 0 elif override: self.ok_counter = self.ok_counter_limit + elif result_ok is True: + self.ok_counter += 1 else: - if result_ok is True: - self.ok_counter += 1 - else: - self.ok_counter = 0 + self.ok_counter = 0 # check if completed if fail: self.stop() @@ -166,6 +167,7 @@ class Test_Test(Widget): d.setCentralWidget(Test_Admin_Permission(info)) d.setModal(True) d.show() + d.centralWidget.password_le.setFocus() r = d.exec() if r == d.Accepted: self.admin_challenged = True