当前位置: 首页 > news >正文

别再死记硬背公式了!用Python/Matlab动手推导牛顿-欧拉方程(附完整代码)

用Python/Matlab动手推导牛顿-欧拉方程:从理论到代码的完整实践

刚体动力学是机器人学和控制工程中的核心课题,而牛顿-欧拉方程则是描述刚体运动的黄金标准。但面对复杂的矢量运算和旋转矩阵推导,许多工程师和学生常常感到无从下手。本文将带你用Python和Matlab这两种工具,通过编写可执行代码来直观理解这些抽象概念。

1. 准备工作与环境搭建

在开始推导之前,我们需要准备好计算工具。Python的NumPy和SymPy库,以及Matlab的符号计算工具箱,将成为我们的得力助手。

对于Python用户,建议使用Jupyter Notebook进行交互式编程:

# Python环境配置 import numpy as np import sympy as sp from sympy import symbols, Matrix, diff, simplify # 初始化符号变量 t = symbols('t') # 时间变量

Matlab用户则可以直接使用Symbolic Math Toolbox:

% Matlab环境配置 syms t real % 声明时间变量为实型符号

2. 坐标系与旋转矩阵的实现

理解牛顿-欧拉方程的第一步是掌握坐标系变换。我们需要实现旋转矩阵和反对称矩阵的运算。

旋转矩阵的实现(以ZYX欧拉角为例):

# Python实现 def rotation_matrix(alpha, beta, gamma): """ZYX顺序的欧拉角旋转矩阵""" Rz = Matrix([ [sp.cos(alpha), -sp.sin(alpha), 0], [sp.sin(alpha), sp.cos(alpha), 0], [0, 0, 1] ]) Ry = Matrix([ [sp.cos(beta), 0, sp.sin(beta)], [0, 1, 0], [-sp.sin(beta), 0, sp.cos(beta)] ]) Rx = Matrix([ [1, 0, 0], [0, sp.cos(gamma), -sp.sin(gamma)], [0, sp.sin(gamma), sp.cos(gamma)] ]) return Rz * Ry * Rx

对应的Matlab实现:

% Matlab实现 function R = rotation_matrix(alpha, beta, gamma) % ZYX顺序的欧拉角旋转矩阵 Rz = [cos(alpha) -sin(alpha) 0; sin(alpha) cos(alpha) 0; 0 0 1]; Ry = [cos(beta) 0 sin(beta); 0 1 0; -sin(beta) 0 cos(beta)]; Rx = [1 0 0; 0 cos(gamma) -sin(gamma); 0 sin(gamma) cos(gamma)]; R = Rz * Ry * Rx; end

反对称矩阵的实现

# Python实现 def skew_symmetric(v): """将3D向量转换为反对称矩阵""" return Matrix([ [0, -v[2], v[1]], [v[2], 0, -v[0]], [-v[1], v[0], 0] ])
% Matlab实现 function S = skew_symmetric(v) % 将3D向量转换为反对称矩阵 S = [0 -v(3) v(2); v(3) 0 -v(1); -v(2) v(1) 0]; end

3. 线运动方程的推导与实现

基于前面的准备工作,我们现在可以开始推导线运动方程。牛顿-欧拉方程的线运动部分描述了刚体的平动动力学。

关键推导步骤

  1. 位置关系:r_A = r_B + C_BU * r_A|B
  2. 速度关系:v_A = v_B + C_BU * (v_A|B + ω_B × r_A|B)
  3. 加速度关系:a_A = a_B + C_BU * [2(ω_B × v_A|B) + ω_B × (ω_B × r_A|B) + a_A|B + α_B × r_A|B]

让我们用代码实现这些关系:

