# Calculating torque required to turn an object to a target rotation, depending on timestep

The function below works fine, when the timesteps of the physicsengine are short enough for the function to update often. It determinates when the ship(the object) needs to start decelerating to reach 0 angular velocity by the time it reaches the target rotation. (Always using maximum torque of the ship to turn)

However, I want to simulate this in a scenario with longer timesteps. Since my function checks for when to start decelerating each update, it will miss this moment when the timesteps are longer and move past the target rotation. The ship then starts swaying back and forth (obviously).

What I need is some way to determinate the torque I need to apply to the body for it to end up at that sweetspot where it needs to decelerate. That way the ship can start decelerating when the next update occurs and hopefully end up facing the target rotation with almost 0 angular velocity!

private void TurnTowardsTarget(Vector2 target, float deltaTime)
{
Vector2 delta = target - body.Position;
float targetRot = (float)Math.Atan2(delta.Y, delta.X);
float dRot = (float)Math.Atan2(Math.Sin(targetRot - body.Rotation),
Math.Cos(targetRot - body.Rotation));
float angularAcceleration = maxTurnForce / body.Inertia;
float avgDecelerationVelocity = body.AngularVelocity / 2;
float time = dRot / avgDecelerationVelocity;
float decelerationRequired = body.AngularVelocity / time;

//Target rotation is to the right (positive rotations are to the right)
if (dRot > 0)
{
//If the ship is rotating to the right
if (body.AngularVelocity >= 0)
{
//Should we start decelerating?
if (decelerationRequired >= angularAcceleration)
{
//Decelerate
TurnLeft();
}
else
{
//Keep on accelerating towards the target
TurnRight();
}
}
else
{
//The ship is rotating the wrong way, turn towards the target
TurnRight();
}
}

//Target rotation is to the left (negative rotations are to the left)
if (dRot < 0)
{
if (body.AngularVelocity <= 0)
{
//Should we start decelerating?
if (-decelerationRequired >= angularAcceleration)
{
//Decelerate
TurnRight();
}
else
{
//Keep on accelerating towards the target
TurnLeft();
}
}
else
{
//The ship is rotating the wrong way, turn towards the target
TurnLeft();
}
}
}


I hope I made myself quite clear, all the TurnLeft() and TurnRight() do is to apply "maxTurnForce" in the corresponding direction. Please respond if you find a solution, my brain is melting (x.

/Kimmeh!

Edit:

This is how the code looks now after implementing Sam's suggestion, it slightly overshoots the target rotation though, no matter the update-rate. And jitters back and forth from the target rotation.

I've put Math.Abs() around the time-calculation, changed sign of decelerationDecelerationRequired and changed sign of angularAcceleration depending on dRot.

        Vector2 delta = turnToTarget - body.Position;
float targetRot = (float)Math.Atan2(delta.Y, delta.X);
float dRot = (float)Math.Atan2(Math.Sin(targetRot - body.Rotation),
Math.Cos(targetRot - body.Rotation));
float angularAcceleration = maxTorque * -Math.Sign(dRot) / body.Inertia;
float avgDecelerationVelocity = body.AngularVelocity / 2;
float time = Math.Abs(dRot / avgDecelerationVelocity);
float decelerationRequired = -body.AngularVelocity / time;

float torque = (decelerationRequired - angularAcceleration) * body.Inertia;
torqueToApply = MathHelper.Clamp(torque, -maxTorque, maxTorque);


Just to clarify, I'm using Farseer physics engine, and I apply the torque of the body right before calling the step() function of farseer. The body has a slight angular damping, so it should actually rotate a bit less than expected.

I think it's because it now smoothly adjusts to the decelerationRequired. (say if the decelerationRequired == angularAcceleration, the change of torque would be 0, when it should be +-maxTorque in order to stop in time.

The problem is that TurnLeft() and TurnRight() basically work as on/off switches instead of continuously. You need to simulate what happens when the force is applied only during a fraction of the timestep. I suggest adding an argument to these functions indicating the force to be used instead of maxTurnForce: at a reasonably small scale, applying half the force is equivalent to applying it for half the time.

Assuming your current computations are correct, you already know the value of that force: it is (decelerationRequired - angularAcceleration) * body.Inertia, which should be clamped between -maxTurnForce and maxTurnForce.

Another nice thing is that the sign of the force already indicates the direction. You can therefore merge TurnLeft() and TurnRight() into a single Turn(float Force) function.

I know this is a very old question, but I recently tried to solve this problem too. I found that modeling the problem as a damped harmonic oscillator proved to be a fairly elegant solution with nice results. Here is a javascript implementation using an imaginary physics engine:

/**
* Applies a torque to the body to rotate it towards the angle.
*/
function rotate(body, targetAngle) {
k = 3.0; // Spring constant. Higher means faster rotation.
m = body.momentOfInertia;
d = 1.0; // Damping coefficient. Lower than 1.0 will overshoot.
c = -Math.sqrt(4 * m * k) * d;
v = body.angularVelocity;
x = angleDelta(body.angle, targetAngle);
springForce = k * x;
dampingForce = c * v;
body.applyTorque(springForce + dampingForce);
}

/**
* Modulo that handles negatives properly.
*/
function mod(a, b) {
return ((a % b) + b) % b;
}

/**
* Return the difference between angles, normalized to [-pi, pi].
*/
function angleDelta(a, b) {
diff = b - a;
return mod(diff + Math.PI, Math.PI * 2) - Math.PI
}


This is a solution to a slightly different problem than the original, but it's the solution I was looking for when I came across this question, so hopefully it will be of some use to somebody else who was also in my situation.

• Answering old questions is fine, especially if you have something new to add like you do! Welcome :) – Kevin Oct 17 '15 at 8:17

i allways use something like this:

        if (keyboardManager.IsKeyDown(Keys.W))
{
if (Math.Abs(_car.AngularVelocity) < 10f)
{
totalRotation = 0 -_car.Rotation;
while (totalRotation < -MathHelper.Pi) totalRotation += MathHelper.TwoPi;
while (totalRotation > MathHelper.Pi) totalRotation -= MathHelper.TwoPi;
_car.ApplyAngularImpulse(totalRotation * 0.01f);
}
}


in this case i try to turn my car to the angle 0 (totalRotation = 0 -_car.Rotation;).