完善耐久采集

This commit is contained in:
gitea 2025-04-07 10:38:59 +08:00
parent 671db5b1db
commit 6e547ca6a3
16 changed files with 341 additions and 387 deletions

2
.gitignore vendored
View File

@ -3,5 +3,5 @@ venv/
**/__pycache__/ **/__pycache__/
assets/files/examples/ assets/files/examples/
assets/logs/* assets/logs/*
test.py codes/durable/curves_draw.py
package/* package/*

127
aio.py
View File

@ -7,10 +7,10 @@ import sys
import time import time
from urllib import request from urllib import request
import os.path import os.path
import matplotlib # import matplotlib
import matplotlib.pyplot as plt # import matplotlib.pyplot as plt
import pandas # import pandas
from matplotlib.widgets import Slider # from matplotlib.widgets import Slider
from PySide6.QtCore import Qt, QThread, Signal, QObject, QTimer from PySide6.QtCore import Qt, QThread, Signal, QObject, QTimer
from PySide6.QtGui import QTextCursor, QFont, QPixmap, QColor, QBrush, QIcon from PySide6.QtGui import QTextCursor, QFont, QPixmap, QColor, QBrush, QIcon
@ -21,8 +21,8 @@ import codes.common.openapi as openapi
import codes.ui.main_window as main_window import codes.ui.main_window as main_window
from codes.analysis import brake, current, wavelogger, iso from codes.analysis import brake, current, wavelogger, iso
from codes.autotest import do_current, do_brake from codes.autotest import do_current, do_brake
from codes.durable import factory_test from codes.durable import factory_test, curves_draw
matplotlib.use('QtAgg') # matplotlib.use('QtAgg')
class ContentDialog(QDialog): class ContentDialog(QDialog):
@ -30,36 +30,21 @@ class ContentDialog(QDialog):
super().__init__(parent) super().__init__(parent)
self.setWindowTitle("日志详情") self.setWindowTitle("日志详情")
self.setGeometry(100, 100, 700, 300) self.setGeometry(100, 100, 700, 300)
# 设置对话框在屏幕正中间
self.center_on_screen() self.center_on_screen()
# 创建布局
layout = QVBoxLayout(self) layout = QVBoxLayout(self)
# 创建 QPlainTextEdit 并设置为只读
self.plain_text_edit = QPlainTextEdit() self.plain_text_edit = QPlainTextEdit()
self.plain_text_edit.setReadOnly(True) self.plain_text_edit.setReadOnly(True)
self.plain_text_edit.setPlainText(content) self.plain_text_edit.setPlainText(content)
# 添加到布局
layout.addWidget(self.plain_text_edit) layout.addWidget(self.plain_text_edit)
def center_on_screen(self): def center_on_screen(self):
# 获取屏幕尺寸
screen_geometry = QApplication.primaryScreen().geometry() screen_geometry = QApplication.primaryScreen().geometry()
screen_width = screen_geometry.width() screen_width = screen_geometry.width()
screen_height = screen_geometry.height() screen_height = screen_geometry.height()
# 获取对话框尺寸
dialog_width = self.width() dialog_width = self.width()
dialog_height = self.height() dialog_height = self.height()
# 计算位置
x = (screen_width - dialog_width) // 2 x = (screen_width - dialog_width) // 2
y = (screen_height - dialog_height) // 2 y = (screen_height - dialog_height) // 2
# 设置位置
self.move(x, y) self.move(x, y)
@ -227,81 +212,9 @@ class MainWindow(main_window.Ui_MainWindow):
idx_dict[tab_index].setText(dir_path) idx_dict[tab_index].setText(dir_path)
def curve_draw(self): def curve_draw(self):
procs = self.get_checkbox_states() window = curves_draw.ChartWindow(self.le_durable_path.text(), self.get_checkbox_states())
dir_path = self.le_durable_path.text() window.setWindowModality(Qt.WindowModality.ApplicationModal)
curve_map = { window.show()
"周期内平均转矩": ["device_servo_trq_feedback", ],
"周期内最大速度": ["hw_joint_vel_feedback", ],
}
ylabels = {"周期内最大速度": "速度(rad/s)", "周期内平均转矩": "转矩(Nm)"}
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['figure.dpi'] = 100
plt.rcParams['font.size'] = 14
plt.rcParams['lines.marker'] = 'o'
plt.rcParams["figure.autolayout"] = True
if not os.path.exists(dir_path):
self.w2t(f"数据文件夹{dir_path}不存在,请确认后重试......", "red")
return
for proc_name, is_enabled in procs.items():
if is_enabled:
break
else:
self.w2t(f"需要选择至少一个功能,才能继续绘图......", "red")
return
_, files = clibs.traversal_files(dir_path)
csv_files = []
for file in files:
if file.endswith(".csv"):
csv_files.append(file)
if len(csv_files) == 0:
self.w2t("程序未开始运行,暂无数据可以展示......", "red")
return
for proc_name, is_enabled in procs.items():
if not is_enabled:
continue
title = proc_name
ylabel = ylabels[proc_name]
fig, axes = plt.subplots(figsize=(10, 4.5), dpi=100)
for curve in curve_map[proc_name]:
cols = [f"{curve}_{i}" for i in range(6)]
cols.insert(0, "time")
try:
df = pandas.read_csv(f"{dir_path}/{proc_name}.csv")
except Exception as err:
self.w2t(f"获取{dir_path}/{proc_name}.csv文件数据失败需确认是否存在该文件......", "red")
self.w2t(f"报错信息:{err}", "red")
return
for i in range((len(cols) - 1) // 6):
plt.plot(df[cols[1]], label=f"一轴{curve_map[proc_name][i]}")
plt.plot(df[cols[2]], label=f"二轴{curve_map[proc_name][i]}")
plt.plot(df[cols[3]], label=f"三轴{curve_map[proc_name][i]}")
plt.plot(df[cols[4]], label=f"四轴{curve_map[proc_name][i]}")
plt.plot(df[cols[5]], label=f"五轴{curve_map[proc_name][i]}")
plt.plot(df[cols[6]], label=f"六轴{curve_map[proc_name][i]}")
axes.set_title(title)
axes.set_ylabel(ylabel)
axes.legend(loc="upper right")
slider_position = plt.axes((0.1, 0.01, 0.8, 0.05), facecolor="blue") # (left, bottom, width, height)
scrollbar = Slider(slider_position, 'Time', 1, int(len(df)), valstep=1)
def update(val):
pos = scrollbar.val
axes.set_xlim([pos, pos + 10])
fig.canvas.draw_idle()
scrollbar.on_changed(update)
fig.tight_layout(rect=(0, 0.02, 0.96, 1)) # tuple (left, bottom, right, top)
plt.show()
def durable_cb_change(self): def durable_cb_change(self):
stat = True if self.cb_durable_total.isChecked() else False stat = True if self.cb_durable_total.isChecked() else False
@ -982,17 +895,17 @@ class MainWindow(main_window.Ui_MainWindow):
info_text = "当前有程序正在停止中,确认退出?" if clibs.stop_flag else info_text info_text = "当前有程序正在停止中,确认退出?" if clibs.stop_flag else info_text
reply = QMessageBox.question(self, "退出", info_text) reply = QMessageBox.question(self, "退出", info_text)
if reply == QMessageBox.Yes: if reply == QMessageBox.Yes:
os.chdir(clibs.log_path) # os.chdir(clibs.log_path)
t = datetime.datetime.now().strftime("%Y%m%d%H%M%S") # t = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
disk_conn = sqlite3.connect(f"log_{t}.db", isolation_level=None, check_same_thread=False, cached_statements=256) # disk_conn = sqlite3.connect(f"log_{t}.db", isolation_level=None, check_same_thread=False, cached_statements=256)
#
clibs.conn.backup(target=disk_conn, pages=1, progress=None) # clibs.conn.backup(target=disk_conn, pages=1, progress=None)
#
_, logs = clibs.traversal_files(".") # _, logs = clibs.traversal_files(".")
logs.sort() # logs.sort()
while len(logs) > 10: # while len(logs) > 10:
_ = logs.pop(0) # _ = logs.pop(0)
os.remove(_) # os.remove(_)
if clibs.status["md"] == 1: if clibs.status["md"] == 1:
self.run_program_thread(clibs.c_md.close, -99, self.prog_done_disconn, "md") self.run_program_thread(clibs.c_md.close, -99, self.prog_done_disconn, "md")

View File

@ -6,8 +6,8 @@ VSVersionInfo(
ffi=FixedFileInfo( ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0. # Set not needed items to zero 0.
filevers=(0, 4, 0, 1), filevers=(0, 4, 0, 2),
prodvers=(0, 4, 0, 1), prodvers=(0, 4, 0, 2),
# Contains a bitmask that specifies the valid bits 'flags'r # Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f, mask=0x3f,
# Contains a bitmask that specifies the Boolean attributes of the file. # Contains a bitmask that specifies the Boolean attributes of the file.
@ -31,12 +31,12 @@ VSVersionInfo(
'040904b0', '040904b0',
[StringStruct('CompanyName', 'Rokae - https://www.rokae.com/'), [StringStruct('CompanyName', 'Rokae - https://www.rokae.com/'),
StringStruct('FileDescription', 'All in one automatic toolbox'), StringStruct('FileDescription', 'All in one automatic toolbox'),
StringStruct('FileVersion', '0.4.0.1 (2025-03-30)'), StringStruct('FileVersion', '0.4.0.2 (2025-04-07)'),
StringStruct('InternalName', 'AIO.exe'), StringStruct('InternalName', 'AIO.exe'),
StringStruct('LegalCopyright', '© 2024-2025 Manford Fan'), StringStruct('LegalCopyright', '© 2024-2025 Manford Fan'),
StringStruct('OriginalFilename', 'AIO.exe'), StringStruct('OriginalFilename', 'AIO.exe'),
StringStruct('ProductName', 'AIO'), StringStruct('ProductName', 'AIO'),
StringStruct('ProductVersion', '0.4.0.1 (2025-03-30)')]) StringStruct('ProductVersion', '0.4.0.2 (2025-04-07)')])
]), ]),
VarFileInfo([VarStruct('Translation', [1033, 1200])]) VarFileInfo([VarStruct('Translation', [1033, 1200])])
] ]

View File

@ -1 +1 @@
0.4.0.1@03/30/2025 0.4.0.2@04/07/2025

View File

@ -1 +1 @@
0.4.0.1@03/30/2025 0.4.0.2@04/07/2025

View File

@ -48,3 +48,42 @@ QPushButton[objectName^="btn"]:pressed {
/* ------------------------------------------- QStatusBar -------------------------------------------*/ /* ------------------------------------------- QStatusBar -------------------------------------------*/
QStatusBar::item { border: 0px; } QStatusBar::item { border: 0px; }
/* ------------------------------------------- QSlider -------------------------------------------*/
QSlider {
min-height: 40px; /* 控制滑块控件最小高度 */
background: transparent;
}
/* ===== 滑条轨道 ===== */
QSlider::groove:horizontal {
background: #E0E0E0;
height: 8px; /* 轨道高度 */
border-radius: 4px;
}
/* ===== 已滑过的轨道部分 ===== */
QSlider::sub-page:horizontal {
background: #2196F3; /* 进度颜色 */
border-radius: 4px;
}
/* ===== 滑块手柄 ===== */
QSlider::handle:horizontal {
background: #FFFFFF;
border: 2px solid #2196F3;
width: 10px; /* 滑块宽度 */
height: 20px; /* 滑块高度 */
margin: -8px 0; /* 调整滑块在轨道上的位置 */
border-radius: 5px;
}
/* ===== 悬停/按下状态 ===== */
QSlider::handle:horizontal:hover {
background: #E3F2FD;
}
QSlider::handle:horizontal:pressed {
background: #BBDEFB;
}

View File

