Domanda

Qualcuno ha un esempio di implementazione della Meccanica Orbitale (preferibilmente in XNA)? Il codice che sto attualmente utilizzando è di seguito, ma non "si sente bene". quando viene eseguito. L'oggetto si piega leggermente al pianeta, e non importa quanto io possa modificare le variabili che non riesco a far entrare in un'orbita, o anche in un'orbita parziale.

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

Modifica Contrassegnare la risposta di Mendelt corretta per aver sottolineato che devo aggiornare la velocità, non la posizione. Ho anche dovuto cambiare il calcolo di gPull in

float gPull = shot.Mass * planet.Mass / distanceSqr * planet.gStr;
È stato utile?

Soluzione

Nell'ultima riga stai aggiornando la posizione dello scatto. Dovresti aggiornare la velocità.

Potresti dare un'occhiata al codice in questo post sul blog http: //blog.mendeltsiebenga.com/post/Fun-with-planets.aspx No xna, ma meccanica orbitale funzionante. (anche se non mi sono mai liberato dello sfarfallio dello schermo)

Altri suggerimenti

Newton-Raphson iteration non è un modo stabile per risolvere questo problema (che sei impossibile farlo bene usando un integratore così semplice per l'equazione differenziale). Prendi in considerazione l'idea di utilizzare una seconda soluzione (o superiore): Runge-Kutta è buono ed è abbastanza facile da implementare in questo caso.

Dal punto di vista dell'analisi numerica, il problema della meccanica orbitale si riduce a quello della risoluzione dell'insieme di equazioni differenziali accoppiate:

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

dove i x sono tre vettori che rappresentano le posizioni dei corpi, i m sono le masse degli stessi corpi e r_ji = x_j - x_i è lo spostamento vettoriale tra i corpi j e i .

Il "quotant rana" " il metodo è molto efficiente e stabile e funziona bene per qualsiasi sistema dinamico di particelle / campo, inclusi i plasma. Per gravità, è semplice. Ecco tutto ciò che fai per una singola iterazione su un singolo pianeta (problema di 1 corpo, singolo pianeta attorno al sole stazionario):

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

Dove " Gravity.dT " è un passo temporale uniforme, in una misura arbitraria del tempo. Sto usando System.Windows.Vector, ma qualsiasi classe Vector personalizzata lo farà, purché supporti la moltiplicazione e l'aggiunta di base. Il trucco è che la posizione e la velocità non sono allo stesso "tempo", il che è molto comune per la maggior parte dei metodi di integrazione. Piuttosto, sono sfalsati. La posizione sull'iterazione N viene aggiornata in base alla velocità dall'iterazione N - 1/2, ma quindi la velocità all'iterazione N + 1/2 viene aggiornata in base alla posizione all'iterazione N.

La versione N-body è simile alla seguente:

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

Dove

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

L'N-body è solo più complicato perché invece di una singola fonte gravitazionale, ce ne sono diverse. Il formato del codice è lo stesso, però: la posizione di ogni pianeta viene spinta dalla velocità N-1/2, quindi scopriamo l'accelerazione di gravità totale su ciascun pianeta in base alle nuove posizioni, quindi spingiamo la velocità di ciascun pianeta da quella accelerazione totale .

Altri metodi, anche i metodi di ordine superiore , sono spesso instabili perché proiettano linearmente il passaggio successivo in base alla velocità di posizione e allo stesso tempo. Ciò errerà sempre dal lato dell'aggiunta di energia al sistema e le orbite si sposteranno gradualmente sempre più verso l'esterno. Altri metodi possono compensare eccessivamente questo errore naturale e rimuovere energia dal sistema. In generale, si vuole una soluzione neutra dal punto di vista energetico. Il metodo del salto con le rane andrà gradualmente in errore in termini di fase delle orbite, ma non in termini di energia complessiva.

Un oggetto che passa non entrerà in orbita. Una caratteristica di un'orbita è che tornerai allo stesso punto (rispetto al corpo in orbita) con la stessa velocità. Se sei partito dall'infinito effettivo, tornerai all'infinito effettivo.

Per entrare in orbita, dovrai cambiare la velocità ad un certo punto in un modo non correlato alla gravità, o forse avere ulteriori corpi di grandi dimensioni. Allo stesso modo, non puoi lanciare un oggetto in orbita dalla superficie: devi avere qualcosa (come un'ultima bruciatura di un razzo) una volta che il satellite raggiunge l'altitudine desiderata. Altrimenti proverà a tornare al punto di lancio, che è in superficie.

Alcune delle mie peggiori esperienze di debug sono avvenute quando il programma andava bene ei miei dati di test o calcoli erano fuori. Assicurati di sapere cosa cercare.

A) Non abbiamo idea di quali siano i tuoi valori di input.

B) Potresti voler usare un'approssimazione migliore di Newton-Raphson.

C) Gli oggetti di passaggio generalmente non cadono in orbita IRL, la gravità è estremamente debole, ci vogliono velocità altrettanto deboli o masse davvero eccezionali per ottenere molto più della curvatura.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top