hikrobot dual smart cam test alpha

This commit is contained in:
gg 2025-01-24 16:51:58 +01:00
parent 10c9284d00
commit b52897fc33
11 changed files with 97 additions and 50 deletions

View File

@ -48,7 +48,6 @@ balance_blue: 1.5
time_format: %Y-%m-%d_%H-%M-%S time_format: %Y-%m-%d_%H-%M-%S
path: ./data/images path: ./data/images
minimum_disk_free_space_gb: 20 minimum_disk_free_space_gb: 20
resize_resolution: 612x512
[archive_synchronizer] [archive_synchronizer]
portal_address: https://r5portal.it/ portal_address: https://r5portal.it/

View File

@ -5,7 +5,7 @@ image_for_warning= st-ten-1
[hardware_config] [hardware_config]
archive_synchronizer: absent archive_synchronizer: present
galaxy_camera: absent galaxy_camera: absent
uvc_camera: absent uvc_camera: absent
hikrobot_sc: present hikrobot_sc: present
@ -20,6 +20,11 @@ fixture_id: absent
digital_io: absent digital_io: absent
external_flush_blow: absent external_flush_blow: absent
[archive_synchronizer]
portal_address: https://dev.r5portal.it/
poll_time: 10
hold_time: 10
[tecna_t3] [tecna_t3]
port: COM4 port: COM4
model: t3p model: t3p

View File

@ -28,9 +28,9 @@ rotations=2,1
[markers] [markers]
[zones] [zones]
p1: 620,630 600,600 ok SX: 620,630 600,600 ok
p2: 1420,630 600,600 ok DX: 1420,630 600,600 ok
[labels] [labels]
p1: 340,200 120 0xffffffff 0xff000000 4 O-RING 1 SX: 160,230 100 0xffffffff 0xff000000 4 GUARNIZIONE SX
p2: 1170,200 120 0xffffffff 0xff000000 4 O-RING 2 DX: 1100,230 100 0xffffffff 0xff000000 4 GUARNIZIONE DX

View File

@ -78,7 +78,7 @@ class ArchiveSynchronizer(Component):
save_ok = self.remote_archive(record) is True save_ok = self.remote_archive(record) is True
e = time.time() e = time.time()
else: else:
save_ok=True save_ok = True
if record.uploaded is not True: if record.uploaded is not True:
record.uploaded = self.remote_store(record) is True record.uploaded = self.remote_store(record) is True
else: else:
@ -87,9 +87,10 @@ class ArchiveSynchronizer(Component):
if save_ok: if save_ok:
record.archived |= (1 << bit_pos) record.archived |= (1 << bit_pos)
self.log.info(f"({self.name}) id {record.id}: archived remotely") # self.log.info(f"({self.name}) id {record.id}: archived remotely")
else: else:
self.log.info(f"({self.name}) id {record.id}: failed to archive remotely") pass
# self.log.info(f"({self.name}) id {record.id}: failed to archive remotely")
self.main_window.run_request.emit(record.save, [], {}) self.main_window.run_request.emit(record.save, [], {})
if self.hold_time > 0: if self.hold_time > 0:
@ -118,9 +119,10 @@ class ArchiveSynchronizer(Component):
else: else:
self.parse_response_and_execute(response) self.parse_response_and_execute(response)
except AssertionError as e: except AssertionError as e:
self.log.warning( if response is not None:
f"Status: {self.machine_status}: failed to update machine status: {str(e)}: {response.status_code if response else 'no response'}: {response.content if response else 'no response'}" self.log.warning(f"Status: {self.machine_status}: failed to update machine status: {str(e)}: {response.status_code} : {response.content}")
) else:
self.log.warning(f"Status: no response")
return False return False
except (requests.ConnectionError, requests.Timeout) as e: except (requests.ConnectionError, requests.Timeout) as e:
self.log.warning( self.log.warning(
@ -129,7 +131,7 @@ class ArchiveSynchronizer(Component):
return False return False
except Exception: except Exception:
self.log.error( self.log.error(
f"Status: {self.machine_status}: failed to update machine status:\n{traceback.format_exc()}:\n{response.status_code if response else 'no response'}: {response.content if response else 'no response'}" f"Status: {self.machine_status}: failed to update machine status:\n{traceback.format_exc()}:\n{response.status_code}: {response.content}"
) )
return False return False
@ -255,7 +257,7 @@ class ArchiveSynchronizer(Component):
self.gcs_bucket = None self.gcs_bucket = None
if self.gcs_bucket is None: if self.gcs_bucket is None:
return False return False
for path in record.test_data["vision"]["0"]["files"]: for path in record.test_data["vision"]["files"]:
dt = record.time dt = record.time
# path_in = f"{self.images_path}/{dt.strftime('%Y')}/{dt.strftime('%m')}/{os.path.basename(path)}" # path_in = f"{self.images_path}/{dt.strftime('%Y')}/{dt.strftime('%m')}/{os.path.basename(path)}"
path_in = path path_in = path

View File

@ -3,6 +3,7 @@ import traceback
import types import types
from lib.helpers import timing from lib.helpers import timing
from PyQt5.QtWidgets import QDialog, QMessageBox
from PyQt5.QtCore import (QMutex, QObject, QSemaphore, Qt, QThread, QTimer, from PyQt5.QtCore import (QMutex, QObject, QSemaphore, Qt, QThread, QTimer,
pyqtSignal) pyqtSignal)
@ -62,6 +63,7 @@ class Component(QObject):
Component.reconfigurators.remove(self) Component.reconfigurators.remove(self)
Component.reconfigurators_lock.unlock() Component.reconfigurators_lock.unlock()
return ret return ret
QMessageBox.critical(None, "ERRORE", f"ERRORE COMPONENTE {self.name}")
raise RuntimeError(f"retried to run {f} and reconfigure {self} with no success for {t_limit} times. giving up.") raise RuntimeError(f"retried to run {f} and reconfigure {self} with no success for {t_limit} times. giving up.")
return wrapper return wrapper

View File

@ -13,7 +13,7 @@ from .hikrobot_dll import *
class HikrobotSmartCamera(Component): class HikrobotSmartCamera(Component):
def __init__(self, config=None, name=None, period=1, lazy=True, paused=False, threaded=True): def __init__(self, config=None, name=None, period=0.5, lazy=True, paused=False, threaded=True):
super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded) super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded)
self.lock = QMutex() self.lock = QMutex()
self.simulate = "--sim-camera" in sys.argv self.simulate = "--sim-camera" in sys.argv
@ -102,3 +102,9 @@ class HikrobotSmartCamera(Component):
concat_results.append(not res) concat_results.append(not res)
super()._get([concat_frame,concat_results]) super()._get([concat_frame,concat_results])
def resume(self):
for cam_idx in range(self.num_cameras):
cam = self.cam_list[cam_idx]
nRet = mv_lib.MV_VS_SetCommandValue(cam["handle"], b"AcquisitionStart")
frame_res = MV_VS_GetFrame(cam["handle"])
super().resume()