@ -13,7 +13,6 @@ class BrakeDataProcess(QThread):
super().__init__() super().__init__()
self.dir_path = dir_path self.dir_path = dir_path
self.idx = 0 self.idx = 0
self.logger = clibs.logger
def check_files(self, rawdata_dirs, result_files): def check_files(self, rawdata_dirs, result_files):
msg_wrong = "需要有四个文件和若干个数据文件夹,可参考如下确认:<br>" msg_wrong = "需要有四个文件和若干个数据文件夹,可参考如下确认:<br>"
@ -21,7 +20,7 @@ class BrakeDataProcess(QThread):
msg_wrong += "- reach33_load33_speed33<br>- reach33_load33_speed66<br>...<br>- reach100_load100_speed66<br>- reach100_load100_speed100<br>" msg_wrong += "- reach33_load33_speed33<br>- reach33_load33_speed66<br>...<br>- reach100_load100_speed66<br>- reach100_load100_speed100<br>"
if len(result_files) != 4 or len(rawdata_dirs) == 0: if len(result_files) != 4 or len(rawdata_dirs) == 0:
self.logger("ERROR", "brake", msg_wrong, "red") clibs.logger("ERROR", "brake", msg_wrong, "red")
config_file, reach33_file, reach66_file, reach100_file = None, None, None, None config_file, reach33_file, reach66_file, reach100_file = None, None, None, None
for result_file in result_files: for result_file in result_files:
@ -36,7 +35,7 @@ class BrakeDataProcess(QThread):
reach100_file = result_file reach100_file = result_file
else: else:
if not (config_file and reach33_file and reach66_file and reach100_file): if not (config_file and reach33_file and reach66_file and reach100_file):
self.logger("ERROR", "brake", msg_wrong, "red") clibs.logger("ERROR", "brake", msg_wrong, "red")
reach_s = ['reach33', 'reach66', 'reach100'] reach_s = ['reach33', 'reach66', 'reach100']
load_s = ['load33', 'load66', 'load100'] load_s = ['load33', 'load66', 'load100']
@ -49,24 +48,24 @@ class BrakeDataProcess(QThread):
msg = f"报错信息:数据目录 {rawdata_dir} 命名不合规,请参考如下形式<br>" msg = f"报错信息:数据目录 {rawdata_dir} 命名不合规,请参考如下形式<br>"
msg += "命名规则reachAA_loadBB_speedCCAA/BB/CC 指的是臂展/负载/速度的比例<br>" msg += "命名规则reachAA_loadBB_speedCCAA/BB/CC 指的是臂展/负载/速度的比例<br>"
msg += "规则解释reach66_load100_speed33表示 66% 臂展100% 负载以及 33% 速度情况下的测试结果文件夹<br>" msg += "规则解释reach66_load100_speed33表示 66% 臂展100% 负载以及 33% 速度情况下的测试结果文件夹<br>"
self.logger("ERROR", "brake", msg, "red") clibs.logger("ERROR", "brake", msg, "red")
_, rawdata_files = clibs.traversal_files(rawdata_dir) _, rawdata_files = clibs.traversal_files(rawdata_dir)
if len(rawdata_files) != 3: if len(rawdata_files) != 3:
msg = f"数据目录 {rawdata_dir} 下数据文件个数错误,每个数据目录下有且只能有三个以 .data 为后缀的数据文件" msg = f"数据目录 {rawdata_dir} 下数据文件个数错误,每个数据目录下有且只能有三个以 .data 为后缀的数据文件"
self.logger("ERROR", "brake", msg, "red") clibs.logger("ERROR", "brake", msg, "red")
for rawdata_file in rawdata_files: for rawdata_file in rawdata_files:
if not rawdata_file.endswith(".data"): if not rawdata_file.endswith(".data"):
msg = f"数据文件 {rawdata_file} 后缀错误,每个数据目录下有且只能有三个以 .data 为后缀的数据文件" msg = f"数据文件 {rawdata_file} 后缀错误,每个数据目录下有且只能有三个以 .data 为后缀的数据文件"
self.logger("ERROR", "brake", msg, "red") clibs.logger("ERROR", "brake", msg, "red")
result_files = [] result_files = []
for _ in [reach33_file, reach66_file, reach100_file]: for _ in [reach33_file, reach66_file, reach100_file]:
if _.split("/")[-1].split("_")[0] in set(prefix): if _.split("/")[-1].split("_")[0] in set(prefix):
result_files.append(_) result_files.append(_)
self.logger("INFO", "brake", "数据目录合规性检查结束,未发现问题......", "green") clibs.logger("INFO", "brake", "数据目录合规性检查结束,未发现问题......", "green")
return config_file, result_files return config_file, result_files
def get_configs(self, config_file): def get_configs(self, config_file):
@ -76,7 +75,7 @@ class BrakeDataProcess(QThread):
p_dir = config_file.split('/')[-2] p_dir = config_file.split('/')[-2]
if not re.match("^[jJ][123]$", p_dir): if not re.match("^[jJ][123]$", p_dir):
self.logger("ERROR", "brake", "被处理的根文件夹命名必须是 [Jj][123] 的格式", "red") clibs.logger("ERROR", "brake", "被处理的根文件夹命名必须是 [Jj][123] 的格式", "red")
axis = int(p_dir[-1]) # 要处理的轴 axis = int(p_dir[-1]) # 要处理的轴
rrs = [abs(_) for _ in configs["TRANSMISSION"]["REDUCTION_RATIO_NUMERATOR"]] # 减速比rr for reduction ratio rrs = [abs(_) for _ in configs["TRANSMISSION"]["REDUCTION_RATIO_NUMERATOR"]] # 减速比rr for reduction ratio
@ -85,19 +84,19 @@ class BrakeDataProcess(QThread):
av = avs[axis-1] av = avs[axis-1]
return av, rr return av, rr
except Exception as Err: except Exception as Err:
self.logger("ERROR", "brake", f"无法打开 {config_file},或者使用了错误的机型配置文件,需检查<br>{Err}", "red") clibs.logger("ERROR", "brake", f"无法打开 {config_file},或者使用了错误的机型配置文件,需检查<br>{Err}", "red")
def now_doing_msg(self, docs, flag): def now_doing_msg(self, docs, flag):
now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
file_type = 'file' if os.path.isfile(docs) else 'dir' file_type = 'file' if os.path.isfile(docs) else 'dir'
if flag == 'start' and file_type == 'dir': if flag == 'start' and file_type == 'dir':
self.logger("INFO", "brake", f"[{now}] 正在处理目录 {docs} 中的数据......") clibs.logger("INFO", "brake", f"[{now}] 正在处理目录 {docs} 中的数据......")
elif flag == 'start' and file_type == 'file': elif flag == 'start' and file_type == 'file':
self.logger("INFO", "brake", f"[{now}] 正在处理文件 {docs} 中的数据......") clibs.logger("INFO", "brake", f"[{now}] 正在处理文件 {docs} 中的数据......")
elif flag == 'done' and file_type == 'dir': elif flag == 'done' and file_type == 'dir':
self.logger("INFO", "brake", f"[{now}] 目录 {docs} 数据文件已处理完毕") clibs.logger("INFO", "brake", f"[{now}] 目录 {docs} 数据文件已处理完毕")
elif flag == 'done' and file_type == 'file': elif flag == 'done' and file_type == 'file':
self.logger("INFO", "brake", f"[{now}] 文件 {docs} 数据已处理完毕") clibs.logger("INFO", "brake", f"[{now}] 文件 {docs} 数据已处理完毕")
@staticmethod @staticmethod
def data2result(df, ws_result, row_start, row_end): def data2result(df, ws_result, row_start, row_end):
@ -131,7 +130,7 @@ class BrakeDataProcess(QThread):
row_start = row - 20 if row - 20 > 0 else 0 # 急停前找 20 个点 row_start = row - 20 if row - 20 > 0 else 0 # 急停前找 20 个点
break break
else: else:
self.logger("ERROR", "brake", f"数据文件 {data_file} 采集的数据中没有 ESTOP 为非 0 的情况,需要确认", "red") clibs.logger("ERROR", "brake", f"数据文件 {data_file} 采集的数据中没有 ESTOP 为非 0 的情况,需要确认", "red")
for row in range(row_start, df.index[-1] - 1, 10): for row in range(row_start, df.index[-1] - 1, 10):
speed_row = df.iloc[row, 0] * clibs.RADIAN * rr * 60 / 360 speed_row = df.iloc[row, 0] * clibs.RADIAN * rr * 60 / 360
@ -139,13 +138,13 @@ class BrakeDataProcess(QThread):
row_end = row + 100 if row + 100 <= df.index[-1] - 1 else df.index[-1] - 1 row_end = row + 100 if row + 100 <= df.index[-1] - 1 else df.index[-1] - 1
break break
else: else:
self.logger("ERROR", "brake", f"数据文件 {data_file} 最后的速度未降为零", "red") clibs.logger("ERROR", "brake", f"数据文件 {data_file} 最后的速度未降为零", "red")
av_estop = abs(df.iloc[row_start - 20:row_start, 0].abs().mean() * clibs.RADIAN) av_estop = abs(df.iloc[row_start - 20:row_start, 0].abs().mean() * clibs.RADIAN)
if abs(av_estop / av_max) < threshold: if abs(av_estop / av_max) < threshold:
filename = data_file.split("/")[-1] filename = data_file.split("/")[-1]
msg = f"[av_estop: {av_estop:.2f} | shouldbe: {av_max:.2f}] 数据文件 {filename} 触发 ESTOP 时未采集到指定百分比的最大速度,需要检查" msg = f"[av_estop: {av_estop:.2f} | shouldbe: {av_max:.2f}] 数据文件 {filename} 触发 ESTOP 时未采集到指定百分比的最大速度,需要检查"
self.logger("WARNING", "brake", msg, "#8A2BE2") clibs.logger("WARNING", "brake", msg, "#8A2BE2")
return row_start, row_end return row_start, row_end
@ -169,11 +168,11 @@ class BrakeDataProcess(QThread):
def data_process(self, result_file, rawdata_dirs, av, rr): def data_process(self, result_file, rawdata_dirs, av, rr):
filename = result_file.split("/")[-1] filename = result_file.split("/")[-1]
self.logger("INFO", "brake", f"正在打开文件 {filename},这可能需要一些时间......", "blue") clibs.logger("INFO", "brake", f"正在打开文件 {filename},这可能需要一些时间......", "blue")
try: try:
wb = openpyxl.load_workbook(result_file) wb = openpyxl.load_workbook(result_file)
except Exception as Err: except Exception as Err:
self.logger("ERROR", "brake", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!<br>{Err}", "red") clibs.logger("ERROR", "brake", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!<br>{Err}", "red")
prefix = filename.split('_')[0] prefix = filename.split('_')[0]
for rawdata_dir in rawdata_dirs: for rawdata_dir in rawdata_dirs:
@ -191,7 +190,7 @@ class BrakeDataProcess(QThread):
# [t.join() for t in threads] # [t.join() for t in threads]
self.now_doing_msg(rawdata_dir, 'done') self.now_doing_msg(rawdata_dir, 'done')
self.logger("INFO", "brake", f"正在保存文件 {filename},这可能需要一些时间......<br>", "blue") clibs.logger("INFO", "brake", f"正在保存文件 {filename},这可能需要一些时间......<br>", "blue")
wb.save(result_file) wb.save(result_file)
wb.close() wb.close()
@ -206,7 +205,7 @@ class BrakeDataProcess(QThread):
for result_file in result_files: for result_file in result_files:
self.data_process(result_file, rawdata_dirs, av, rr) self.data_process(result_file, rawdata_dirs, av, rr)
self.logger("INFO", "brake", "-"*60 + "<br>全部处理完毕<br>", "purple") clibs.logger("INFO", "brake", "-"*60 + "<br>全部处理完毕<br>", "purple")
time_total = time.time() - time_start time_total = time.time() - time_start
msg = f"处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s" msg = f"处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s"
self.logger("INFO", "brake", msg) clibs.logger("INFO", "brake", msg)

View File

@ -14,7 +14,6 @@ class CurrentDataProcess(QThread):
self.dir_path = dir_path self.dir_path = dir_path
self.proc = proc self.proc = proc
self.idx = 1 self.idx = 1
self.logger = clibs.logger
def initialization(self): def initialization(self):
_, data_files = clibs.traversal_files(self.dir_path) _, data_files = clibs.traversal_files(self.dir_path)
@ -30,16 +29,16 @@ class CurrentDataProcess(QThread):
if not re.match("^j[1-7].*\\.data$", filename): if not re.match("^j[1-7].*\\.data$", filename):
msg = f"不合规 {data_file}<br>" msg = f"不合规 {data_file}<br>"
msg += "所有数据文件必须以 j[1-7]_ 开头,以 .data 结尾比如j1_abcdef.data请检查整改后重新运行" msg += "所有数据文件必须以 j[1-7]_ 开头,以 .data 结尾比如j1_abcdef.data请检查整改后重新运行"
self.logger("ERROR", "current", msg, "red") clibs.logger("ERROR", "current", msg, "red")
if count != 2: if count != 2:
msg = "需要有一个机型配置文件\"*.cfg\",以及一个数据处理文件\"T_电机电流.xlsx\"表格,请检查整改后重新运行" msg = "需要有一个机型配置文件\"*.cfg\",以及一个数据处理文件\"T_电机电流.xlsx\"表格,请检查整改后重新运行"
self.logger("ERROR", "current", msg, "red") clibs.logger("ERROR", "current", msg, "red")
return data_files, config_file return data_files, config_file
def current_max(self, data_files, rts): def current_max(self, data_files, rts):
self.logger("INFO", "current", f"正在处理最大转矩值逻辑......") clibs.logger("INFO", "current", f"正在处理最大转矩值逻辑......")
current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []} current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []}
for data_file in data_files: for data_file in data_files:
if data_file.endswith(".data"): if data_file.endswith(".data"):
@ -47,11 +46,11 @@ class CurrentDataProcess(QThread):
else: else:
continue continue
self.logger("DEBUG", "current", f"正在处理 {data_file} ...") clibs.logger("DEBUG", "current", f"正在处理 {data_file} ...")
cols = len(df.columns) cols = len(df.columns)
axis = int(data_file.split("/")[-1].split("_")[0].removeprefix("j")) axis = int(data_file.split("/")[-1].split("_")[0].removeprefix("j"))
rt = rts[axis-1] rt = rts[axis-1]
self.logger("DEBUG", "current", f"最大列数为 {cols}{axis} 轴的额定转矩为 {rt}") clibs.logger("DEBUG", "current", f"最大列数为 {cols}{axis} 轴的额定转矩为 {rt}")
col = df.columns.values[clibs.c_servo_trq-1] # 获取 "device_servo_trq_feedback" col = df.columns.values[clibs.c_servo_trq-1] # 获取 "device_servo_trq_feedback"
c_max = df[col].abs().max() c_max = df[col].abs().max()
@ -59,8 +58,8 @@ class CurrentDataProcess(QThread):
scale = 1000 scale = 1000
_ = abs(c_max/scale*rt) _ = abs(c_max/scale*rt)
current[axis].append(_) current[axis].append(_)
self.logger("DEBUG", "current", f"{data_file}: {_:.2f}") clibs.logger("DEBUG", "current", f"{data_file}: {_:.2f}")
self.logger("DEBUG", "current", f"获取到的列名为 {col},最大转矩为 {_}") clibs.logger("DEBUG", "current", f"获取到的列名为 {col},最大转矩为 {_}")
with open(data_file, "a+") as f_data: with open(data_file, "a+") as f_data:
csv_writer = csv.writer(f_data, delimiter="\t") csv_writer = csv.writer(f_data, delimiter="\t")
@ -73,14 +72,14 @@ class CurrentDataProcess(QThread):
_ = "" _ = ""
for value in cur: for value in cur:
_ += f"{value:.4f} " _ += f"{value:.4f} "
self.logger("INFO", "current", f"{axis}轴最大转矩数据:{_}") clibs.logger("INFO", "current", f"{axis}轴最大转矩数据:{_}")
self.logger("DEBUG", "current", f"获取最大转矩值结束 current_max = {current}") clibs.logger("DEBUG", "current", f"获取最大转矩值结束 current_max = {current}")
self.logger("INFO", "current", f"最大转矩数据处理完毕......") clibs.logger("INFO", "current", f"最大转矩数据处理完毕......")
return current return current
def current_avg(self, data_files, rts): def current_avg(self, data_files, rts):
self.logger("INFO", "current", f"正在处理平均转矩值逻辑......") clibs.logger("INFO", "current", f"正在处理平均转矩值逻辑......")
current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []} current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []}
for data_file in data_files: for data_file in data_files:
if data_file.endswith(".data"): if data_file.endswith(".data"):
@ -88,11 +87,11 @@ class CurrentDataProcess(QThread):
else: else:
continue continue
self.logger("DEBUG", "current", f"正在处理 {data_file} ...") clibs.logger("DEBUG", "current", f"正在处理 {data_file} ...")
cols = len(df.columns) cols = len(df.columns)
axis = int(data_file.split("/")[-1].split("_")[0].removeprefix("j")) axis = int(data_file.split("/")[-1].split("_")[0].removeprefix("j"))
rt = rts[axis-1] rt = rts[axis-1]
self.logger("DEBUG", "current", f"最大列数为 {cols}{axis} 轴的额定转矩为 {rt}") clibs.logger("DEBUG", "current", f"最大列数为 {cols}{axis} 轴的额定转矩为 {rt}")
col = df.columns.values[clibs.c_servo_trq-1] col = df.columns.values[clibs.c_servo_trq-1]
c_std = df[col].std() c_std = df[col].std()
@ -101,8 +100,8 @@ class CurrentDataProcess(QThread):
scale = 1000 scale = 1000
_ = (abs(c_avg)+c_std*3)/scale*rt _ = (abs(c_avg)+c_std*3)/scale*rt
current[axis].append(_) current[axis].append(_)
self.logger("DEBUG", "current", f"{data_file}: {_:.2f}") clibs.logger("DEBUG", "current", f"{data_file}: {_:.2f}")
self.logger("DEBUG", "current", f"获取到的列名为 {col},平均转矩为 {_}") clibs.logger("DEBUG", "current", f"获取到的列名为 {col},平均转矩为 {_}")
with open(data_file, "a+") as f_data: with open(data_file, "a+") as f_data:
csv_writer = csv.writer(f_data, delimiter="\t") csv_writer = csv.writer(f_data, delimiter="\t")
@ -115,10 +114,10 @@ class CurrentDataProcess(QThread):
_ = "" _ = ""
for value in cur: for value in cur:
_ += f"{value:.4f} " _ += f"{value:.4f} "
self.logger("INFO", "current", f"{axis}轴平均转矩数据:{_}") clibs.logger("INFO", "current", f"{axis}轴平均转矩数据:{_}")
self.logger("DEBUG", "current", f"获取平均转矩值结束 current_avg = {current}") clibs.logger("DEBUG", "current", f"获取平均转矩值结束 current_avg = {current}")
self.logger("INFO", "current", f"平均转矩数据处理完毕......") clibs.logger("INFO", "current", f"平均转矩数据处理完毕......")
return current return current
def current_cycle(self, data_files, rrs, rts, params): def current_cycle(self, data_files, rrs, rts, params):
@ -136,11 +135,11 @@ class CurrentDataProcess(QThread):
single.append(data_file) single.append(data_file)
clibs.stop, filename = True, result.split("/")[-1] clibs.stop, filename = True, result.split("/")[-1]
self.logger("INFO", "current", f"正在打开文件 {filename},这可能需要一些时间......", "blue") clibs.logger("INFO", "current", f"正在打开文件 {filename},这可能需要一些时间......", "blue")
try: try:
wb = openpyxl.load_workbook(result) wb = openpyxl.load_workbook(result)
except Exception as err: except Exception as err:
self.logger("ERROR", "current", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!<br>{err}", "red") clibs.logger("ERROR", "current", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!<br>{err}", "red")
ws = wb["统计"] ws = wb["统计"]
for idx in range(len(params)-1): for idx in range(len(params)-1):
@ -160,7 +159,7 @@ class CurrentDataProcess(QThread):
else: else:
self.p_scenario(wb, scenario, rrs, dur_time) self.p_scenario(wb, scenario, rrs, dur_time)
self.logger("INFO", "current", f"正在保存文件 {filename},这可能需要一些时间......", "blue") clibs.logger("INFO", "current", f"正在保存文件 {filename},这可能需要一些时间......", "blue")
wb.save(result) wb.save(result)
wb.close() wb.close()
@ -177,10 +176,10 @@ class CurrentDataProcess(QThread):
# 从实际数据看,这开逻辑很小概率能触发到 # 从实际数据看,这开逻辑很小概率能触发到
speed_avg = df.iloc[row_s-end_point*skip_scale:row_e-end_point*skip_scale].abs().mean() speed_avg = df.iloc[row_s-end_point*skip_scale:row_e-end_point*skip_scale].abs().mean()
if speed_avg < threshold: if speed_avg < threshold:
self.logger("WARNING", "current", f"【lt】{axis} 轴第 {seq} 次查找数据可能有异常row_s = {row_s}, row_e = {row_e}", "purple") clibs.logger("WARNING", "current", f"【lt】{axis} 轴第 {seq} 次查找数据可能有异常row_s = {row_s}, row_e = {row_e}", "purple")
return row_s, row_e return row_s, row_e
else: else:
self.logger("ERROR", "current", f"{data_file} 数据有误,需要检查,无法找到第 {seq} 个有效点......", "red") clibs.logger("ERROR", "current", f"{data_file} 数据有误,需要检查,无法找到第 {seq} 个有效点......", "red")
elif flag == "gt": elif flag == "gt":
while row_e > end_point: while row_e > end_point:
speed_avg = df.iloc[row_s:row_e].abs().mean() speed_avg = df.iloc[row_s:row_e].abs().mean()
@ -193,10 +192,10 @@ class CurrentDataProcess(QThread):
# 从实际数据看,这开逻辑很小概率能触发到 # 从实际数据看,这开逻辑很小概率能触发到
speed_avg = df.iloc[row_s-end_point*skip_scale:row_e-end_point*skip_scale].abs().mean() speed_avg = df.iloc[row_s-end_point*skip_scale:row_e-end_point*skip_scale].abs().mean()
if speed_avg > threshold: if speed_avg > threshold:
self.logger("WARNING", "current", f"【gt】{axis} 轴第 {seq} 次查找数据可能有异常row_s = {row_s}, row_e = {row_e}", "purple") clibs.logger("WARNING", "current", f"【gt】{axis} 轴第 {seq} 次查找数据可能有异常row_s = {row_s}, row_e = {row_e}", "purple")
return row_s, row_e return row_s, row_e
else: else:
self.logger("ERROR", "current", f"{data_file} 数据有误,需要检查,无法找到第 {seq} 个有效点......", "red") clibs.logger("ERROR", "current", f"{data_file} 数据有误,需要检查,无法找到第 {seq} 个有效点......", "red")
def get_row_number(self, threshold, flag, df, row_s, row_e, axis): def get_row_number(self, threshold, flag, df, row_s, row_e, axis):
count_1, count_2 = 0, 0 count_1, count_2 = 0, 0
@ -220,7 +219,7 @@ class CurrentDataProcess(QThread):
count_1 = 0 count_1 = 0
places = {"start": "起点", "middle": "中间点", "end": "终点"} # 因为是终点数据,所以可能有异常 places = {"start": "起点", "middle": "中间点", "end": "终点"} # 因为是终点数据,所以可能有异常
self.logger("DEBUG", "current", f"{axis} 轴获取{places[flag]}数据 {row_e} 可能有异常,需关注!", "purple") clibs.logger("DEBUG", "current", f"{axis} 轴获取{places[flag]}数据 {row_e} 可能有异常,需关注!", "purple")
return row_e return row_e
def p_single(self, wb, single, rrs): def p_single(self, wb, single, rrs):
@ -296,13 +295,13 @@ class CurrentDataProcess(QThread):
row_s, row_e = self.find_point(data_file, df, "gt", row_s, row_e, threshold, step, end_point, skip_scale, axis, 3) row_s, row_e = self.find_point(data_file, df, "gt", row_s, row_e, threshold, step, end_point, skip_scale, axis, 3)
row_start = self.get_row_number(threshold, "start", df, row_s, row_e, axis) row_start = self.get_row_number(threshold, "start", df, row_s, row_e, axis)
self.logger("DEBUG", "current", f"{axis} 轴起点:{row_start}") clibs.logger("DEBUG", "current", f"{axis} 轴起点:{row_start}")
self.logger("DEBUG", "current", f"{axis} 轴中间点:{row_middle}") clibs.logger("DEBUG", "current", f"{axis} 轴中间点:{row_middle}")
self.logger("DEBUG", "current", f"{axis} 轴终点:{row_end}") clibs.logger("DEBUG", "current", f"{axis} 轴终点:{row_end}")
self.logger("DEBUG", "current", f"{axis} 轴数据非零段点数:{row_middle-row_start+1}") clibs.logger("DEBUG", "current", f"{axis} 轴数据非零段点数:{row_middle-row_start+1}")
self.logger("DEBUG", "current", f"{axis} 轴数据为零段点数:{row_end-row_middle+1}") clibs.logger("DEBUG", "current", f"{axis} 轴数据为零段点数:{row_end-row_middle+1}")
if abs(row_end+row_start-2*row_middle) > 1000: if abs(row_end+row_start-2*row_middle) > 1000:
self.logger("WARNING", "current", f"{axis} 轴数据占空比异常,处理数据可能有误,需检查!", "purple") clibs.logger("WARNING", "current", f"{axis} 轴数据占空比异常,处理数据可能有误,需检查!", "purple")
data, first_c, second_c, third_c, fourth_c = [], clibs.c_joint_vel-1, clibs.c_servo_trq-1, clibs.c_sensor_trq-1, clibs.c_estimate_trans_trq-1 data, first_c, second_c, third_c, fourth_c = [], clibs.c_joint_vel-1, clibs.c_servo_trq-1, clibs.c_sensor_trq-1, clibs.c_estimate_trans_trq-1
for row in range(row_start, row_end+1): for row in range(row_start, row_end+1):
@ -327,7 +326,7 @@ class CurrentDataProcess(QThread):
i += 1 i += 1
def p_scenario(self, wb, scenario, rrs, dur_time): def p_scenario(self, wb, scenario, rrs, dur_time):
self.logger("INFO", "current", f"本次处理的是电机电流场景数据,场景运动周期为 {dur_time}s", "blue") clibs.logger("INFO", "current", f"本次处理的是电机电流场景数据,场景运动周期为 {dur_time}s", "blue")
for data_file in scenario: for data_file in scenario:
cycle = 0.001 cycle = 0.001
axis = int(data_file.split("/")[-1].split("_")[0].removeprefix("j")) axis = int(data_file.split("/")[-1].split("_")[0].removeprefix("j"))
@ -344,7 +343,7 @@ class CurrentDataProcess(QThread):
row_start = 3000 row_start = 3000
row_end = row_start + int(dur_time/cycle) row_end = row_start + int(dur_time/cycle)
if row_end > df.index[-1]: if row_end > df.index[-1]:
self.logger("ERROR", "current", f"位置超限:{data_file} 共有 {df.index[-1]} 条数据,无法取到第 {row_end} 条数据,需要确认场景周期时间...", "red") clibs.logger("ERROR", "current", f"位置超限:{data_file} 共有 {df.index[-1]} 条数据,无法取到第 {row_end} 条数据,需要确认场景周期时间...", "red")
data, first_c, second_c, third_c, fourth_c = [], clibs.c_joint_vel-1, clibs.c_servo_trq-1, clibs.c_sensor_trq-1, clibs.c_estimate_trans_trq-1 data, first_c, second_c, third_c, fourth_c = [], clibs.c_joint_vel-1, clibs.c_servo_trq-1, clibs.c_sensor_trq-1, clibs.c_estimate_trans_trq-1
for row in range(row_start, row_end+1): for row in range(row_start, row_end+1):
@ -391,13 +390,13 @@ class CurrentDataProcess(QThread):
r_max_t = configs["TRANSMISSION"]["MAX_PEAK_TORQUE"] # 减速器瞬时最大转矩 r_max_t = configs["TRANSMISSION"]["MAX_PEAK_TORQUE"] # 减速器瞬时最大转矩
r_avg_t = configs["TRANSMISSION"]["MAX_AVERAGE_TORQUE"] # 减速器平均负载转矩允许最大值 r_avg_t = configs["TRANSMISSION"]["MAX_AVERAGE_TORQUE"] # 减速器平均负载转矩允许最大值
self.logger("INFO", "current", f"get_configs: 机型文件版本 {config_file}_{version}") clibs.logger("INFO", "current", f"get_configs: 机型文件版本 {config_file}_{version}")
self.logger("INFO", "current", f"get_configs: 减速比 {r_rrs}") clibs.logger("INFO", "current", f"get_configs: 减速比 {r_rrs}")
self.logger("INFO", "current", f"get_configs: 额定转矩 {m_rts}") clibs.logger("INFO", "current", f"get_configs: 额定转矩 {m_rts}")
self.logger("INFO", "current", f"get_configs: 最大角速度 {m_avs}") clibs.logger("INFO", "current", f"get_configs: 最大角速度 {m_avs}")
return sc, r_rrs, m_avs, m_stall_ts, m_rts, m_max_ts, m_r_rpms, m_max_rpms, r_max_sst, r_max_t, r_avg_t, robot_type return sc, r_rrs, m_avs, m_stall_ts, m_rts, m_max_ts, m_r_rpms, m_max_rpms, r_max_sst, r_max_t, r_avg_t, robot_type
except Exception as err: except Exception as err:
self.logger("ERROR", "current", f"get_config: 无法打开 {config_file},或获取配置文件参数错误 {err}", "red") clibs.logger("ERROR", "current", f"get_config: 无法打开 {config_file},或获取配置文件参数错误 {err}", "red")
def processing(self): def processing(self):
time_start = time.time() time_start = time.time()
@ -413,7 +412,7 @@ class CurrentDataProcess(QThread):
elif self.proc == "周期": elif self.proc == "周期":
self.current_cycle(data_files, rrs, rts, params) self.current_cycle(data_files, rrs, rts, params)
self.logger("INFO", "current", "-"*60 + "<br>全部处理完毕<br>", "purple") clibs.logger("INFO", "current", "-"*60 + "<br>全部处理完毕<br>", "purple")
time_total = time.time() - time_start time_total = time.time() - time_start
msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s" msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s"
self.logger("INFO", "current", msg) clibs.logger("INFO", "current", msg)

