6

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

我想添加类似“火箭”的运动(我说类似火箭的意思是它不一定是火箭 - 它可以是水上的飞机或船只或任何数量的类似情况)我的 2D 场景中的某些对象。我知道如何使用运动学模拟来实现它,但我想使用动态模拟来实现它(即随着时间的推移施加力)。我对如何实现这一点有点迷茫。

为了简化事情,我不需要动力学来旋转几何体,只需要影响身体的速度。我正在使用在 Farseer 中设置为不旋转的圆形几何图形,因此我只关心对象的速度。

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

我可以直接使用这个抽象,或者使用类似“rudder”值的东西来控制对象改变方向的速度(顺时针或逆时针)。

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

编辑:我的看法,如果我错了,请纠正我,你有两个力量(暂时忽略主推力):

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());
        }
    }

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

4

3 回答 3

2

我突然“明白”了。

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


要做到“正确”(空间):

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

要产生转弯,您将飞行器指向当前的运动方向并应用主驱动器。

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

顺便说一句——这可能比它的价值更麻烦:在自由落体中操纵火箭很棘手(你可能还记得几年前俄罗斯人在国际空间站上搞砸了一次对接机动;好吧,那不是因为他们很愚蠢。 )。除非您告诉我们您的用例,否则我们无法就此为您提供真正的建议。

一个小伪代码来暗示你在这里进入的内容:

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);
}

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


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

于 2010-07-12T19:41:47.300 回答
2

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

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

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

对于方向舵,产生的效果是一瞬间的,但除非你的游戏绝对需要进入角度动力学,否则更简单的做法是让方向舵控制在你的每时间滴答声中对你的火箭体角度进行固定量的变化。游戏。

于 2010-07-12T20:52:38.667 回答
0

想象一下你漂浮在空旷的空间中……你手里拿着一块大石头……如果你扔石头,一个小的冲动会在你扔石头的完全相反的方向上施加在你身上。您可以将您的火箭建模为快速将量子燃料转换为一定量的力(向量)的东西,您可以将其添加到方向向量中。

于 2010-07-12T20:11:58.890 回答