View File

@ -1,3 +1,4 @@
import copy
import logging import logging
import os import os
import sys import sys
@ -537,30 +538,48 @@ class Vision(Component):
return parsed_detections return parsed_detections
def read_smart_camera_results(self, detections): def read_smart_camera_results(self, results):
dummy_detection = {
"box": [0, 0, 0, 0],
"center": [0, 0],
"class": {},
"score": 1,
"size": [0, 0],
}
if self.zones is None or not len(self.zones): if self.zones is None or not len(self.zones):
return None return None
results = dict.fromkeys(self.zones) results_out = dict.fromkeys(self.zones)
idx=0 idx=0
checked = {} checked = {}
for zone_name, detection in results.items(): detections_out=[]
for zone_name, detection in results_out.items():
res_det=copy.deepcopy(dummy_detection)
if results[idx]:
res_det["class"] = {"id": 1, "name": "OK", "color": "#00ff00"}
else:
res_det["class"] = {"id": 2, "name": "KO", "color": "#ff0000"}
checked[zone_name] = { checked[zone_name] = {
"ok": detections[idx], "ok": results[idx],
"expected": {"name": "OK", "expected": {"id": 1, "name": "OK", "color": "#00ff00"},
"color": "rgb(0,255,0)"}, "detection": res_det
} }
idx+=1 detection_out=copy.deepcopy(dummy_detection)
detection_out["class"]={"id":1,"name":"OK","color":"rgb(0,255,0)"} if results[idx] else {"id":1,"name":"KO","color":"rgb(255,0,0)"}
detections_out.append(detection_out)
idx += 1
global vision_override global vision_override
if vision_override is None: if vision_override is None:
ok = all(map(lambda detection: detection["ok"] is True, checked.values())) ok = all(map(lambda detection_l: detection_l["ok"] is True, checked.values()))
else: else:
ok = vision_override ok = vision_override
return {
results={
"ok": ok, "ok": ok,
"results": checked, "results": checked,
} }
return results,detections_out
@ -887,8 +906,7 @@ class Vision(Component):
detections = self.check_features(consumable["frame"]) detections = self.check_features(consumable["frame"])
results = self.process_detections(detections) results = self.process_detections(detections)
elif self.vision_config["type"]=="smart_camera": elif self.vision_config["type"]=="smart_camera":
results = self.read_smart_camera_results(consumable["detections"]) results,detections = self.read_smart_camera_results(consumable["detections"])
detections = []
return {"detections": detections, "results": results} return {"detections": detections, "results": results}

View File