View File

@ -11,7 +11,6 @@ class IsoDataProcess(QThread):
super().__init__() super().__init__()
self.dir_path = dir_path self.dir_path = dir_path
self.idx = 2 self.idx = 2
self.logger = clibs.logger
@staticmethod @staticmethod
def p_iso(file, p_files, ws, tmpfile): def p_iso(file, p_files, ws, tmpfile):
@ -144,7 +143,7 @@ class IsoDataProcess(QThread):
def initialization(self): def initialization(self):
dirs, files = clibs.traversal_files(self.dir_path) dirs, files = clibs.traversal_files(self.dir_path)
if len(dirs) != 0: if len(dirs) != 0:
self.logger("ERROR", "iso", f"init: 工作目录下不可以有文件夹!", "red") clibs.logger("ERROR", "iso", f"init: 工作目录下不可以有文件夹!", "red")
for file in files: for file in files:
file = file.lower() file = file.lower()
@ -157,7 +156,7 @@ class IsoDataProcess(QThread):
elif file.endswith("iso.pdf"): elif file.endswith("iso.pdf"):
pass pass
else: else:
self.logger("ERROR", "iso", f"init: 工作目录下只允许有如下四个文件不区分大小写pdf文件最少有一个<br>1. iso-results.xlsx<br>2. ISO.pdf<br>3. ISO-V100.pdf<br>4. ISO-V1000.pdf", "red") clibs.logger("ERROR", "iso", f"init: 工作目录下只允许有如下四个文件不区分大小写pdf文件最少有一个<br>1. iso-results.xlsx<br>2. ISO.pdf<br>3. ISO-V100.pdf<br>4. ISO-V1000.pdf", "red")
return files return files
@ -175,24 +174,24 @@ class IsoDataProcess(QThread):
for i in range(3, 50): for i in range(3, 50):
ws.cell(row=i, column=7).value = None ws.cell(row=i, column=7).value = None
except Exception as err: except Exception as err:
self.logger("ERROR", "iso", f"main: 无法打开文件 {filename}<br>{err}", "red") clibs.logger("ERROR", "iso", f"main: 无法打开文件 {filename}<br>{err}", "red")
p_files = [] p_files = []
for file in files: for file in files:
if file.split("/")[-1].lower() == "iso.pdf": if file.split("/")[-1].lower() == "iso.pdf":
self.logger("INFO", "iso", f"正在处理{file}......") clibs.logger("INFO", "iso", f"正在处理{file}......")
self.p_iso(file, p_files, ws, tmpfile) self.p_iso(file, p_files, ws, tmpfile)
self.logger("INFO", "iso", f"文件{file}已处理完毕。") clibs.logger("INFO", "iso", f"文件{file}已处理完毕。")
elif file.split("/")[-1].lower() == "iso-v100.pdf": elif file.split("/")[-1].lower() == "iso-v100.pdf":
self.logger("INFO", "iso", f"正在处理{file}......") clibs.logger("INFO", "iso", f"正在处理{file}......")
self.p_iso_100(file, p_files, ws, tmpfile) self.p_iso_100(file, p_files, ws, tmpfile)
self.logger("INFO", "iso", f"文件{file}已处理完毕。") clibs.logger("INFO", "iso", f"文件{file}已处理完毕。")
elif file.split("/")[-1].lower() == "iso-v1000.pdf": elif file.split("/")[-1].lower() == "iso-v1000.pdf":
self.logger("INFO", "iso", f"正在处理{file}......") clibs.logger("INFO", "iso", f"正在处理{file}......")
self.p_iso_1000(file, p_files, ws, tmpfile) self.p_iso_1000(file, p_files, ws, tmpfile)
self.logger("INFO", "iso", f"文件{file}已处理完毕。") clibs.logger("INFO", "iso", f"文件{file}已处理完毕。")
else: else:
pass pass
@ -200,11 +199,11 @@ class IsoDataProcess(QThread):
wb.close() wb.close()
if len(p_files) == 0: if len(p_files) == 0:
self.logger("ERROR", "iso", f"目录 {self.dir_path} 下没有需要处理的文件,需要确认......", "red") clibs.logger("ERROR", "iso", f"目录 {self.dir_path} 下没有需要处理的文件,需要确认......", "red")
else: else:
os.remove(tmpfile) os.remove(tmpfile)
self.logger("INFO", "current-processing", "-" * 60 + "<br>全部处理完毕<br>", "purple") clibs.logger("INFO", "current-processing", "-" * 60 + "<br>全部处理完毕<br>", "purple")
time_total = time.time() - time_start time_total = time.time() - time_start
msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s" msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s"
self.logger("INFO", "current-processing", msg) clibs.logger("INFO", "current-processing", msg)

View File

@ -12,7 +12,6 @@ class WaveloggerDataProcess(QThread):
super().__init__() super().__init__()
self.dir_path = dir_path self.dir_path = dir_path
self.idx = 3 self.idx = 3
self.logger = clibs.logger
def find_point(self, bof, step, margin, threshold, pos, data_file, flag, df, row): def find_point(self, bof, step, margin, threshold, pos, data_file, flag, df, row):
# bof: backward or forward # bof: backward or forward
@ -31,7 +30,7 @@ class WaveloggerDataProcess(QThread):
break break
else: else:
if bof == "backward": if bof == "backward":
self.logger("ERROR", "wavelogger", f"find_point-gt: [{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...", "red") clibs.logger("ERROR", "wavelogger", f"find_point-gt: [{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...", "red")
elif bof == "forward": elif bof == "forward":
row_target = row + margin # to end while loop in function `single_file_proc` row_target = row + margin # to end while loop in function `single_file_proc`
elif flag == "lt": elif flag == "lt":
@ -45,7 +44,7 @@ class WaveloggerDataProcess(QThread):
break break
else: else:
if bof == "backward": if bof == "backward":
self.logger("ERROR", "wavelogger", f"find_point-lt: [{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...", "red") clibs.logger("ERROR", "wavelogger", f"find_point-lt: [{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...", "red")
elif bof == "forward": elif bof == "forward":
row_target = row + margin # to end while loop in function `single_file_proc` row_target = row + margin # to end while loop in function `single_file_proc`
return row_target return row_target
@ -82,7 +81,7 @@ class WaveloggerDataProcess(QThread):
for data_file in data_files: for data_file in data_files:
if not data_file.lower().endswith(".csv"): if not data_file.lower().endswith(".csv"):
self.logger("ERROR", "wavelogger", f"init: {data_file} 文件后缀错误,只允许 .csv 文件,需要确认!", "red") clibs.logger("ERROR", "wavelogger", f"init: {data_file} 文件后缀错误,只允许 .csv 文件,需要确认!", "red")
return data_files return data_files
@ -108,7 +107,7 @@ class WaveloggerDataProcess(QThread):
value = df.iloc[start:end, 2].astype(float).mean() + 3 * df.iloc[start:end, 2].astype(float).std() value = df.iloc[start:end, 2].astype(float).mean() + 3 * df.iloc[start:end, 2].astype(float).std()
if value > 1: if value > 1:
msg = f"\n" msg = f"\n"
self.logger("WARNING", "wavelogger", f"{data_file} 文件第 {count} 轮 第 {count_i} 个数据可能有问题,需人工手动确认,确认有问题可删除,无问题则保留") clibs.logger("WARNING", "wavelogger", f"{data_file} 文件第 {count} 轮 第 {count_i} 个数据可能有问题,需人工手动确认,确认有问题可删除,无问题则保留")
data[count].append(value) data[count].append(value)
count_i += 1 count_i += 1
@ -129,7 +128,7 @@ class WaveloggerDataProcess(QThread):
row += 1 row += 1
def execution(self, data_files): def execution(self, data_files):
self.logger("INFO", "wavelogger", "正在处理中......", "blue") clibs.logger("INFO", "wavelogger", "正在处理中......", "blue")
wb = openpyxl.Workbook() wb = openpyxl.Workbook()
step, margin, data_length, threshold = 5, 50, 50, 5 step, margin, data_length, threshold = 5, 50, 50, 5
for data_file in data_files: for data_file in data_files:
@ -148,7 +147,7 @@ class WaveloggerDataProcess(QThread):
data_files = self.initialization() data_files = self.initialization()
self.execution(data_files) self.execution(data_files)
self.logger("INFO", "wavelogger", "-" * 60 + "<br>全部处理完毕<br>", "purple") clibs.logger("INFO", "wavelogger", "-" * 60 + "<br>全部处理完毕<br>", "purple")
time_total = time.time() - time_start time_total = time.time() - time_start
msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s" msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s"
self.logger("INFO", "wavelogger", msg) clibs.logger("INFO", "wavelogger", msg)

