【问题标题】:Plotting Space Ship Distance over Time绘制随时间变化的太空船距离
【发布时间】:2016-10-20 05:21:08
【问题描述】:

我正在研究使用力、加速度和质量在笛卡尔地图上进行点对点宇宙飞船旅行的一些逻辑。船将以 1G 的速度加速并燃烧到目的地,在中途标记处翻转 180 度,并以 1G 的速度减速到达目的地的相对停靠点。

我遇到的问题是使用船在加速或减速时所经过的时间来确定 (x, y) 坐标。

这是ship 的规格:

ship = {
  mass: 135000, // kg
  force: 1324350, // Newtons
  p: { x: -1, y: -5 } // (x,y) coordinates
}

dest: {
  p: { x: 15, y: 30 }  // (x,y) coordinates
}

对于问题的第一部分,我计算到达目的地的时间:

var timeToDestination = function(ship, dest) {

  // calculate acceleration (F = ma)
  var acceleration = ship.force / ship.mass; // ~9.81 (1G)

  // calculate distance between 2 points (Math.sqrt((a - x)^2+(b - y)^2))
  var totalDistance = Math.sqrt(
    Math.pow(dest.p.x - ship.p.x, 2) + 
    Math.pow(dest.p.y - ship.p.y, 2)
  ); // 38.48376280978771

  // multiply grid system to galactic scale
  var actualDistance = totalDistance * 1e9; // 1 = 1Mkm (38,483,763km) Earth -> Venus

  // determine the mid-point where ship should flip and burn to decelerate
  var midPoint = actualDistance / 2;

  // calculate acceleration + deceleration time by solving t for each: (Math.sqrt(2d/a))
  return Math.sqrt( 2 * midPoint / acceleration ) * 2; // 125,266s or 34h or 1d 10h
}

第二部分有点棘手,在增量时间之后获取 (x, y) 坐标。这就是我卡住的地方,但这是我目前所拥有的:

var plotCurrentTimeDistance = function(ship, dest, time) {

  // recalculate acceleration (F = ma)
  var acc = ship.force / ship.mass; //~9.81m/s^2

  // recalculate total distance
  var distance = Math.sqrt(
    Math.pow(dest.p.x - ship.p.x, 2) + 
    Math.pow(dest.p.y - ship.p.y, 2)
  ) * 1e9; // 38,483,762,810m

  // get distance traveled (d = (1/2) at^2)
  var traveled = (acc * Math.pow(time, 2)) / 2;

  // get ratio of distance traveled to actualDistance
  var ratio = traveled / distance;

  // midpoint formula to test @ 50% time ((x+a)/2,(y+b)/2)
  console.log({ x: (ship.p.x+dest.p.x)/2, y: (ship.p.y+dest.p.y)/2})

  // get the point using this formula (((1−t)a+tx),((1−t)b+ty))
  return { 
    x: (( 1 - ratio ) * ship.p.x) + (ratio * dest.p.x), 
    y: (( 1 - ratio ) * ship.p.y) + (ratio * dest.p.y) 
  };
}

@ 50% 时间,62,633s 点返回为 (~7, ~12.5),与返回为 (~7, ~12.5) 的中点公式相匹配。但是,您输入的任何其他距离/时间都将大错特错。我的猜测是加速度会打乱计算,但我不知道如何更改公式以使其工作。感谢您的宝贵时间。

