转向从机型配置文件获取参数

This commit is contained in:
gitea 2025-01-14 14:14:33 +08:00
parent 137122947c
commit 0e67a2831c
25 changed files with 524877 additions and 203 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
{
"id": "xxxxxxxxxxx",
"module": "system",
"command": "controller.get_params"
}

View File

@ -15,6 +15,7 @@ from datetime import datetime
import os
from common import clibs, openapi
from data_process import current, brake, iso, wavelogger
from automatic_test import do_current
import threading
import re
@ -118,6 +119,7 @@ class App:
self.label_tips = ctk.CTkLabel(self.frame_status, textvariable=var_tips, compound="left", bg_color="#C9C9C9", font=self.f_status, anchor="e")
self.__auth_and_vercheck()
if local_vers == self.server_vers:
# if True:
image = ctk.CTkImage(Image.open(f"{clibs.PREFIX}/media/updated.png"), size=(16, 16))
var_tips.set(" 当前是最新版本,继续保持! ")
self.label_tips.configure(text_color="#0D8A3D", image=image)
@ -207,6 +209,12 @@ class App:
clibs.running = False
raise Exception(desc)
@staticmethod
def __is_running(operation):
if clibs.running:
messagebox.showerror(title="处理中", message=f"有程序正在运行,需等待结束后,在执行{operation}操作!")
return
def __program_start(self):
def get_data_dp():
data = {
@ -230,10 +238,11 @@ class App:
return data
def init_op():
self.__is_running("开始")
self.text_output.delete("1.0", ctk.END)
self.tabview_bottom.set("输出")
clibs.tl_prg = self.__toplevel_progress
if clibs.db_state != "readwrite":
self.text_output.delete("1.0", ctk.END)
clibs.cursor.close()
clibs.conn.close()
clibs.conn = self.conn
@ -241,8 +250,6 @@ class App:
clibs.db_state = "readwrite"
self.btn_load.configure(fg_color="#979DA2")
self.__get_realtime_log()
clibs.tl_prg = self.__toplevel_progress
# TBD: something signifies status of program and terminate some thread ect.
def exec_function():
init_op()
@ -250,15 +257,22 @@ class App:
if not clibs.running:
clibs.running = True
clibs.data_dp = get_data_dp()
eval(clibs.data_dp["_main"] + ".main()")
clibs.running = False
try:
eval(clibs.data_dp["_main"] + ".main()")
finally:
clibs.running = False
else:
messagebox.showinfo(title="进行中...", message="当前有程序正在运行!")
elif self.tabview_top.get() == "自动测试":
clibs.running = True
clibs.data_at = get_data_at()
eval(clibs.data_at["_main"] + ".main()")
clibs.running = False
if not clibs.running:
clibs.running = True
clibs.data_at = get_data_at()
try:
eval("do_" + clibs.data_at["_main"] + ".main()")
finally:
clibs.running = False
else:
messagebox.showinfo(title="进行中...", message="当前有程序正在运行!")
exec_function()
@ -270,6 +284,8 @@ class App:
self.entry_path_atv.set("数据文件夹路径")
self.entry_path_atv.set("数据文件夹路径")
self.__is_running("重置")
if clibs.db_state == "readwrite":
res = messagebox.askyesno(title="状态重置", message="这将清空本次所有的输出以及日志记录,且不可恢复,请确认!", default=messagebox.NO, icon=messagebox.WARNING)
if res:
@ -278,13 +294,14 @@ class App:
clibs.lock.acquire(True)
clibs.cursor.execute("delete from logs")
clibs.cursor.execute("delete from sqlite_sequence") # 主键归零
except Exception:
self.__w2t("主键归零操作失败", "red")
finally:
clibs.lock.release()
self.treeview_logs.delete(*self.treeview_logs.get_children())
self.label_pages_logs.set("-.-.-.-.-.-")
reset_methods()
# TBD: something signifies status of program and terminate some thread ect.
elif clibs.db_state == "readonly":
res = messagebox.askyesno(title="状态重置", message="这将清空本次所有的输出以及恢复本次的日志记录,请确认!", default=messagebox.NO, icon=messagebox.INFO)
if res:
@ -296,12 +313,11 @@ class App:
clibs.db_state = "readwrite"
self.__get_realtime_log()
reset_methods()
# TBD: something signifies status of program and terminate some thread ect.
@clibs.db_lock
def __get_realtime_log(self):
clibs.cursor.execute("select id from logs")
len_records = len(clibs.cursor.fetchall())
clibs.cursor.execute("select count(id) from logs")
len_records = clibs.cursor.fetchone()[0]
pages_all = len_records // 100 if len_records % 100 == 0 else len_records // 100 + 1
self.label_pages_logs.set(f"{pages_all} / {pages_all}")
@ -333,14 +349,14 @@ class App:
self.treeview_logs.delete(*self.treeview_logs.get_children())
for record in records:
self.treeview_logs.insert("", "end", values=record, tags=record[2])
# self.treeview_logs.yview_moveto(1)
self.treeview_logs.yview_moveto(0)
clibs.cursor.execute("select * from logs order by id desc")
records = clibs.cursor.fetchall()
pages_all = len(records) // 100 if len(records) % 100 == 0 else len(records) // 100 + 1
clibs.cursor.execute("select count(id) from logs")
len_records = clibs.cursor.fetchone()[0]
pages_all = len_records // 100 if len_records % 100 == 0 else len_records // 100 + 1
current_page = int(end) // 100 if int(end) % 100 == 0 else int(end) // 100 + 1
self.label_pages_logs.set(f"{current_page} / {pages_all}")
except Exception as ERR:
except Exception:
...
else:
pages_all = self.label_pages_logs.get().split("/")[1].strip()
@ -354,6 +370,7 @@ class App:
if index_end <= 100:
for record in clibs.f_records[:index_end]:
self.treeview_logs.insert("", "end", values=record, tags=record[2])
self.treeview_logs.yview_moveto(0)
else:
for record in clibs.f_records[index_end-100:index_end]:
self.treeview_logs.insert("", "end", values=record, tags=record[2])
@ -365,10 +382,9 @@ class App:
@clibs.db_lock
def get_next_page():
if self.btn_find.cget("fg_color") == "#979DA2":
# noinspection PyBroadException
try:
clibs.cursor.execute("select id from logs")
len_records = len(clibs.cursor.fetchall())
clibs.cursor.execute("select count(id) from logs")
len_records = clibs.cursor.fetchone()[0]
row = self.treeview_logs.get_children()
last_id = self.treeview_logs.item(row[-1], "values")[0]
@ -380,18 +396,18 @@ class App:
self.treeview_logs.delete(*self.treeview_logs.get_children())
for record in records:
self.treeview_logs.insert("", "end", values=record, tags=record[2])
# self.treeview_logs.yview_moveto(1)
self.treeview_logs.yview_moveto(0)
pages_all = len_records // 100 if len_records % 100 == 0 else len_records // 100 + 1
current_page = int(start) // 100 if int(start) % 100 == 0 else int(start) // 100 + 1
self.label_pages_logs.set(f"{current_page} / {pages_all}")
except Exception as Err:
print(f"get_next_page-if: {Err}")
_pages_all = len_records // 100 if len_records % 100 == 0 else len_records // 100 + 1
_current_page = int(start) // 100 if int(start) % 100 == 0 else int(start) // 100 + 1
self.label_pages_logs.set(f"{_current_page} / {_pages_all}")
except Exception:
...
else:
len_records = len(clibs.f_records)
pages_all = int(self.label_pages_logs.get().split("/")[1].strip())
current_page = int(self.label_pages_logs.get().split("/")[0].strip())
if current_page < pages_all:
_pages_all = int(self.label_pages_logs.get().split("/")[1].strip())
_current_page = int(self.label_pages_logs.get().split("/")[0].strip())
if _current_page < _pages_all:
row = self.treeview_logs.get_children()
last_one = list(self.treeview_logs.item(row[-1], "values"))
last_one[0] = int(last_one[0])
@ -400,12 +416,14 @@ class App:
if index_start+100 <= len_records:
for record in clibs.f_records[index_start:index_start+100]:
self.treeview_logs.insert("", "end", values=record, tags=record[2])
self.treeview_logs.yview_moveto(0)
else:
for record in clibs.f_records[index_start:]:
self.treeview_logs.insert("", "end", values=record, tags=record[2])
self.treeview_logs.yview_moveto(0)
next_page = current_page + 1
self.label_pages_logs.set(f"{next_page} / {pages_all}")
_next_page = _current_page + 1
self.label_pages_logs.set(f"{_next_page} / {_pages_all}")
current_page = int(self.label_pages_logs.get().split("/")[0].strip())
pages_all = int(self.label_pages_logs.get().split("/")[1].strip())
@ -417,19 +435,24 @@ class App:
get_next_page()
def __load_log_db(self):
self.__is_running("加载")
db_file = filedialog.askopenfilename(title="加载数据库文件", defaultextension=".db", initialdir=f"{clibs.PREFIX}/logs")
if not db_file:
return
self.conn = clibs.conn
self.cursor = clibs.cursor
try:
clibs.conn = sqlite3.connect(f"file:{db_file}?mode=ro", uri=True, isolation_level=None, check_same_thread=False, cached_statements=256)
clibs.conn = sqlite3.connect(f"file:{db_file}?mode=ro", uri=True, isolation_level=None, check_same_thread=False, cached_statements=2048)
clibs.cursor = clibs.conn.cursor()
clibs.cursor.execute("PRAGMA synchronous=normal")
clibs.cursor.execute("PRAGMA temp_store=memory")
clibs.cursor.execute("PRAGMA mmap_size=30000000000")
clibs.cursor.execute("PRAGMA cache_size=200000")
clibs.db_state = "readonly"
self.__get_realtime_log()
self.btn_load.configure(fg_color="#000080")
except Exception as Err:
clibs.insert_logdb("ERROR", "aio", f"加载数据库失败,需确认 {db_file} 是否是有效数据库文件!")
clibs.insert_logdb("ERROR", "aio", f"load_log_db: 加载数据库失败,需确认 {db_file} 是否是有效数据库文件!\n{Err}")
messagebox.showerror(title="加载数据库失败", message=f"需确认 {db_file} 是否是有效数据库文件!")
def __main_switch_dp(self, event):
@ -459,7 +482,7 @@ class App:
url_vers = "http://10.2.23.150:10008/version"
try:
self.server_vers = request.urlopen(url_vers, timeout=2).read().decode("utf-8").strip()
except Exception as Err:
except Exception:
messagebox.showwarning(title="退出", message="无法连接至服务器.....")
clibs.cursor.close()
clibs.conn.close()
@ -543,7 +566,7 @@ class App:
index_start = all_text.find(selected)
index_end = index_start + len(selected)
widget.delete(index_start, index_end)
except Exception as Err:
except Exception:
...
@staticmethod
@ -556,7 +579,7 @@ class App:
index_start = all_text.find(selected)
index_end = index_start + len(selected)
widget.delete(index_start, index_end)
except Exception as Err:
except Exception:
...
@staticmethod
@ -565,7 +588,7 @@ class App:
widget.clipboard_clear()
copy_text = widget.selection_get()
widget.clipboard_append(copy_text)
except Exception as Err:
except Exception:
...
@staticmethod
@ -601,7 +624,6 @@ class App:
widget_toplevel.destroy()
def double_click(event):
# noinspection PyBroadException
try:
e = event.widget
iid = e.identify("item", event.x, event.y)
@ -616,7 +638,7 @@ class App:
toplevel.bind("<Escape>", esc_quit_log_tl)
toplevel.transient(self.root)
toplevel.focus()
_text = f"TS: {_ts} | Log level: {_level} | Module: {_module}"
_text = f"{_level} log in {_module} @ {_ts}"
label_info = ctk.CTkLabel(toplevel, text=_text, width=10, fg_color="#5F9EA0", corner_radius=5, font=self.f_treeview)
text_content = ctk.CTkTextbox(toplevel, width=10, font=self.f_toplevel)
text_content.insert(ctk.END, repr(_content))
@ -638,19 +660,19 @@ class App:
if number > 0:
start = number * 100 - 99
end = number * 100
clibs.cursor.execute("select id from logs")
len_records = len(clibs.cursor.fetchall())
clibs.cursor.execute("select count(id) from logs")
len_records = clibs.cursor.fetchone()[0]
if start <= len_records:
clibs.cursor.execute(f"select * from logs where id between {start} and {end}")
records = clibs.cursor.fetchall()
self.treeview_logs.delete(*self.treeview_logs.get_children())
for record in records:
self.treeview_logs.insert("", "end", values=record, tags=record[2])
self.treeview_logs.yview_moveto(1)
self.treeview_logs.yview_moveto(0)
pages_all = len_records // 100 if len_records % 100 == 0 else len_records // 100 + 1
self.label_pages_logs.set(f"{number} / {pages_all}")
except Exception as Err:
except Exception:
...
def close_toplevel(tl):
@ -861,22 +883,25 @@ class App:
if self.btn_conn.cget("fg_color") == "#979DA2":
self.btn_conn.configure(state="disabled")
clibs.ip_addr = self.entry_ip_atv.get().strip()
ip_pattern = re.compile(r'(([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.){3}([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])')
ip_pattern = re.compile(r"(([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.){3}([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])")
if not ip_pattern.fullmatch(clibs.ip_addr):
messagebox.showerror(title="非法地址", message=f"{clibs.ip_addr} 不是一个有效的 IP 地址")
clibs.insert_logdb("ERROR", "aio", f"connection: {clibs.ip_addr} 不是一个有效的 IP 地址")
return
try:
# clibs.c_md = openapi.ModbusRequest(clibs.ip_addr, clibs.modbus_port)
clibs.c_md = openapi.ModbusRequest(clibs.ip_addr, clibs.modbus_port)
clibs.c_hr = openapi.HmiRequest(clibs.ip_addr, clibs.socket_port, clibs.xService_port)
clibs.c_pd = openapi.PreDos(clibs.ip_addr, clibs.ssh_port, clibs.username, clibs.password)
self.btn_conn.configure(state="normal", fg_color="#2E8B57")
except Exception as Err:
except Exception:
self.btn_conn.configure(state="normal", fg_color="#979DA2")
elif self.btn_conn.cget("fg_color") == "#2E8B57":
self.btn_conn.configure(state="disabled")
try:
# clibs.c_md.close()
clibs.c_md.close()
clibs.c_hr.close()
except Exception:
...
finally:
self.btn_conn.configure(state="normal", fg_color="#979DA2")
t = threading.Thread(target=conn_or_disconn)
@ -989,10 +1014,11 @@ class App:
self.om_sensor_dp.configure(state="disabled")
# ========================================================================
clibs.w2t = self.__w2t
# clibs.insert_logdb("INFO", "aio", "AIO starts running......")
clibs.insert_logdb("INFO", "aio", "AIO starts running......")
def show(self):
if self.server_vers:
# if True:
t = threading.Thread(target=self.__detect_network)
t.daemon = True
t.start()

View File

@ -0,0 +1,67 @@
from sys import argv
from commons import clibs
tab_name = clibs.tab_names['at']
logger = clibs.log_prod
def trigger_estop(md, w2t):
md.trigger_estop()
w2t("触发急停成功,可点击机器状态验证。", 0, 0, 'green', tab_name)
def reset_estop(md, w2t):
md.reset_estop()
w2t("恢复急停成功,可点击机器状态验证。", 0, 0, 'green', tab_name)
def get_state(hr, w2t):
# 获取机器状态
_response = clibs.execution('state.get_state', hr, w2t, tab_name)
stat_desc = {'engine': '上电状态', 'operate': '操作模式', 'rc_state': '控制器状态', 'robot_action': '机器人动作', 'safety_mode': '安全模式', 'servo_mode': '伺服工作模式', 'task_space': '工作任务空间'}
for component, state in _response['data'].items():
w2t(f"{stat_desc[component]}: {state}", tab_name=tab_name)
# 获取设备伺服信息
_response = clibs.execution('device.get_params', hr, w2t, tab_name)
dev_desc = {0: '伺服版本', 1: '伺服参数', 2: '安全板固件', 3: '控制器', 4: '通讯总线', 5: '解释器', 6: '运动控制', 8: '力控版本', 9: '末端固件', 10: '机型文件', 11: '环境包'}
dev_vers = {}
for device in _response['data']['devices']:
dev_vers[device['type']] = device['version']
for i in sorted(dev_desc.keys()):
w2t(f"{dev_desc[i]}: {dev_vers[i]}", tab_name=tab_name)
# 设置示教器模式
_response = clibs.execution('state.set_tp_mode', hr, w2t, tab_name, tp_mode='without')
def warning_info(hr, w2t):
for postfix in ['', '.2', '.3', '.4', '.5', '.6', '.7', '.8', '.9', '.10']:
log_name = clibs.log_data_hmi + postfix
try:
with open(log_name, 'r', encoding='utf-8') as f_log:
for line in f_log:
if 'alarm' in line:
w2t(line.strip(), tab_name=tab_name)
except FileNotFoundError:
pass
def main(hr, md, func, w2t):
if hr is None:
w2t("无法连接机器人检查是否已经使用Robot Assist软件连接机器重试中...", 0, 49, 'red', tab_name)
# func: get_state/
match func:
case 'trigger_estop':
trigger_estop(md, w2t)
case 'reset_estop':
reset_estop(md, w2t)
case 'get_state':
get_state(hr, w2t)
case 'warning_info':
warning_info(hr, w2t)
if __name__ == '__main__':
main(*argv[1:])

View File

@ -0,0 +1,298 @@
from time import sleep, time, strftime, localtime
from sys import argv
from os import mkdir
from paramiko import SSHClient, AutoAddPolicy
from json import loads
from openpyxl import load_workbook
from pandas import DataFrame, concat
from commons import clibs
tab_name = clibs.tab_names['at']
logger = clibs.log_prod
def check_files(path, loadsel, data_dirs, data_files, w2t):
if len(data_dirs) != 0 or len(data_files) != 5:
w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red', tab_name)
w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 1, 'red', tab_name)
config_file = reach33 = reach66 = reach100 = prj_file = None
for data_file in data_files:
filename = data_file.split('\\')[-1]
if filename == 'configs.xlsx':
config_file = data_file
elif filename.startswith('reach33_') and filename.endswith('.xlsx'):
reach33 = data_file
elif filename.startswith('reach66_') and filename.endswith('.xlsx'):
reach66 = data_file
elif filename.startswith('reach100_') and filename.endswith('.xlsx'):
reach100 = data_file
elif filename.endswith('.zip'):
prj_file = data_file
else:
w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red', tab_name)
w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 2, 'red', tab_name)
if config_file and reach33 and reach66 and reach100 and prj_file:
result_dirs = []
mkdir(f"{path}\\j1")
mkdir(f"{path}\\j2")
mkdir(f"{path}\\j3")
for _reach in ['reach33', 'reach66', 'reach100']:
for _load in [f'load{loadsel.removeprefix("tool")}']:
for _speed in ['speed33', 'speed66', 'speed100']:
dir_name = '_'.join([_reach, _load, _speed])
result_dirs.append(dir_name)
mkdir(f"{path}\\j1\\{dir_name}")
mkdir(f"{path}\\j2\\{dir_name}")
if _reach == 'reach100':
mkdir(f"{path}\\j3\\{dir_name}")
w2t("数据目录合规性检查结束,未发现问题......", 0, 0, 'blue', tab_name)
return config_file, reach33, reach66, reach100, prj_file, result_dirs
else:
w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red', tab_name)
w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 1, 'red', tab_name)
def gen_result_file(path, curve_data, axis, _reach, _load, _speed, count):
_d2d_vel = {'hw_joint_vel_feedback': []}
_d2d_trq = {'device_servo_trq_feedback': []}
_d2d_stop = {'device_safety_estop': []}
for data in curve_data[-240:]: # 保留最后12s的数据
dict_results = data['data']
for item in dict_results:
try:
item['value'].reverse()
except KeyError:
continue
if item.get('channel', None) == axis-1 and item.get('name', None) == 'hw_joint_vel_feedback':
_d2d_vel['hw_joint_vel_feedback'].extend(item['value'])
elif item.get('channel', None) == axis-1 and item.get('name', None) == 'device_servo_trq_feedback':
_d2d_trq['device_servo_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 0 and item.get('name', None) == 'device_safety_estop':
_d2d_stop['device_safety_estop'].extend(item['value'])
df1 = DataFrame.from_dict(_d2d_vel)
df2 = DataFrame.from_dict(_d2d_trq)
df3 = DataFrame.from_dict(_d2d_stop)
df = concat([df1, df2, df3], axis=1)
_filename = f"{path}\\j{axis}\\reach{_reach}_load{_load}_speed{_speed}\\reach{_reach}_load{_load}_speed{_speed}_{count}.data"
df.to_csv(_filename, sep='\t', index=False)
def run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t):
_count = 0
_total = 63
display_pdo_params = [
{"name": "hw_joint_vel_feedback", "channel": 0},
{"name": "hw_joint_vel_feedback", "channel": 1},
{"name": "hw_joint_vel_feedback", "channel": 2},
{"name": "hw_joint_vel_feedback", "channel": 3},
{"name": "hw_joint_vel_feedback", "channel": 4},
{"name": "hw_joint_vel_feedback", "channel": 5},
{"name": "device_servo_trq_feedback", "channel": 0},
{"name": "device_servo_trq_feedback", "channel": 1},
{"name": "device_servo_trq_feedback", "channel": 2},
{"name": "device_servo_trq_feedback", "channel": 3},
{"name": "device_servo_trq_feedback", "channel": 4},
{"name": "device_servo_trq_feedback", "channel": 5},
{"name": "device_safety_estop", "channel": 0},
]
wb = load_workbook(config_file, read_only=True)
ws = wb['Target']
write_diagnosis = float(ws.cell(row=3, column=10).value)
get_init_speed = float(ws.cell(row=4, column=10).value)
single_brake = str(ws.cell(row=5, column=10).value)
logger.info(f"write_diagnosis = {write_diagnosis}, get_init_speed = {get_init_speed}, single_brake = {single_brake}")
if ws.cell(row=1, column=1).value == 'positive':
md.write_pon(1)
elif ws.cell(row=1, column=1).value == 'negative':
md.write_pon(0)
else:
w2t("configs.xlsx中Target页面A1单元格填写不正确检查后重新运行...", 0, 111, 'red', tab_name)
clibs.execution('diagnosis.open', hr, w2t, tab_name, open=True, display_open=True)
clibs.execution('diagnosis.set_params', hr, w2t, tab_name, display_pdo_params=display_pdo_params)
for condition in result_dirs:
_reach = condition.split('_')[0].removeprefix('reach')
_load = condition.split('_')[1].removeprefix('load')
_speed = condition.split('_')[2].removeprefix('speed')
# for single condition test
_single_axis = 0
if single_brake != '0':
_total = 3
_single_axis = int(single_brake.split('-')[0])
if _reach != single_brake.split('-')[1] or _load != single_brake.split('-')[2] or _speed != single_brake.split('-')[3]:
continue
for axis in range(1, 4):
# for single condition test
if _single_axis != 0 and _single_axis != axis:
continue
md.write_axis(axis)
speed_max = 0
if axis == 3 and _reach != '100':
continue
w2t(f"-"*90, 0, 0, 'purple', tab_name)
for count in range(1, 4):
_count += 1
this_time = strftime("%Y-%m-%d %H:%M:%S", localtime(time()))
prj_path = 'target/_build/target.prj'
w2t(f"[{this_time} | {_count}/{_total}] 正在执行 {axis}{condition} 的第 {count} 次制动测试...", 0, 0, 'purple', tab_name)
# 1. 关闭诊断曲线,触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电
md.trigger_estop()
md.reset_estop()
md.clear_alarm()
md.write_act(0)
sleep(write_diagnosis) # 软急停超差后等待写诊断时间可通过configs.xlsx配置
while count == 1:
# 2. 修改要执行的场景
ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(hostname=clibs.ip_addr, port=22, username='luoshi', password='luoshi2019')
if ws.cell(row=1, column=1).value == 'positive':
_rl_cmd = f"brake_E(j{axis}_{_reach}_p, j{axis}_{_reach}_n, p_speed, p_tool)"
elif ws.cell(row=1, column=1).value == 'negative':
_rl_cmd = f"brake_E(j{axis}_{_reach}_n, j{axis}_{_reach}_p, p_speed, p_tool)"
else:
w2t("configs.xlsx中Target页面A1单元格填写不正确检查后重新运行...", 0, 111, 'red', tab_name)
_rl_speed = f"VelSet {_speed}"
_rl_tool = f"tool p_tool = tool{loadsel.removeprefix('tool')}"
cmd = 'cd /home/luoshi/bin/controller/; '
cmd += 'sudo sed -i "/brake_E/d" projects/target/_build/brake/main.mod; '
cmd += f'sudo sed -i "/DONOTDELETE/i {_rl_cmd}" projects/target/_build/brake/main.mod; '
cmd += 'sudo sed -i "/VelSet/d" projects/target/_build/brake/main.mod; '
cmd += f'sudo sed -i "/MoveAbsJ/i {_rl_speed}" projects/target/_build/brake/main.mod; '
cmd += 'sudo sed -i "/tool p_tool/d" projects/target/_build/brake/main.mod; '
cmd += f'sudo sed -i "/VelSet/i {_rl_tool}" projects/target/_build/brake/main.mod; '
stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
stdin.write('luoshi2019' + '\n')
stdout.read().decode() # 需要read一下才能正常执行
stderr.read().decode()
# 3. reload工程后pp2main并且自动模式和上电最后运行程序
clibs.execution('overview.reload', hr, w2t, tab_name, prj_path=prj_path, tasks=['brake', 'stop0_related'])
clibs.execution('rl_task.pp_to_main', hr, w2t, tab_name, tasks=['brake', 'stop0_related'])
clibs.execution('state.switch_auto', hr, w2t, tab_name)
clibs.execution('state.switch_motor_on', hr, w2t, tab_name)
clibs.execution('rl_task.set_run_params', hr, w2t, tab_name, loop_mode=True, override=1.0)
clibs.execution('rl_task.run', hr, w2t, tab_name, tasks=['brake', 'stop0_related'])
_t_start = time()
while True:
if md.read_ready_to_go() == 1:
md.write_act(True)
break
else:
if (time() - _t_start) // 20 > 1:
w2t("20s内未收到机器人的运行信号需要确认RL程序编写正确并正常执行...", 0, 111, 'red', tab_name)
else:
sleep(1)
# 4. 找出最大速度传递给RL程序最后清除相关记录
sleep(get_init_speed+5) # 冗余5s指定时间后获取实际【正|负】方向的最大速度可通过configs.xlsx配置
clibs.execution('rl_task.stop', hr, w2t, tab_name, tasks=['brake'])
# 找出最大速度
_c_msg = hr.c_msg.copy()
_number = 0
for _msg in _c_msg:
if _number > get_init_speed*20: # 最开始回零点的时候,二轴速度可以达到最大值,实际摆动时,某一方向可能达不到
break
if 'diagnosis.result' in _msg:
_number += 1
dict_results = loads(_msg)['data']
for item in dict_results:
if item.get('channel', None) == axis-1 and item.get('name', None) == 'hw_joint_vel_feedback':
_ = clibs.RADIAN * sum(item['value']) / len(item['value'])
if ws.cell(row=1, column=1).value == 'positive':
speed_max = max(_, speed_max)
elif ws.cell(row=1, column=1).value == 'negative':
speed_max = min(_, speed_max)
logger.info(f"speed max = {speed_max}")
speed_max = abs(speed_max)
speed_target = float(ws.cell(row=3, column=axis+1).value) * float(_speed) / 100
if speed_max < speed_target*0.95 or speed_max > speed_target*1.05:
w2t(f"Axis: {axis}-{count} | Speed: {speed_max} | Shouldbe: {speed_target}", 0, 0, 'indigo', tab_name)
md.write_speed_max(speed_max)
hr.c_msg_xs.clear()
if len(hr.c_msg) > 270:
del hr.c_msg[270:]
if speed_max < 10:
md.clear_alarm()
w2t("未获取到正确的速度,即将重新获取...", 0, 0, 'red', tab_name)
continue
else:
break
# 5. 清除软急停重新运行程序并打开曲线发送继续运动信号当速度达到最大值时通过DO触发急停
md.reset_estop() # 其实没必要
md.clear_alarm()
# clibs.execution('overview.reload', hr, w2t, tab_name, prj_path=prj_path, tasks=['brake', 'stop0_related'])
clibs.execution('rl_task.pp_to_main', hr, w2t, tab_name, tasks=['brake', 'stop0_related'])
clibs.execution('state.switch_auto', hr, w2t, tab_name)
clibs.execution('state.switch_motor_on', hr, w2t, tab_name)
clibs.execution('rl_task.run', hr, w2t, tab_name, tasks=['brake', 'stop0_related'])
for i in range(3):
if md.read_ready_to_go() == 1:
md.write_act(1)
break
else:
sleep(1)
else:
w2t("未收到机器人的运行信号需要确认RL程序编写正确并正常执行...", 0, 111, 'red', tab_name)
sleep(10) # 排除从其他位姿到零点位姿,再到轴极限位姿的时间
md.write_probe(1)
_t_start = time()
while True:
if md.read_brake_done() == 1:
sleep(4) # 保证速度归零
md.write_probe(0)
break
else:
if (time() - _t_start) > 30:
w2t(f"30s内未触发急停该条数据无效需要确认RL/Python程序编写正确并正常执行或者判别是否是机器本体问题比如正负方向速度是否一致...", 0, 0, 'red', tab_name)
md.write_probe(0)
break
else:
sleep(1)
# 6. 保留数据并处理输出
curve_data = []
_c_msg = hr.c_msg.copy()
for _msg in _c_msg:
if 'diagnosis.result' in _msg:
curve_data.insert(0, loads(_msg))
else:
hr.c_msg_xs.clear()
if len(hr.c_msg) > 270:
del hr.c_msg[270:]
gen_result_file(path, curve_data, axis, _reach, _load, _speed, count)
else:
w2t(f"\n{loadsel.removeprefix('tool')}%负载的制动性能测试执行完毕,如需采集其他负载,须切换负载类型,并更换其他负载,重新执行。", 0, 0, 'green', tab_name)
def main(path, hr, md, loadsel, w2t):
_s_time = time()
data_dirs, data_files = clibs.traversal_files(path, w2t)
config_file, reach33, reach66, reach100, prj_file, result_dirs = check_files(path, loadsel, data_dirs, data_files, w2t)
clibs.prj_to_xcore(prj_file)
run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t)
_e_time = time()
time_total = _e_time - _s_time
w2t(f"处理总时长:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s", 0, 0, 'green', tab_name)
if __name__ == '__main__':
main(*argv[1:])

