我发现这个问题非常有趣,因为我最近做了一些关于用阻力建模抛射体运动的工作。
第 1 点:您实际上是在使用显式/前向欧拉迭代来更新位置和速度,其中状态的每个新值都应该是旧值的函数。在这种情况下,您应该先更新位置,然后再更新速度。
第 2 点:阻力摩擦效应有更真实的物理模型。一个模型(由Adam Liss建议)涉及与速度成比例的阻力(称为斯托克斯阻力,通常适用于低速情况)。我之前建议的一个涉及与速度的平方成正比的阻力(称为二次阻力,通常适用于高速情况)。我将就如何推导出最大速度的公式以及有效达到最大速度所需的时间来解决每一个问题。我将放弃完整的推导,因为它们相当复杂。
斯托克斯的阻力:
更新速度的方程为:
velocity += acceleration - friction*velocity
它表示以下微分方程:
dv/dt = a - f*v
使用这个积分表中的第一个条目,我们可以找到解(假设 v = 0 在 t = 0):
v = (a/f) - (a/f)*exp(-f*t)
当 t >> 0 时出现最大(即终端)速度,因此等式中的第二项非常接近于零,并且:
v_max = a/f
关于达到最大速度所需的时间,请注意方程从未真正达到它,而是逐渐接近它。然而,当指数的参数等于 -5 时,速度大约是最大速度的 98%,可能接近到足以认为它相等。然后,您可以将达到最大速度的时间近似为:
t_max = 5/f
然后,您可以使用这两个方程来求解f和给定的所需vmax和tmax。
二次阻力:
更新速度的方程为:
velocity += acceleration - friction*velocity*velocity
它表示以下微分方程:
dv/dt = a - f*v^2
使用这个积分表中的第一个条目,我们可以找到解(假设 v = 0 在 t = 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)的公式以获得p(t)的封闭形式解决方案,从而完全不需要牛顿迭代。我会把这个留给其他人尝试。=)