简单的2D火箭动力学

时间:2010-07-12 19:24:47

标签: c# xna 2d physics farseer

我目前正在使用Farseer Physics库在XNA中试验一些物理玩具,但我的问题不是特定于XNA或Farseer - 而是任何2D物理库。

我想添加“类似火箭”的运动(我说火箭似乎不需要火箭 - 它可以是水面上的飞机或船只或任何类似的对于我的2D场景中的某些对象。我知道如何使用运动学模拟实现这一点,但我想使用动态模拟(即随时间推移施加力)来实现它。我对如何实现这一点感到很遗憾。

为了简化操作,我不需要动力学来旋转几何体,只是为了影响身体的速度。我使用的圆形几何体设置为不在Farseer中旋转,所以我只关心物体的速度。

我甚至不确定最好的抽象应该是什么。从概念上讲,我有身体当前移动的方向(单位矢量),我希望它去的方向,以及表示我希望它改变方向的速度的值,同时保持速度相对恒定(小的变化是可接受的)。

我可以直接使用这种抽象,或使用像“舵”这样的值来控制物体改变方向的速度(顺时针或逆时针)。

我应该在身体上施加什么样的力量来模拟我正在寻找的运动?请记住,我也希望能够在飞行中调整火箭的“推力”。

编辑: 我看待它的方式,并纠正我,如果我错了,你有两种力量(暂时忽略主推力):

1)你有一个静态的“鳍”,总是指向与身体相同的方向。如果主体旋转使得翅片不与运动方向对齐,则空气阻力将沿着翅片的长度施加力,与运动方向和翅片之间的角度成比例。

2)你有一个“舵”,它可以在一个指定的范围内自由旋转,这个范围与身体的质心相距一定距离(在这种情况下,我们有一个圆圈)。同样,当这个平面与运动方向不平行时,空气阻力会沿着方向舵的长度产生比例力。

我的问题是,不同地说,我如何计算空气阻力对鳍和方向舵的这些比例力?

编辑: 作为参考,这里是我编写的一些代码来测试接受的答案:

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main(string[] args)
    {
        float dc = 0.001f;
        float lc = 0.025f;
        float angle = MathHelper.ToRadians(45);
        Vector2 vel = new Vector2(1, 0);
        Vector2 pos = new Vector2(0, 0);
        for (int i = 0; i < 200; i++)
        {
            Vector2 drag = vel * angle * dc;
            Vector2 sideForce = angle * lc * vel;
            //sideForce = new Vector2(sideForce.Y, -sideForce.X); // rotate 90 degrees CW
            sideForce = new Vector2(-sideForce.Y, sideForce.X); // rotate 90 degrees CCW
            vel = vel + (-drag) + sideForce;
            pos = pos + vel;
            if(i % 10 == 0)
                System.Console.WriteLine("{0}\t{1}\t{2}", pos.X, pos.Y, vel.Length());
        }
    }

当你绘制这个程序的输出图时,你会看到一条漂亮的光滑圆形曲线,这正是我想要的!

3 个答案:

答案 0 :(得分:2)

我突然“得到”它。

你想模拟在空气中飞行的火箭动力导弹,好的。这是一个与我下面详述的问题不同的问题,并施加了不同的限制。你需要一个航空航天爱好者。或者你可以试试。


“正确”(空间):

模拟体应在其质心周围提供惯性矩,并且还必须具有指向方向和角速度。然后根据施加的脉冲和距离CoM的距离计算角加速度,并将其加到角速度上。这允许您计算飞行器的当前“指向”(如果您不使用陀螺仪或配对姿态喷射器,您还可以获得(通常非常小)线性加速度)。

要生成转弯,请将飞行器指向当前的移动方向并应用主驱动器。

如果您对此非常认真,还需要从总质量中减去燃烧燃料的质量,并对每个时间增量的惯性矩进行适当的修正。

BTW - 这可能比它的价值更麻烦:在自由落体中操纵火箭是棘手的(你可能还记得俄罗斯人几年前在国际空间站上捣乱了对接机动嗯,那不是因为他们是愚蠢的。)除非你告诉我们你的用例,否则我们无法就此提出建议。

一个小伪代码暗示你要进入这里:

rocket {
  float structuralMass;
  float fuelMass;
  point position;
  point velocity;
  float heading;
  float omega;       // Angular velocity
  float structuralI; // moment of inertia from craft
  float fuelI;       // moemnt of inertia from the fuel load

  float Mass(){return struturalMass + fuelMass};
  float I(){return struturalI + fuelI};
  float Thrust(float t);
  float AdjustAttitude(float a);
}

结果是:也许你想要一个“游戏物理”版本。


因为我不会同时进入这里,运行“真正的”火箭的最有效方法通常是来逐渐转弯和缓慢加速,而是推动很难什么时候你想改变方向。在这种情况下,您可以通过从当前向量中减去所需向量(完整向量,而不是单位)来获得推力角度。然后你指向那个的方向,并信任所有人,直到达到所需的路线。

答案 1 :(得分:2)

如果您已经拥有将力和质量与加速度和速度相结合的代码,那么您只需要计算您正在谈论的两个元素中每个元素的各个部分。

保持简单,我会暂时忘掉鳍,只要说火箭的身体与它的速度成一定角度,它就会产生线性增加的侧向力和阻力。只需使用系数,直到它看起来和感觉如何。

Drag = angle*drag_coefficient*velocity + base_drag
SideForce = angle*lift_coefficent*velocity

对于方向舵,产生的效果是一个时刻,但除非你的游戏绝对需要进入角度动力学,更简单的事情是让方向舵控制每次都对你的火箭体角度进行固定的变化在你的游戏中打勾。

答案 2 :(得分:0)

想象一下你漂浮在空旷的空间......你的手中有一块巨大的岩石......如果你抛出岩石,一个小的冲动会以你抛出岩石的方向完全相反的方式施加在你身上。您可以将火箭建模为快速将量子燃料转换为可以添加到方向向量的一定量的力(矢量)。