如何用代码模拟自由落体

发表时间

当学习图形化编程(比如 Python 或者 Scratch)时,能写出模拟自然界的物理现象会很有趣,比如最常见的小球自由落体现象。为了写出逼真的小球下落轨迹,首先要了解背后的原理。

原理

我们的图形化程序是基于帧来显示动画的。每隔一段时间,屏幕内容更新一次,称为一帧。为了模拟出自由落体的动画,我们的程序需要计算出每帧小球出现的位置。

想象一下用一个照相机,在小球下落过程中,每隔一段等长的时间,对小球的位置拍个照片。经过一段时间后,这些照片上小球的位置,就是我们要计算的数值。

模型

最简单的模型,是小球从静止状态自由下落。将重力加速度记为 $g_0$ ,我们知道在任意时刻 $t$,小球的速度是 $$v(t)=g_0t=g_0nT$$

$T$ 为相邻两帧的间隔时间。上式中 $g_0$, $T$ 都为常量,我们可以合并为一个新的常量 $g_1$,这样 $v(n)$ 构成了一个离散序列:

$$ v(n)=g_1n$$或者$$ v(n)=v(n-1)+g_1 \tag{1}$$

速度 $v(n)$ 是个等差数列,随时间变化的曲线如下图中的红线:

假设第 $n$ 帧到第 $n+1$ 帧之间,小球保持 $v(n)$ 匀速,那么在两帧之间走过的路程为 $$\Delta y(n)=v(n)T=g_1nT=gn$$

第 $n$ 帧的小球位置是前 $n$ 次路程的累积:$$ y(n) = y(n-1)+ gn \tag{2}$$

这里 $g$ 是一个常量,和真正的重力加速度的数值 $9.8 m/s^2$ 已经没有关系,但是仍然起到了加速度的作用。这个值越大,小球下落的越快。位置 $y(n)$ 的级差是等差数列,随时间变化的曲线如下图中的红线:

更深入的研究,请参看 蛙跳积分法

实现

用下面的伪代码可以实现上面的 $(2)$ 式:

y=0, n=0, g=1
while(小球未落地)
    y+=(n++)*g

这就是自由落体的代码实现。

(点击动画重新播放)

反弹

如何模拟:当小球接触到地面后的反弹?我们先假设一切条件都是理想值(摩擦、刚性等等),小球将保持自身的能量不变,同时加速度方向和地面的反作用力一致。这样,小球的速度就变为竖直向上,同时数值保持不变。为了模拟反弹的状态,首先要根据上面$(1)$ $(2)$ 式改写上面的伪代码:

y=0, v=0, g=1
while(小球未落地)
    v+=g
    y+=v

这里 位置 $y$ 和速度 $v$ 是量纲不同的变量,不能直接相加,但这里这么写纯粹为了计算数值。接下来可以写小球反弹的场景:

y=0, v=0, g=1
while(true)
    if(小球触碰地面){
        v=-v
    }
    v+=g
    y+=v
效果如下图:

损耗

由于摩擦的存在和小球的形变,反弹的一瞬间,有能量的损失,所以速度从数值上会减少。假设减少的数量和速度成正比,也就是乘一个系数,记为 $f, 0<f<1$,那么上面的伪代码就变为:

y=0, v=0, g=1
while(true)
    if(小球触碰地面){
        v=-f*v
    }
    v+=g
    y+=v

效果如下图:

(点击动画重新播放)

(完)


  欢迎到 留言板 写下你的看法。
  本页面内容采用 署名协议 CC-BY 授权。欢迎转载,请保留原文链接