底层控制接口基本完成,部分功能待力控层完成后测试
96
Massage/MassageControl/hardware/DobotDemo.py
Normal file
@ -0,0 +1,96 @@
|
||||
from dobot_api import DobotApiFeedBack,DobotApiDashboard
|
||||
import threading
|
||||
from time import sleep
|
||||
import re
|
||||
|
||||
class DobotDemo:
|
||||
def __init__(self, ip):
|
||||
self.ip = ip
|
||||
self.dashboardPort = 29999
|
||||
self.feedPortFour = 30004
|
||||
self.dashboard = None
|
||||
self.feedInfo = []
|
||||
self.__globalLockValue = threading.Lock()
|
||||
|
||||
class item:
|
||||
def __init__(self):
|
||||
self.robotMode = -1 #
|
||||
self.robotCurrentCommandID = 0
|
||||
self.MessageSize = -1
|
||||
self.DigitalInputs =-1
|
||||
self.DigitalOutputs = -1
|
||||
# 自定义添加所需反馈数据
|
||||
|
||||
self.feedData = item() # 定义结构对象
|
||||
|
||||
def start(self):
|
||||
# 启动机器人并使能
|
||||
self.dashboard = DobotApiDashboard(self.ip, self.dashboardPort)
|
||||
self.feedFour = DobotApiFeedBack(self.ip, self.feedPortFour)
|
||||
if self.parseResultId(self.dashboard.EnableRobot())[0] != 0:
|
||||
print("使能失败: 检查29999端口是否被占用")
|
||||
return
|
||||
print("使能成功")
|
||||
|
||||
# 启动状态反馈线程
|
||||
feed_thread = threading.Thread(
|
||||
target=self.GetFeed) # 机器状态反馈线程
|
||||
feed_thread.daemon = True
|
||||
feed_thread.start()
|
||||
|
||||
# 定义两个目标点
|
||||
point_a = [146.3759,-283.4321,332.3956,177.7879,-1.8540,147.5821]
|
||||
point_b = [146.3759,-283.4321,432.3956,177.7879,-1.8540,147.5821]
|
||||
|
||||
# 走点循环
|
||||
while True:
|
||||
print("DI:", self.feedData.DigitalInputs,"2DI:", bin(self.feedData.DigitalInputs),"--16:",hex(self.feedData.DigitalInputs))
|
||||
print("DO:", self.feedData.DigitalOutputs,"2DO:" ,bin(self.feedData.DigitalOutputs),"--16:",hex(self.feedData.DigitalOutputs))
|
||||
print("robomode",self.feedData.robotMode)
|
||||
sleep(2)
|
||||
|
||||
def GetFeed(self):
|
||||
# 获取机器人状态
|
||||
while True:
|
||||
feedInfo = self.feedFour.feedBackData()
|
||||
with self.__globalLockValue:
|
||||
if feedInfo is not None:
|
||||
if hex((feedInfo['TestValue'][0])) == '0x123456789abcdef':
|
||||
# 基础字段
|
||||
self.feedData.MessageSize = feedInfo['len'][0]
|
||||
self.feedData.robotMode = feedInfo['RobotMode'][0]
|
||||
self.feedData.DigitalInputs = feedInfo['DigitalInputs'][0]
|
||||
self.feedData.DigitalOutputs = feedInfo['DigitalOutputs'][0]
|
||||
# 自定义添加所需反馈数据
|
||||
'''
|
||||
self.feedData.DigitalOutputs = int(feedInfo['DigitalOutputs'][0])
|
||||
self.feedData.RobotMode = int(feedInfo['RobotMode'][0])
|
||||
self.feedData.TimeStamp = int(feedInfo['TimeStamp'][0])
|
||||
'''
|
||||
|
||||
def RunPoint(self, point_list):
|
||||
# 走点指令
|
||||
recvmovemess = self.dashboard.MovJ(*point_list, 0)
|
||||
print("MovJ:", recvmovemess)
|
||||
print(self.parseResultId(recvmovemess))
|
||||
currentCommandID = self.parseResultId(recvmovemess)[1]
|
||||
print("指令 ID:", currentCommandID)
|
||||
#sleep(0.02)
|
||||
while True: #完成判断循环
|
||||
|
||||
print(self.feedData.robotMode)
|
||||
if self.feedData.robotMode == 5 and self.feedData.robotCurrentCommandID == currentCommandID:
|
||||
print("运动结束")
|
||||
break
|
||||
sleep(0.1)
|
||||
|
||||
def parseResultId(self, valueRecv):
|
||||
# 解析返回值,确保机器人在 TCP 控制模式
|
||||
if "Not Tcp" in valueRecv:
|
||||
print("Control Mode Is Not Tcp")
|
||||
return [1]
|
||||
return [int(num) for num in re.findall(r'-?\d+', valueRecv)] or [2]
|
||||
|
||||
def __del__(self):
|
||||
del self.dashboard
|
||||
del self.feedFour
|
3077
Massage/MassageControl/hardware/dobot_api.py
Normal file
346
Massage/MassageControl/hardware/dobot_nova5.py
Normal file
@ -0,0 +1,346 @@
|
||||
from dobot_api import DobotApiFeedBack,DobotApiDashboard
|
||||
import threading
|
||||
from time import sleep
|
||||
import re
|
||||
|
||||
class dobot_nova5:
|
||||
def __init__(self,ip):
|
||||
self.ip = ip
|
||||
self.dashboardPort = 29999 ## 一发一收-设置-控制及运动端口号
|
||||
self.feedFourPort = 30004 ## 第四实时反馈(8ms)反馈数据端口号
|
||||
self.dashboard = None ## 初始化控制及运动端口实例
|
||||
self.feedFour = None ## 初始化数据反馈端口实例
|
||||
self.feedInfo = []
|
||||
self.__globalLockValue = threading.Lock() # 多线程安全
|
||||
|
||||
class feedbackItem:
|
||||
def __init__(self):
|
||||
self.robotMode = -1
|
||||
self.robotCurrentCommandID = 0
|
||||
self.MessageSize = -1
|
||||
self.DigitalInputs = -1
|
||||
self.DigitalOutputs = -1
|
||||
# ... 自定义反馈数据
|
||||
self.feedbackData = feedbackItem() # 自定义反馈数据结构体
|
||||
|
||||
def parseResultId(self,valueRecv):
|
||||
# 解析返回值
|
||||
if "Not Tcp" in valueRecv:
|
||||
print("Control Mode is not TCP")
|
||||
print("机械臂不在二次开发模式下")
|
||||
return [1]
|
||||
return [int(num) for num in re.findall(r'-?\d+',valueRecv)] or [2]
|
||||
|
||||
def GetFeedback(self):
|
||||
while True:
|
||||
feedInfo = self.feedFour.feedBackData()
|
||||
with self.__globalLockValue:
|
||||
if feedInfo is not None:
|
||||
if hex((feedInfo['TestValue'][0]))=='0x123456789abcdef': ## DOBOT官方的数据魔数验证
|
||||
# 基础字段
|
||||
self.feedbackData.MessageSize = feedInfo['len'][0]
|
||||
self.feedbackData.robotMode = feedInfo['RobotMode'][0]
|
||||
self.feedbackData.DigitalInputs = feedInfo['DigitalInputs'][0]
|
||||
self.feedbackData.DigitalOutputs = feedInfo['DigitalOutputs'][0]
|
||||
self.feedbackData.robotCurrentCommandID = feedInfo['CurrentCommandId'][0]
|
||||
# 自定义添加所需反馈数据
|
||||
'''
|
||||
self.feedData.DigitalOutputs = int(feedInfo['DigitalOutputs'][0])
|
||||
self.feedData.RobotMode = int(feedInfo['RobotMode'][0])
|
||||
self.feedData.TimeStamp = int(feedInfo['TimeStamp'][0])
|
||||
'''
|
||||
|
||||
def start(self):
|
||||
self.dashboard = DobotApiDashboard(self.ip,self.dashboardPort)
|
||||
self.feedFour = DobotApiFeedBack(self.ip,self.feedFourPort)
|
||||
if self.parseResultId(self.dashboard.EnableRobot())[0] != 0:
|
||||
print("使能失败:检查29999端口是否被占用")
|
||||
return
|
||||
print("机械臂使能成功")
|
||||
|
||||
# 状态反馈线程
|
||||
feedback_thread = threading.Thread(
|
||||
target=self.GetFeedback # 机器状态反馈线程
|
||||
)
|
||||
feedback_thread.daemon = True
|
||||
feedback_thread.start()
|
||||
|
||||
def RunPoint_P_inPose(self,poses_list):
|
||||
'''
|
||||
RUNPOINT_P 以关节运动方式运动到目标点
|
||||
MovJ flag = 0 通过位姿走点,输入为[X Y Z RX RY RZ] unit: mm/deg
|
||||
'''
|
||||
# 走点
|
||||
recvmovemess = self.dashboard.MovJ(*poses_list,0)
|
||||
print("MovJ:",recvmovemess)
|
||||
print(self.parseResultId(recvmovemess))
|
||||
currentCommandID = self.parseResultId(recvmovemess)[1]
|
||||
print("指令 ID:", currentCommandID)
|
||||
# sleep(0.02)
|
||||
while True: # 完成判断循环
|
||||
########## 调试注释 #############
|
||||
# print("robot mode",self.feedbackData.robotMode)
|
||||
# print("feedback current ID", self.feedbackData.robotCurrentCommandID)
|
||||
# print("指令 ID:", currentCommandID)
|
||||
########## 调试注释 #############
|
||||
currentCommandID = self.parseResultId(self.dashboard.GetCurrentCommandID())[1]
|
||||
if self.feedbackData.robotMode == 5 and self.feedbackData.robotCurrentCommandID == currentCommandID:
|
||||
print("该次运动完成")
|
||||
break
|
||||
sleep(0.1)
|
||||
|
||||
def RunPoint_P_inJoint(self,joints_list):
|
||||
'''
|
||||
RUNPOINT_P 以关节运动方式运动到目标点
|
||||
MovJ flag = 1 通过关节角度走点,输入为[J1 J2 J3 J4 J5 J6] unit: deg
|
||||
'''
|
||||
# 走点
|
||||
recvmovemess = self.dashboard.MovJ(*joints_list,1)
|
||||
print("MovJ:",recvmovemess)
|
||||
print(self.parseResultId(recvmovemess))
|
||||
currentCommandID = self.parseResultId(recvmovemess)[1]
|
||||
print("指令 ID:", currentCommandID)
|
||||
# sleep(0.02)
|
||||
while True: # 完成判断循环
|
||||
########## 调试注释 #############
|
||||
# print("robot mode",self.feedbackData.robotMode)
|
||||
# print("feedback current ID", self.feedbackData.robotCurrentCommandID)
|
||||
# print("指令 ID:", currentCommandID)
|
||||
# print("30004",self.dashboard.GetCurrentCommandID())
|
||||
########## 调试注释 #############
|
||||
currentCommandID = self.parseResultId(self.dashboard.GetCurrentCommandID())[1]
|
||||
if self.feedbackData.robotMode == 5 and self.feedbackData.robotCurrentCommandID == currentCommandID:
|
||||
print("该次运动完成")
|
||||
break
|
||||
sleep(0.1)
|
||||
|
||||
def RunPoint_L_inPose(self,poses_list):
|
||||
'''
|
||||
RUNPOINT_L 以直线运动方式运动到目标点
|
||||
MovJ flag = 0 通过位姿走点,输入为[X Y Z RX RY RZ] unit: mm/deg
|
||||
'''
|
||||
# 走点
|
||||
recvmovemess = self.dashboard.MovL(*poses_list,0)
|
||||
print("MovL:",recvmovemess)
|
||||
print(self.parseResultId(recvmovemess))
|
||||
currentCommandID = self.parseResultId(recvmovemess)[1]
|
||||
print("指令 ID:", currentCommandID)
|
||||
while True:
|
||||
currentCommandID = self.parseResultId(self.dashboard.GetCurrentCommandID())[1]
|
||||
if self.feedbackData.robotMode == 5 and self.feedbackData.robotCurrentCommandID == currentCommandID:
|
||||
print("该次运动完成")
|
||||
break
|
||||
sleep(0.1)
|
||||
|
||||
def RunPoint_L_inJoint(self,joints_list):
|
||||
'''
|
||||
RUNPOINT_L 以直线运动方式运动到目标点
|
||||
MovJ flag = 0 通过位姿走点,输入为[X Y Z RX RY RZ] unit: mm/deg
|
||||
'''
|
||||
# 走点
|
||||
recvmovemess = self.dashboard.MovL(*joints_list,0)
|
||||
print("MovL:",recvmovemess)
|
||||
print(self.parseResultId(recvmovemess))
|
||||
currentCommandID = self.parseResultId(recvmovemess)[1]
|
||||
print("指令 ID:", currentCommandID)
|
||||
while True:
|
||||
currentCommandID = self.parseResultId(self.dashboard.GetCurrentCommandID())[1]
|
||||
if self.feedbackData.robotMode == 5 and self.feedbackData.robotCurrentCommandID == currentCommandID:
|
||||
print("该次运动完成")
|
||||
break
|
||||
sleep(0.1)
|
||||
|
||||
def ServoJoint(self,joints_list,t=-1,aheadtime=-1,gain=-1):
|
||||
# 关节空间伺服
|
||||
recvmovemess = self.dashboard.ServoJ(*joints_list,t,aheadtime,gain)
|
||||
print("ServoJ:",recvmovemess)
|
||||
print(self.parseResultId(recvmovemess))
|
||||
currentCommandID = self.parseResultId(recvmovemess)[1]
|
||||
print("指令 ID", currentCommandID)
|
||||
while True:
|
||||
currentCommandID = self.parseResultId(self.dashboard.GetCurrentCommandID())[1]
|
||||
if self.feedbackData.robotMode == 5 and self.feedbackData.robotCurrentCommandID == currentCommandID:
|
||||
print("完成一次伺服动作")
|
||||
break
|
||||
|
||||
def ServoPose(self,poses_list,t=-1,aheadtime=-1,gain=-1):
|
||||
# 位姿伺服
|
||||
recvmovemess = self.dashboard.ServoP(*poses_list,t,aheadtime,gain)
|
||||
print("ServoP:",recvmovemess)
|
||||
print(self.parseResultId(recvmovemess))
|
||||
currentCommandID = self.parseResultId(recvmovemess)[1]
|
||||
print("指令 ID", currentCommandID)
|
||||
while True:
|
||||
currentCommandID = self.parseResultId(self.dashboard.GetCurrentCommandID())[1]
|
||||
if self.feedbackData.robotMode == 5 and self.feedbackData.robotCurrentCommandID == currentCommandID:
|
||||
print("完成一次伺服动作")
|
||||
break
|
||||
|
||||
def setEndEffector(self,i,tool_i):
|
||||
'''
|
||||
设置工具坐标系在索引i. i!=0
|
||||
tool_i 需要以字符串形式输入 "{x,y,z,rx,ry,rz}"
|
||||
'''
|
||||
if i == 0:
|
||||
print("不可修改工具0(初始法兰坐标系)")
|
||||
return
|
||||
|
||||
if i not in {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}:
|
||||
print("工具坐标系序号超出范围")
|
||||
return
|
||||
|
||||
code = self.dashboard.SetTool(i,tool_i)
|
||||
if code == 0:
|
||||
print(f"设置工具坐标系{i}的偏移量成功")
|
||||
else:
|
||||
print(f"设置工具坐标系{i}失败")
|
||||
return
|
||||
|
||||
def chooseEndEffector(self,i):
|
||||
'''
|
||||
切换工具坐标系, 0~9
|
||||
'''
|
||||
if i not in {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}:
|
||||
print("工具坐标系序号超出范围")
|
||||
return
|
||||
code = self.dashboard.Tool(i)
|
||||
if code == 0:
|
||||
print(f"切换为工具坐标系{i}成功")
|
||||
else:
|
||||
print("切换工具坐标系失败")
|
||||
return
|
||||
|
||||
def setBaseFrame(self,i,base_i):
|
||||
'''
|
||||
设置工具坐标系在索引i. i!=0
|
||||
base_i 修改后的用户坐标系(非偏移量!) 需要以字符串形式输入 "{x,y,z,rx,ry,rz}"
|
||||
'''
|
||||
if i == 0:
|
||||
print("不可修改用户坐标系0(初始基坐标系)")
|
||||
return
|
||||
|
||||
if i not in {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}:
|
||||
print("用户坐标系序号超出范围")
|
||||
return
|
||||
|
||||
code = self.dashboard.SetUser(i,base_i)
|
||||
if code == 0:
|
||||
print(f"设置用户坐标系{i}成功")
|
||||
else:
|
||||
print(f"设置用户坐标系{i}失败")
|
||||
return
|
||||
|
||||
def chooseBaseFrame(self,i):
|
||||
'''
|
||||
切换用户基坐标系, 0~9
|
||||
'''
|
||||
if i not in {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}:
|
||||
print("工具坐标系序号超出范围")
|
||||
return
|
||||
code = self.dashboard.User(i)
|
||||
if code == 0:
|
||||
print(f"切换为用户基坐标系{i}成功")
|
||||
else:
|
||||
print("切换用户基坐标系失败")
|
||||
return
|
||||
|
||||
def getPose(self,user=-1,tool=-1):
|
||||
if (user == -1) != (tool == -1): ## XOR 必须同时设置或者同时不设置
|
||||
print("必须同时设置或同时不设置坐标系参数")
|
||||
res = self.dashboard.GetPose(user,tool) # 返回字符串
|
||||
code = int(res[0]) # 拿到的是字符串
|
||||
if code == 0:
|
||||
pass
|
||||
# print("success")
|
||||
else:
|
||||
print("获取位姿失败")
|
||||
return
|
||||
# 处理字符串
|
||||
start = res.find("{")+1
|
||||
end = res.find("}")
|
||||
pose_str = res[start:end]
|
||||
pose = [float(x.strip()) for x in pose_str.split(",")]
|
||||
return pose
|
||||
|
||||
def getAngel(self):
|
||||
res = self.dashboard.GetAngle()
|
||||
code = int(res[0])
|
||||
if code == 0:
|
||||
pass
|
||||
# print("success")
|
||||
else:
|
||||
print("获取关节角度失败")
|
||||
return
|
||||
# 处理字符串
|
||||
start = res.find("{")+1
|
||||
end = res.find("}")
|
||||
angle_str = res[start:end]
|
||||
angle = [float(x.strip()) for x in angle_str.split(",")]
|
||||
return angle
|
||||
|
||||
def getForwardKin(self,joints_list,user=-1,tool=-1):
|
||||
res = self.dashboard.PositiveKin(*joints_list,user,tool)
|
||||
code = int(res[0])
|
||||
if code == 0:
|
||||
pass
|
||||
# print("success")
|
||||
else:
|
||||
print("获取正向运动学解失败")
|
||||
return
|
||||
# 处理字符串
|
||||
start = res.find("{")+1
|
||||
end = res.find("}")
|
||||
pose_str = res[start:end]
|
||||
pose = [float(x.strip()) for x in pose_str.split(",")]
|
||||
return pose
|
||||
|
||||
def getInverseKin(self,poses_list,user=-1,tool=-1,useJointNear=-1,JointNear=''):
|
||||
'''
|
||||
poses_list X Y Z RX RY RZ
|
||||
useJointNear 0 或不携带 表示 JointNear无效
|
||||
1 表示根据JointNear就近选解
|
||||
jointNear string "{j1,j2,j3,j4,j5,j6}"
|
||||
'''
|
||||
res = self.dashboard.InverseKin(*poses_list,user,tool,useJointNear,JointNear)
|
||||
code = int(res[0])
|
||||
if code == 0:
|
||||
pass
|
||||
# print("success")
|
||||
else:
|
||||
print("获取逆向运动学解失败")
|
||||
return
|
||||
# 处理字符串
|
||||
start = res.find("{")+1
|
||||
end = res.find("}")
|
||||
joint_str = res[start:end]
|
||||
joint = [float(x.strip()) for x in joint_str.split(",")]
|
||||
return joint
|
||||
|
||||
def disableRobot(self):
|
||||
code = self.dashboard.DisableRobot()
|
||||
if code == 0:
|
||||
print("下使能机械臂成功")
|
||||
else:
|
||||
print("下使能机械臂失败")
|
||||
return
|
||||
|
||||
def __del__(self):
|
||||
del self.dashboard
|
||||
del self.feedFour
|
||||
|
||||
if __name__ == "__main__":
|
||||
dobot = dobot_nova5("192.168.5.1")
|
||||
dobot.start()
|
||||
posJ = [0,30,-120,0,90,0]
|
||||
sleep(1)
|
||||
dobot.RunPoint_P_inJoint(posJ)
|
||||
############### 测试 #################
|
||||
# curAngle = dobot.getAngel()
|
||||
# curPose = dobot.getPose()
|
||||
|
||||
# res1 = dobot.getForwardKin(curAngle)
|
||||
# res2 = dobot.getInverseKin(curPose)
|
||||
|
||||
# print(res1)
|
||||
# print(res2)
|
||||
# dobot.disableRobot()
|
20121
Massage/MassageControl/hardware/files/alarmController.json
Normal file
20121
Massage/MassageControl/hardware/files/alarmController.py
Normal file
2834
Massage/MassageControl/hardware/files/alarmServo.json
Normal file
2834
Massage/MassageControl/hardware/files/alarmServo.py
Normal file
0
Massage/MassageControl/hardware/force_sensor.py
Normal file
5
Massage/MassageControl/hardware/main.py
Normal file
@ -0,0 +1,5 @@
|
||||
from DobotDemo import DobotDemo
|
||||
|
||||
if __name__ == '__main__':
|
||||
dobot = DobotDemo("192.168.5.1")
|
||||
dobot.start()
|
6
Massage/MassageControl/hardware/main_UI.py
Normal file
@ -0,0 +1,6 @@
|
||||
from ui import RobotUI
|
||||
|
||||
robot_ui = RobotUI()
|
||||
|
||||
robot_ui.pack()
|
||||
robot_ui.mainloop()
|
BIN
Massage/MassageControl/hardware/picture/checkTcpMode.png
Normal file
After Width: | Height: | Size: 250 KiB |
BIN
Massage/MassageControl/hardware/picture/checkTcpMode_en.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
Massage/MassageControl/hardware/picture/exception.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
Massage/MassageControl/hardware/picture/exception_en.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
Massage/MassageControl/hardware/picture/feed.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
Massage/MassageControl/hardware/picture/feed_en.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
Massage/MassageControl/hardware/picture/main.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
Massage/MassageControl/hardware/picture/main_en.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
Massage/MassageControl/hardware/picture/move.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
Massage/MassageControl/hardware/picture/move_en.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
Massage/MassageControl/hardware/picture/netConnect.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
Massage/MassageControl/hardware/picture/netConnect_en.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
Massage/MassageControl/hardware/picture/runpy.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
Massage/MassageControl/hardware/picture/updateIP.png
Normal file
After Width: | Height: | Size: 166 KiB |
BIN
Massage/MassageControl/hardware/picture/updateIP_en.png
Normal file
After Width: | Height: | Size: 33 KiB |
0
Massage/MassageControl/hardware/remote_cam.py
Normal file
494
Massage/MassageControl/hardware/ui.py
Normal file
@ -0,0 +1,494 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from threading import Thread
|
||||
import time
|
||||
from tkinter import *
|
||||
from tkinter import ttk, messagebox
|
||||
from tkinter.scrolledtext import ScrolledText
|
||||
from dobot_api import *
|
||||
import json
|
||||
from files.alarmController import alarm_controller_list
|
||||
from files.alarmServo import alarm_servo_list
|
||||
|
||||
LABEL_JOINT = [["J1-", "J2-", "J3-", "J4-", "J5-", "J6-"],
|
||||
["J1:", "J2:", "J3:", "J4:", "J5:", "J6:"],
|
||||
["J1+", "J2+", "J3+", "J4+", "J5+", "J6+"]]
|
||||
|
||||
LABEL_COORD = [["X-", "Y-", "Z-", "Rx-", "Ry-", "Rz-"],
|
||||
["X:", "Y:", "Z:", "Rx:", "Ry:", "Rz:"],
|
||||
["X+", "Y+", "Z+", "Rx+", "Ry+", "Rz+"]]
|
||||
|
||||
LABEL_ROBOT_MODE = {
|
||||
1: "ROBOT_MODE_INIT",
|
||||
2: "ROBOT_MODE_BRAKE_OPEN",
|
||||
3: "",
|
||||
4: "ROBOT_MODE_DISABLED",
|
||||
5: "ROBOT_MODE_ENABLE",
|
||||
6: "ROBOT_MODE_BACKDRIVE",
|
||||
7: "ROBOT_MODE_RUNNING",
|
||||
8: "ROBOT_MODE_RECORDING",
|
||||
9: "ROBOT_MODE_ERROR",
|
||||
10: "ROBOT_MODE_PAUSE",
|
||||
11: "ROBOT_MODE_JOG"
|
||||
}
|
||||
|
||||
|
||||
class RobotUI(object):
|
||||
|
||||
def __init__(self):
|
||||
self.root = Tk()
|
||||
self.root.title("Python demo V4")
|
||||
# fixed window size
|
||||
self.root.geometry("900x850")
|
||||
# set window icon
|
||||
# self.root.iconbitmap("images/robot.ico")
|
||||
|
||||
# global state dict
|
||||
self.global_state = {}
|
||||
|
||||
# all button
|
||||
self.button_list = []
|
||||
|
||||
# all entry
|
||||
self.entry_dict = {}
|
||||
|
||||
# Robot Connect
|
||||
self.frame_robot = LabelFrame(self.root, text="Robot Connect",
|
||||
labelanchor="nw", bg="#FFFFFF", width=870, height=120, border=2)
|
||||
|
||||
self.label_ip = Label(self.frame_robot, text="IP Address:")
|
||||
self.label_ip.place(rely=0.2, x=10)
|
||||
ip_port = StringVar(self.root, value="8.209.98.146")
|
||||
self.entry_ip = Entry(self.frame_robot, width=12, textvariable=ip_port)
|
||||
self.entry_ip.place(rely=0.2, x=90)
|
||||
|
||||
self.label_dash = Label(self.frame_robot, text="Dashboard Port:")
|
||||
self.label_dash.place(rely=0.2, x=210)
|
||||
dash_port = IntVar(self.root, value=29999)
|
||||
self.entry_dash = Entry(
|
||||
self.frame_robot, width=7, textvariable=dash_port)
|
||||
self.entry_dash.place(rely=0.2, x=320)
|
||||
|
||||
self.label_feed = Label(self.frame_robot, text="Feedback Port:")
|
||||
self.label_feed.place(rely=0.2, x=420)
|
||||
feed_port = IntVar(self.root, value=30004)
|
||||
self.entry_feed = Entry(
|
||||
self.frame_robot, width=7, textvariable=feed_port)
|
||||
self.entry_feed.place(rely=0.2, x=520)
|
||||
|
||||
# Connect/DisConnect
|
||||
self.button_connect = self.set_button(master=self.frame_robot,
|
||||
text="Connect", rely=0.6, x=630, command=self.connect_port)
|
||||
self.button_connect["width"] = 10
|
||||
self.global_state["connect"] = False
|
||||
|
||||
# Dashboard Function
|
||||
self.frame_dashboard = LabelFrame(self.root, text="Dashboard Function",
|
||||
labelanchor="nw", bg="#FFFFFF", pady=10, width=870, height=120, border=2)
|
||||
|
||||
# Enable/Disable
|
||||
self.button_enable = self.set_button(master=self.frame_dashboard,
|
||||
text="Enable", rely=0.1, x=10, command=self.enable)
|
||||
self.button_enable["width"] = 7
|
||||
self.global_state["enable"] = False
|
||||
|
||||
self.set_button(master=self.frame_dashboard,
|
||||
text="ClearError", rely=0.1, x=200, command=self.clear_error)
|
||||
|
||||
# Speed Ratio
|
||||
self.label_speed = Label(self.frame_dashboard, text="Speed Ratio:")
|
||||
self.label_speed.place(rely=0.1, x=430)
|
||||
|
||||
s_value = StringVar(self.root, value="50")
|
||||
self.entry_speed = Entry(self.frame_dashboard,
|
||||
width=6, textvariable=s_value)
|
||||
self.entry_speed.place(rely=0.1, x=520)
|
||||
self.label_cent = Label(self.frame_dashboard, text="%")
|
||||
self.label_cent.place(rely=0.1, x=550)
|
||||
|
||||
self.set_button(master=self.frame_dashboard,
|
||||
text="Confirm", rely=0.1, x=586, command=self.confirm_speed)
|
||||
|
||||
# DO:Digital Outputs
|
||||
self.label_digitial = Label(
|
||||
self.frame_dashboard, text="Digital Outputs: Index:")
|
||||
self.label_digitial.place(rely=0.55, x=10)
|
||||
|
||||
i_value = IntVar(self.root, value="1")
|
||||
self.entry_index = Entry(
|
||||
self.frame_dashboard, width=5, textvariable=i_value)
|
||||
self.entry_index.place(rely=0.55, x=160)
|
||||
|
||||
self.label_status = Label(self.frame_dashboard, text="Status:")
|
||||
self.label_status.place(rely=0.55, x=220)
|
||||
|
||||
self.combo_status = ttk.Combobox(self.frame_dashboard, width=5)
|
||||
self.combo_status["value"] = ("On", "Off")
|
||||
self.combo_status.current(0)
|
||||
self.combo_status["state"] = "readonly"
|
||||
self.combo_status.place(rely=0.55, x=275)
|
||||
|
||||
self.set_button(self.frame_dashboard, "Confirm",
|
||||
rely=0.55, x=350, command=self.confirm_do)
|
||||
|
||||
# Move Function
|
||||
self.frame_move = LabelFrame(self.root, text="Move Function", labelanchor="nw",
|
||||
bg="#FFFFFF", width=870, pady=10, height=130, border=2)
|
||||
|
||||
self.set_move(text="X:", label_value=10,
|
||||
default_value="600", entry_value=40, rely=0.1, master=self.frame_move)
|
||||
self.set_move(text="Y:", label_value=110,
|
||||
default_value="-260", entry_value=140, rely=0.1, master=self.frame_move)
|
||||
self.set_move(text="Z:", label_value=210,
|
||||
default_value="380", entry_value=240, rely=0.1, master=self.frame_move)
|
||||
self.set_move(text="Rx:", label_value=310,
|
||||
default_value="170", entry_value=340, rely=0.1, master=self.frame_move)
|
||||
self.set_move(text="Ry:", label_value=410,
|
||||
default_value="12", entry_value=440, rely=0.1, master=self.frame_move)
|
||||
self.set_move(text="Rz:", label_value=510,
|
||||
default_value="140", entry_value=540, rely=0.1, master=self.frame_move)
|
||||
|
||||
self.set_button(master=self.frame_move, text="MovJ",
|
||||
rely=0.05, x=610, command=self.movj)
|
||||
self.set_button(master=self.frame_move, text="MovL",
|
||||
rely=0.05, x=700, command=self.movl)
|
||||
|
||||
self.set_move(text="J1:", label_value=10,
|
||||
default_value="0", entry_value=40, rely=0.5, master=self.frame_move)
|
||||
self.set_move(text="J2:", label_value=110,
|
||||
default_value="-20", entry_value=140, rely=0.5, master=self.frame_move)
|
||||
self.set_move(text="J3:", label_value=210,
|
||||
default_value="-80", entry_value=240, rely=0.5, master=self.frame_move)
|
||||
self.set_move(text="J4:", label_value=310,
|
||||
default_value="30", entry_value=340, rely=0.5, master=self.frame_move)
|
||||
self.set_move(text="J5:", label_value=410,
|
||||
default_value="90", entry_value=440, rely=0.5, master=self.frame_move)
|
||||
self.set_move(text="J6:", label_value=510,
|
||||
default_value="120", entry_value=540, rely=0.5, master=self.frame_move)
|
||||
|
||||
self.set_button(master=self.frame_move,
|
||||
text="MovJ", rely=0.45, x=610, command=self.joint_movj)
|
||||
|
||||
self.frame_feed_log = Frame(
|
||||
self.root, bg="#FFFFFF", width=870, pady=10, height=400, border=2)
|
||||
# Feedback
|
||||
self.frame_feed = LabelFrame(self.frame_feed_log, text="Feedback", labelanchor="nw",
|
||||
bg="#FFFFFF", width=550, height=150)
|
||||
|
||||
self.frame_feed.place(relx=0, rely=0, relheight=1)
|
||||
|
||||
# Current Speed Ratio
|
||||
self.set_label(self.frame_feed,
|
||||
text="Current Speed Ratio:", rely=0.05, x=10)
|
||||
self.label_feed_speed = self.set_label(
|
||||
self.frame_feed, "", rely=0.05, x=145)
|
||||
self.set_label(self.frame_feed, text="%", rely=0.05, x=175)
|
||||
|
||||
# Robot Mode
|
||||
self.set_label(self.frame_feed, text="Robot Mode:", rely=0.1, x=10)
|
||||
self.label_robot_mode = self.set_label(
|
||||
self.frame_feed, "", rely=0.1, x=95)
|
||||
|
||||
# 点动及获取坐标
|
||||
self.label_feed_dict = {}
|
||||
self.set_feed(LABEL_JOINT, 9, 52, 74, 117)
|
||||
self.set_feed(LABEL_COORD, 165, 209, 231, 272)
|
||||
|
||||
# Digitial I/O
|
||||
self.set_label(self.frame_feed, "Digital Inputs:", rely=0.8, x=11)
|
||||
self.label_di_input = self.set_label(
|
||||
self.frame_feed, "", rely=0.8, x=100)
|
||||
self.set_label(self.frame_feed, "Digital Outputs:", rely=0.85, x=10)
|
||||
self.label_di_output = self.set_label(
|
||||
self.frame_feed, "", rely=0.85, x=100)
|
||||
|
||||
# Error Info
|
||||
self.frame_err = LabelFrame(self.frame_feed, text="Error Info", labelanchor="nw",
|
||||
bg="#FFFFFF", width=180, height=50)
|
||||
self.frame_err.place(relx=0.65, rely=0, relheight=0.7)
|
||||
|
||||
self.text_err = ScrolledText(
|
||||
self.frame_err, width=170, height=50, relief="flat")
|
||||
self.text_err.place(rely=0, relx=0, relheight=0.7, relwidth=1)
|
||||
|
||||
self.set_button(self.frame_feed, "Clear", rely=0.71,
|
||||
x=487, command=self.clear_error_info)
|
||||
|
||||
# Log
|
||||
self.frame_log = LabelFrame(self.frame_feed_log, text="Log", labelanchor="nw",
|
||||
bg="#FFFFFF", width=300, height=150)
|
||||
self.frame_log.place(relx=0.65, rely=0, relheight=1)
|
||||
|
||||
self.text_log = ScrolledText(
|
||||
self.frame_log, width=270, height=140, relief="flat")
|
||||
self.text_log.place(rely=0, relx=0, relheight=1, relwidth=1)
|
||||
|
||||
# initial client
|
||||
self.client_dash = None
|
||||
self.client_feed = None
|
||||
|
||||
self.alarm_controller_dict = self.convert_dict(alarm_controller_list)
|
||||
self.alarm_servo_dict = self.convert_dict(alarm_servo_list)
|
||||
|
||||
def convert_dict(self, alarm_list):
|
||||
alarm_dict = {}
|
||||
for i in alarm_list:
|
||||
alarm_dict[i["id"]] = i
|
||||
return alarm_dict
|
||||
|
||||
def read_file(self, path):
|
||||
# 读json文件耗时大,选择维护两个变量alarm_controller_list alarm_servo_list
|
||||
# self.read_file("files/alarm_controller.json")
|
||||
with open(path, "r", encoding="utf8") as fp:
|
||||
json_data = json.load(fp)
|
||||
return json_data
|
||||
|
||||
def mainloop(self):
|
||||
self.root.mainloop()
|
||||
|
||||
def pack(self):
|
||||
self.frame_robot.pack()
|
||||
self.frame_dashboard.pack()
|
||||
self.frame_move.pack()
|
||||
self.frame_feed_log.pack()
|
||||
|
||||
def set_move(self, text, label_value, default_value, entry_value, rely, master):
|
||||
self.label = Label(master, text=text)
|
||||
self.label.place(rely=rely, x=label_value)
|
||||
value = StringVar(self.root, value=default_value)
|
||||
self.entry_temp = Entry(master, width=6, textvariable=value)
|
||||
self.entry_temp.place(rely=rely, x=entry_value)
|
||||
self.entry_dict[text] = self.entry_temp
|
||||
|
||||
def move_jog(self, text):
|
||||
if self.global_state["connect"]:
|
||||
if text[0] == "J":
|
||||
self.client_dash.MoveJog(text)
|
||||
else:
|
||||
self.client_dash.MoveJog(text,coordtype=1,user=0,tool=0)
|
||||
|
||||
def move_stop(self, event):
|
||||
if self.global_state["connect"]:
|
||||
self.client_dash.MoveJog("")
|
||||
|
||||
def set_button(self, master, text, rely, x, **kargs):
|
||||
self.button = Button(master, text=text, padx=5,
|
||||
command=kargs["command"])
|
||||
self.button.place(rely=rely, x=x)
|
||||
|
||||
if text != "Connect":
|
||||
self.button["state"] = "disable"
|
||||
self.button_list.append(self.button)
|
||||
return self.button
|
||||
|
||||
def set_button_bind(self, master, text, rely, x, **kargs):
|
||||
self.button = Button(master, text=text, padx=5)
|
||||
self.button.bind("<ButtonPress-1>",
|
||||
lambda event: self.move_jog(text=text))
|
||||
self.button.bind("<ButtonRelease-1>", self.move_stop)
|
||||
self.button.place(rely=rely, x=x)
|
||||
|
||||
if text != "Connect":
|
||||
self.button["state"] = "disable"
|
||||
self.button_list.append(self.button)
|
||||
return self.button
|
||||
|
||||
def set_label(self, master, text, rely, x):
|
||||
self.label = Label(master, text=text)
|
||||
self.label.place(rely=rely, x=x)
|
||||
return self.label
|
||||
|
||||
def connect_port(self):
|
||||
if self.global_state["connect"]:
|
||||
print("断开成功")
|
||||
self.client_dash.close()
|
||||
self.client_feed.close()
|
||||
self.client_dash = None
|
||||
self.client_feed = None
|
||||
|
||||
for i in self.button_list:
|
||||
i["state"] = "disable"
|
||||
self.button_connect["text"] = "Connect"
|
||||
else:
|
||||
try:
|
||||
print("连接成功")
|
||||
self.client_dash = DobotApiDashboard(
|
||||
self.entry_ip.get(), int(self.entry_dash.get()), self.text_log)
|
||||
self.client_feed = DobotApiFeedBack(
|
||||
self.entry_ip.get(), int(self.entry_feed.get()), self.text_log)
|
||||
except Exception as e:
|
||||
messagebox.showerror("Attention!", f"Connection Error:{e}")
|
||||
return
|
||||
|
||||
for i in self.button_list:
|
||||
i["state"] = "normal"
|
||||
self.button_connect["text"] = "Disconnect"
|
||||
self.global_state["connect"] = not self.global_state["connect"]
|
||||
self.set_feed_back()
|
||||
|
||||
def set_feed_back(self):
|
||||
if self.global_state["connect"]:
|
||||
thread = Thread(target=self.feed_back)
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
|
||||
def enable(self):
|
||||
if self.global_state["enable"]:
|
||||
self.client_dash.DisableRobot()
|
||||
self.button_enable["text"] = "Enable"
|
||||
else:
|
||||
self.client_dash.EnableRobot()
|
||||
# if need time sleep
|
||||
# time.sleep(0.5)
|
||||
self.button_enable["text"] = "Disable"
|
||||
|
||||
self.global_state["enable"] = not self.global_state["enable"]
|
||||
|
||||
def clear_error(self):
|
||||
self.client_dash.ClearError()
|
||||
|
||||
def confirm_speed(self):
|
||||
self.client_dash.SpeedFactor(int(self.entry_speed.get()))
|
||||
|
||||
def movj(self):
|
||||
self.client_dash.MovJ(float(self.entry_dict["X:"].get()), float(self.entry_dict["Y:"].get()), float(self.entry_dict["Z:"].get()),
|
||||
float(self.entry_dict["Rx:"].get()), float(self.entry_dict["Ry:"].get()), float(self.entry_dict["Rz:"].get()),0)
|
||||
|
||||
def movl(self):
|
||||
self.client_dash.MovL(float(self.entry_dict["X:"].get()), float(self.entry_dict["Y:"].get()), float(self.entry_dict["Z:"].get()),
|
||||
float(self.entry_dict["Rx:"].get()), float(self.entry_dict["Ry:"].get()), float(self.entry_dict["Rz:"].get()),0)
|
||||
|
||||
def joint_movj(self):
|
||||
self.client_dash.MovJ(float(self.entry_dict["J1:"].get()), float(self.entry_dict["J2:"].get()), float(self.entry_dict["J3:"].get()),
|
||||
float(self.entry_dict["J4:"].get()), float(self.entry_dict["J5:"].get()), float(self.entry_dict["J6:"].get()),1)
|
||||
|
||||
def confirm_do(self):
|
||||
if self.combo_status.get() == "On":
|
||||
print("高电平")
|
||||
self.client_dash.DO(int(self.entry_index.get()), 1)
|
||||
else:
|
||||
print("低电平")
|
||||
self.client_dash.DO(int(self.entry_index.get()), 0)
|
||||
|
||||
def set_feed(self, text_list, x1, x2, x3, x4):
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[0][0], rely=0.2, x=x1, command=lambda: self.move_jog(text_list[0][0]))
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[0][1], rely=0.3, x=x1, command=lambda: self.move_jog(text_list[0][1]))
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[0][2], rely=0.4, x=x1, command=lambda: self.move_jog(text_list[0][2]))
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[0][3], rely=0.5, x=x1, command=lambda: self.move_jog(text_list[0][3]))
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[0][4], rely=0.6, x=x1, command=lambda: self.move_jog(text_list[0][4]))
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[0][5], rely=0.7, x=x1, command=lambda: self.move_jog(text_list[0][5]))
|
||||
|
||||
self.set_label(self.frame_feed, text_list[1][0], rely=0.21, x=x2)
|
||||
self.set_label(self.frame_feed, text_list[1][1], rely=0.31, x=x2)
|
||||
self.set_label(self.frame_feed, text_list[1][2], rely=0.41, x=x2)
|
||||
self.set_label(self.frame_feed, text_list[1][3], rely=0.51, x=x2)
|
||||
self.set_label(self.frame_feed, text_list[1][4], rely=0.61, x=x2)
|
||||
self.set_label(self.frame_feed, text_list[1][5], rely=0.71, x=x2)
|
||||
|
||||
self.label_feed_dict[text_list[1][0]] = self.set_label(
|
||||
self.frame_feed, " ", rely=0.21, x=x3)
|
||||
self.label_feed_dict[text_list[1][1]] = self.set_label(
|
||||
self.frame_feed, " ", rely=0.31, x=x3)
|
||||
self.label_feed_dict[text_list[1][2]] = self.set_label(
|
||||
self.frame_feed, " ", rely=0.41, x=x3)
|
||||
self.label_feed_dict[text_list[1][3]] = self.set_label(
|
||||
self.frame_feed, " ", rely=0.51, x=x3)
|
||||
self.label_feed_dict[text_list[1][4]] = self.set_label(
|
||||
self.frame_feed, " ", rely=0.61, x=x3)
|
||||
self.label_feed_dict[text_list[1][5]] = self.set_label(
|
||||
self.frame_feed, " ", rely=0.71, x=x3)
|
||||
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[2][0], rely=0.2, x=x4, command=lambda: self.move_jog(text_list[2][0]))
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[2][1], rely=0.3, x=x4, command=lambda: self.move_jog(text_list[2][0]))
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[2][2], rely=0.4, x=x4, command=lambda: self.move_jog(text_list[2][0]))
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[2][3], rely=0.5, x=x4, command=lambda: self.move_jog(text_list[2][0]))
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[2][4], rely=0.6, x=x4, command=lambda: self.move_jog(text_list[2][0]))
|
||||
self.set_button_bind(
|
||||
self.frame_feed, text_list[2][5], rely=0.7, x=x4, command=lambda: self.move_jog(text_list[2][0]))
|
||||
|
||||
def feed_back(self):
|
||||
while True:
|
||||
print("self.global_state(connect)", self.global_state["connect"])
|
||||
if not self.global_state["connect"]:
|
||||
break
|
||||
|
||||
self.client_feed.socket_dobot.setblocking(True) # 设置为阻塞模式
|
||||
data = bytes()
|
||||
temp = self.client_feed.socket_dobot.recv(144000)
|
||||
if len(temp) > 1440:
|
||||
temp = self.client_feed.socket_dobot.recv(144000)
|
||||
data = temp[0:1440]
|
||||
|
||||
|
||||
a = np.frombuffer(data, dtype=MyType)
|
||||
print("robot_mode:", a["RobotMode"][0])
|
||||
print("TestValue:", hex((a['TestValue'][0])))
|
||||
if hex((a['TestValue'][0])) == '0x123456789abcdef':
|
||||
# print('tool_vector_actual',
|
||||
# np.around(a['tool_vector_actual'], decimals=4))
|
||||
# print('QActual', np.around(a['q_aQActualctual'], decimals=4))
|
||||
|
||||
# Refresh Properties
|
||||
self.label_feed_speed["text"] = a["SpeedScaling"][0]
|
||||
self.label_robot_mode["text"] = LABEL_ROBOT_MODE[a["RobotMode"][0]]
|
||||
self.label_di_input["text"] = bin(a["DigitalInputs"][0])[
|
||||
2:].rjust(64, '0')
|
||||
self.label_di_output["text"] = bin(a["DigitalOutputs"][0])[
|
||||
2:].rjust(64, '0')
|
||||
|
||||
# Refresh coordinate points
|
||||
self.set_feed_joint(LABEL_JOINT, a["QActual"])
|
||||
self.set_feed_joint(LABEL_COORD, a["ToolVectorActual"])
|
||||
|
||||
# check alarms
|
||||
if a["RobotMode"] == 9:
|
||||
self.display_error_info()
|
||||
|
||||
|
||||
def display_error_info(self):
|
||||
error_list = self.client_dash.GetErrorID().split("{")[1].split("}")[0]
|
||||
|
||||
error_list = json.loads(error_list)
|
||||
print("error_list:", error_list)
|
||||
if error_list[0]:
|
||||
for i in error_list[0]:
|
||||
self.form_error(i, self.alarm_controller_dict,
|
||||
"Controller Error")
|
||||
|
||||
for m in range(1, len(error_list)):
|
||||
if error_list[m]:
|
||||
for n in range(len(error_list[m])):
|
||||
self.form_error(n, self.alarm_servo_dict, "Servo Error")
|
||||
|
||||
def form_error(self, index, alarm_dict: dict, type_text):
|
||||
if index in alarm_dict.keys():
|
||||
date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||
error_info = f"Time Stamp:{date}\n"
|
||||
error_info = error_info + f"ID:{index}\n"
|
||||
error_info = error_info + \
|
||||
f"Type:{type_text}\nLevel:{alarm_dict[index]['level']}\n" + \
|
||||
f"Solution:{alarm_dict[index]['en']['solution']}\n"
|
||||
|
||||
self.text_err.insert(END, error_info)
|
||||
|
||||
def clear_error_info(self):
|
||||
self.text_err.delete("1.0", "end")
|
||||
|
||||
def set_feed_joint(self, label, value):
|
||||
array_value = np.around(value, decimals=4)
|
||||
self.label_feed_dict[label[1][0]]["text"] = array_value[0][0]
|
||||
self.label_feed_dict[label[1][1]]["text"] = array_value[0][1]
|
||||
self.label_feed_dict[label[1][2]]["text"] = array_value[0][2]
|
||||
self.label_feed_dict[label[1][3]]["text"] = array_value[0][3]
|
||||
self.label_feed_dict[label[1][4]]["text"] = array_value[0][4]
|
||||
self.label_feed_dict[label[1][5]]["text"] = array_value[0][5]
|