View File

@ -15,14 +15,13 @@ class DoBrakeTest(QThread):
self.dir_path = dir_path self.dir_path = dir_path
self.tool = tool self.tool = tool
self.idx = 4 self.idx = 4
self.logger = clibs.logger
def initialization(self, data_dirs, data_files): def initialization(self, data_dirs, data_files):
def check_files(): def check_files():
msg = "初始路径下不允许有文件夹,只能存在如下五个文件,且文件为关闭状态,确认后重新运行!<br>" msg = "初始路径下不允许有文件夹,只能存在如下五个文件,且文件为关闭状态,确认后重新运行!<br>"
msg += "1. configs.xlsx<br>2. reach33/reach66/reach100_xxxx.xlsx<br>3. xxxx.zip" msg += "1. configs.xlsx<br>2. reach33/reach66/reach100_xxxx.xlsx<br>3. xxxx.zip"
if len(data_dirs) != 0 or len(data_files) != 5: if len(data_dirs) != 0 or len(data_files) != 5:
self.logger("ERROR", "do_brake", msg, "red") clibs.logger("ERROR", "do_brake", msg, "red")
config_file, reach33_file, reach66_file, reach100_file, prj_file, result_dirs = None, None, None, None, None, [] config_file, reach33_file, reach66_file, reach100_file, prj_file, result_dirs = None, None, None, None, None, []
for data_file in data_files: for data_file in data_files:
@ -38,7 +37,7 @@ class DoBrakeTest(QThread):
elif filename.endswith(".zip"): elif filename.endswith(".zip"):
prj_file = data_file prj_file = data_file
else: else:
self.logger("ERROR", "do_brake", msg, "red") clibs.logger("ERROR", "do_brake", msg, "red")
if config_file and reach33_file and reach66_file and reach100_file and prj_file: if config_file and reach33_file and reach66_file and reach100_file and prj_file:
os.mkdir(f"{self.dir_path}/j1") os.mkdir(f"{self.dir_path}/j1")
@ -57,7 +56,7 @@ class DoBrakeTest(QThread):
return config_file, prj_file, result_dirs return config_file, prj_file, result_dirs
else: else:
self.logger("ERROR", "do_brake", msg, "red") clibs.logger("ERROR", "do_brake", msg, "red")
def get_configs(): def get_configs():
robot_type = None robot_type = None
@ -74,19 +73,19 @@ class DoBrakeTest(QThread):
with open(local_file, mode="r", encoding="utf-8") as f_config: with open(local_file, mode="r", encoding="utf-8") as f_config:
configs = json.load(f_config) configs = json.load(f_config)
except Exception as Err: except Exception as Err:
self.logger("ERROR", "do_brake", f"无法打开 {local_file}<br>{Err}", "red") clibs.logger("ERROR", "do_brake", f"无法打开 {local_file}<br>{Err}", "red")
# 最大角速度,额定电流,减速比,额定转速 # 最大角速度,额定电流,减速比,额定转速
version = configs["VERSION"] version = configs["VERSION"]
avs = configs["MOTION"]["JOINT_MAX_SPEED"] avs = configs["MOTION"]["JOINT_MAX_SPEED"]
self.logger("INFO", "do_brake", f"get_configs: 机型文件版本 {robot_type}_{version}") clibs.logger("INFO", "do_brake", f"get_configs: 机型文件版本 {robot_type}_{version}")
self.logger("INFO", "do_brake", f"get_configs: 各关节角速度 {avs}") clibs.logger("INFO", "do_brake", f"get_configs: 各关节角速度 {avs}")
return avs return avs
self.logger("INFO", "do_brake", "正在做初始化校验和配置,这可能需要一点时间......", "green") clibs.logger("INFO", "do_brake", "正在做初始化校验和配置,这可能需要一点时间......", "green")
_config_file, _prj_file, _result_dirs = check_files() _config_file, _prj_file, _result_dirs = check_files()
_avs = get_configs() _avs = get_configs()
self.logger("INFO", "do_brake", "数据目录合规性检查结束,未发现问题......", "green") clibs.logger("INFO", "do_brake", "数据目录合规性检查结束,未发现问题......", "green")
return _config_file, _prj_file, _result_dirs, _avs return _config_file, _prj_file, _result_dirs, _avs
def gen_result_file(self, axis, end_time, reach, load, speed, speed_max, rounds): def gen_result_file(self, axis, end_time, reach, load, speed, speed_max, rounds):
@ -118,13 +117,13 @@ class DoBrakeTest(QThread):
av_estop = abs(sum(d_vel[idx - 20:idx])/20 * clibs.RADIAN) av_estop = abs(sum(d_vel[idx - 20:idx])/20 * clibs.RADIAN)
if av_estop / speed_max < threshold: if av_estop / speed_max < threshold:
self.logger("WARNING", "do_brake", f"[av_estop: {av_estop:.2f} | shouldbe: {speed_max:.2f}] 处理数据时,本次触发 ESTOP 时未采集到指定百分比的最大速度,即将重试!", "#8A2BE2") clibs.logger("WARNING", "do_brake", f"[av_estop: {av_estop:.2f} | shouldbe: {speed_max:.2f}] 处理数据时,本次触发 ESTOP 时未采集到指定百分比的最大速度,即将重试!", "#8A2BE2")
clibs.count += 1 clibs.count += 1
if clibs.count < 3: if clibs.count < 3:
return "retry" return "retry"
else: else:
clibs.count = 0 clibs.count = 0
self.logger("WARNING", "do_brake", f"尝试三次后仍无法获取正确数据,本次数据无效,继续执行...", "red") clibs.logger("WARNING", "do_brake", f"尝试三次后仍无法获取正确数据,本次数据无效,继续执行...", "red")
df1 = pandas.DataFrame.from_dict({"hw_joint_vel_feedback": d_vel}) df1 = pandas.DataFrame.from_dict({"hw_joint_vel_feedback": d_vel})
df2 = pandas.DataFrame.from_dict({"device_servo_trq_feedback": d_trq}) df2 = pandas.DataFrame.from_dict({"device_servo_trq_feedback": d_trq})
@ -154,14 +153,14 @@ class DoBrakeTest(QThread):
io_name = ws.cell(row=5, column=2).value.upper().strip() io_name = ws.cell(row=5, column=2).value.upper().strip()
wb.close() wb.close()
msg = f"基本参数配置get_init_speed = {get_init_speed}, single_brake = {single_brake}, pon = {pon}, IO = {io_name}" msg = f"基本参数配置get_init_speed = {get_init_speed}, single_brake = {single_brake}, pon = {pon}, IO = {io_name}"
self.logger("INFO", "do_brake", msg) clibs.logger("INFO", "do_brake", msg)
if pon == "positive": if pon == "positive":
clibs.c_md.write_pon(1) clibs.c_md.write_pon(1)
elif pon == "negative": elif pon == "negative":
clibs.c_md.write_pon(0) clibs.c_md.write_pon(0)
else: else:
self.logger("ERROR", "do_brake", "configs.xlsx 中 Target 页面 B5 单元格填写不正确,检查后重新运行...", "red") clibs.logger("ERROR", "do_brake", "configs.xlsx 中 Target 页面 B5 单元格填写不正确,检查后重新运行...", "red")
self.change_curve_state(True) self.change_curve_state(True)
for condition in result_dirs: for condition in result_dirs:
@ -183,18 +182,18 @@ class DoBrakeTest(QThread):
continue continue
clibs.c_md.write_axis(axis) clibs.c_md.write_axis(axis)
self.logger("INFO", "brake", "-" * 90, "purple") clibs.logger("INFO", "brake", "-" * 90, "purple")
speed_max = 0 speed_max = 0
for rounds in range(1, 4): for rounds in range(1, 4):
if clibs.stop_flag: if clibs.stop_flag:
self.logger("ERROR", "do_brake", "后台数据清零完成,现在可以重新运行其他程序。", "green") clibs.logger("ERROR", "do_brake", "后台数据清零完成,现在可以重新运行其他程序。", "green")
count += 1 count += 1
_ = 3 if count % 3 == 0 else count % 3 _ = 3 if count % 3 == 0 else count % 3
this_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) this_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
prj_path = f"{prj_name}/_build/{prj_name}.prj" prj_path = f"{prj_name}/_build/{prj_name}.prj"
msg = f"[{this_time} | {count}/{total}] 正在执行 {axis}{condition} 的第 {_} 次制动测试..." msg = f"[{this_time} | {count}/{total}] 正在执行 {axis}{condition} 的第 {_} 次制动测试..."
self.logger("INFO", "do_brake", msg) clibs.logger("INFO", "do_brake", msg)
# 1. 触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电 # 1. 触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电
clibs.c_md.r_soft_estop(0) clibs.c_md.r_soft_estop(0)
@ -243,7 +242,7 @@ class DoBrakeTest(QThread):
else: else:
time.sleep(1) time.sleep(1)
if (time.time() - t_start) > 15: if (time.time() - t_start) > 15:
self.logger("ERROR", "do_brake", "15s 内未收到机器人的运行信号,需要确认 RL 程序编写正确并正常执行...", "red") clibs.logger("ERROR", "do_brake", "15s 内未收到机器人的运行信号,需要确认 RL 程序编写正确并正常执行...", "red")
# 4. 找出最大速度传递给RL程序最后清除相关记录 # 4. 找出最大速度传递给RL程序最后清除相关记录
time.sleep(5) # 消除前 5s 的不稳定数据 time.sleep(5) # 消除前 5s 的不稳定数据
start_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) start_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
@ -270,14 +269,14 @@ class DoBrakeTest(QThread):
speed_max = abs(get_speed_max()) speed_max = abs(get_speed_max())
speed_target = avs[axis-1] * float(speed) / 100 speed_target = avs[axis-1] * float(speed) / 100
self.logger("INFO", "do_brake", f"axis = {axis}, direction = {pon}, max speed = {speed_max}") clibs.logger("INFO", "do_brake", f"axis = {axis}, direction = {pon}, max speed = {speed_max}")
if speed_max < speed_target*0.95 or speed_max > speed_target*1.05: if speed_max < speed_target*0.95 or speed_max > speed_target*1.05:
self.logger("WARNING", "do_brake", f"Axis: {axis}-{count} | 采集获取最大 Speed: {speed_max} | Shouldbe: {speed_target}", "indigo") clibs.logger("WARNING", "do_brake", f"Axis: {axis}-{count} | 采集获取最大 Speed: {speed_max} | Shouldbe: {speed_target}", "indigo")
clibs.c_md.write_speed_max(speed_max) clibs.c_md.write_speed_max(speed_max)
if speed_max < 10: if speed_max < 10:
clibs.c_md.r_clear_alarm() clibs.c_md.r_clear_alarm()
self.logger("WARNING", "do_brake", f"未获取到正确的速度,即将重新获取...", "red") clibs.logger("WARNING", "do_brake", f"未获取到正确的速度,即将重新获取...", "red")
continue continue
else: else:
break break
@ -301,7 +300,7 @@ class DoBrakeTest(QThread):
else: else:
time.sleep(2) time.sleep(2)
if time.time() - t_start > 60: if time.time() - t_start > 60:
self.logger("ERROR", "do_brake", "60s 内程序未能正常执行,需检查...", "red") clibs.logger("ERROR", "do_brake", "60s 内程序未能正常执行,需检查...", "red")
for i in range(16): for i in range(16):
if clibs.c_md.read_ready_to_go() == 1: if clibs.c_md.read_ready_to_go() == 1:
@ -310,14 +309,14 @@ class DoBrakeTest(QThread):
else: else:
time.sleep(1) time.sleep(1)
else: else:
self.logger("ERROR", "do_brake", "16s 内未收到机器人的运行信号,需要确认 RL 程序配置正确并正常执行...", "red") clibs.logger("ERROR", "do_brake", "16s 内未收到机器人的运行信号,需要确认 RL 程序配置正确并正常执行...", "red")
def exec_brake(): def exec_brake():
flag, start, data, record = True, time.time(), None, None flag, start, data, record = True, time.time(), None, None
while flag: while flag:
time.sleep(0.05) time.sleep(0.05)
if time.time() - start > 20: if time.time() - start > 20:
self.logger("ERROR", "do_brake", "20s 内未触发急停,需排查......", "red") clibs.logger("ERROR", "do_brake", "20s 内未触发急停,需排查......", "red")
try: try:
clibs.lock.acquire(True) clibs.lock.acquire(True)
@ -352,20 +351,20 @@ class DoBrakeTest(QThread):
time.sleep(clibs.INTERVAL*2) time.sleep(clibs.INTERVAL*2)
self.change_curve_state(False) self.change_curve_state(False)
msg = f"<br>{self.tool.removeprefix('tool')}%负载的制动性能测试执行完毕,如需采集其他负载,须切换负载类型,并更换其他负载,重新执行" msg = f"<br>{self.tool.removeprefix('tool')}%负载的制动性能测试执行完毕,如需采集其他负载,须切换负载类型,并更换其他负载,重新执行"
self.logger("INFO", "do_brake", msg, "green") clibs.logger("INFO", "do_brake", msg, "green")
def processing(self): def processing(self):
time_start = time.time() time_start = time.time()
clibs.running[self.idx] = 1 clibs.running[self.idx] = 1
if clibs.status["hmi"] != 1 or clibs.status["md"] != 1 or clibs.status["ec"] != 1: if clibs.status["hmi"] != 1 or clibs.status["md"] != 1 or clibs.status["ec"] != 1:
self.logger("ERROR", "do_brake", "processing: 需要在网络设置中连接HMIModbus通信以及外部通信", "red") clibs.logger("ERROR", "do_brake", "processing: 需要在网络设置中连接HMIModbus通信以及外部通信", "red")
data_dirs, data_files = clibs.traversal_files(self.dir_path) data_dirs, data_files = clibs.traversal_files(self.dir_path)
config_file, prj_file, result_dirs, avs = self.initialization(data_dirs, data_files) config_file, prj_file, result_dirs, avs = self.initialization(data_dirs, data_files)
clibs.c_pd.push_prj_to_server(prj_file) clibs.c_pd.push_prj_to_server(prj_file)
self.run_rl(config_file, prj_file, result_dirs, avs) self.run_rl(config_file, prj_file, result_dirs, avs)
self.logger("INFO", "do_brake", "-"*60 + "<br>全部处理完毕<br>", "purple") clibs.logger("INFO", "do_brake", "-"*60 + "<br>全部处理完毕<br>", "purple")
time_total = time.time() - time_start time_total = time.time() - time_start
msg = f"处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s" msg = f"处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s"
self.logger("INFO", "do_brake", msg) clibs.logger("INFO", "do_brake", msg)

View File

