![]() |
[PyQt] PyQT5 Thread crashes after a while - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: [PyQt] PyQT5 Thread crashes after a while (/thread-28490.html) |
PyQT5 Thread crashes after a while - Suresh - Jul-21-2020 Hi. This is my first thread. So please forgive if any mistake on my part. I have developed an application using opencv, pyqt5 and python. I am trying to capture live images from Flir Camera which comes with it's own SDK. I have already tested this camera and code separately using thread which worked for almost hours. But now, I am am getting issues and I have a doubt if I have understood the threading correctly. This is a huge code that is why I removed the actual code in functions and sort of showing only the heirarchy of the functions and calls. I request help in sorting out this issue. In case any one wants to view the complete code please mention. Please note I removed the code to make it easy to read and find the issue. The issue is the code gets stuck after some time and crashes. When using Spyder, I get kernel restart . When i am using an exe created with pyInstaller, the exe crashes and shuts down after some time. The following is the code from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5 import QtGui from PyQt5 import QtWidgets from PyQt5 import QtCore import time from time import time as my_timer import traceback, sys from dbqry import * # custom developed python code in another file from dberror import * # custom developed python code in another file import numpy import math import serial #from manual_check123 import * from manual_check123_Spin_ManiHeirarchy import * # custom developed python code in another file import os.path from os import path from Crypto.Cipher import AES import datetime import PDevApi class VisionProcess(QObject): ''' Defines the signals available from a running worker thread. Supported signals are: finished No data error `tuple` (exctype, value, traceback.format_exc() ) result `object` data returned from processing, anything progress `int` indicating % progress ''' finished = pyqtSignal() error = pyqtSignal(tuple) result = pyqtSignal(object) progress = pyqtSignal(numpy.ndarray,str) # modified #240520 class VisionR(QRunnable): ''' VisionR thread Inherits from QRunnable to handler worker thread setup, signals and wrap-up. :param callback: The function callback to run on this worker thread. Supplied args and kwargs will be passed through to the runner. :type callback: function :param args: Arguments to pass to the callback function :param kwargs: Keywords to pass to the callback function ''' def __init__(self, fn, *args, **kwargs): super(VisionR, self).__init__() # Store constructor arguments (re-used for processing) self.fn = fn self.args = args self.kwargs = kwargs self.signals = VisionProcess() # Add the callback to our kwargs self.kwargs['progress_callback'] = self.signals.progress # self.kwargs['progress_callback'] = self.signals.pass_image @pyqtSlot() def run(self): ''' Initialise the runner function with passed args, kwargs. ''' # Retrieve args/kwargs here; and fire processing using them try: result = self.fn(*self.args, **self.kwargs) except: traceback.print_exc() exctype, value = sys.exc_info()[:2] self.signals.error.emit((exctype, value, traceback.format_exc())) else: self.signals.result.emit(result) # Return the result of the processing finally: self.signals.finished.emit() # Done class Color(QWidget): def __init__(self, color, *args, **kwargs): super(Color, self).__init__(*args, **kwargs) self.setAutoFillBackground(True) palette = self.palette() palette.setColor(QPalette.Window, QColor(color)) self.setPalette(palette) class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.counter = 0 self.video_file_exists = False self.frame_counter = 0 self.start_time=my_timer() self.cycle_timeout=my_timer() self.max_time_taken=0 self.min_time_taken=0 self.video_frame_count = 0 self.run_loop = True self.vision_thread_start = False self.worker = None self.video_acq_run = False # doubtul to remove debug used to start and stop the video. Might not be needed for cam self.video_stop_by_button = False # debug need to be removed # self.cap = None # new Display Code pyQT left = 50 top = 50 width = 640 height = 480 self.setGeometry(left, top, width, height) # Modbus Variables Start self.read_modbus_flag = 1 self.write_modbus_flag = 0 self.mb_connected = False # self.client = ModbusClient('192.168.1.131', port=502) #modbusuncomment # self.client = ModbusClient('localhost', port=502) # plc to PC self.curr_plc_command = 0 self.prev_plc_command = 0 self.next_plc_command = 0 self.prevPLCSignal = 0 self.prev_pass_signal=0 self.prev_fail_signal=0 self.prev_motor_fw_signal=0 self.prev_motor_rw_signal=0 self.prev_motor_all_off_signal=0 self.prev_out_home7_signal=0 self.home_pass = False self.lowbeam_fwd_pass = False self.lowbeam_rev_pass = False self.highbeam_pass = False # Modbus write value variables self.motor_fw_rv_off = 0 # 0 is motor stop 1 Motor fwrd 2 motor rev 3 self.lb_on = 1 self.lb_off = 2 self.mot_off = 3 self.mot_fwd = 4 self.mot_rev = 5 self.hb_on = 6 self.hb_off = 7 self.write_mb_test_result = 0 self.mb_connect_tried =0 self.mb_connect_try_stop_at = 3 self.start_time = my_timer() self.start_time2 = my_timer() self.running_time = my_timer()+ 100 self.prev_time = my_timer() self.elapsed_time = 0 self.write_modbus_arr = [0,0] # Modbus Variables End # Vision Variables Start # other variables self.pr_name_in_hmi = "" self.curr_jig_product = 0 # value 12 assigned for testing make it 0 latter self.prev_jig_product = 0 # value 12 assigned for testing make it 0 latter self.envOK = 0 # variables for drawing rectangle self.orig_frame = None self.temp_img = None # self.img = None # self.ix,self.iy=-1,-1 # # final rectangle co ordinates self.fsx,self.fsy = 0,0 # FinalStartX FinalStartY self.fex,self.fey = 0,0 # FinalEndX FinalEndY self.pr_Pos_H,self.pr_Pos_L =0,0 self.pr_Pos_M = 0 self.image_file_path = "../templates/" # Home / Frwd Location 1 , 2 , 3 co ordinates # Home co ords. self.hm_top_x=[0,0,0,0] # first element is dummy self.hm_top_y=[0,0,0,0] self.hm_bot_x=[0,0,0,0] self.hm_bot_y=[0,0,0,0] # tolerance roi self.hm_tol_top_x=[0,0,0,0] # first element is dummy self.hm_tol_top_y=[0,0,0,0] self.hm_tol_bot_x=[0,0,0,0] self.hm_tol_bot_y=[0,0,0,0] # common # Fwrd Co ords self.fw_top_x=[0,0,0,0] self.fw_top_y=[0,0,0,0] self.fw_bot_x=[0,0,0,0] self.fw_bot_y=[0,0,0,0] # tolerance roi co ord self.fw_tol_top_x=[0,0,0,0] # first element is dummy self.fw_tol_top_y=[0,0,0,0] # Template Find ROI Co ordinates self.tm_top_left=[0] # first element is dummy self.tm_bot_right=[0] self.tm_color=[0,0,0,0] self.tm_tolerance = 30 # ROI mid points self.hm1_mtpt_mhl=[0,0,0,0] self.hm2_mtpt_mhl=[0,0,0,0] self.hm3_mtpt_mhl=[0,0,0,0] self.fw1_mtpt_mhl=[0,0,0,0] # self.show_rectangle =0 self.r_color_id = 0 # this is index of r_Color self.show_rect_id = 0 # this is for home, forward, reverse rectangle self.r_Color=[(170,255,0),(0,255,0),(0,0,255),(255,255,)] # 0 Cyan 1 Green 2 Red 3 Yellow self.show_home_rect = False self.top_X,self.top_Y,self.bot_X,self.bot_Y =0,0,0,0 # mod050720 variable declaration self.defined_tol_mtpt1,self.defined_tol_mtpt2 = 0,0 self.fw_line=0 self.com_tol_top_X,self.com_tol_top_Y,self.com_tol_bot_X,self.com_tol_bot_Y =0,0,0,0 self.home_at_fw_start_x,self.home_at_fw_start_y =0,0 ## final home position when home ok and forward starts # the above at_fw_start will be the return to base value when reverse is done self.show_template_rectange_hmfw = 0 # 1 --> hm 2 --> fw self.btn_color = "NA" self.str_ret_val = "NA" self.seq_begin_timer = my_timer() self.home_midpoint_call_spacing = my_timer() # # end variables for drawing rectanlge # variables from manis code for table self.hllareq = 0 self.barcodereq = 0 self.prndata = "" self.hminame = "" self.custcode ="" self.prodcode = "" self.cpartcode = "" self.ctime = None self.lampnametype = "" self.day_of_year = datetime.datetime.now().timetuple().tm_yday self.conn = None self.lastserial_fromtable =0 self.serialtoprint =0 self.print_bc_only_once = 9 self.custprodyydayofyear ="" self.final_test_pass = 0 self.final_test_fail = 0 # Vision Variables End # UI Widgets, layouts etc mainLayout = QVBoxLayout() titleLayout = QHBoxLayout() statusLayout = QHBoxLayout() imgLayout = QVBoxLayout() lblLayout = QVBoxLayout() btnLayout = QVBoxLayout() roundBtnLayout = QHBoxLayout() btnFWRVLayout = QHBoxLayout() plotLayOut = QHBoxLayout() lblLayout.setAlignment(Qt.AlignCenter) btnLayout.setAlignment(Qt.AlignTop) titleLayout.setAlignment(Qt.AlignCenter) statusLayout.setAlignment(Qt.AlignLeft) imgLayout.addStretch() btnLayout.setSpacing(15) plotLayOut.addLayout(imgLayout,20) plotLayOut.addLayout(btnLayout,2) mainLayout.addLayout(titleLayout,1) mainLayout.addLayout(plotLayOut,18) mainLayout.addLayout(statusLayout,1) # self.l = QLabel("Start") self.tm = QLabel("Time") # folloing is a label used to display camera input. Continually updated self.imgdis = QtWidgets.QLabel(self) self.imgdis.setGeometry(QtCore.QRect(150, 100, 1000, 600))#740,512 self.imgdis.setObjectName("imgdis") self.imgdis.setMouseTracking(True) self.imgdis.installEventFilter(self) self.hBeamBtn = QPushButton(self) # self.hBeamBtn.setObjectName("hBeamBtn") self.hBeamBtn.setText("HIGHBEAM") titleLbl = QLabel("Light Beam Testing System") self.prdLbl = QLabel("Product") self.testRunningLbl = QLabel("Test Running") self.mbBtn = QPushButton("PLC") # new buttons self.camBtn = QPushButton("CAMERA") # new buttons self.dumBtn = QPushButton("DUM") # new buttons self.visionStartStop = QPushButton("Start") self.videoStartStop = QPushButton("Video ON") # Debug to remove latter self.lBeamBtn = QPushButton("LOWBEAM") self.hmPassBtn = QPushButton("HOME") self.fwPassBtn = QPushButton("FRWD") self.rvPassBtn = QPushButton("RVRS") self.allTestBtn = QPushButton("ALLPASS") self.prnStatusBtn = QPushButton("PRINT") # startBtn.pressed.connect(self.start_run) self.visionStartStop.pressed.connect(self.start_stop_vision_thread) self.videoStartStop.pressed.connect(self.video_start_stop) # debug to remove latter self.prdLbl.setAlignment( Qt.AlignHCenter) self.testRunningLbl.setAlignment( Qt.AlignHCenter) titleLbl.setAlignment( Qt.AlignHCenter) titleLbl.setStyleSheet("font: bold;background-color: blue;font-size: 36px;height: 60px;width: 250px;") self.prdLbl.setStyleSheet("font: bold;background-color: cyan;font-size: 24px;height: 60px;width: 150px;") self.testRunningLbl.setStyleSheet("font: bold;background-color: yellow;font-size: 24px;height: 60px;width: 150px;") self.hBeamBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") self.lBeamBtn.setStyleSheet("font: bold;background-color: white;font-size: 12px;height: 14px;width: 80px;") self.hmPassBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") self.fwPassBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") self.rvPassBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") self.allTestBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") self.prnStatusBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") # startBtn.setStyleSheet("font: bold;background-color: green;font-size: 12px;height: 28px;width: 80px;") self.visionStartStop.setStyleSheet("font: bold;background-color: red;font-size: 12px;height: 28px;width: 80px;") # new buttons self.mbBtn.setStyleSheet("font: bold;background-color: green; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop: 0 #fff, stop: 1 #888);padding: 5px; font-size: 12px;height: 30px;width: 30px;") self.camBtn.setStyleSheet("font: bold;background-color: green; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop: 0 #fff, stop: 1 #888);padding: 5px; font-size: 12px;height: 30px;width: 30px;") self.dumBtn.setStyleSheet("font: bold;background-color: green; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop: 0 #fff, stop: 1 #888);padding: 5px; font-size: 12px;height: 30px;width: 30px;") self.tm.setStyleSheet("font:bold:font-size: 20px;height: 30px;width: 30px;") titleLayout.addWidget(titleLbl) # title2Layout.addWidget(prdLbl) # title2Layout.addWidget(testRunningLbl) btnFWRVLayout.addWidget(self.hmPassBtn) btnFWRVLayout.addWidget(self.fwPassBtn) btnFWRVLayout.addWidget(self.rvPassBtn) imgLayout.addWidget(self.imgdis) btnLayout.addWidget(self.prdLbl) # btnLayout.addWidget(self.testRunningLbl) btnLayout.addWidget(self.lBeamBtn) btnLayout.addLayout(btnFWRVLayout) btnLayout.addWidget(self.hBeamBtn) btnLayout.addWidget(self.allTestBtn) btnLayout.addWidget(self.prnStatusBtn) roundBtnLayout.addWidget(self.mbBtn) # new buttons roundBtnLayout.addWidget(self.dumBtn) # new buttons roundBtnLayout.addWidget(self.camBtn) # new buttons btnLayout.addLayout(roundBtnLayout) # btnLayout.addWidget(mbBtn) btnLayout.addWidget(self.visionStartStop) btnLayout.addWidget(self.videoStartStop) # debug to remove # statusLayout.addWidget(self.l) statusLayout.addWidget(self.tm ) # statusLayout.addWidget(self.maxt) widget = QWidget() widget.setLayout(mainLayout) # since only 1 layout is set to the widget. This one must contain others self.setCentralWidget(widget) # new Display Code pyQT END widget = QWidget() widget.setLayout(mainLayout) # since only 1 layout is set to the widget. This one must contain others self.setCentralWidget(widget) self.show() self.threadpool = QThreadPool() #print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) self.timer = QTimer() self.timer.setInterval(1) self.timer.timeout.connect(self.recurring_timer) frame = cv2.imread('../templates/dispimg.png',1) # ============================================================================= Top = cv2.resize(frame, None, fx=0.65, fy=0.65) Top_Image1 = cv2.resize(Top, (1000,600)) # 740, 512 # Top_Image1=cv2.cvtColor(Top_Image1, cv2.COLOR_RGB2BGR) self.imgdisplay1(Top_Image1) self.dumBtn.hide() #print ("starting modbus ") if cam_detected: self.video_acq_run = True self.camBtn.setStyleSheet("font: bold;background-color: green; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop:0 white, stop: 0.01 gray, stop:1 green);padding: 5px; font-size: 12px;height: 30px;width: 30px;") Acq_start_one() else: self.video_acq_run = False self.camBtn.setStyleSheet("font: bold; color: black; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop:0 white, stop: 0.01 gray, stop:1 red);padding: 5px; font-size: 12px;height: 30px;width: 30px;") print("no Camera") # self.start_modbus() self.envOK = self.check_environment() # self.modbus_connect() #modbusuncomment # PDevAPI section below PDev_CardNumber = 11 Pdev_Port = 1 Pdev_Line = 0 Pdev_Direction = 1 pinval= PDevApi.RegisterCard(11,0) rd = 0 # PDEV Api section above # init UI # End Init UI # Adlink PDEV code below def read_dio(self): # # # called from run_vision_function once every 5 seconds self.curr_plc_command = 1 # Actually around 20 statements to read an external DAQ Device and set the above value which # can be anything from 1 to 129 def out_home7(self,onOff): #called from run_vision_function once every 15 seconds rd = 0 if onOff==1: out = PDevApi.DOWriteLine(0,0,7,1) # trying to switch off all outputs at a go provide #time.sleep(0.5) print("Home Aiming Ok Signal Sent") elif onOff==2: out = PDevApi.DOWriteLine(0,0,7,0) self.prev_out_home7_signal=1 def out_pass(self): # # called from run_vision_function once every 15 seconds either 1 pass or fail #same as out_home7 to switch on outputs on DAQ # print ("Pass On ") def out_fail(self): # # called from run_vision_function once every 15 seconds either one pass or fail rd = 0 #same as out_home7 to switch on outputs on DAQ def out_motor_fw(self,fw_on_off): # # called from run_vision_function once every 15 seconds rd = 0 #same as out_motor_rv to switch on outputs on DAQ def out_motor_rv(self,rv_on_off): #called from run_vision_function once every 15 seconds rd = 0 # Leaving the original code to give an insight of the code is like if self.prev_motor_rw_signal==0: if rv_on_off ==1 : # forward on out = PDevApi.DOWriteLine(0,0,2,0) # forward off time.sleep(0.3) out = PDevApi.DOWriteLine(0,0,3,1) # reverse on time.sleep(0.3) #print ("Motor Reverse On " ) else: #elif rv_on_off ==2 : # reverse off out = PDevApi.DOWriteLine(0,0,3,0) # reverse off time.sleep(0.3) out = PDevApi.DOWriteLine(0,0,2,0) # forward off time.sleep(0.3) #print ("Motor Reverse Off " ) self.prev_motor_rw_signal=1 def out_motor_off(self): # # called from run_vision_function once every 15 seconds rd = 0 #same as out_motor_rv to switch on outputs on DAQ # called on if condition def imgdisplay1(self, p_TopImage): # called from run_vision_function continously almost every 300 milli seconds # called continously pixmap1 = QPixmap(p_TopImage) self.imgdis.setPixmap(pixmap1) pixmap1.detach()#mod180720 self.imgdis.resize(pixmap1.width(),pixmap1.height()) def check_environment(self): # called only once at start of progam time_expired = 0 # key_location = "F:\\vision37\\envtext.bin" # A safe place to store a key. Can be on a USB or even locally on the machine (not recommended unless it has been further encrypted) key_location = ".\\envtext.bin" # A safe place to store a key. Can be on a USB or even locally on the machine (not recommended unless it has been further encrypted) decoded_val_s=0 str_message = '' file_exists = os.path.exists(key_location) # read a text file process and return values as below # called only once return(time_expired,decoded_val_s,str_message) def progress_fn(self, tp_image, strval): self.imgdisplay1(tp_image) def video_start_stop(self): # invoked by QButton if self.video_stop_by_button == True: self.video_stop_by_button = False else: self.video_stop_by_button = True def draw_rectangles(self,Top_Image1): # called from run_vision_function continously # following code is mostly to draw rectangles, Lines on the image before display # can skip this part of the code. Leaving it for your reference tlr = self.tm_tolerance - 15 # to draw closer if self.show_template_rectange_hmfw == 1:# this is to show home template match boxes # print ("Entered imgdisplay through do_template_check ") for x in range (1,4): # print("imgdisplay point 1" ) if (self.hm_top_x[x] !=0) & (self.hm_top_y[x]-tlr !=0) & \ (self.hm_bot_x[x] !=0) & (self.hm_bot_y[x] !=0 ) : roi_top_left = (self.hm_top_x[x]-tlr,self.hm_top_y[x]-tlr) roi_bot_right = (self.hm_bot_x[x]+tlr,self.hm_bot_y[x]+tlr) cv2.rectangle(Top_Image1,roi_top_left,roi_bot_right,self.r_Color[self.tm_color[x]],thickness=4) else: if ((self.show_rect_id ==1) or(self.show_rect_id ==3)): # mod130720 newly added if statement #if (self.show_rect_id in range (1,4)): #mod130720 this line is commented out c_color = self.r_Color[self.r_color_id] # cv2.rectangle(Top_Image1,(self.top_X,self.top_Y), (self.bot_X,self.bot_Y),c_color,2) cv2.rectangle(Top_Image1,(self.top_X,self.top_Y), (self.bot_X,self.bot_Y),(170,255,0),2) # fixed color # mod050720 drawing circle at the point cv2.circle(Top_Image1,(self.defined_tol_mtpt1,self.defined_tol_mtpt2 ),3,[0,0,255],-1) # self.fw_line=0 Following is for actual tolerance rectangle check Modify this latter with common variables cv2.rectangle(Top_Image1,(self.com_tol_top_X ,self.com_tol_top_Y),(self.com_tol_bot_X,self.com_tol_bot_Y),c_color,2) elif (self.show_rect_id ==5): # show forward line only #130720 latter try to change the 5 to 1 c_color = self.r_Color[self.r_color_id] # drawing a line height, width, channels = Top_Image1.shape line_thickness = 2 x_end = (width) # self.defined_tol_mtpt1 #fw_check draw line self.fw_line=0 cv2.line(Top_Image1, (0, self.fw_line ), (x_end, self.fw_line), c_color, thickness=line_thickness) #mod130720 commented out #cv2.line(Top_Image1, (0, self.defined_tol_mtpt2 ), (x_end, self.defined_tol_mtpt2), c_color, thickness=line_thickness) #mod130720 commented out Top_Image2 = cv2.resize(Top_Image1, (1000,600)) #740, 512 Top_Image2=cv2.cvtColor(Top_Image2, cv2.COLOR_RGB2BGR) height, width, channel = Top_Image2.shape # 190520 in accordance to above lines new # height, width, channel = Top_Image1.shape bytesPerLine = 3 * width ret_QImage = QImage( Top_Image2.data, width, height, bytesPerLine, QImage.Format_RGB888) return(QImage) def run_vision_function(self, progress_callback): # QThread self.elapsed_time = my_timer() prev_mb_timer = my_timer() -2 # so that first time it gets executed frame_set = False seq_running_timer = my_timer() hm_temp_res = [0,0,0,0] fw_temp_res = [0,0,0,0] action_to_do = 0 # set the action_to_do with 1 - 5 of the following act_lb_hm_chk = 1 # do home check act_lb_hm_tmp_chk = 2 # do home template check act_lb_fw_chk = 3 # do forward check act_lb_fw_tmp_chk = 4 # do forward template check act_lb_rv_chk = 5 # do reverse check act_hb_cont_chk = 6 # do reverse check act_all_pass_chk = 10 # do reverse check act_all_fail_chk = 12 # do reverse check act_bc_print_chk = 13 # do reverse check hm_chk_result = False fw_chk_result = False high_beam_result = False rv_chk_result = False hm_template_chk_pass = False fw_template_chk_pass = False # show_rectangle = 0 n = 0 # debug start_high_beam_chk = False # debug img_write_once = True # debug # self.read_table() # debug remove self.curr_plc_command = 0 # debug remove dummy_always_true = True temp_img = self.orig_frame roi_hide_time = 1.00 roi_hide_after_timer = True all_test_timer = False read_daq = False test_time_taken = 0 disp_delay = my_timer() save_image = False # do_template_check_run = False # to control that the template is run only once while self.run_loop: # while True: self.elapsed_time = round(my_timer() - prev_mb_timer) if ((self.curr_plc_command== 16) or (self.curr_plc_command==2) or (self.curr_plc_command==0)): if (self.elapsed_time > 2): #print ("daq bef read ", self.curr_plc_command, " elapsed time ", self.elapsed_time) read_daq = True if (read_daq==True) : prev_mb_timer = round(my_timer()) # bug self.prev_mb_timer modified to prev_mb_timer 080720 self.read_dio() #print ("daq after read ", self.curr_plc_command) read_daq = False #print ("Reading DIO ",self.curr_plc_command,prev_mb_timer, " ", self.elapsed_time) if self.mb_connected == True: # self.execute_modbus() #modbusuncomment pass if(self.prev_jig_product != self.curr_jig_product) & (self.curr_jig_product in range(1,16)): self.prev_jig_product = self.curr_jig_product self.read_table() if (self.curr_plc_command != self.prev_plc_command): self.prev_plc_command = self.curr_plc_command prev_mb_timer = my_timer() self.cycle_timeout = my_timer() # used to timeut cycle # seq_start_timer = my_timer() # reset the start time whenever sequence change from plc self.seq_begin_timer = my_timer() # reset the start time whenever sequence change from plc if self.curr_plc_command == 1: # start home aiming then initialize self.show_rect_id = 1 hm_temp_res = [0,0,0,0] fw_temp_res = [0,0,0,0] hm_chk_result = False fw_chk_result = False rv_chk_result = False high_beam_result = False self.prev_pass_signal=0 self.prev_fail_signal=0 self.prev_motor_fw_signal=0 self.prev_motor_rw_signal=0 self.prev_motor_all_off_signal=0 self.prev_out_home7_signal=0 action_to_do = act_lb_hm_chk self.print_bc_only_once=1 self.out_home7(2) self.start_time = my_timer() # debug for timing #self.cycle_timeout = my_timer() # used to timeut cycle sequence self.btn_color ="ALL_gray" # sets all btns to red initially #print ("curr_command 1 ") save_image = True # debug used to save image as per AJINs request to find the deflector if (self.curr_plc_command == 4): # start low beam sequence check self.prev_pass_signal=0 self.prev_fail_signal=0 #print ("curr_command 4 ") action_to_do == act_lb_hm_chk if (self.curr_plc_command == 8): # start high beam check self.prev_pass_signal=0 self.prev_fail_signal=0 self.show_rect_id = 0 action_to_do = act_hb_cont_chk start_high_beam_chk = True # required in actual run if (self.video_acq_run == True and self.video_stop_by_button == False): # debug this and next line # next 4 lines needed change indent after removing above 1st line # ret_frame_list = self.run_video_loop() # this will be replaced with get from camera # ret_frame_list = self.run_video_loop() # this will be replaced with get from camera ret,frame = grab_image_one() frame_set = ret ret_frame = frame if frame_set == True and self.video_stop_by_button == False : # print("here 1") temp_img = ret_frame self.template_logging(temp_img,self.curr_jig_product,1,2,3) self.orig_frame = ret_frame # just in case to remove if not using temp_img = cv2.resize(ret_frame, None, fx=0.65, fy=0.65) homing_roi_image = ret_frame # check if the following four lines to be done here or on home self.top_X,self.top_Y = self.hm_top_x[1],self.hm_top_y[1] self.bot_X,self.bot_Y = self.hm_bot_x[1],self.hm_bot_y[1] self.com_tol_top_X,self.com_tol_top_Y = self.hm_tol_top_x[1],self.hm_tol_top_y[1] self.com_tol_bot_X,self.com_tol_bot_Y = self.hm_tol_bot_x[1],self.hm_tol_bot_y[1] if (my_timer() - self.seq_begin_timer >= roi_hide_time) & (roi_hide_after_timer==True ): # print ("Hide timer ",my_timer() - self.seq_begin_timer, roi_hide_timer ) self.show_template_rectange_hmfw = 0 if (self.curr_plc_command == 1): # low beam manual aiming mod060720 new code added hm_chk_result = self.do_home_check(temp_img,1) # mod060720 new code added if (hm_chk_result == True): self.out_home7(1) # mod130720 commented out send home signal as pass DAQ Code self.curr_plc_command = 0 self.next_plc_command = 4 if save_image == True: image_time = int(datetime.datetime.now().timestamp()) save_filename = "../templates/deflectorimage/f"+str(image_time)+".png" print ("file name ", save_filename) cv2.imwrite(save_filename,temp_img) save_image = False if (self.curr_plc_command == 4): # start lowbeam Forward Reverse check if (action_to_do == act_lb_hm_chk): if (hm_chk_result == True ): action_to_do = act_lb_hm_tmp_chk # set next action to hm_template check if (action_to_do == act_lb_hm_tmp_chk): # start home template check hm_temp_res = self.do_template_check(temp_img,1) #mod140720 commented out for testing #hm_temp_res = (1,1,1,1) if (hm_temp_res[1] ==1) & (hm_temp_res[2] ==1) & (hm_temp_res[3] ==1): action_to_do = act_lb_fw_chk # set next action to forward check self.seq_begin_timer = my_timer() # store next action begin time hm_template_chk_pass = True roi_hide_after_timer = True self.show_rect_id = 5 # show forward rectangle mod130720 self.r_color_id = 2 # color Red print ("Forward Start ") self.out_motor_fw(1) # send forward signal 1 for forward DAQ Code else: print("Hm Template Fail ",hm_temp_res,self.tm_color) hm_template_chk_pass = False #roi_hide_after_timer = False roi_hide_after_timer = True self.seq_begin_timer = my_timer() self.out_fail() # send fail signal as pass DAQ Code self.curr_plc_command = 0 # to restart action_to_do = 0 if (action_to_do == act_lb_fw_chk): fw_chk_result = self.do_fw_check(temp_img) if (fw_chk_result == True ): self.out_motor_fw(2) # forward motor off signal action_to_do = act_lb_fw_tmp_chk # set next action to hm_template check if (action_to_do == act_lb_fw_tmp_chk): # forward template check # FORWARD POSITION TEMPLATE CHECK AS FOLLOWS -- Bypassed on 060720 # fw_temp_res = self.do_template_check(temp_img,2) # bypassed 060720 #print ("Rverse Start 3 ") fw_temp_res = (1,1,1,1) # print ("Forward Result ",fw_temp_res) if (fw_temp_res[1] ==1) & (fw_temp_res[2] ==1) & (fw_temp_res[3] ==1): # START REVERSE #print ("Rverse Start 4") action_to_do = act_lb_rv_chk # set next action to forward check self.seq_begin_timer = my_timer() # store next action begin time fw_template_chk_pass = True roi_hide_after_timer = True #self.out_pass() self.show_rect_id = 3 # show reverse rectangle self.r_color_id = 2 # color Red self.out_motor_rv(1) # send reverse signal 1 for forward DAQ Code if (action_to_do == act_lb_rv_chk): rv_chk_result = self.do_home_check(temp_img,3) # 3 is for reverse check if (rv_chk_result == True): action_to_do = 0 # read daq self.out_motor_off() # send forward & reverse off signals for DAQ Code self.out_pass() # send reverse pass signal for DAQ Code self.curr_plc_command = 0 # to restart self.next_plc_command = 8 test_time_taken = round(my_timer() - self.cycle_timeout) if (test_time_taken > 15): fw_template_chk_pass = False hm_template_chk_pass = False roi_hide_after_timer = False self.seq_begin_timer = my_timer() self.out_fail() # send forward template fail signal for DAQ Code self.curr_plc_command = 0 # to restart read_daq = True action_to_do = 0 if (self.curr_plc_command == 8) & (start_high_beam_chk == True) : time.sleep(0.5) (high_beam_result,r_contours) = self.do_high_beam_contour(temp_img) if (high_beam_result == True): cv2.drawContours(temp_img, r_contours, -1, (0, 255, 0), 2) self.out_pass() # send high beam pass signal for DAQ Code self.curr_plc_command = 0 # to restart read_daq = True self.next_plc_command = 1 action_to_do = 0 if (test_time_taken > 15): print("High beam Fail " ) self.out_fail() # send forward template fail signal for DAQ Code self.curr_plc_command = 0 # to restart read_daq = True action_to_do = 0 if (self.curr_plc_command == 2) : # do ALL Pass show indicator print ("Bar Code on Pass ", self.print_bc_only_once) if (self.barcodereq == 1) and (self.print_bc_only_once==1): print(" bc print under pass ") self.do_print_barcode() self.btn_color= 'self.prnStatusBtn_green' self.print_bc_only_once=9 self.curr_plc_command = 0 self.btn_color= 'self.allTestBtn_green' if (self.curr_plc_command == 16) : # all Fail show indicator self.btn_color= 'self.allTestBtn_red' if (self.curr_plc_command == 32) : # do barcode print print ("Bar Code on Print Command") if self.barcodereq == 1: #self.do_print_barcode()#commneted mod170720 self.btn_color= 'self.prnStatusBtn_green' self.curr_plc_command = 0 status_message = self.str_ret_val final_image = self.draw_rectangles(temp_img) #mod180720 disp_elapsed = round((my_timer() - disp_delay),2) disp_image = False if disp_elapsed > 0.03: disp_image = True disp_delay = my_timer() if disp_image == True : progress_callback.emit(final_image,status_message) def do_home_check(self,tmp_img, hm_fw_pos):# called from run_vision_function continously until condition met # Leaving code as is for reference home_check_result = False defined_mtptH = 0 defined_mtptL = 0 btn_color_red = '' btn_color_yellow ='' hmtlrx = 8 hmtlry = 12 str_movement = " " do_delayed_check = False tolr = 0 if (hm_fw_pos == 1): # get home ROI 1 self.top_X,self.top_Y = self.hm_top_x[1],self.hm_top_y[1] self.bot_X,self.bot_Y = self.hm_bot_x[1],self.hm_bot_y[1] self.com_tol_top_X,self.com_tol_top_Y = self.hm_tol_top_x[1],self.hm_tol_top_y[1] self.com_tol_bot_X,self.com_tol_bot_Y = self.hm_tol_bot_x[1],self.hm_tol_bot_y[1] defined_mtptH = self.hm1_mtpt_mhl[2] defined_mtptL = self.hm1_mtpt_mhl[3] btn_color_red = 'self.hmPassBtn_red' btn_color_yellow = 'self.hmPassBtn_yellow' str_movement = "Home " do_delayed_check = True tolr = 9 #mod130720 forward rectangle check not done from this part elif (hm_fw_pos == 2): # get FW ROI 1 print ("This part must not run. insteac the do_fw_check should run for the forward movement ") # comment out above section of does nto run #130720 elif (hm_fw_pos == 3): # reverse sequence of low beam use teh HOME 1 ROI (both are same only button different) self.top_X,self.top_Y = self.hm_top_x[1],self.hm_top_y[1] self.bot_X,self.bot_Y = self.hm_bot_x[1],self.hm_bot_y[1] self.com_tol_top_X,self.com_tol_top_Y = self.hm_tol_top_x[1],self.hm_tol_top_y[1] self.com_tol_bot_X,self.com_tol_bot_Y = self.hm_tol_bot_x[1],self.hm_tol_bot_y[1] defined_mtptH = self.hm1_mtpt_mhl[2] # X h is x l is y defined_mtptL = self.hm1_mtpt_mhl[3] # Y h is x l is y # hm_fw_pos = hm_fw_pos - 2 # changing the 3 passed to 1 to allow home based functions like rectangle & color btn_color_red = 'self.rvPassBtn_red' btn_color_yellow = 'self.rvPassBtn_green' # here wil be using green instead of yellow str_movement = "Reverse " do_delayed_check = True tolr = 9 if (self.top_X>0) & (self.top_Y>0) & (self.bot_X>0) & (self.bot_Y >0): homing_roi_image = tmp_img[self.top_Y:self.bot_Y , self.top_X:self.bot_X] else: homing_roi_image = tmp_img.copy() cont_err,mtpt1,mtpt2=self.homing_midpoint(homing_roi_image) tol_mtpt1 = self.top_X + mtpt1 tol_mtpt2 = self.top_Y + mtpt2 # mod050720 following 2 lines self.defined_tol_mtpt1 = self.top_X + defined_mtptH self.defined_tol_mtpt2 = self.top_Y + defined_mtptL self.r_color_id = 2 x_ok = False y_ok = False if ((tol_mtpt1 > self.com_tol_top_X ) & (tol_mtpt1 < self.com_tol_bot_X) & (mtpt1 !=0)): x_ok = True if ((tol_mtpt2> self.com_tol_top_Y ) & (tol_mtpt2 < self.com_tol_bot_Y) & (mtpt2 !=0)): y_ok = True # if (tol_mtpt1 in range (self.com_tol_top_X, self.com_tol_bot_X)) and (tol_mtpt2 in range (self.com_tol_top_Y,self.com_tol_bot_Y)) and (mtpt2!=0): if ((x_ok == True ) and (y_ok==True)): #print (" tol ", self.com_tol_top_X ,tol_mtpt1 ,self.com_tol_bot_X, " 2 ",self.com_tol_top_Y , tol_mtpt2 ,self.com_tol_bot_Y) # self.show_color_arr[hm_fw_pos] = 1 # green self.r_color_id = 1 # mod050720 adding the following if if (do_delayed_check == True): # setting time delay only at initial home if(round(my_timer() - self.seq_begin_timer,2)> 2): self.home_at_fw_start_x,self.home_at_fw_start_y =tol_mtpt1,tol_mtpt2 #mod130720 home_check_result = True self.btn_color= btn_color_yellow #'self.hmPassBtn_yellow' else: home_check_result = True self.btn_color= btn_color_yellow #'self.hmPassBtn_yellow' # above line change 070720 else: #if (mtpt2 < self.hm1_mtpt_mhl[2]) and (mtpt2 > self.hm1_mtpt_mhl[3]) and (mtpt2!=0): self.seq_begin_timer = my_timer() self.r_color_id = 2 # self.show_color_arr[hm_fw_pos] = 2 # red home_check_result = False self.btn_color=btn_color_red # 'self.hmPassBtn_red' # self.str_ret_val = str_movement + " Tolerance Req " + str(defined_mtptH) + " " + str(defined_mtptL) +" Actual TX " + str(self.com_tol_top_X) + " VAL " + str(tol_mtpt1) +" BX " + str( self.com_tol_bot_X) + " TY " + str( self.com_tol_top_Y) + " VAL " + str(tol_mtpt2) +" BY " + str(self.com_tol_bot_Y) + " Final Result " + str(home_check_result) + " X Y Result " + str(x_ok) + " " + str(y_ok) self.str_ret_val = str_movement + " Current Tol X " + str(tol_mtpt1) + " Between " + str(self.com_tol_top_X) + "/" + str(self.com_tol_bot_X) + " Req Tol X " + str(self.defined_tol_mtpt1) + " Current Tol Y " + str(tol_mtpt2) + " Between " + str(self.com_tol_top_Y) + "/" + str(self.com_tol_bot_Y) + " Req Tol Y " + str(self.defined_tol_mtpt2) + " X Y Result " + str(x_ok) + " " + str(y_ok) + " Final Result " + str(home_check_result) return home_check_result #mod130720 do_rv_check added as a new function for reverse check def do_rv_check(self,tmp_img): # called from run_vision_function conditionally once 15 seconds rv_check_result = False # code same as above do_home_check with slight variation return rv_check_result #mod100720 def do_fw_check(self,tmp_img): # called from run_vision_function conditionally once 15 seconds fw_check_result = False # code same as above do_home_check with slight variation return fw_check_result def do_template_check(self,tmp_img,hm_fwd_check): # called from run_vision_function conditionally once 15 seconds self.r_color_id = 0 self.show_rect_id = 0 template_result=[0,0,0,0] # first one dummy # there is for loop here with range 1 to 4 . In sense loop runs 3 times return template_result def template_logging(self,cimg,jigid,tmp_res1,temp_res2,temp_res3): # called by do_template_check above imgpath = "../errtrack/f" image_time = int(datetime.datetime.now().timestamp()) save_filename = imgpath +str(image_time)+".png" cv2.imwrite(save_filename,cimg) next_row_id=0 insert_row((save_filename,image_time,jigid,tmp_res1,temp_res2,temp_res3)) def do_high_beam_contour(self,img1): # called from run_vision_function conditionally once 15 seconds cntr_result = False f if (area > 30000): cntr_result = True self.btn_color= 'self.hBeamBtn_green' return(cntr_result, [contours[0]]) # print routine start def do_print_barcode(self): # called from run_vision_function conditionally once 15 seconds # reads text file and prints to serial port / barcode printer ser.close() def homing_midpoint(self,img1): # used under do_home_check & fw_check and rv_check t1=far[0] t2=far[1] return (cont_try_error,t1,t2) def btn_color_set(self,btn_name_color): # called from recurring_timer continously for changing the color state of the buttons if (btn_name_color != "NA"): btnname_color = btn_name_color.split("_") btn_name = btnname_color[0] s_color = btnname_color[1] s_style = '' # print(btn_name," ", s_color) if s_color == 'red': s_style = '.setStyleSheet("font: bold;background-color: red;font-size: 12px;height: 28px;width: 80px;")' elif s_color == 'green': s_style = '.setStyleSheet("font: bold;background-color: green;font-size: 12px;height: 28px;width: 80px;")' # 230520 change for home and forward color set elif s_color == 'yellow': s_style = '.setStyleSheet("font: bold;background-color: yellow;font-size: 12px;height: 28px;width: 80px;")' elif s_color == 'gray': s_style = '.setStyleSheet("font: bold;background-color: gray;font-size: 12px;height: 28px;width: 80px;")' #'self.lBeamBtn', btns = ['self.hmPassBtn','self.fwPassBtn','self.rvPassBtn','self.hBeamBtn','self.allTestBtn','self.prnStatusBtn'] for btn in btns: if (str(btn_name) == str(btn)) | (str(btn_name) == 'ALL'): styl = btn+'.setStyleSheet("font: bold;background-color: red;font-size: 12px;height: 28px;width: 80px;")' styl = btn+ s_style eval(styl) def print_output(self, s): print(s) def thread_complete(self): print("THREAD COMPLETE!") def closeEvent(self, event): # print ("exit clicked") self.run_loop = False # self.threadpool.stop(self.worker) self.timer.stop() Acq_stop_one() # a call to function from external python file. sys.exit() def start_vision(self): # Pass the function to execute self.worker = VisionR(self.run_vision_function) # Any other args, kwargs are passed to the run function self.worker.signals.result.connect(self.print_output) # commented out by suresh self.worker.signals.finished.connect(self.thread_complete) # commented out by suresh self.worker.signals.progress.connect(self.progress_fn) # commented out by suresh # worker.signals.pass_image.connect(self.progress_fn) # commented out by suresh self.counter =0 #print ("Counter Reset") # Execute self.threadpool.start(self.worker) def modbus_connect(self): if (self.mb_connected==False): print("Connecting ...") # self.mb_connect_tried +=1 mb_connect_tries = 0 while mb_connect_tries <= 3: try: #client = ModbusClient('192.168.1.190', port=502) self.mb_connected = self.client.connect() print ("Connection Status {0}".format(self.mb_connected)) except AssertionError as error: print("Modbus Connection Error") self.mb_connected = False if self.mb_connected == True: mb_connect_tries = 4 else: mb_connect_tries +=1 time.sleep(1) if self.mb_connected: self.mbBtn.setStyleSheet("font: bold;background-color: green; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop:0 white, stop: 0.01 gray, stop:1 green);padding: 5px; font-size: 12px;height: 30px;width: 30px;") else: self.mbBtn.setStyleSheet("font: bold; color: black; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop:0 white, stop: 0.01 gray, stop:1 red);padding: 5px; font-size: 12px;height: 30px;width: 30px;") print("no Camera") def start_stop_vision_thread(self): if self.envOK[0] != 1: self.str_ret_val= self.envOK[2] + str(" Val ") + str(self.envOK[1]) + str(" Error ") + str(self.envOK[0]) #self.tm.setText(self.str_ret_val) #return if self.vision_thread_start == False: # self.start_run() self.visionStartStop.setText("Stop") self.start_time = my_timer() self.start_vision() self.timer.start() # self.run_loop = False # added on 290520 self.vision_thread_start = True else: self.visionStartStop.setText("Start") self.run_loop = False self.vision_thread_start = False # self.threadpool.stop(self.worker) self.timer.stop() Acq_stop_one() sys.exit() def read_table(self): # conditional read. not frequent. From vision_function . Read SQL TAble print ("read table done") # self.draw_rectangle_manual() def vld(self,in_val): # called from read_table for validation # checks if value from field is valid and not equal to None. If none returns 0 applies to numerics only ret_val = 0 if in_val == None: ret_val = 0 else: ret_val = int(in_val) return ret_val def recurring_timer(self): # pass self.btn_color_set(self.btn_color) self.prdLbl.setText(self.pr_name_in_hmi) #self.tm.setText(self.str_ret_val) app = QApplication([]) window = MainWindow() app.exec_() |