主要内容
对重力和摩擦力建模
现在, 让我们改进上一个例子的重力并引入摩擦力, 努力将我们的力变得更真实一点。
地球上的重力
你可能已经注意到关于上一个例子的一些非常不准确的地方。圆圈越小,下降的速度就越快。这是有逻辑的;毕竟我们只是 (根据牛顿第二定律) 设定质量越小, 加速度就越高。
但这并不是现实世界中会发生的事情。如果你爬上比萨斜塔的顶端,同时释放两个不同质量的球, 哪一个会先落地?根据传说, 伽利略在1589年进行了这一测试, 发现它们以同样的加速度坠落, 同时击中地面。
为什么会这样呢?我们课程在后面将会讲到:重力是相对于物体的质量来计算的。物体越大, 力就越大。因此, 如果力与质量成正比,当力除以质量时,质量就会被抵消。我们可以通过将质量乘以我们假设的重力加速度而在我们的程序中实现这一点:
for (var i = 0; i < movers.length; i++) {
gravity.set(0, 0.1 * movers[i].mass);
movers[i].applyForce(gravity);
…
}
虽然物体现在以同样的速度下降, 但由于风力的强度与质量无关, 较小的物体仍然更快地向右加速。
这些假设的力实际上对我们很有帮助。ProcessingJS 是一个虚假的像素世界,而且你就是世界的主人。所以不管你认为怎样的力是合适的,好吧,这些力就会这样出现在程序中。尽管如此,你可能有的时候会想:“但这一切实际应该是怎样运作的”?
打开高中物理教科书, 你会发现一些图表和公式描述了许多不同的力——重力,电磁力,摩擦力,张力,弹力,等等。嘿,或者你可以打开可汗学院的物理课程。在本章节中,我们将研究其中的两种力——摩擦和重力。我们所想要说明的不是摩擦和重力是你所有 ProcessingJS 程序中所必须的基础力。相反, 我们希望将这两种力量作为以下问题的案例来研究:
- 理解力背后的概念
- 将力的公式分解为两部分:
- 我们如何计算力的方向?
- 我们如何计算力的大小?
- 将该公式转换为 ProcessingJS 代码, 该代码计算要传递给
Mover
对象的applyForce()
函数的PVector
参数。
如果你可以按照上面的步骤分析这两个力,那么希望当你发现你未来某个时候在凌晨三点需要百度 “弱相对作用” 的时候,你可以理解你它并将其融合到你的 ProcessingJS 代码中。
利用公式
好的,马上我们要写出摩擦力的公式。这已经不是我们第一次在这个课程中看到公式了。我们刚刚完成了对牛顿第二定律的讨论, (或者力 = 质量 * 加速度)。我们没有花很多时间处理这个公式,因为它非常简单明了。尽管如此, 外面的世界很可怕。我们在导言中提到的“正态分布”的方程只要看看就行了:
我们可以看到,公式都喜欢使用很多符号 (很多时候是希腊字母)。现在让我们来看看摩擦力的公式。
如果距离你上一次看数学或者物理公式已经有一段时间了,有三个关键点需要注意一下。
- 处理右侧,赋值给左侧 就像代码一样!我们在这里要做的是计算方程的右侧,并将其赋值给左侧。在上面的例子中,我们想要计算摩擦力——方程左侧告诉我们要计算的是什么,方程右侧告诉我们如何计算。
- 我们在计算一个向量还是一个标量? 你需要意识到有些时候我们计算的是矢量。,而有些时候是标量。举个例子,在这里我们所要计算的摩擦力是矢量。我们可以通过 “friction” 上面的箭头知道这一点。它有方向和大小。方程右侧也是一个矢量,正如
所示,在这里它代表速度向量。 - 当符号被放在一起时,他们代表相乘 上面的公式实际上由四个元素组成:
-1
, , ,和 。我们想要它们相乘,并把它们写为
摩擦力
让我们按照我们的步骤分析摩擦力。
摩擦力是一个 耗散力 。耗散力是指当物体运动时,系统的总能量会减少的力。假设你在开车,当你踩下刹车踏板的时候,汽车的刹车系统会使用摩擦力来减缓轮胎的运动。动能 (运动) 转化为热能 (热)。每当两个表面接触且具有相对运动趋势时, 它们就会产生摩擦力。一个完整的摩擦力模型将包括静摩擦力 (物体相对表面静止) 和滑动摩擦力 (一个物体在运动中的表面) , 但为了我们的目的, 我们只考虑滑动摩擦力。
下面是摩擦的公式,以及一个例子:
现在要由我们把这个公式分成两个部分来确定摩擦力的方向和大小。基于上图, 我们可以看到在 摩擦力指向与物体相对运动方向相反 。事实上, 这就是公式的一个部分, 它说 ,也就是 -1 倍的速度单位矢量。在 ProcessingJS 中, 这意味着获取速度矢量, 将其归一化, 并乘以-1。
var friction = velocity.get();
friction.normalize();
// 让我们找出摩擦力的方向
// (与速度方向相反的单位矢量)
friction.mult(-1);
请注意此处的另外两个步骤。首先, 复制速度矢量很重要,因为我们不想意外地逆转物体的速度方向。其次,我们归一化向量。这是因为摩擦力的大小与它移动的速度无关,我们希望从大小为一的摩擦矢量开始,这样就可以很容易地缩放它。
根据公式, 其大小为 。在这里, 希腊字母 mu (发音为 "miu") 用来描述摩擦系数。摩擦系数确定特定表面的摩擦力的强度。系数越高, 摩擦就越强;系数越低,摩擦越弱。例如, 一块冰的摩擦系数会比砂纸要低得多。由于我们处于一个虚假的 ProcessingJS 世界中, 我们可以根据要模拟的摩擦量任意设置系数。
var c = 0.01;
设想一辆汽车沿着一条路行驶。车辆有重力施加于道路,牛顿第三定律告诉我们, 道路也需要施加重力的反作用力。这就是正压力。对于物体水平移动的简单情况, 正压力等于质量乘以重力加速度, 。 这意味着轻型跑车相比于大型拖车将施加较小的正压力,也将经历更少的摩擦。
在上面的雪橇图中,人物沿着有一定的角度表面移动,因此计算正压力要复杂一些,因为它不指向与重力相反的方向。为此,我们需要了解一些关于角度和三角学的知识。
目前我们的目标将是让我们的 ProcessingJS 程序进行 "足够好" 的模拟,而不是一个完美的模拟。 例如,我们可以假设摩擦力产生在正压力大小永远只有单位一的条件下。这样我们的
n
将简化为:var normal = 1;
当我们在下一节学习三角学知识的时候,我们会重新回顾一下这些细节,并使用一些更复杂的摩擦力案例。
现在我们既有摩擦力的大小,也有摩擦力的方向, 我们可以把这一切放在一起.....
var c = 0.01;
var normal = 1;
var frictionMag = c * normal;
var friction = movers[i].velocity.get();
friction.mult(-1);
friction.normalize();
friction.mult(frictionMag);
……并将其添加到我们的 “力” 例子中,也就是物体经历重力,风力,并且现在接受摩擦力的那一个:
如果你观察程序运行一段时间,你就会发现那些圆圈运动的越来越慢,并且倾向于在一个区域附近移动。因为摩擦力不停的将物体向其运动方向的反方向推,这些物体就会越来越慢。这即可以是一个很有用的技巧也可能是一个问题,取决于你想要的效果是怎么样的。
“自然模拟”系列课程是由 Daniel Shiffman 的 "编程的本质" 衍生而来,基于 知识共享 著名-非商用性 3.0 本地化许可协议。