@ -13,14 +13,13 @@ class DoCurrentTest(QThread):
self.dir_path = dir_path self.dir_path = dir_path
self.tool = tool self.tool = tool
self.idx = 5 self.idx = 5
self.logger = clibs.logger
def initialization(self, data_dirs, data_files): def initialization(self, data_dirs, data_files):
def check_files(): def check_files():
msg = "初始路径下不允许有文件夹,初始路径下只能存在如下两个文件,且文件为关闭状态,确认后重新运行!<br>" msg = "初始路径下不允许有文件夹,初始路径下只能存在如下两个文件,且文件为关闭状态,确认后重新运行!<br>"
msg += "1. T_电机电流.xlsx<br>2. xxxx.zip" msg += "1. T_电机电流.xlsx<br>2. xxxx.zip"
if len(data_dirs) != 0 or len(data_files) != 2: if len(data_dirs) != 0 or len(data_files) != 2:
self.logger("ERROR", "do_current", msg, "red") clibs.logger("ERROR", "do_current", msg, "red")
prj_file, count = None, 0 prj_file, count = None, 0
for data_file in data_files: for data_file in data_files:
@ -31,10 +30,10 @@ class DoCurrentTest(QThread):
count += 1 count += 1
prj_file = data_file prj_file = data_file
else: else:
self.logger("ERROR", "do_current", msg, "red") clibs.logger("ERROR", "do_current", msg, "red")
if count != 2: if count != 2:
self.logger("ERROR", "do_current", msg, "red") clibs.logger("ERROR", "do_current", msg, "red")
if self.tool == "tool100": if self.tool == "tool100":
os.mkdir(f"{self.dir_path}/single") os.mkdir(f"{self.dir_path}/single")
@ -44,7 +43,7 @@ class DoCurrentTest(QThread):
elif self.tool == "inertia": elif self.tool == "inertia":
os.mkdir(f"{self.dir_path}/inertia") os.mkdir(f"{self.dir_path}/inertia")
else: else:
self.logger("ERROR", "do_current", "负载选择错误,电机电流测试只能选择 tool100/inertia 规格!", "red") clibs.logger("ERROR", "do_current", "负载选择错误,电机电流测试只能选择 tool100/inertia 规格!", "red")
return prj_file return prj_file
@ -59,10 +58,10 @@ class DoCurrentTest(QThread):
local_file = self.dir_path + f"/{robot_type}.cfg" local_file = self.dir_path + f"/{robot_type}.cfg"
clibs.c_pd.pull_file_from_server(server_file, local_file) clibs.c_pd.pull_file_from_server(server_file, local_file)
self.logger("INFO", "do_current", "正在做初始化校验和配置,这可能需要一点时间......", "green") clibs.logger("INFO", "do_current", "正在做初始化校验和配置,这可能需要一点时间......", "green")
_prj_file = check_files() _prj_file = check_files()
get_configs() get_configs()
self.logger("INFO", "do_current", "数据目录合规性检查结束,未发现问题......", "green") clibs.logger("INFO", "do_current", "数据目录合规性检查结束,未发现问题......", "green")
return _prj_file return _prj_file
def single_axis_proc(self, records, number): def single_axis_proc(self, records, number):
@ -184,13 +183,13 @@ class DoCurrentTest(QThread):
for condition in conditions: for condition in conditions:
if clibs.stop_flag: if clibs.stop_flag:
self.logger("ERROR", "do_current", "后台数据清零完成,现在可以重新运行其他程序。", "green") clibs.logger("ERROR", "do_current", "后台数据清零完成,现在可以重新运行其他程序。", "green")
number = conditions.index(condition) number = conditions.index(condition)
# for testing # for testing
# if number < 12: # if number < 12:
# continue # continue
self.logger("INFO", "do_current", f"正在执行{disc[number]}测试......") clibs.logger("INFO", "do_current", f"正在执行{disc[number]}测试......")
# 1. 将act重置为False并修改将要执行的场景 # 1. 将act重置为False并修改将要执行的场景
clibs.c_md.write_act(False) clibs.c_md.write_act(False)
@ -223,7 +222,7 @@ class DoCurrentTest(QThread):
else: else:
time.sleep(1) time.sleep(1)
if (time.time() - t_start) > 15: if (time.time() - t_start) > 15:
self.logger("ERROR", "do_current", "15s 内未收到机器人的运行信号需要确认RL程序和工具通信是否正常执行...", "red") clibs.logger("ERROR", "do_current", "15s 内未收到机器人的运行信号需要确认RL程序和工具通信是否正常执行...", "red")
# 4. 执行采集 # 4. 执行采集
time.sleep(10) # 消除前 10s 的不稳定数据 time.sleep(10) # 消除前 10s 的不稳定数据
@ -239,12 +238,12 @@ class DoCurrentTest(QThread):
while True: while True:
scenario_time = float(f"{float(clibs.c_md.read_scenario_time()):.2f}") scenario_time = float(f"{float(clibs.c_md.read_scenario_time()):.2f}")
if float(scenario_time) != 0: if float(scenario_time) != 0:
self.logger("INFO", "do_current", f"场景{number - 11}的周期时间:{scenario_time}") clibs.logger("INFO", "do_current", f"场景{number - 11}的周期时间:{scenario_time}")
break break
else: else:
time.sleep(1) time.sleep(1)
if (time.time()-t_start) > 180: if (time.time()-t_start) > 180:
self.logger("ERROR", "do_current", f"180s 内未收到场景{number - 11}的周期时间需要确认RL程序和工具通信交互是否正常执行...", "red") clibs.logger("ERROR", "do_current", f"180s 内未收到场景{number - 11}的周期时间需要确认RL程序和工具通信交互是否正常执行...", "red")
time.sleep(20) time.sleep(20)
# 5.停止程序运行,保留数据并处理输出 # 5.停止程序运行,保留数据并处理输出
@ -255,22 +254,22 @@ class DoCurrentTest(QThread):
self.gen_result_file(number, start_time, end_time, scenario_time) self.gen_result_file(number, start_time, end_time, scenario_time)
else: else:
if self.tool == "tool100": if self.tool == "tool100":
self.logger("INFO", "do_current", "单轴和场景电机电流采集完毕,如需采集惯量负载,须切换负载类型,并更换惯量负载,重新执行", "green") clibs.logger("INFO", "do_current", "单轴和场景电机电流采集完毕,如需采集惯量负载,须切换负载类型,并更换惯量负载,重新执行", "green")
elif self.tool == "inertia": elif self.tool == "inertia":
self.logger("INFO", "do_current", "惯量负载电机电流采集完毕,如需采集单轴/场景/保持电机电流,须切换负载类型,并更换偏置负载,重新执行", "green") clibs.logger("INFO", "do_current", "惯量负载电机电流采集完毕,如需采集单轴/场景/保持电机电流,须切换负载类型,并更换偏置负载,重新执行", "green")
def processing(self): def processing(self):
time_start = time.time() time_start = time.time()
clibs.running[self.idx] = 1 clibs.running[self.idx] = 1
if clibs.status["hmi"] != 1 or clibs.status["md"] != 1: if clibs.status["hmi"] != 1 or clibs.status["md"] != 1:
self.logger("ERROR", "do_current", "processing: 需要在网络设置中连接HMI以及Modbus通信", "red") clibs.logger("ERROR", "do_current", "processing: 需要在网络设置中连接HMI以及Modbus通信", "red")
data_dirs, data_files = clibs.traversal_files(self.dir_path) data_dirs, data_files = clibs.traversal_files(self.dir_path)
prj_file = self.initialization(data_dirs, data_files) prj_file = self.initialization(data_dirs, data_files)
clibs.c_pd.push_prj_to_server(prj_file) clibs.c_pd.push_prj_to_server(prj_file)
self.run_rl(prj_file) self.run_rl(prj_file)
self.logger("INFO", "do_current", "-" * 60 + "<br>全部处理完毕<br>", "purple") clibs.logger("INFO", "do_current", "-" * 60 + "<br>全部处理完毕<br>", "purple")
time_total = time.time() - time_start time_total = time.time() - time_start
msg = f"处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s" msg = f"处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s"
self.logger("INFO", "do_current", msg) clibs.logger("INFO", "do_current", msg)

View File

@ -1,5 +1,6 @@
import os import os
import os.path import os.path
import time
import threading import threading
import sqlite3 import sqlite3
from PySide6.QtCore import Signal, QThread from PySide6.QtCore import Signal, QThread
@ -82,19 +83,41 @@ class LoggerHandler(QThread):
raise Exception() raise Exception()
def detect_db_size():
@db_lock
def release_memory():
line_number = 20000
leftover = 4000 # 200s
cursor.execute("SELECT COUNT(id) FROM logs")
len_records = cursor.fetchone()[0]
if len_records > line_number:
del_num = len_records - leftover + 1
cursor.execute(f"DELETE FROM logs WHERE id < {del_num}")
cursor.execute(f"UPDATE logs SET id=(id-{del_num - 1}) WHERE id > {del_num - 1}")
cursor.execute(f"UPDATE sqlite_sequence SET seq = {leftover + 1} WHERE name = 'logs' ")
cursor.execute("VACUUM")
while True:
release_memory()
time.sleep(INTERVAL*10)
PREFIX = "resources/assets" # for pyinstaller PREFIX = "resources/assets" # for pyinstaller
# PREFIX = "assets" # for local testing # PREFIX = "assets" # for local testing
log_path = f"{PREFIX}/logs" # log_path = f"{PREFIX}/logs"
lock = threading.Lock() lock = threading.Lock()
running = [0, 0, 0, 0, 0, 0, 0] # 制动数据/转矩数据/激光数据/精度数据/制动自动化/转矩自动化/耐久数据采集 running = [0, 0, 0, 0, 0, 0, 0] # 制动数据/转矩数据/激光数据/精度数据/制动自动化/转矩自动化/耐久数据采集
stop_flag = False stop_flag = False
functions = ["制动数据处理", "转矩数据处理", "激光数据处理", "精度数据处理", "制动自动化测试", "转矩自动化测试", "耐久数据采集"] functions = ["制动数据处理", "转矩数据处理", "激光数据处理", "精度数据处理", "制动自动化测试", "转矩自动化测试", "耐久数据采集"]
levels = ["DEBUG", "INFO", "WARNING", "ERROR"] levels = ["DEBUG", "INFO", "WARNING", "ERROR"]
ip_addr, ssh_port, socket_port, xService_port, external_port, modbus_port, upgrade_port = "", 22, 5050, 6666, 8080, 502, 4567 ip_addr, ssh_port, socket_port, xService_port, external_port, modbus_port, upgrade_port = "", 22, 5050, 6666, 8080, 502, 4567
username, password = "luoshi", "luoshi2019" username, password = "luoshi", "123456"
INTERVAL, RADIAN, MAX_FRAME_SIZE, MAX_LOG_NUMBER, CYCLE = 1, 57.3, 1024, 10, 300 INTERVAL, RADIAN, MAX_FRAME_SIZE, MAX_LOG_NUMBER, CYCLE = 1, 57.3, 1024, 10, 30
c_md, c_hr, c_ec, c_pd, conn, cursor, search_records, logger, count = None, None, None, None, None, None, None, None, 0 c_md, c_hr, c_ec, c_pd, conn, cursor, search_records, logger, count = None, None, None, None, None, None, None, None, 0
status = {"mysql": 0, "hmi": 0, "md": 0, "ec": 0} status = {"mysql": 0, "hmi": 0, "md": 0, "ec": 0}
c_joint_vel, c_servo_trq, c_sensor_trq, c_estimate_trans_trq, c_safety_estop = 1, 2, 3, 4, 3 # 各个指标所在列 c_joint_vel, c_servo_trq, c_sensor_trq, c_estimate_trans_trq, c_safety_estop = 1, 2, 3, 4, 3 # 各个指标所在列
init_logdb() init_logdb()
t = threading.Thread(target=detect_db_size)
t.daemon = True
t.start()

View File

