5

Johnathan Dummer 在网上有一个常用的 Verlet积分公式,称为 Time-Corrected Verlet。但是我读过几篇论坛帖子,人们在某些情况下会得到奇怪或意想不到的结果。

Johnathan Dummer 的公式:

x1 = x + (x – x0) * dt / dt0 + a * dt^2

还有一个stackoverflow answer,其中指出 Dummer 的时间校正公式被破坏,并且发布者将他自己的推导作为正确的推导。

通过stackoverflow答案建议的正确公式

x1 = x + (x – x0) * dt / dt0 + a * dt * (dt + dt0) / 2

那么,Dummer 的公式真的被打破了吗?如果是,海报的推导是否更好?

PS:Dummerx1 = x - x0 + a * dt^2在他的网站上使用 verlet 积分公式而不是正确的x1 = 2x - x0 + a * dt^2.

4

3 回答 3

8

维基百科页面Verlet integration - Non-constant time Differences给出了这两个公式,没有引用。我自己没有检查推导,但第二个改进公式的推理看起来很合理。

我已经下载了 Dummer 的电子表格并修改了其中一个公式以使用更正。结果要好得多。

方法比较

确切的结果是黄色的,我们看到仅仅使用帧率波动的普通 Verlet 算法是不好的。Dummer 的红色时间校正变量非常好,但有点偏离。带有改进校正的深绿色版本要好得多。

对于具有二次解的重力射弹,您可能会发现改进的版本是精确的。当度数变得更高一点时,它会与真实路径有所不同,可能值得测试一下,看看我们是否还能得到更好的近似值。

比较罪的方法

对 sin 曲线进行相同的计算表明改进的方法要好得多。在这里,时间正确的 Verlet 漂移了很多。改进的版本更好,只有一点点的确切答案。


对于PS。请注意,如果您在 TCV 公式中设置 dt=dt0

x1 = x + (x – x0) * dt / dt0 + a * dt^2

你得到

x1 = x + x – x0 + a * dt^2
   = 2 x – x0 + a * dt^2

原始的 Verlet 公式。

于 2015-09-22T07:37:46.073 回答
3

我决定不再偷懒,而是展示了原始 Verlet 方法在可变步长下的外观的某种推导。因为看起来 Dummer 的这种错误改编比我想象的更普遍,这令人难过。我还注意到,正如上面的答案所指出的,正确的版本现在与 Dummer 一起在维基百科上,尽管它是在我的“建议的正确答案”之后添加的。

当我查看 Verlet 方法时,我发现它看起来很像跳跃、速度 Verlet、隐式 Euler 等,它们看起来像修改中点的二阶版本,其中一些可能是相同的。在每一个中,在某种程度上,他们都有一个跨越式的想法,其中加速度的积分(到速度)和恒定速度的积分(到位置)各自交错,使它们重叠一半。这带来了诸如时间可逆性和稳定性之类的东西,这对于模拟的“真实性”来说比准确性更重要。而“真实感”,即可信度,对于电子游戏来说更为重要。我们不在乎某物移动到的位置是否与它的确切质量真正引起的位置略有不同,只要它的外观感觉实际的。我们并没有计算将我们的高功率卫星望远镜指向哪里来观察遥远物体的特征或未来的天体事件。在这里,稳定性和效率优先于数学准确性。因此,似乎越级方法是合适的。当您为可变时间步调整越级时,它会失去一些优势,并且会失去一些对游戏物理的吸引力。Stormer-Verlet 类似于蛙跳,除了它使用上一步的平均速度而不是单独保持的速度。您可以像蛙跳一样调整这个 Stormer-Verlet。要将前进速度与固定加速度相结合,您使用前一步长度的一半和下一步长度的一半,因为它们是交错的。如果台阶像真正的跨越式一样固定,它们的长度相同,因此两个半长之和为一。我使用 h 作为步长,使用 a/v/p 作为加速度/速度/位置,使用 hl/pl 作为上一步中的“最后一个”。这些不是真正的方程式,更像是赋值操作。

原始越级:

v = v + a*h
p = p + v*h

使用可变时间步长:

v = v + a*hl/2 + a*h/2
p = p + v*h

因素a/2

v = v + a*(hl + h)/2
p = p + v*h

使用先前位置(p - pl)/hl作为初始速度:

v = (p - pl)/hl + a*(hl + h)/2
p = p + v*h

代替,我们不需要v

p = p + ( (p - pl)/hl + a*(hl + h)/2)*h

分发h

p = p + (p - pl)*h/hl + a*h*(h + hl)/2

结果并不像 Verlet 的原始 Stormer 形式那样简单或快速,2p - pl + a*h^2. 我希望这有点道理。您将省略实际代码中的最后一步,无需乘以h两次。

于 2016-03-07T02:09:49.830 回答
3

真正的推导基于泰勒公式

x(t-h0) = x(t) - x'(t)*h0 + 0.5*x''(t)*h0^2 + O(h0^3)
x(t+h1) = x(t) + x'(t)*h1 + 0.5*x''(t)*h1^2 + O(h1^3)

现在x'(t)从这两个公式中消除得到一个类似 Verlet 的公式

h0*x(t+h1) + h1*x(t-h0) = (h0+h1)*x(t) + 0.5*a(t)*h0*h1*(h0+h1) +O(h^3)

这使得传播公式

x(t+h1) = (1+h1/h0)*x(t) - h1/h0*x(t-h0) + 0.5*a(t)*h1*(h0+h1)
        = x(t) + (x(t)-x(t-h0))*h1/h0 + 0.5*a(t)*h1*(h0+h1)

所以修正后的公式确实是正确的。


请注意,如果您使用velocity Verlet 步骤

Verlet(dt) {
    v += a * 0.5*dt
    x += v*dt
    a = acceleration(x)
    v += a * 0.5*dt
}

那么每个步骤都是独立的辛,因此步骤之间的步长变化绝对没有问题。然后

于 2016-03-12T19:30:54.840 回答