Using torque to rotate an object into a desired orientation

Started by
4 comments, last by JoeJ 9 years, 2 months ago

Hi,

I've got an object with forward vector f, and I want to rotate this object so that the forward vector = v (Some other vector). Currently I do this by applying a torque on the object by the cross product f x v.


torq = cross(
    normalize(object_forward),
    normalize(desired_forward)
);

ApplyTorque(torq);

.

Now theres an issue, it rotates towards the desired forward vector, however the velocity is extremely high so it misses it and keeps oscillating around the desired forward vector. This gives sense, however how can one somehow scale the magnitude of the torque in such a way that it accelerates fast in the beginning but slowly reaches the goal ( So basically dont miss it...).

Thank you for your attention.

-MIGI0027

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

Advertisement

Is there a particular reason you want to use torque to accomplish the direction change?

Unless you want to get quite a bit more complicated, a simpler approach is to add a time-based fraction of the difference in the vectors to the current direction, and normalize the current direction. If the difference is "small enough" [ you pick a delta ], simply set the current direction to the desired. That is, change the direction "manually" rather than accomplishing it using angular acceleration and angular velocity, which is what torque does.

I don't know what your ApplyTorque() function does, but, if it's constructed properly, the overshoot/oscillation occurs because you keep applying torque in the direction of the desired direction no matter how fast the object is approaching the desired direction. I.e., reducing the torque does not reduce the angular velocity.

Think in terms of: "Torque is to angular position as force is to linear position." If you keep applying force (even smaller and smaller amounts) to an object in the same direction, its position changes but its velocity keeps increasing. If you keep applying torque to an object in the same direction, its angular position changes but its angular velocity keeps increasing. That's what force and torque do.

It may be a more complicated approach than you want, but changing angular position using torque can be done using PID algorithms. That is, you have to decide what the new direction should be, and how fast you want the direction to change to get to the desired result. If you choose parameters other than those that produce critical damping you'll still get overshoot.

If you want to use torque, whatever scheme you decide on, you still have to consider the difference in current-vs-desired as an error term, and stop the process when the error is "small enough." I.e., assuming you're using floating point variables, you can't use "float_value_1 == float_value_2" to determine an end point, you'll have to do the equivalent of "Is error < some_epsilon?" to determine the end point.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Using PID should not be necessary for a simple problem like that -
they are hard to tune right and mostly there's a better analytical solution.
Torques ar harder than forces so first a simple example,

Calculate force to reach a target:


Vec3 targetLinvel = (targetPos - body.com) / timestep; // desired linear velocity to move target distance in one step
targetLinvel -= body.linearVelocity; // subtract current velocity
Vec3 force = 0.3 * targetLinvel * (body.mass / timestep); // soften by some factor <1 to avoid oszillation

This should work and you have only a single tuning factor, which is easy to understand and predict.

Now the same for orientation:


Vec3 axis; float angle;
ToAxisAndAngle (&axis, &angle, object_forward, desired_forward); // normalized axis and radians

Vec3 targetAngvel = axis * angle / timestep;
targetAngvel -= body.angularVelocity;

Vec3 torque = targetAngvel / timestep;
torque = body.WorldSpaceMatrix.Unrotate (torque); // rotate to body local space...
torque.x *= body.InertiaXX; //... so we can apply 3D inertia in the space where it is defined
torque.y *= body.InertiaYY;
torque.z *= body.InertiaZZ;
torque = body.WorldSpaceMatrix.Rotate (torque); // rotate back to world space
torque *= 0.3; // avoid oszillation 
In order to solve this problem, I would start with an easier problem: Applying a force try to get a particle to reach a particular position. If you do the naive thing and accelerate towards the point, you'll get oscillations just like the ones you observe. Look up "arrive steering behavior" for some attempts at solving this problem. You can then try to adapt the steering behavior to work with rotations; I don't think that would be very hard to do.

Yeah it might seem like an overkill, and it most likely is. However I'm trying to do this in this particular manner to "simulate" thrusters, well it's just my extremely naive attempt to do this.

I got it working thank to you guys. ( JoeL thanks for the snippets )

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

Just to clarify, the snippets i gave are very good to answer the question: I'm used to position obejcts however i want (i've coded a Space Invasres clone or i'm a graphics programmer) - but how can i do the same thing when using a physics simulator?

For thrusters (spaceships etc.) PID control might give good realistic results, but i dislike that you solve a hard to understand control problem (physics) with another hard to predict tool (PID)... it's hard to learn something by doing so - at least for me.

To do thrusters i'd clamp the final torque to a small max length, and use smaller factor than 0.3 to make it less stiff.

If this still looks too precise or artificial trying / combining with PID might work better.

To develop a more complex model a nice exercise would be: Compute initial velocity to hit a target with a rock under gravity and how much time will it take.

This leads to equations that can solve control problems analytically without any 'professional trial and error approach' like PID. ... cool but time consuming :)

This topic is closed to new replies.

Advertisement