2. 三连杆机械臂逆运动学几何法

任务目标

本案例使用几何法求解三连杆平面机械臂的逆运动学问题:已知末端执行器的目标位置 \((x, y)\) 及末端姿态角 \(\phi\),求解三个关节角 \(\theta_1, \theta_2, \theta_3\)。三连杆长度分别为 \(L_1, L_2, L_3\),所有关节均为旋转关节,运动平面为二维平面。

几何法原理与多解处理

将三连杆机械臂的末端位置分解为两部分:前三连杆中前两杆决定腕部位置,第三杆决定末端姿态。设腕部位置为 \((x_w, y_w)\),则有:

\(x_w = x - L_3 \cos\phi,\quad y_w = y - L_3 \sin\phi\)

此时问题退化为两连杆机械臂的逆运动学(求 \(\theta_1, \theta_2\)),再加上 \(\theta_3 = \phi - (\theta_1 + \theta_2)\)。两连杆部分存在两种典型构型:肘上(elbow-up)和肘下(elbow-down),对应 \(\theta_2\) 的正负两种取值,由此产生多解。此外,当腕部位置超出可达范围时无解,恰好位于边界时仅有一解。

完整实现代码

import numpy as np

def inverse_kinematics_3link(x, y, phi, L1, L2, L3, elbow='up'):
    """
    几何法求解三连杆平面机械臂逆运动学。
    参数:
        x, y   : 末端目标位置
        phi    : 末端姿态角(弧度)
        L1,L2,L3: 三杆长度
        elbow  : 'up' 或 'down',指定肘部构型
    返回:
        (theta1, theta2, theta3) 或 None(无解)
    """
    # 1. 计算腕部位置
    xw = x - L3 * np.cos(phi)
    yw = y - L3 * np.sin(phi)

    # 2. 腕部可达性检查
    r = np.hypot(xw, yw)
    if r > L1 + L2 or r < abs(L1 - L2):
        return None  # 不可达

    # 3. 两连杆逆解(余弦定理)
    cos_theta2 = (xw**2 + yw**2 - L1**2 - L2**2) / (2 * L1 * L2)
    cos_theta2 = np.clip(cos_theta2, -1.0, 1.0)  # 数值保护

    if elbow == 'up':
        theta2 = np.arccos(cos_theta2)          # 肘上:theta2 为正
    else:
        theta2 = -np.arccos(cos_theta2)         # 肘下:theta2 为负

    # 4. 求 theta1(atan2 自动处理象限)
    alpha = np.arctan2(yw, xw)
    beta = np.arctan2(L2 * np.sin(theta2), L1 + L2 * np.cos(theta2))
    theta1 = alpha - beta

    # 5. 求 theta3
    theta3 = phi - theta1 - theta2

    return (theta1, theta2, theta3)

# ===== 最小验证示例 =====
if __name__ == "__main__":
    L1, L2, L3 = 3.0, 2.0, 1.0

    # 测试1:肘上构型
    sol_up = inverse_kinematics_3link(4.0, 2.0, 0.5, L1, L2, L3, 'up')
    print("肘上解:", sol_up)

    # 测试2:肘下构型(同一目标,不同构型)
    sol_down = inverse_kinematics_3link(4.0, 2.0, 0.5, L1, L2, L3, 'down')
    print("肘下解:", sol_down)

    # 测试3:不可达位置
    sol_invalid = inverse_kinematics_3link(10.0, 10.0, 0.0, L1, L2, L3, 'up')
    print("不可达位置:", sol_invalid)

    # 验证:正解回代(确认解的正确性)
    def forward_kinematics(theta1, theta2, theta3):
        x = L1*np.cos(theta1) + L2*np.cos(theta1+theta2) + L3*np.cos(theta1+theta2+theta3)
        y = L1*np.sin(theta1) + L2*np.sin(theta1+theta2) + L3*np.sin(theta1+theta2+theta3)
        phi = theta1 + theta2 + theta3
        return x, y, phi

    if sol_up:
        xf, yf, pf = forward_kinematics(*sol_up)
        print(f"肘上回代误差: x={xf-4.0:.2e}, y={yf-2.0:.2e}, phi={pf-0.5:.2e}")
    if sol_down:
        xf, yf, pf = forward_kinematics(*sol_down)
        print(f"肘下回代误差: x={xf-4.0:.2e}, y={yf-2.0:.2e}, phi={pf-0.5:.2e}")

运行与验证方法

运行方式:将代码保存为 ik_3link.py,在装有 NumPy 的 Python 环境中执行 python ik_3link.py。

验证路径:

  1. 多解验证:同一目标位置 \((4.0, 2.0)\) 和姿态 \(0.5\text{ rad}\),肘上与肘下应输出两组不同的关节角,且两组角度均满足正解回代误差接近 \(10^{-15}\) 量级(浮点精度内)。
  2. 无解验证:目标 \((10.0, 10.0)\) 超出最大可达距离 \(L_1+L_2+L_3=6.0\),函数应返回 None。
  3. 姿态一致性:回代时 \(\theta_1+\theta_2+\theta_3\) 应等于目标 \(\phi\),误差在浮点精度内。

通过条件:肘上与肘下解均能通过正解回代验证(误差 < \(10^{-10}\)),且不可达位置正确返回 None。

三连杆机械臂两种构型示意 X Y O 肘上 θ₂ > 0 肘下 θ₂ < 0 T(x,y,φ) 图例 肘上 L1 肘下 L1

常见问题:当目标位置恰好位于工作空间边界(\(r = L_1+L_2\) 或 \(r = |L_1-L_2|\))时,肘上与肘下解重合,此时两种构型返回相同结果,属正常现象。数值计算中若 \(\cos\theta_2\) 因浮点误差略超出 \([-1,1]\),代码中已用 np.clip 处理。