整合功能

时间:2017-03-19 14:41:35

标签: c++ math game-physics

我有这个功能来达到一定的1维值加速和过冲阻尼。即:给定初始值,速度和加速度(力/质量),通过加速到达目标值并在接近目标值的同时逐渐减弱目标值。

这一切都运行正常,如果我想知道TotalAngle在时间't'之后是什么我必须运行这个函数说N步骤用'小'dt找到'限制'。 我想知道我是否可以(以及如何)在dt上进行整合,以便在最初的时间't'确定TotalAngle。

问候,坦克可以提供任何帮助。

dt = delta time step per frame
input = 1
TotalAngle = 0 at t=0
Velocity   = 0 at t=0

void FAccelDampedWithOvershoot::Update(float dt, float input, float& Velocity, float& TotalAngle)
{
const float Force = 500000.f;
const float DampForce = 5000.f;
const float MaxAngle  = 45.f;
const float InvMass   = 1.f / 162400.f;

float target  = MaxAngle * input;
float ratio   = (target - TotalAngle) / MaxAngle;
float fMove   = Force * ratio;
float fDamp   = -Velocity * DampForce;

Velocity   += (fMove + fDamp) * invMass * dt;
TotalAngle += Velocity * dt;
}

2 个答案:

答案 0 :(得分:1)

这不是一个完整的答案,我相信其他人可以解决,但评论中没有空间,它可能会帮助您找到更好的解决方案。

下图显示了功能在时间步骤1中积分时的速度(蓝色)。红色显示下面的函数,用于计算时间t的值

enter image description here

函数F(t)

F(t) = sin((t / f) * pi * 2) * (1 / (((t / f) + a) ^ c)) * b

使用f = 23.7a = 1.4c = 2b= 50给出上图中的红色图

所有值都只是近似值。

f确定频率并接近匹配, abc控制振幅的衰减,并且是一个眼睛的猜测。

如果你有完美的匹配并不重要,那么这对你有用。 totalAngle使用相同的函数但添加了0.25。遗憾的是,我没有为a获取bctotalAngle的任何值,我确实注意到它已被偏移,因此您必须添加偏移值{{ 1}}(我将所有内容规范化,因此不知道d的范围是什么)

totalAngle

的函数F(t)

totalAngle

抱歉,只有F(t) = sin(((t+0.25) / f) * pi * 2) * (1 / ((((t+0.25) / f) + a) ^ c)) * b + df = 23.7c= 2 b =什么都没有? d =?

答案 1 :(得分:1)

更新,修复了数学

中的错误

最初我已经失去了质量和MaxAngle几次。这就是为什么你应该首先在纸上解决它然后进入SO而不是试图在文本编辑器中解决它。

无论如何,我已经修好了数学,现在似乎工作得相当好。我把固定解决方案放在前一个解决方案上。

嗯,这看起来像牛顿力学,这意味着微分方程。让我们试着解决它们。

SO对数学公式不是很友好,我输入字符有点无聊所以这就是我用的:

  • F = Force
  • Fd = DampForce
  • MA = MaxAngle
  • A = TotalAngle
  • v = Velocity
  • m = 1 / InvMass
  • '对于衍生工具,something'tsomething''的第一阶导数,是第二衍生物

如果我将最后两行代码除以dt并合并我可以得到的所有其他行(我还假设input = 1,因为其他情况显然是对称的)

v' = ([F * (1 - A / MA)]  - v * Fd) / m

并应用A' = v我们得到

m * A'' = F(1 - A/MA)  - Fd * A' 

或向一侧移动我们得到一个简单的二阶微分方程

m * A'' + Fd * A'  + F/MA * A  = F
IIRC,解决它的方法是先解决这里的特征方程

m * x ^ 2 + Fd * x + F / MA = 0

x [1,2] =(-Fd +/- sqrt(Fd ^ 2 - 4 * F * m / MA))/(2 * m)

我希望sqrt下的部分即(Fd^2 - 4*F*m/MA)为负数,因此解决方案应采用以下形式。让

Dm =  Fd/(2*m)
K =  sqrt(F/MA/m - Dm^2)

(注意sqrt下的否定值,所以现在可以正常工作)然后

A(t) = e^(-Dm*t) * [P * sin(K*t) + Q * cos(K*t)] + C

其中PQC是一些常量。

该解决方案更容易找到两种解决方案的总和:

的一些特定解决方案
m * A'' + Fd * A'  + F/MA * A  = F

和homogeneou的一般解决方案

m * A'' + Fd * A'  + F/MA * A  = 0

使原始条件适合。显然,具体的解决方案A(t) = MA起作用,因而C = MA。所以现在我们需要使PQ通用解决方案符合起始条件。要找到它们,我们需要

A(0) = - MA
A'(0) = V(0) = 0

鉴于e^0 = 1,sin(0) = 0且cos(0) = 1,您会得到类似

的内容
Q = -MA
P = 0

P = 0
Q = - MA
C = MA

从而

A(t) = MA * [1 - e^(-Dm*t) * cos(K*t)]
where 
Dm =  Fd/(2*m)
K =  sqrt(F/MA/m - Dm^2)

根据你的任务,这是有道理的。

另请注意,此等式假设所有内容均以弧度而非度数发生(即[sin(t)]'的导数仅为cos(t)),因此您应相应地转换所有常量或转换解决方案。

const float Force = 500000.f * M_PI / 180;
const float DampForce = 5000.f * M_PI / 180;
const float MaxAngle = M_PI_4;

在我的机器上产生

Dm = 0.000268677541
K  = 0.261568546

这似乎与原始功能相似,因为dt = 0.01f

,我与float同步并且主要障碍似乎是精确损失

希望这有帮助!