Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 轨道力学_C#_Xna_Physics - Fatal编程技术网

C# 轨道力学

C# 轨道力学,c#,xna,physics,C#,Xna,Physics,有没有人有实施轨道力学的例子(最好是XNA)?我目前使用的代码如下所示,但在执行时“感觉不正确”。物体只是稍微向行星弯曲,无论我如何调整变量,我都无法让它进入轨道,甚至部分轨道 shot.Position += shot.Velocity; foreach (Sprite planet in planets) { Vector2 directionToPlanet = (planet.Position - shot.Position); directionToPlane

有没有人有实施轨道力学的例子(最好是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);  
} 
编辑 标记门德尔的答案是正确的,因为它指出我需要更新速度,而不是位置。我还需要将gPull的计算更改为

float gPull = shot.Mass * planet.Mass / distanceSqr * planet.gStr;
这不是一个解决这个问题的稳定方法(也就是说,你不能用这么简单的微分方程积分器得到正确的结果)。考虑使用第二(或更高)阶解:是好的,在这种情况下是相当容易实现的。

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

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

其中,
x
是表示物体位置的三个向量,
m
是相同物体的质量,
r_ji=x_j-x_i
是更新快照位置的最后一行中物体
j
i
之间的向量位移。你应该更新速度

你可能想看看这篇博文中的代码,不是xna,而是工作轨道力学。(尽管我从未摆脱屏幕闪烁)

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

B) 您可能希望使用比Newton Raphson更好的近似值


C) 经过的物体通常不会进入轨道IRL,重力非常弱,需要同样弱的速度或真正异常的质量才能获得比曲率大得多的能量。

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

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

我最糟糕的调试经历是当程序运行良好,测试数据或计算中断时。确保你知道要寻找什么。

这种“蛙跳”方法非常有效和稳定,适用于任何动态粒子/场系统,包括等离子体。对于重力来说,这很简单。以下是您在单个行星上进行单个迭代所做的全部工作(单体问题,围绕静止太阳的单个行星):

其中“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;
        }
在哪里

N体更为复杂,因为不是单个引力源,而是多个引力源。代码格式是一样的:每个行星的位置都被N-1/2的速度推动,然后我们根据新的位置计算出每个行星上的总重力加速度,然后我们通过总加速度推动每个行星的速度


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

有趣的是,这给了我一个很好的正弦波……这不完全是我想要的,但这是我研究的结果equation@Joe:如果绘制圆形轨道中对象的单个位置分量(如x),则为正弦波(加上可能的阶段)是你所期望的…链接已经移动到了。而且源代码的rar也不可用。即使你使用archive.org。如果“经过的物体”和“轨道物体”以相同的速度与另一个物体保持相同的距离,它们之间有什么区别?我的印象是“经过的物体”来自很远的地方。它和轨道物体之间的区别当然是速度。当然,我可能误解了OP。很肯定你错了,因为Triton®声波风廓线仪被认为是一颗被捕获的卫星,它正在经过;现在它在绕轨道运行。如果我理解正确,不管物体离我们有多远当它靠近一个更大的物体时,如果速度和距离合适,它可能会进入轨道。简单地说,如果你拿一根绳子并把两端绑在一起,你就有一个环,但是如果你把绳子的一端绑在中间,你仍然有一个环。要进入轨道,你不需要回到原点。@P Daddy:引力相互作用完全是时间reversal不变量。要捕获“经过的物体”,需要推力或与第三个物体的相互作用。而且所有两个物体的引力相互作用路径都是圆锥截面(在COM框架中)。没错,但你可以在不借助Runge Kutta的情况下获得一些轨道。它不会停留在同一轨道上那么久
    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);
    }