Интерполяция объекта с учетом как ускорения, так и замедления во времени

Я создаю симулятор на Javascript и изо всех сил пытаюсь понять основы физики и кинематики, так как прошло некоторое время с тех пор, как я закончил учебу. В любом случае, у меня есть цикл, который должен имитировать время, и каждая итерация цикла равна 1 секунде, и у меня есть объект, который я хочу переместить из точки A ([150, 50]) в точку B ([1, 1]). Объект имеет максимальную скорость 10, ускорение 4.9 и замедление -4.9. Я пересчитываю целевую позицию на каждой итерации цикла (1 сек.), но это не работает, когда мне приходится замедляться, потому что в какой-то момент скорость становится отрицательной. Есть ли какая-либо формула, которую я могу использовать для расчета интерполяции, учитывающей как ускорение, так и замедление каждые x секунд при перемещении из точки A в точку B?

Вот текущее состояние моего кода:

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;
    }
}

person fgoncalves    schedule 27.06.2020    source источник
comment
Вы говорите, что частица разгонится до максимальной скорости, а затем начнет замедляться? Или и ускорение, и замедление применяются вместе?   -  person QurakNerd    schedule 27.06.2020
comment
@QurakNerd Я хочу, чтобы частица ускорялась, пока не достигнет максимальной скорости (если только она уже не на максимальной скорости), и замедлялась, прежде чем добраться до точки B.   -  person fgoncalves    schedule 27.06.2020
comment
И ваше ускорение постоянно, пока не достигнет максимальной скорости? Если это так, поскольку ваше ускорение зависит от того, достигли вы уже максимальной скорости или нет, я не думаю, что существует простая формула, которая даст вам то, что вам нужно. Вместо этого вам нужно будет разделить функцию на 2 части, ускоряющую и замедляющую, и любой расчет должен проверять, какую из них нужно использовать. Могу я спросить, какой физический процесс вы моделируете, потому что резкое изменение ускорения в зависимости от скорости не является обычным явлением?   -  person QurakNerd    schedule 27.06.2020
comment
Да, ускорение и замедление являются константами. Поскольку я рассчитываю скорость каждую секунду, я не понимаю, как использовать формулы на случай, если в течение одной секунды частица должна ускоряться и замедляться.   -  person fgoncalves    schedule 27.06.2020
comment
Что я делаю, так это сначала нахожу расстояние между точками A и B, а затем вычисляю расстояние до остановки с учетом текущей скорости и ускорения. Каждую секунду я проверяю, больше ли оставшееся расстояние для следующей интерполяции, чем расстояние до остановки. Если это так, я разбиваю интерполяцию на 2 части в течение одной секунды. Первая часть ускоряется, если еще не на максимальной скорости), а вторая замедляется. На следующей итерации я буду замедляться, пока не достигну точки B.   -  person fgoncalves    schedule 27.06.2020
comment
для постоянных ускорений вам нужно найти уравнения SUVAT, если в данную секунду ваше ускорение постоянно, это будет просто. Если нет, вам придется разбить вторую часть на две части и использовать несколько уравнений SUVAT.   -  person QurakNerd    schedule 27.06.2020
comment
Чего я здесь не понимаю, так это того, что скорость — это вектор, а ускорение — это скаляр. В каком направлении вы прикладываете ускорение, чтобы достичь цели? Это предполагает, что объект НЕ обращен прямо к цели, и ему нужно изогнуться, чтобы добраться туда.   -  person JAlex    schedule 07.07.2020
comment
Кроме того, то, что вы показываете, НЕ является симуляцией, а является решением некоторых уравнений. Моделирование берет существующее положение и скорость и обновляет эти значения с небольшим приращением времени, пока цель не будет достигнута.   -  person JAlex    schedule 07.07.2020


Ответы (2)


Давайте рассмотрим математику, стоящую за проблемой, как одномерную проблему. Найдем профиль движения объекта по прямой, соединяющей начальную и конечную точки.

Учитывая расстояние между точками 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
    

Они были получены из стандартных уравнений кинематики с учетом ограничений максимальной скорости и общего пройденного расстояния.

person JAlex    schedule 08.07.2020

Основываясь на вашем комментарии о первом нахождении расстояния между A и B, я собираюсь сделать снимок в темноте, что вы, возможно, ищете функцию легкого перехода.

Если вы знаете расстояние от A до B и знаете, как долго должна длиться вся анимация (т. е. продолжительность), то вам не нужно учитывать ускорение. Вы можете получить скорость в любой момент времени на основе параболической, квадратичной, синусоидальной или другого типа кривой, которая идет от начальной скорости (0) до конечной скорости (0) с максимальной скоростью и определенным пиком кривой. по свойствам кривой.

Здесь показано множество функций плавности входа/выхода: https://gizma.com/easing/

Если вы хотите реконструировать такую ​​кривую на основе известного ускорения и расстояния, вы должны заменить позицию и расстояние на t время и d продолжительность соответственно.

person joshstrike    schedule 08.07.2020