Files
5dof/calculate/ik.py

96 lines
3.4 KiB
Python
Raw Normal View History

import math
def inverseF(x, y, l1, l2, l3, l4, l5):
"""
2025-09-15 10:45:15 +08:00
五连杆机构逆向运动学函数优化版
输入
x, y: 末端执行器坐标
2025-09-15 10:45:15 +08:00
l1, l2: 左侧连杆长度 (O1B, BC)
l3, l4: 右侧连杆长度 (CD, DO2)
l5: 两基座距离 (O1O2)
输出
2025-09-15 10:45:15 +08:00
theta1, theta2: 两个主动关节角度弧度 x 轴逆时针
注意
- 构型为肘部向上通过 2π - acos 保证
- 若目标点不可达抛出 ValueError
"""
2025-09-15 10:45:15 +08:00
Xc, Yc = x, y
2025-09-15 10:45:15 +08:00
# ---------------- 左侧链路:求解 θ1 (O1 处电机角) ----------------
R2_left = Xc * Xc + Yc * Yc # O1 到末端距离平方
cos_phi12 = (R2_left - l1 * l1 - l2 * l2) / (2 * l1 * l2)
2025-09-15 10:45:15 +08:00
if cos_phi12 < -1 or cos_phi12 > 1:
raise ValueError(f"左侧无解cosφ12 = {cos_phi12:.4f} 超出 [-1,1]")
2025-09-15 10:45:15 +08:00
# φ12 = ∠B (三角形 O1-B-C 的内角)
phi12 = 2 * math.pi - math.acos(cos_phi12) # 肘部向上构型
2025-09-15 10:45:15 +08:00
# 计算 B 点坐标(从 C 反推)
# 向量 BC 的方向角 = atan2(Yc, Xc) + delta_angle
# 更稳定的方法:使用向量投影或直接几何
cos_phi12_val = math.cos(phi12)
sin_phi12_val = math.sin(phi12)
2025-09-15 10:45:15 +08:00
# 使用向量法求 B 点
# B = C - l2 * (cos(u2), sin(u2)),但 u2 未知
# 改用B 在以 O1 为圆心 l1 的圆 和 以 C 为圆心 l2 的圆 的交点
# 我们已有 φ12可用三角法
2025-09-15 10:45:15 +08:00
# 方法:从 O1 出发B 的方向角 foai_01
numerator = l2 * Yc * sin_phi12_val + Xc * (l2 * cos_phi12_val + l1)
denominator = (l2 * cos_phi12_val + l1) ** 2 + (l2 * sin_phi12_val) ** 2
2025-09-15 10:45:15 +08:00
if abs(denominator) < 1e-12:
raise ZeroDivisionError("左侧分母接近零,机构处于奇异位形。")
2025-09-15 10:45:15 +08:00
cos_theta1 = numerator / denominator
if cos_theta1 < -1 or cos_theta1 > 1:
raise ValueError(f"cosθ1 = {cos_theta1:.4f} 超出 [-1,1],左侧无解。")
2025-09-15 10:45:15 +08:00
theta1 = math.acos(cos_theta1)
# 根据 Yc 符号判断象限(保持上凸构型)
if Yc < 0:
theta1 = 2 * math.pi - theta1 # 或根据机构限制决定
2025-09-15 10:45:15 +08:00
# ---------------- 右侧链路:求解 θ2 (O2 处电机角) ----------------
Xc_rel = Xc - l5 # C 点相对于 O2 的 x 坐标
R2_right = Xc_rel * Xc_rel + Yc * Yc # O2 到末端距离平方
cos_phi34 = (R2_right - l3 * l3 - l4 * l4) / (2 * l3 * l4)
2025-09-15 10:45:15 +08:00
if cos_phi34 < -1 or cos_phi34 > 1:
raise ValueError(f"右侧无解cosφ34 = {cos_phi34:.4f} 超出 [-1,1]")
2025-09-15 10:45:15 +08:00
phi34 = 2 * math.pi - math.acos(cos_phi34) # 肘部向上
# 计算辅助量
A = l5 - Xc
B = l3 * math.sin(phi34)
C = l4 + l3 * math.cos(phi34)
if abs(B) < 1e-12 and abs(C) < 1e-12:
raise ValueError("右侧分母为零,机构处于奇异位形。")
sqrt_BC = math.sqrt(B * B + C * C)
try:
foai_t = math.acos(B / sqrt_BC)
inner_asin = A / sqrt_BC
if inner_asin < -1 or inner_asin > 1:
raise ValueError("asin 参数越界")
foai_40 = foai_t - math.asin(inner_asin)
except (ValueError, ZeroDivisionError) as e:
raise ValueError(f"右侧三角计算失败: {e}")
# 关键:直接输出弧度,不再转角度
# 原 C 代码中theta2 = 180 - foai_40_deg对应 u4 = pi - foai_40
theta2 = math.pi - foai_40
# ---------------- 可选:验证解的合理性 ----------------
# 可添加工作空间边界检查、关节限位等
return theta1, theta2