hikrobot dual smart cam test alpha
This commit is contained in:
parent
10c9284d00
commit
b52897fc33
|
|
@ -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/
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user