View File

@ -0,0 +1,405 @@
import json
from os import mkdir
import time
from time import sleep, time
from sys import argv
from paramiko import SSHClient, AutoAddPolicy
from json import loads
from pandas import DataFrame, concat
from common import clibs
display_pdo_params = [{"name": name, "channel": chl} for name in ["hw_joint_vel_feedback", "device_servo_trq_feedback", "hw_sensor_trq_feedback"] for chl in range(6)]
def initialization(path, sub, data_dirs, data_files, hr, w2t):
def check_files():
if len(data_dirs) != 0 or len(data_files) != 2:
w2t("初始路径下不允许有文件夹,且初始路径下只能存在如下两个文件,确认后重新运行!\n", "red")
w2t("1. T_电机电流.xlsx\n2. xxxx.zip\n", "red", "ConfigFileError")
prj_file, count = None, 0
for data_file in data_files:
filename = data_file.split("/")[-1]
if filename == "T_电机电流.xlsx":
count += 1
elif filename.endswith(".zip"):
count += 1
prj_file = data_file
else:
w2t(f"{data_file} 不合规:初始路径下只能存在如下两个文件,确认后重新运行!\n", "red")
w2t("1. T_电机电流.xlsx\n2. xxxx.zip\n", "red", "ConfigFileError")
if count != 2:
w2t("初始路径下不允许有文件夹,且初始路径下只能存在如下两个文件,确认后重新运行!\n", "red")
w2t("1. T_电机电流.xlsx\n2. xxxx.zip\n", "red", "ConfigFileError")
w2t("数据目录合规性检查结束,未发现问题......\n")
if sub == "tool100" or sub == "inertia":
mkdir(f"{path}/single")
mkdir(f"{path}/s_1")
mkdir(f"{path}/s_2")
mkdir(f"{path}/s_3")
elif sub == "inertia":
mkdir(f"{path}/inertia")
else:
w2t("负载选择错误,电机电流测试只能选择 tool100/inertia 规格!\n", "red", "LoadSelectError")
return prj_file
def get_configs():
robot_type = None
msg_id, state = hr.execution("controller.get_params")
records = hr.get_from_id(msg_id, state)
for record in records:
if "请求发送成功" not in record[0]:
robot_type = eval(record[0])["data"]["robot_type"]
server_file = f"/home/luoshi/bin/controller/robot_cfg/{robot_type}/{robot_type}.cfg"
local_file = path + f"/{robot_type}.cfg"
clibs.c_pd.pull_file_from_server(server_file, local_file)
return local_file
prj_file = check_files()
config_file = get_configs()
return config_file, prj_file
def data_proc_regular(path, filename, channel, scenario_time):
if channel in list(range(6)):
with open(filename, 'r', encoding='utf-8') as f_obj:
lines = f_obj.readlines()
_d2d_vel = {'hw_joint_vel_feedback': []}
_d2d_trq = {'device_servo_trq_feedback': []}
_d2d_sensor = {'hw_sensor_trq_feedback': []}
for line in lines[-500:]: # 保留最后25s的数据
data = eval(line.strip())['data']
for item in data:
try:
item['value'].reverse()
except KeyError:
continue
if item.get('channel', None) == channel and item.get('name', None) == 'hw_joint_vel_feedback':
_d2d_vel['hw_joint_vel_feedback'].extend(item['value'])
elif item.get('channel', None) == channel and item.get('name', None) == 'device_servo_trq_feedback':
_d2d_trq['device_servo_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == channel and item.get('name', None) == 'hw_sensor_trq_feedback':
_d2d_sensor['hw_sensor_trq_feedback'].extend(item['value'])
df1 = DataFrame.from_dict(_d2d_vel)
df2 = DataFrame.from_dict(_d2d_trq)
df3 = DataFrame.from_dict(_d2d_sensor)
df = concat([df1, df2, df3], axis=1)
_filename = f'{path}\\single\\j{channel+1}_single_{time()}.data'
df.to_csv(_filename, sep='\t', index=False)
elif channel in list(range(6, 9)):
with open(filename, 'r', encoding='utf-8') as f_obj:
lines = f_obj.readlines()
_d2d_vel_0 = {'hw_joint_vel_feedback': []}
_d2d_trq_0 = {'device_servo_trq_feedback': []}
_d2d_sensor_0 = {'hw_sensor_trq_feedback': []}
_d2d_vel_1 = {'hw_joint_vel_feedback': []}
_d2d_trq_1 = {'device_servo_trq_feedback': []}
_d2d_sensor_1 = {'hw_sensor_trq_feedback': []}
_d2d_vel_2 = {'hw_joint_vel_feedback': []}
_d2d_trq_2 = {'device_servo_trq_feedback': []}
_d2d_sensor_2 = {'hw_sensor_trq_feedback': []}
_d2d_vel_3 = {'hw_joint_vel_feedback': []}
_d2d_trq_3 = {'device_servo_trq_feedback': []}
_d2d_sensor_3 = {'hw_sensor_trq_feedback': []}
_d2d_vel_4 = {'hw_joint_vel_feedback': []}
_d2d_trq_4 = {'device_servo_trq_feedback': []}
_d2d_sensor_4 = {'hw_sensor_trq_feedback': []}
_d2d_vel_5 = {'hw_joint_vel_feedback': []}
_d2d_trq_5 = {'device_servo_trq_feedback': []}
_d2d_sensor_5 = {'hw_sensor_trq_feedback': []}
for line in lines:
data = eval(line.strip())['data']
for item in data:
try:
item['value'].reverse()
except KeyError:
continue
if item.get('channel', None) == 0 and item.get('name', None) == 'hw_joint_vel_feedback':
_d2d_vel_0['hw_joint_vel_feedback'].extend(item['value'])
elif item.get('channel', None) == 0 and item.get('name', None) == 'device_servo_trq_feedback':
_d2d_trq_0['device_servo_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 0 and item.get('name', None) == 'hw_sensor_trq_feedback':
_d2d_sensor_0['hw_sensor_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 1 and item.get('name', None) == 'hw_joint_vel_feedback':
_d2d_vel_1['hw_joint_vel_feedback'].extend(item['value'])
elif item.get('channel', None) == 1 and item.get('name', None) == 'device_servo_trq_feedback':
_d2d_trq_1['device_servo_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 1 and item.get('name', None) == 'hw_sensor_trq_feedback':
_d2d_sensor_1['hw_sensor_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 2 and item.get('name', None) == 'hw_joint_vel_feedback':
_d2d_vel_2['hw_joint_vel_feedback'].extend(item['value'])
elif item.get('channel', None) == 2 and item.get('name', None) == 'device_servo_trq_feedback':
_d2d_trq_2['device_servo_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 3 and item.get('name', None) == 'hw_sensor_trq_feedback':
_d2d_sensor_2['hw_sensor_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 3 and item.get('name', None) == 'hw_joint_vel_feedback':
_d2d_vel_3['hw_joint_vel_feedback'].extend(item['value'])
elif item.get('channel', None) == 3 and item.get('name', None) == 'device_servo_trq_feedback':
_d2d_trq_3['device_servo_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 3 and item.get('name', None) == 'hw_sensor_trq_feedback':
_d2d_sensor_3['hw_sensor_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 4 and item.get('name', None) == 'hw_joint_vel_feedback':
_d2d_vel_4['hw_joint_vel_feedback'].extend(item['value'])
elif item.get('channel', None) == 4 and item.get('name', None) == 'device_servo_trq_feedback':
_d2d_trq_4['device_servo_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 4 and item.get('name', None) == 'hw_sensor_trq_feedback':
_d2d_sensor_4['hw_sensor_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 5 and item.get('name', None) == 'hw_joint_vel_feedback':
_d2d_vel_5['hw_joint_vel_feedback'].extend(item['value'])
elif item.get('channel', None) == 5 and item.get('name', None) == 'device_servo_trq_feedback':
_d2d_trq_5['device_servo_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == 5 and item.get('name', None) == 'hw_sensor_trq_feedback':
_d2d_sensor_5['hw_sensor_trq_feedback'].extend(item['value'])
df_01 = DataFrame.from_dict(_d2d_vel_0)
df_02 = DataFrame.from_dict(_d2d_trq_0)
df_03 = DataFrame.from_dict(_d2d_sensor_0)
df = concat([df_01, df_02, df_03], axis=1)
_filename = f'{path}\\s_{channel-5}\\j1_s_{channel-5}_{scenario_time}_{time()}.data'
df.to_csv(_filename, sep='\t', index=False)
df_01 = DataFrame.from_dict(_d2d_vel_1)
df_02 = DataFrame.from_dict(_d2d_trq_1)
df_03 = DataFrame.from_dict(_d2d_sensor_1)
df = concat([df_01, df_02, df_03], axis=1)
_filename = f'{path}\\s_{channel-5}\\j2_s_{channel-5}_{scenario_time}_{time()}.data'
df.to_csv(_filename, sep='\t', index=False)
df_01 = DataFrame.from_dict(_d2d_vel_2)
df_02 = DataFrame.from_dict(_d2d_trq_2)
df_03 = DataFrame.from_dict(_d2d_sensor_2)
df = concat([df_01, df_02, df_03], axis=1)
_filename = f'{path}\\s_{channel-5}\\j3_s_{channel-5}_{scenario_time}_{time()}.data'
df.to_csv(_filename, sep='\t', index=False)
df_01 = DataFrame.from_dict(_d2d_vel_3)
df_02 = DataFrame.from_dict(_d2d_trq_3)
df_03 = DataFrame.from_dict(_d2d_sensor_3)
df = concat([df_01, df_02, df_03], axis=1)
_filename = f'{path}\\s_{channel-5}\\j4_s_{channel-5}_{scenario_time}_{time()}.data'
df.to_csv(_filename, sep='\t', index=False)
df_01 = DataFrame.from_dict(_d2d_vel_4)
df_02 = DataFrame.from_dict(_d2d_trq_4)
df_03 = DataFrame.from_dict(_d2d_sensor_4)
df = concat([df_01, df_02, df_03], axis=1)
_filename = f'{path}\\s_{channel-5}\\j5_s_{channel-5}_{scenario_time}_{time()}.data'
df.to_csv(_filename, sep='\t', index=False)
df_01 = DataFrame.from_dict(_d2d_vel_5)
df_02 = DataFrame.from_dict(_d2d_trq_5)
df_03 = DataFrame.from_dict(_d2d_sensor_5)
df = concat([df_01, df_02, df_03], axis=1)
_filename = f'{path}\\s_{channel-5}\\j6_s_{channel-5}_{scenario_time}_{time()}.data'
df.to_csv(_filename, sep='\t', index=False)
elif channel in list(range(9, 15)):
with open(filename, 'r', encoding='utf-8') as f_obj:
lines = f_obj.readlines()
_d2d_vel = {'hw_joint_vel_feedback': []}
_d2d_trq = {'device_servo_trq_feedback': []}
_d2d_sensor = {'hw_sensor_trq_feedback': []}
for line in lines[-300:]: # 保留最后15s的数据
data = eval(line.strip())['data']
for item in data:
try:
item['value'].reverse()
except KeyError:
continue
if item.get('channel', None) == channel-9 and item.get('name', None) == 'hw_joint_vel_feedback':
_d2d_vel['hw_joint_vel_feedback'].extend(item['value'])
elif item.get('channel', None) == channel-9 and item.get('name', None) == 'device_servo_trq_feedback':
_d2d_trq['device_servo_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == channel-9 and item.get('name', None) == 'hw_sensor_trq_feedback':
_d2d_sensor['hw_sensor_trq_feedback'].extend(item['value'])
df1 = DataFrame.from_dict(_d2d_vel)
df2 = DataFrame.from_dict(_d2d_trq)
df3 = DataFrame.from_dict(_d2d_sensor)
df = concat([df1, df2, df3], axis=1)
_filename = f'{path}\\single\\j{channel-8}_hold_{time()}.data'
df.to_csv(_filename, sep='\t', index=False)
def data_proc_inertia(path, filename, channel):
with open(filename, 'r', encoding='utf-8') as f_obj:
lines = f_obj.readlines()
_d2d_vel = {'hw_joint_vel_feedback': []}
_d2d_trq = {'device_servo_trq_feedback': []}
_d2d_sensor = {'hw_sensor_trq_feedback': []}
for line in lines:
data = eval(line.strip())['data']
for item in data:
try:
item['value'].reverse()
except KeyError:
continue
if item.get('channel', None) == channel+3 and item.get('name', None) == 'hw_joint_vel_feedback':
_d2d_vel['hw_joint_vel_feedback'].extend(item['value'])
elif item.get('channel', None) == channel+3 and item.get('name', None) == 'device_servo_trq_feedback':
_d2d_trq['device_servo_trq_feedback'].extend(item['value'])
elif item.get('channel', None) == channel+3 and item.get('name', None) == 'hw_sensor_trq_feedback':
_d2d_trq['hw_sensor_trq_feedback'].extend(item['value'])
df1 = DataFrame.from_dict(_d2d_vel)
df2 = DataFrame.from_dict(_d2d_trq)
df3 = DataFrame.from_dict(_d2d_sensor)
df = concat([df1, df2, df3], axis=1)
_filename = f'{path}\\inertia\\j{channel+4}_inertia_{time()}.data'
df.to_csv(_filename, sep='\t', index=False)
def gen_result_file(path, loadsel, disc, number, scenario_time):
filename = path + f'\\data.txt'
with open(filename, 'w', encoding='utf-8') as f_obj:
for line in disc[number][1]:
f_obj.write(str(line)+'\n')
if loadsel == 'tool100':
data_proc_regular(path, filename, number, scenario_time)
elif loadsel == 'inertia':
data_proc_inertia(path, filename, number)
def run_rl(path, hr, md, sub, w2t):
c_regular = [
"scenario(0, j1_p, j1_n, p_speed, p_tool, i_tool)",
"scenario(0, j2_p, j2_n, p_speed, p_tool, i_tool)",
"scenario(0, j3_p, j3_n, p_speed, p_tool, i_tool)",
"scenario(0, j4_p, j4_n, p_speed, p_tool, i_tool)",
"scenario(0, j5_p, j5_n, p_speed, p_tool, i_tool)",
"scenario(0, j6_p, j6_n, p_speed, p_tool, i_tool)",
"scenario(1, j6_p, j6_n, p_speed, p_tool, i_tool)",
"scenario(2, j6_p, j6_n, p_speed, p_tool, i_tool)",
"scenario(3, j6_p, j6_n, p_speed, p_tool, i_tool)",
"scenario(4, j1_hold, j1_hold, p_speed, p_tool, i_tool)",
"scenario(4, j2_hold, j2_hold, p_speed, p_tool, i_tool)",
"scenario(4, j3_hold, j3_hold, p_speed, p_tool, i_tool)",
"scenario(4, j4_hold, j4_hold, p_speed, p_tool, i_tool)",
"scenario(4, j5_hold, j5_hold, p_speed, p_tool, i_tool)",
"scenario(4, j6_hold, j6_hold, p_speed, p_tool, i_tool)",
]
c_inertia = [
"scenario(5, j4_p_inertia, j4_n_inertia, p_speed, p_tool, i_tool)",
"scenario(5, j5_p_inertia, j5_n_inertia, p_speed, p_tool, i_tool)",
"scenario(5, j6_p_inertia, j6_n_inertia, p_speed, p_tool, i_tool)",
]
disc_regular = {
0: ['一轴', []], 1: ['二轴', []], 2: ['三轴', []], 3: ['四轴', []], 4: ['五轴', []], 5: ['六轴', []],
6: ['场景一', []], 7: ['场景二', []], 8: ['场景三', []], 9: ['一轴保持', []], 10: ['二轴保持', []],
11: ['三轴保持', []], 12: ['四轴保持', []], 13: ['五轴保持', []], 14: ['六轴保持', []]
}
disc_inertia = {0: ['四轴惯量', []], 1: ['五轴惯量', []], 2: ['六轴惯量', []]}
if sub == 'tool100':
conditions = c_regular
disc = disc_regular
elif sub == 'inertia':
conditions = c_inertia
disc = disc_inertia
# preparation 触发软急停,并解除,目的是让可能正在运行着的机器停下来
hr.execution('diagnosis.open', hr, w2t, tab_name, open=True, display_open=True)
hr.execution('diagnosis.set_params', hr, w2t, tab_name, display_pdo_params=display_pdo_params)
# clibs.execution('diagnosis.save', hr, w2t, tab_name, save=True) # 这条命令有问题
md.trigger_estop()
md.reset_estop()
for condition in conditions:
number = conditions.index(condition)
w2t(f"正在执行{disc[number][0]}测试......", 0, 0, 'purple', tab_name)
# 1. 将act重置为False并修改未要执行的场景
md.write_act(False)
ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(clibs.ip_addr, 22, username='luoshi', password='luoshi2019')
cmd = 'cd /home/luoshi/bin/controller/; '
cmd += 'sudo sed -i "/scenario/d" projects/target/_build/current/main.mod; '
cmd += f'sudo sed -i "/DONOTDELETE/i {condition}" projects/target/_build/current/main.mod'
stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
stdin.write('luoshi2019' + '\n')
stdout.read().decode() # 需要read一下才能正常执行
stderr.read().decode()
# 2. reload工程后pp2main并且自动模式和上电
prj_path = 'target/_build/target.prj'
clibs.execution('overview.reload', hr, w2t, tab_name, prj_path=prj_path, tasks=['current'])
clibs.execution('rl_task.pp_to_main', hr, w2t, tab_name, tasks=['current'])
clibs.execution('state.switch_auto', hr, w2t, tab_name)
clibs.execution('state.switch_motor_on', hr, w2t, tab_name)
# 3. 开始运行程序单轴运行35s
clibs.execution('rl_task.set_run_params', hr, w2t, tab_name, loop_mode=True, override=1.0)
clibs.execution('rl_task.run', hr, w2t, tab_name, tasks=['current'])
_t_start = time()
while True:
if md.read_ready_to_go() == 1:
md.write_act(True)
break
else:
if (time() - _t_start) // 20 > 1:
w2t("20s内未收到机器人的运行信号需要确认RL程序编写正确并正常执行...", 0, 111, 'red', tab_name)
else:
sleep(1)
# 4. 打开诊断曲线,并执行采集
sleep(10) # 保证程序已经运行起来,其实主要是为了保持电流的采集而设定
scenario_time = 0
if number < 6:
sleep(35)
elif number > 8:
sleep(15)
else:
_t_start = time()
while True:
scenario_time = md.read_scenario_time()
if float(scenario_time) > 1:
w2t(f"场景{number-5}的周期时间:{scenario_time}", 0, 0, 'green', tab_name)
break
else:
if (time()-_t_start)//60 > 3:
w2t(f"未收到场景{number-5}的周期时间需要确认RL程序编写正确并正常执行...", 0, 111, 'red', tab_name)
else:
sleep(5)
sleep(1) # 一定要延迟一秒再读一次scenario time寄存器因为一开始读取的数值不准确
scenario_time = md.read_scenario_time()
sleep(float(scenario_time)*0.2) # 再运行周期的20%即可
# 5.停止程序运行,保留数据并处理输出
clibs.execution('rl_task.stop', hr, w2t, tab_name, tasks=['current'])
_c_msg = hr.c_msg.copy()
for _msg in _c_msg:
if 'diagnosis.result' in _msg:
disc[number][1].insert(0, loads(_msg))
else:
hr.c_msg_xs.clear()
if len(hr.c_msg) > 270:
del hr.c_msg[270:]
gen_result_file(path, loadsel, disc, number, scenario_time)
else:
if loadsel == 'tool100':
w2t("单轴和场景电机电流采集完毕,如需采集惯量负载,须切换负载类型,并更换惯量负载,重新执行。", 0, 0, 'green', tab_name)
elif loadsel == 'inertia':
w2t("惯量负载电机电流采集完毕,如需采集单轴/场景/保持电机电流,须切换负载类型,并更换偏置负载,重新执行。", 0, 0, 'green', tab_name)
def main():
path = clibs.data_at["_path"]
sub = clibs.data_at["_sub"]
w2t = clibs.w2t
hr = clibs.c_hr
md = clibs.c_md
insert_logdb = clibs.insert_logdb
data_dirs, data_files = clibs.traversal_files(path, w2t)
config_file, prj_file = initialization(path, sub, data_dirs, data_files, hr, w2t)
clibs.c_pd.push_prj_to_server(prj_file)
clibs.c_hr.execution("diagnosis.open", open=False, display_open=False, overrun=True, turn_area=True, delay_motion=False)
# run_rl(path, hr, md, sub, w2t)
if __name__ == '__main__':
main()

View File

@ -21,15 +21,16 @@ def traversal_files(_path, _w2t):
return dirs, files
def init_logdb(_conn, _cursor):
_conn = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False, cached_statements=4096)
_cursor = _conn.cursor()
_cursor.execute("PRAGMA journal_mode=wal")
_cursor.execute("PRAGMA wal_checkpoint=TRUNCATE")
_cursor.execute("PRAGMA synchronous=normal")
_cursor.execute("PRAGMA temp_store=memory")
_cursor.execute("PRAGMA mmap_size=30000000000")
_cursor.execute(
def init_logdb(conn, cursor):
conn = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False, cached_statements=2048)
cursor = conn.cursor()
cursor.execute("PRAGMA journal_mode=wal")
cursor.execute("PRAGMA wal_checkpoint=TRUNCATE")
cursor.execute("PRAGMA synchronous=normal")
cursor.execute("PRAGMA temp_store=memory")
cursor.execute("PRAGMA mmap_size=30000000000")
cursor.execute("PRAGMA cache_size=200000")
cursor.execute(
"""
create table if not exists logs(
id integer primary key autoincrement,
@ -40,7 +41,7 @@ def init_logdb(_conn, _cursor):
)
"""
)
return _conn, _cursor
return conn, cursor
def db_lock(func):
@ -61,7 +62,7 @@ def insert_logdb(_level, _module, _content):
global conn, cursor, lock
if "move.monitor" in _content:
return
data = [_level, _module, repr(_content)]
data = [_level, _module, _content]
cursor.execute("insert into logs (level, module, content) values (?, ?, ?)", data)
@ -89,7 +90,6 @@ class GetThreadResult(threading.Thread):
def get_result(self):
threading.Thread.join(self) # 等待线程执行完毕
# noinspection PyBroadException
try:
return self.result
except Exception:
@ -99,35 +99,18 @@ class GetThreadResult(threading.Thread):
# PREFIX = 'assets' # for pyinstaller packaging
PREFIX = '../assets' # for source code testing and debug
log_path = f"{PREFIX}/logs"
conn = None
cursor = None
levels = ["DEBUG", "INFO", "WARNING", "ERROR"]
db_state = "readwrite"
data_dp = {}
data_at = {}
w2t = None
running = False
stop = True
tl_prg = None
f_records = None
data_dp, data_at = {}, {}
conn, cursor, w2t, tl_prg, f_records, stop, running = None, None, None, None, None, True, False
ip_addr = "192.168.0.160"
ssh_port = 22
socket_port = 5050
xService_port = 6666
external_port = 8080
modbus_port = 502
upgrade_port = 4567
username = "luoshi"
password = "luoshi2019" # for real robot
# password = "forpqart" # for robot vm
ssh_port, socket_port, xService_port, external_port, modbus_port, upgrade_port = 22, 5050, 6666, 8080, 502, 4567
username, password = "luoshi", "luoshi2019"
interval = 0.5 # interval after actions being triggered, such as modbus/socket/external communication operations
RADIAN = 57.3 # 180 / 3.1415926
MAX_FRAME_SIZE = 1024
c_md = None
c_hr = None
c_ec = None
c_pd = None
c_md, c_hr, c_ec, c_pd = None, None, None, None
lock = threading.Lock()
conn, cursor = init_logdb(conn, cursor)

View File

@ -11,7 +11,6 @@ import time
from common import clibs
from os import listdir
from threading import Thread
# from pymodbus.payload import BinaryPayloadDecoder, BinaryPayloadBuilder
# from pymodbus.constants import Endian
import os.path
@ -290,7 +289,7 @@ class ModbusRequest(object):
class HmiRequest(object):
socket.setdefaulttimeout(clibs.interval * 10)
socket.setdefaulttimeout(clibs.interval * 6)
def __init__(self, ip, port, port_xs):
self.__ip = ip
@ -312,38 +311,15 @@ class HmiRequest(object):
self.__is_debug = True
self.__socket_conn()
self.__t_heartbeat = Thread(target=self.__heartbeat)
self.__t_heartbeat = threading.Thread(target=self.__heartbeat)
self.__t_heartbeat.daemon = True
self.__t_heartbeat.start()
self.__t_unpackage = Thread(target=self.__unpackage, args=(self.__c,))
self.__t_unpackage = threading.Thread(target=self.__unpackage, args=(self.__c,))
self.__t_unpackage.daemon = True
self.__t_unpackage.start()
self.__t_unpackage_xs = Thread(target=self.__unpackage_xs, args=(self.__c_xs,))
self.__t_unpackage_xs = threading.Thread(target=self.__unpackage_xs, args=(self.__c_xs,))
self.__t_unpackage_xs.daemon = True
self.__t_unpackage_xs.start()
# self.__t_heartbeat = None
# self.__t_unpackage = None
# self.__t_unpackage_xs = None
# self.__t_is_alive = Thread(target=self.__is_alive)
# self.__t_is_alive.daemon = True
# self.__t_is_alive.start()
# time.sleep(3)
def __is_alive(self):
while not self.__close_hmi:
if not self.__is_connected:
self.__socket_conn()
if self.__is_connected:
self.__t_heartbeat = Thread(target=self.__heartbeat)
self.__t_heartbeat.daemon = True
self.__t_heartbeat.start()
self.__t_unpackage = Thread(target=self.__unpackage, args=(self.__c,))
self.__t_unpackage.daemon = True
self.__t_unpackage.start()
self.__t_unpackage_xs = Thread(target=self.__unpackage_xs, args=(self.__c_xs,))
self.__t_unpackage_xs.daemon = True
self.__t_unpackage_xs.start()
time.sleep(3)
@property
def status(self):
@ -351,7 +327,6 @@ class HmiRequest(object):
def close(self):
try:
# self.__close_hmi = True
self.__is_connected = False
time.sleep(clibs.interval*2)
self.__c.close()
@ -458,7 +433,7 @@ class HmiRequest(object):
self.__index += pkg_value
# 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")
clibs.insert_logdb("DEBUG", "openapi", self.__response.decode())
clibs.insert_logdb("DEBUG", "openapi", str(json.loads(self.__response.decode())))
self.__response = b""
self.__leftovers = 0
self.__is_first_frame = True
@ -506,7 +481,7 @@ class HmiRequest(object):
if self.__valid_data_length == 0:
# 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")
clibs.insert_logdb("DEBUG", "openapi", self.__response.decode())
clibs.insert_logdb("DEBUG", "openapi", str(json.loads(self.__response.decode())))
self.__response = b""
self.__is_first_frame = True
continue # 此时应该重新 get_headers
@ -538,7 +513,7 @@ class HmiRequest(object):
self.__leftovers = 0
# 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")
clibs.insert_logdb("DEBUG", "openapi", self.__response.decode())
clibs.insert_logdb("DEBUG", "openapi", str(json.loads(self.__response.decode())))
self.__response = b""
self.__is_first_frame = True
elif len(data) < self.__leftovers:
@ -596,7 +571,7 @@ class HmiRequest(object):
if self.__valid_data_length == 0:
# 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")
clibs.insert_logdb("DEBUG", "openapi", self.__response.decode())
clibs.insert_logdb("DEBUG", "openapi", str(json.loads(self.__response.decode())))
self.__response = b""
self.__is_first_frame = True
continue
@ -626,7 +601,7 @@ class HmiRequest(object):
if self.__valid_data_length == 0:
# 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")
clibs.insert_logdb("DEBUG", "openapi", self.__response.decode())
clibs.insert_logdb("DEBUG", "openapi", str(json.loads(self.__response.decode())))
self.__response = b""
self.__is_first_frame = True
continue
@ -701,20 +676,20 @@ class HmiRequest(object):
self.__response_xs = response
def get_from_id(self, msg_id, state):
f_text = f"%{msg_id}%"
f_text, res = f"%{msg_id}%", 0
if state is None:
self.close()
clibs.w2t(f"请求 {msg_id} 发送失败......", "red", "ReqSendFailed")
clibs.w2t(f"请求 {msg_id} 发送失败......\n", "red", "ReqSendFailed")
for _ in range(3):
time.sleep(clibs.interval * 2)
try:
clibs.lock.acquire(True)
clibs.cursor.execute(f"select content from logs where content like '{f_text}'")
res = len(clibs.cursor.fetchall())
records = clibs.cursor.fetchall()
finally:
clibs.lock.release()
if res >= 2:
break
if len(records) == 2:
return records
else:
clibs.insert_logdb("ERROR", "openapi", f"hr: 无法找到请求 {msg_id} 的响应")
self.close()
@ -739,7 +714,8 @@ class HmiRequest(object):
with open(f"{clibs.PREFIX}/files/protocols/{command}.json", encoding="utf-8", mode="r") as f_json:
req = json.load(f_json)
except Exception as Err:
clibs.insert_logdb("ERROR", "openapi", f"hr: 暂不支持 {command} 功能,或确认该功能存在... {Err}")
clibs.insert_logdb("ERROR", "openapi", f"hr-execution: 暂不支持 {command} 功能,或确认该功能存在... {Err}")
clibs.w2t(f"hr-execution: 暂不支持 {command} 功能,或确认该功能存在... {Err}", "red")
if p_flag == 0: # for old protocols
match command:
@ -1863,7 +1839,7 @@ class ExternalCommunication(object):
self.exec_desc = " :--: 返回 true 表示执行成功false 失败"
def socket_client(self):
self.__c = socket(AF_INET, SOCK_STREAM)
self.__c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.__c.connect((clibs.ip_addr, clibs.external_port))
clibs.insert_logdb("INFO", "openapi", f"ec: 外部通信连接成功...")
@ -2127,31 +2103,35 @@ class ExternalCommunication(object):
class PreDos(object):
def __init__(self):
def __init__(self, ip, port, username, password):
self.__ssh = None
self.__sftp = None
self.ip = ip
self.port = port
self.username = username
self.password = password
def __ssh2server(self):
try:
self.__ssh = SSHClient()
self.__ssh.set_missing_host_key_policy(AutoAddPolicy())
self.__ssh.connect(clibs.ip_addr, clibs.ssh_port, username=clibs.username, password=clibs.password)
self.__ssh.connect(hostname=self.ip, port=self.port, username=self.username, password=self.password)
self.__sftp = self.__ssh.open_sftp()
except Exception as Err:
msg = f"predos: SSH 无法连接到 {clibs.ip_addr}:{clibs.ssh_port},需检查网络连通性或者登录信息是否正确 {Err}"
msg = f"predos: SSH 无法连接到 {self.ip}:{self.port},需检查网络连通性或者登录信息是否正确 {Err}"
clibs.insert_logdb("ERROR", "openapi", msg)
clibs.w2t(msg, "red", f"SSHError: cannot connected to {clibs.ip_addr}:{clibs.ssh_port}")
clibs.w2t(msg, "red", f"SSHError: cannot connected to {self.ip}:{self.port}")
def push_prj_to_server(self, prj_file):
# prj_file本地工程完整路径
self.__ssh2server()
prj_name = prj_file.split("\\")[-1].split("/")[-1].split(".")[0]
prj_name = prj_file.split("/")[-1].split(".")[0]
self.__sftp.put(prj_file, f"/tmp/{prj_name}.zip")
cmd = f"cd /tmp; mkdir {prj_name}; unzip -d {prj_name} -q {prj_name}.zip; rm -rf /tmp/{prj_name}.zip; "
cmd += f"sudo rm -rf /home/luoshi/bin/controller/projects/{prj_name}; "
cmd += f"sudo mv /tmp/{prj_name}/ /home/luoshi/bin/controller/projects/"
stdin, stdout, stderr = self.__ssh.exec_command(cmd, get_pty=True)
stdin.write(clibs.password + "\n")
stdin.write(self.password + "\n")
stdout.read().decode() # 需要read一下才能正常执行
stderr.read().decode()
self.__ssh.close()
@ -2163,14 +2143,14 @@ class PreDos(object):
cmd = f"cd /tmp/; sudo rm -rf {prj_name}*; sudo cp -rf /home/luoshi/bin/controller/projects/{prj_name} .; "
cmd += f"sudo zip -q -r {prj_name}.zip {prj_name}/; sudo rm -rf {prj_name}"
stdin, stdout, stderr = self.__ssh.exec_command(cmd, get_pty=True)
stdin.write(clibs.password + "\n")
stdin.write(self.password + "\n")
print(stdout.read().decode()) # 需要read一下才能正常执行
print(stderr.read().decode())
self.__sftp.get(f"/tmp/{prj_name}.zip", local_prj_path)
cmd = f"sudo rm -rf /tmp/{prj_name}.zip"
stdin, stdout, stderr = self.__ssh.exec_command(cmd, get_pty=True)
stdin.write(clibs.password + "\n")
stdin.write(self.password + "\n")
print(stdout.read().decode()) # 需要read一下才能正常执行
print(stderr.read().decode())
@ -2184,7 +2164,7 @@ class PreDos(object):
self.__sftp.put(local_file, f"/tmp/{filename}")
cmd = f"sudo mv /tmp/{filename} {server_file}"
stdin, stdout, stderr = self.__ssh.exec_command(cmd, get_pty=True)
stdin.write(clibs.password + "\n")
stdin.write(self.password + "\n")
stdout.read().decode() # 需要read一下才能正常执行
stderr.read().decode()
self.__ssh.close()
@ -2195,21 +2175,21 @@ class PreDos(object):
self.__ssh2server()
cmd = f"sudo cp {server_file} /tmp/"
stdin, stdout, stderr = self.__ssh.exec_command(cmd, get_pty=True)
stdin.write(clibs.password + "\n")
stdin.write(self.password + "\n")
stdout.read().decode() # 需要read一下才能正常执行
stderr.read().decode()
filename = server_file.split("/")[-1]
self.__sftp.get(f"/tmp/{filename}", f"{local_file}")
cmd = f"sudo rm -rf /tmp/{filename}"
stdin, stdout, stderr = self.__ssh.exec_command(cmd, get_pty=True)
stdin.write(clibs.password + "\n")
stdin.write(self.password + "\n")
stdout.read().decode() # 需要read一下才能正常执行
stderr.read().decode()
self.__ssh.close()
def robot_init():
hr = HmiRequest()
hr = clibs.c_hr
pd = PreDos()
# 推送配置文件
clibs.insert_logdb("INFO", "openapi", "init: 推送配置文件 fieldbus_device.json/registers.json/registers.xml 到控制器,并配置 IO 设备,设备号为 7...")
@ -2254,7 +2234,7 @@ def robot_init():
hr.reload_fieldbus()
hr.set_fieldbus_device_params("autotest", True)
md = ModbusRequest()
md = clibs.c_md
# 触发急停并恢复
md.r_soft_estop(0)
md.r_soft_estop(1)
@ -2323,12 +2303,12 @@ def fw_updater(local_file_path):
fw_size = os.path.getsize(local_file_path)
if fw_size > 10000000:
# get previous version of xCore
hr = HmiRequest()
hr = clibs.c_hr
version_previous = hr.get_robot_params["version"]
hr.close()
# var def
remote_file_path = './upgrade/lircos.zip'
remote_file_path = "./upgrade/lircos.zip"
fw_content = bytearray()
package_data = bytearray()
package_data_with_head = bytearray()
@ -2336,7 +2316,7 @@ def fw_updater(local_file_path):
# socket connect
clibs.insert_logdb("INFO", "openapi", f"update firmware: 正在连接 {clibs.ip_addr}:{clibs.upgrade_port}...")
try:
tcp_socket = socket(AF_INET, SOCK_STREAM)
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_socket.connect((clibs.ip_addr, clibs.upgrade_port))
tcp_socket.setblocking(True)
except Exception as Err:
@ -2345,13 +2325,13 @@ def fw_updater(local_file_path):
# get firmware content of binary format
clibs.insert_logdb("INFO", "openapi", f"update firmware: 正在读取 {local_file_path} 文件内容...")
with open(local_file_path, 'rb') as f_fw:
with open(local_file_path, "rb") as f_fw:
fw_content += f_fw.read()
# construct package data: http://confluence.i.rokae.com/pages/viewpage.action?pageId=15634148
clibs.insert_logdb("INFO", "openapi", "update firmware: 正在构造数据包,以及包头...")
# 1 protocol id
protocol_id = c_ushort(htons(0)) # 2 bytes
protocol_id = c_ushort(socket.htons(0)) # 2 bytes
package_data += protocol_id
# 2 write type
@ -2369,7 +2349,7 @@ def fw_updater(local_file_path):
i += 2
# 4 remote path len
remote_file_path_len = c_ushort(htons(len(remote_file_path)))
remote_file_path_len = c_ushort(socket.htons(len(remote_file_path)))
package_data += remote_file_path_len
# 5 remote path
@ -2380,7 +2360,7 @@ def fw_updater(local_file_path):
# construct communication protocol: http://confluence.i.rokae.com/pages/viewpage.action?pageId=15634045
# 1 get package data with header
package_size = c_uint(htonl(len(package_data)))
package_size = c_uint(socket.htonl(len(package_data)))
package_type = c_ubyte(1) # 0-无协议 1-文件 2-json
package_reserve = c_ubyte(0) # 预留位
@ -2409,7 +2389,7 @@ def fw_updater(local_file_path):
if fw_size > 10000000:
# get current version of xCore
hr = HmiRequest()
hr = clibs.c_hr
version_current = hr.get_robot_params["version"]
hr.close()
@ -2429,7 +2409,7 @@ class UpgradeJsonCmd(object):
# socket connect
clibs.insert_logdb("INFO", "clibs", f"正在连接 {clibs.ip_addr}:{clibs.upgrade_port}...")
try:
self.__c = socket(AF_INET, SOCK_STREAM)
self.__c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__c.connect((clibs.ip_addr, clibs.upgrade_port))
self.__c.setblocking(True)
self.__c.settimeout(3)
@ -2439,16 +2419,16 @@ class UpgradeJsonCmd(object):
@staticmethod
def __do_package(cmd):
package_size = struct.pack('!I', len(cmd))
package_type = struct.pack('B', 2)
reserved_byte = struct.pack('B', 0)
package_size = struct.pack("!I", len(cmd))
package_type = struct.pack("B", 2)
reserved_byte = struct.pack("B", 0)
return package_size + package_type + reserved_byte + cmd
def __recv_result(self, cmd):
time.sleep(2)
try:
res = self.__c.recv(10240).decode()
except timeout:
except Exception:
res = "ResponseNone"
clibs.insert_logdb("INFO", "openapi", f"upgrade: 请求命令 {cmd.decode()} 的返回信息:\n{res[8:]}")
self.__c.close()
@ -2457,7 +2437,7 @@ class UpgradeJsonCmd(object):
def __exec(self, command: dict):
try:
self.__c.recv(10240)
except timeout:
except Exception:
pass
cmd = json.dumps(command, separators=(",", ":")).encode("utf-8")
self.__c.sendall(self.__do_package(cmd))

View File

@ -1,3 +1,4 @@
import json
import threading
import openpyxl
import pandas
@ -8,26 +9,26 @@ from common import clibs
def initialization(path, w2t, insert_logdb):
_, data_files = clibs.traversal_files(path, w2t)
count = 0
count, config_file = 0, None
for data_file in data_files:
filename = data_file.split("/")[-1]
if filename == "configs.xlsx":
if re.match(".*\\.cfg", filename):
config_file = filename
count += 1
elif filename == "T_电机电流.xlsx":
...
count += 1
else:
if not re.match("j[1-7].*\\.data", filename):
msg = f"不合规 {data_file}\n"
msg += "所有数据文件必须以 j[1-7]_ 开头,以 .data 结尾比如j1_abcdef.data\n配置文件需要命名为\"configs.xlsx\",结果文件需要命名为\"T_电机电流.xlsx\"\n"
msg += "需要有配置文件\"configs.xlsx\"表格,以及数据处理文件\"T_电机电流.xlsx\"表格,请检查整改后重新运行\n"
msg += "所有数据文件必须以 j[1-7]_ 开头,以 .data 结尾比如j1_abcdef.data请检查整改后重新运行\n"
w2t(msg, "red", "FilenameIllegal")
if count != 1:
msg = "需要有配置文件\"configs.xlsx\"表格,以及数据处理文件\"T_电机电流.xlsx\"表格,请检查整改后重新运行\n"
if count != 2:
msg = "需要有一个机型配置文件\"*.cfg\",以及一个数据处理文件\"T_电机电流.xlsx\"表格,请检查整改后重新运行\n"
w2t(msg, "red", "FilenameIllegal")
insert_logdb("INFO", "current", f"current: 获取必要文件:{data_files}")
return data_files
return data_files, config_file
def current_max(data_files, rcs, trq, w2t, insert_logdb):
@ -71,7 +72,7 @@ def current_max(data_files, rcs, trq, w2t, insert_logdb):
return current
def current_avg(data_files, rcs, trq, w2t, insert_logdb):
def current_avg(data_files, rcs, trqh, w2t, insert_logdb):
insert_logdb("INFO", "current", "AVG: 正在处理平均电流值逻辑...")
current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []}
for data_file in data_files:
@ -86,7 +87,7 @@ def current_avg(data_files, rcs, trq, w2t, insert_logdb):
rca = rcs[axis-1]
insert_logdb("INFO", "current", f"AVG: 最大列数为 {cols}{axis} 轴的额定电流为 {rca}")
col = df.columns.values[trq-1]
col = df.columns.values[trqh-1]
c_std = df[col].std()
c_avg = df[col].mean()
@ -113,7 +114,7 @@ def current_avg(data_files, rcs, trq, w2t, insert_logdb):
return current
def current_cycle(data_files, vel, trq, trqh, rrs, rcs, rpms, w2t, insert_logdb):
def current_cycle(data_files, vel, trq, trqh, sensor, rrs, rcs, params, w2t, insert_logdb):
result, hold, single, scenario, dur_time = None, [], [], [], 0
for data_file in data_files:
filename = data_file.split("/")[-1]
@ -137,6 +138,12 @@ def current_cycle(data_files, vel, trq, trqh, rrs, rcs, rpms, w2t, insert_logdb)
t_progress.start()
wb = t_excel.get_result()
ws = wb["统计"]
for idx in range(len(params)):
row = idx + 2
for col in range(2, 8):
ws.cell(row=row, column=col).value = params[idx][col-2]
if hold:
avg = current_avg(hold, rcs, trqh, w2t, insert_logdb)
for axis, cur_value in avg.items():
@ -144,9 +151,9 @@ def current_cycle(data_files, vel, trq, trqh, rrs, rcs, rpms, w2t, insert_logdb)
wb[sht_name]["O4"].value = float(cur_value[0])
if dur_time == 0:
p_single(wb, single, vel, rrs, w2t, insert_logdb)
p_single(wb, single, vel, trq, sensor, rrs, w2t, insert_logdb)
else:
p_scenario(wb, scenario, vel, rrs, dur_time, w2t, insert_logdb)
p_scenario(wb, scenario, vel, trq, sensor, rrs, dur_time, w2t)
clibs.stop = True
w2t(f"正在保存文件 {result},需要 10s 左右......\n")
@ -227,12 +234,12 @@ def get_row_number(threshold, flag, df, row_s, row_e, axis, insert_logdb):
else:
count_1 = 0
places = {"start": "起点", "middle": "中间点", "end": "终点"}
places = {"start": "起点", "middle": "中间点", "end": "终点"} # 因为是终点数据,所以可能有异常
insert_logdb("WARNING", "current", f"{axis} 轴获取{places[flag]}数据 {row_e} 可能有异常,需关注!")
return row_e
def p_single(wb, single, vel, rrs, w2t, insert_logdb):
def p_single(wb, single, vel, trq, sensor, rrs, w2t, insert_logdb):
# 1. 先找到第一个速度为零的点,数据从后往前找,一开始就是零的情况不予考虑
# 2. 记录第一个点的位置,继续向前查找第二个速度为零的点,同理,一开始为零的点不予考虑
# 3. 记录第二个点的位置,并将其中的数据拷贝至对应位置
@ -313,11 +320,11 @@ def p_single(wb, single, vel, rrs, w2t, insert_logdb):
if abs(row_end+row_start-2*row_middle) > 1000:
insert_logdb("WARNING", "current", f"{axis} 轴数据占空比异常!")
data = []
data, first_c, second_c, third_c = [], vel-1, trq-1, sensor-1
for row in range(row_start, row_end+1):
data.append(df_origin.iloc[row, 0])
data.append(df_origin.iloc[row, 1])
data.append(df_origin.iloc[row, 2])
data.append(df_origin.iloc[row, first_c])
data.append(df_origin.iloc[row, second_c])
data.append(df_origin.iloc[row, third_c])
i = 0
for row in ws.iter_rows(min_row=2, min_col=2, max_row=150000, max_col=4):
@ -328,14 +335,14 @@ def p_single(wb, single, vel, rrs, w2t, insert_logdb):
_ = f"{data[i]:.2f}"
cell.value = float(_)
i += 1
except Exception as Err:
except Exception:
if i % 3 == 0:
ws.cell((i//3)+2, 1).value = None
cell.value = None
i += 1
def p_scenario(wb, scenario, vel, rrs, dur_time, w2t, insert_logdb):
def p_scenario(wb, scenario, vel, trq, sensor, rrs, dur_time, w2t):
for data_file in scenario:
cycle = 0.001
axis = int(data_file.split("/")[-1].split("_")[0].removeprefix("j"))
@ -354,11 +361,11 @@ def p_scenario(wb, scenario, vel, rrs, dur_time, w2t, insert_logdb):
if row_end > df.index[-1]:
w2t(f"位置超限:{data_file} 共有 {df.index[-1]} 条数据,无法取到第 {row_end} 条数据,需要确认场景周期时间...", "red", "DataOverLimit")
data = []
data, first_c, second_c, third_c = [], vel-1, trq-1, sensor-1
for row in range(row_start, row_end+1):
data.append(df_origin.iloc[row, 0])
data.append(df_origin.iloc[row, 1])
data.append(df_origin.iloc[row, 2])
data.append(df_origin.iloc[row, first_c])
data.append(df_origin.iloc[row, second_c])
data.append(df_origin.iloc[row, third_c])
i = 0
for row in ws.iter_rows(min_row=2, min_col=2, max_row=250000, max_col=4):
@ -369,34 +376,44 @@ def p_scenario(wb, scenario, vel, rrs, dur_time, w2t, insert_logdb):
_ = f"{data[i]:.2f}"
cell.value = float(_)
i += 1
except Exception as Err:
except Exception:
cell.value = None
if i % 3 == 0:
ws.cell((i//3)+2, 1).value = None
i += 1
def get_configs(configfile, w2t, insert_logdb):
def get_configs(config_file, w2t, insert_logdb):
try:
wb = openpyxl.load_workbook(configfile, read_only=True)
ws = wb["Target"]
with open(config_file, mode="r", encoding="utf-8") as f_config:
configs = json.load(f_config)
except Exception as Err:
insert_logdb("ERROR", "current", f"无法打开 {configfile},获取配置文件参数错误 {Err}")
w2t(f"无法打开 {configfile}", color="red", desc="OpenFileError")
insert_logdb("ERROR", "current", f"get_config: 无法打开 {config_file},获取配置文件参数错误 {Err}")
w2t(f"无法打开 {config_file}", color="red", desc="OpenFileError")
# 最大角速度,额定电流,减速比,额定转速
rrs, avs, rcs, rpms = [], [], [], []
for i in range(2, 8):
rrs.append(abs(float(ws.cell(row=2, column=i).value)))
avs.append(abs(float(ws.cell(row=3, column=i).value)))
rpms.append(abs(float(ws.cell(row=4, column=i).value)))
rcs.append(abs(float(ws.cell(row=6, column=i).value)))
version = configs["VERSION"]
rcs = [abs(_) for _ in configs["MOTOR"]["RATED_TORQUE"]] # 电机额定电流rc for rated current
m_max_rcs = [] # 电机最大电流
m_hold_rcs = [] # 电机堵转电流
m_rts = [] # 电机额定转矩rt for rated torque
m_max_rts = [] # 电机峰值转矩
m_r_rpms = [] # 电机额定转速
m_max_rpms = [] # 电机最大转速
m_tcs = [] # 电机转矩常数tc for torque constant
rrs = [abs(_) for _ in configs["TRANSMISSION"]["REDUCTION_RATIO_NUMERATOR"]] # 减速比rr for reduction ratio
r_max_sst = [] # 减速器最大启停转矩sst for start and stop torque
r_max_t = [] # 减速器瞬时最大转矩
sc = [] # 采样周期sc for sample cycle
r_rts = [] # 减速器额定转矩
r_r_rpms = [] # 减速器额定转速
r_life_cycle = [] # 减速器L10寿命
r_avg_t = [] # 减速器平均负载转矩允许最大值
insert_logdb("INFO", "current", f"current: 获取减速比:{rrs}")
insert_logdb("INFO", "current", f"current: 获取角速度:{avs}")
insert_logdb("INFO", "current", f"current: 获取额定电流:{rcs}")
insert_logdb("INFO", "current", f"current: 获取额定转速:{rpms}")
return rrs, avs, rcs, rpms
insert_logdb("INFO", "current", f"get_configs: 机型文件版本 {config_file}_{version}")
insert_logdb("INFO", "current", f"get_configs: 减速比 {rrs}")
insert_logdb("INFO", "current", f"get_configs: 额定电流 {rcs}")
return rcs, m_max_rcs, m_hold_rcs, m_rts, m_max_rts, m_r_rpms, m_max_rpms, m_tcs, rrs, r_max_sst, r_max_t, sc, r_rts, r_r_rpms, r_life_cycle, r_avg_t
def main():
@ -405,18 +422,20 @@ def main():
vel = int(clibs.data_dp["_vel"])
trq = int(clibs.data_dp["_trq"])
trqh = int(clibs.data_dp["_trqh"])
sensor = int(clibs.data_dp["_sensor"])
w2t = clibs.w2t
insert_logdb = clibs.insert_logdb
insert_logdb("INFO", "current", "current: 参数初始化成功")
data_files = initialization(path, w2t, insert_logdb)
rrs, avs, rcs, rpms = get_configs(path + "\\configs.xlsx", w2t, insert_logdb)
data_files, config_file = initialization(path, w2t, insert_logdb)
params = get_configs(f"{path}/{config_file}", w2t, insert_logdb)
rcs, rrs = params[0], params[8]
if sub == "max":
current_max(data_files, rcs, trq, w2t, insert_logdb)
elif sub == "avg":
current_avg(data_files, rcs, trq, w2t, insert_logdb)
current_avg(data_files, rcs, trqh, w2t, insert_logdb)
elif sub == "cycle":
current_cycle(data_files, vel, trq, trqh, rrs, rcs, rpms, w2t, insert_logdb)
current_cycle(data_files, vel, trq, trqh, sensor, rrs, rcs, params, w2t, insert_logdb)
if __name__ == '__main__':

View File

@ -1,5 +1,183 @@
import pdfplumber
import openpyxl
import os
from common import clibs
def main():
print("iso")
def p_iso(file, p_files, ws, tmpfile):
p_files.append(file)
pdf = pdfplumber.open(file)
with open(tmpfile, mode="w", encoding="utf-8") as fb:
for page in pdf.pages:
fb.write(page.extract_text())
with open(tmpfile, mode="r", encoding="utf-8") as fb:
lines = fb.readlines()
lines = [line for line in lines if not line.startswith("Page ")]
for line in lines:
if line.strip() == "Pose Accuracy and Repeatability":
index = lines.index(line)
ws.cell(row=3, column=7).value = float(lines[index+4].split()[1])
ws.cell(row=4, column=7).value = float(lines[index+5].split()[1])
ws.cell(row=5, column=7).value = float(lines[index+6].split()[1])
ws.cell(row=6, column=7).value = float(lines[index+7].split()[1])
ws.cell(row=7, column=7).value = float(lines[index+8].split()[1])
ws.cell(row=8, column=7).value = float(lines[index+4].split()[2])
ws.cell(row=9, column=7).value = float(lines[index+5].split()[2])
ws.cell(row=10, column=7).value = float(lines[index+6].split()[2])
ws.cell(row=11, column=7).value = float(lines[index+7].split()[2])
ws.cell(row=12, column=7).value = float(lines[index+8].split()[2])
elif line.strip() == "Pose Accuracy Variation":
index = lines.index(line)
ws.cell(row=13, column=7).value = float(lines[index+4].split()[1])
ws.cell(row=14, column=7).value = float(lines[index+5].split()[1])
ws.cell(row=15, column=7).value = float(lines[index+6].split()[1])
elif line.strip() == "Distance Accuracy":
index = lines.index(line)
ws.cell(row=16, column=7).value = float(lines[index + 4].split()[1])
ws.cell(row=17, column=7).value = float(lines[index + 4].split()[2])
elif line.strip() == "Stabilisation Time and Overshoot":
index = lines.index(line)
ws.cell(row=18, column=7).value = float(lines[index + 7].split()[3])
ws.cell(row=19, column=7).value = float(lines[index + 7].split()[2])
elif line.strip() == "Velocity Accuracy and Repeatability":
index = lines.index(line)
ws.cell(row=20, column=7).value = float(lines[index + 4].split()[1])
ws.cell(row=21, column=7).value = float(lines[index + 4].split()[2])
ws.cell(row=22, column=7).value = float(lines[index + 4].split()[3])
elif line.strip()[:31] == "Path Accuracy and Repeatability":
index = lines.index(line)
ws.cell(row=29, column=7).value = float(lines[index + 4].split()[1])
ws.cell(row=30, column=7).value = float(lines[index + 4].split()[2])
elif line.strip() == "Corner Overshoot and Roundoff":
index = lines.index(line)
ws.cell(row=35, column=7).value = float(lines[index + 4].split()[1])
ws.cell(row=36, column=7).value = float(lines[index + 4].split()[2])
elif line.strip() == "Robot Weaving":
index = lines.index(line)
ws.cell(row=41, column=7).value = float(lines[index + 4].split()[2])
ws.cell(row=42, column=7).value = float(lines[index + 4].split()[3])
ws.cell(row=43, column=7).value = float(lines[index + 4].split()[4])
else:
pass
pdf.close()
def p_iso_100(file, p_files, ws, tmpfile):
p_files.append(file)
pdf = pdfplumber.open(file)
with open(tmpfile, mode="w", encoding="utf-8") as fb:
for page in pdf.pages:
fb.write(page.extract_text())
with open(tmpfile, mode="r", encoding="utf-8") as fb:
lines = fb.readlines()
lines = [line for line in lines if not line.startswith("Page ")]
for line in lines:
if line.strip() == "Velocity Accuracy and Repeatability":
index = lines.index(line)
ws.cell(row=26, column=7).value = float(lines[index + 4].split()[1])
ws.cell(row=27, column=7).value = float(lines[index + 4].split()[2])
ws.cell(row=28, column=7).value = float(lines[index + 4].split()[3])
elif line.strip()[:31] == "Path Accuracy and Repeatability":
index = lines.index(line)
ws.cell(row=33, column=7).value = float(lines[index + 4].split()[1])
ws.cell(row=34, column=7).value = float(lines[index + 4].split()[2])
elif line.strip() == "Corner Overshoot and Roundoff":
index = lines.index(line)
ws.cell(row=39, column=7).value = float(lines[index + 4].split()[1])
ws.cell(row=40, column=7).value = float(lines[index + 4].split()[2])
elif line.strip() == "Robot Weaving":
index = lines.index(line)
ws.cell(row=47, column=7).value = float(lines[index + 4].split()[2])
ws.cell(row=48, column=7).value = float(lines[index + 4].split()[3])
ws.cell(row=49, column=7).value = float(lines[index + 4].split()[4])
else:
pass
pdf.close()
def p_iso_1000(file, p_files, ws, tmpfile):
p_files.append(file)
pdf = pdfplumber.open(file)
with open(tmpfile, mode="w", encoding="utf-8") as fb:
for page in pdf.pages:
fb.write(page.extract_text())
with open(tmpfile, mode="r", encoding="utf-8") as fb:
lines = fb.readlines()
lines = [line for line in lines if not line.startswith("Page ")]
for line in lines:
if line.strip() == "Velocity Accuracy and Repeatability":
index = lines.index(line)
ws.cell(row=23, column=7).value = float(lines[index + 4].split()[1])
ws.cell(row=24, column=7).value = float(lines[index + 4].split()[2])
ws.cell(row=25, column=7).value = float(lines[index + 4].split()[3])
elif line.strip()[:31] == "Path Accuracy and Repeatability":
index = lines.index(line)
ws.cell(row=31, column=7).value = float(lines[index + 4].split()[1])
ws.cell(row=32, column=7).value = float(lines[index + 4].split()[2])
elif line.strip() == "Corner Overshoot and Roundoff":
index = lines.index(line)
ws.cell(row=37, column=7).value = float(lines[index + 4].split()[1])
ws.cell(row=38, column=7).value = float(lines[index + 4].split()[2])
elif line.strip() == "Robot Weaving":
index = lines.index(line)
ws.cell(row=44, column=7).value = float(lines[index + 4].split()[2])
ws.cell(row=45, column=7).value = float(lines[index + 4].split()[3])
ws.cell(row=46, column=7).value = float(lines[index + 4].split()[4])
else:
pass
pdf.close()
def main():
path = clibs.data_dp["_path"]
w2t = clibs.w2t
dirs, files = clibs.traversal_files(path, 1)
filename = f"{path}/iso-results.xlsx"
tmpfile = f"{path}/data.txt"
wb, ws = None, None
try:
wb = openpyxl.load_workbook(filename)
ws = wb.active
for i in range(3, 50):
ws.cell(row=i, column=7).value = None
except Exception as Err:
clibs.insert_logdb("ERROR", "iso", f"main: 无法打开文件 {filename}")
w2t(f"发生错误:{Err}", "red", "FileOpenError")
p_files = []
for file in files:
if file.endswith(".pdf") and file.split("/")[-1] == "ISO.pdf":
w2t(f"正在处理{file}......\n")
p_iso(file, p_files, ws, tmpfile)
w2t(f"文件{file}已处理完毕。\n")
elif file.endswith(".pdf") and file.split("/")[-1] == "ISO-V100.pdf":
w2t(f"正在处理{file}......\n")
p_iso_100(file, p_files, ws, tmpfile)
w2t(f"文件{file}已处理完毕。\n")
elif file.endswith(".pdf") and file.split("/")[-1] == "ISO-V1000.pdf":
w2t(f"正在处理{file}......\n")
p_iso_1000(file, p_files, ws, tmpfile)
w2t(f"文件{file}已处理完毕。\n")
else:
pass
wb.save(filename)
wb.close()
if len(p_files) == 0:
w2t(f"目录 {path} 下没有需要处理的文件,需要确认......", "red")
else:
os.remove(tmpfile)
w2t("------------------------------------------\n")
w2t("所有文件均已处理完毕!\n")
if __name__ == "__main__":
main()

View File

@ -1,5 +1,148 @@
import pandas
import csv
import openpyxl
from common import clibs
def main():
print("wavelogger")
def find_point(bof, step, margin, threshold, pos, data_file, flag, df, row, w2t):
# bof: backward or forward
# pos: used for debug
# flag: greater than or lower than
row_target = None
row_origin = df.index[-1] - margin + 1
if flag == "gt":
while 0 < row < row_origin:
value = float(df.iloc[row, 2])
if value > threshold:
row = row - step if bof == "backward" else row + step
continue
else:
row_target = row - step if bof == "backward" else row + step
break
else:
if bof == "backward":
clibs.insert_logdb("ERROR", "wavelogger", f"find_point-gt: [{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...")
w2t(f"[{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...", "red", "DataError")
elif bof == "forward":
row_target = row + margin # to end while loop in function `single_file_proc`
elif flag == "lt":
while 0 < row < row_origin:
value = float(df.iloc[row, 2])
if value < threshold:
row = row - step if bof == "backward" else row + step
continue
else:
row_target = row - step if bof == "backward" else row + step
break
else:
if bof == "backward":
clibs.insert_logdb("ERROR", "wavelogger", f"find_point-lt: [{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...")
w2t(f"[{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...", "red", "DataError")
elif bof == "forward":
row_target = row + margin # to end while loop in function `single_file_proc`
return row_target
def get_cycle_info(data_file, step, margin, threshold, w2t):
# end -> middle: low
# middle -> start: high
# 1. 从最后读取数据无论是大于1还是小于1都舍弃找到相反的值的起始点
# 2. 从起始点,继续往前寻找,找到与之数值相反的中间点
# 3. 从中间点,继续往前寻找,找到与之数值相反的结束点,至此,得到了高低数值的时间区间以及一轮的周期时间
csv_reader = csv.reader(open(data_file))
begin = int(next(csv_reader)[1])
df = pandas.read_csv(data_file, sep=",", encoding="gbk", skip_blank_lines=False, header=begin - 1, on_bad_lines="skip")
row = df.index[-1] - margin
if float(df.iloc[row, 2]) < threshold:
row = find_point("backward", step, margin, threshold, "a1", data_file, "lt", df, row, w2t)
_row = find_point("backward", step, margin, threshold, "a2", data_file, "gt", df, row, w2t)
_row = find_point("backward", step, margin, threshold, "a3", data_file, "lt", df, _row, w2t)
row_end = find_point("backward", step, margin, threshold, "a4", data_file, "gt", df, _row, w2t)
row_middle = find_point("backward", step, margin, threshold, "a5", data_file, "lt", df, row_end, w2t)
row_start = find_point("backward", step, margin, threshold, "a6", data_file, "gt", df, row_middle, w2t)
# print(f"row_end = {row_end}")
# print(f"row_middle = {row_middle}")
# print(f"row_start = {row_start}")
return row_end-row_middle, row_middle-row_start, row_end-row_start, df
def initialization(path, w2t):
_, data_files = clibs.traversal_files(path, w2t)
for data_file in data_files:
if not data_file.lower().endswith(".csv"):
clibs.insert_logdb("ERROR", "wavelogger", f"init: {data_file} 文件后缀错误,只允许 .csv 文件,需要确认!")
w2t(f"{data_file} 文件后缀错误,只允许 .csv 文件,需要确认!", "red", "FileTypeError")
return data_files
def preparation(data_file, step, margin, threshold, wb, w2t):
shtname = data_file.split("/")[-1].split(".")[0]
ws = wb.create_sheet(shtname)
low, high, cycle, df = get_cycle_info(data_file, step, margin, threshold, w2t)
return ws, df, low, high, cycle
def single_file_proc(ws, data_file, step, threshold, margin, data_length, df, cycle, w2t):
row, row_lt, row_gt, count, count_i, data = 1, 1, 1, 1, 1, {}
row_max = df.index[-1] - margin
while row < row_max:
if count not in data.keys():
data[count] = []
value = float(df.iloc[row, 2])
if value < threshold:
row_lt = find_point("forward", step, margin, threshold, "c"+str(row), data_file, "lt", df, row, w2t)
start = int(row_gt + (row_lt - row_gt - data_length) / 2)
end = start + data_length
value = df.iloc[start:end, 2].mean() + 3 * df.iloc[start:end, 2].std()
if value > 1:
msg = f"{data_file} 文件第 {count} 轮 第 {count_i} 个数据可能有问题,需人工手动确认,确认有问题可删除,无问题则保留"
clibs.insert_logdb("WARNING", "wavelogger", msg)
w2t(msg, "orange")
data[count].append(value)
count_i += 1
else:
row_gt = find_point("forward", step, margin, threshold, "c"+str(row), data_file, "gt", df, row, w2t)
if row_gt - row_lt > cycle * 2:
count += 1
count_i = 1
row = max(row_gt, row_lt)
for i in range(2, 10):
ws.cell(row=1, column=i).value = f"{i-1}次测试"
ws.cell(row=i, column=1).value = f"{i-1}次精度变化"
for i in sorted(data.keys()):
row, column = 2, i + 1
for value in data[i]:
ws.cell(row=row, column=column).value = float(value)
row += 1
def execution(data_files, w2t):
wb = openpyxl.Workbook()
step, margin, data_length, threshold = 5, 50, 50, 5
for data_file in data_files:
ws, df, low, high, cycle = preparation(data_file, step, margin, threshold, wb, w2t)
single_file_proc(ws, data_file, step, threshold, margin, data_length, df, cycle, w2t)
wd = "/".join(data_files[0].split("/")[:-1])
filename = wd + "/result.xlsx"
wb.save(filename)
wb.close()
w2t("----------------------------------------\n")
w2t("所有文件均已处理完毕\n")
def main():
path = clibs.data_dp["_path"]
w2t = clibs.w2t
data_files = initialization(path, w2t)
execution(data_files, w2t)
if __name__ == "__main__":
main()