Каковы некоторые алгоритмы, которые позволят мне моделировать физику планет?

Я заинтересован в создании симулятора "Солнечной системы", который позволит мне смоделировать вращательные и гравитационные силы планет и звезд.

Я хотел бы сказать, смоделировать нашу солнечную систему и имитировать ее на разных скоростях (т.е. наблюдать, как Земля и другие планеты вращаются вокруг Солнца через дни, годы и т.д.). Я хотел бы иметь возможность добавлять планеты и изменять массу планет и т.д., Чтобы увидеть, как это повлияет на систему.

Есть ли у кого-нибудь какие-либо ресурсы, которые указывали бы мне в правильном направлении для написания такого типа симулятора?

Существуют ли какие-либо существующие физические двигатели, предназначенные для этой цели?

28
02 февр. '10 в 11:09
источник поделиться
12 ответов

Это все здесь и вообще все, что написал Жан Миус.

alt text

9
02 февр. '10 в 11:15
источник

Вам нужно знать и понимать Закон Ньютона Универсальной Гравитации и Kepler Законы планетарного движения. Эти два просты, и я уверен, что вы слышали о них, если не изучали их в старшей школе. Наконец, если вы хотите, чтобы ваш симулятор был как можно более точным, вы должны ознакомиться с проблемой n-Body.

Вы должны начать просто. Попробуйте создать объект Sun и объект Earth, который вращается вокруг него. Это должно дать вам очень прочный старт, и оттуда его довольно легко расширить. Объект планеты будет выглядеть примерно так:

Class Planet {
  float x;
  float y;
  float z; // If you want to work in 3D
  double velocity;
  int mass;
}

Просто помните, что F = MA, а остальная просто скучная математика: P

8
02 февр. '10 в 11:19
источник

Это отличный учебник по проблемам N-body в целом.

http://www.artcompsci.org/#msa

Он написан с использованием Ruby, но довольно легко отображает его на другие языки и т.д. Он охватывает некоторые общие подходы к интеграции; Форвард-Эйлер, Лепфрог и Эрмит.

6
03 февр. '10 в 0:18
источник

Вы можете взглянуть на Celestia, симулятор свободного пространства. Я считаю, что вы можете использовать его для создания фиктивных солнечных систем, и с открытым исходным кодом.

4
02 февр. '10 в 11:33
источник

В физике это называется N-Body Problem. Это известно, потому что вы не можете решить это вручную для системы с более чем тремя планетами. К счастью, вы можете легко получить приблизительные решения с компьютером.

Хорошую статью о написании этого кода с нуля можно найти здесь.

Тем не менее, я чувствую, что слово предупреждения важно здесь. Вы не можете получить ожидаемые результаты. Если вы хотите увидеть, как:

  • масса планеты влияет на ее орбитальную скорость вокруг Солнца, прохладно. Вы увидите это.
  • разные планеты взаимодействуют друг с другом, вас будут обманывать.

Проблема заключается в этом.

Да, современные астрономы озабочены тем, как масса Сатурна изменяет орбиту Земли вокруг Солнца. Но это ОЧЕНЬ незначительный эффект. Если вы собираетесь заложить путь планеты вокруг Солнца, вряд ли будет иметь значение, что в Солнечной системе есть другие планеты. Солнце настолько велико, что оно заглушит всю другую гравитацию. Исключение составляют только:

  • Если ваши планеты имеют очень эллиптические орбиты. Это заставит планеты потенциально сближаться, поэтому они будут взаимодействовать больше.
  • Если ваши планеты находятся почти на том же расстоянии от Солнца. Они будут взаимодействовать больше.
  • Если вы сделаете свои планеты такими смешными, они конкурируют с Солнцем за гравитацию во внешней Солнечной системе.

Чтобы быть ясным, да, вы сможете рассчитать некоторые взаимодействия между планетами. Но нет, эти взаимодействия не будут значительными для невооруженного глаза, если вы создадите реалистичную Солнечную систему.

Попробуйте, и узнайте!

2
05 окт. '12 в 1:20
источник

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

В Интернете есть такие симуляторы.

Вот один простой, реализованный в 500 строк кода c. (montion algorhitm намного меньше) http://astro.berkeley.edu/~dperley/programs/ssms.html.

Также проверьте это:
http://en.wikipedia.org/wiki/Kepler_problem
http://en.wikipedia.org/wiki/Two-body_problem
http://en.wikipedia.org/wiki/N-body_problem

2
02 февр. '10 в 19:37
источник

Похоже, что это очень сложно и требует сильного знания физики, но на самом деле это очень легко, вам нужно знать только 2 формулы и базовое понимание векторов:

