NSV、欧拉积分混乱
我正在尝试了解这些集成方法,但我完全感到困惑。
这是代码:
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 方法会发生这种情况。为什么我会失去能量?
(velocity verlet 和 RK4 方法按照我的预期工作)。
我感觉我缺乏关于这个主题的基本信息,但我不知道是什么。
我确实意识到我的时间步长不足,并且使用静态时间步长更新它以运行物理会阻止我失去/获得能量,但我正在尝试了解发生了什么。
任何帮助将不胜感激。
I'm trying to get my head around these integration methods and I'm thouroughly confused.
Here is the code:
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);
}
Firstly, I just want to make sure I've got these right.
I am simulating a perfectly elastic ball bouncing, so on the bounce I just reverse the velocity.
The Euler method, the ball bounces higher on each bounce. Is this due to an error in my code or is this due to the innacuracy of the method. I've read that with the Euler integration you lose energy over time. Well I'm gaining it and I don't know why.
The nsv method: I don't quite understand how this is different to the Eular method, but in any case the ball bounces lower on each bounce. It is losing energy which I've read isnt meant to happen with the nsv method. Why am I losing energy?
(The velocity verlet and RK4 methods are working as I'd expect them to).
I get the impression I'm lacking a fundamental bit of information on this subject, but I don't know what.
I do realise my timestep is lacking, and updating it to run the physics using a static timestep would stop me losing/gaining energy, but I am trying to understand what is going on.
Any help would be appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
要为 @Beta 的答案添加另一个选项,如果对两种方法进行平均,则错误应该消失(除了处理实际弹跳的问题之外)。
我在这里所做的是将速度更新为间隔内的平均速度,然后根据该速度更新位置,然后将速度更新为间隔结束时的速度。
如果您想要建模更复杂的场景,请考虑使用龙格-库塔方法 求解
y' = f(x, y)
形式的微分方程。 (请注意,这里 y 可以是一组不同的变量。因此,在您的情况下,您将拥有 d(position,velocity)/dt = (velocity, -gravity)我给你的代码与该方法的二阶版本相同。To add another option to @Beta's answer, if you average the two methods, your error should disappear (except for issues around handling the actual bounce).
What I'm doing here is updating the velocity to the average velocity over the interval, then updating the position based on that velocity, then updating the velocity to the velocity at the end of the interval.
If you have a more complicated scenario that you want to model, consider using the Runge-Kutta Method to solve differential equations of the form
y' = f(x, y)
. (Note that herey
can be a set of different variables. So in your case you'd haved(position, velocity)/dt = (velocity, -gravity)
. And the code I gave you works out to be the same as the second-order version of that method.在现实生活中,球向上移动并减速,到达顶点(远地点),其速度瞬间为零,然后向下移动并加速。在任何时间间隔内,它都在交换动能(快)和势能(高)。
在欧拉方法中,它在间隔期间以恒定速度移动,然后在间隔结束时突然改变速度。因此,在向上的旅程中,它会高速上升,然后减速,获得比应有的高度更高的高度。在向下的腿上,它缓慢地向下爬,稍微降低高度,然后加速。
在 NSV 方法中,情况正好相反:在上升过程中,它“太快”失去速度并且不会变得很高,在下降过程中,它会匆忙到达地面,而不会增加太多速度。
这两种方法在
timeDelta
归零的限制方面是相同的。 (如果这个说法毫无意义,别担心,这只是微积分。)如果您将timeDelta
设置得较小,效果就会消失。或者您可以使用能量作为主要变量,而不是{位置,速度},但数学会更复杂一些。In real life, the ball moves upward and decelerates, reaches the apex (apogee) where its velocity is zero for a split-second, then moves downward and accelerates. Over any time interval it is exchanging kinetic energy (being fast) with potential energy (being high).
In the Euler method, it moves with constant velocity for the duration of the interval, then at the end of the interval it suddenly changes its velocity. So on the upward journey it goes up at high speed, then slows down, having gained more altitude than it should have. On the downward leg it creeps down slowly, losing little altitude, then speeds up.
In the nsv method, the opposite happens: on the way up it loses speed "too soon" and doesn't get very high, on the way down it hurries and reaches the ground without building up much speed.
The two methods are the same in the limit as
timeDelta
goes to zero. (If that statement made no sense, don't sweat it, it's just calculus.) If you maketimeDelta
small, the effect should fade. Or you could use energy as your primary variable, not {position, velocity}, but the math would be a little more complicated.该集成将人工阻尼引入系统。我相信你可以通过对积分方案进行傅里叶分析来确定多少,但我必须刷新我对细节的记忆。
The integration introduces artificial damping into the system. I believe you can determine ho much by doing a Fourier analysis on the integration scheme, but I'd have to refresh my memory on the details.