【问题标题】:Interpolation of an object considering both acceleration and deceleration over time考虑随时间的加速度和减速度的对象插值
【发布时间】:2020-10-18 05:18:17
【问题描述】:

我正在用 Javascript 构建一个模拟器,并努力理解物理和运动学的基础知识,因为我毕业已经有一段时间了。无论如何,我有一个循环应该模拟时间,循环的每次迭代都等于 1 秒,我有一个对象,我想从点 A[150, 50])移动到点 B(@987654324 @)。该对象的最大速度为10,加速度为4.9,减速度为-4.9。我正在重新计算循环的每次迭代(1秒)的目标位置,但是当我必须减速时它不起作用,因为在某些时候速度是负的。 有没有什么公式可以用来计算插值,同时考虑从 A 点移动到 B 点每 x 秒的加速度和减速度?

这是我的代码的当前状态:

const math = require('mathjs');
const { distance } = require('mathjs');

let currentPos = [150, 51];
const targetPosition = [1, 1];

const MAX_SPEED = 10;
const BASE_ACCELERATION = 4.9;
let currentVelocity= 0;
let stopping = false;

const interpolate = (pos, velocity, target, acceleration, t) => {
    const d = math.distance(target, pos);
    const delta = math.subtract(target, pos);
    const ratio = math.divide(delta, d);

    const v = Math.min(velocity + (acceleration * t), MAX_SPEED);
    const newPos = move(pos, ratio, lerp(velocity, v, t));

    return { pos: newPos, d , v, ratio };
};

const move = (pos, ratio, velocity) => {
    return math.chain(ratio)
        .multiply(velocity)
        .add(pos)
        .done();
};

const lerp = (v0, v1, t) => {
    return v0 + t * (v1 - v0);
};

const getStopDistance = (v0, a) => v0 / 2 * a;


// Let's say I'm simulating 15 seconds 
for (let i = 0; i < 15; i++) {
    console.log(`####### sec ${i} #######`);
    console.log(`currentPos -> `, currentPos);
    console.log(`currentVelocity -> `, currentVelocity);
    console.log(`stopping -> `, stopping);

    const sd = getStopDistance(currentVelocity, BASE_ACCELERATION);
    const a = (stopping) ? -BASE_ACCELERATION : BASE_ACCELERATION;
    const it = interpolate(currentPos, currentVelocity, targetPosition, a, 1);

    if (it.d == 0)
        break;

    console.log('sd -> ', sd);
    console.log('it -> ', it);

    if (!stopping && sd >= it.d) {
        // Trying to break it down in 2 equations within 1 sec. The first with the current velocity and accelerations and the rest should be the time I should start stopping ?**strong text**
        const d1 = sd - it.d;
        const t1 = (2 * d1) / (currentVelocity + currentVelocity);
        const i1 = interpolate(currentPos, currentVelocity, targetPosition, BASE_ACCELERATION, t1);

        const t2 = 1 - t1;
        const i2 = interpolate(i1.pos, i1.v, targetPosition, -BASE_ACCELERATION, t2);

        console.log('d1 -> ', d1);
        console.log('t1 -> ', t1);
        console.log('i1 -> ', i1);
        console.log('t2 -> ', t2);
        console.log('i2 -> ', i2);

        stopping = true;
        currentPos = i2.pos;
        currentVelocity = i2.v;
    } else {
        currentPos = it.pos;
        currentVelocity = it.v;
    }
}

【问题讨论】:

  • 你是说粒子会加速到最大速度然后开始减速?还是加速和减速同时应用?
  • @QurakNerd 我希望粒子加速直到达到最大速度(除非它已经处于最大速度)并在到达 B 点之前减速。
  • 你的加速度是恒定的,直到达到最大速度?如果是这样,由于您的加速度取决于您是否已经达到最大速度,我认为没有一个简单的公式可以满足您的需求。相反,您需要将函数分成两部分,加速和减速,并且任何计算都需要检查它需要使用哪一个。我可以问一下您正在建模什么物理过程,因为基于速度的加速度突然变化并不常见
  • 是的,加速度和减速度都是常数。因为我每秒都在计算速度,所以我对如何使用公式感到困惑,以防粒子必须在同一秒内加速和减速。
  • 另外,你展示的不是模拟,而是一些方程的解。模拟采用现有的位置和速度,并以较小的时间增量更新这些值,直到达到目标。

标签: javascript interpolation game-physics physics kinematics


【解决方案1】:

让我们将问题背后的数学视为一维问题。让我们沿着连接起点和终点的直线找到对象的运动轮廓。

给定点之间的距离L、最大速度v_max 和可用的加速度和减速度a,运动分为三个状态。下面是总行驶距离x 和速度v 的数学计算(给出的是伪代码)

  • 加速

     t = 0 ... v_max/a
     x = 0.5*a*t^2
     v = a*t
    
  • 滑行

     t = v_max/a ... L/v_max
     x = t*v_max - 0.5*v_max^2/a
     v = v_max
    
  • 减速

     t = L/v_max ... v_max/a+l/v_max
     x = t*v_max - a*(L-t*v_max)^2/(2*v_max^2)-v_max^2/(2*a)
     v = v_max - a*(t - L/v_max) + v_max
    

这些是从标准运动学方程推导出来的,受最大速度和总行驶距离的限制。

【讨论】:

    【解决方案2】:

    根据您关于首先找到 A 和 B 之间距离的评论,我将在黑暗中进行拍摄,您可能正在寻找缓入缓出的“补间”功能。

    如果您知道从 A 到 B 的距离,并且您知道希望整个动画持续多长时间(即持续时间),那么您就不需要考虑加速。您可以根据从起始速度 (0) 到结束速度 (0) 的抛物线或二次曲线或正弦曲线或其他类型的曲线获得任何时间点的速度,其中最大速度和曲线峰值已确定由曲线的属性决定。

    这里显示了大量的输入/输出缓动函数: https://gizma.com/easing/

    如果您想根据已知的加速度和距离对此类曲线进行逆向工程,您可以分别用位置和距离替换t 时间和d 持续时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-28
      • 2011-01-10
      相关资源
      最近更新 更多