Орбитальная механика - PullRequest
       21

Орбитальная механика

11 голосов
/ 17 марта 2009

У кого-нибудь есть пример реализации Орбитальной Механики (желательно в 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;

Ответы [ 5 ]

8 голосов
/ 17 марта 2009

В последней строке вы обновляете позицию выстрела. Вы должны обновлять скорость.

Возможно, вы захотите взглянуть на код в этом посте http://blog.mendeltsiebenga.com/post/Fun-with-planets.aspx Нет, но работает орбитальная механика (хотя я никогда не избавлялся от мерцания экрана)

7 голосов
/ 17 марта 2009

Итерация Ньютона-Рафсона не является устойчивым способом решения этой проблемы (то есть вы не можете понять это правильно, используя столь простой интегратор для дифференциального уравнения). Подумайте об использовании решения второго (или более высокого) порядка: Рунге-Кутта хорошо и его довольно легко реализовать в этом случае.

С точки зрения численного анализа задача орбитальной механики сводится к решению системы связанных дифференциальных уравнений:

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.

4 голосов
/ 03 мая 2011

Метод «прыжковой лягушки» очень эффективен и стабилен, и хорошо работает для любой динамической системы частиц / полей, включая плазму. Для гравитации это просто. Вот все, что вы делаете для одной итерации на одной планете (проблема с одним телом, одна планета вокруг неподвижного солнца):

    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-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 голосов
/ 18 марта 2009

Проходящий объект не выйдет на орбиту. Одной из характеристик орбиты является то, что вы вернетесь в ту же точку (относительно тела, на котором движется орбита) с той же скоростью. Если вы начали с эффективной бесконечности, вы вернетесь к эффективной бесконечности.

Чтобы выйти на орбиту, вам нужно будет изменить скорость в некоторой точке, не связанную с гравитацией, или, возможно, иметь дополнительные большие тела. Точно так же вы не можете запустить объект на орбиту с поверхности: у вас должно быть что-то (например, последняя вспышка ракеты), когда спутник достигнет желаемой высоты. В противном случае он попытается вернуться к точке запуска, которая находится на поверхности.

Некоторые из моих худших случаев отладки были, когда программа была в порядке, и мои тестовые данные или расчеты были отключены. Убедитесь, что вы знаете, что искать.

1 голос
/ 17 марта 2009

A) Мы не знаем, какие у вас входные значения.

B) Возможно, вы захотите использовать лучшее приближение, чем Ньютон-Рафсон.

C) Проходящие объекты обычно не попадают на орбиту IRL, гравитация чрезвычайно слабая, для получения гораздо большего, чем кривизна, требуются одинаково низкие скорости или действительно исключительные массы.

...