计算截距的轨道对于给定的速度。(Calculate an intercept to an orbit

2019-09-30 21:31发布

背景:试图写一个游戏,“超光速”旅行是由重力和加速度的影响是即时的。

如何计算,其中一颗行星将是,由于开普勒轨道对地球和船舶当前位置和其最大FTL速度。 (以m / s)

我能得到这个星球对于给定的日期时间的位置,但我在努力弄清楚如何计算,其中一颗行星会,以及在何处船送,不追逐周围的轨道上的行星。

Answer 1:

我会遍历...

  1. 计算行星之间的距离和船舶的当前位置

    从您计算出有多少时间你的船,需要满足的目标,如果目标是静态的(不动)。 让我们把这个时间t

  2. 计算行星位置actual_time+t和计算t这个新职位

    记得去年t让叫它t0 。 然后计算新t以同样的方式在#1但之后地球的位置t

  3. 环#2

    停止,如果fabs(t-t0)<accuracy

这种迭代的解决方案应该是更接近于发现t ,除非你的星球移动过快和/或船实在是太远或过慢(最初在每次迭代t是显著的部分或大于行星回归年更大)。 在这种情况下,你通常首先跳进恒星系统,然后跳转到行星(如在原来的精英)。

对于模糊的行星运动(如太小轨道周期),你会需要不同的方法,但要意识到这种情况下,就意味着是地球非常接近星或非常沉重的系统质量中心像黑洞...

在以恒定速度FTL它的代码是这样的:

vec3 pp,ps=vec3(?,?,?); // planet and ship positions
double t,t0,time;

time=actual_time(); t=0.0;
for (int i=0;i<100;i++) // just avoiding infinite loop in case t/planet_orbit_period>=~0.5
 {
 t0=t;
 pp = planet_position(time+t);
 t=Length(pp-ps)/ship_FTL_speed;
 if (fabs(t-t0)*ship_FTL_speed<=ship_safe_FTL_distance) break;
 }

这应该收敛很快(如5-10次迭代应该足够)现在t应保持必要的旅行和时间pp应该保持你的船应该去的位置。 如何过,如果i>=100无解被发现,所以你首先需要去接近系统,或使用更快的FTL或使用不同的方法,但不应该是常见的恒星系统FTL的旅行时间应该远远的情况下小于目标轨道周期...

顺便说一句。 这个你可能会感兴趣:

  • 是否有可能做出现实正体太阳能系统仿真的规模和质量的关系吗?

比FTL翻译驱动慢[EDIT1]

我给它一点点教,改变算法中位。 首先,它检查沿整个地球周期与一些步骤(每期100分)的所有位置,并记住前往该船无论行驶过程中传递的行星的周期最接近的时间。 然后,只需“递归”检查与小角度步左右最佳位置。 这里的结果预览:

而更新的源(全VCL应用程序代码,因此只使用/端口您需要什么,忽略其他的)

//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "win_main.h"
#include "GLSL_math.h"  // just for vec3
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMain *Main;
//---------------------------------------------------------------------------
// constants
const double deg=M_PI/180.0;
const double t_day=60.0*60.0*24.0;
// view
double view_x0=0.0;
double view_y0=0.0;
double zoom=1.0;
// simulation
double sim_t=0.0,sim_dt=0.01*t_day;
//---------------------------------------------------------------------------
void toscr(double &x,double &y)
    {
    x*=zoom; x+=view_x0;
    y*=zoom; y+=view_y0;
    }
//---------------------------------------------------------------------------
class planet                // Kepler body simplified to 2D axis aligned. For fully 3D orbit add mising orbital parameters and equations
    {
public:
    // input parameters
    double a,b,t0,T;        // major axis,minor axis, time where M=E=0.0 deg, orbital period
    // computet parameters
    double c1,c2,e;

    void ld(double _a,double _b,double _t0,double _T)
        {
        // copy input orbital parameters
        a=_a;
        b=_b;
        t0=_t0;
        T=_T;
        // prepare orbital constants
        e=1.0-((b*b)/(a*a));                // eccentricity
        if (e>=1.0) e=0;                    // wrong e
        c1=sqrt((1.0+e)/(1.0-e));           // some helper constants computation
        c2=a*(1-e*e);
        //b=a*sqrt(1.0-e);
        }
    vec3 position(double t) // actual position relative to center mass of the system
        {
        int q;
        vec3 p;
        double E,V,r,M;
        // compute mean orbital position M [rad] from time t
        M=(t-t0)/T;
        M-=floor(M);
        M*=2.0*M_PI;
        // compute real orbital position E [rad] from M
        for (E=M,q=0;q<20;q++) E=M+e*sin(E);// Kepler's equation
        // heliocentric ellipse
        V=2.0*atan(c1*tan(E/2.0));
        r=c2/(1.0+e*cos(V));
        p.x=r*cos(V);
        p.y=r*sin(V);
        p.z=0.0;
        return p;
        }
    void draw_orbit(TCanvas *scr)
        {
        int i;
        double ang,x,y,r,V,E;
        x=a; y=0; toscr(x,y);
        for (i=2,E=0.0;i;E+=3.6*deg)
            {
            if (E>=2.0*M_PI) { E=0.0; i=0; }
            V=2.0*atan(c1*tan(E/2.0));
            r=c2/(1.0+e*cos(V));
            x=r*cos(V);
            y=r*sin(V);
            toscr(x,y);
            if (i==2){ scr->MoveTo(x,y); i=1; }
             else      scr->LineTo(x,y);
            }
        }
    };
//---------------------------------------------------------------------------
class ship                          // Space ship with translation propulsion
    {
public:
    vec3 pos,dir;                   // position and translation direction
    double spd,tim;                 // translation speed and time to translate or 0.0 if no translation
    ship() { pos=vec3(0.0,0.0,0.0); dir=pos; spd=0.0; tim=0.0; }
    void update(double dt)          // simulate dt time step has passed
        {
        if (tim<=0.0) return;
        if (dt>tim) { dt=tim; tim=0.0; }
         else                 tim-=dt;
        pos+=spd*dt*dir;
        }
    void intercept(planet &pl)      // set course for planet pl intercept
        {
        if (spd<=0.0) { tim=0.0; return; }
        const double d=1000000.0;   // safe distance to target
/*
        // [Iteration]
        int i;
        vec3 p;
        double t0;
        for (tim=0.0,i=0;i<100;i++)
            {
            t0=tim;
            p=pl.position(sim_t+tim);
            tim=length(p-pos)/spd;
            if (fabs(tim-t0)*spd<=d) break;
            }
        dir=normalize(p-pos);
*/
        // [search]
        vec3 p;
        int i;
        double tt,t,dt,a0,a1,T;
        // find orbital position with min error (coarse)
        for (a1=-1.0,t=0.0,dt=0.01*pl.T;t<pl.T;t+=dt)
            {
            p=pl.position(sim_t+t);                     // try time t
            tt=length(p-pos)/spd;
            a0=tt-t; if (a0<0.0) continue;              // ignore overshoots
            a0/=pl.T;                                   // remove full periods from the difference
            a0-=floor(a0);
            a0*=pl.T;
            if ((a0<a1)||(a1<0.0)) { a1=a0; tim=tt; }   // remember best option
            }
        // find orbital position with min error (fine)
        for (i=0;i<3;i++)                               // recursive increase of accuracy
         for (a1=-1.0,t=tim-dt,T=tim+dt,dt*=0.1;t<T;t+=dt)
            {
            p=pl.position(sim_t+t);                     // try time t
            tt=length(p-pos)/spd;
            a0=tt-t; if (a0<0.0) continue;              // ignore overshoots
            a0/=pl.T;                                   // remove full periods from the difference
            a0-=floor(a0);
            a0*=pl.T;
            if ((a0<a1)||(a1<0.0)) { a1=a0; tim=tt; }   // remember best option
            }
        // direction
        p=pl.position(sim_t+tim);
        dir=normalize(p-pos);
        }
    };
//---------------------------------------------------------------------------
planet pl;
ship sh;
//---------------------------------------------------------------------------
void TMain::draw()
    {
    if (!_redraw) return;
    double x,y,r=3;
    vec3 p;

    // clear buffer
    bmp->Canvas->Brush->Color=clBlack;
    bmp->Canvas->FillRect(TRect(0,0,xs,ys));

    // Star
    bmp->Canvas->Pen->Color=clYellow;
    bmp->Canvas->Brush->Color=clYellow;
    x=0; y=0; toscr(x,y);
    bmp->Canvas->Ellipse(x-r,y-r,x+r,y+r);
    // planet
    bmp->Canvas->Pen->Color=clDkGray;
    pl.draw_orbit(bmp->Canvas);
    bmp->Canvas->Pen->Color=clAqua;
    bmp->Canvas->Brush->Color=clAqua;
    p=pl.position(sim_t);
    x=p.x; y=p.y; toscr(x,y);
    bmp->Canvas->Ellipse(x-r,y-r,x+r,y+r);
    // ship
    bmp->Canvas->Pen->Color=clRed;
    bmp->Canvas->Brush->Color=clRed;
    p=sh.pos;
    x=p.x; y=p.y; toscr(x,y);
    bmp->Canvas->Ellipse(x-r,y-r,x+r,y+r);

    // render backbuffer
    Main->Canvas->Draw(0,0,bmp);
    _redraw=false;
    }
//---------------------------------------------------------------------------
__fastcall TMain::TMain(TComponent* Owner) : TForm(Owner)
    {
    pl.ld(1000000000.0,350000000.0,0.0,50.0*t_day);
    sh.pos=vec3(-3500000000.0,-800000000.0,0.0);
    sh.spd=500.0;   // [m/s]
    sh.intercept(pl);

    bmp=new Graphics::TBitmap;
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    pyx=NULL;
    _redraw=true;
    }
//---------------------------------------------------------------------------
void __fastcall TMain::FormDestroy(TObject *Sender)
    {
    if (pyx) delete[] pyx;
    delete bmp;
    }
//---------------------------------------------------------------------------
void __fastcall TMain::FormResize(TObject *Sender)
    {
    xs=ClientWidth;  xs2=xs>>1;
    ys=ClientHeight; ys2=ys>>1;
    bmp->Width=xs;
    bmp->Height=ys;
    if (pyx) delete[] pyx;
    pyx=new int*[ys];
    for (int y=0;y<ys;y++) pyx[y]=(int*) bmp->ScanLine[y];
    _redraw=true;

    view_x0=xs-(xs>>3);
    view_y0=ys2;
    zoom=double(xs2)/(2.5*pl.a);

    // draw(); Sleep(5000);
    }
//---------------------------------------------------------------------------
void __fastcall TMain::FormPaint(TObject *Sender)
    {
    _redraw=true;
    }
//---------------------------------------------------------------------------
void __fastcall TMain::tim_redrawTimer(TObject *Sender)
    {
    for (int i=0;i<10;i++)
        {
        sh.update(sim_dt);
        sim_t+=sim_dt;
        if (sh.tim<=0.0) sim_dt=0.0; // stop simulation when jump done
        }
    if (sim_dt>0.0) _redraw=true;
    draw();
    }
//---------------------------------------------------------------------------

最重要的东西是在两个班planet,ship然后sim_t是实际的模拟时间和sim_dt是模拟的时间步长。 在这种情况下,模拟船之后停止到达目的地。 所述ship::tim是行驶左的在所计算的时间ship::intercept()与预置速度沿着。 更新应该呼吁每个模拟时间步长...



文章来源: Calculate an intercept to an orbit for a given speed.