# Python实现线运动推导 # 定义符号变量 r_A, r_B, r_A_B = symbols('r_A r_B r_A_B', cls=Matrix) v_A, v_B, v_A_B = symbols('v_A v_B v_A_B', cls=Matrix) a_A, a_B, a_A_B = symbols('a_A a_B a_A_B', cls=Matrix) omega_B, alpha_B = symbols('omega_B alpha_B', cls=Matrix) # 位置关系 position_relation = r_A - (r_B + C_BU * r_A_B) # 速度关系 velocity_relation = v_A - (v_B + C_BU * (v_A_B + skew_symmetric(omega_B) * r_A_B)) # 加速度关系 coriolis = 2 * skew_symmetric(omega_B) * v_A_B centripetal = skew_symmetric(omega_B) * skew_symmetric(omega_B) * r_A_B angular_accel = skew_symmetric(alpha_B) * r_A_B acceleration_relation = a_A - (a_B + C_BU * (coriolis + centripetal + a_A_B + angular_accel))
% Matlab实现线运动推导 syms r_A r_B r_A_B [3 1] real syms v_A v_B v_A_B [3 1] real syms a_A a_B a_A_B [3 1] real syms omega_B alpha_B [3 1] real % 位置关系 position_relation = r_A - (r_B + C_BU * r_A_B); % 速度关系 velocity_relation = v_A - (v_B + C_BU * (v_A_B + skew_symmetric(omega_B) * r_A_B)); % 加速度关系 coriolis = 2 * skew_symmetric(omega_B) * v_A_B; centripetal = skew_symmetric(omega_B) * skew_symmetric(omega_B) * r_A_B; angular_accel = skew_symmetric(alpha_B) * r_A_B; acceleration_relation = a_A - (a_B + C_BU * (coriolis + centripetal + a_A_B + angular_accel));

4. 角运动方程的推导与实现

角运动方程描述了刚体的转动动力学,其推导过程与线运动类似但更为简洁。

角运动关键方程

  1. 角速度关系:ω_A = ω_B + C_BU * ω_A|B
  2. 角加速度关系:α_A = α_B + C_BU * (ω_B × ω_A|B + α_A|B)

代码实现如下:

# Python实现角运动推导 # 定义符号变量 omega_A, omega_A_B = symbols('omega_A omega_A_B', cls=Matrix) alpha_A = symbols('alpha_A', cls=Matrix) # 角速度关系 angular_velocity_relation = omega_A - (omega_B + C_BU * omega_A_B) # 角加速度关系 angular_acceleration_relation = alpha_A - (alpha_B + C_BU * (skew_symmetric(omega_B) * omega_A_B + alpha_A_B))
% Matlab实现角运动推导 syms omega_A omega_A_B [3 1] real syms alpha_A [3 1] real % 角速度关系 angular_velocity_relation = omega_A - (omega_B + C_BU * omega_A_B); % 角加速度关系 angular_acceleration_relation = alpha_A - (alpha_B + C_BU * (skew_symmetric(omega_B) * omega_A_B + alpha_A_B));

5. 完整动力学方程的组装与验证

现在我们将线运动和角运动方程组合起来,形成完整的牛顿-欧拉方程,并通过具体案例进行验证。

完整动力学方程

线运动: F = m * a_A

角运动: τ = I * α_A + ω_A × (I * ω_A)

其中I是惯性张量。我们可以用代码实现这些方程:

# Python实现完整动力学方程 m = symbols('m') # 质量 I = symbols('I', cls=Matrix) # 惯性张量 # 外力 F = symbols('F', cls=Matrix) tau = symbols('tau', cls=Matrix) # 线运动方程 linear_dynamics = F - m * a_A # 角运动方程 angular_dynamics = tau - (I * alpha_A + skew_symmetric(omega_A) * I * omega_A)
% Matlab实现完整动力学方程 syms m real % 质量 syms I [3 3] real % 惯性张量 % 外力 syms F [3 1] real syms tau [3 1] real % 线运动方程 linear_dynamics = F - m * a_A; % 角运动方程 angular_dynamics = tau - (I * alpha_A + skew_symmetric(omega_A) * I * omega_A);

验证案例:简单旋转刚体

考虑一个绕z轴旋转的刚体,我们可以通过代码验证我们的实现是否正确:

