Make a body rotate towards a point

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Make a body rotate towards a point

Postby deadstar » Mon Jan 05, 2009 9:45 am

Hi,

I'm making a laser guided missile system, much like the alt-fire of the rocket launcher in Half Life.

I'm performing a raycast to get the look-at point, and without physics usually I would use a lookat function based on quaternion slerp (over delta time) to make the rocket gradually point towards the target, but I can't figure out how to achieve this using force and torque.

Any ideas?
deadstar
 
Posts: 4
Joined: Sat Jul 12, 2008 10:11 am

Re: Make a body rotate towards a point

Postby Julio Jerez » Mon Jan 05, 2009 12:58 pm

That’s and interesting problem.
You can do it in two ways, one is in a force call back, there is making unilateral joint controller.
In both cases the math is the same but the application a little different.
The advantage of the joint is that give you more steering control, but the force callback is good too.

Here sit ha math, and it is all base of the method you are already using to get the rotation that will align the missile to the target.
In you method afte to get the quatenion q this what you do.

Remembet that the expression of a quaterion is given by

Q(q0, q1, q2, q3)

Where

Q0 = cos (a /2)
Q1, q2, q3 = sin(a/2) * vector (x, y, z)

You can interpreted that like this if the missile was at rest, (no angular velocity and no linear velocity)
What instantaneous angular velocity w around the unit vector (x, y, z) will align the missile with the target? The answer is given by.

W = a / dt

You can easily get a from q0

a = 2.0 * acos(q0);
therefore

|W| = a / dt

The direction vector of the angula velocity magnitude is given by:

Dir = normilze (q1, q2, q3)

Now w in vectors form is

W = dir * (a / (k * dt))

Now you know the this is a angular velocity the will take the missile for the rest position, bu if the missil was already spinning you need to subtract the missile velocity from the theoretical W

W = dir * (a / (k * dt)) - Missele.GetOmega();

Now you know what angular velocity to apply to the missile, to convert that into a angular acceleration, all you need to do is divide it by the time step.
You need to use a scale value of the time because if you use the same dt of the simulation then it will over shoot

Alpha = W * ( 1.0/dt * K))

K can be 2, 3, … I find the 3 is a nice value for smotth steering.

That will take care of the direction, you still need to steer the, the idea is the same.
You can get the direction vector form the missile to the target,

Dir = normalize (missile.position – targetPosition)

You can decompose the missile velocity alone that direction vectors

Velc_tanget = dotproduct (MissileVelociti, dir)
Veloc_Lateral = MissileVelociti - dotproduct (MissileVelociti, dir)

Now you need to drive Veloc_Lateral by adding an velocity to counter act it

That is;

Correction_Vel = -Veloc_Lateral

Then you can convert Correction_Vel to an acceleration

Accel = Correction_Vel * (1.0 / (dt * k));

Again k is a scale of the time step

teh you mutiply thiose values by teh Inertia and the mass, and you add then to the body.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Make a body rotate towards a point

Postby deadstar » Tue Jan 06, 2009 1:43 pm

Thank you very much for the detailed post!

I'll see if I can figure the maths out and I'll let you know the result.
deadstar
 
Posts: 4
Joined: Sat Jul 12, 2008 10:11 am

Re: Make a body rotate towards a point

Postby lost_jedi » Sun Mar 08, 2009 4:03 pm

Hey there,

Sorry to bump such an old thread. I have been trying to implement the code above, so it seemed appropriate. :-)

I am attempting to make a rigid body rotate to face a point in global space. However the body spins (rather jerkily) and I can't see where I am going wrong. I would be very grateful if you physics masters could offer some assistance! :mrgreen:

Here is the code I am using:

Code: Select all
            // Here we are going to try and turn a body to face a location....
            float fAcceleration = 0.01f;
            float fSmoothing = 3.0f;
            float fDeltaTime = fTimeStep;

            Vector3 vLocation = new Vector3(50.0f, 0.0f, -50.0f);

            // Get the quaternion which represents the rotation.
            Quaternion Q = this.getRotationQuaternion();

            // Get the direction of angular velocity.
            Vector3 vDirection = new Vector3(Q.X, Q.Y, Q.Z);
            vDirection.Normalize();
            float a = (float)(2.0 * Math.Acos((double)Q.W));

            // Now we know the angular velocity which will take the object to rest we need to subtract the existing velocity.
            Vector3 W = Vector3.Multiply(vDirection, (a / (fSmoothing * fDeltaTime)));
            W.Subtract(this.getAngularVelocity());

            // Now we have the angular velocity we can convert that into an acceleration so we can apply it to the ship.  To do this we divide it by the scaled timestep.
            Vector3 vAlpha = Vector3.Multiply(W, (1.0f / (fDeltaTime * fSmoothing)));

            // Now we can compute the torque using t=I*alpha
            float fMass;
            Vector3 vInertia = new Vector3(0.0f, 0.0f, 0.0f);
            Newton.NewtonBodyGetMassMatrix(nBody, out fMass, out vInertia.X, out vInertia.Y, out vInertia.Z);
            Vector3 vTorque = Vector3.Cross(vInertia, vAlpha);

            // Stearing the ship.
            // Get the direction vector from the ship to the target.
            vDirection = Vector3.Normalize(Vector3.Subtract(this.getTranslate(), vLocation));

            // Decompose the ships velocity into the direction.
            Vector3 vCurrentVelocity    = this.getAngularVelocity();
            float fVelocTangent         = Vector3.Dot(vCurrentVelocity, vDirection);
            Vector3 vCorrectionVeloc    = Vector3.Subtract(vCurrentVelocity, new Vector3(fVelocTangent, fVelocTangent, fVelocTangent));
            vCorrectionVeloc.Multiply(-1.0f);

            // Convert it into an acceleration.
            Vector3 vAcc = Vector3.Multiply(vCorrectionVeloc, (fAcceleration / (fDeltaTime * fSmoothing)));

            // Using F=ma get the force.
            Vector3 F = Vector3.Multiply(vAcc, this.getMass());
         
            // Apply it to the body.
            Newton.NewtonBodySetForce(nBody, ref F);
            Newton.NewtonBodySetTorque(nBody, ref vTorque);
lost_jedi
 
Posts: 12
Joined: Thu Aug 21, 2008 7:45 pm


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 15 guests

cron