integrate.py 10.80 KiB
import tkinter as tk
from tkinter import ttk
from matplotlib.pyplot import Figure
from vpython import *
from time import time
import serial
from math import atan2, asin, cos, sin
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
from vpython import canvas
from communications import Communications
class Interface:
_serial_data = Communications()
def __init__(self):
print("start")
self.treeview = None
self.x_data = []
self.y1_data = []
self.y2_data = []
def create_popup(self):
global frame1, frame2, frame3, frame4,width,height,popup
popup = tk.Tk()
popup.title("Project")
# Set the initial size and position of the popup window
width = 1000
height = 600
screen_width = popup.winfo_screenwidth()
screen_height = popup.winfo_screenheight()
x = (screen_width // 2) - (width // 2)
y = (screen_height // 2) - (height // 2)
popup.geometry(f"{width}x{height}+{x}+{y}")
# Configure the grid to be expandable
popup.columnconfigure(0, weight=1)
popup.columnconfigure(1, weight=1)
popup.rowconfigure(0, weight=1)
popup.rowconfigure(1, weight=1)
# First row, two sections
frame1 = ttk.Frame(popup, borderwidth=1, relief="solid",width=width/3,height=height/2)
frame1.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
frame2 = ttk.Frame(popup, borderwidth=1, relief="solid",width=width*2/3,height=height/2)
frame2.grid(row=0, column=1, padx=10, pady=10, sticky="nsew")
label1 = ttk.Label(frame2, text="If IMU is connected to the laptop please click the Connect button",
wraplength=width / 2)
label1.place(relx=0.5, rely=0.9, anchor='center')
self.label2 = ttk.Label(frame2, text="Port: None ")
self.label2.place(relx=0.35, rely=0.8, anchor='center')
frame2.update_idletasks()
# Second row, two sections
frame3 = ttk.Frame(popup, borderwidth=1, relief="solid",width=width/3,height=height/2)
frame3.grid(row=1, column=0, padx=10, pady=10, sticky="nsew")
label3 = ttk.Label(frame3, text="If EMG is connected to the laptop please click the Connect button",wraplength=width/4)
label3.place(relx=0.5, rely=0.9, anchor='center')
label4 = ttk.Label(frame3, text="Port: None ")
label4.place(relx=0.35, rely=0.8, anchor='e')
frame4 = ttk.Frame(popup, borderwidth=1, relief="solid",width=width*2/3,height=height/2)
frame4.grid(row=1, column=1, padx=10, pady=10, sticky="nsew")
frame4.grid_propagate(False)
label4 = ttk.Label(frame4, text="Section 4")
label4.place(relx=0.5, rely=0.5, anchor='center')
self._initialise_real_time_classification_graph()
# Add a button to frame1 to trigger adding widgets
add_button1 = ttk.Button(frame2, text="Connect", command=self.IMU_Connect)
add_button1.place(relx=0.5, rely=0.8, anchor='center')
add_button3 = ttk.Button(frame2, text="Disconnect", command=self.IMU_disconnect)
add_button3.place(relx=0.8, rely=0.8, anchor='center')
add_button2 = ttk.Button(frame3, text="Connect", command=self.EMG_Connect)
add_button2.place(relx=0.5, rely=0.8, anchor='center')
add_button4 = ttk.Button(frame3, text="Disconnect", command=self.EMG_disconnect())
add_button4.place(relx=0.8, rely=0.8, anchor='center')
popup.mainloop()
def IMU_Connect(self):
try:
self._iMU_isConnected=True
self.arduino = serial.Serial('COM6', 115200, timeout=1)
column_limit = 9
self.label2 = ttk.Label(frame2, text="Port: COM6 ")
self.label2.place(relx=0.35, rely=0.8, anchor='center')
print("Connected to IMU")
except serial.SerialException:
print("IMU is not connected")
return
sleep(1)
scene.range = 5 # 修改场景的范围为10
scene.forward = vector(-1, -1, -1) # 保持视角不变
scene.width = 300 # 修改场景的宽度为800
scene.height = 300 # 修改场景的高度为800
scene.center = vector(0, 0, 0) # 将场景中心位置调整为 (0, 0, 0)
scene.width = 600
scene.height = 600
frontArrow = arrow(axis=vector(1, 0, 0), length=4, shaftwidth=.1, color=color.purple)
upArrow = arrow(axis=vector(0, 1, 0), length=1, shaftwidth=.1, color=color.magenta)
sideArrow = arrow(axis=vector(0, 0, 1), length=2, shaftwidth=.1, color=color.orange)
bBoard = box(length=3, width=4, height=.2, color=color.white, opacity=0.8, pos=vector(0, 0, 0))
bno = box(color=color.blue, length=1, width=.75, height=0.1, pos=vector(-0.5, 0.1 + 0.05, 0))
nano = box(length=1.75, width=.6, height=.1, pos=vector(-2, .1 + .05, 0), color=color.green)
myObj = compound([bBoard, bno, nano])
last_print_time = time()
try:
while (self._iMU_isConnected==True):
while self.arduino.inWaiting() == 0:
pass
try:
data_packet = self.arduino.readline().decode('utf-8').strip()
data = data_packet.split(',')
if len(data) == column_limit:
emg = float(data[0]) # emg sensor data
q0 = float(data[1]) # qw
q1 = float(data[2]) # qx
q2 = float(data[3]) # qy
q3 = float(data[4]) # qz
roll = atan2(2 * (q0 * q1 + q2 * q3), 1 - 2 * (q1 * q1 + q2 * q2))
pitch = -asin(2 * (q0 * q2 - q3 * q1))
yaw = -atan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2 * q2 + q3 * q3))
current_time = time()
if current_time - last_print_time >= 0.01:
print(f"EMG: {emg}, Roll: {roll}, Pitch: {pitch}, Yaw: {yaw}")
k = vector(cos(yaw) * cos(pitch), sin(pitch), sin(yaw) * cos(pitch)) # this is the x vector
y = vector(0, 1, 0) # y vector: pointing down
s = cross(k, y) # this is pointing to the side
v = cross(s, k) # the up vector
vrot = v * cos(roll) + cross(k, v) * sin(roll)
# print(k,y,s,v)
frontArrow.axis = k
sideArrow.axis = cross(k, vrot)
upArrow.axis = vrot
myObj.axis = k
myObj.up = vrot
sideArrow.length = 2
frontArrow.length = 4
upArrow.length = 1
last_print_time = current_time
else:
print("Data packet does not match column limit")
except ValueError:
print("Error in data conversion")
except UnicodeDecodeError:
print("Error in decoding data")
except KeyboardInterrupt:
self.arduino.close()
print("Disconnected from IMU")
def IMU_disconnect(self):
self._iMU_isConnected = False
if self.arduino and self.arduino.is_open:
self.arduino.close()
print("IMU disconnected")
if scene:
scene.delete()
def EMG_Connect(self):
try:
self._EMG_isConnected = True
self.label2 = ttk.Label(frame3, text="Port: COM5 ")
self.label2.place(relx=0.35, rely=0.8, anchor='e')
label_EMG_title = ttk.Label(frame3, text="Auto Calibralian",font=("Helvetica", 16))
label_EMG_title.place(relx=0.5, rely=0.1, anchor='center')
label_EMG_Gesture = ttk.Label(frame3, text="Gesture :", font=("Helvetica", 13))
label_EMG_Gesture.place(relx=0.2, rely=0.5, anchor='center')
self._serial_data.configure(port='COM5', baudrate=9600, timeout=1)
self._serial_data.connect()
self.start_data_collection()
print("Connected to EMG")
except serial.SerialException:
print("EMG is not connected")
return
def EMG_disconnect(self):
self._EMG_isConnected = False
if self._serial_data.connected==True:
self._serial_data.disconnect()
print("EMG disconnected")
def start_data_collection(self):
print("Starting EMG data collection...")
try:
while (self._EMG_isConnected==True):
emg_data=self._serial_data.read()
if emg_data is not None:
print(f"EMG Value 1: {emg_data[0]}, EMG Value 2: {emg_data[1]}")
else:
print("Failed to read EMG data")
except KeyboardInterrupt:
print("Stopping EMG data collection.")
def update_table(self, emg_data):
if self.treeview:
self.treeview.delete(*self.treeview.get_children()) # 清除现有数据
self.treeview.insert("", "end", values=("Gesture 1", f"{emg_data[0]:.2f}"))
self.treeview.insert("", "end", values=("Gesture 2", f"{emg_data[1]:.2f}"))
def _initialise_real_time_classification_graph(self):
# Create a figure and axis
fig = Figure(figsize=((width / 200), (height / 200))) # Adjusting figsize based on frame size
self.ax = fig.add_subplot(111)
self.ax.set_title("Electromyography Envelope", fontsize=14, pad=0)
self.ax.set_xlim(0, 5)
self.ax.set_ylim(0, 5)
self.ax.set_xlabel("Sample(20 samples per second)",fontsize=8,labelpad=-2)
self.ax.set_ylabel("Magnitude",labelpad=0)
self.ax.set_xticks(np.arange(0, 41, 8))
self.ax.set_yticks(np.arange(0, 1001, 200))
for x_tick in self.ax.get_xticks():
self.ax.axvline(x_tick, color='gray', linestyle='--', linewidth=0.5)
for y_tick in self.ax.get_yticks():
self.ax.axhline(y_tick, color='gray', linestyle='--', linewidth=0.5)
# Plot two lines
self.line1, = self.ax.plot([], [], color='red', label='Outer Wrist Muscle (Extensor Carpi Ulnaris)')
self.line2, = self.ax.plot([], [], color='blue', label='Inner Wrist Muscle (Flexor Carpi Radialis)')
self.ax.legend(fontsize=9, loc='upper right')
# Embed the plot in the tkinter frame
self.canvas = FigureCanvasTkAgg(fig, master=frame4)
self.canvas.draw()
self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
if __name__ == "__main__":
windows = Interface()
windows.create_popup()