【问题讨论】:

  • // get distance travelled (d = (1/2) at^2) var travelled = (acc * Math.pow(time, 2)) / 2; distance 不用作计算中的变量? (d = (1/2) at^2 的预期结果是什么? time plotCurrentTimeDistancetimeToDestination 的返回值吗?
  • travelled 用于确定plotCurrentTimeDistance() 函数的比率。 (d = (1/2) at^2 返回 n 秒后经过的距离为 time
  • timeplotCurrentTimeDistance Math.sqrt( 2 * midPoint / acceleration ) * 2 是从 timeToDestination 返回的吗?为什么在计算结束时包含* 2,而/ 2 位于(acc * Math.pow(time, 2)) / 2?计算中的唯一动态变量是acc
  • 不,time 是动态变量。您正试图根据船在一定数量的time 后行驶的距离来确定笛卡尔地图(x,y) 上的点。第一个*2 只是将距离的两半(加速+减速)相加(我们将距离一分为二)。 /2 只是重新排列公式来解决时间而不是距离。还是一样的公式。

标签: javascript math physics game-physics


【解决方案1】:

首先,您说distance 是总距离,但实际上是从船到目的地的距离。我不完全理解你的计算计划,所以我会在下面提出一些不同的建议。

让我们称起始位置为start,它有一个x 和y 坐标:start.xstart.y。与end 类似。

现在,要使这样的模拟工作,我们还需要速度作为船上的属性,所以

ship = {
    ...
    v : {x : 0, y : 0}
}

它将从休息开始,它应该达到休息。理想情况下,它应该有加速度a 用于一般运动,但我们现在可以跳过它。我们会有两种不同的行为

  1. 船从静止状态开始,以 9.8 m/s^2 的速度向目标加速,直到到达半点。
  2. 船在中点以v 的速度开始,以-9.8 m/s^2 的速度向目标方向减速,直到速度为0。现在我们应该已经到达目标了。

我们使用v = v_start + a*time从加速度获取速度,并使用x = x_start + v*time从速度获取位置。那么船的当前位置是针对这两种情况的

// Case 1
current = start + a*time*time
// the above is due to the fact that
//     current = start + v*time
// and the fact that v = v_start + a*time as I wrote previously,
// with v_start.x = v_start.y = 0

//Case 2
current = midpoint + (v_at_midpoint - a*time_since_midpoint)*time_since_midpoint

请注意这里的startcurrenta 是向量,因此它们将有一个xy(可能还有z)坐标。

通过以下算法得到的加速度

 a = (start - end)/totalDistance * 9.81 // 9.81 is the desired acceleration -- change it to whatever you want

如果您想了解上面的实际含义,它会计算所谓的unit vector,它告诉我们力指向的方向

您现在需要做的事情如下:

  1. 计算总距离和加速度

  2. 根据函数中的输入 time 确定您是在情况 1 还是 2。

  3. 到达中点后,存储速度和到达那里所需的时间,并使用它来确定情况 2 中的运动。

  4. 一旦到达目的地就停下来,否则你最终会回到起点!

祝你好运!

P.S 我还应该在这里注意,这没有考虑到special relativity,所以如果你的距离太远,你将获得非物理速度。但是,如果您想考虑到这一点,就会变得更加混乱。

【讨论】:

  • 谢谢@pingul,我没有走矢量路线,因为我无法让它工作,但你确实给了我需要了解如何计算加速和减速期间距离的见解.我在下面发布了我的答案作为sn-p。你介意看看并运行sn-p。我没有完全理解你的答案,但我还是赞成它,因为我确实使用了它的主要部分。
【解决方案2】:

感谢@pingul,我能够从他的建议中得到答案。

var ship = {
  mass: 135000,
  force: 1324350,
  accel: 0,
  nav: {
  	startPos: { x: 0, y: 0 },
    endPos: { x: 0, y: 0 },
  	distanceToDest: 0,
    distanceTraveled: 0,
    departTime: 0,
    timeToDest: 0,
    arriveTime: 0,
    startDeceleration: 0
  }
};

var log = [];
var start = { x: -1, y: -5 };
var end = { x: 15, y: 30 };

var updateLog = function() {
 document.getElementById('ship').textContent = JSON.stringify(ship, null, 2);
 document.getElementById('pos').textContent = JSON.stringify(log, null, 2);
}

var plotCourse = function(ship, start, end) {

  // calculate acceleration (F = ma)
  var acceleration = ship.force / ship.mass; // ~9.81 (1G)

  // calculate distance between 2 points (Math.sqrt((a - x)^2+(b - y)^2))
  var totalDistance = Math.sqrt(
    Math.pow(end.x - start.x, 2) + 
    Math.pow(end.y - start.y, 2)
  ); // 38.48376280978771

  // multiply grid system to galactic scale
  var actualDistance = totalDistance * 1e9; // 1 = 1Mkm (38,483,763km) Earth -> Venus

  // determine the mid-point where ship should flip and burn to decelerate
  var midpoint = actualDistance / 2;
  
  // calculate acceleration + deceleration time by solving t for each: (Math.sqrt(2d/a))
  var time = Math.sqrt( 2 * midpoint / acceleration ) * 2; // 125,266s or 34h or 1d 10h
  
  // load data into ship nav
  ship.nav = {
  	startPos: start,
    endPos: end,
  	distanceToDest: actualDistance,
    timeToDest: time,
    startDeceleration: time / 2
  }
  ship.accel = acceleration

  //log it
	updateLog();  
};

var goUnderway = function(ship) {
	var arrivalEl = document.getElementById('arrivalTime');
  
	// set depart and arrive times
  var timeToDest = ship.nav.timeToDest * 1000; // convert to ms
  ship.nav['departTime'] = moment().valueOf(); // returns now as unix ms
  ship.nav['arriveTime'] = moment(ship.nav.departTime).add(timeToDest).valueOf();
  
  //log it
  arrivalEl.textContent = 'Your ship will arrive ' + moment(ship.nav.arriveTime).calendar();
	updateLog();  
};

var getPosition = function(ship, date) {
	var currentTime = date ? moment(date).valueOf() : moment().valueOf() // unix ms
  var elapsedTime = (currentTime - ship.nav.departTime) / 1000; // convert to s
  var remainingTime = (ship.nav.arriveTime - currentTime) / 1000;  // convert to s
  var distanceAtMidpoint = 0;
  var timeSinceMidpoint = 0;
  var pos = { x: 0, y: 0 };
  
  // calculate velocity from elapsed time
	if (elapsedTime < ship.nav.startDeceleration) {
  
  	// if ship is accelerating use this function
    ship.nav.distanceTraveled = 0 + ship.accel * Math.pow(elapsedTime, 2) / 2;
  } else if (elapsedTime > ship.nav.startDeceleration) {
  
  	// else if ship is decelerating use this function
  	distanceAtMidpoint = 0 + ship.accel * Math.pow(ship.nav.startDeceleration, 2) / 2; // distance at midpoint
    timeSinceMidpoint = elapsedTime - ship.nav.startDeceleration;
  	ship.nav.distanceTraveled = distanceAtMidpoint + ship.accel * Math.pow(timeSinceMidpoint, 2) / 2;
  }
  
  if (remainingTime <= 0) {
  	ship.force = ship.vel = ship.accel = 0;
    pos = ship.nav.endPos;
  } else {
    // get ratio of distance traveled to actualDistance
    var ratio = ship.nav.distanceTraveled / ship.nav.distanceToDest;
  	// get the point using this formula (((1−t)a+tx),((1−t)b+ty))
    pos = { 
      x: (( 1 - ratio ) * start.x) + (ratio * end.x), 
      y: (( 1 - ratio ) * start.y) + (ratio * end.y) 
    };
  }
  
  log.push({
  	timestamp: moment(currentTime),
    pos: pos
  })
  
  //log it
  updateLog();
};

plotCourse(ship, start, end);
goUnderway(ship);
for (var i = 0; i < 35; i++) {
	getPosition(ship, moment().add(i, 'hour'));
}
pre {
  outline: 1px solid #ccc;
  padding: 5px;
  margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>
Ship: <span id="arrivalTime"></span>
<pre id="ship"></pre> Last Known Positions:
<pre id="pos"></pre>

【讨论】:

  • 您在什么方面寻找 cmets?我不确定您的代码是否按预期工作,但我预计该比率会在 [0, 1] 中,但似乎并非如此。
猜你喜欢
  • 1970-01-01
  • 2014-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-13
  • 1970-01-01
相关资源
最近更新 更多