硬币减速旋转的代码无法正常工作

Code for decelerating rotation of a coin not working properly

我正在尝试模拟硬币的旋转。一个完整的旋转被建模为一个参数从 1 到 -1 回到 1 的变化,1 是直硬币,-1 是硬币倒置。硬币应该逐渐减速。该函数的参数是硬币在停止前要转半圈的次数、运动应该进行的帧数以及硬币旋转的初始速度(每帧转半圈)。

首先我用公式2*(displacement - initial_v*time) / time*time计算减速度的值。然后我创建一个列表,其中包含每帧的距离值。这里出了点问题,因为价值真的很高。 (我省略了将位置值限制在 1 和 -1 之间的代码部分,因为在到达该点之前出现了问题)。

def animate_rotation(n_half_turns, n_frames, speed):
    """
    First I calculate the appropriate deceleration given distance d, initial velocity t_0, and time t
    Then I find the position value per frame by calculating the distance given the found acceleration
    """

    displacement = n_half_turns   # every half turn is a movement from 1 to -1, i.e. 2 units
    v = speed                   # this is the initial speed, i.e. n of half turns per frame
    time = n_frames
    position = 1

    deceleration = 2 * (displacement - v * time) / time*time

    #distance traveled from initial position for each frame
    frame_distance = []
    for i in range(n_frames):
        position += v
        frame_distance.append(position)
        v += deceleration

    #the rest of the code transforms the values so that they are between 1 and -1. I eliminated this part because things go wrong before it.

animate_rotation(1, 10, 1)

我希望 new_dist 列表从某个速度开始以 n_frames 帧数(new_dist 列表的长度)达到 n_half_turns 值并适当减速。然而,当 运行 代码时我得到的更像是一个寓言:首先位置增加,然后超过 n_half_turns,然后返回到它。 new_dist 列表是:

[1, 1.8200000000000003, 2.4600000000000004, 2.9200000000000004, 3.2, 3.3000000000000007, 3.2200000000000006, 2.960000000000001, 2.520000000000001, 1.9000000000000012]

可能是部分答案(可能还有其他问题)但至少这个公式是错误的:

2 * (displacement - v * time) / time*time

因为除法优先于乘法,所以等价于

2 * (displacement - v * time)

当你希望它成为:

2 * (displacement - v * time) / (time*time)

快速演示:

>>> 1/4*4
1.0
>>> 1/(4*4)
0.0625

另外,在你的循环中,更多的是物理方面的东西:

for i in range(n_frames):
    position += position * v
    frame_distance.append(position)
    v += v * deceleration

没有意义。如果我理解正确的话,每次迭代都是经过的时间。因此,您只需 加上 速度即可将速度应用于位置,而不是速度与位置的乘积,这就解释了为什么您的位置会飙升。

速度变化也是如此。我的提议:

for i in range(n_frames):
    position += v
    frame_distance.append(position)
    v += deceleration

通过所有这些修复,我得到了一组好看的值,不确定它们是否正常,但看起来更好:

[1.0, 1.0984, 1.1952, 1.2904, 1.384, 1.476, 1.5664, 1.6552, 1.7424, 1.8279999999999998, 1.912, 1.9943999999999997, 2.0751999999999997, 2.1544, 2.2319999999999998, 2.308, 2.3823999999999996, 2.4551999999999996, 2.5263999999999993, 2.595999999999999, 2.6639999999999993, 2.730399999999999, 2.795199999999999, 2.8583999999999987, 2.9199999999999986, 2.9799999999999986, 3.0383999999999984, 3.0951999999999984, 3.1503999999999985, 3.2039999999999984, 3.2559999999999985, 3.3063999999999982, 3.355199999999998, 3.4023999999999983, 3.447999999999998, 3.491999999999998, 3.534399999999998, 3.575199999999998, 3.614399999999998, 3.651999999999998, 3.687999999999998, 3.7223999999999977, 3.7551999999999977, 3.7863999999999978, 3.8159999999999976, 3.8439999999999976, 3.8703999999999974, 3.8951999999999973, 3.918399999999997, 3.9399999999999973, 3.959999999999997, 3.9783999999999966, 3.9951999999999965, 4.010399999999997, 4.023999999999997, 4.035999999999996, 4.046399999999997, 4.055199999999996, 4.062399999999997, 4.067999999999996, 4.071999999999996, 4.074399999999995, 4.075199999999995, 4.074399999999995, 4.071999999999996, 4.067999999999996, 4.062399999999995, 4.055199999999996, 4.046399999999995, 4.035999999999996, 4.023999999999996, 4.010399999999995, 3.9951999999999948, 3.978399999999995, 3.959999999999995, 3.9399999999999946, 3.9183999999999943, 3.8951999999999942, 3.8703999999999943, 3.843999999999994, 3.815999999999994, 3.786399999999994, 3.755199999999994, 3.722399999999994, 3.687999999999994, 3.651999999999994, 3.614399999999994, 3.575199999999994, 3.534399999999994, 3.4919999999999938, 3.4479999999999937, 3.402399999999994, 3.3551999999999937, 3.306399999999994, 3.2559999999999936, 3.2039999999999935, 3.1503999999999936, 3.0951999999999935, 3.0383999999999936, 2.9799999999999933]