Reputation: 10379
I am writing a simulation in which an object moves in a 2D world towards a target position, stored as vector target(x,y)
. The object position is stored as position vector pos(x,y)
as well. The object contains two more vectors, the desired movement velocity dv(x,y)
, as well as the current movement velocity cv(x,y)
. At the start of the simulation both these velocity vectors are initial, i.e. set to (0,0)
.
When the object should move towards the target position, I calcuate the desired velocity vector dv
, normalize it, and scale it by a movement speed value:
dv.set(target).sub(pos).normalize()
dv.scale(speed)
I want to make the movement look more realistic, that's why I use two velocity vectors. dv
tells the full speed I want to move the object, and cv
holds the real speed the object currently moves at.
Then at each frame (update step) the current velocity cv
is set based on the desired velocity dv
and an acceleration value acc
. This is done by simply calculating the difference between cv
and dv
and clamping this difference to acc
. That way the object starts to move slowly and accelerates gradually to eventually reach full speed.
So far this is working fine. Now I want to make use of acc
for deceleration as well. When the distance between pos
and target
is at a certain value, the desired velocity dv
should be set to (0,0)
, so that the object gradually decelerates until it comes to a full stop at the target position.
My question is: How can I calculate at which distance I need to set dv
to (0,0)
(i.e. tell the system to stop movement), so that the object decelerates correctly to stop exactly at the target position?
Upvotes: 2
Views: 4536
Reputation: 34829
You're doing a discrete time simulation of motion. One way to keep things simple is to perform the calculations in a way that makes acceleration and deceleration symmetrical. In other words, the distance traveled while accelerating should be the same as the distance traveled while decelerating. As an example, assume
Here's how the discrete time simulation would progress
first tick
old speed = 0
new speed = 5
distance = 5
second tick
old speed = 5
new speed = 10
distance = 15
third tick
old speed = 10
new speed = 13
distance = 28 <-- total distance while accelerating
fourth tick
old speed = 13
distance = 41
new speed = 10 <-- not 8!!!
fifth tick
old speed = 10
distance = 51
new speed = 5
sixth tick
old speed = 5
distance = 56 <-- Yay, twice the distance, we have symmetry
new speed = 0
There are two key points here
In the C programming language, the following code could be used to update the speed during deceleration
if ( old_speed % acceleration != 0 ) // if speed is not a multiple of acceleration
new_speed = old_speed - old_speed % acceleration; // reduce speed to a multiple of acceleration
else // otherwise
new_speed = old_speed - acceleration; // reduce speed by acceleration
If acceleration and deceleration are symmetrical, then computing the deceleration distance is the same as computing the acceleration distance.
distance = acceleration * (1+2+3+ ... +N) + fudge_factor
where
N
is top_speed / acceleration
truncated to an integer, e.g. 13/5 ==> 2
fudge_factor
is 0
if top speed is a multiple of acceleration, or
top_speed
otherwiseThe computation can be simplified by noting that
1+2+3+ ... +N = N * (N+1) / 2
In C, the total distance travelled while decelerating could be computed as follows
int top_speed = 13;
int acceleration = 5;
int N = top_speed / acceleration; // Note: in C, integer division truncates
int fudge = 0;
if ( top_speed % acceleration != 0 )
fudge = top_speed;
int distance = acceleration * (N * (N+1)) / 2 + fudge;
Upvotes: 1
Reputation: 41100
Use the kinematic equations:
vf is your final velocity, or 0 (the speed you want to be going)
vi is your initial velocity, given (the speed your object is currently moving).
a is acceleration
d is distance.
2*a*d = vf2 - vi2
2*a*d = 0 - vi2
assume acceleration is negative, so multiply both sides by -1
|a| is the absolute value of your acceleration (deceleration in your case)
Upvotes: 1