保姆级教程:用Python+SymPy手把手推导二自由度机械臂正运动学(附完整代码)

张开发
2026/6/9 17:55:34 15 分钟阅读
保姆级教程:用Python+SymPy手把手推导二自由度机械臂正运动学(附完整代码)
保姆级教程用PythonSymPy手把手推导二自由度机械臂正运动学附完整代码当你第一次面对机械臂运动学时那些复杂的矩阵变换和坐标系转换可能让人望而生畏。但别担心今天我们就用Python和SymPy这个强大的符号计算库从零开始一步步推导二自由度机械臂的正运动学模型。通过这篇教程你将不仅理解背后的数学原理还能获得可以直接运行的Python代码。1. 准备工作与环境搭建在开始之前我们需要准备好Python环境和必要的库。推荐使用Python 3.8或更高版本并创建一个干净的虚拟环境python -m venv robot-env source robot-env/bin/activate # Linux/Mac # 或 robot-env\Scripts\activate # Windows安装必要的依赖库pip install sympy numpy matplotlibSymPy是我们的核心工具它能够进行符号计算自动推导和简化数学表达式。NumPy用于数值计算Matplotlib则用于可视化结果。提示如果你使用Jupyter Notebook可以安装ipykernel并将虚拟环境添加到Jupyter内核中方便交互式开发。2. 理解二自由度机械臂的基本结构我们考虑一个典型的平面二自由度旋转关节机械臂由两个连杆组成连杆1长度l₁连接基座和第一个旋转关节连杆2长度l₂连接第一个和第二个旋转关节关节变量θ₁基座到连杆1的旋转角度θ₂连杆1到连杆2的旋转角度这种结构在SCARA机器人、教学机械臂中非常常见。我们的目标是找到末端执行器相对于基坐标系的位置(x,y)和朝向。3. 使用DH参数建立运动学模型Denavit-Hartenberg(DH)参数法是机器人运动学分析的经典方法。对于我们的二自由度机械臂DH参数表如下连杆a (连杆长度)α (连杆转角)d (偏距)θ (关节角)1l₁00θ₁2l₂00θ₂在Python中我们可以这样定义这些参数from sympy import symbols, cos, sin, pi, simplify # 定义符号变量 theta1, theta2 symbols(theta1 theta2) l1, l2 symbols(l1 l2) # DH参数表 dh_params [ {a: l1, alpha: 0, d: 0, theta: theta1}, # 连杆1 {a: l2, alpha: 0, d: 0, theta: theta2} # 连杆2 ]4. 构建变换矩阵每个连杆的变换矩阵可以通过DH参数计算得到。变换矩阵A_i从坐标系{i-1}到{i}的齐次变换矩阵为from sympy import Matrix def dh_transform(a, alpha, d, theta): 根据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] ]) # 计算各连杆变换矩阵 A1 dh_transform(dh_params[0][a], dh_params[0][alpha], dh_params[0][d], dh_params[0][theta]) A2 dh_transform(dh_params[1][a], dh_params[1][alpha], dh_params[1][d], dh_params[1][theta]) # 总变换矩阵 T A1 * A25. 推导末端位置总变换矩阵T包含了从基坐标系到末端执行器的完整变换。末端执行器的位置可以从矩阵的最后一列提取# 提取位置向量 position T[:3, 3] print(末端执行器位置:) print(fx {position[0]}) print(fy {position[1]}) print(fz {position[2]})对于我们的平面二自由度机械臂z坐标应该为0因为所有运动都在xy平面内。6. 完整代码实现现在我们把所有部分组合成一个完整的Python脚本from sympy import symbols, cos, sin, pi, Matrix, simplify, pprint def compute_kinematics(): # 定义符号变量 theta1, theta2 symbols(theta1 theta2) l1, l2 symbols(l1 l2) # DH参数表 dh_params [ {a: l1, alpha: 0, d: 0, theta: theta1}, {a: l2, alpha: 0, d: 0, theta: theta2} ] # 计算变换矩阵 def dh_transform(a, alpha, d, theta): 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] ]) A1 dh_transform(dh_params[0][a], dh_params[0][alpha], dh_params[0][d], dh_params[0][theta]) A2 dh_transform(dh_params[1][a], dh_params[1][alpha], dh_params[1][d], dh_params[1][theta]) T A1 * A2 # 提取位置和姿态 position T[:3, 3] rotation T[:3, :3] print(\n末端执行器位置:) pprint(position) print(\n末端执行器旋转矩阵:) pprint(rotation) return T # 运行计算 T compute_kinematics()7. 结果验证与可视化为了验证我们的推导是否正确我们可以数学验证检查当θ₁0, θ₂0时末端位置是否在(l₁l₂, 0, 0)数值验证代入具体数值计算可视化验证绘制机械臂在不同关节角度下的位置让我们实现一个简单的可视化函数import numpy as np import matplotlib.pyplot as plt def visualize_arm(l1_val, l2_val, theta1_val, theta2_val): # 计算各关节位置 joint0 np.array([0, 0]) joint1 joint0 np.array([l1_val * np.cos(theta1_val), l1_val * np.sin(theta1_val)]) joint2 joint1 np.array([l2_val * np.cos(theta1_val theta2_val), l2_val * np.sin(theta1_val theta2_val)]) # 绘图 plt.figure(figsize(8, 6)) plt.plot([joint0[0], joint1[0]], [joint0[1], joint1[1]], b-o, linewidth3) plt.plot([joint1[0], joint2[0]], [joint1[1], joint2[1]], r-o, linewidth3) plt.xlim(-(l1_val l2_val 1), l1_val l2_val 1) plt.ylim(-(l1_val l2_val 1), l1_val l2_val 1) plt.grid(True) plt.title(f2-DOF Arm: θ1{np.degrees(theta1_val):.1f}°, θ2{np.degrees(theta2_val):.1f}°) plt.xlabel(X position) plt.ylabel(Y position) plt.show() # 示例l12, l21.5, θ145°, θ230° visualize_arm(2, 1.5, np.radians(45), np.radians(30))8. 实用技巧与常见问题在实际应用中有几个值得注意的地方坐标系约定不同库和机器人厂商可能使用不同的坐标系约定务必确认z轴和旋转方向的定义奇异位置当机械臂完全伸直或完全折叠时可能会遇到奇异位置单位一致性确保所有长度单位和角度单位一致通常米和弧度注意SymPy的符号计算虽然强大但对于复杂系统可能会变得缓慢。对于实时控制建议将符号表达式转换为数值函数from sympy import lambdify # 将符号表达式转换为数值函数 position_func lambdify((theta1, theta2, l1, l2), T[:3, 3], numpy) # 现在可以高效计算数值结果 result position_func(np.pi/4, np.pi/6, 2.0, 1.5) print(数值结果:, result)9. 扩展应用掌握了正运动学基础后你可以进一步探索逆运动学求解给定末端位置求解关节角度轨迹规划让机械臂平滑地从一点运动到另一点速度运动学研究末端执行器速度与关节速度的关系动力学分析考虑力和扭矩对运动的影响# 示例计算雅可比矩阵速度运动学 from sympy import diff x, y T[0, 3], T[1, 3] # 末端x,y位置 J Matrix([ [diff(x, theta1), diff(x, theta2)], [diff(y, theta1), diff(y, theta2)] ]) print(\n雅可比矩阵:) pprint(J)在实际项目中我发现将符号推导与数值计算结合使用效率最高——先用SymPy进行理论推导和验证再转换为数值函数用于实际控制。对于更复杂的机械臂可以考虑使用专业的机器人库如PyBullet或ROS中的MoveIt但理解这些底层原理仍然是不可或缺的。

更多文章