first commit

This commit is contained in:
2025-07-29 13:16:30 +08:00
commit dca51db4eb
145 changed files with 721268 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

41
Util/util_ini.py Normal file
View File

@ -0,0 +1,41 @@
import configparser
def writeFeedLine_to_ini(feedLine_dirt,file_path:str):
config = configparser.ConfigParser()
for key,value in feedLine_dirt.items():
config.add_section(key)
config.set(key,'name',value.name)
config.set(key,'SafePosition_x',str(value.safe_position.X))
config.set(key,'SafePosition_y',str(value.safe_position.Y))
config.set(key,'SafePosition_z',str(value.safe_position.Z))
config.set(key,'SafePosition_u',str(value.safe_position.U))
config.set(key,'SafePosition_v',str(value.safe_position.V))
config.set(key,'SafePosition_w',str(value.safe_position.W))
config.set(key, 'brokenposition1_x', str(value.broken1_position.X))
config.set(key, 'brokenposition1_y', str(value.broken1_position.Y))
config.set(key, 'brokenposition1_z', str(value.broken1_position.Z))
config.set(key, 'brokenposition1_u', str(value.broken1_position.U))
config.set(key, 'brokenposition1_v', str(value.broken1_position.V))
config.set(key, 'brokenposition1_w', str(value.broken1_position.W))
config.set(key, 'brokenposition2_x', str(value.broken2_position.X))
config.set(key, 'brokenposition2_y', str(value.broken2_position.Y))
config.set(key, 'brokenposition2_z', str(value.broken2_position.Z))
config.set(key, 'brokenposition2_u', str(value.broken2_position.U))
config.set(key, 'brokenposition2_v', str(value.broken2_position.V))
config.set(key, 'brokenposition2_w', str(value.broken2_position.W))
config.set(key,'ShakePosition_x',str(value.shake_position.X))
config.set(key,'ShakePosition_y',str(value.shake_position.Y))
config.set(key,'ShakePosition_z',str(value.shake_position.Z))
config.set(key,'ShakePosition_u',str(value.shake_position.U))
config.set(key,'ShakePosition_v',str(value.shake_position.V))
config.set(key,'ShakePosition_w',str(value.shake_position.W))
config.set(key,'DropBagPosition_x',str(value.drop_bag_position.X))
config.set(key,'DropBagPosition_y',str(value.drop_bag_position.Y))
config.set(key,'DropBagPosition_z',str(value.drop_bag_position.Z))
config.set(key,'DropBagPosition_u',str(value.drop_bag_position.U))
config.set(key,'DropBagPosition_v',str(value.drop_bag_position.V))
config.set(key,'DropBagPosition_w',str(value.drop_bag_position.W))
config.write(open(file_path,'w',encoding='utf-8'))
return True

10
Util/util_language.py Normal file
View File

@ -0,0 +1,10 @@
from PyQt5.QtCore import QTranslator, QLocale, QLibraryInfo
def show_translated_message_box(app):
# 加载翻译文件
translator = QTranslator()
locale = QLocale.system().name() # 获取系统语言
qt_translations_path = QLibraryInfo.path(QLibraryInfo.TranslationsPath)
translator.load(f"qtbase_{locale}", qt_translations_path)
app.installTranslator(translator)

103
Util/util_log.py Normal file
View File

