Math 欧拉积分

Math 欧拉积分,math,language-agnostic,physics,game-physics,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; vP

我正试图了解这些集成方法,但我在思想上感到困惑

代码如下:

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);
}
首先,我只是想确定我把这些都弄对了

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

使用Euler方法,每次反弹时球反弹得更高。这是因为我的代码中有错误,还是因为方法不准确。我读到过,用欧拉积分,你会随着时间而失去能量。我得到了,我不知道为什么

nsv方法:我不太明白这与Eular方法有何不同,但在任何情况下,每次反弹时球反弹得更低。它正在失去能量,我读到了nsv方法不应该发生的事情。为什么我会失去能量

(velocity verlet和RK4方法按照我的预期工作)

我觉得我在这个问题上缺乏基本的信息,但我不知道是什么

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


任何帮助都将不胜感激。

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

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

在nsv方法中,情况正好相反:在上升的过程中,它“太快”失去速度,速度也不太高;在下降的过程中,它急急忙忙地到达地面,速度却没有增加多少


timeDelta
变为零时,这两种方法的限制相同。(如果这句话毫无意义,别担心,这只是微积分。)如果你把
timeDelta
设置得很小,效果就会消失。或者你可以使用能量作为你的主要变量,而不是{位置,速度},但是数学会稍微复杂一些。

在现实生活中,球向上移动并减速,到达顶点(远地点),在那里它的速度在瞬间为零,然后向下移动并加速。在任何时间间隔内,它都在用势能(高)交换动能(快)

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

在nsv方法中,情况正好相反:在上升的过程中,它“太快”失去速度,速度也不太高;在下降的过程中,它急急忙忙地到达地面,速度却没有增加多少


timeDelta
变为零时,这两种方法的限制相同。(如果这句话毫无意义,别担心,这只是微积分。)如果你把
timeDelta
设置得很小,效果就会消失。或者你可以使用能量作为你的主要变量,而不是{position,velocity},但是数学会稍微复杂一些。

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

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


如果你有一个更复杂的场景,你想建模,考虑使用它来解形式的微分方程<代码> y′=f(x,y)< /代码>。(注意这里的

y
可以是一组不同的变量。所以在你的例子中,你会有
d(位置,速度)/dt=(速度,-重力)
。我给你的代码与该方法的二阶版本是一样的。

要在@Beta的答案中添加另一个选项,如果你将两种方法取平均值,你的错误应该消失(除了处理实际反弹的问题)

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


如果你有一个更复杂的场景,你想建模,考虑用它来解形式的微分方程<代码> y′=f(x,y)< /代码>。(注意这里<代码> y>代码>可以是一组不同的变量。因此,在你的情况下,你将拥有<代码> d(位置,速度)/dt =(速度,重力)。。我给你的代码与该方法的二阶版本是一样的。

积分在系统中引入了人工阻尼。我相信你可以通过对积分方案进行傅里叶分析来确定多少,但我必须刷新我对细节的记忆。

积分引入了art系统中的人工阻尼。我相信你可以通过对积分方案进行傅里叶分析来确定多少,但我必须刷新我对细节的记忆。

这实际上相当于将
timeDelta
除以二,然后交替使用Euler和nsv。@Beta:True。但仔细计算一下,结果是正确的和二阶的龙格库塔一样,仔细想想,它也是精确解:dx=vt+at^2/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;
}