@ -21,20 +21,19 @@ class ModbusRequest(QThread):
self.ip = ip self.ip = ip
self.port = port self.port = port
self.c = None self.c = None
self.logger = clibs.logger
def net_conn(self): def net_conn(self):
self.logger("INFO", "openapi", f"Modbus 正在连接中,需要配置设备,这可能需要一点时间......", "blue") clibs.logger("INFO", "openapi", f"Modbus 正在连接中,需要配置设备,这可能需要一点时间......", "blue")
RobotInit.modbus_init() RobotInit.modbus_init()
self.c = ModbusTcpClient(host=self.ip, port=self.port) self.c = ModbusTcpClient(host=self.ip, port=self.port)
if self.c.connect(): if self.c.connect():
self.logger("INFO", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) success!", "green") clibs.logger("INFO", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) success!", "green")
else: else:
self.logger("ERROR", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) failed!", "red") clibs.logger("ERROR", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) failed!", "red")
def close(self): def close(self):
self.c.close() self.c.close()
self.logger("INFO", "openapi", f"modbus: 关闭 Modbus 连接成功", "green") clibs.logger("INFO", "openapi", f"modbus: 关闭 Modbus 连接成功", "green")
def __reg_high_pulse(self, addr: int) -> None: def __reg_high_pulse(self, addr: int) -> None:
self.c.write_register(addr, 0) self.c.write_register(addr, 0)
@ -45,71 +44,71 @@ class ModbusRequest(QThread):
def r_clear_alarm(self): # OK def r_clear_alarm(self): # OK
self.__reg_high_pulse(40000) self.__reg_high_pulse(40000)
self.logger("DEBUG", "openapi", "modbus: 40000-010 执行清除告警信息") clibs.logger("DEBUG", "openapi", "modbus: 40000-010 执行清除告警信息")
def r_reset_estop(self): # OK def r_reset_estop(self): # OK
self.__reg_high_pulse(40001) self.__reg_high_pulse(40001)
self.logger("DEBUG", "openapi", "modbus: 40001-010 执行复位急停状态(非软急停)") clibs.logger("DEBUG", "openapi", "modbus: 40001-010 执行复位急停状态(非软急停)")
def r_reset_estop_clear_alarm(self): # OK def r_reset_estop_clear_alarm(self): # OK
self.__reg_high_pulse(40002) self.__reg_high_pulse(40002)
self.logger("DEBUG", "openapi", "modbus: 40002-010 执行复位急停状态(非软急停),并清除告警信息") clibs.logger("DEBUG", "openapi", "modbus: 40002-010 执行复位急停状态(非软急停),并清除告警信息")
def r_motor_off(self): # OK def r_motor_off(self): # OK
self.__reg_high_pulse(40003) self.__reg_high_pulse(40003)
self.logger("DEBUG", "openapi", "modbus: 40003-010 执行机器人下电") clibs.logger("DEBUG", "openapi", "modbus: 40003-010 执行机器人下电")
def r_motor_on(self): # OK def r_motor_on(self): # OK
self.__reg_high_pulse(40004) self.__reg_high_pulse(40004)
self.logger("DEBUG", "openapi", "modbus: 40004-010 执行机器人上电") clibs.logger("DEBUG", "openapi", "modbus: 40004-010 执行机器人上电")
def r_motoron_pp2main_start(self): # OK def r_motoron_pp2main_start(self): # OK
self.__reg_high_pulse(40005) self.__reg_high_pulse(40005)
self.logger("DEBUG", "openapi", "modbus: 40005-010 执行机器人上电/pp2main/开始运行程序,需自动模式执行,若运行失败,可清除告警后再次尝试") clibs.logger("DEBUG", "openapi", "modbus: 40005-010 执行机器人上电/pp2main/开始运行程序,需自动模式执行,若运行失败,可清除告警后再次尝试")
def r_motoron_start(self): # OK def r_motoron_start(self): # OK
self.__reg_high_pulse(40006) self.__reg_high_pulse(40006)
self.logger("DEBUG", "openapi", "modbus: 40006-010 执行机器人上电/开始运行程序需自动模式执行若运行失败可清除告警、执行pp2main后再次尝试") clibs.logger("DEBUG", "openapi", "modbus: 40006-010 执行机器人上电/开始运行程序需自动模式执行若运行失败可清除告警、执行pp2main后再次尝试")
def r_pulse_motoroff(self): # OK def r_pulse_motoroff(self): # OK
self.__reg_high_pulse(40007) self.__reg_high_pulse(40007)
self.logger("DEBUG", "openapi", "modbus: 40007-010 执行机器人停止,并下电,手动模式下可停止程序运行,但不能下电,若运行失败,可清除告警后再次尝试") clibs.logger("DEBUG", "openapi", "modbus: 40007-010 执行机器人停止,并下电,手动模式下可停止程序运行,但不能下电,若运行失败,可清除告警后再次尝试")
def r_pp2main(self): # OK def r_pp2main(self): # OK
self.__reg_high_pulse(40008) self.__reg_high_pulse(40008)
self.logger("DEBUG", "openapi", "modbus: 40008-010 执行机器人 pp2main需自动模式执行若运行失败可清除告警后再次尝试") clibs.logger("DEBUG", "openapi", "modbus: 40008-010 执行机器人 pp2main需自动模式执行若运行失败可清除告警后再次尝试")
def r_program_start(self): # OK def r_program_start(self): # OK
self.__reg_high_pulse(40009) self.__reg_high_pulse(40009)
self.logger("DEBUG", "openapi", "modbus: 40009-010 执行机器人默认程序运行,需有 pp2main 前置操作,若运行失败,可清除告警后再次尝试") clibs.logger("DEBUG", "openapi", "modbus: 40009-010 执行机器人默认程序运行,需有 pp2main 前置操作,若运行失败,可清除告警后再次尝试")
def r_program_stop(self): # OK def r_program_stop(self): # OK
self.__reg_high_pulse(40010) self.__reg_high_pulse(40010)
self.logger("DEBUG", "openapi", "modbus: 40010-010 执行机器人默认程序停止,需有 pp2main 前置操作,若运行失败,可清除告警后再次尝试") clibs.logger("DEBUG", "openapi", "modbus: 40010-010 执行机器人默认程序停止,需有 pp2main 前置操作,若运行失败,可清除告警后再次尝试")
def r_reduced_mode(self, action: int): # OK def r_reduced_mode(self, action: int): # OK
self.c.write_register(40011, action) self.c.write_register(40011, action)
actions = "进入" if action == 1 else "退出" actions = "进入" if action == 1 else "退出"
self.logger("DEBUG", "openapi", f"modbus: 40011-{action} 执行机器人{actions}缩减模式") clibs.logger("DEBUG", "openapi", f"modbus: 40011-{action} 执行机器人{actions}缩减模式")
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
def r_soft_estop(self, action: int): # OK def r_soft_estop(self, action: int): # OK
self.c.write_register(40012, action) self.c.write_register(40012, action)
actions = "解除" if action == 1 else "触发" actions = "解除" if action == 1 else "触发"
self.logger("DEBUG", "openapi", f"modbus: 40012-{action} 执行{actions}急停动作") clibs.logger("DEBUG", "openapi", f"modbus: 40012-{action} 执行{actions}急停动作")
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
def r_switch_auto_motoron(self): # OK def r_switch_auto_motoron(self): # OK
self.__reg_high_pulse(40013) self.__reg_high_pulse(40013)
self.logger("DEBUG", "openapi", "modbus: 40013-010 执行切换为自动模式,并上电,初始状态 !!不能是!! 手动上电模式") clibs.logger("DEBUG", "openapi", "modbus: 40013-010 执行切换为自动模式,并上电,初始状态 !!不能是!! 手动上电模式")
def r_switch_auto(self): # OK def r_switch_auto(self): # OK
self.__reg_high_pulse(40014) self.__reg_high_pulse(40014)
self.logger("DEBUG", "openapi", "modbus: 40014-010 执行切换为自动模式") clibs.logger("DEBUG", "openapi", "modbus: 40014-010 执行切换为自动模式")
def r_switch_manual(self): # OK def r_switch_manual(self): # OK
self.__reg_high_pulse(40015) self.__reg_high_pulse(40015)
self.logger("DEBUG", "openapi", "modbus: 40015-010 执行切换为手动模式") clibs.logger("DEBUG", "openapi", "modbus: 40015-010 执行切换为手动模式")
def r_switch_safe_region01(self, action: bool): # OK | 上升沿打开,下降沿关闭 def r_switch_safe_region01(self, action: bool): # OK | 上升沿打开,下降沿关闭
if action: if action:
@ -121,7 +120,7 @@ class ModbusRequest(QThread):
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
self.c.write_register(40016, False) self.c.write_register(40016, False)
actions = "打开" if action else "关闭" actions = "打开" if action else "关闭"
self.logger("DEBUG", "openapi", f"modbus: 40016-{action} 执行{actions}安全区 safe region 01") clibs.logger("DEBUG", "openapi", f"modbus: 40016-{action} 执行{actions}安全区 safe region 01")
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
def r_switch_safe_region02(self, action: bool): # OK | 上升沿打开,下降沿关闭 def r_switch_safe_region02(self, action: bool): # OK | 上升沿打开,下降沿关闭
@ -134,7 +133,7 @@ class ModbusRequest(QThread):
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
self.c.write_register(40017, False) self.c.write_register(40017, False)
actions = "打开" if action else "关闭" actions = "打开" if action else "关闭"
self.logger("DEBUG", "openapi", f"modbus: 40017-{action} 执行{actions}安全区 safe region 02") clibs.logger("DEBUG", "openapi", f"modbus: 40017-{action} 执行{actions}安全区 safe region 02")
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
def r_switch_safe_region03(self, action: bool): # OK | 上升沿打开,下降沿关闭 def r_switch_safe_region03(self, action: bool): # OK | 上升沿打开,下降沿关闭
@ -147,150 +146,150 @@ class ModbusRequest(QThread):
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
self.c.write_register(40018, False) self.c.write_register(40018, False)
actions = "打开" if action else "关闭" actions = "打开" if action else "关闭"
self.logger("DEBUG", "openapi", f"modbus: 40018-{action} 执行{actions}安全区 safe region 03") clibs.logger("DEBUG", "openapi", f"modbus: 40018-{action} 执行{actions}安全区 safe region 03")
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
def write_act(self, number): def write_act(self, number):
self.c.write_register(40100, number) self.c.write_register(40100, number)
self.logger("DEBUG", "openapi", f"modbus: 40100 将 {number} 写入") clibs.logger("DEBUG", "openapi", f"modbus: 40100 将 {number} 写入")
def write_probe(self, probe): def write_probe(self, probe):
self.c.write_register(40101, probe) self.c.write_register(40101, probe)
self.logger("DEBUG", "openapi", f"modbus: 40101 将 {probe} 写入") clibs.logger("DEBUG", "openapi", f"modbus: 40101 将 {probe} 写入")
def write_pon(self, pon): def write_pon(self, pon):
self.c.write_register(40102, pon) self.c.write_register(40102, pon)
self.logger("DEBUG", "openapi", f"modbus: 40102 将 {pon} 写入") clibs.logger("DEBUG", "openapi", f"modbus: 40102 将 {pon} 写入")
def write_axis(self, axis): def write_axis(self, axis):
result = self.c.convert_to_registers(int(axis), self.c.DATATYPE.INT32, "little") result = self.c.convert_to_registers(int(axis), self.c.DATATYPE.INT32, "little")
self.c.write_registers(40103, result) self.c.write_registers(40103, result)
self.logger("DEBUG", "openapi", f"modbus: 40103 将 {axis} 写入") clibs.logger("DEBUG", "openapi", f"modbus: 40103 将 {axis} 写入")
def write_speed_max(self, speed): def write_speed_max(self, speed):
result = self.c.convert_to_registers(float(speed), self.c.DATATYPE.FLOAT32, "little") result = self.c.convert_to_registers(float(speed), self.c.DATATYPE.FLOAT32, "little")
self.c.write_registers(40105, result) self.c.write_registers(40105, result)
self.logger("DEBUG", "openapi", f"modbus: 40105 将 {speed} 写入") clibs.logger("DEBUG", "openapi", f"modbus: 40105 将 {speed} 写入")
def r_write_signals(self, addr: int, value): # OK | 40100 - 40109: signal_0 ~ signal_9 def r_write_signals(self, addr: int, value): # OK | 40100 - 40109: signal_0 ~ signal_9
if -1 < addr < 10 and addr.is_integer(): if -1 < addr < 10 and addr.is_integer():
self.c.write_register(40100+addr, value) self.c.write_register(40100+addr, value)
self.logger("DEBUG", "openapi", f"modbus: {40100+addr}-{value} 将寄存器 signal_{addr} 赋值为 {value}") clibs.logger("DEBUG", "openapi", f"modbus: {40100+addr}-{value} 将寄存器 signal_{addr} 赋值为 {value}")
else: else:
self.logger("INFO", "openapi", f"modbus: {40100+addr}-{value} 地址错误,无法赋值!", "red") clibs.logger("INFO", "openapi", f"modbus: {40100+addr}-{value} 地址错误,无法赋值!", "red")
@property @property
def w_alarm_state(self): # OK def w_alarm_state(self): # OK
res = self.c.read_holding_registers(40500, count=1).registers[0] res = self.c.read_holding_registers(40500, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40500 获取告警状态,结果为 {res} :--: 0 表示无告警,1 表示有告警") clibs.logger("DEBUG", "openapi", f"modbus: 40500 获取告警状态,结果为 {res} :--: 0 表示无告警,1 表示有告警")
return res return res
@property @property
def w_collision_alarm_state(self): # OK def w_collision_alarm_state(self): # OK
res = self.c.read_holding_registers(40501, count=1).registers[0] res = self.c.read_holding_registers(40501, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40501 获取碰撞告警状态,结果为 {res} :--: 0 表示未触发1 表示已触发") clibs.logger("DEBUG", "openapi", f"modbus: 40501 获取碰撞告警状态,结果为 {res} :--: 0 表示未触发1 表示已触发")
return res return res
@property @property
def w_collision_open_state(self): # OK def w_collision_open_state(self): # OK
res = self.c.read_holding_registers(40502, count=1).registers[0] res = self.c.read_holding_registers(40502, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40502 获取碰撞检测开启状态,结果为 {res} :--: 0 表示关闭1 表示开启") clibs.logger("DEBUG", "openapi", f"modbus: 40502 获取碰撞检测开启状态,结果为 {res} :--: 0 表示关闭1 表示开启")
return res return res
@property @property
def w_controller_is_running(self): # OK def w_controller_is_running(self): # OK
res = self.c.read_holding_registers(40503, count=1).registers[0] res = self.c.read_holding_registers(40503, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40503 获取控制器运行状态,结果为 {res} :--: 0 表示运行异常1 表示运行正常") clibs.logger("DEBUG", "openapi", f"modbus: 40503 获取控制器运行状态,结果为 {res} :--: 0 表示运行异常1 表示运行正常")
return res return res
@property @property
def w_encoder_low_battery(self): # OK def w_encoder_low_battery(self): # OK
res = self.c.read_holding_registers(40504, count=1).registers[0] res = self.c.read_holding_registers(40504, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40504 获取编码器低电压状态,结果为 {res} :--: 0 表示非低电压1 表示低电压 需关注") clibs.logger("DEBUG", "openapi", f"modbus: 40504 获取编码器低电压状态,结果为 {res} :--: 0 表示非低电压1 表示低电压 需关注")
return res return res
@property @property
def w_estop_state(self): # OK def w_estop_state(self): # OK
res = self.c.read_holding_registers(40505, count=1).registers[0] res = self.c.read_holding_registers(40505, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40505 获取机器人急停状态(非软急停),结果为 {res} :--: 0 表示未触发1 表示已触发") clibs.logger("DEBUG", "openapi", f"modbus: 40505 获取机器人急停状态(非软急停),结果为 {res} :--: 0 表示未触发1 表示已触发")
return res return res
@property @property
def w_motor_state(self): # OK def w_motor_state(self): # OK
res = self.c.read_holding_registers(40506, count=1).registers[0] res = self.c.read_holding_registers(40506, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40506 获取机器人上电状态,结果为 {res} :--: 0 表示未上电1 表示已上电") clibs.logger("DEBUG", "openapi", f"modbus: 40506 获取机器人上电状态,结果为 {res} :--: 0 表示未上电1 表示已上电")
return res return res
@property @property
def w_operation_mode(self): # OK def w_operation_mode(self): # OK
res = self.c.read_holding_registers(40507, count=1).registers[0] res = self.c.read_holding_registers(40507, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40507 获取机器人操作模式,结果为 {res} :--: 0 表示手动模式1 表示自动模式") clibs.logger("DEBUG", "openapi", f"modbus: 40507 获取机器人操作模式,结果为 {res} :--: 0 表示手动模式1 表示自动模式")
return res return res
@property @property
def w_program_state(self): # OK def w_program_state(self): # OK
res = self.c.read_holding_registers(40508, count=1).registers[0] res = self.c.read_holding_registers(40508, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40508 获取程序的运行状态,结果为 {res} :--: 0 表示未运行1 表示正在运行") clibs.logger("DEBUG", "openapi", f"modbus: 40508 获取程序的运行状态,结果为 {res} :--: 0 表示未运行1 表示正在运行")
return res return res
@property @property
def w_program_not_run(self): # OK def w_program_not_run(self): # OK
res = self.c.read_holding_registers(40509, count=1).registers[0] res = self.c.read_holding_registers(40509, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40509 判定程序为未运行状态,结果为 {res} :--: 0 表示正在运行1 表示未运行") clibs.logger("DEBUG", "openapi", f"modbus: 40509 判定程序为未运行状态,结果为 {res} :--: 0 表示正在运行1 表示未运行")
return res return res
@property @property
def w_program_reset(self): # OK def w_program_reset(self): # OK
res = self.c.read_holding_registers(40510, count=1).registers[0] res = self.c.read_holding_registers(40510, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40510 判定程序指针为 pp2main 状态,结果为 {res} :--: 0 表示指针不在 main 函数1 表示指针在 main 函数") clibs.logger("DEBUG", "openapi", f"modbus: 40510 判定程序指针为 pp2main 状态,结果为 {res} :--: 0 表示指针不在 main 函数1 表示指针在 main 函数")
return res return res
@property @property
def w_reduce_mode_state(self): # OK def w_reduce_mode_state(self): # OK
res = self.c.read_holding_registers(40511, count=1).registers[0] res = self.c.read_holding_registers(40511, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40511 获取机器人缩减模式状态,结果为 {res} :--: 0 表示非缩减模式1 表示缩减模式") clibs.logger("DEBUG", "openapi", f"modbus: 40511 获取机器人缩减模式状态,结果为 {res} :--: 0 表示非缩减模式1 表示缩减模式")
return res return res
@property @property
def w_robot_is_busy(self): # OK def w_robot_is_busy(self): # OK
res = self.c.read_holding_registers(40512, count=1).registers[0] res = self.c.read_holding_registers(40512, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40512 获取机器人是否处于 busy 状态,结果为 {res} :--: 0 表示未处于 busy 状态1 表示处于 busy 状态") clibs.logger("DEBUG", "openapi", f"modbus: 40512 获取机器人是否处于 busy 状态,结果为 {res} :--: 0 表示未处于 busy 状态1 表示处于 busy 状态")
return res return res
@property @property
def w_robot_is_moving(self): # OK def w_robot_is_moving(self): # OK
res = self.c.read_holding_registers(40513, count=1).registers[0] res = self.c.read_holding_registers(40513, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40513 获取机器人是否处于运动状态,结果为 {res} :--: 0 表示未运动1 表示正在运动") clibs.logger("DEBUG", "openapi", f"modbus: 40513 获取机器人是否处于运动状态,结果为 {res} :--: 0 表示未运动1 表示正在运动")
return res return res
@property @property
def w_safe_door_state(self): # OK def w_safe_door_state(self): # OK
res = self.c.read_holding_registers(40514, count=1).registers[0] res = self.c.read_holding_registers(40514, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40514 获取机器人是否处于安全门打开状态,需自动模式下执行,结果为 {res} :--: 0 表示未触发安全门1 表示已触发安全门") clibs.logger("DEBUG", "openapi", f"modbus: 40514 获取机器人是否处于安全门打开状态,需自动模式下执行,结果为 {res} :--: 0 表示未触发安全门1 表示已触发安全门")
return res return res
@property @property
def w_safe_region01_trig_state(self): # OK def w_safe_region01_trig_state(self): # OK
res = self.c.read_holding_registers(40515, count=1).registers[0] res = self.c.read_holding_registers(40515, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40515 获取安全区域 safe region01 的触发状态,结果为 {res} :--: 0 表示未触发1 表示已触发") clibs.logger("DEBUG", "openapi", f"modbus: 40515 获取安全区域 safe region01 的触发状态,结果为 {res} :--: 0 表示未触发1 表示已触发")
return res return res
@property @property
def w_safe_region02_trig_state(self): # OK def w_safe_region02_trig_state(self): # OK
res = self.c.read_holding_registers(40516, count=1).registers[0] res = self.c.read_holding_registers(40516, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40516 获取安全区域 safe region02 的触发状态,结果为 {res} :--: 0 表示未触发1 表示已触发") clibs.logger("DEBUG", "openapi", f"modbus: 40516 获取安全区域 safe region02 的触发状态,结果为 {res} :--: 0 表示未触发1 表示已触发")
return res return res
@property @property
def w_safe_region03_trig_state(self): # OK def w_safe_region03_trig_state(self): # OK
res = self.c.read_holding_registers(40517, count=1).registers[0] res = self.c.read_holding_registers(40517, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40517 获取安全区域 safe region03 的触发状态,结果为 {res} :--: 0 表示未触发1 表示已触发") clibs.logger("DEBUG", "openapi", f"modbus: 40517 获取安全区域 safe region03 的触发状态,结果为 {res} :--: 0 表示未触发1 表示已触发")
return res return res
@property @property
def w_soft_estop_state(self): # OK def w_soft_estop_state(self): # OK
res = self.c.read_holding_registers(40518, count=1).registers[0] res = self.c.read_holding_registers(40518, count=1).registers[0]
self.logger("DEBUG", "openapi", f"modbus: 40518 获取机器人软急停状态,结果为 {res} :--: 0 表示未触发软急停1 表示已触发软急停") clibs.logger("DEBUG", "openapi", f"modbus: 40518 获取机器人软急停状态,结果为 {res} :--: 0 表示未触发软急停1 表示已触发软急停")
return res return res
def io_write_coils(self, addr, action): # OK | 名字叫写线圈,其实是写 modbus 的 discrete inputs(DI) def io_write_coils(self, addr, action): # OK | 名字叫写线圈,其实是写 modbus 的 discrete inputs(DI)
@ -298,17 +297,17 @@ class ModbusRequest(QThread):
# e.g. io_write_coils(1, 1) # e.g. io_write_coils(1, 1)
# e.g. io_write_coils(0, [1, 1, 1]) # e.g. io_write_coils(0, [1, 1, 1])
self.c.write_coils(addr, action) self.c.write_coils(addr, action)
self.logger("DEBUG", "openapi", f"modbus: 执行给 DI 地址 {addr} 赋值为 {action},可根据情况传递列表,实现一次性赋值多个") clibs.logger("DEBUG", "openapi", f"modbus: 执行给 DI 地址 {addr} 赋值为 {action},可根据情况传递列表,实现一次性赋值多个")
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
def io_read_coils(self): # OK | 读 modbus 的 16 个 discrete inputs(DI) def io_read_coils(self): # OK | 读 modbus 的 16 个 discrete inputs(DI)
res = self.c.read_coils(0, count=16).bits res = self.c.read_coils(0, count=16).bits
self.logger("DEBUG", "openapi", f"modbus: 执行读取所有 DI 的结果为 {res}") clibs.logger("DEBUG", "openapi", f"modbus: 执行读取所有 DI 的结果为 {res}")
return res return res
def io_read_discretes(self): # OK | 读 modbus 的 coil outputs(DO) def io_read_discretes(self): # OK | 读 modbus 的 coil outputs(DO)
res = self.c.read_discrete_inputs(0, count=16).bits res = self.c.read_discrete_inputs(0, count=16).bits
self.logger("DEBUG", "openapi", f"modbus: 执行读取所有 DO 的结果为 {res}") clibs.logger("DEBUG", "openapi", f"modbus: 执行读取所有 DO 的结果为 {res}")
return res return res
def read_ready_to_go(self): def read_ready_to_go(self):
@ -346,7 +345,6 @@ class HmiRequest(QThread):
self.__half_pkg_flag = False self.__half_pkg_flag = False
self.__is_first_frame = True self.__is_first_frame = True
self.__is_debug = True self.__is_debug = True
self.logger = clibs.logger
def net_conn(self): def net_conn(self):
self.__socket_conn() self.__socket_conn()
@ -360,7 +358,7 @@ class HmiRequest(QThread):
def close(self): def close(self):
self.c.close() self.c.close()
self.c_xs.close() self.c_xs.close()
self.logger("INFO", "openapi", f"hmi: 关闭 Socket 连接成功", "green") clibs.logger("INFO", "openapi", f"hmi: 关闭 Socket 连接成功", "green")
def __socket_conn(self): def __socket_conn(self):
# self.close() # self.close()
@ -377,9 +375,9 @@ class HmiRequest(QThread):
_ = self.execution("controller.heart") _ = self.execution("controller.heart")
time.sleep(clibs.INTERVAL/4) time.sleep(clibs.INTERVAL/4)
clibs.status["hmi"] = 1 clibs.status["hmi"] = 1
self.logger("INFO", "openapi", "hmi: HMI connection success...", "green") clibs.logger("INFO", "openapi", "hmi: HMI connection success...", "green")
except Exception: except Exception:
self.logger("ERROR", "openapi", f"hmi: HMI connection failed...", "red") clibs.logger("ERROR", "openapi", f"hmi: HMI connection failed...", "red")
@staticmethod @staticmethod
def package(cmd): def package(cmd):
@ -410,7 +408,7 @@ class HmiRequest(QThread):
callback = key.data callback = key.data
callback(key.fileobj, mask) callback(key.fileobj, mask)
except Exception as err: except Exception as err:
self.logger("DEBUG", "openapi", f"hmi: 老协议解包报错 err = {err}") clibs.logger("DEBUG", "openapi", f"hmi: 老协议解包报错 err = {err}")
def __get_headers(self, index, data): def __get_headers(self, index, data):
if index + 8 < len(data): if index + 8 < len(data):
@ -423,7 +421,7 @@ class HmiRequest(QThread):
else: else:
# print("hr-get_headers: 解包数据有误,需要确认!") # print("hr-get_headers: 解包数据有误,需要确认!")
# print(data) # print(data)
self.logger("ERROR", "openapi", f"hmi: 解包数据有误,需要确认,最后一个数据包如下 {data}", "red") clibs.logger("ERROR", "openapi", f"hmi: 解包数据有误,需要确认,最后一个数据包如下 {data}", "red")
else: else:
self.__half_pkg = data[index:] self.__half_pkg = data[index:]
self.__half_pkg_flag = True self.__half_pkg_flag = True
@ -451,7 +449,7 @@ class HmiRequest(QThread):
if len(data[self.__index:]) >= pkg_value: if len(data[self.__index:]) >= pkg_value:
self.__response = data[self.__index:self.__index + pkg_value] self.__response = data[self.__index:self.__index + pkg_value]
self.__index += pkg_value self.__index += pkg_value
self.logger("DEBUG", "openapi", str(json.loads(self.__response.decode()))) clibs.logger("DEBUG", "openapi", str(json.loads(self.__response.decode())))
self.__response = b"" self.__response = b""
self.__leftovers = 0 self.__leftovers = 0
self.__is_first_frame = True self.__is_first_frame = True
@ -499,7 +497,7 @@ class HmiRequest(QThread):
if self.__valid_data_length == 0: if self.__valid_data_length == 0:
# with open(f"{clibs.log_path}/response.txt", mode="a", encoding="utf-8") as f_res: # with open(f"{clibs.log_path}/response.txt", mode="a", encoding="utf-8") as f_res:
# f_res.write(f"{json.loads(self.__response.decode())}" + "\n") # f_res.write(f"{json.loads(self.__response.decode())}" + "\n")
self.logger("DEBUG", "openapi", str(json.loads(self.__response.decode()))) clibs.logger("DEBUG", "openapi", str(json.loads(self.__response.decode())))
self.__response = b"" self.__response = b""
self.__is_first_frame = True self.__is_first_frame = True
continue # 此时应该重新 get_headers continue # 此时应该重新 get_headers
@ -529,7 +527,7 @@ class HmiRequest(QThread):
self.__response += data[:self.__leftovers] self.__response += data[:self.__leftovers]
self.__index = self.__leftovers self.__index = self.__leftovers
self.__leftovers = 0 self.__leftovers = 0
self.logger("DEBUG", "openapi", str(json.loads(self.__response.decode()))) clibs.logger("DEBUG", "openapi", str(json.loads(self.__response.decode())))
self.__response = b"" self.__response = b""
self.__is_first_frame = True self.__is_first_frame = True
elif len(data) < self.__leftovers: elif len(data) < self.__leftovers:
@ -584,7 +582,7 @@ class HmiRequest(QThread):
self.__half_frm_flag = -1 self.__half_frm_flag = -1
if self.__valid_data_length == 0: if self.__valid_data_length == 0:
self.logger("DEBUG", "openapi", str(json.loads(self.__response.decode()))) clibs.logger("DEBUG", "openapi", str(json.loads(self.__response.decode())))
self.__response = b"" self.__response = b""
self.__is_first_frame = True self.__is_first_frame = True
continue continue
@ -612,7 +610,7 @@ class HmiRequest(QThread):
self.__index += frm_value self.__index += frm_value
self.__valid_data_length -= frm_value self.__valid_data_length -= frm_value
if self.__valid_data_length == 0: if self.__valid_data_length == 0:
self.logger("DEBUG", "openapi", str(json.loads(self.__response.decode()))) clibs.logger("DEBUG", "openapi", str(json.loads(self.__response.decode())))
self.__response = b"" self.__response = b""
self.__is_first_frame = True self.__is_first_frame = True
continue continue
@ -646,7 +644,7 @@ class HmiRequest(QThread):
# if self.__valid_data_length < 0 or self.__leftovers > 1024: # if self.__valid_data_length < 0 or self.__leftovers > 1024:
# print(f"data = {data}") # print(f"data = {data}")
# raise Exception("DataError") # raise Exception("DataError")
self.logger("ERROR", "openapi", "hmi: will never be here", "red") clibs.logger("ERROR", "openapi", "hmi: will never be here", "red")
@staticmethod @staticmethod
def package_xs(cmd): def package_xs(cmd):
@ -672,7 +670,7 @@ class HmiRequest(QThread):
callback = key.data callback = key.data
callback(key.fileobj, mask) callback(key.fileobj, mask)
except Exception as err: except Exception as err:
self.logger("DEBUG", "openapi", f"hmi: xService解包报错 err = {err}") clibs.logger("DEBUG", "openapi", f"hmi: xService解包报错 err = {err}")
def get_response_xs(self, data): def get_response_xs(self, data):
char, response = "", self.__response_xs char, response = "", self.__response_xs
@ -680,7 +678,7 @@ class HmiRequest(QThread):
if char != "\r": if char != "\r":
response = "".join([response, char]) response = "".join([response, char])
else: else:
self.logger("DEBUG", "openapi", response) clibs.logger("DEBUG", "openapi", response)
self.response_xs = response self.response_xs = response
response = "" response = ""
else: else:
@ -704,7 +702,7 @@ class HmiRequest(QThread):
if flag is True: if flag is True:
return records return records
else: else:
self.logger("ERROR", "openapi", f"hmi: {time_delay}s内无法找到请求 {msg_id} 的响应!", "red") clibs.logger("ERROR", "openapi", f"hmi: {time_delay}s内无法找到请求 {msg_id} 的响应!", "red")
def execution(self, command, **kwargs): def execution(self, command, **kwargs):
req = None req = None
@ -716,7 +714,7 @@ class HmiRequest(QThread):
flag = req["p_type"] flag = req["p_type"]
del req["p_type"] del req["p_type"]
except Exception as err: except Exception as err:
self.logger("ERROR", "openapi", f"hmi: 暂不支持 {command} 功能,或确认该功能存在...<br>err = {err}", "red") clibs.logger("ERROR", "openapi", f"hmi: 暂不支持 {command} 功能,或确认该功能存在...<br>err = {err}", "red")
match command: match command:
case "state.set_tp_mode" | "overview.set_autoload" | "overview.reload" | "rl_task.pp_to_main" | "rl_task.run" | "rl_task.stop" | "rl_task.set_run_params" | "diagnosis.set_params" | "diagnosis.open" | "drag.set_params" | "controller.set_params" | "collision.set_state" | "collision.set_params" | "move.set_quickstop_distance" | "move.set_params" | "move.set_monitor_cfg" | "modbus.get_values" | "modbus.set_params" | "system_io.update_configuration" | "diagnosis.get_params" | "jog.set_params" | "jog.start" | "move.stop" | "move.quick_turn" | "move.set_quickturn_pos" | "soft_limit.set_params" | "fieldbus_device.set_params" | "socket.set_params" | "diagnosis.save" | "register.set_value": case "state.set_tp_mode" | "overview.set_autoload" | "overview.reload" | "rl_task.pp_to_main" | "rl_task.run" | "rl_task.stop" | "rl_task.set_run_params" | "diagnosis.set_params" | "diagnosis.open" | "drag.set_params" | "controller.set_params" | "collision.set_state" | "collision.set_params" | "move.set_quickstop_distance" | "move.set_params" | "move.set_monitor_cfg" | "modbus.get_values" | "modbus.set_params" | "system_io.update_configuration" | "diagnosis.get_params" | "jog.set_params" | "jog.start" | "move.stop" | "move.quick_turn" | "move.set_quickturn_pos" | "soft_limit.set_params" | "fieldbus_device.set_params" | "socket.set_params" | "diagnosis.save" | "register.set_value":
@ -733,18 +731,18 @@ class HmiRequest(QThread):
try: try:
self.c.send(self.package(cmd)) self.c.send(self.package(cmd))
time.sleep(clibs.INTERVAL/4) # 这里一定是要等几百毫秒的避免多指令同一时间发送导致xCore不响应 time.sleep(clibs.INTERVAL/4) # 这里一定是要等几百毫秒的避免多指令同一时间发送导致xCore不响应
self.logger("DEBUG", "openapi", f"hmi: 老协议请求发送成功 {cmd}") clibs.logger("DEBUG", "openapi", f"hmi: 老协议请求发送成功 {cmd}")
except Exception as err: except Exception as err:
if "controller.heart" in cmd: if "controller.heart" in cmd:
raise Exception() raise Exception()
self.logger("ERROR", "openapi", f"hmi: 老协议请求发送失败 {cmd},报错信息 {err}", "red") clibs.logger("ERROR", "openapi", f"hmi: 老协议请求发送失败 {cmd},报错信息 {err}", "red")
elif flag == 1: elif flag == 1:
try: try:
self.c_xs.send(self.package_xs(req)) self.c_xs.send(self.package_xs(req))
time.sleep(clibs.INTERVAL/4) time.sleep(clibs.INTERVAL/4)
self.logger("DEBUG", "openapi", f"hmi: xService请求发送成功 {req}") clibs.logger("DEBUG", "openapi", f"hmi: xService请求发送成功 {req}")
except Exception as err: except Exception as err:
self.logger("ERROR", "openapi", f"hr: xService请求发送失败 {req} 报错信息 {err}", "red") clibs.logger("ERROR", "openapi", f"hr: xService请求发送失败 {req} 报错信息 {err}", "red")
return req["id"] return req["id"]
@ -762,7 +760,7 @@ class HmiRequest(QThread):
case "off": case "off":
self.execution("state.switch_motor_off") self.execution("state.switch_motor_off")
case _: case _:
self.logger("ERROR", "openapi", f"hmi: switch_motor_state 参数错误 {state} 非法参数,只接受 on/off", "red") clibs.logger("ERROR", "openapi", f"hmi: switch_motor_state 参数错误 {state} 非法参数,只接受 on/off", "red")
def switch_operation_mode(self, mode: str): # OK def switch_operation_mode(self, mode: str): # OK
""" """
@ -776,7 +774,7 @@ class HmiRequest(QThread):
case "manual": case "manual":
self.execution("state.switch_manual") self.execution("state.switch_manual")
case _: case _:
self.logger("ERROR", "openapi", f"hmi: switch_operation_mode 参数错误 {mode},非法参数,只接受 auto/manual", "red") clibs.logger("ERROR", "openapi", f"hmi: switch_operation_mode 参数错误 {mode},非法参数,只接受 auto/manual", "red")
def reload_project(self, prj_name: str, tasks: list): # OK def reload_project(self, prj_name: str, tasks: list): # OK
""" """
@ -842,7 +840,7 @@ class HmiRequest(QThread):
:return: None :return: None
""" """
self.execution("controller.reboot") self.execution("controller.reboot")
self.logger("INFO", "openapi", f"hmi: 控制器重启中,重连预计需要等待 100s 左右...") clibs.logger("INFO", "openapi", f"hmi: 控制器重启中,重连预计需要等待 100s 左右...")
ts = time.time() ts = time.time()
time.sleep(30) time.sleep(30)
while True: while True:
@ -857,7 +855,7 @@ class HmiRequest(QThread):
break break
time.sleep(2) time.sleep(2)
else: else:
self.logger("INFO", "openapi", "hr: HMI 重新连接成功...", "green") clibs.logger("INFO", "openapi", "hr: HMI 重新连接成功...", "green")
break break
def reload_io(self): def reload_io(self):
@ -1483,7 +1481,7 @@ class HmiRequest(QThread):
case "without": case "without":
self.execution("state.set_tp_mode", tp_mode="without") self.execution("state.set_tp_mode", tp_mode="without")
case _: case _:
self.logger("ERROR", "openapi", f"hmi: switch_tp_mode 参数错误{mode} 非法参数,只接受 with/without", "red") clibs.logger("ERROR", "openapi", f"hmi: switch_tp_mode 参数错误{mode} 非法参数,只接受 with/without", "red")
@property @property
def get_tp_mode(self): # OK def get_tp_mode(self): # OK
@ -1745,7 +1743,6 @@ class ExternalCommunication(QThread):
self.port = int(port) self.port = int(port)
self.suffix = "\r" self.suffix = "\r"
self.exec_desc = " :--: 返回 true 表示执行成功false 失败" self.exec_desc = " :--: 返回 true 表示执行成功false 失败"
self.logger = clibs.logger
def net_conn(self): def net_conn(self):
clibs.c_hr.execution("socket.set_params", enable=False, ip="0.0.0.0", port=str(self.port), suffix="\r", type=1) clibs.c_hr.execution("socket.set_params", enable=False, ip="0.0.0.0", port=str(self.port), suffix="\r", type=1)
@ -1756,14 +1753,14 @@ class ExternalCommunication(QThread):
self.c.settimeout(clibs.INTERVAL*3) self.c.settimeout(clibs.INTERVAL*3)
try: try:
self.c.connect((self.ip, self.port)) self.c.connect((self.ip, self.port))
self.logger("INFO", "openapi", f"ec: 外部通信连接成功...", "green") clibs.logger("INFO", "openapi", f"ec: 外部通信连接成功...", "green")
# return self.c # return self.c
except Exception as err: except Exception as err:
self.logger("ERROR", "openapi", f"ec: 外部通信连接失败... {err}", "red") clibs.logger("ERROR", "openapi", f"ec: 外部通信连接失败... {err}", "red")
def close(self): def close(self):
self.c.close() self.c.close()
self.logger("INFO", "openapi", f"ec: 关闭外部通信连接成功", "green") clibs.logger("INFO", "openapi", f"ec: 关闭外部通信连接成功", "green")
@clibs.db_lock @clibs.db_lock
def sr_string(self, directive, interval=clibs.INTERVAL/2): def sr_string(self, directive, interval=clibs.INTERVAL/2):
@ -2022,7 +2019,7 @@ class ExternalCommunication(QThread):
self.s_string(directive) self.s_string(directive)
time.sleep(clibs.INTERVAL/2) time.sleep(clibs.INTERVAL/2)
result = self.r_string(directive).strip() result = self.r_string(directive).strip()
self.logger("DEBUG", "openapi", f"ec: 执行{description}指令是 {directive},返回值为 {result}{more_desc}") clibs.logger("DEBUG", "openapi", f"ec: 执行{description}指令是 {directive},返回值为 {result}{more_desc}")
return result return result
@ -2034,7 +2031,6 @@ class PreDos(object):
self.ssh_port = ssh_port self.ssh_port = ssh_port
self.username = username self.username = username
self.password = password self.password = password
self.logger = clibs.logger
def __ssh2server(self): def __ssh2server(self):
try: try:
@ -2043,7 +2039,7 @@ class PreDos(object):
self.__ssh.connect(hostname=self.ip, port=self.ssh_port, username=self.username, password=self.password) self.__ssh.connect(hostname=self.ip, port=self.ssh_port, username=self.username, password=self.password)
self.__sftp = self.__ssh.open_sftp() self.__sftp = self.__ssh.open_sftp()
except Exception as err: except Exception as err:
self.logger("ERROR", "openapi", f"predos: SSH 无法连接到 {self.ip}:{self.ssh_port},需检查网络连通性或者登录信息是否正确 {err}", "red") clibs.logger("ERROR", "openapi", f"predos: SSH 无法连接到 {self.ip}:{self.ssh_port},需检查网络连通性或者登录信息是否正确 {err}", "red")
def push_prj_to_server(self, prj_file): def push_prj_to_server(self, prj_file):
# prj_file本地工程完整路径 # prj_file本地工程完整路径

View File

@ -1,4 +1,5 @@
import json import json
import os.path
import threading import threading
import time import time
import pandas import pandas
@ -22,7 +23,6 @@ class DoFactoryTest(QThread):
self.procs = procs self.procs = procs
self.idx = 6 self.idx = 6
self.curves = [] self.curves = []
self.logger = clibs.logger
def initialization(self, data_dirs, data_files): def initialization(self, data_dirs, data_files):
def check_files(): def check_files():
@ -31,13 +31,13 @@ class DoFactoryTest(QThread):
self.curves.extend(self.curve_map[proc_name]) self.curves.extend(self.curve_map[proc_name])
if len(self.curves) == 0: if len(self.curves) == 0:
self.logger("ERROR", "factory", "未查询到需要记录数据的曲线,至少选择一个!", "red") clibs.logger("ERROR", "factory", "未查询到需要记录数据的曲线,至少选择一个!", "red")
if len(data_dirs) != 0 or len(data_files) != 1: if len(data_dirs) != 0 or len(data_files) != 1:
self.logger("ERROR", "factory", "初始路径下不允许有文件夹,且初始路径下只能存在一个工程文件 —— *.zip确认后重新运行", "red") clibs.logger("ERROR", "factory", "初始路径下不允许有文件夹,且初始路径下只能存在一个工程文件 —— *.zip确认后重新运行", "red")
if not data_files[0].endswith(".zip"): if not data_files[0].endswith(".zip"):
self.logger("ERROR", "factory", f"{data_files[0]} 不是一个有效的工程文件,需确认!", "red") clibs.logger("ERROR", "factory", f"{data_files[0]} 不是一个有效的工程文件,需确认!", "red")
return data_files[0] return data_files[0]
@ -55,17 +55,17 @@ class DoFactoryTest(QThread):
try: try:
with open(local_file, mode="r", encoding="utf-8") as f_config: with open(local_file, mode="r", encoding="utf-8") as f_config:
configs = json.load(f_config) configs = json.load(f_config)
except Exception as Err: except Exception as err:
self.logger("ERROR", "factory", f"无法打开 {local_file}<br>{Err}", "red") clibs.logger("ERROR", "factory", f"无法打开 {local_file}<br>{err}", "red")
# 最大角速度,额定电流,减速比,额定转速 # 最大角速度,额定电流,减速比,额定转速
version = configs["VERSION"] version = configs["VERSION"]
m_avs = configs["MOTION"]["JOINT_MAX_SPEED"] m_avs = configs["MOTION"]["JOINT_MAX_SPEED"]
self.logger("INFO", "factory", f"get_configs: 机型文件版本 {robot_type}_{version}") clibs.logger("INFO", "factory", f"get_configs: 机型文件版本 {robot_type}_{version}")
self.logger("INFO", "factory", f"get_configs: 各关节角速度 {m_avs}") clibs.logger("INFO", "factory", f"get_configs: 各关节角速度 {m_avs}")
return m_avs return m_avs
self.logger("INFO", "factory", "正在做初始化校验和配置,这可能需要一点时间......", "green") clibs.logger("INFO", "factory", "正在做初始化校验和配置,这可能需要一点时间......", "green")
prj_file = check_files() prj_file = check_files()
if prj_file is None: if prj_file is None:
return return
@ -75,7 +75,7 @@ class DoFactoryTest(QThread):
"interval": self.interval, "interval": self.interval,
"avs": avs, "avs": avs,
} }
self.logger("INFO", "factory", "数据目录合规性检查结束,未发现问题......", "green") clibs.logger("INFO", "factory", "数据目录合规性检查结束,未发现问题......", "green")
return params return params
def change_curve_state(self, stat): def change_curve_state(self, stat):
@ -103,7 +103,7 @@ class DoFactoryTest(QThread):
clibs.c_hr.execution("state.switch_motor_on") clibs.c_hr.execution("state.switch_motor_on")
# 3. 开始运行程序 # 3. 开始运行程序
self.logger("INFO", "factory", f"正在采集场景工程的周期,大概1min左右......", "blue") clibs.logger("INFO", "factory", f"正在采集场景工程的周期,根据周期长短大约需要2~5分钟左右......", "blue")
clibs.c_hr.execution("rl_task.set_run_params", loop_mode=True, override=1.0) clibs.c_hr.execution("rl_task.set_run_params", loop_mode=True, override=1.0)
clibs.c_hr.execution("rl_task.run", tasks=["factory"]) clibs.c_hr.execution("rl_task.run", tasks=["factory"])
t_start = time.time() t_start = time.time()
@ -113,7 +113,7 @@ class DoFactoryTest(QThread):
break break
else: else:
if (time.time() - t_start) > 15: if (time.time() - t_start) > 15:
self.logger("ERROR", "factory", "15s 内未收到机器人的运行信号需要确认RL程序编写正确并正常执行...", "red") clibs.logger("ERROR", "factory", "15s 内未收到机器人的运行信号需要确认RL程序编写正确并正常执行...", "red")
else: else:
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
@ -123,12 +123,12 @@ class DoFactoryTest(QThread):
while True: while True:
scenario_time = float(f"{float(clibs.c_md.read_scenario_time()):.2f}") scenario_time = float(f"{float(clibs.c_md.read_scenario_time()):.2f}")
if scenario_time != 0: if scenario_time != 0:
self.logger("INFO", "factory", f"耐久工程的周期时间:{scenario_time}s | 单轮次执行时间:{scenario_time+interval}~{scenario_time*2+interval}") clibs.logger("INFO", "factory", f"耐久工程的周期时间:{scenario_time}s | 单轮次执行时间:{scenario_time+interval}~{scenario_time*2+interval}")
break break
else: else:
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
if (time.time() - t_start) > 900: if (time.time() - t_start) > 900:
self.logger("ERROR", "factory", f"900s内未收到耐久工程的周期时间需要确认RL程序和工具通信交互是否正常执行支持最长工程周期时间为300s......", "red") clibs.logger("ERROR", "factory", f"900s内未收到耐久工程的周期时间需要确认RL程序和工具通信交互是否正常执行支持最长工程周期时间为300s......", "red")
# 6. 准备数据保存文件 # 6. 准备数据保存文件
for proc_name, is_enabled in self.procs.items(): for proc_name, is_enabled in self.procs.items():
@ -148,7 +148,7 @@ class DoFactoryTest(QThread):
this_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) this_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
next_time_1 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()+scenario_time+interval+1)) next_time_1 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()+scenario_time+interval+1))
next_time_2 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()+scenario_time+interval+1+scenario_time)) next_time_2 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()+scenario_time+interval+1+scenario_time))
self.logger("INFO", "factory", f"[{this_time}] 当前次数:{count:09d} | 预计下次数据更新时间:{next_time_1}~{next_time_2}", "#008B8B") clibs.logger("INFO", "factory", f"[{this_time}] 当前次数:{count:09d} | 预计下次数据更新时间:{next_time_1}~{next_time_2}", "#008B8B")
count += 1 count += 1
# 固定间隔,更新一次数据,打开曲线,获取周期内电流,关闭曲线 # 固定间隔,更新一次数据,打开曲线,获取周期内电流,关闭曲线
time.sleep(interval) time.sleep(interval)
@ -166,9 +166,9 @@ class DoFactoryTest(QThread):
self.change_curve_state(False) self.change_curve_state(False)
# 保留数据并处理输出 # 保留数据并处理输出
self.gen_results(params, start_time, end_time) self.gen_results(params, start_time, end_time)
else:
clibs.stop_flag = False clibs.stop_flag = False
self.logger("INFO", "factory", "后台数据清零完成,现在可以重新运行其他程序。", "green") clibs.logger("INFO", "factory", "后台数据清零完成,现在可以重新运行其他程序。", "green")
def gen_results(self, params, start_time, end_time): def gen_results(self, params, start_time, end_time):
s_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time)) s_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time))
@ -199,80 +199,69 @@ class DoFactoryTest(QThread):
t.start() t.start()
def get_avg_trq(self, records, params, proc_name): def get_avg_trq(self, records, params, proc_name):
d_trq, results = [[], [], [], [], [], []], [time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))] t = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
d_trq = {f"device_servo_trq_feedback_{axis}": [] for axis in range(6)}
result_data, result_file = [t, ], f"device_servo_trq_feedback_{t}"
for record in records: for record in records:
data = eval(record[0])["data"] data = eval(record[0])["data"]
for item in data: for item in data:
d_item = reversed(item["value"])
for axis in range(6): for axis in range(6):
if item.get("channel", None) == axis and item.get("name", None) == "device_servo_trq_feedback": if item.get("channel", None) == axis and item.get("name", None) == "device_servo_trq_feedback":
d_trq[axis].extend(d_item) d_trq[f"device_servo_trq_feedback_{axis}"].extend(reversed(item["value"]))
for axis in range(6): for axis in range(6):
df = pandas.DataFrame.from_dict({"device_servo_trq_feedback": d_trq[axis]}) df = pandas.DataFrame.from_dict({"device_servo_trq_feedback": d_trq[f"device_servo_trq_feedback_{axis}"]})
_ = math.sqrt(numpy.square(df[df.columns[0]].values * 1.27 / 1000).sum() / len(df)) _ = math.sqrt(numpy.square(df[df.columns[0]].values * 1.27 / 1000).sum() / len(df))
results.append(_) result_data.append(_)
path = "/".join(params["prj_file"].split("/")[:-1]) path = "/".join(params["prj_file"].split("/")[:-1])
with open(f"{path}/{proc_name}.csv", mode="a+", newline="") as f_csv: with open(f"{path}/{proc_name}.csv", mode="a+", newline="") as f_csv:
csv_writer = csv.writer(f_csv) csv_writer = csv.writer(f_csv)
csv_writer.writerow(results) csv_writer.writerow(result_data)
if not os.path.exists(f"{path}/{proc_name}/"):
os.mkdir(f"{path}/{proc_name}/")
df = pandas.DataFrame.from_dict(d_trq)
df.to_csv(f"{path}/{proc_name}/{result_file}.csv", index=False)
def get_joint_max_vel(self, records, params, proc_name): def get_joint_max_vel(self, records, params, proc_name):
d_trq, results = [[], [], [], [], [], []], [time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))] t = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
d_vel = {f"hw_joint_vel_feedback_{axis}": [] for axis in range(6)}
result_data, result_file = [t, ], f"hw_joint_vel_feedback_{t}"
for record in records: for record in records:
data = eval(record[0])["data"] data = eval(record[0])["data"]
for item in data: for item in data:
d_item = reversed(item["value"])
for axis in range(6): for axis in range(6):
if item.get("channel", None) == axis and item.get("name", None) == "hw_joint_vel_feedback": if item.get("channel", None) == axis and item.get("name", None) == "hw_joint_vel_feedback":
d_trq[axis].extend(d_item) d_vel[f"hw_joint_vel_feedback_{axis}"].extend(reversed(item["value"]))
for axis in range(6): for axis in range(6):
df = pandas.DataFrame.from_dict({"hw_joint_vel_feedback": d_trq[axis]}) df = pandas.DataFrame.from_dict({"hw_joint_vel_feedback": d_vel[f"hw_joint_vel_feedback_{axis}"]})
_ = df.max().iloc[0] _ = df.max().iloc[0]
results.append(_) result_data.append(_)
path = "/".join(params["prj_file"].split("/")[:-1]) path = "/".join(params["prj_file"].split("/")[:-1])
with open(f"{path}/{proc_name}.csv", mode="a+", newline="") as f_csv: with open(f"{path}/{proc_name}.csv", mode="a+", newline="") as f_csv:
csv_writer = csv.writer(f_csv) csv_writer = csv.writer(f_csv)
csv_writer.writerow(results) csv_writer.writerow(result_data)
@staticmethod if not os.path.exists(f"{path}/{proc_name}/"):
def detect_db_size(): os.mkdir(f"{path}/{proc_name}/")
@clibs.db_lock df = pandas.DataFrame.from_dict(d_vel)
def release_memory(): df.to_csv(f"{path}/{proc_name}/{result_file}.csv", index=False)
line_number = 20000
leftover = 4000 # 200s
clibs.cursor.execute("SELECT COUNT(id) FROM logs")
len_records = clibs.cursor.fetchone()[0]
if len_records > line_number:
del_num = len_records - leftover + 1
clibs.cursor.execute(f"DELETE FROM logs WHERE id < {del_num}")
clibs.cursor.execute(f"UPDATE logs SET id=(id-{del_num - 1}) WHERE id > {del_num - 1}")
clibs.cursor.execute(f"UPDATE sqlite_sequence SET seq = {leftover + 1} WHERE name = 'logs' ")
clibs.cursor.execute("VACUUM")
while True:
release_memory()
time.sleep(clibs.INTERVAL*10)
def processing(self): def processing(self):
time_start = time.time() time_start = time.time()
clibs.running[self.idx] = 1 clibs.running[self.idx] = 1
if clibs.status["hmi"] != 1 or clibs.status["md"] != 1: if clibs.status["hmi"] != 1 or clibs.status["md"] != 1:
self.logger("ERROR", "factory", "processing: 需要在网络设置中连接HMI以及Modbus通信", "red") clibs.logger("ERROR", "factory", "processing: 需要在网络设置中连接HMI以及Modbus通信", "red")
t = threading.Thread(target=self.detect_db_size)
t.daemon = True
t.start()
data_dirs, data_files = clibs.traversal_files(self.dir_path) data_dirs, data_files = clibs.traversal_files(self.dir_path)
params = self.initialization(data_dirs, data_files) params = self.initialization(data_dirs, data_files)
clibs.c_pd.push_prj_to_server(params["prj_file"]) clibs.c_pd.push_prj_to_server(params["prj_file"])
self.run_rl(params) self.run_rl(params)
self.logger("INFO", "factory", "-"*60 + "<br>全部处理完毕<br>", "purple") clibs.logger("INFO", "factory", "-"*60 + "<br>全部处理完毕<br>", "purple")
time_total = time.time() - time_start time_total = time.time() - time_start
msg = f"处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s" msg = f"处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s"
self.logger("INFO", "factory", msg) clibs.logger("INFO", "factory", msg)

View File

@ -225,7 +225,7 @@
</font> </font>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<property name="elideMode"> <property name="elideMode">
<enum>Qt::TextElideMode::ElideNone</enum> <enum>Qt::TextElideMode::ElideNone</enum>
@ -559,7 +559,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>213</width> <width>212</width>
<height>78</height> <height>78</height>
</rect> </rect>
</property> </property>