Аттракционная сила (или гравитационная сила) между планетой 1 и планетой2 с массой m1 и m2 и расстояние между ними d: Fg = G * m1 * m2/d ^ 2; Fg = m * a. G - постоянная, найдите ее, заменив случайные значения так, чтобы ускорение "a" не было слишком маленьким и не слишком большим приблизительно "0,01" или "0,1".

Если у вас есть полная векторная сила, действующая на текущую планету в этот момент времени, вы можете найти мгновенное ускорение a = (полная сила)/(масса текущей планеты). И если у вас текущее ускорение и текущая скорость и текущее положение, вы можете найти новую скорость и новую позицию.

Если вы хотите посмотреть, как это реально, вы можете использовать следующий алгоритм суперэварии (псевдокод):

int n; // # of planets
Vector2D planetPosition[n]; 
Vector2D planetVelocity[n]; // initially set by (0, 0)
double planetMass[n];

while (true){
    for (int i = 0; i < n; i++){
        Vector2D totalForce = (0, 0); // acting on planet i
        for (int j = 0; j < n; j++){
            if (j == i)
                continue; // force between some planet and itself is 0
            Fg = G * planetMass[i] * planetMass[j] / distance(i, j) ^ 2;
        // Fg is a scalar value representing magnitude of force acting
        // between planet[i] and planet[j]
        // vectorFg is a vector form of force Fg
        // (planetPosition[j] - planetPosition[i]) is a vector value
        // (planetPosition[j]-planetPosition[i])/(planetPosition[j]-plantetPosition[i]).magnitude() is a
        // unit vector with direction from planet[i] to planet[j]
            vectorFg = Fg * (planetPosition[j] - planetPosition[i]) / 
                  (planetPosition[j] - planetPosition[i]).magnitude();
            totalForce += vectorFg;
        }
        Vector2D acceleration = totalForce / planetMass[i];
        planetVelocity[i] += acceleration;
    }

    // it is important to separate two for's, if you want to know why ask in the comments
    for (int i = 0; i < n; i++)
        planetPosition[i] += planetVelocity[i];

    sleep 17 ms;
    draw planets;
}
1
15 июля '15 в 1:50
источник

Отметьте nMod, набор инструментов моделирования n-body, написанный на С++ и использующий OpenGL. Он имеет довольно хорошо заполненную модель солнечной системы, которая поставляется вместе с ней, и ее нужно легко модифицировать. Кроме того, у него довольно хорошая вики о моделировании n-body в целом. Тот же парень, который создал это, также создает новую программу под названием Moody, но, похоже, она не так далеко.

Кроме того, если вы собираетесь делать симуляции n-body с более чем несколькими объектами, вы должны действительно посмотреть на быстрый мультипольный метод (также называемый быстрым мультипольным алгоритмом). Он может сократить количество вычислений от O (N ^ 2) до O (N), чтобы действительно ускорить вашу симуляцию. По словам автора этой статьи, он также является одним из десяти лучших успешных алгоритмов 20-го века.

1
06 февр. '10 в 9:35
источник

Алгоритмы моделирования физики планет.

Вот реализация частей Keppler в приложении для Android. Основные части находятся на моем веб-сайте, так как вы можете загрузить весь источник: http://www.barrythomas.co.uk/keppler.html

Это мой метод рисования планеты в "следующей" позиции на орбите. Подумайте о таких шагах, как шаг по кругу, по одной градусе за раз, по кругу, который имеет тот же период, что и планета, которую вы пытаетесь отследить. Вне этого метода я использую глобальный двойник в качестве счетчика шагов, называемый dTime, который содержит несколько степеней вращения.

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

drawPlanet:

public void drawPlanet (double dEccentricity, double dScalar, double dYear, Canvas canvas, Paint paint, 
            String sName, Bitmap bmp, double dLongPeri)
{
        double dE, dr, dv, dSatX, dSatY, dSatXCorrected, dSatYCorrected;
        float fX, fY;
        int iSunXOffset = getWidth() / 2;
        int iSunYOffset = getHeight() / 2;

        // get the value of E from the angle travelled in this 'tick'

        dE = getE (dTime * (1 / dYear), dEccentricity);

        // get r: the length of 'radius' vector

        dr = getRfromE (dE, dEccentricity, dScalar);

        // calculate v - the true anomaly

        dv = 2 * Math.atan (
                Math.sqrt((1 + dEccentricity) / (1 - dEccentricity))
                *
                Math.tan(dE / 2)
                ); 

        // get X and Y coords based on the origin

        dSatX = dr / Math.sin(Math.PI / 2) * Math.sin(dv);
        dSatY = Math.sin((Math.PI / 2) - dv) * (dSatX / Math.sin(dv));

        // now correct for Longitude of Perihelion for this planet

        dSatXCorrected = dSatX * (float)Math.cos (Math.toRadians(dLongPeri)) - 
            dSatY * (float)Math.sin(Math.toRadians(dLongPeri));
        dSatYCorrected = dSatX * (float)Math.sin (Math.toRadians(dLongPeri)) + 
            dSatY * (float)Math.cos(Math.toRadians(dLongPeri));

        // offset the origin to nearer the centre of the display

        fX = (float)dSatXCorrected + (float)iSunXOffset;
        fY = (float)dSatYCorrected + (float)iSunYOffset;

        if (bDrawOrbits)
            {
            // draw the path of the orbit travelled
            paint.setColor(Color.WHITE);
            paint.setStyle(Paint.Style.STROKE);
            paint.setAntiAlias(true);

            // get the size of the rect which encloses the elliptical orbit

            dE = getE (0.0, dEccentricity);
            dr = getRfromE (dE, dEccentricity, dScalar);
            rectOval.bottom = (float)dr;
            dE = getE (180.0, dEccentricity);
            dr = getRfromE (dE, dEccentricity, dScalar);
            rectOval.top = (float)(0 - dr);

            // calculate minor axis from major axis and eccentricity
            // http://www.1728.org/ellipse.htm

            double dMajor = rectOval.bottom - rectOval.top;
            double dMinor = Math.sqrt(1 - (dEccentricity * dEccentricity)) * dMajor;

            rectOval.left = 0 - (float)(dMinor / 2);
            rectOval.right = (float)(dMinor / 2);

            rectOval.left += (float)iSunXOffset;
            rectOval.right += (float)iSunXOffset;
            rectOval.top += (float)iSunYOffset;
            rectOval.bottom += (float)iSunYOffset;

            // now correct for Longitude of Perihelion for this orbit path

            canvas.save();
                canvas.rotate((float)dLongPeri, (float)iSunXOffset, (float)iSunYOffset);
                canvas.drawOval(rectOval, paint);
            canvas.restore();
            }

        int iBitmapHeight = bmp.getHeight();

        canvas.drawBitmap(bmp, fX - (iBitmapHeight / 2), fY - (iBitmapHeight / 2), null);

        // draw planet label

        myPaint.setColor(Color.WHITE);
        paint.setTextSize(30);
        canvas.drawText(sName, fX+20, fY-20, paint);
}

В приведенном выше методе рассматриваются еще два метода, которые обеспечивают значения E (средняя аномалия) и r, длина вектора, в конце которого найдена планета.

Gete:

public double getE (double dTime, double dEccentricity)
    {
    // we are passed the degree count in degrees (duh) 
    // and the eccentricity value
    // the method returns E

    double dM1, dD, dE0, dE = 0; // return value E = the mean anomaly
    double dM; // local value of M in radians

    dM = Math.toRadians (dTime);

    int iSign = 1;

    if (dM > 0) iSign = 1; else iSign = -1;

    dM = Math.abs(dM) / (2 * Math.PI); // Meeus, p 206, line 110
    dM = (dM - (long)dM) * (2 * Math.PI) * iSign; // line 120
    if (dM < 0)
        dM = dM + (2 * Math.PI); // line 130
    iSign = 1;
    if (dM > Math.PI) iSign = -1; // line 150
    if (dM > Math.PI) dM = 2 * Math.PI - dM; // line 160

    dE0 = Math.PI / 2; // line 170
    dD = Math.PI / 4; // line 170

    for (int i = 0; i < 33; i++) // line 180 
        {
        dM1 = dE0 - dEccentricity * Math.sin(dE0); // line 190
        dE0 = dE0 + dD * Math.signum((float)(dM - dM1));
        dD = dD / 2; 
        }

    dE = dE0 * iSign;

    return dE;
    }

getRfromE:

public double getRfromE (double dE, double dEccentricty, double dScalar)
{
    return Math.min(getWidth(), getHeight()) / 2 * dScalar * (1 - (dEccentricty * Math.cos(dE)));
}
1
29 июля '14 в 11:55
источник

Если вы моделируете физику, я настоятельно рекомендую Box2D.
Это отличный физический симулятор, и он действительно сократит количество плиты котла, которое вам понадобится, с физикой, имитирующей.

0
02 февр. '10 в 21:58
источник

Основы астродинамики Бате, Мюллером и Уайтом по-прежнему требуют чтения у моей альма-матер для инженеров-аэрокосмических инженеров. Это, как правило, охватывает орбитальную механику тел на орбите Земли... но это, вероятно, уровень физики и математики, вам нужно будет начать понимать.

