Advertisement

Inaccuracies in deceleration

Started by February 26, 2015 01:04 AM
3 comments, last by LorenzoGatti 9 years, 11 months ago

I am rotating an object with constant deceleration. I want the object to stop at a predetermined location at given time t. The object stops at the correct location when I do not take time in consideration using the equation acceleration = -(velocity * velocity)/(2 * spinTo) or a = (v22 – v12) / (2 ?s)

However this equation does not allow me to incorporate the amount of time I want the deceleration to take. To incorporate time I am using the equation

acceleration = (2 * spinTo - (2 * velocity() * time))/(time * time) or a = (2 ?s – 2 v1 ?t) / (?t)2

This produces inconsistent results and my object does not rotate to the correct location. I'm fairly confident my math is correct. What could be causing the inaccuracies when time is taken into consideration? My rotation code looks like this

void WheelSpinEffect::HandleRotation(float degree, float velocity, float accel)
{
float oldVel = velocity;
float dt = 1.0f/GraphicsDevice::GetRefreshRate();

velocity += (accel * dt);
degree += (oldVel + velocity) * 0.5f * dt;

Rotate(degree);
SetVelocity( velocity );
}

Any help is greatly appreciated.

I don't understand your math, what spinTo represents or even whether this is 2D or 3D. Why is velocity a float, and not a vector? Can you provide some definitions so we know what we are talking about?
Advertisement

I don't understand your math, what spinTo represents or even whether this is 2D or 3D. Why is velocity a float, and not a vector? Can you provide some definitions so we know what we are talking about?

spinTo = (360 * 3) - (stopPosition * 30.0f) - currentDegree; //wedges are 30 degrees apart (360/12)

It's a basic 2D rotation.

I personally wouldn't have the timing of my rotation based on the refresh rate as you have here:


float dt = 1.0f/GraphicsDevice::GetRefreshRate();

Because it varies wildly and can affect accuracy and consistency of results. It should be over a more stable timer like those offered by chrono in C++ 11 shown here http://en.cppreference.com/w/cpp/chrono/steady_clock. As the wheel slows you sample the time interval less and less to decelerate it.

So using chrono your dt will look something like:


std::chrono::steady_clock::time_point start, stop;
std::chrono::duration<double> elapsed_secs;

...

// Start the timer.
start = std::chrono::steady_clock::now();

// Do something in here like the time taken for the wheel to rotate 1 degree as it decelerates.

// Stop the timer.
stop = std::chrono::steady_clock::now();

elapsed_secs = std::chrono::duration_cast<std::chrono::duration<double>>(stop - start);

double dt = 1.0 / elapsed_secs;

Something like this will give you better results because it isn't based on framerate.


float dt = 1.0f/GraphicsDevice::GetRefreshRate();

This is bad at any frame rate: the duration of your animation should be fixed and predictable, while your refresh rate is constant and need not be queried repeatedly.


velocity += (accel * dt);
degree += (oldVel + velocity) * 0.5f * dt;

This accumulates errors. Multiply instead, with t varying between 0 and the animation length and matching the real time clock, not theoretical frame rates::

  • velocity = initial velocity+ accel*t
  • position= initial position + 0.5*accel*t*t

Omae Wa Mou Shindeiru

This topic is closed to new replies.

Advertisement