【问题标题】:Simple Euler Physics, Weird Behaviour简单的欧拉物理,奇怪的行为
【发布时间】:2011-10-07 07:16:57
【问题描述】:

我有这个简单的欧拉积分器。为了找到精确的碰撞时间,它还应该处理负 dt(我划分帧时间并在检测到碰撞时进行模拟)。

由于某种原因

someBody.update(1.0);
someBody.update(-0.3);
someBody.update(-0.3);
someBody.update(0.6);

给出不同的结果:

someBody.update(1.0);

可能是因为我使用 euler 而不是 RK4 或 verlet?

这是集成商的代码:

void Body::update(double dt)
{
    if (dt > 0) velocity += acceleration * (dt*dt);
    else velocity -= acceleration * (dt*dt);
    pos += velocity * dt;
    rotation += angularVelocity * dt;
}

非常感谢!

马丁

【问题讨论】:

  • 为什么是velocity += acceleration * (dt*dt);?不是$v=at$吗?
  • 请检查someBody.update(1.0); 是否会产生与someBody.update(0.5); someBody.update(0.5); 相同的值我认为您当前的公式不正确。还要检查在 x=0, v=0, a=1 时,someBody.update(1.0); 之后您将在 x=0.5, v=1。

标签: c++ integration physics


【解决方案1】:

原因是数学。让我们关注velocity变量:

如果你打电话:

someBody.update(1.0)

你会得到:

velocity += acceleration * 1

但如果你打电话:

someBody.update(1.0);
someBody.update(-0.3);
someBody.update(-0.3);
someBody.update(0.6);

你会得到:

velocity += acceleration * (1 - 0.3^2 - 0.32^2 + 0.6^2)

(给出velocity += acceleration * 1.18

你应该有简单的velocity += acceleration * dt;

【讨论】:

  • 感谢 Martinho 添加正确答案,我什至没有考虑过物理本身。
【解决方案2】:

怀疑在 Body::update 中累积浮点错误。 示例:1 + 2 + 3 + 4 = 10 但 1.0 + 2.0 + 3.0 + 4.0 = 其他。

最简单的解决方法是在每个主要计算步骤之后对结果进行四舍五入。

【讨论】:

    【解决方案3】:

    谢谢,加速确实错了。

    我为每一帧使用一个固定的时间步长。此功能用于运行部分帧的模拟。所以我现在完全忽略了加速。这样一帧内的一切都是线性发生的,加速度只在帧之间添加。

    问题仍然存在。我认为这可能是 Magicianeer 指出的浮点错误。

    虽然我认为这些错误加起来不会那么大。在大约 50 帧中,一个弹跳物体从其全高 (100) 变为该高度的大约一半。在大约 200 帧中,它仍然在地板上。当我不在框架内调用多个更新时,一切都很好。

    我将尝试将位置保持在帧的末尾,并在进行部分帧模拟后将其放回原处。这样,错误就不会在多个帧上累加。

    【讨论】:

      猜你喜欢
      • 2015-06-25
      • 1970-01-01
      • 2018-04-25
      • 1970-01-01
      • 1970-01-01
      • 2021-04-26
      • 1970-01-01
      • 2013-12-14
      • 2018-04-02
      相关资源
      最近更新 更多