Files
5dof/calculate/calculate_angle.py

179 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# qt_main.py
import numpy as np
import matplotlib.pyplot as plt
from ik import inverseF # 假设这是你自己的逆运动学函数
from matplotlib.animation import FuncAnimation
# 设置中文字体和解决负号显示问题
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
# 1. 轨迹生成函数:每个轨迹类型独立封装,支持外部传参
# --------------------------------------------------
def generate_circle(center=(100, 300), radius=40):
from trajectory import circle_trajectory
return circle_trajectory(center=center, radius=radius)
def generate_line(start=(125, 300), end=(125, 400)):
from trajectory import line_trajectory
return line_trajectory(start=start, end=end)
def generate_ellipse(center=(100, 200), rx=50, ry=25):
from trajectory import ellipse_trajectory
return ellipse_trajectory(center=center, rx=rx, ry=ry)
def generate_square(side=60, start_point=(100, 200)):
from trajectory import square_trajectory
return square_trajectory(side=side, start_point=start_point)
def generate_triangle(base_length=100, height=80, base_center=(100, 200)):
from trajectory import triangle_trajectory
return triangle_trajectory(base_length=base_length, height=height, base_center=base_center)
# 4. 主函数:根据轨迹类型调用对应函数并执行
# --------------------------------------------------
def main_of_5dof(trajectory_type='line', show_animation=True, save_angle_a='angle_A.txt',
save_angle_b='angle_B.txt', **kwargs):
"""
主函数:生成轨迹、计算逆解,并将 theta1 和 theta4 分别保存为两个 txt 文件,逗号分隔
参数:
- trajectory_type: 轨迹类型 ('circle', 'line', 'ellipse', 'square', 'triangle')
- show_animation: 是否显示动画
- save_angle_a: 保存 theta1A角的文件名设为 None 不保存
- save_angle_b: 保存 theta4B角的文件名设为 None 不保存
- **kwargs: 传递给轨迹生成函数的参数
"""
# 生成轨迹
if trajectory_type == 'circle':
x_list, y_list = generate_circle(
center=kwargs.get('center', (100, 300)),
radius=kwargs.get('radius', 40)
)
elif trajectory_type == 'line':
x_list, y_list = generate_line(
start=kwargs.get('start', (125, 300)),
end=kwargs.get('end', (125, 400))
)
elif trajectory_type == 'ellipse':
x_list, y_list = generate_ellipse(
center=kwargs.get('center', (100, 200)),
rx=kwargs.get('rx', 50),
ry=kwargs.get('ry', 25)
)
elif trajectory_type == 'square':
x_list, y_list = generate_square(
side=kwargs.get('side', 60),
start_point=kwargs.get('start_point', (100, 200))
)
elif trajectory_type == 'triangle':
x_list, y_list = generate_triangle(
base_length=kwargs.get('base_length', 100),
height=kwargs.get('height', 80),
base_center=kwargs.get('base_center', (100, 200))
)
else:
raise ValueError(f"不支持的轨迹类型: {trajectory_type}")
# 存储角度值的列表
angle_A_list = [] # theta1 (弧度或角度)
angle_B_list = [] # theta4 (弧度或角度)
# 计算每个点的逆运动学并存储角度(以角度制保存)
for i in range(len(x_list)):
x = x_list[i]
y = y_list[i]
try:
theta1, theta4 = inverseF(x, y, L1, L2, L3, L4, L0)
angle_A_list.append(theta1)
angle_B_list.append(theta4)
print(f"{i} 个点: A角 = {theta1:.2f}°, B角 = {theta4:.2f}°")
except Exception as e:
print(f"{i} 点逆解失败: {e}")
# 可选择插入 NaN 或上一个有效值
angle_A_list.append(np.nan)
angle_B_list.append(np.nan)
# ==================== 保存为两个独立的 txt 文件 ====================
if save_angle_a:
with open(save_angle_a, 'w') as f:
# 将所有 A 角度转为字符串保留2位小数用逗号连接
formatted = ",".join([f"{angle:.2f}" for angle in angle_A_list])
f.write(formatted)
print(f"\n✅ A角度theta1已保存至: {save_angle_a}")
if save_angle_b:
with open(save_angle_b, 'w') as f:
formatted = ",".join([f"{angle:.2f}" for angle in angle_B_list])
f.write(formatted)
print(f"✅ B角度theta4已保存至: {save_angle_b}")
# ==================== 可选:显示动画 ====================
if show_animation:
fig, ax = plt.subplots()
ax.set_xlim(-300, 500)
ax.set_ylim(0, 500)
ax.set_aspect('equal')
ax.grid(True)
ax.set_title("五连杆末端沿轨迹运动")
ax.plot(x_list, y_list, 'b--', label='理想轨迹')
line, = ax.plot([], [], 'r-o', linewidth=2, markersize=6, label='五连杆结构')
def draw_frame(i):
x = x_list[i]
y = y_list[i]
try:
theta1, theta4 = inverseF(x, y, L1, L2, L3, L4, L0)
except Exception as e:
print(f"{i} 帧: 计算失败 -> {e}")
theta1 = theta4 = None
if theta1 is None or theta4 is None:
line.set_data([], [])
return line,
# 计算连杆坐标
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]
line.set_data(x_coords, y_coords)
return line,
ani = FuncAnimation(fig, draw_frame, frames=len(x_list), interval=50, blit=True)
plt.legend()
plt.show()
# 📌 运行主函数
if __name__ == "__main__":
main_of_5dof(trajectory_type='line',start=(125, 300), end=(125, 400), show_animation=False)
#main_of_5dof(
# trajectory_type='circle',
# center=(150, 250),
# radius=60,
# show_animation=False # 设置为 False 则不显示动画
#)
# 示例:其他轨迹使用方式
# main_of_5dof(trajectory_type='line', start=(0, 0), end=(200, 300), show_animation=False)
# main_of_5dof(trajectory_type='ellipse', center=(100, 200), rx=80, ry=40)
# main_of_5dof(trajectory_type='square', side=100, start_point=(100, 200))
# main_of_5dof(trajectory_type='triangle', base_length=120, height=100, base_center=(100, 200))