时间校正的Verlet数值积分公式

时间:2015-09-22 06:12:32

标签: math game-physics numerical-methods numerical-integration verlet-integration

Johnathan Dummer在网络上有一个常用的verlet-integration公式,名为Time-Corrected Verlet。不过,我已经阅读了几篇论坛帖子,人们在某些条件下会得到奇怪或意想不到的结果。

Formula by Johnathan Dummer:

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

还有一个stackoverflow answer,其中指出Dummer的时间校正公式已被破坏,而海报则将其自己的推导视为正确的推导。

Suggested correct formula by a stackoverflow answer

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

嗯,Dummer的公式真的坏了吗?如果是的话,海报的推导是否更好?

PS:Dummer在他的网站上使用verlet集成公式x1 = x - x0 + a * dt^2而不是正确的x1 = 2x - x0 + a * dt^2也很奇怪。

3 个答案:

答案 0 :(得分:8)

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

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

Comparison of methods

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

对于具有二次解决方案的重力射弹,您可能会发现改进后的版本是精确的。当学位变得更高时,它将与真实路径不同,可能值得测试,看看我们是否仍然得到更好的近似值。

Comparing methods for sin

对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公式。

答案 1 :(得分:3)

我决定退出懒惰,并展示了原始Verlet方法如何以可变步长看起来的某种推导。因为看起来Dummer这种错误的改编比我想象的更为普遍,这令人难过。我也注意到,正如上面的答案所指出的那样,正确的版本现在和Dummer一起出现在维基百科上,虽然它是在我的“建议的正确答案”之后添加的。

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

原始的越级:

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

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

答案 2 :(得分: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
}
然后每一步都是独立的辛,因此步骤之间步长的变化绝对没有问题。