c# - 跳ね返り - 軌道伝播



軌道力学 (4)

誰かが(できれば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;

Answer #1

A)入力値が何であるかわかりません。

B)Newton-Raphsonよりも良い近似を使用したいと思うかもしれません。

C)通過する物体は一般にIRLの軌道に入らず、重力は非常に弱く、曲率以上のものを得るためには同じように弱い速度または真に並外れた質量を必要とします。


Answer #2

「うるうカエル」法は非常に効率的で安定しており、プラズマを含むあらゆる動的粒子/場システムにうまく機能する。 重力のために、それは簡単です。 これが、単一の惑星での単一の反復(1体問題、静止した太陽の周りの単一の惑星)に対して行うことのすべてです。

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

ここで、 "Gravity.dT"は、任意の時間単位での一様な時間ステップです。 私はSystem.Windows.Vectorを使用していますが、基本的な乗算と加算をサポートしている限り、任意のカスタムVectorクラスが使用できます。 トリックは、PositionとVelocityが「同時」ではないことです。これは、ほとんどの統合方法では非常に一般的です。 むしろ、それらは互い違いになっています。 反復Nの位置は反復N - 1/2からの速度に基づいて更新されますが、反復N + 1/2の速度は反復Nの位置に基づいて更新されます。

N体バージョンは次のようになります。

    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の速度でプッシュされ、次に新しい位置に基づいて各惑星の総重力加速度を計算し、その総加速度で各惑星の速度をプッシュします。 。

他の方法は、 高次の方法でも、位置速度に基づいて次のステップを同時に線形的に投影するため、不安定なことがよくあります。 これは常にシステムにエネルギーを追加する側ではエラーになり、軌道は徐々にさらに遠くへと移動します。 他の方法では、この自然な誤差を過補償し、システムからエネルギーを取り除くことができます。 一般的に、人はエネルギー中立の解決策を望んでいます。 うるうカエル法は軌道の位相に関してはだんだんと誤りますが、全体的なエネルギーに関してはそうではありません。


Answer #3

最後の行で、ショットの位置を更新しています。 あなたは速度を更新しているはずです。

このブログ記事http://blog.mendeltsiebenga.com/post/Fun-with-planets.aspxコードを見てみるのもいいかもしれません。 (私は画面のちらつきを取り除くことはありませんでしたが)


Answer #4

通過する物体は軌道に入らないでしょう。 軌道の1つの特徴は、同じ速度で(軌道を回っている物体に対して)同じ点に戻るということです。 有効無限大から始めた場合は、有効無限大に戻ります。

軌道に入るためには、重力とは無関係にある点で速度を変更するか、あるいはおそらく追加の大きな物体が必要になります。 同様に、あなたは表面から軌道にオブジェクトを発射することはできません:衛星が望みの高度に到達したら、あなたは何か(最後のロケット弾きのような)を持っていなければなりません。 さもなければそれは表面上にある発射点に戻ることを試みるでしょう。

私の最悪のデバッグ経験のいくつかは、プログラムがうまくいっていてテストデータや計算がオフになっていた時でした。 何を探すべきか知っていることを確認してください。





physics