3

I am building a simulator in Javascript and struggling to understand the basics of the physics and kinematic since it's been a while since I graduated. Anyways, I have a loop that should simulate the time and every iteration of the loop is equal to 1 second and I have an object that I want to move from point A ( [150, 50] ) to point B ( [1, 1] ). The object has a max speed of 10, acceleration of 4.9 and deceleration of -4.9. I'm recalculating the target position every iteration of the loop ( 1 sec. ) but it doesn't work when I have to decelerate because at some point the velocity is negative. Is there any formula I can use to calculate the interpolation considering both acceleration and deceleration every x seconds moving from point A to point B?

Here's the current state of my code:

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;
    }
}
fgoncalves
  • 31
  • 2
  • Are you saying the particle will accelerate to the max speed and then start to decelerate? Or do both acceleration and deceleration apply together? – QurakNerd Jun 27 '20 at 19:34
  • @QurakNerd I want the particle to accelerate until it reaches the maximum speed ( unless it's already in maximum speed ) and decelerate before getting to point B. – fgoncalves Jun 27 '20 at 19:40
  • And your acceleration is constant until it reaches max speed? If so, since your acceleration depends on wheter or not you have already reached max speed, I don't think there is a simple formula to give you what you need. Instead, you would need to split the function into 2 parts, accelerating and decelerating and any calculation needs to check which one it needs to use. Can I ask what physical process you are modelling, because abrupt change in acceleration based on velocity isnt a common thing – QurakNerd Jun 27 '20 at 19:49
  • Yes, acceleration and deceleration are both constants.Since I'm calculating the velocity every second I'm confused on how to use the formulas in case within the same second the particle has to accelerate and decelerate. – fgoncalves Jun 27 '20 at 19:59
  • What I'm doing is to first find the distance between points A and B and then calculate the distance to stop given current velocity and acceleration. Every second I check if the remaining distance for the next interpolation is bigger than the distance to stop. If so, I break down the interpolation in 2 parts within the same second. The first part is accelerating if not already in max speed) and the second is decelerating. Next iteration I will decelerate until I reach point B – fgoncalves Jun 27 '20 at 19:59
  • for constant accelerations, you need to look up SUVAT equations, if in a given second your acceleration is constant this will be simple. If not, you will have to split the second into two parts and use multiple SUVAT equations – QurakNerd Jun 27 '20 at 20:08
  • What I don't understand here is that velocity is a vector and acceleration is a scalar. In what direction are you applying the acceleration to reach the target? This assumes the object is NOT facing directly towards the target and it need to curve to get there. – JAlex Jul 07 '20 at 18:40
  • 1
    Also, what you show is NOT a simulation, but a solution of _some_ equations. A simulation takes an existing position and velocity and updates these values for a small time increment, until the target is reached. – JAlex Jul 07 '20 at 18:42

2 Answers2

0

Lets consider the math behind the problem, as a 1D problem. Lets find the motion profile of the object along a straight line connecting the beginning and ending points.

Given the distance between the points L, the maximum speed v_max and the available acceleration and deceleration a, the motion is split into three regimes. Below is the math for the total travel distance x, as well as the speed v (given is pseudo code)

  • Acceleration

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

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

     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
    

These were derived from the standard kinematics equations subject to the constraints of maximum speed, and total distance traveled.

JAlex
  • 1,486
  • 8
  • 19
0

Based on your comment about first finding the distance between A and B, I'm going to take a shot in the dark that you might be looking for an ease-in-out "tween" function.

If you know the distance from A to B and you know how long you want the whole animation to last (i.e. the duration), then you don't need to consider acceleration. You can get the velocity at any point in time based on a parabolic or quadratic or sinusoidal or other type of curve that goes from the starting speed (0) to the ending speed (0) with a maximum speed and the peak of the curve determined by the curve's properties.

There are ton of in/out easing functions shown here: https://gizma.com/easing/

If you wanted to reverse engineer such a curve based on a known acceleration and distance, you would substitute position and distance for t time and d duration, respectively.

joshstrike
  • 1,753
  • 11
  • 15