完善rokae自动化测试脚本工具,增加readme文件等
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,3 +2,5 @@
|
|||||||
.idea/
|
.idea/
|
||||||
rokae/testbench.py
|
rokae/testbench.py
|
||||||
**/__pycache__/
|
**/__pycache__/
|
||||||
|
gui/
|
||||||
|
testing/
|
220
rokae/README.md
Normal file
220
rokae/README.md
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
## 自动化测试工具脚本
|
||||||
|
|
||||||
|
### 0. 用前须知
|
||||||
|
|
||||||
|
1. 调用必须在rokae目录下执行
|
||||||
|
2. python3.13开发,使用时需版本匹配,并安装requirements.txt中的依赖库
|
||||||
|
|
||||||
|
### 1. socket通信(支持xService)
|
||||||
|
|
||||||
|
> #### **A. 调用方法示例**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from codes import openapi
|
||||||
|
import time
|
||||||
|
|
||||||
|
hr = openapi.HmiRequest()
|
||||||
|
time.sleep(2)
|
||||||
|
hr.close()
|
||||||
|
msg_id = hr.exec_cmd("controller.get_params")
|
||||||
|
record = hr.get_from_id(msg_id)
|
||||||
|
print(f"version = {eval(record)['data']['version']}")
|
||||||
|
```
|
||||||
|
|
||||||
|
> #### **B. 目前支持(后续可按需增加)**
|
||||||
|
|
||||||
|
```
|
||||||
|
collision.get_params
|
||||||
|
collision.set_params
|
||||||
|
controller.get_params
|
||||||
|
controller.heart
|
||||||
|
controller.reboot
|
||||||
|
controller.set_params
|
||||||
|
device.get_params
|
||||||
|
diagnosis.get_params
|
||||||
|
diagnosis.open
|
||||||
|
diagnosis.save
|
||||||
|
diagnosis.set_params
|
||||||
|
drag.get_params
|
||||||
|
drag.set_params
|
||||||
|
fieldbus_device.get_params
|
||||||
|
fieldbus_device.load_cfg
|
||||||
|
fieldbus_device.set_params
|
||||||
|
io_device.load_cfg
|
||||||
|
jog.get_params
|
||||||
|
jog.set_params
|
||||||
|
jog.start
|
||||||
|
log_code.data.code_list
|
||||||
|
log_code.data
|
||||||
|
modbus.get_params
|
||||||
|
modbus.get_values
|
||||||
|
modbus.load_cfg
|
||||||
|
modbus.set_params
|
||||||
|
move.get_joint_pos
|
||||||
|
move.get_monitor_cfg
|
||||||
|
move.get_params
|
||||||
|
move.get_pos
|
||||||
|
move.get_quickstop_distance
|
||||||
|
move.get_quickturn_pos
|
||||||
|
move.quick_turn
|
||||||
|
move.set_monitor_cfg
|
||||||
|
move.set_params
|
||||||
|
move.set_quickstop_distance
|
||||||
|
move.set_quickturn_pos
|
||||||
|
move.stop
|
||||||
|
overview.get_autoload
|
||||||
|
overview.get_cur_prj
|
||||||
|
overview.reload
|
||||||
|
overview.set_autoload
|
||||||
|
register.set_value
|
||||||
|
rl_task.pp_to_main
|
||||||
|
rl_task.run
|
||||||
|
rl_task.set_run_params
|
||||||
|
rl_task.stop
|
||||||
|
safety.safety_area.overall_enable
|
||||||
|
safety.safety_area.safety_area_enable
|
||||||
|
safety.safety_area.set_param
|
||||||
|
safety.safety_area.signal_enable
|
||||||
|
safety_area_data
|
||||||
|
servo.clear_alarm
|
||||||
|
socket.get_params
|
||||||
|
socket.set_params
|
||||||
|
soft_limit.get_params
|
||||||
|
soft_limit.set_params
|
||||||
|
state.get_state
|
||||||
|
state.get_tp_mode
|
||||||
|
state.set_tp_mode
|
||||||
|
state.switch_auto
|
||||||
|
state.switch_manual
|
||||||
|
state.switch_motor_off
|
||||||
|
state.switch_motor_on
|
||||||
|
system_io.query_configuration
|
||||||
|
system_io.query_event_cfg
|
||||||
|
system_io.update_configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. modbus通信
|
||||||
|
|
||||||
|
> #### **A. 调用方法示例**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from codes import openapi
|
||||||
|
|
||||||
|
md = openapi.ModbusRequest()
|
||||||
|
md.r_switch_auto()
|
||||||
|
_ = md.w_sta_tcp_vel
|
||||||
|
print(_)
|
||||||
|
```
|
||||||
|
|
||||||
|
> #### **B. 目前支持**
|
||||||
|
|
||||||
|
自定义的寄存器读写操作,以及98%以上的预置modbus功能码。
|
||||||
|
|
||||||
|
### 3. 外部通信
|
||||||
|
|
||||||
|
> #### **A. 调用方法示例**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from codes import openapi
|
||||||
|
|
||||||
|
ec = openapi.EcRequest()
|
||||||
|
_ = ec.get_cart_pos
|
||||||
|
ec.close_reduced_mode()
|
||||||
|
```
|
||||||
|
|
||||||
|
> #### **B. 目前支持**
|
||||||
|
|
||||||
|
包括状态和控制操作,覆盖98%以上的外部通信功能。
|
||||||
|
|
||||||
|
### 4. 文件传输
|
||||||
|
|
||||||
|
> #### **A. 调用方法示例**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from codes import openapi
|
||||||
|
|
||||||
|
pd = openapi.PreDos()
|
||||||
|
downloads = "C:/Users/Administrator/Downloads"
|
||||||
|
pd.pull_prj_from_server("aio", downloads)
|
||||||
|
local_prj = downloads + "/aio.zip"
|
||||||
|
pd.push_prj_to_server(local_prj)
|
||||||
|
|
||||||
|
local_file = downloads + "/aio.txt"
|
||||||
|
server_file = "/tmp/aio.txt"
|
||||||
|
pd.push_file_to_server(local_file, server_file)
|
||||||
|
pd.pull_file_from_server(server_file, local_file)
|
||||||
|
```
|
||||||
|
|
||||||
|
> #### **B. 目前支持(除了prj_name为工程名,其他均为对应系统下的绝对路径)**
|
||||||
|
|
||||||
|
- push_prj_to_server(prj_file)
|
||||||
|
- pull_prj_from_server(prj_name, local_prj_path)
|
||||||
|
- push_file_to_server(local_file, server_file)
|
||||||
|
- pull_file_from_server(server_file, local_file)
|
||||||
|
|
||||||
|
### 5. 初始化以及固件更新
|
||||||
|
|
||||||
|
> #### **A. 调用方法示例**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from codes import openapi
|
||||||
|
|
||||||
|
ri = openapi.RobotInit()
|
||||||
|
ri.robot_init()
|
||||||
|
ri.fw_updater("C:/Users/Administrator/Downloads/FW/v3.1.1.rpa")
|
||||||
|
ri.fw_updater("C:/Users/Administrator/Downloads/XMS3-R580-W4G3C2_ME_AE_SS_xC.v3.1.0.R0.rpa")
|
||||||
|
```
|
||||||
|
|
||||||
|
> #### **B. 目前支持**
|
||||||
|
|
||||||
|
- robot_init() # 初始化机器人,新建modbus设备,并配置寄存器文件,打开IO设备中的modbus设备
|
||||||
|
- fw_updater(fw_file) # 目前仅测试支持机型文件和控制器
|
||||||
|
|
||||||
|
### 6. 升级协议
|
||||||
|
|
||||||
|
> #### **A. 调用方法示例**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from codes import openapi
|
||||||
|
|
||||||
|
ur = openapi.UpgradeRequest()
|
||||||
|
ur.version_query()
|
||||||
|
ur.robot_reboot()
|
||||||
|
```
|
||||||
|
|
||||||
|
> #### **B. 目前支持**
|
||||||
|
|
||||||
|
- erase_cfg
|
||||||
|
- clear_rubbish
|
||||||
|
- soft_reboot
|
||||||
|
- version_query
|
||||||
|
- robot_reboot
|
||||||
|
- backup_origin
|
||||||
|
- origin_recovery
|
||||||
|
|
||||||
|
### 7. 生成运动轨迹
|
||||||
|
|
||||||
|
> #### **A. 调用方法示例**
|
||||||
|
|
||||||
|
```python
|
||||||
|
from codes import openapi
|
||||||
|
|
||||||
|
hr = openapi.HmiRequest()
|
||||||
|
pd = openapi.PreDos() # 如下三行首次运行时,必须打开
|
||||||
|
ri = openapi.RobotInit(hr, pd) # 非首次重复运行时,可以注释
|
||||||
|
ri.robot_init() # 注释后可以节省运行时间
|
||||||
|
md = openapi.ModbusRequest()
|
||||||
|
|
||||||
|
pt = openapi.PlotTrajectory(hr, md, prj_name="arc_test_M", tasks=["task0", ], curve_name="hw_cart_pos_feedback_tcp_in_world")
|
||||||
|
pt.draw_traj()
|
||||||
|
```
|
||||||
|
|
||||||
|
> #### **B. 目前支持**
|
||||||
|
|
||||||
|
自动保存3D空间运动曲线图到本地的trajectory.html文件
|
||||||
|
|
||||||
|
- hw_cart_pos_feedback_motorside
|
||||||
|
- hw_cart_pos_feedback_linkside
|
||||||
|
- hw_cart_pos_feedback_encoder_tcp_in_world
|
||||||
|
- hw_cart_pos_feedback_flan_in_world
|
||||||
|
- hw_cart_pos_feedback_tcp_in_world
|
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ip_addr": "192.168.40.130",
|
"ip_addr": "192.168.0.160",
|
||||||
"ssh_port": "22",
|
"ssh_port": "22",
|
||||||
"socket_port": 5050,
|
"socket_port": 5050,
|
||||||
"xService_port": 6666,
|
"xService_port": 6666,
|
||||||
|
BIN
rokae/codes/openapi.cp313-win_amd64.pyd
Normal file
BIN
rokae/codes/openapi.cp313-win_amd64.pyd
Normal file
Binary file not shown.
@@ -11,13 +11,18 @@ from typing import Callable, Dict
|
|||||||
from loguru import logger
|
from loguru import logger
|
||||||
from pymodbus.client.tcp import ModbusTcpClient
|
from pymodbus.client.tcp import ModbusTcpClient
|
||||||
from paramiko import SSHClient, AutoAddPolicy
|
from paramiko import SSHClient, AutoAddPolicy
|
||||||
|
import plotly.graph_objects as go
|
||||||
|
|
||||||
from codes import clibs
|
from codes import clibs
|
||||||
|
|
||||||
|
|
||||||
class HmiRequest:
|
class HmiRequest:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.c = self.c_xs = self.t_rx_pkg = self.t_rx_pkg_xs = self.t_s_heart = None
|
self.c: socket.socket
|
||||||
|
self.c_xs: socket.socket
|
||||||
|
self.t_rx_pkg: threading.Thread
|
||||||
|
self.t_rx_pkg_xs: threading.Thread
|
||||||
|
self.t_s_heart: threading.Thread
|
||||||
self.data = self.data_xs = b""
|
self.data = self.data_xs = b""
|
||||||
self.is_connected = True
|
self.is_connected = True
|
||||||
self.sock_conn()
|
self.sock_conn()
|
||||||
@@ -170,8 +175,8 @@ class HmiRequest:
|
|||||||
cmd, ts = msg_id.split("@")
|
cmd, ts = msg_id.split("@")
|
||||||
t = ts.replace("T", " ")
|
t = ts.replace("T", " ")
|
||||||
t_ts = datetime.timestamp(datetime.strptime(t, "%Y-%m-%d %H:%M:%S.%f"))
|
t_ts = datetime.timestamp(datetime.strptime(t, "%Y-%m-%d %H:%M:%S.%f"))
|
||||||
t_send = datetime.strftime(datetime.fromtimestamp(t_ts-time_delay), '%Y-%m-%d %H:%M:%S.%f')
|
t_send = datetime.strftime(datetime.fromtimestamp(t_ts-time_delay), "%Y-%m-%d %H:%M:%S.%f")
|
||||||
t_receive = datetime.strftime(datetime.fromtimestamp(t_ts+time_delay), '%Y-%m-%d %H:%M:%S.%f')
|
t_receive = datetime.strftime(datetime.fromtimestamp(t_ts+time_delay), "%Y-%m-%d %H:%M:%S.%f")
|
||||||
for idx in range(time_delay):
|
for idx in range(time_delay):
|
||||||
time.sleep(clibs.interval)
|
time.sleep(clibs.interval)
|
||||||
try:
|
try:
|
||||||
@@ -187,7 +192,7 @@ class HmiRequest:
|
|||||||
logger.error(f"hr: {time_delay}s内无法找到请求 {msg_id} 的响应!")
|
logger.error(f"hr: {time_delay}s内无法找到请求 {msg_id} 的响应!")
|
||||||
# raise Exception()
|
# raise Exception()
|
||||||
|
|
||||||
def exec_cmd(self, cmd, **kwargs):
|
def exec_cmd(self, cmd: str, **kwargs):
|
||||||
try:
|
try:
|
||||||
with open(f"{clibs.base_path}/assets/protocols/{cmd}.json", mode="r", encoding="utf-8") as f_cmd:
|
with open(f"{clibs.base_path}/assets/protocols/{cmd}.json", mode="r", encoding="utf-8") as f_cmd:
|
||||||
req = json.load(f_cmd)
|
req = json.load(f_cmd)
|
||||||
@@ -199,15 +204,14 @@ class HmiRequest:
|
|||||||
logger.error(f"hr: 暂不支持 {cmd} 功能,或确认该功能存在,err = {err}")
|
logger.error(f"hr: 暂不支持 {cmd} 功能,或确认该功能存在,err = {err}")
|
||||||
raise Exception()
|
raise Exception()
|
||||||
|
|
||||||
match cmd:
|
if cmd in ["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_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_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":
|
req["data"].update(kwargs)
|
||||||
req["data"].update(kwargs)
|
elif cmd in ["safety.safety_area.signal_enable", "safety.safety_area.overall_enable", "safety.safety_area.safety_area_enable", "safety.safety_area.set_param"]:
|
||||||
case "safety.safety_area.signal_enable" | "safety.safety_area.overall_enable" | "safety.safety_area.safety_area_enable" | "safety.safety_area.set_param":
|
req["c"].update(kwargs)
|
||||||
req["c"].update(kwargs)
|
elif cmd in ["log_code.data.code_list"]:
|
||||||
case "log_code.data.code_list":
|
req["s"]["log_code.data"]["code_list"] = kwargs["code_list"]
|
||||||
req["s"]["log_code.data"]["code_list"] = kwargs["code_list"]
|
else:
|
||||||
case _:
|
pass
|
||||||
pass
|
|
||||||
|
|
||||||
cmd = json.dumps(req, separators=(",", ":"))
|
cmd = json.dumps(req, separators=(",", ":"))
|
||||||
if p_type == 0:
|
if p_type == 0:
|
||||||
@@ -217,12 +221,13 @@ class HmiRequest:
|
|||||||
else:
|
else:
|
||||||
raise Exception("Unexpected CMD Input")
|
raise Exception("Unexpected CMD Input")
|
||||||
|
|
||||||
|
time.sleep(clibs.interval/4)
|
||||||
return req["id"]
|
return req["id"]
|
||||||
|
|
||||||
|
|
||||||
class ModbusRequest:
|
class ModbusRequest:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.c = None
|
self.c: ModbusTcpClient
|
||||||
self.sock_conn()
|
self.sock_conn()
|
||||||
|
|
||||||
def sock_conn(self):
|
def sock_conn(self):
|
||||||
@@ -250,10 +255,10 @@ class ModbusRequest:
|
|||||||
def r_reset_estop_clear_alarm(self):
|
def r_reset_estop_clear_alarm(self):
|
||||||
self.__reg_high_pulse(40002, "复位外部急停状态,并清除告警信息")
|
self.__reg_high_pulse(40002, "复位外部急停状态,并清除告警信息")
|
||||||
|
|
||||||
def r_motor_off(self):
|
def r_motor_on(self):
|
||||||
self.__reg_high_pulse(40004, "上电")
|
self.__reg_high_pulse(40004, "上电")
|
||||||
|
|
||||||
def r_motor_on(self):
|
def r_motor_off(self):
|
||||||
self.__reg_high_pulse(40005, "下电")
|
self.__reg_high_pulse(40005, "下电")
|
||||||
|
|
||||||
def r_motor_on_off(self, action: bool):
|
def r_motor_on_off(self, action: bool):
|
||||||
@@ -333,7 +338,7 @@ class ModbusRequest:
|
|||||||
|
|
||||||
def __get_state(self, addr: int, count: int = 1, **kwargs):
|
def __get_state(self, addr: int, count: int = 1, **kwargs):
|
||||||
res = self.c.read_holding_registers(addr, count=count).registers[0]
|
res = self.c.read_holding_registers(addr, count=count).registers[0]
|
||||||
logger.info(f"md: {addr}-{kwargs['func']},结果为{res} {kwargs['desc']}")
|
logger.info(f'md: {addr}-{kwargs["func"]},结果为{res} {kwargs["desc"]}')
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -501,7 +506,7 @@ class ModbusRequest:
|
|||||||
|
|
||||||
class EcRequest:
|
class EcRequest:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.c = None
|
self.c: socket.socket
|
||||||
self.exec_desc = " :--: true表示执行成功,false表示执行失败"
|
self.exec_desc = " :--: true表示执行成功,false表示执行失败"
|
||||||
self.sock_conn()
|
self.sock_conn()
|
||||||
|
|
||||||
@@ -783,7 +788,7 @@ class PreDos(object):
|
|||||||
logger.error(f"pd: SSH无法连接,需检查网络连通性或者登录信息是否正确 -- {e}")
|
logger.error(f"pd: SSH无法连接,需检查网络连通性或者登录信息是否正确 -- {e}")
|
||||||
raise Exception()
|
raise Exception()
|
||||||
|
|
||||||
def push_prj_to_server(self, prj_file):
|
def push_prj_to_server(self, prj_file: str):
|
||||||
# prj_file:工程的本地完整路径
|
# prj_file:工程的本地完整路径
|
||||||
self.__ssh2server()
|
self.__ssh2server()
|
||||||
prj_name, postfix = os.path.basename(prj_file).split(".")
|
prj_name, postfix = os.path.basename(prj_file).split(".")
|
||||||
@@ -797,7 +802,7 @@ class PreDos(object):
|
|||||||
_ = stderr.read().decode()
|
_ = stderr.read().decode()
|
||||||
self.__ssh.close()
|
self.__ssh.close()
|
||||||
|
|
||||||
def pull_prj_from_server(self, prj_name, local_prj_path):
|
def pull_prj_from_server(self, prj_name: str, local_prj_path: str):
|
||||||
# prj_name:要拉取的服务端工程名
|
# prj_name:要拉取的服务端工程名
|
||||||
# local_prj_path:存放工程文件的本地路径
|
# local_prj_path:存放工程文件的本地路径
|
||||||
self.__ssh2server()
|
self.__ssh2server()
|
||||||
@@ -817,7 +822,7 @@ class PreDos(object):
|
|||||||
|
|
||||||
self.__ssh.close()
|
self.__ssh.close()
|
||||||
|
|
||||||
def push_file_to_server(self, local_file, server_file):
|
def push_file_to_server(self, local_file: str, server_file: str):
|
||||||
# local_file:本地文件完整路径
|
# local_file:本地文件完整路径
|
||||||
# server_file:服务端文件完整路径
|
# server_file:服务端文件完整路径
|
||||||
self.__ssh2server()
|
self.__ssh2server()
|
||||||
@@ -830,7 +835,7 @@ class PreDos(object):
|
|||||||
_ = stderr.read().decode()
|
_ = stderr.read().decode()
|
||||||
self.__ssh.close()
|
self.__ssh.close()
|
||||||
|
|
||||||
def pull_file_from_server(self, server_file, local_file):
|
def pull_file_from_server(self, server_file: str, local_file: str):
|
||||||
# local_file:本地文件完整路径
|
# local_file:本地文件完整路径
|
||||||
# server_file:服务端文件完整路径
|
# server_file:服务端文件完整路径
|
||||||
self.__ssh2server()
|
self.__ssh2server()
|
||||||
@@ -851,9 +856,9 @@ class PreDos(object):
|
|||||||
|
|
||||||
|
|
||||||
class RobotInit(object):
|
class RobotInit(object):
|
||||||
def __init__(self):
|
def __init__(self, hr: HmiRequest, pd: PreDos):
|
||||||
self.pd = PreDos()
|
self.hr: HmiRequest = hr
|
||||||
self.hr = HmiRequest()
|
self.pd: PreDos = pd
|
||||||
|
|
||||||
def robot_init(self):
|
def robot_init(self):
|
||||||
# 推送配置文件
|
# 推送配置文件
|
||||||
@@ -903,7 +908,7 @@ class RobotInit(object):
|
|||||||
self.hr.exec_cmd("io_device.load_cfg")
|
self.hr.exec_cmd("io_device.load_cfg")
|
||||||
self.hr.exec_cmd("modbus.load_cfg")
|
self.hr.exec_cmd("modbus.load_cfg")
|
||||||
|
|
||||||
def fw_updater(self, fw_file):
|
def fw_updater(self, fw_file: str):
|
||||||
"""
|
"""
|
||||||
:param fw_file: xCore升级文件/机型文件的绝对路径
|
:param fw_file: xCore升级文件/机型文件的绝对路径
|
||||||
:return: None
|
:return: None
|
||||||
@@ -984,7 +989,7 @@ class UpgradeRequest:
|
|||||||
http://confluence.i.rokae.com/pages/viewpage.action?pageId=21531754
|
http://confluence.i.rokae.com/pages/viewpage.action?pageId=21531754
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.c = None
|
self.c: socket.socket
|
||||||
self.sock_conn()
|
self.sock_conn()
|
||||||
|
|
||||||
def sock_conn(self):
|
def sock_conn(self):
|
||||||
@@ -1039,3 +1044,88 @@ class UpgradeRequest:
|
|||||||
|
|
||||||
def origin_recovery(self): # OK 恢复备份,恢复后手动设置,并重启生效
|
def origin_recovery(self): # OK 恢复备份,恢复后手动设置,并重启生效
|
||||||
self.sr_pkg({"cmd": "recover"})
|
self.sr_pkg({"cmd": "recover"})
|
||||||
|
|
||||||
|
|
||||||
|
class PlotTrajectory:
|
||||||
|
# hw_cart_pos_feedback_motorside:笛卡尔空间下电机侧位置反馈,单位m,rad
|
||||||
|
# hw_cart_pos_feedback_linkside:笛卡尔空间下连杆侧位置反馈,单位m,rad
|
||||||
|
# hw_cart_pos_feedback_encoder_tcp_in_world:笛卡尔位置反馈(关节端编码器数据),单位m,rad
|
||||||
|
# hw_cart_pos_feedback_flan_in_world:笛卡尔位置反馈(法兰相对于世界坐标系)
|
||||||
|
# hw_cart_pos_feedback_tcp_in_world:笛卡尔位置反馈(tcp相对于世界坐标系)
|
||||||
|
def __init__(self, hr: HmiRequest, md: ModbusRequest, prj_name: str, tasks: list, curve_name: str = "hw_cart_pos_feedback_tcp_in_world"):
|
||||||
|
self.hr: HmiRequest = hr
|
||||||
|
self.md: ModbusRequest = md
|
||||||
|
self.curve_name: str = curve_name
|
||||||
|
self.prj_name: str = prj_name
|
||||||
|
self.tasks: list = tasks
|
||||||
|
|
||||||
|
def __change_curve_state(self, stat):
|
||||||
|
if not stat:
|
||||||
|
display_pdo_params = [{"name": "count", "channel": 0}]
|
||||||
|
else:
|
||||||
|
display_pdo_params = [{"name": self.curve_name, "channel": chl} for chl in range(3)]
|
||||||
|
self.hr.exec_cmd("diagnosis.set_params", display_pdo_params=display_pdo_params)
|
||||||
|
self.hr.exec_cmd("diagnosis.open", open=stat, display_open=stat)
|
||||||
|
|
||||||
|
def __plot_trajectory(self, start_time, end_time):
|
||||||
|
x, y, z = [], [], []
|
||||||
|
try:
|
||||||
|
clibs.lock.acquire(True)
|
||||||
|
clibs.cursor.execute(f"SELECT content FROM logs WHERE timestamp BETWEEN '{start_time}' AND '{end_time}' AND content LIKE '%diagnosis.result%' ORDER BY id ASC")
|
||||||
|
records = clibs.cursor.fetchall()
|
||||||
|
finally:
|
||||||
|
clibs.lock.release()
|
||||||
|
|
||||||
|
for record in records:
|
||||||
|
data = eval(record[0])["data"]
|
||||||
|
for item in data:
|
||||||
|
item_rm = [x * 1000 for x in reversed(item["value"])]
|
||||||
|
# item_rm = item["value"]
|
||||||
|
if item.get("channel", None) == 0 and item.get("name", None) == self.curve_name:
|
||||||
|
x.extend(item_rm)
|
||||||
|
elif item.get("channel", None) == 1 and item.get("name", None) == self.curve_name:
|
||||||
|
y.extend(item_rm)
|
||||||
|
elif item.get("channel", None) == 2 and item.get("name", None) == self.curve_name:
|
||||||
|
z.extend(item_rm)
|
||||||
|
|
||||||
|
# pyplot
|
||||||
|
trace_path = go.Scatter3d(x=x, y=y, z=z, mode="lines", line=dict(color="blue", width=4), name="运动轨迹")
|
||||||
|
trace_start = go.Scatter3d(x=[x[0]], y=[y[0]], z=[z[0]], mode="markers+text", marker=dict(color="green", size=8), text=["起点"], textposition="top center", name="起点")
|
||||||
|
trace_end = go.Scatter3d(x=[x[-1]], y=[y[-1]], z=[z[-1]], mode="markers+text", marker=dict(color="red", size=8), text=["终点"], textposition="bottom center", name="终点")
|
||||||
|
fig = go.Figure(data=[trace_path, trace_start, trace_end])
|
||||||
|
fig.write_html("trajectory.html", auto_open=False)
|
||||||
|
|
||||||
|
fig.update_layout(
|
||||||
|
scene=dict(
|
||||||
|
xaxis_title="X",
|
||||||
|
yaxis_title="Y",
|
||||||
|
zaxis_title="Z"
|
||||||
|
),
|
||||||
|
margin=dict(l=0, r=0, b=0, t=30),
|
||||||
|
legend=dict(x=0, y=1),
|
||||||
|
dragmode="orbit"
|
||||||
|
)
|
||||||
|
|
||||||
|
fig.show(config={"scrollZoom": True})
|
||||||
|
|
||||||
|
def draw_traj(self):
|
||||||
|
self.md.r_soft_estop(True)
|
||||||
|
self.md.r_reset_estop_clear_alarm()
|
||||||
|
self.md.r_switch_auto()
|
||||||
|
self.md.r_motor_on()
|
||||||
|
|
||||||
|
self.__change_curve_state(True)
|
||||||
|
self.hr.exec_cmd("overview.reload", prj_path=f"{self.prj_name}/_build/{self.prj_name}.prj", tasks=self.tasks)
|
||||||
|
self.hr.exec_cmd("rl_task.set_run_params", loop_mode=False, override=1.0)
|
||||||
|
self.hr.exec_cmd("rl_task.pp_to_main", tasks=self.tasks)
|
||||||
|
self.hr.exec_cmd("rl_task.run", tasks=self.tasks)
|
||||||
|
|
||||||
|
t_start = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
|
||||||
|
time.sleep(clibs.interval)
|
||||||
|
while self.md.w_sta_robot_is_moving:
|
||||||
|
time.sleep(clibs.interval * 10)
|
||||||
|
time.sleep(clibs.interval * 5)
|
||||||
|
t_end = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
|
||||||
|
self.__change_curve_state(False)
|
||||||
|
|
||||||
|
self.__plot_trajectory(t_start, t_end)
|
||||||
|
229
rokae/codes/openapi.pyi
Normal file
229
rokae/codes/openapi.pyi
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
import socket
|
||||||
|
import threading
|
||||||
|
from pymodbus.client.tcp import ModbusTcpClient
|
||||||
|
|
||||||
|
class HmiRequest:
|
||||||
|
is_connected: bool
|
||||||
|
def __init__(self) -> None: ...
|
||||||
|
def close(self) -> None: ...
|
||||||
|
@staticmethod
|
||||||
|
def get_from_id(msg_id: str) -> str: ...
|
||||||
|
def exec_cmd(self, cmd: str, **kwargs): ...
|
||||||
|
|
||||||
|
class ModbusRequest:
|
||||||
|
def __init__(self) -> None: ...
|
||||||
|
def r_clear_alarm(self) -> None: ...
|
||||||
|
def r_reset_estop(self) -> None: ...
|
||||||
|
def r_reset_estop_clear_alarm(self) -> None: ...
|
||||||
|
def r_motor_on(self) -> None: ...
|
||||||
|
def r_motor_off(self) -> None: ...
|
||||||
|
def r_motor_on_off(self, action: bool): ...
|
||||||
|
def r_motoron_pp2main_start(self) -> None: ...
|
||||||
|
def r_motoron_start(self) -> None: ...
|
||||||
|
def r_pulse_motoroff(self) -> None: ...
|
||||||
|
def r_pp2main(self) -> None: ...
|
||||||
|
def r_program_start(self) -> None: ...
|
||||||
|
def r_program_stop(self) -> None: ...
|
||||||
|
def r_program_start_stop(self, action: bool): ...
|
||||||
|
def r_set_program_speed(self, speed: int): ...
|
||||||
|
def r_soft_estop(self, action: bool): ...
|
||||||
|
def r_switch_auto_motoron(self) -> None: ...
|
||||||
|
def r_switch_auto(self) -> None: ...
|
||||||
|
def r_switch_manual(self) -> None: ...
|
||||||
|
def r_switch_auto_manual(self, action: bool): ...
|
||||||
|
def r_reduced_mode(self, action: bool): ...
|
||||||
|
def r_switch_safe_region(self, idx: int, enable: bool): ...
|
||||||
|
@property
|
||||||
|
def w_alarm_state(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_collision(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_collision_alarm(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_collision_open(self): ...
|
||||||
|
@property
|
||||||
|
def w_controller_is_running(self): ...
|
||||||
|
@property
|
||||||
|
def w_encoder_low_battery(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_error_code(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_estop(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_heartbeat(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_home(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_motor(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_operation_mode(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_program(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_program_full(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_program_not_run(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_program_reset(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_program_speed(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_reduce_mode(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_robot_is_busy(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_robot_is_moving(self): ...
|
||||||
|
@property
|
||||||
|
def w_safe_door_state(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_safe_jnt_pos(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_soft_estop(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_safe_region(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_on_path(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_near_path(self): ...
|
||||||
|
@property
|
||||||
|
def w_sta_cart_pose(self) -> list: ...
|
||||||
|
@property
|
||||||
|
def w_sta_cart_vel(self) -> list: ...
|
||||||
|
@property
|
||||||
|
def w_sta_jnt_pose(self) -> list: ...
|
||||||
|
@property
|
||||||
|
def w_sta_jnt_vel(self) -> list: ...
|
||||||
|
@property
|
||||||
|
def w_sta_tcp_pose(self) -> list: ...
|
||||||
|
@property
|
||||||
|
def w_sta_tcp_vel(self) -> list: ...
|
||||||
|
@property
|
||||||
|
def w_sta_tcp_vel_mag(self): ...
|
||||||
|
def io_write_coils(self, addr, value: bool): ...
|
||||||
|
def io_read_coils(self): ...
|
||||||
|
def io_read_discretes(self): ...
|
||||||
|
|
||||||
|
class EcRequest:
|
||||||
|
def __init__(self) -> None: ...
|
||||||
|
def motor_on(self): ...
|
||||||
|
def motor_off(self): ...
|
||||||
|
def pp_to_main(self): ...
|
||||||
|
def program_start(self): ...
|
||||||
|
def program_stop(self): ...
|
||||||
|
def clear_alarm(self): ...
|
||||||
|
def switch_operation_auto(self): ...
|
||||||
|
def switch_operation_manual(self): ...
|
||||||
|
def open_drag_mode(self): ...
|
||||||
|
def close_drag_mode(self): ...
|
||||||
|
def get_project_list(self): ...
|
||||||
|
def get_current_project(self): ...
|
||||||
|
def load_project(self, project_name): ...
|
||||||
|
def estop_reset(self): ...
|
||||||
|
def estopreset_and_clearalarm(self): ...
|
||||||
|
def motoron_pp2main_start(self): ...
|
||||||
|
def motoron_start(self): ...
|
||||||
|
def pause_motoroff(self): ...
|
||||||
|
def set_program_speed(self, speed: int = 20): ...
|
||||||
|
def set_soft_estop(self, enable: str): ...
|
||||||
|
def switch_auto_motoron(self): ...
|
||||||
|
def open_safe_region(self, number: int): ...
|
||||||
|
def close_safe_region(self, number: int): ...
|
||||||
|
def open_reduced_mode(self): ...
|
||||||
|
def close_reduced_mode(self): ...
|
||||||
|
def setdo_value(self, do_name: str, do_value: str): ...
|
||||||
|
def set_robot_time(self, robot_time: str = ...): ...
|
||||||
|
@property
|
||||||
|
def motor_on_state(self): ...
|
||||||
|
@property
|
||||||
|
def robot_running_state(self): ...
|
||||||
|
@property
|
||||||
|
def estop_state(self): ...
|
||||||
|
@property
|
||||||
|
def operation_mode(self): ...
|
||||||
|
@property
|
||||||
|
def home_state(self): ...
|
||||||
|
@property
|
||||||
|
def fault_state(self): ...
|
||||||
|
@property
|
||||||
|
def collision_state(self): ...
|
||||||
|
@property
|
||||||
|
def task_state(self): ...
|
||||||
|
@property
|
||||||
|
def get_cart_pos(self): ...
|
||||||
|
@property
|
||||||
|
def get_joint_pos(self): ...
|
||||||
|
@property
|
||||||
|
def get_joint_vel(self): ...
|
||||||
|
@property
|
||||||
|
def get_joint_trq(self): ...
|
||||||
|
@property
|
||||||
|
def reduced_mode_state(self): ...
|
||||||
|
def get_io_state(self, io_list: str): ...
|
||||||
|
@property
|
||||||
|
def alarm_state(self): ...
|
||||||
|
@property
|
||||||
|
def collision_alarm_state(self): ...
|
||||||
|
@property
|
||||||
|
def collision_open_state(self): ...
|
||||||
|
@property
|
||||||
|
def controller_is_running(self): ...
|
||||||
|
@property
|
||||||
|
def encoder_low_battery_state(self): ...
|
||||||
|
@property
|
||||||
|
def robot_error_code(self): ...
|
||||||
|
@property
|
||||||
|
def rl_pause_state(self): ...
|
||||||
|
@property
|
||||||
|
def program_reset_state(self): ...
|
||||||
|
@property
|
||||||
|
def program_speed_value(self): ...
|
||||||
|
@property
|
||||||
|
def robot_is_busy(self): ...
|
||||||
|
@property
|
||||||
|
def robot_is_moving(self): ...
|
||||||
|
@property
|
||||||
|
def safe_door_state(self): ...
|
||||||
|
@property
|
||||||
|
def soft_estop_state(self): ...
|
||||||
|
@property
|
||||||
|
def get_cart_vel(self): ...
|
||||||
|
@property
|
||||||
|
def get_tcp_pos(self): ...
|
||||||
|
@property
|
||||||
|
def get_tcp_vel(self): ...
|
||||||
|
@property
|
||||||
|
def get_tcp_vel_mag(self): ...
|
||||||
|
@property
|
||||||
|
def ext_estop_state(self): ...
|
||||||
|
@property
|
||||||
|
def hand_estop_state(self): ...
|
||||||
|
@property
|
||||||
|
def sta_on_path(self): ...
|
||||||
|
@property
|
||||||
|
def sta_near_path(self): ...
|
||||||
|
|
||||||
|
class PreDos:
|
||||||
|
def __init__(self) -> None: ...
|
||||||
|
def push_prj_to_server(self, prj_file: str): ...
|
||||||
|
def pull_prj_from_server(self, prj_name: str, local_prj_path: str): ...
|
||||||
|
def push_file_to_server(self, local_file: str, server_file: str): ...
|
||||||
|
def pull_file_from_server(self, server_file: str, local_file: str): ...
|
||||||
|
|
||||||
|
class RobotInit:
|
||||||
|
def __init__(self, hr: HmiRequest, pd: PreDos) -> None: ...
|
||||||
|
def robot_init(self) -> None: ...
|
||||||
|
def fw_updater(self, fw_file: str): ...
|
||||||
|
|
||||||
|
class UpgradeRequest:
|
||||||
|
def __init__(self) -> None: ...
|
||||||
|
def erase_cfg(self) -> None: ...
|
||||||
|
def clear_rubbish(self) -> None: ...
|
||||||
|
def soft_reboot(self) -> None: ...
|
||||||
|
def version_query(self) -> None: ...
|
||||||
|
def robot_reboot(self) -> None: ...
|
||||||
|
def backup_origin(self) -> None: ...
|
||||||
|
def origin_recovery(self) -> None: ...
|
||||||
|
|
||||||
|
class PlotTrajectory:
|
||||||
|
def __init__(self, hr: HmiRequest, md: ModbusRequest, prj_name: str, tasks: list, curve_name: str = 'hw_cart_pos_feedback_tcp_in_world') -> None: ...
|
||||||
|
def draw_traj(self) -> None: ...
|
4
rokae/requirements.txt
Normal file
4
rokae/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
loguru==0.7.3
|
||||||
|
paramiko==3.5.1
|
||||||
|
plotly==6.3.0
|
||||||
|
pymodbus==3.9.2
|
BIN
rokae/自动化测试工具脚本说明.pdf
Normal file
BIN
rokae/自动化测试工具脚本说明.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user