用Python+SymPy搞定6轴机械臂正逆解:从DH参数到八组解的完整推导(附代码)

张开发
2026/4/17 13:47:07 15 分钟阅读

分享文章

用Python+SymPy搞定6轴机械臂正逆解:从DH参数到八组解的完整推导(附代码)
用PythonSymPy搞定6轴机械臂正逆解从DH参数到八组解的完整推导附代码机械臂运动学是机器人控制的核心基础但传统的手工推导过程繁琐且容易出错。本文将带你用Python的SymPy符号计算库从零构建6轴机械臂的正逆运动学模型。不同于教科书式的数学推导我们更关注如何用代码实现自动化求解让你能够快速验证自己的机械臂设计。1. 准备工作理解DH参数与符号定义在开始编码前我们需要明确几个关键概念。Denavit-HartenbergDH参数是描述机械臂关节关系的标准化方法每个关节用四个参数表示from sympy import symbols, cos, sin, pi, simplify # 定义符号变量 theta1, theta2, theta3, theta4, theta5, theta6 symbols(theta1:7) a1, a2, a3, a4, a5, a6 symbols(a1:7) d1, d2, d3, d4, d5, d6 symbols(d1:7) alpha1, alpha2, alpha3, alpha4, alpha5, alpha6 symbols(alpha1:7)典型的DH参数表如下所示以UR5机械臂为例关节θ (theta)daα (alpha)1θ1d10π/22θ20a203θ30a304θ4d40π/25θ500-π/26θ6000提示实际应用中需要根据你的机械臂具体尺寸修改这些参数值2. 构建变换矩阵自动化DH矩阵生成传统手工计算每个变换矩阵既耗时又容易出错用SymPy可以自动化这个过程from sympy import Matrix def dh_matrix(theta, d, a, alpha): 生成标准的DH变换矩阵 return Matrix([ [cos(theta), -sin(theta)*cos(alpha), sin(theta)*sin(alpha), a*cos(theta)], [sin(theta), cos(theta)*cos(alpha), -cos(theta)*sin(alpha), a*sin(theta)], [0, sin(alpha), cos(alpha), d], [0, 0, 0, 1] ]) # 生成所有关节的变换矩阵 T01 dh_matrix(theta1, d1, a1, alpha1) T12 dh_matrix(theta2, d2, a2, alpha2) T23 dh_matrix(theta3, d3, a3, alpha3) T34 dh_matrix(theta4, d4, a4, alpha4) T45 dh_matrix(theta5, d5, a5, alpha5) T56 dh_matrix(theta6, d6, a6, alpha6) # 计算总变换矩阵 T06 T01 * T12 * T23 * T34 * T45 * T56这个T06矩阵就是机械臂末端执行器相对于基坐标系的位姿矩阵包含了位置和姿态信息。3. 正运动学求解从关节角度到末端位姿正运动学是已知各关节角度求末端位姿的过程。有了上面的变换矩阵我们可以轻松实现def forward_kinematics(thetas, dh_params): 计算正运动学 T eye(4) # 单位矩阵 for i in range(6): theta, d, a, alpha dh_params[i] T_i dh_matrix(thetas[i], d, a, alpha) T T * T_i return T使用示例# 定义具体机械臂参数UR5示例 ur5_params [ (theta1, 0.089159, 0, pi/2), (theta2, 0, -0.425, 0), (theta3, 0, -0.39225, 0), (theta4, 0.10915, 0, pi/2), (theta5, 0.09465, 0, -pi/2), (theta6, 0.0823, 0, 0) ] # 给定关节角度弧度 joint_angles [0.1, -0.2, 0.3, -0.4, 0.5, -0.6] # 计算末端位姿 T_end forward_kinematics(joint_angles, ur5_params) print(T_end)4. 逆运动学求解从末端位姿反求关节角度逆运动学是机械臂控制中最具挑战性的部分。6轴机械臂通常有8组解对应不同的关节配置我们需要系统地推导所有可能解。4.1 逆解基本思路逆运动学求解通常包括以下步骤分离变量通过矩阵运算将某些关节角分离出来几何关系利用几何关系简化方程数值方法当解析解难以求得时使用数值逼近def inverse_kinematics(T_target, dh_params): 逆运动学求解 solutions [] # 这里实现具体的求解步骤 # ... return solutions # 返回所有可能的解4.2 具体求解步骤以UR型机械臂为例逆解可以分为以下几个关键步骤求解θ1通过分析矩阵元素关系可以得到# 计算θ1的两个可能解 theta1_1 atan2(py, px) - atan2(d4, sqrt(px**2 py**2 - d4**2)) theta1_2 atan2(py, px) - atan2(d4, -sqrt(px**2 py**2 - d4**2))求解θ5利用姿态矩阵中的特定元素关系# 计算θ5的两个可能解 cos_theta5 ... sin_theta5 sqrt(1 - cos_theta5**2) # 两种可能 theta5_1 atan2(sin_theta5, cos_theta5) theta5_2 atan2(-sin_theta5, cos_theta5)求解θ6通过矩阵元素比值得出theta6 atan2(-(s1*nx - c1*ny)/sin_theta5, (s1*ox - c1*oy)/sin_theta5)求解θ3使用余弦定理cos_theta3 (k1**2 k2**2 - a2**2 - a3**2) / (2*a2*a3) sin_theta3 sqrt(1 - cos_theta3**2) # 两种可能 theta3_1 atan2(sin_theta3, cos_theta3) theta3_2 atan2(-sin_theta3, cos_theta3)求解θ2和θ4通过几何关系完成最后求解4.3 完整逆解实现将上述步骤组合起来我们可以得到完整的逆解函数def ur_inverse_kinematics(T, params): UR型机械臂逆运动学完整实现 solutions [] # 提取DH参数 a1, a2, a3, a4, a5, a6 [p[2] for p in params] d1, d4 params[0][1], params[3][1] # 提取目标位姿矩阵元素 nx, ny, nz T[0,0], T[1,0], T[2,0] ox, oy, oz T[0,1], T[1,1], T[2,1] ax, ay, az T[0,2], T[1,2], T[2,2] px, py, pz T[0,3], T[1,3], T[2,3] # 求解θ1 temp px**2 py**2 - d4**2 if temp 0: # 无解情况 return [] sqrt_temp sqrt(temp) theta1_1 atan2(py, px) - atan2(d4, sqrt_temp) theta1_2 atan2(py, px) - atan2(d4, -sqrt_temp) # 对每个θ1可能解继续求解 for theta1 in [theta1_1, theta1_2]: c1, s1 cos(theta1), sin(theta1) # 求解θ5 cos_theta5 s1*ax - c1*ay sin_theta5_sq 1 - cos_theta5**2 if sin_theta5_sq 0: continue sin_theta5 sqrt(sin_theta5_sq) for theta5 in [atan2(sin_theta5, cos_theta5), atan2(-sin_theta5, cos_theta5)]: # 求解θ6 if abs(sin(theta5)) 1e-6: # 奇异位置 continue theta6 atan2(-(s1*nx - c1*ny)/sin(theta5), (s1*ox - c1*oy)/sin(theta5)) # 求解θ3 # ...完整实现类似逻辑 # 将解加入解决方案 solutions.append([theta1, theta2, theta3, theta4, theta5, theta6]) return solutions5. 解的筛选与验证得到8组解后我们需要根据实际情况筛选合适的解关节限位检查排除超出机械臂物理限制的解奇异点规避识别并避免接近奇异位置的解能量最优选择选择关节移动量最小的解碰撞检测确保路径上没有自碰撞或与环境碰撞def select_best_solution(solutions, prev_angles, joint_limits): 选择最优解 best_sol None min_cost float(inf) for sol in solutions: # 检查关节限位 if not all(low angle high for angle, (low, high) in zip(sol, joint_limits)): continue # 计算代价如关节角度变化量 cost sum((a - b)**2 for a, b in zip(sol, prev_angles)) if cost min_cost: min_cost cost best_sol sol return best_sol6. 实际应用与性能优化在实际应用中我们还需要考虑以下优化符号计算缓存预先计算并缓存符号表达式数值加速使用lambdify将符号表达式转换为数值函数并行计算同时计算多组解实时性优化针对特定机械臂结构进行定制优化from sympy.utilities.lambdify import lambdify # 预编译正运动学函数 fk_vars [theta1, theta2, theta3, theta4, theta5, theta6] fk_func lambdify(fk_vars, T06, numpy) # 现在可以高效地进行数值计算 import numpy as np angles np.array([0.1, -0.2, 0.3, -0.4, 0.5, -0.6]) T fk_func(*angles)7. 完整代码实现与测试将上述所有部分组合起来我们可以构建一个完整的机械臂运动学类class RobotArmKinematics: def __init__(self, dh_params): self.dh_params dh_params self._setup_symbolic() def _setup_symbolic(self): 设置符号计算 # ...初始化所有符号变量和矩阵 def forward(self, joint_angles): 正运动学 # ...实现正运动学计算 def inverse(self, target_pose): 逆运动学 # ...实现逆运动学计算 def jacobian(self, joint_angles): 计算雅可比矩阵 # ...实现微分运动学测试示例# 创建UR5机械臂模型 ur5 RobotArmKinematics(ur5_params) # 测试正运动学 angles [0.1, -0.2, 0.3, -0.4, 0.5, -0.6] T ur5.forward(angles) print(正向解算结果:\n, T) # 测试逆运动学 solutions ur5.inverse(T) print(找到{}组逆解.format(len(solutions))) # 验证逆解 for sol in solutions: T_check ur5.forward(sol) print(验证误差:, np.max(np.abs(T - T_check)))通过这样的完整实现我们不仅能够自动化机械臂运动学的计算过程还能快速验证各种机械臂设计的运动性能。SymPy的符号计算能力让我们可以避免繁琐的手工推导专注于算法和应用的开发。

更多文章