资讯动态

Matlab单摆数值仿真:从动力学建模到非线性振动分析

发布时间:2026/8/27 23:48:08 来源:尧图企业网站定制
1. 项目缘起从物理实验到数学建模的跨越做物理实验尤其是力学实验最头疼的莫过于理想条件难以实现。就拿单摆来说中学课本上那个简洁的公式T 2π√(L/g)背后是“小角度近似”、“无空气阻力”、“质点模型”等一系列理想化假设。在实验室里你很难找到一个完全没有摩擦的支点摆球也总有体积和空气阻力想精确验证理论周期数据总会有些偏差。这恰恰是数学建模的魅力所在——我们可以在计算机里构建一个“理想”或“可控”的物理世界把那些在现实中难以剥离的因素一个个拎出来单独研究。这次要聊的就是用Matlab对单摆运动进行数值仿真。这听起来像是个基础练习但它的价值远不止于此。对于理工科学生这是理解微分方程数值解、掌握科学计算工具Matlab的绝佳入门案例。对于参加数学建模竞赛的团队单摆模型是许多复杂振动系统如双摆、耦合摆、车辆悬挂系统的基石搞透它就等于掌握了一把打开非线性动力学大门的钥匙。即便你只是对编程和物理感兴趣通过代码“创造”并观察一个物理系统的演化过程本身就是件充满成就感的事。网络上能找到的单摆仿真代码很多但不少都停留在“画出摆动动画”的层面。我们这次要深入一步不仅要让单摆动起来还要理解背后的动力学方程是如何建立的数值积分方法比如欧拉法、龙格-库塔法是如何工作的以及如何通过仿真去探究摆长、初始角度、阻尼系数这些参数对运动的影响。我会基于一个经典的源码框架带你从头拆解并补充大量我在实际教学和项目中积累的细节与心得。你会发现一个简单的单摆能衍生出相当丰富的内容。2. 单摆的动力学从牛顿第二定律到状态方程仿真之前必须搞清楚我们到底要仿真什么。单摆的物理模型虽然简单但建立其精确的数学模型是第一步也是理解后续所有代码的基石。2.1 模型的建立与受力分析我们考虑一个最常见的单摆一根长度为L的轻质刚性杆质量忽略不计一端固定在原点O另一端连接一个质量为m的质点摆球。摆球在重力作用下在竖直平面内摆动。首先进行受力分析。摆球受到两个力重力mg竖直向下。杆的拉力T沿杆的方向指向悬挂点O。这里有一个关键的建模技巧因为杆是刚性的长度L不变所以拉力T是一个“约束力”它的作用是迫使摆球保持在以O为圆心、L为半径的圆周上运动。在动力学方程中我们有时并不直接求解T而是利用约束条件来简化问题。更常用的方法是直接对切向即运动方向列方程。设摆杆与竖直向下方向的夹角为θ弧度制并规定从竖直向下位置逆时针旋转为正方向。将重力mg分解到切向垂直于杆和法向沿杆方向切向分力F_τ -mg sin(θ)。这里的负号至关重要它表示当θ 0摆球在右侧时切向力指向θ减小的方向即向左促使摆球回到平衡位置当θ 0时亦然。这个力是恢复力的来源。法向分力F_n mg cos(θ)与杆的拉力T共同提供摆球做圆周运动所需的向心力。根据牛顿第二定律在切向的投影切向力 质量 × 切向加速度。 切向加速度等于弧长s Lθ对时间的二阶导数即a_τ L * d²θ/dt²。 因此有-mg sin(θ) m * (L * d²θ/dt²)两边同时消去质量m得到单摆的无阻尼自由振动方程d²θ/dt² (g/L) sin(θ) 0这就是我们仿真要解决的核心微分方程。它是一个二阶、非线性常微分方程。非线性项就来自于sin(θ)。2.2 线性化与“小角度近似”当摆动角度θ很小时通常认为 |θ| 0.2 rad约11.5°根据泰勒展开sin(θ) ≈ θ。此时方程简化为d²θ/dt² (g/L) θ 0这是一个标准的二阶线性齐次微分方程其解为简谐运动θ(t) θ₀ cos(ωt φ)其中角频率ω √(g/L)周期T 2π/ω 2π√(L/g)。这就是课本上那个著名的公式。注意在仿真中我们通常直接求解包含sin(θ)的完整非线性方程。线性化公式主要用于理论对比和验证帮助我们理解在什么条件下仿真结果会趋近于简谐运动。2.3 引入阻尼与激励更真实的模型为了模拟更真实的物理环境我们可以在方程中加入阻尼项和外部激励项。阻尼项通常假设阻尼力与速度成正比方向相反即-c * dθ/dt其中c是阻尼系数。阻尼力消耗系统的能量。激励项一个周期性的外力例如F cos(Ωt)模拟持续推动单摆的外界作用。加入这些因素后方程变为d²θ/dt² (c/m) dθ/dt (g/L) sin(θ) (F/(mL)) cos(Ωt)这个方程已经可以描述从自由衰减振动、受迫振动到混沌在特定参数下等一系列丰富的动力学现象。我们本次仿真的基础版本将聚焦于无阻尼自由振动 (c0, F0) 和有阻尼自由振动 (c0, F0) 两种情况。2.4 化二阶为一阶状态空间表示计算机数值积分算法如ode45通常处理一阶微分方程组。因此我们需要把二阶方程d²θ/dt² f(t, θ, dθ/dt)转化为一阶方程组。定义两个状态变量y₁ θ角位移y₂ dθ/dt角速度那么原方程d²θ/dt² -(g/L) sin(θ) - (c/m)(dθ/dt) (F/(mL)) cos(Ωt)可以拆分为dy₁/dt dθ/dt y₂ dy₂/dt d²θ/dt² -(g/L) sin(y₁) - (c/m) y₂ (F/(mL)) cos(Ωt)这样我们就得到了一个关于状态向量Y [y₁; y₂]的一阶微分方程组dY/dt F(t, Y)。这个形式可以直接喂给Matlab的ODE求解器。3. Matlab仿真实战代码逐行解析与实现理论清晰后我们进入实战环节。我将基于一个结构清晰的源码框架逐部分解释其功能并分享关键的实现细节和调试技巧。3.1 环境与参数初始化首先我们创建一个新的脚本文件比如pendulum_sim.m。良好的习惯是从定义所有物理参数和仿真参数开始。%% 单摆运动仿真 - 参数设置 clear; clc; close all; % 清空工作区、命令窗口关闭所有图形 % 物理参数 L 1.0; % 摆长 (m) g 9.81; % 重力加速度 (m/s^2) m 1.0; % 摆球质量 (kg) c 0.1; % 阻尼系数 (kg*m^2/s) —— 注意单位这里假设阻尼力矩与角速度成正比 % 若c0则为无阻尼自由振动 % 初始条件 theta0 pi/3; % 初始角位移 (rad) 60度 omega0 0; % 初始角速度 (rad/s)从静止释放 % 仿真时间设置 t_start 0; % 开始时间 (s) t_end 10; % 结束时间 (s)模拟10秒参数设置心得单位一致性这是建模中最容易出错的地方。确保所有物理量使用国际单位制SI米(m)、千克(kg)、秒(s)、弧度(rad)。g通常取 9.81。阻尼系数c它的物理意义和单位需要根据你定义的阻尼项形式来确定。在上述方程d²θ/dt² (c/m) dθ/dt ...中c的单位是kg/s。如果你定义的是-c * dθ/dt作为阻尼项c是阻尼系数那么为了量纲正确方程写作d²θ/dt² (c/(m*L^2)) dθ/dt ...更常见因为m*L^2是转动惯量。在代码中我们通常用一个等效的、量纲合适的参数。为了简单起见很多教学代码直接使用一个无量纲或经验性的小数值如0.05, 0.1来观察阻尼效果。关键是要理解c越大能量衰减越快。初始角度theta0如果你想对比线性与非线性可以设置一个较大的角度如pi/3和一个较小的角度如pi/18即10度分别运行。3.2 定义微分方程函数这是整个仿真的核心。我们需要定义一个函数用于计算状态向量Y的导数dY/dt。%% 定义单摆系统的微分方程 function dYdt pendulum_ode(t, Y, L, g, m, c) % 输入 % t: 时间 (标量)虽然方程不明显含t但ODE求解器格式要求有此参数 % Y: 状态向量 [theta; omega] % L, g, m, c: 物理参数 % 输出 % dYdt: 状态向量的导数 [d(theta)/dt; d(omega)/dt] theta Y(1); % 角位移 omega Y(2); % 角速度 % 核心动力学方程 % d(theta)/dt omega % d(omega)/dt -(g/L)*sin(theta) - (c/(m*L^2))*omega % 注意这里对阻尼项的处理更符合物理c是阻尼系数阻尼力矩与角速度成正比 % 阻尼项除以了转动惯量 m*L^2将其转化为角加速度量纲 dtheta_dt omega; domega_dt -(g/L) * sin(theta) - (c/(m*L^2)) * omega; dYdt [dtheta_dt; domega_dt]; end代码细节与陷阱函数接口pendulum_ode必须接受(t, Y, ...)作为前两个输入参数即使时间t在方程中未显式出现。这是Matlab ODE求解器如ode45要求的固定格式。阻尼项的处理代码中的阻尼项- (c/(m*L^2)) * omega是经过量纲分析的。角加速度domega/dt的单位是rad/s^2。g/L的单位是1/s^2没问题。阻尼项(c/(m*L^2)) * omega中c的单位如果是N·m·s阻尼力矩系数m*L^2是转动惯量kg·m^2omega是rad/s最终乘积单位也是1/s^2量纲正确。如果你从其他源码看到不同的形式务必检查其物理意义。使用sin(theta)这里直接使用了完整的非线性项没有做小角度近似。这是数值仿真相比解析解的优势所在。3.3 调用ODE求解器进行数值积分有了微分方程函数我们就可以使用Matlab强大的内置求解器来计算状态随时间的变化。%% 数值求解微分方程 % 将参数打包通过匿名函数传递给ODE函数 ode_fun (t, Y) pendulum_ode(t, Y, L, g, m, c); % 初始状态向量 Y0 [theta0; omega0]; % 时间向量用于输出解的时间点 tspan [t_start, t_end]; % 设置ODE求解器选项可选用于提高精度或处理刚性问题 options odeset(RelTol, 1e-9, AbsTol, 1e-9); % RelTol: 相对误差容限默认1e-3。对于长期仿真调小可减少能量漂移。 % AbsTol: 绝对误差容限默认1e-6。 % 调用ode45求解 % 语法[t, Y] ode45(ode_fun, tspan, Y0, options) [t, Y] ode45(ode_fun, tspan, Y0, options); % 提取结果 theta_sim Y(:, 1); % 第一列是角位移theta omega_sim Y(:, 2); % 第二列是角速度omega求解器选择与配置心得为什么用ode45ode45是Matlab中最常用的非刚性non-stiff常微分方程求解器它采用4-5阶龙格-库塔法在精度和效率之间取得了很好的平衡。对于单摆这种通常非刚性的问题它是首选。tspan的两种用法tspan可以是一个二元向量[t0, tf]这时求解器会自己选择内部时间步长进行积分并在这些步长点输出解。你也可以指定一个时间点向量如tspan 0:0.01:10求解器会在这些精确的时间点输出解。前者计算效率高后者输出结果时间间隔均匀便于绘图和后续处理。我们这里用了前者。误差容限RelTol和AbsTol这是控制求解精度的关键参数。对于保守系统无阻尼单摆理论上总机械能应守恒。但由于数值误差能量会缓慢漂移增加或减少。将RelTol和AbsTol设置得更严格如1e-9可以显著减小这种能量漂移但会以增加计算时间为代价。对于教学演示默认值通常足够对于需要精确验证能量守恒的研究则需要调高精度。结果提取ode45的输出Y是一个N×2的矩阵N是时间点的数量。Y(:,1)是所有时间点的θ值Y(:,2)是所有时间点的ω值。t是对应的N×1时间向量。3.4 结果可视化从数据到洞察仿真结果是一堆数字可视化是理解它们的关键。我们将绘制时间序列图、相图相轨迹和能量图。%% 结果可视化 % 1. 角位移和角速度随时间的变化 figure(Position, [100, 100, 1200, 400]) % 设置图形窗口位置和大小 subplot(1, 3, 1) plot(t, theta_sim, b-, LineWidth, 1.5) hold on % 可选绘制小角度近似下的解析解进行对比 if theta0 0.2 % 只有小角度时解析解才准确 omega_n sqrt(g/L); % 固有角频率 theta_linear theta0 * cos(omega_n * t); plot(t, theta_linear, r--, LineWidth, 1.0) legend(非线性仿真, 线性解析解, Location, best) end xlabel(时间 t (s)) ylabel(角位移 \theta (rad)) title(角位移-时间曲线) grid on hold off subplot(1, 3, 2) plot(t, omega_sim, r-, LineWidth, 1.5) xlabel(时间 t (s)) ylabel(角速度 \omega (rad/s)) title(角速度-时间曲线) grid on % 2. 相图 (Phase Portrait)角速度 vs 角位移 subplot(1, 3, 3) plot(theta_sim, omega_sim, k-, LineWidth, 1.0) xlabel(角位移 \theta (rad)) ylabel(角速度 \omega (rad/s)) title(相轨迹) axis equal grid on可视化技巧与解读时间序列图直接观察θ(t)和ω(t)的振荡。对于无阻尼情况它们应是等幅的正余弦波。有阻尼时振幅会指数衰减。对比非线性仿真和线性解析解红线虚线可以直观看到在大角度下非线性系统的周期变长波形也不再是完美的余弦波。相图这是分析动力学系统的强大工具。横轴是位移θ纵轴是速度ω。系统在任一时刻的状态对应相平面上的一个点随时间变化这个点画出的轨迹就是相轨迹。无阻尼保守系统相轨迹是一族闭合的椭圆曲线对于线性系统或更复杂的闭合曲线对于非线性系统。每条闭合曲线对应一个特定的总能量。曲线内部是系统可能的状态空间。有阻尼系统相轨迹是从初始点出发螺旋向内最终趋于原点(0,0)平衡点的曲线。这直观地表示了系统能量耗散、最终静止的过程。axis equal命令确保了横纵轴比例尺相同这样圆看起来才是圆的椭圆才是椭圆的不会失真。能量计算与绘图进阶为了定量验证仿真精度可以计算并绘制总机械能随时间的变化。% 计算动能、势能和总机械能 % 动能: KE 0.5 * m * (L * omega)^2 KE 0.5 * m * (L * omega_sim).^2; % 势能: 取摆球最低点为零势能点PE m*g*L*(1 - cos(theta)) PE m * g * L * (1 - cos(theta_sim)); Total_E KE PE; figure plot(t, KE, b-, t, PE, r-, t, Total_E, k--, LineWidth, 1.5) xlabel(时间 t (s)) ylabel(能量 (J)) legend(动能 KE, 势能 PE, 总机械能 E_{total}, Location, best) title(系统能量随时间变化) grid on对于无阻尼 (c0) 仿真理想情况下Total_E应是一条水平直线。由于数值误差它可能会有微小的波动或漂移。观察总能量的变化幅度是检验求解器精度和参数设置是否合理的一个很好方法。3.5 制作摆动动画静态图表之外一个直观的动画能极大增强理解。下面是一个简单的动画制作代码。%% 制作单摆摆动动画 figure axis_limit L * 1.2; axis([-axis_limit, axis_limit, -axis_limit, axis_limit]); axis equal grid on hold on xlabel(x (m)) ylabel(y (m)) title(单摆运动仿真动画) % 绘制固定点 plot(0, 0, ko, MarkerSize, 10, MarkerFaceColor, k) % 初始化摆杆和摆球的图形对象 pendulum_line line([0, 0], [0, 0], Color, b, LineWidth, 2); pendulum_ball plot(0, 0, ro, MarkerSize, 20, MarkerFaceColor, r); % 设置动画速度每帧间隔时间 animation_speed 0.01; % 秒 % 动画循环 for i 1:length(t) % 计算摆球当前位置 x_ball L * sin(theta_sim(i)); y_ball -L * cos(theta_sim(i)); % 注意y轴向上为正所以最低点y坐标为负 % 更新摆杆和摆球的位置 set(pendulum_line, XData, [0, x_ball], YData, [0, y_ball]); set(pendulum_ball, XData, x_ball, YData, y_ball); % 刷新图形并暂停 drawnow pause(animation_speed) % 可选在动画窗口上实时显示时间和角度 % title(sprintf(单摆运动仿真动画 (t%.2f s, \\theta%.2f rad), t(i), theta_sim(i))); end hold off动画制作避坑指南坐标变换物理模型中角度θ是从竖直向下开始逆时针为正。在笛卡尔坐标系中摆球坐标应为(x, y) (L*sinθ, -L*cosθ)。这样当θ0时球在(0, -L)即最低点。y坐标前的负号是因为Matlab图形窗口的y轴是向上的。drawnow与pauseset函数只更新图形对象的数据drawnow强制Matlab立即重绘图形。pause(animation_speed)控制动画帧率。如果仿真时间步长很密t向量点数很多可以设置pause(0.01)或更小来加速或者每隔几步i i10更新一次动画以提高流畅度。性能优化如果仿真时间很长逐帧绘制动画会非常慢。一个技巧是预先计算好所有位置然后在循环中只更新图形对象避免在循环内进行复杂计算。上面的代码已经做到了这一点。保存动画可以使用getframe捕获每一帧然后用VideoWriter对象保存为视频文件如AVI或MP4方便演示和分享。4. 参数研究与现象探究超越基础仿真一个完整的仿真项目不应止步于“让它动起来”。利用我们搭建好的框架可以轻松地改变参数探究不同的物理现象。这才是数学建模的核心——通过“可控实验”理解系统行为。4.1 阻尼系数c的影响设置不同的阻尼系数c观察系统从欠阻尼到过阻尼的过渡。%% 研究阻尼系数的影响 c_values [0, 0.5, 2, 5]; % 尝试不同的阻尼系数 L 1; g 9.81; m 1; theta0 pi/4; omega0 0; tspan [0, 15]; figure hold on colors lines(length(c_values)); % 获取一组区分度高的颜色 for i 1:length(c_values) c c_values(i); ode_fun (t, Y) pendulum_ode(t, Y, L, g, m, c); [t, Y] ode45(ode_fun, tspan, [theta0; omega0]); theta Y(:, 1); plot(t, theta, -, Color, colors(i, :), LineWidth, 1.5, ... DisplayName, sprintf(c %.1f, c)) end xlabel(时间 t (s)) ylabel(角位移 \theta (rad)) title(不同阻尼系数下的角位移响应) legend(show, Location, best) grid on hold off你会观察到c0无阻尼等幅振荡。c0.5欠阻尼振幅逐渐衰减的振荡。c2可能接近临界阻尼以最快速度无振荡地回到平衡位置。c5过阻尼缓慢地、无振荡地回到平衡位置。通过观察相图你能更清晰地看到轨迹从闭合曲线无阻尼到螺旋收敛欠阻尼再到直接滑向原点过阻尼/临界阻尼的变化。4.2 初始角度theta0对周期的影响非线性效应验证单摆周期与振幅初始角度的关系这是线性理论 (T2π√(L/g)) 所无法描述的。%% 研究初始角度对周期的影响非线性效应 L 1; g 9.81; m 1; c 0; % 无阻尼 theta0_values [pi/18, pi/6, pi/3, pi/2]; % 10°, 30°, 60°, 90° t_end 20; periods zeros(size(theta0_values)); % 存储估算的周期 figure hold on for i 1:length(theta0_values) theta0 theta0_values(i); ode_fun (t, Y) pendulum_ode(t, Y, L, g, m, c); [t, Y] ode45(ode_fun, [0, t_end], [theta0; 0]); theta Y(:, 1); plot(t, theta, DisplayName, sprintf(\\theta_0 %.0f°, rad2deg(theta0))) % 简单估算周期寻找过零点从正到负或负到正 % 注意这种方法对于非简谐波可能不准更稳健的方法是找峰值或使用FFT inds find(diff(sign(theta)) ~ 0); % 符号变化的索引 if length(inds) 2 % 计算前两个过零点的时间差再乘以2得到周期半个周期 periods(i) 2 * (t(inds(2)) - t(inds(1))); end end xlabel(时间 t (s)) ylabel(角位移 \theta (rad)) title(不同初始角度下的摆动无阻尼) legend(show, Location, best) grid on hold off % 显示估算周期与线性理论周期的对比 T_linear 2*pi*sqrt(L/g); fprintf(摆长 L%.2fm线性理论周期 T_linear %.4f s\n, L, T_linear); fprintf(初始角度(°) | 仿真估算周期(s) | 与线性周期的比值\n); fprintf(-------------------------------------------------\n); for i 1:length(theta0_values) fprintf(%10.0f | %16.4f | %18.4f\n, ... rad2deg(theta0_values(i)), periods(i), periods(i)/T_linear); end运行这段代码你会发现随着初始角度增大仿真估算的周期确实变长了。对于θ010°比值接近1对于θ090°比值可能达到1.18左右。这与理论分析周期椭圆积分解是一致的直观地展示了非线性效应。4.3 受迫振动与共振现象进阶为微分方程添加一个周期性的驱动力项可以模拟受迫振动。当驱动频率接近系统的固有频率时会发生共振振幅急剧增大在有阻尼的情况下振幅会稳定在一个较大的值。修改pendulum_ode函数增加驱动力参数F和Omegafunction dYdt pendulum_ode_forced(t, Y, L, g, m, c, F, Omega) theta Y(1); omega Y(2); dtheta_dt omega; % 方程 d²θ/dt² (c/(m*L^2)) dθ/dt (g/L) sinθ (F/(m*L)) cos(Omega*t) domega_dt -(g/L)*sin(theta) - (c/(m*L^2))*omega (F/(m*L))*cos(Omega*t); dYdt [dtheta_dt; domega_dt]; end然后设置一个较小的阻尼c改变驱动频率Omega进行扫描观察稳态振幅的变化就能绘制出经典的共振曲线。5. 常见问题、调试技巧与扩展思路即使代码逻辑正确在实际运行中也可能遇到各种问题。这里分享一些我踩过的坑和解决方法。5.1 能量不守恒与数值漂移在无阻尼仿真中总机械能应该恒定。但你可能发现Total_E曲线有缓慢上升或下降的趋势。原因ode45等变步长求解器通过控制局部截断误差来保证精度但全局误差如能量误差可能会累积。此外默认的误差容限 (RelTol1e-3,AbsTol1e-6) 对于长期仿真来说可能不够严格。解决方案收紧误差容限如之前所示设置options odeset(RelTol, 1e-9, AbsTol, 1e-9)。这会显著提高计算精度减少能量漂移但会增加计算时间。使用专为保守系统设计的求解器对于哈密顿系统如无阻尼单摆有辛积分算法Symplectic Integrators如Verlet方法能在长时间仿真中更好地保持能量守恒。Matlab中可能需要自己实现或寻找工具箱。物理理解对于课堂演示或一般性研究微小的能量漂移是可以接受的。关注现象而非绝对的数值守恒。5.2 仿真“爆炸”数值不稳定如果参数设置不当例如阻尼为负、时间步长太大在自定义欧拉法中解可能会发散角度变得巨大。原因数值算法不稳定或方程本身在参数域内有不稳定平衡点如倒立摆。解决方案检查物理参数质量、长度、阻尼是否为正数。如果使用自己编写的固定步长积分如欧拉法尝试大幅减小步长。使用Matlab内置的ode45它具备自动步长调整和稳定性检测通常更可靠。对于倒立摆这类不稳定系统需要更精细的初始条件和求解器设置。5.3 动画卡顿或不流畅原因仿真时间点太多逐帧绘制间隔太短pause时间不足以完成图形渲染。解决方案降采样显示在动画循环中每隔k步更新一次图形例如for i 1:10:length(t)。调整pause时间pause(0.01)通常比较流畅。可以设为0以最快速度运行但可能看不清。pause(0.05)会慢一些。预计算图形数据确保动画循环内只进行图形更新 (set和drawnow)所有复杂的计算如坐标转换都在循环之前完成。5.4 扩展思路从这里出发这个单摆仿真框架是一个强大的起点你可以基于它探索更多双摆Double Pendulum两个单摆连接是经典的混沌系统示例。状态变量变为4个[θ1, ω1, θ2, ω2]动力学方程更复杂但建模和求解思路完全一致。弹簧摆Spring Pendulum摆长L不再是常数而是一个弹簧的伸长量。系统有两个自由度角度和伸长量方程更复杂能模拟有趣的耦合振动。与Simulink结合在Simulink中用框图方式搭建单摆模型直观地进行控制设计如让摆杆稳定在倒立位置。参数辨识假设你有一段真实单摆的摆动角度时间数据能否用仿真模型反推出系统的阻尼系数c这引出了模型拟合和优化问题。加入控制力设计一个控制器如PID让单摆能从任意初始位置快速稳定到竖直向下位置或者跟踪一个指定的角度轨迹。从一行行代码中看到物理定律被精确复现通过调整参数探索不同的现象这种“数字实验”的体验是理论学习无法替代的。希望这个详细的拆解能帮你不仅运行起一段代码更能理解其背后的每一处设计考量并激发你用它去探索更广阔的动力学世界。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价