# Python验证案例 # 定义具体参数 alpha_val = t # 绕z轴旋转角度随时间线性变化 beta_val = 0 gamma_val = 0 # 计算具体旋转矩阵 C_BU = rotation_matrix(alpha_val, beta_val, gamma_val) # 计算角速度 omega_B_val = Matrix([0, 0, 1]) # 绕z轴单位角速度 # 验证旋转矩阵导数 dC_BU_dt = diff(C_BU, t) S_omega = skew_symmetric(omega_B_val) assert simplify(dC_BU_dt - C_BU * S_omega) == Matrix.zeros(3,3)
% Matlab验证案例 % 定义具体参数 alpha_val = t; % 绕z轴旋转角度随时间线性变化 beta_val = 0; gamma_val = 0; % 计算具体旋转矩阵 C_BU = rotation_matrix(alpha_val, beta_val, gamma_val); % 计算角速度 omega_B_val = [0; 0; 1]; % 绕z轴单位角速度 % 验证旋转矩阵导数 dC_BU_dt = diff(C_BU, t); S_omega = skew_symmetric(omega_B_val); assert(all(all(simplify(dC_BU_dt - C_BU * S_omega) == zeros(3))));

6. 可视化与结果分析

为了更直观地理解牛顿-欧拉方程,我们可以将结果可视化。Python中可以使用Matplotlib,Matlab则有强大的内置绘图功能。

Python可视化示例

import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 模拟刚体运动轨迹 times = np.linspace(0, 10, 100) positions = [] for time in times: # 计算随时间变化的位置 alpha_t = 0.5 * time C = rotation_matrix(alpha_t, 0, 0) r = C * Matrix([1, 0, 0]) # 初始位置(1,0,0) positions.append(np.array(r, dtype=float).flatten()) positions = np.array(positions) # 绘制轨迹 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot(positions[:,0], positions[:,1], positions[:,2]) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.title('刚体运动轨迹') plt.show()

Matlab可视化示例

% 模拟刚体运动轨迹 times = linspace(0, 10, 100); positions = zeros(3, length(times)); for i = 1:length(times) time = times(i); alpha_t = 0.5 * time; C = rotation_matrix(alpha_t, 0, 0); r = C * [1; 0; 0]; % 初始位置(1,0,0) positions(:,i) = r; end % 绘制轨迹 figure; plot3(positions(1,:), positions(2,:), positions(3,:)); xlabel('X'); ylabel('Y'); zlabel('Z'); title('刚体运动轨迹'); grid on;

7. 实际应用与扩展

掌握了牛顿-欧拉方程的基本推导和实现后,我们可以将其应用到更复杂的场景中,比如多刚体系统(如机器人手臂)的动力学建模。

多刚体系统建模的关键点

  1. 建立每个连杆的坐标系
  2. 确定相邻坐标系间的变换关系
  3. 递归计算每个连杆的速度和加速度
  4. 计算作用在每个连杆上的力和力矩
# Python实现简单的两连杆机器人动力学 # 定义连杆参数 m1, m2 = symbols('m1 m2') # 质量 l1, l2 = symbols('l1 l2') # 长度 I1, I2 = symbols('I1 I2', cls=Matrix) # 惯性张量 # 定义关节角度 theta1, theta2 = symbols('theta1 theta2', cls=Function)(t) omega1 = diff(theta1, t) alpha1 = diff(omega1, t) omega2 = diff(theta2, t) alpha2 = diff(omega2, t) # 第一连杆的运动 C01 = rotation_matrix(theta1, 0, 0) # 基座到第一连杆的旋转 r1 = C01 * Matrix([l1/2, 0, 0]) # 第一连杆质心位置 v1 = diff(r1, t) a1 = diff(v1, t) # 第二连杆的运动 C12 = rotation_matrix(theta2, 0, 0) # 第一到第二连杆的旋转 C02 = C01 * C12 r2 = C01 * Matrix([l1, 0, 0]) + C02 * Matrix([l2/2, 0, 0]) # 第二连杆质心位置 v2 = diff(r2, t) a2 = diff(v2, t) # 计算动力学方程 # 这里省略了具体的力和力矩计算,实际应用中需要完整推导
% Matlab实现简单的两连杆机器人动力学 % 定义连杆参数 syms m1 m2 real % 质量 syms l1 l2 real % 长度 syms I1 I2 [3 3] real % 惯性张量 % 定义关节角度 syms theta1(t) theta2(t) omega1 = diff(theta1, t); alpha1 = diff(omega1, t); omega2 = diff(theta2, t); alpha2 = diff(omega2, t); % 第一连杆的运动 C01 = rotation_matrix(theta1, 0, 0); % 基座到第一连杆的旋转 r1 = C01 * [l1/2; 0; 0]; % 第一连杆质心位置 v1 = diff(r1, t); a1 = diff(v1, t); % 第二连杆的运动 C12 = rotation_matrix(theta2, 0, 0); % 第一到第二连杆的旋转 C02 = C01 * C12; r2 = C01 * [l1; 0; 0] + C02 * [l2/2; 0; 0]; % 第二连杆质心位置 v2 = diff(r2, t); a2 = diff(v2, t); % 计算动力学方程 % 这里省略了具体的力和力矩计算,实际应用中需要完整推导

