146 lines
4.6 KiB
Python
146 lines
4.6 KiB
Python
import sys
|
|
import numpy as np
|
|
import matplotlib
|
|
|
|
matplotlib.use('Qt5Agg') # 必须在导入 pyplot 前设置
|
|
|
|
from PyQt5.QtWidgets import QApplication, QDialog, QVBoxLayout
|
|
from PyQt5.QtGui import QStandardItemModel, QStandardItem # ✅ 正确的模块
|
|
from calculate.trajectory import circle_trajectory, line_trajectory
|
|
from calculate.ik import inverseF
|
|
from matplotlib.figure import Figure
|
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
|
from matplotlib.animation import FuncAnimation
|
|
|
|
# 导入你生成的界面
|
|
from untitled import Ui_Dialog
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
# 设置中文字体和解决负号显示问题
|
|
plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Zen Hei', 'FangSong'] # 按优先级选择字体
|
|
plt.rcParams['axes.unicode_minus'] = False # 显示负号 -
|
|
|
|
# 杆长参数
|
|
L1 = 250
|
|
L2 = 300
|
|
L3 = 300
|
|
L4 = 250
|
|
L0 = 250
|
|
|
|
|
|
class MyDialog(QDialog, Ui_Dialog):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setupUi(self)
|
|
|
|
# ****** 新增:为 listView 初始化模型 ******
|
|
self.angle_model = QStandardItemModel(self.listView)
|
|
self.listView.setModel(self.angle_model)
|
|
|
|
# 创建 matplotlib 图形
|
|
self.figure = Figure(figsize=(8, 6), dpi=100)
|
|
self.ax = self.figure.add_subplot(111)
|
|
self.ax.set_xlim(-300, 500)
|
|
self.ax.set_ylim(0, 500)
|
|
self.ax.set_aspect('equal')
|
|
self.ax.grid(True)
|
|
self.ax.set_title("五连杆沿轨迹运动")
|
|
|
|
# 创建画布
|
|
self.canvas = FigureCanvas(self.figure)
|
|
self.widget.setLayout(QVBoxLayout())
|
|
self.widget.layout().addWidget(self.canvas)
|
|
|
|
# 添加 line 对象
|
|
self.line, = self.ax.plot([], [], 'r-o', linewidth=2, markersize=6)
|
|
# 初始化轨迹数据
|
|
self.x_list = []
|
|
self.y_list = []
|
|
self.ani = None # 动画对象
|
|
|
|
# 连接按钮
|
|
self.pushButton.clicked.connect(self.start_line_trajectory)
|
|
self.pushButton_2.clicked.connect(self.start_circle_trajectory)
|
|
|
|
def start_line_trajectory(self):
|
|
# 清除旧的角度数据显示
|
|
self.angle_model.clear()
|
|
|
|
self.ax.set_title("五连杆 - 直线轨迹运动")
|
|
x, y = line_trajectory(start=(125, 300), end=(125, 400))
|
|
self.start_animation(x, y)
|
|
|
|
def start_circle_trajectory(self):
|
|
# 清除旧的角度数据显示
|
|
self.angle_model.clear()
|
|
|
|
self.ax.set_title("五连杆 - 圆形轨迹运动")
|
|
x, y = circle_trajectory(center=(100, 200), radius=40)
|
|
self.start_animation(x, y)
|
|
|
|
def start_animation(self, x_list, y_list):
|
|
self.x_list = x_list
|
|
self.y_list = y_list
|
|
|
|
# 安全停止旧动画
|
|
try:
|
|
if self.ani is not None and self.ani.event_source is not None:
|
|
self.ani.event_source.stop()
|
|
except:
|
|
pass # 忽略停止过程中的任何异常
|
|
|
|
|
|
# 动画函数
|
|
def draw_frame(i):
|
|
x = x_list[i]
|
|
y = y_list[i]
|
|
try:
|
|
theta1, theta4 = inverseF(x, y, L1, L2, L3, L4, L0)
|
|
|
|
# ****** 新增:将弧度转换为角度并显示 ******
|
|
theta1_deg = np.degrees(theta1)
|
|
theta4_deg = np.degrees(theta4)
|
|
angle_text = f"点 {i}: θ1={theta1_deg:.1f}°, θ4={theta4_deg:.1f}°"
|
|
|
|
# 限制 listView 只显示最近 10 条
|
|
if self.angle_model.rowCount() >= 10:
|
|
self.angle_model.removeRow(0)
|
|
# 创建新项并添加
|
|
item = QStandardItem(angle_text)
|
|
self.angle_model.appendRow(item)
|
|
|
|
# 左侧电机臂末端
|
|
x2 = L1 * np.cos(theta1)
|
|
y2 = L1 * np.sin(theta1)
|
|
|
|
# 右侧电机臂末端
|
|
x4 = L4 * np.cos(theta4) + L0
|
|
y4 = L4 * np.sin(theta4)
|
|
|
|
# 构建点序列
|
|
x_coords = [0, x2, x, x4, L0]
|
|
y_coords = [0, y2, y, y4, 0]
|
|
|
|
self.line.set_data(x_coords, y_coords)
|
|
except Exception as e:
|
|
print(f"第 {i} 帧错误: {e}")
|
|
return self.line,
|
|
|
|
# 创建新动画
|
|
self.ani = FuncAnimation(
|
|
self.figure,
|
|
draw_frame,
|
|
frames=len(x_list),
|
|
interval=100,
|
|
repeat=False ,
|
|
blit=False # PyQt 中 blit=True 有时有问题,先设 False
|
|
)
|
|
self.canvas.draw()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app = QApplication(sys.argv)
|
|
dialog = MyDialog()
|
|
dialog.show()
|
|
sys.exit(app.exec_()) |