Java中的偏心向量在轨道移动时不精确

Java中的偏心向量在轨道移动时不精确,java,libgdx,game-physics,Java,Libgdx,Game Physics,我正在用java编写一个小的libgdx程序,这个程序的灵感来自Kerbal Space程序,我现在正在编写一个类来控制将对其施加力的对象。这些对象中的每一个都有一个速度矢量,该矢量由力矢量改变 该程序每秒运行60帧左右,每帧对改变速度的力进行1000次计算。(不过,我经常使用这个号码)。现在,这个程序非常简单,每次迭代都会施加和计算的唯一作用力来自地球 forcedub = ((gravConstanat*parentBody.getMass())/Math.pow(loc.distance

我正在用java编写一个小的libgdx程序,这个程序的灵感来自Kerbal Space程序,我现在正在编写一个类来控制将对其施加力的对象。这些对象中的每一个都有一个速度矢量,该矢量由力矢量改变

该程序每秒运行60帧左右,每帧对改变速度的力进行1000次计算。(不过,我经常使用这个号码)。现在,这个程序非常简单,每次迭代都会施加和计算的唯一作用力来自地球

 forcedub = ((gravConstanat*parentBody.getMass())/Math.pow(loc.distance(parentBody.getLoc()),2));
 force = new Point2D(((-1)*forcedub*Math.cos(a)),((-1)*forcedub*Math.sin(a)));
这会明显地改变速度,调整位置并继续循环。这个过程运行得很好,看起来很稳定。我已经连续几天没有运行它了,但即使在相对较高的偏心率下,轨道看起来也很稳定。不幸的是,我需要能够加快这个过程,这样就不需要2天的实时到达月球。所以我需要一个系统,使轨道“在轨道上”,而不需要重新计算每次迭代的力。一旦乘数值设置得太高,轨道就会分离

好消息是我已经有了这个系统,我只是不能在两者之间切换

我需要轨道上的一些值来在我的系统中执行此操作。(我知道有些值有点多余,但事实就是如此)

  • 半长轴
  • 半短轴
  • 偏心矢量
  • 偏心率
  • 真异常
  • 重点信息
切中要害的是,最大的问题是偏心向量/偏心率。我的“bake”函数是一个每次迭代都试图从轨道的状态向量计算值的函数,偏心率的值变化很大,在标准轨道中应该保持不变。向量的方向也是到处都是

我已经硬编码了一个物体,它的偏心率应该是.62,偏心率向量应该指向π,但是值在.25和.88之间,方向在π和π/3之间

下面是如何从状态向量获取eccvecc的两个版本,我已经尝试了这两个版本。它们都给出了完全相同的结果:

以下是整个课程: **初始距离为父实体左侧约900000 **母体质量为5.3*数学功率(10,22)

公共类对象{
字符串名;
质感;
雪碧雪碧;
B体父母体;
点2D loc;
点2D水平;
公共布尔加速;
双乘数;
静态双重力=6.67*数学功率(10,-11);
双半a,半b,ecc,w;
保护双t;
保护双质量;
保护双旋转;
保护双焦点;
公共对象(Cbody cb){
质量=1;
乘数=1;
旋转率=0;
父体=cb;
加速度=假;
cb.addKlob(本);
loc=新点2D((parentBody.getX()-900_000f),
(parentBody.getY());
vel=新点2D(02526.733);
sprite=textureAtlas.createSprite(名称);
setOrigin(sprite.getWidth()/2,sprite.getHeight()/2);
烘焙();
}
公共无效更新(浮动dt){
oneXupdate(dt);
烘焙();
}
私有无效oneXupdate(浮动dt){
int timesLooped=1000;
双a;
双钳;
点2D力;
点2D速度;
双dx;
双dy;
dt=dt/时间循环;
for(int i=0;i
对于精确浮动,double可能不是最好的数据类型-
public void bake(){
    double velSq = Math.pow(vel.distance(0,0),2);
    double r = loc.distance(parentBody.getLoc());
    double gm = gravConstanat*parentBody.getMass();

    Point2D posr = new Point2D(loc.getX()-parentBody.getX(), loc.getY()-parentBody.getY());

    Point2D calc1 = posr.scale((velSq/gm));
    Point2D calc2 = vel.scale((dotProd(posr,vel)/gm));
    Point2D calc3 = posr.scale(1/r);

    Point2D eccVecc = (calc1.minus(calc2)).minus(calc3);

    ecc = eccVecc.distance(0,0);

    w = Math.toRadians(90)-(Math.atan2(eccVecc.x(),eccVecc.y()));

    semiA = (gm*r)/(2*gm - r*velSq);
    semiB = semiA*(Math.sqrt((1-Math.pow(ecc,2))));
    focus = findFocus(semiA,semiB);

    System.out.println("ecc  " + ecc + " W " + w + " SEMI A " + semiA);
    System.out.println();
}
public class Klobject {

    String name;
    TextureAtlas textureAtlas;
    Sprite sprite;
    Cbody parentBody;
    Point2D loc;
    Point2D vel;
    public boolean acceleration;

    double MULTIPLIER;
    static double gravConstanat = 6.67*Math.pow(10,-11);

    double semiA, semiB, ecc, w;

    protected double t;
    protected double mass;
    protected double rotateRate;
    protected double focus;

    public Klobject(Cbody cb){

        mass = 1;
        MULTIPLIER = 1;
        rotateRate = 0;
        parentBody = cb;
        acceleration = false;
        cb.addKlob(this);

        loc = new Point2D((parentBody.getX() - 900_000f ),
                (parentBody.getY()));

        vel = new Point2D(0,2526.733);

        sprite = textureAtlas.createSprite(name);
        sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
        bake();
    }


    public void update(float dt){

        oneXupdate(dt);
        bake();

    }

    private void oneXupdate(float dt){

        int timesLooped = 1000;

        double a;
        double forcedub;
        Point2D force;
        Point2D velout;
        double dx;
        double dy;
        dt = dt/timesLooped;

        for (int i = 0; i < timesLooped; i++){

            velout = vel.scale(MULTIPLIER);

            dx =  (dt*velout.getX());
            dy =  (dt*velout.getY());

            loc = new Point2D(loc.getX()+dx, loc.getY()+dy);

            a = Math.atan2(loc.getX()-parentBody.getX(), loc.getY()-parentBody.getY());
            a = Math.toRadians(90)-a;

            forcedub = ((gravConstanat*parentBody.getMass())/Math.pow(loc.distance(parentBody.getLoc()),2));
            force = new Point2D(((-1)*forcedub*Math.cos(a)),((-1)*forcedub*Math.sin(a)));


            force = force.scale(MULTIPLIER*MULTIPLIER);

            velout = velout.plus(new Point2D(force.getX()*dt,force.getY()*dt));

            vel = velout.scale(1/MULTIPLIER);


        }

    }


    public void bake(){
        double velSq = Math.pow(vel.distance(0,0),2);
        double r = loc.distance(parentBody.getLoc());
        double gm = gravConstanat*parentBody.getMass();

        Point2D posr = new Point2D(loc.getX()-parentBody.getX(), loc.getY()-parentBody.getY());

        Point2D calc1 = posr.scale((velSq/gm));
        Point2D calc2 = vel.scale((dotProd(posr,vel)/gm));
        Point2D calc3 = posr.scale(1/r);

        Point2D eccVecc = (calc1.minus(calc2)).minus(calc3);

        ecc = eccVecc.distance(0,0);

        w = Math.toRadians(90)-(Math.atan2(eccVecc.x(),eccVecc.y()));

        semiA = (gm*r)/(2*gm - r*velSq);
        semiB = semiA*(Math.sqrt((1-Math.pow(ecc,2))));
        focus = findFocus(semiA,semiB);

        System.out.println("ecc  " + ecc + " W " + w + " SEMI A " + semiA);
        System.out.println();


    }

    public double findFocus(double a, double b){
        return Math.sqrt(a*a - b*b);
    }

    public double getX(){
        return loc.getX();
    }
    public double getY(){
        return loc.getY();
    }
    public void setRotateRate(double rr){rotateRate = rr;}
    public String getName(){
        return name;
    }
    public Sprite getSprite(){
        return sprite;
    }
    public void setMultiplier(double mult){
        MULTIPLIER = mult;
    }
    public Point2D getLoc(){
        return loc;
    }
    public void setLoc(Point2D newLoc){
        loc = newLoc;
    }

    public double dotProd(Point2D a, Point2D b){
        return a.x()*b.x() + a.y()+b.y();
    }
}