+1 для предложения @Stefano Borini для "всего, что написал Жан Миус".

-1
22 февр. '10 в 22:34
источник
Dear Friend here is the graphics code that simulate solar system

Kindly refer through it

/*Arpana*/

#include<stdio.h>
#include<graphics.h>
#include<conio.h>
#include<math.h>
#include<dos.h>
void main()
{
int i=0,j=260,k=30,l=150,m=90;
int n=230,o=10,p=280,q=220;
float pi=3.1424,a,b,c,d,e,f,g,h,z;
int gd=DETECT,gm;
initgraph(&gd,&gm,"c:\tc\bgi");
outtextxy(0,10,"SOLAR SYSTEM-Appu");
outtextxy(500,10,"press any key...");
circle(320,240,20);               /* sun */
setfillstyle(1,4);
floodfill(320,240,15);
outtextxy(310,237,"sun");
circle(260,240,8);
setfillstyle(1,2);
floodfill(258,240,15);
floodfill(262,240,15);
outtextxy(240,220,"mercury");
circle(320,300,12);
setfillstyle(1,1);
floodfill(320,298,15);
floodfill(320,302,15);
outtextxy(335,300,"venus");
circle(320,160,10);
setfillstyle(1,5);
floodfill(320,161,15);
floodfill(320,159,15);
outtextxy(332,150, "earth");
circle(453,300,11);
setfillstyle(1,6);
floodfill(445,300,15);
floodfill(448,309,15);
outtextxy(458,280,"mars");
circle(520,240,14);
setfillstyle(1,7);
floodfill(519,240,15);
floodfill(521,240,15);
outtextxy(500,257,"jupiter");
circle(169,122,12);
setfillstyle(1,12);
floodfill(159,125,15);
floodfill(175,125,15);
outtextxy(130,137,"saturn");
circle(320,420,9);
setfillstyle(1,13);
floodfill(320,417,15);
floodfill(320,423,15);
outtextxy(310,400,"urenus");
circle(40,240,9);
setfillstyle(1,10);
floodfill(38,240,15);
floodfill(42,240,15);
outtextxy(25,220,"neptune");
circle(150,420,7);
setfillstyle(1,14);
floodfill(150,419,15);
floodfill(149,422,15);
outtextxy(120,430,"pluto");
getch();
while(!kbhit())             /*animation*/
{
a=(pi/180)*i;
b=(pi/180)*j;
c=(pi/180)*k;
d=(pi/180)*l;
e=(pi/180)*m;
f=(pi/180)*n;
g=(pi/180)*o;
h=(pi/180)*p;
z=(pi/180)*q;
cleardevice();
circle(320,240,20);
setfillstyle(1,4);
floodfill(320,240,15);
outtextxy(310,237,"sun");

circle(320+60*sin(a),240-35*cos(a),8);
setfillstyle(1,2);
pieslice(320+60*sin(a),240-35*cos(a),0,360,8);
circle(320+100*sin(b),240-60*cos(b),12);
setfillstyle(1,1);
pieslice(320+100*sin(b),240-60*cos(b),0,360,12);
circle(320+130*sin(c),240-80*cos(c),10);
setfillstyle(1,5);
pieslice(320+130*sin(c),240-80*cos(c),0,360,10);
circle(320+170*sin(d),240-100*cos(d),11);
setfillstyle(1,6);
pieslice(320+170*sin(d),240-100*cos(d),0,360,11);
circle(320+200*sin(e),240-130*cos(e),14);
setfillstyle(1,7);
pieslice(320+200*sin(e),240-130*cos(e),0,360,14);
circle(320+230*sin(f),240-155*cos(f),12);
setfillstyle(1,12);
pieslice(320+230*sin(f),240-155*cos(f),0,360,12);
circle(320+260*sin(g),240-180*cos(g),9);
setfillstyle(1,13);
pieslice(320+260*sin(g),240-180*cos(g),0,360,9);
circle(320+280*sin(h),240-200*cos(h),9);
setfillstyle(1,10);
pieslice(320+280*sin(h),240-200*cos(h),0,360,9);
circle(320+300*sin(z),240-220*cos(z),7);
setfillstyle(1,14);
pieslice(320+300*sin(z),240-220*cos(z),0,360,7);
delay(20);
i++;
j++;
k++;
l++;
m++;
n++;
o++;
p++;
q+=2;
}
getch();
}
-4
21 марта '14 в 9:24
источник

Посмотрите другие вопросы по меткам или Задайте вопрос