@ -622,15 +622,14 @@ class Test(Widget):
self.data[leak]["results"] = results self.data[leak]["results"] = results
if "vision" in self.data: if "vision" in self.data:
vision_test_1 = self.data.get("vision", {}).get("0", {}) vision = self.data.get("vision", {})
out_paths = self.components["vision_saver"].save( out_paths = self.components["vision_saver"].save(
save_time=vision_test_1.get("time", None), save_time=vision.get("time", None),
frame=vision_test_1.get("frame", None), frame=vision.get("frame", None),
# vision=vision_test_1.get("detections", None), # vision=vision_test_1.get("detections", None),
) )
self.data.get("vision", {}).get("0", {})["files"] = out_paths vision["files"] = out_paths
self.log.info(f"cycle vision saved locally: {out_paths!r}") self.log.info(f"cycle vision saved locally: {out_paths!r}")
for vision in self.data.get("vision", {}).values():
vision.pop("frame", None) vision.pop("frame", None)
vision.pop("render", None) vision.pop("render", None)
vision.pop("detections", None) vision.pop("detections", None)
@ -691,7 +690,15 @@ class Test(Widget):
psetminp2_a = leak_test_2_step_spec.get("settling_pressure_min_percent", 0) * (100 + leak_test_2_step_spec.get("test_pressure_qneg", 0) / 100) psetminp2_a = leak_test_2_step_spec.get("settling_pressure_min_percent", 0) * (100 + leak_test_2_step_spec.get("test_pressure_qneg", 0) / 100)
psetmaxp2_a = leak_test_2_step_spec.get("settling_pressure_max_percent", 0) * (100 + leak_test_2_step_spec.get("test_pressure_qpos", 0) / 100) psetmaxp2_a = leak_test_2_step_spec.get("settling_pressure_max_percent", 0) * (100 + leak_test_2_step_spec.get("test_pressure_qpos", 0) / 100)
if self.tester_component is not None: if self.tester_component is not None:
leak_test_1_results["Running test: pressure at the end of measure"] = leak_test_1_results["Running test: pressure at the end of settling"] + leak_test_1_results["Running test: measured leak"] if self.recipe.spec["leak_1"]:
leak_test_1_results["Running test: pressure at the end of measure"] = (
leak_test_1_results["Running test: pressure at the end of settling"]
+ leak_test_1_results["Running test: measured leak"])
if self.recipe.spec["leak_1"]:
leak_test_2_results["Running test: pressure at the end of measure"] = (
leak_test_2_results["Running test: pressure at the end of settling"]
+ leak_test_2_results["Running test: measured leak"])
printer_fields = self.print_step.spec printer_fields = self.print_step.spec
context = { context = {
# RECIPE DATA # RECIPE DATA
@ -781,7 +788,8 @@ class Test(Widget):
else: else:
compiled_label = self.components["label_printer"].print_label(label, context=context) compiled_label = self.components["label_printer"].print_label(label, context=context)
self.log.info(f"Main label printed: {context!r}") self.log.info(f"Main label printed: {context!r}")
return compiled_label # return fields used to print label for saving into test archive
return context
def print_extra_labels(self): def print_extra_labels(self):
# PRINT EXTRA LABELS IF NEEDED (BEFORE LEAK TEST) # PRINT EXTRA LABELS IF NEEDED (BEFORE LEAK TEST)

View File

@ -150,7 +150,7 @@ class Test_Test(Widget):
else: else:
result_ok = data.get("results", {}).get("ok", None) result_ok = data.get("results", {}).get("ok", None)
duration=cur_timing - self.start_time duration=cur_timing - self.start_time
data.pop("step",None) data.pop("step", None)
self.last = { self.last = {
**data, **data,
"overridden": override, "overridden": override,

View File

@ -58,10 +58,11 @@ class Test_Vision(Test_Test):
def stop(self): def stop(self):
# disable camera-vision loop # disable camera-vision loop
if "uvc_camera" in self.components: cam_type = self.components["vision"].vision_config["camera_type"]
self.components["uvc_camera"].pause() if cam_type in ("uvc_camera","galaxy_camera","hikrobot_sc"):
elif "galaxy_camera" in self.components: self.components[cam_type].pause()
self.components["galaxy_camera"].pause() else:
return
self.components["vision"].pause() self.components["vision"].pause()
self.disconnect(self.get_connection) self.disconnect(self.get_connection)
self.disconnect(self.request_frame_connection) self.disconnect(self.request_frame_connection)
@ -75,7 +76,7 @@ class Test_Vision(Test_Test):
# super().reset() # super().reset()
def get(self, data=None, override=False): def get(self, data=None, override=False):
if self.done: # avoid proccessing if completed if self.done: # avoid processing if completed
return return
if data is None or data[-1] is None: if data is None or data[-1] is None:
super().get(None, override=override) super().get(None, override=override)

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1250</width> <width>1018</width>
<height>629</height> <height>1064</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
@ -145,9 +145,15 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>400</width>
<height>0</height>
</size>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>500</width> <width>600</width>
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
@ -199,7 +205,7 @@
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLabel" name="img_l"> <widget class="QLabel" name="img_l">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>