NSV,Euler Integration Confusion

时间:2011-06-22 20:19:40

标签: math language-agnostic physics game-physics

我正试图了解这些整合方法,但我一直很困惑。

以下是代码:

public void update_euler(float timeDelta){
    vPos.y += vVelocity.y * timeDelta; 
    vVelocity.y += gravity.y * timeDelta;
}


public void update_nsv(float timeDelta){    
    vVelocity.y += gravity.y*timeDelta;
    vPos.y += vVelocity.y * timeDelta; 
}


public void onDrawFrame(GL10 gl) {      
    currentTime = System.currentTimeMillis();
    float timeDelta = currentTime - startTime;
    startTime = currentTime;
    timeDelta *= 1.0f/1000;;

//  update_RK4(timeDelta);
//  update_nsv(timeDelta);
//  update_euler(timeDelta);
//  update_velocity_verlet(timeDelta);
}

首先,我只是想确保我有这些权利。

我正在模拟一个完全弹性的球弹跳,所以在反弹时我只是反转速度。

欧拉方法,球在每次弹跳时反弹得更高。这是由于我的代码中的错误,还是由于该方法的无效性。我已经读到,随着欧拉积分,你会随着时间的推移而失去能量。好吧,我正在获得它,我不知道为什么。

nsv方法:我不太明白这与Eular方法有什么不同,但无论如何球在每次反弹时都会反弹。它正在失去能量,我已经读过并不意味着用nsv方法发生。为什么我会失去能量?

(速度verlet和RK4方法正如我所期望的那样工作)。

我得到的印象是我缺乏关于这个主题的基本信息,但我不知道是什么。

我确实意识到我的时间步缺失,并且使用静态时间步长更新它以运行物理将阻止我失去/获得能量,但我试图了解发生了什么。

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:2)

要为@ Beta的答案添加另一个选项,如果您平均这两种方法,您的错误应该会消失(除了处理实际反弹的问题)。

public void update_avg(float timeDelta){    
    vVelocity.y += gravity.y*timeDelta/2;
    vPos.y += vVelocity.y * timeDelta; 
    vVelocity.y += gravity.y*timeDelta/2;
}

我在这里做的是将速度更新为区间内的平均速度,然后根据该速度更新位置,然后将速度更新为间隔结束时的速度。

如果您想要建模更复杂的场景,请考虑使用Runge-Kutta Method来解决y' = f(x, y)形式的微分方程。 (请注意,这里y可以是一组不同的变量。所以在你的情况下你有d(position, velocity)/dt = (velocity, -gravity)。我给你的代码与二阶版本相同那种方法。

答案 1 :(得分:1)

在现实生活中,球向上移动并减速,到达顶点(远地点),其速度为零,持续一秒钟,然后向下移动并加速。在任何时间间隔内,它都在与势能(高)交换动能(快速)。

在欧拉方法中,它以恒定速度移动一段时间,然后在间隔结束时突然改变其速度。因此,在向上的旅程中,它会以高速上升,然后减速,获得更多的高度。在向下的腿上,它缓慢地向下爬行,失去一点高度,然后加速。

在nsv方法中,情况正好相反:在上升的过程中,它“速度太快”会失去速度并且不会变得非常高,在向下的路上它会匆匆赶到地面而不会增加很多速度。

这两种方法的限制相同,因为timeDelta为零。 (如果这句话毫​​无意义,不要冒汗,那只是微积分。)如果你让timeDelta变小,效果就会消失。或者你可以使用能量作为你的主要变量,而不是{position,velocity},但数学会更复杂。

答案 2 :(得分:0)

集成将人工阻尼引入系统。我相信你可以通过对集成方案进行傅立叶分析来确定很多,但我必须更新我对内容的了解。