@ -0,0 +1,103 @@
import logging
import queue
import threading
import time
from logging.handlers import TimedRotatingFileHandler
from PySide6.QtCore import Signal, QObject
class QTextEditLogger(logging.Handler):
def __init__(self, text_widget):
super().__init__()
self.widget = text_widget
def emit(self, record):
# 格式化日志信息
log_message = self.format(record)
# 在主线程中更新 QTextEdit
self.widget.append(log_message)
class Logger(QObject):
log_info_signal = Signal(str)
log_warning_signal = Signal(str)
log_error_signal = Signal(str)
def __init__(self):
super().__init__()
self.logger_textEdit_info = logging.getLogger('info_logger')
self.logger_textEdit_info.setLevel(logging.INFO)
self.logger_textEdit_warning = logging.getLogger('warning_logger')
self.logger_textEdit_warning.setLevel(logging.WARNING)
self.logger_file_info = logging.getLogger('file_logger')
self.logger_file_info.setLevel(logging.INFO)
self.pre_message = ''
self.lock = threading.Lock() # 创建锁
self.log_queue = queue.Queue()
self.logger_thread = threading.Thread(target=self._process_logs, daemon=True)
self.logger_thread.start()
def init_log(self,textEdit_info,textEdit_warning,file_path):
text_edit_handler = QTextEditLogger(textEdit_info)
formatter = logging.Formatter('%(asctime)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
text_edit_handler.setFormatter(formatter)
self.logger_textEdit_info.addHandler(text_edit_handler)
text_edit_handler_warning = QTextEditLogger(textEdit_warning)
formatter_warning = logging.Formatter('%(asctime)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
text_edit_handler_warning.setFormatter(formatter_warning)
self.logger_textEdit_warning.addHandler(text_edit_handler_warning)
handler = TimedRotatingFileHandler(file_path, when='D', interval=1, backupCount=30)
handler.suffix = "%Y-%m-%d"
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
handler.setFormatter(formatter)
self.logger_file_info.addHandler(handler)
def _process_logs(self):
while True:
time.sleep(0.1)
level, message = self.log_queue.get()
if level == logging.INFO:
self.log_info_signal.emit(message)
# self.logger_textEdit_info.info(message)
self.logger_file_info.info(message)
elif level == logging.ERROR:
# self.logger_textEdit_info.error(message)
self.logger_file_info.error(message)
# self.logger_textEdit_warning.error(message)
self.log_error_signal.emit(message)
elif level == logging.WARNING:
self.logger_file_info.warning(message)
self.log_warning_signal.emit(message)
def log_message(self,level,message):
self.log_queue.put((level, message))
return
try:
with self.lock: # 确保线程安全
if message == self.pre_message:
return
self.pre_message = message
if level == logging.INFO:
self.logger_textEdit_info.info(message)
#return
self.logger_file_info.info(message)
if level == logging.ERROR:
self.logger_textEdit_info.error(message)
self.logger_textEdit_warning.error(message)
self.logger_file_info.error(message)
if level == logging.WARNING:
#return
self.logger_file_info.warning(message)
except Exception as e:
print(e)
log = Logger()

14
Util/util_math.py Normal file
View File

@ -0,0 +1,14 @@
import math
def get_distance(p1, p2):
"""
计算两点间的距离
:param p1:
:param p2:
:return:
"""
return math.sqrt((p1.X - p2.X) ** 2 + (p1.Y - p2.Y) ** 2+ (p1.Z - p2.Z)**2)
def is_bit_set(n, position):
return (n >> position) & 1 == 1

45
Util/util_pic.py Normal file
View File

@ -0,0 +1,45 @@
import logging
import cv2
from PySide6.QtGui import QPixmap, QImage
from Util.util_log import log
def cv2_to_qpixmap(cv_img):
"""将OpenCV图像转换为QPixmap"""
# img = cv_img.copy()
# cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
try:
height, width, channel = cv_img.shape
bytes_per_line = channel * width
q_image = QImage(cv_img.data, width, height, bytes_per_line, QImage.Format_RGB888)
pixmap = QPixmap.fromImage(q_image)
return pixmap
except Exception as e:
print(e)
log.log_message(logging.ERROR,e)
return None
# def cv2_to_qpixmap(cv_img):
# """将OpenCV图像转换为QPixmap"""
# if len(cv_img.shape) !=3:
# print("cv_img.shape !=3")
# return None
# try:
# img = cv_img.copy()
# height, width, channel = img.shape
# bytes_per_line = 3 * width
# q_img = QImage(img.data, width, height, bytes_per_line, QImage.Format_RGB888)
# return QPixmap.fromImage(q_img)
# except Exception as e:
# log.log_message(logging.ERROR, e)
# return None
# def cv2_to_qpixmap(cv_img):
# #g = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
# height, width, channel = cv_img.shape
# bytes_per_line = 3 * width
# q_img = QImage(cv_img.data, width, height, bytes_per_line, QImage.Format_RGB888)
# return QPixmap.fromImage(q_img)

142
Util/util_time.py Normal file
View File

@ -0,0 +1,142 @@
import time
class MyTimer:
@staticmethod
def gMyGetTickCount():
ts = time.time()
return int(ts * 1000) # Convert to milliseconds
# CTon class equivalent in Python
class CTon:
def __init__(self):
self.m_unET = 0
self.m_bLastI = False
self.m_bIn = False
self.m_bPause = False
self.m_bOver = True
self.m_unPT = 0
self.m_unStartTime = 0
self.m_unPauseET = 0
def GetET(self):
if self.m_bIn:
nET = self.m_unPT + (self.m_unStartTime - MyTimer.gMyGetTickCount())
return max(nET, 0)
else:
return 0
def SetReset(self):
self.m_bIn = False
self.m_bLastI = False
self.m_bPause = False
def SetPause(self, value):
if self.m_bIn:
self.m_bPause = value
if self.m_bPause:
self.m_unPauseET = MyTimer.gMyGetTickCount() - self.m_unStartTime
def SetOver(self, value):
self.m_bOver = value
def GetStartTime(self):
return self.m_unStartTime
def Q(self, value_i, value_pt):
self.m_bIn = value_i
self.m_unPT = value_pt
un_tick = MyTimer.gMyGetTickCount()
if self.m_bOver and self.m_bIn:
self.m_unStartTime = un_tick - self.m_unPT
self.m_bOver = False
if self.m_bPause and self.m_bIn:
self.m_unStartTime = un_tick - self.m_unPauseET
if self.m_bIn != self.m_bLastI:
self.m_bLastI = self.m_bIn
if self.m_bIn:
self.m_unStartTime = un_tick
self.m_bPause = False
return self.m_bIn and (un_tick >= (self.m_unStartTime + self.m_unPT))
# CClockPulse class equivalent in Python
class CClockPulse:
def __init__(self):
self.m_bFirstOut = True
self.m_bTonAOut = False
self.m_bTonBOut = False
self.m_cTonA = CTon()
self.m_cTonB = CTon()
def Q(self, value_i, run_time, stop_time):
if self.m_bFirstOut:
self.m_bTonAOut = self.m_cTonA.Q(not self.m_bTonBOut and value_i, run_time)
self.m_bTonBOut = self.m_cTonB.Q(self.m_bTonAOut and value_i, stop_time)
return not self.m_bTonAOut and value_i
else:
self.m_bTonAOut = self.m_cTonA.Q(not self.m_bTonBOut and value_i, stop_time)
self.m_bTonBOut = self.m_cTonB.Q(self.m_bTonAOut and value_i, run_time)
return self.m_bTonAOut and value_i
# CDelayOut class equivalent in Python
class CDelayOut:
def __init__(self):
self.m_cOutTon = CTon()
self.m_cmWaitTon = CTon()
def Reset(self):
self.m_cOutTon.SetReset()
self.m_cmWaitTon.SetReset()
def Q(self, value_i, wait_time, out_time):
if self.m_cmWaitTon.Q(value_i, wait_time):
if self.m_cOutTon.Q(True, out_time):
self.m_cOutTon.SetReset()
self.m_cmWaitTon.SetReset()
value_i = False
return False
return True
return False
# CRisOrFall class equivalent in Python
class CRisOrFall:
def __init__(self):
self.m_bTemp = False
def Q(self, value_i, ris_or_fall):
result = False
if value_i != self.m_bTemp:
if ris_or_fall and value_i: # Rising edge
result = True
if not ris_or_fall and not value_i: # Falling edge
result = True
self.m_bTemp = value_i
return result
# CTof class equivalent in Python
class CTof:
def __init__(self):
self.m_cDelayTon = CTon()
self.m_bValue = False
self.m_cRis = CRisOrFall()
def SetReset(self):
self.m_bValue = False
self.m_cDelayTon.SetReset()
def Q(self, value_i, delay_time):
if self.m_cRis.Q(value_i, False):
self.m_cDelayTon.SetReset()
self.m_bValue = True
if self.m_cDelayTon.Q(self.m_bValue, delay_time):
self.m_bValue = False
self.m_cDelayTon.SetReset()
return value_i or self.m_bValue
# Utility function
def gGetNowTime():
return int(time.time())