我发现这个问题非常有趣,因为我最近做了一些关于带阻力的抛体运动建模的工作。
要点1:你基本上是使用显式/向前欧拉迭代来更新位置和速度,在这种情况下,每个状态的新值应该是旧值的函数。在这种情况下,你应该先更新位置,然后再更新速度。
要点2:有更现实的物理模型可以用于阻力摩擦效应。其中一个模型(由Adam Liss提出)涉及一个与速度成比例的阻力力(称为斯托克斯阻力,通常适用于低速情况)。我之前提出的一个模型涉及一个与速度平方成比例的阻力力(称为二次阻力,通常适用于高速情况)。我将针对如何推导最大速度和有效到达最大速度所需时间的公式来讨论每个模型。我将放弃完整的推导,因为它们相当复杂。
斯托克斯阻力:
更新速度的方程式为:
velocity += acceleration - friction*velocity
这代表以下微分方程:
dv/dt = a - f*v
使用这个积分表中的第一个条目,我们可以找到解决方案(假设在t = 0时v = 0):
v = (a/f) - (a/f)*exp(-f*t)
最大速度(即终端速度)发生在 t >> 0 时,因此方程中的第二项非常接近于零,并且:
v_max = a/f
关于达到最大速度所需的时间,请注意方程式从未真正达到最大速度,而是渐近于最大速度。然而,当指数等于-5时,速度约为最大速度的98%,足以认为它相等。您可以将达到最大速度的时间近似为:
t_max = 5/f
您可以使用这两个方程式来解出f和a,假设您已知所需的vmax和tmax。
二次阻力:
更新速度的方程为:
velocity += acceleration - friction*velocity*velocity
这代表以下微分方程:
dv/dt = a - f*v^2
使用
这个积分表 中的第一个条目,我们可以找到解决方案(假设在 t = 0 时 v = 0)。
v = sqrt(a/f)*(exp(2*sqrt(a*f)*t) - 1)/(exp(2*sqrt(a*f)*t) + 1)
当 t >> 0 时,最大(即终端)速度发生,因此指数项远大于1,方程式趋近于:
v_max = sqrt(a/f)
关于达到最大速度所需的时间,请注意该方程永远无法真正达到最大速度,而是渐近趋向于它。然而,当指数函数的参数等于5时,速度接近最大速度的99%,可能足够接近以被认为相等。您可以将达到最大速度的时间近似为:
t_max = 2.5/sqrt(a*f)
这也等同于:
t_max = 2.5/(f*v_max)
对于所需的vmax和tmax,第二个关于tmax的方程将告诉您应该是什么f,然后您可以将其插入到vmax的方程中以获取a的值。
这似乎有点过度,但这些实际上是建模阻力最简单的方法之一!真正想看到整合步骤的人可以给我发电子邮件,我会把它们发送给您。它们有点复杂,无法在此处键入。
另一个要点:我没有立即意识到,但如果您使用我为v(t)推导的公式,则不再需要更新速度。如果您只是从静止开始建模加速度,并且您正在跟踪自加速以来的时间,则代码将如下所示:
position += velocity_function(timeSinceStart)
其中"velocity_function"是两个公式之一,用于
v(t),您将不再需要速度变量。一般来说,这里存在一个权衡:计算
v(t)可能比使用迭代方案更新速度更加计算密集(由于指数项),但它保证保持稳定和有界。在某些条件下(例如尝试获得非常短的
tmax),迭代可能变得不稳定并崩溃,这是前向欧拉方法的常见问题。然而,限制变量(如0<
f<1)应该可以防止这些不稳定性。
此外,如果您感觉有点虐待狂,您可能能够积分
v(t)的公式,从而放弃完全需要牛顿迭代的需求。我会让其他人尝试这个。=)