通过这种动手实践的方式,牛顿-欧拉方程不再是纸上抽象的数学公式,而变成了可以直观理解和验证的计算机代码。在实际机器人动力学仿真中,这种基于代码的实现方式可以直接用于控制器设计和系统仿真。

http://www.jsqmd.com/news/755142/

相关文章:

  • 避开蓝桥杯嵌入式PWM的那些坑:HAL库配置与调试经验全分享
  • Olla框架:Go语言构建模块化本地AI应用,实现RAG与私有化部署
  • RTOS实时系统设计与任务调度模式详解
  • AI模型自动化爬取工具:Python实现免费模型库高效构建
  • 过采样真能‘无中生有’提高ADC精度?一个Arduino实验带你看清真相与误区
  • 2025届毕业生推荐的十大AI写作网站推荐榜单
  • Obsidian AI副驾驶Infio-Copilot:重塑知识管理与写作的智能工作流
  • Windows服务器自动化管理利器:OpenClaw节点管理器部署与实战
  • 使用Taotoken后API调用延迟与稳定性可观测性体验分享
  • VQE算法在横向场伊辛模型中的变分电路设计与优化
  • 50kW 光储一体机 功率回路硬件设计报告(一)
  • 深入Linux VFS:UBIFS文件系统如何通过四大对象(superblock, inode, dentry, file)与内核交互?
  • 无电池LoRa电流钳技术解析与应用实践
  • 多模态图像编辑技术评估与优化实践
  • Docker部署Node.js应用时异步日志丢失怎么排查?
  • 从宿舍自动门到汽车悬挂:手把手教你用《自动控制原理》的眼光重新看世界
  • SkillThis:免费AI技能生成工具,将专家经验转化为结构化提示词
  • 从Deutsch-Jozsa到Simon:量子算法如何一步步实现指数级加速?
  • 基于LLM与向量数据库的本地化记忆增强系统架构与实践
  • MoE路由优化:平衡舍入算法提升专家模型稳定性
  • 环境配置与基础教程:全链路提效:Roboflow 平台 API 接入实战,一行代码实现数据集云端管理与本地一键下载
  • 第24篇:Vibe Coding时代:LangGraph 自动生成单元测试实战,解决项目缺测试和回归风险问题
  • 你的智能终端为什么信号稳?聊聊手机EMC测试里的性能判据(A/B/C类)
  • 别再乱搜了!C++程序员必备的离线参考手册全攻略(含CHM/Qt助手/DevHelp配置)
  • 2025届学术党必备的降重复率平台推荐
  • UCoder无监督代码生成技术解析与实践
  • 量子计算中的海森堡图像与向量化技术解析
  • 避开Cortex-M7内存配置的坑:MPU区域重叠、子区域禁用与Cache策略详解
  • 强化世界模型:提升LLM智能体复杂决策能力
  • DFloat11无损压缩技术:基于哈夫曼编码的BFloat16大模型显存优化方案