import numpy as np
import math
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib as mpl
plt.rcParams["font.family"] = ["SimHei", "PingFang SC", "WenQuanYi Micro Hei", "DejaVu Sans"]
plt.rcParams['axes.unicode_minus'] = False
mpl.rcParams['font.sans-serif'] = plt.rcParams["font.family"]
def deg2rad(deg):
return deg * math.pi / 180
def rad2deg(rad):
return rad * 180 / math.pi
def dh_transform(theta, d, a, alpha):
T = np.array([
[math.cos(theta), -math.sin(theta) * math.cos(alpha), math.sin(theta) * math.sin(alpha), a * math.cos(theta)],
[math.sin(theta), math.cos(theta) * math.cos(alpha), -math.cos(theta) * math.sin(alpha), a * math.sin(theta)],
[0, math.sin(alpha), math.cos(alpha), d],
[0, 0, 0, 1]
])
return T
def your_arm_forward_kinematics(joint_angles):
"""
参数:
joint_angles: 列表,6 个关节角(弧度)[q1, q2, q3, q4, q5, q6]
返回:
T_total: 末端总变换矩阵
joint_positions: 各关节(0-6)的坐标列表
end_rotation: 末端旋转矩阵
"""
q1, q2, q3, q4, q5, q6 = joint_angles
offset = [math.pi / 2, -math.pi / 2, 0, -math.pi / 2, 0, 0]
theta1 = q1 + offset[0]
theta2 = q2 + offset[1]
theta3 = q3 + offset[2]
theta4 = q4 + offset[3]
theta5 = q5 + offset[4]
theta6 = q6 + offset[5]
d = [540, 0, 0, 500, 345, 175]
a = [0, -900, -900, 0, 0, 0]
alpha = [math.pi / 2, 0, 0, math.pi / 2, -math.pi / 2, 0]
T1 = dh_transform(theta1, d[0], a[0], alpha[0])
T2 = dh_transform(theta2, d[1], a[1], alpha[1])
T3 = dh_transform(theta3, d[2], a[2], alpha[2])
T4 = dh_transform(theta4, d[3], a[3], alpha[3])
T5 = dh_transform(theta5, d[4], a[4], alpha[4])
T6 = dh_transform(theta6, d[5], a[5], alpha[5])
T0_0 = np.eye(4)
T0_1 = T0_0 @ T1
T0_2 = T0_1 @ T2
T0_3 = T0_2 @ T3
T0_4 = T0_3 @ T4
T0_5 = T0_4 @ T5
T0_6 = T0_5 @ T6
joint_positions = [
T0_0[:3, 3],
T0_1[:3, 3],
T0_2[:3, 3],
T0_3[:3, 3],
T0_4[:3, 3],
T0_5[:3, 3],
T0_6[:3, 3]
]
return T0_6, joint_positions, T0_6[:3, :3]
def visualize_your_arm(joint_angles, title="六轴机械臂正运动学可视化"):
T_total, joint_positions, end_rot = your_arm_forward_kinematics(joint_angles)
x = [pos[0] for pos in joint_positions]
y = [pos[1] for pos in joint_positions]
z = [pos[2] for pos in joint_positions]
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
ax.plot(x, y, z, 'b-', linewidth=3, label='机械臂连杆')
ax.scatter(x, y, z, c='r', s=100, label='关节', marker='o')
ax.scatter(x[-1], y[-1], z[-1], c='red', s=300, label='末端执行器', marker='*')
ax.set_xlabel('X 轴 (mm)', fontsize=12)
ax.set_ylabel('Y 轴 (mm)', fontsize=12)
ax.set_zlabel('Z 轴 (mm)', fontsize=12)
ax.set_title(title, fontsize=14, fontweight='bold')
ax.legend(loc='upper left', fontsize=10)
ax.set_xlim([-2000, 2000])
ax.set_ylim([-2000, 2000])
ax.set_zlim([0, 2000])
print("=" * 60)
print("机械臂末端位姿信息:")
print(f"末端位置 (x, y, z):({x[-1]:.2f}, {y[-1]:.2f}, {z[-1]:.2f}) 毫米")
print("末端旋转矩阵:")
print(np.round(end_rot, 3))
def rot2euler(rot):
sy = math.sqrt(rot[0, 0] ** 2 + rot[1, 0] ** 2)
singular = sy < 1e-6
if not singular:
roll = math.atan2(rot[2, 1], rot[2, 2])
pitch = math.atan2(-rot[2, 0], sy)
yaw = math.atan2(rot[1, 0], rot[0, 0])
else:
roll = math.atan2(-rot[1, 2], rot[1, 1])
pitch = math.atan2(-rot[2, 0], sy)
yaw = 0
return [rad2deg(roll), rad2deg(pitch), rad2deg(yaw)]
rpy = rot2euler(end_rot)
print(f"末端姿态(横滚角 Roll, 俯仰角 Pitch, 偏航角 Yaw):({rpy[0]:.2f}, {rpy[1]:.2f}, {rpy[2]:.2f}) 度")
print("=" * 60)
plt.show()
def input_joint_angles():
"""让用户选择输入模式(角度/弧度),并输入 6 个关节角,返回弧度制的关节角列表"""
print("=" * 60)
print("欢迎输入六轴机械臂的关节角!")
while True:
mode = input("请选择输入模式(1=角度,2=弧度):")
if mode in ["1", "2"]:
mode = int(mode)
break
else:
print("输入错误!请输入 1 或 2。")
joint_angles_input = []
joint_names = ["关节 1 (q1)", "关节 2 (q2)", "关节 3 (q3)", "关节 4 (q4)", "关节 5 (q5)", "关节 6 (q6)"]
for i, name in enumerate(joint_names):
while True:
try:
angle = float(input(f"请输入{name}的角度值:"))
joint_angles_input.append(angle)
break
except ValueError:
print("输入错误!请输入数字(整数/小数均可)。")
if mode == 1:
joint_angles_rad = [deg2rad(angle) for angle in joint_angles_input]
print(f"\n你输入的角度(角度制):{[round(angle, 2) for angle in joint_angles_input]}")
print(f"转换为弧度制:{[round(rad, 4) for rad in joint_angles_rad]}")
else:
joint_angles_rad = joint_angles_input
print(f"\n你输入的角度(弧度制):{[round(rad, 4) for rad in joint_angles_rad]}")
print("=" * 60)
return joint_angles_rad
if __name__ == "__main__":
joint_angles = input_joint_angles()
visualize_your_arm(joint_angles, "自定义关节角的六轴机械臂姿态")