Math 无法在我的太阳系模型上获得正确的轨道

Math 无法在我的太阳系模型上获得正确的轨道,math,simulation,physics,orbital-mechanics,Math,Simulation,Physics,Orbital Mechanics,我正在制作一个太阳系模型,只使用p5.js,不使用box2D,尽管语言/平台对这个问题并不重要。此外,用于描述问题的所有数字和变量并非100%准确,但行为是相同的 我使用牛顿公式(F=G Mm/r^2)来计算两个物体之间的相互引力,比如说A和B。现在为了吸引A朝向B,我将这个相互引力除以A的质量来计算A上的向心加速度,然后乘以一个指向B的单位向量。将这个关系应用到A和B上,它们都体验到彼此的吸引力,与它们的质量成反比 现在,如果我让它们相互作用,A的质量=1000个单位,B的质量=10个单位,正

我正在制作一个太阳系模型,只使用p5.js,不使用box2D,尽管语言/平台对这个问题并不重要。此外,用于描述问题的所有数字和变量并非100%准确,但行为是相同的

我使用牛顿公式(F=G Mm/r^2)来计算两个物体之间的相互引力,比如说A和B。现在为了吸引A朝向B,我将这个相互引力除以A的质量来计算A上的向心加速度,然后乘以一个指向B的单位向量。将这个关系应用到A和B上,它们都体验到彼此的吸引力,与它们的质量成反比

现在,如果我让它们相互作用,A的质量=1000个单位,B的质量=10个单位,正如预期的那样,A不会被拉,保持静止,但B会向A加速。现在发生的是,当B到达中心,朝相反的方向飞行,它比我最初设定的距离更远。这在每个加速周期中都会不断滚雪球,并且在某个时候会从屏幕上消失。这似乎违反了能量守恒定律,或者是我的物理学中的一些重大缺陷

好的,然后继续第二个问题,我们有相同的物体和质量。不同的是,我给了B(较轻的物体)一个初始速度,某个值,比如x轴正方向的x。现在我把B垂直于A的x轴,让它们相互作用。这一次,B在一种椭圆轨道上运动,有两个问题。第一个是A(较重的物体)不在椭圆的某个焦点上,而是在椭圆的正中心,第二个是随着时间的推移,轨道本身开始旋转。我觉得这个旋转是由提供的初始速度引起的,只是为了澄清一下,速度只是最初应用的,而不是应用在每一帧上。该轨道的轨迹如下所示:

还请注意,每个轨道的最大范围比前一个轨道大一点。这几乎是之前的问题与此混合在一起

接下来我正在尝试的是,应用一个与运动相切的恒定速度,以及重力向心加速度。让我知道这是否有用,或者我的整个方法是否需要改变

这也是我的模拟代码:

var constG;
var axisX;
var planets = [];

function setup() {
  createCanvas(500, 500);
  //createCanvas(displayWidth, displayHeight);
  //fullscreen(true);
  constG = 0.0001;//6.67 * pow(10, -11);
  axisX = createVector(1, 0);
}

function draw() {
  background(0, 5);
  for (var planet of planets) {   
    planet.update();
    planet.display();
  }

  for (var i = 0; i < planets.length; i++){
    var selfPlanet = planets[i];
    for (var j = 0; j < planets.length; j++){
      if (j == i){
        continue;
      }
      var otherPlanet = planets[j];
      var gravitalAcc = calcGravitalAcc(selfPlanet, otherPlanet);
      selfPlanet.applyForce(gravitalAcc);
    }
  }
  
  if (planets.length > 0){
    planets[0].radius = 15;
    planets[0].mass = 100;    // this just makes the first planet heavy so that i 
    planets[0].vel.mult(0);   // can test stuff while making it the sun.
    planets[0].speed = 0;
  }
}

function mousePressed() {
    planets.push(new CelestialBody(mouseX, mouseY, 7));
}

function calcGravitalAcc(self, other){
  var tempVec = p5.Vector.sub(other.pos, self.pos);
  return tempVec.normalize().mult(constG * (other.mass)/pow(tempVec.mag(), 2))
}

第一个问题通常是由于模拟的时间步长过大,加上缺少碰撞处理造成的。当你的物体靠近时,力会变大,模拟中的增量步骤变得太大,所以下一个迭代位置是碰撞后,通常会离碰撞前更远,所以破断力会变小,从而在时间上导致越来越大的轨道

要解决此问题,您可以执行以下操作:

  • 添加冲突处理
  • 将最大速度或力限制在某个合理的限度内
我从来没有遇到过你的第二个问题,没有代码我甚至猜不到。。。除舍入误差外

看看这个:

还有所有的子链接在那里

[Edit1]在我看到你的代码后

代码的架构看起来还可以。问题是你的公式有点偏离。应该是:

vel+=acc*dt;
pos+=vel*dt;
acc=0.0;
而不是你的:

pos+=vel;
vel+=acc;
acc=0.0;

因此,您的顺序错误,缺少
*dt
,其中
dt
是时间步长。因此,无论您如何更改计时器间隔,结果都是相同的(只是速度较慢/较快),并且加速度方向的应用比导致轨道旋转的时间晚一步(因为加速度是从不同的位置计算的,而不是应用于最终位置,因此其方向始终为关闭).

对于第一个问题,我的时间步长非常低,我确实尝试在小数点后添加更多的零,但我想即使是最小的错误也会发生。好的,现在我将限制这些值。如果您想查看我的代码,我将编辑我的问题并将其放在那里。修复顺序确实有很大帮助,但与dt相乘会使其变得非常不可预测。我也尝试过dt的超高和超低值。尽管我读了这篇关于轨道力学的论文,并简单地总结了我的问题2,但没关系,螺旋呼啦圈式的方向改变并不是一个错误,而是现实中发生的事情。唯一的区别是,这种变化可以忽略不计。我改变了一些价值观,并在我的G工作,现在它的工作相当好。感谢您花时间帮助我。@Ontropy
dt
[s]
中,但为了使其工作,您需要将质量G恒定,初始位置和速度设置为有效值/单位。。。你所描述的轨道转动不是牛顿-达朗贝尔物理学中的情况,它是由相对论效应引起的,也不应该发生在你当前的模拟中。@n如果你看一看关于太阳系模拟的链接QA
G=6.67384e-11;v=sqrt(G*M/a);//轨道速度;T=sqrt((4.0*M_-PI*M_-PI*a*a*a)/(G*(M+M));//轨道周期
可用于生成初始位置和速度。。。
pos+=vel;
vel+=acc;
acc=0.0;