3
votes

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

2 Answers

0
votes

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.

0
votes

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.