轨道力学

时间:2009-03-17 20:12:49

标签: c# xna physics

有没有人有一个实施轨道力学的例子(最好是在XNA中)?我目前使用的代码如下,但它执行时并没有“感觉正确”。物体只是稍微向地球弯曲,无论我调整多少变量,我都无法进入轨道,甚至是部分轨道。

shot.Position += shot.Velocity;  

foreach (Sprite planet in planets)  
{  
  Vector2 directionToPlanet = (planet.Position - shot.Position);  
  directionToPlanet.Normalize();  

  float distance = Vector2.DistanceSquared(shot.Position, planet.Position);  

  float gPull = (float)(planet.gravityStrength * (planet.Mass * shot.Mass) / distance) + planet.gravityField;  
  shot.Position += new Vector2(directionToPlanet.X * gPull, directionToPlanet.Y * gPull);  
} 

修改 标记Mendelt的答案是正确的,指出我需要更新速度,而不是位置。我还需要将gPull的计算更改为

float gPull = shot.Mass * planet.Mass / distanceSqr * planet.gStr;

5 个答案:

答案 0 :(得分:8)

在最后一行,你正在更新镜头的位置。你应该更新速度。

您可能需要查看此博客帖子中的代码http://blog.mendeltsiebenga.com/post/Fun-with-planets.aspx否xna,但需要工作轨道机制。 (虽然我从来没有摆脱过屏幕闪烁)

答案 1 :(得分:7)

Newton-Raphson iteration不是解决此问题的稳定方法(即无法使用如此简单的微分方程积分器来正确使用它)。考虑使用第二个(或更高)订单解决方案:Runge-Kutta很好,在这种情况下很容易实现。

从数值分析的角度来看,轨道力学的问题减少到求解耦合微分方程组的问题:

x_i'' + G m_i \sum_{i != j} m_j r_ji/(|r_ji|)^3 = 0

其中x是表示身体位置的三个向量,m是同一个身体的质量,r_ji = x_j - x_i是向量之间的位移正文ji

答案 2 :(得分:4)

“跳蛙”方法非常有效和稳定,适用于任何动态粒子/场系统,包括等离子体。对于重力,它很简单。以下是您在单个行星上进行单次迭代的所有操作(单体问题,固定太阳周围的单个行星):

    public void Push()
    {
        Position += Gravity.dT * Velocity;
        Velocity += Gravity.dT * GravityAccelerationVector(Position);
    }

其中“Gravity.dT”是一个统一的时间步长,在任意时间段内。我正在使用System.Windows.Vector,但任何自定义Vector类都可以,只要它支持基本的乘法和加法。诀窍是位置和速度不是“同时”,这对于大多数集成方法来说非常常见。相反,它们是错开的。迭代N上的位置基于迭代N - 1/2的速度更新,但是迭代时的速度N + 1/2基于迭代N处的位置更新。

N-body版本如下所示:

    public static void PushPlanets(Planet[] planets)
    {
        // Position Push at iteration N + 0:
        foreach(var p in planets)
            p.Position += Gravity.dT * p.Velocity; // Velocity from N - 1/2

        // Velocity Push at iteration N + 1/2:
        foreach (var p in planets)
        {
            Vector TotalGravity = new Vector(0,0);
            foreach (var pN in planets)
            {
                if (pN == p) continue;
                TotalGravity += pN.Mass * p.Mass * GravityAccelerationVector(p.Position - pN.Position);
            }
            TotalGravity += Sun.Mass * p.Mass * GravityAccelerationVector(p.Position); // Solar acceleration
            p.Velocity += Gravity.dT * TotalGravity;
        }

其中

    public static Vector GravityAccelerationVector(Vector position)
    {
        return Vector.Multiply(-G / position.LengthSquared / position.Length, position);
    }

N体只是更复杂,因为有几种,而不是单一的引力源。但是代码格式是相同的:每个行星的位置被N-1/2速度推动,然后我们根据新位置计算出每个行星上的总重力加速度,然后我们将每个行星的速度推动到总加速度

其他方法,即使是高阶方法,也经常不稳定,因为它们同时基于位置速度线性投影下一步。这总是在向系统增加能量方面犯错,并且轨道将逐渐向外进一步向外移动。其他方法可以过度补偿这种自然误差并从系统中移除能量。一般来说,人们需要能量中性解决方案。跳蛙方法在轨道相位方面会逐渐出错,但在整体能量方面则不然。

答案 3 :(得分:3)

传球对象不会进入轨道。轨道的一个特征是你将以相同的速度返回相同的点(相对于被轨道运行的物体)。如果你从有效的无限远开始,你将回到有效的无限远。

为了进入轨道,您需要在某个点以与重力无关的方式改变速度,或者可能有更多的大体。同样地,你不能从地面将物体发射到轨道上:一旦卫星达到所需的高度,你必须有一些东西(比如最后一次火箭燃烧)。否则它将尝试返回到表面上的发射点。

我最糟糕的一些调试经验是程序运行良好且我的测试数据或计算结束时。确保你知道要寻找什么。

答案 4 :(得分:1)

A)我们不知道您的输入值是什么。

B)你可能想要使用比Newton-Raphson更好的近似值。

C)通过物体通常不会进入轨道IRL,重力弱,它需要同样弱的速度或真正特殊的质量来获得比曲率更多的东西。