我有这个功能来达到一定的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;
}
答案 0 :(得分:1)
这不是一个完整的答案,我相信其他人可以解决,但评论中没有空间,它可能会帮助您找到更好的解决方案。
下图显示了功能在时间步骤1中积分时的速度(蓝色)。红色显示下面的函数,用于计算时间t的值
函数F(t)
F(t) = sin((t / f) * pi * 2) * (1 / (((t / f) + a) ^ c)) * b
使用f = 23.7
,a = 1.4
,c = 2
和b= 50
给出上图中的红色图
所有值都只是近似值。
f
确定频率并接近匹配,
a
,b
,c
控制振幅的衰减,并且是一个眼睛的猜测。
如果你有完美的匹配并不重要,那么这对你有用。 totalAngle
使用相同的函数但添加了0.25。遗憾的是,我没有为a
获取b
,c
,totalAngle
的任何值,我确实注意到它已被偏移,因此您必须添加偏移值{{ 1}}(我将所有内容规范化,因此不知道d
的范围是什么)
totalAngle
totalAngle
抱歉,只有F(t) = sin(((t+0.25) / f) * pi * 2) * (1 / ((((t+0.25) / f) + a) ^ c)) * b + d
,f = 23.7
,c= 2
b =什么都没有? d =?
答案 1 :(得分:1)
更新,修复了数学
中的错误最初我已经失去了质量和MaxAngle几次。这就是为什么你应该首先在纸上解决它然后进入SO而不是试图在文本编辑器中解决它。
无论如何,我已经修好了数学,现在似乎工作得相当好。我把固定解决方案放在前一个解决方案上。
嗯,这看起来像牛顿力学,这意味着微分方程。让我们试着解决它们。
SO对数学公式不是很友好,我输入字符有点无聊所以这就是我用的:
F
= Force
Fd
= DampForce
MA
= MaxAngle
A
= TotalAngle
v
= Velocity
m
= 1 / InvMass
'
对于衍生工具,something'
是t
和something''
的第一阶导数,是第二衍生物如果我将最后两行代码除以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
其中P
,Q
和C
是一些常量。
该解决方案更容易找到两种解决方案的总和:
的一些特定解决方案m * A'' + Fd * A' + F/MA * A = F
和homogeneou的一般解决方案
m * A'' + Fd * A' + F/MA * A = 0
使原始条件适合。显然,具体的解决方案A(t) = MA
起作用,因而C = MA
。所以现在我们需要使P
和Q
通用解决方案符合起始条件。要找到它们,我们需要
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
同步并且主要障碍似乎是精确损失
希望这有帮助!