This commit is contained in:
matteo porta 2022-07-20 19:29:11 +02:00
commit ef0b6cda54
15 changed files with 167 additions and 121 deletions

View File

@ -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

View File

@ -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'
}

View File

@ -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

View File

@ -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

4
designer.sh Executable file
View File

@ -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"

View File

@ -1,2 +0,0 @@
#!/bin/bash -e
./simulate.sh --diagnostic $*

View File

@ -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 \

View File

@ -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()

View File

@ -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)
)

View File

@ -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:

View File

@ -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:

29
src/test/multicomp.py Normal file
View File

@ -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()

View File

@ -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)

View File

@ -1,57 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Admin permission</class>
<widget class="QWidget" name="Admin permission">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>422</width>
<height>139</height>
</rect>
</property>
<property name="windowTitle">
<string>Admin permission</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="6" column="1">
<widget class="QPushButton" name="cancel_b">
<property name="text">
<string>Annulla</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="continue_b">
<property name="text">
<string>Continua</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLineEdit" name="password_le">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
<property name="placeholderText">
<string>password</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="info_l">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
</layout>
<class>Admin permission</class>
<widget class="QWidget" name="Admin permission">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>422</width>
<height>139</height>
</rect>
</property>
<property name="windowTitle">
<string>Admin permission</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="6" column="1">
<widget class="QPushButton" name="cancel_b">
<property name="text">
<string>Annulla</string>
</property>
</widget>
<tabstops>
<tabstop>password_le</tabstop>
<tabstop>continue_b</tabstop>
<tabstop>cancel_b</tabstop>
</tabstops>
<resources/>
<connections/>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="continue_b">
<property name="text">
<string>Continua</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLineEdit" name="password_le">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
<property name="placeholderText">
<string>password</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="info_l">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>password_le</tabstop>
<tabstop>continue_b</tabstop>
<tabstop>cancel_b</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -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