2025-08-13 12:36:04 +08:00
|
|
|
|
import math
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def inverseF(x, y, l1, l2, l3, l4, l5):
|
|
|
|
|
|
"""
|
2025-09-15 10:45:15 +08:00
|
|
|
|
五连杆机构逆向运动学函数(优化版)
|
2025-08-13 12:36:04 +08:00
|
|
|
|
|
|
|
|
|
|
输入:
|
|
|
|
|
|
x, y: 末端执行器坐标
|
2025-09-15 10:45:15 +08:00
|
|
|
|
l1, l2: 左侧连杆长度 (O1→B, B→C)
|
|
|
|
|
|
l3, l4: 右侧连杆长度 (C→D, D→O2)
|
|
|
|
|
|
l5: 两基座距离 (O1O2)
|
2025-08-13 12:36:04 +08:00
|
|
|
|
|
|
|
|
|
|
输出:
|
2025-09-15 10:45:15 +08:00
|
|
|
|
theta1, theta2: 两个主动关节角度(弧度,从 x 轴逆时针)
|
|
|
|
|
|
|
|
|
|
|
|
注意:
|
|
|
|
|
|
- 构型为“肘部向上”(通过 2π - acos 保证)
|
|
|
|
|
|
- 若目标点不可达,抛出 ValueError
|
2025-08-13 12:36:04 +08:00
|
|
|
|
"""
|
2025-09-15 10:45:15 +08:00
|
|
|
|
Xc, Yc = x, y
|
2025-08-13 12:36:04 +08:00
|
|
|
|
|
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-08-13 12:36:04 +08:00
|
|
|
|
|
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-08-13 12:36:04 +08:00
|
|
|
|
|
2025-09-15 10:45:15 +08:00
|
|
|
|
# φ12 = ∠B (三角形 O1-B-C 的内角)
|
|
|
|
|
|
phi12 = 2 * math.pi - math.acos(cos_phi12) # 肘部向上构型
|
2025-08-13 12:36:04 +08:00
|
|
|
|
|
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-08-13 12:36:04 +08:00
|
|
|
|
|
2025-09-15 10:45:15 +08:00
|
|
|
|
# 使用向量法求 B 点
|
|
|
|
|
|
# B = C - l2 * (cos(u2), sin(u2)),但 u2 未知
|
|
|
|
|
|
# 改用:B 在以 O1 为圆心 l1 的圆 和 以 C 为圆心 l2 的圆 的交点
|
|
|
|
|
|
# 我们已有 φ12,可用三角法
|
2025-08-13 12:36:04 +08:00
|
|
|
|
|
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-08-13 12:36:04 +08:00
|
|
|
|
|
2025-09-15 10:45:15 +08:00
|
|
|
|
if abs(denominator) < 1e-12:
|
|
|
|
|
|
raise ZeroDivisionError("左侧分母接近零,机构处于奇异位形。")
|
2025-08-13 12:36:04 +08:00
|
|
|
|
|
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-08-13 12:36:04 +08:00
|
|
|
|
|
2025-09-15 10:45:15 +08:00
|
|
|
|
theta1 = math.acos(cos_theta1)
|
|
|
|
|
|
# 根据 Yc 符号判断象限(保持上凸构型)
|
|
|
|
|
|
if Yc < 0:
|
|
|
|
|
|
theta1 = 2 * math.pi - theta1 # 或根据机构限制决定
|
2025-08-13 12:36:04 +08:00
|
|
|
|
|
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-08-13 12:36:04 +08:00
|
|
|
|
|
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-08-13 12:36:04 +08:00
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------- 可选:验证解的合理性 ----------------
|
|
|
|
|
|
# 可添加工作空间边界检查、关节限位等
|
2025-08-13 12:36:04 +08:00
|
|
|
|
|
|
|
|
|
|
return theta1, theta2
|