Gaffer on Games 有一篇很棒的文章,介绍了使用RK4 集成来获得更好的游戏物理效果。实现很简单,但它背后的数学让我感到困惑。我在概念层面上了解导数和积分,但很长时间没有操纵方程了。
这是 Gaffer 实现的主要内容:
void integrate(State &state, float t, float dt)
{
Derivative a = evaluate(state, t, 0.0f, Derivative());
Derivative b = evaluate(state, t+dt*0.5f, dt*0.5f, a);
Derivative c = evaluate(state, t+dt*0.5f, dt*0.5f, b);
Derivative d = evaluate(state, t+dt, dt, c);
const float dxdt = 1.0f/6.0f * (a.dx + 2.0f*(b.dx + c.dx) + d.dx);
const float dvdt = 1.0f/6.0f * (a.dv + 2.0f*(b.dv + c.dv) + d.dv)
state.x = state.x + dxdt * dt;
state.v = state.v + dvdt * dt;
}
谁能简单地解释一下 RK4 是如何工作的?具体来说,为什么我们要对0.0f
, 0.5f
,处的导数进行平均0.5f
,以及1.0f?
对 4 阶导数进行平均与用更小时间步进行简单的欧拉积分有何不同?
在阅读了下面公认的答案以及其他几篇文章后,我对 RK4 的工作原理有了一定的了解。回答我自己的问题:
谁能简单地解释一下 RK4 是如何工作的?
RK4 利用了这样一个事实,即如果我们使用函数的高阶导数而不仅仅是一阶或二阶导数,我们可以获得更好的函数逼近。这就是泰勒级数 比欧拉近似收敛得快得多的原因。(看看那个页面右侧的动画)
具体来说,为什么我们要对 、 、 和 处的导0.0f
数0.5f
进行0.5f
平均1.0f
?
Runge-Kutta 方法是一个函数的近似值,它在一个时间步长内对多个点的导数进行采样,而泰勒级数仅对单个点的导数进行采样。在对这些导数进行采样后,我们需要知道如何对每个样本进行称重以获得最接近的近似值。一个简单的方法是选择与泰勒级数一致的常数,这是确定龙格-库塔方程常数的方法。
这篇文章让我更清楚了。注意
(15)
泰勒级数展开是怎样的,而(17)
龙格-库塔推导是怎样的。
对高达 4 阶的导数求平均与用更小时间步进行简单的欧拉积分有何不同?
从数学上讲,它的收敛速度比许多欧拉近似要快得多。当然,通过足够的欧拉近似值,我们可以获得与 RK4 相同的精度,但所需的计算能力并不能证明使用欧拉是合理的。