Advertisement

Apply torque on angular acceleration

Started by October 03, 2014 02:56 PM
9 comments, last by Tostaky42 10 years, 4 months ago

I'm working on a game project about a top down car game in 2d. I want to manage all the physics by myself. Im working with this book : http://www.amazon.fr/Game-Physics-Engine-Development-Commercial-Grade/dp/0123819768 to implement the physics.

From now my physic engine can handle force on the different cardinal axes. But I have some issues to implement a correct simulation of rotation. Im trying to implement some torque to find angular acceleration. So I implemented an inertia tensor matrix :


setMass(400.f);
Matrix3 it;
it.setBlockInertiaTensor(Vector3(2, 1, 1), 400);
setInertiaTensor(it);

void setBlockInertiaTensor(const Vector3 &halfSizes, float mass)
{
    Vector3 squares = halfSizes.componentProduct(halfSizes);
    setInertiaTensorCoeffs(0.3f*mass*(squares.y + squares.z),
        0.3f*mass*(squares.x + squares.z),
        0.3f*mass*(squares.x + squares.y));
}

To apply torque I apply a force on a body point of my car and I find the torque by a cross product :

The meaning of this is to simulate the steering :


player->addForceAtBodyPoint(Vector3(-2000, 1000, 0), Vector3(0, 100, 0));

void AObject::addForceAtBodyPoint(const Vector3 &force, const Vector3 &point)
{
    Vector3 pt = getPointInWorldSpace(point);
    addForceAtPoint(force, pt);
}

void AObject::addForceAtPoint(const Vector3 &force,
    const Vector3 &point)
{
    // Convert to coordinates relative to center of mass.
    Vector3 pt = point;
    pt -= _position;

    _forceAccumulate += force;
    _torqueAccumulate += pt % force;
    //std::cout << "torque x " << pt.x << " y " << pt.y  <<  " z "<< pt.z <<  std::endl;
}

Vector3 Vector3::operator%(const Vector3 &vector) const
{
    return Vector3(y*vector.z - z*vector.y,
        z*vector.x - x*vector.z,
        x*vector.y - y*vector.x);
}

The overload of modulo is the cross product

And finally I do the integration of all the physics data (forces and torques)


void    Player::integrate(float deltaTime)
{

    addForce(_velocity * -150.0f);

    // Calculate linear acceleration from force inputs.
    _lastFrameAcceleration = _acceleration;
    _lastFrameAcceleration.addScaledVector(_forceAccumulate, _inverseMass);
    // Calculate angular acceleration from torque inputs.
    Vector3 angularAcceleration = _inverseInertiaTensorWorld.transform(_torqueAccumulate);
    // Update linear velocity from acceleration .
    _velocity.addScaledVector(_lastFrameAcceleration, deltaTime);
    // Update angular velocity from  acceleration .
    _rotation.addScaledVector(angularAcceleration, deltaTime);
    // Impose drag.
    _velocity *= pow(_linearDamping, deltaTime);
    _rotation *= pow(_angularDamping, deltaTime);
    // Update linear position.
    _position.addScaledVector(_velocity, deltaTime);
    _position.z = 0;
    // Update angular position
    _orientation.addScaledVector(_rotation, deltaTime);
    // Normalise the orientation, and update the matrice
    calculateWorldLocalData();
    // Clear accumulators.
    clearAccumulator();
}

And the orientation is not working at all. Im not that good with physics stuff, so I think that im misunderstanding the physic implementation of torque with inertia tensor...

Thank you for your help.

Questions:

Does "_inverseInertiaTensorWorld.transform(_torqueAccumulate)" apply moment of inertia to transform torque to angular acceleration? Does it work correctly?

Stating "orientation is not working" isn't sufficient information. Assuming _orientation is what you mean by "orientation," how do you use it and what does "not working" mean?

At what point in your code does the problem occur? That is, when you step through your code and examine values, which line of code gives you a result you don't expect?

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.

Advertisement

_inverseInertiaTensorWorld.transform(_torqueAccumulate) seems to work correctly. But the value of torque is null at this moment, and the interial tensor has good value. So I think the way to find torque is not the right way.

What I want to do is to apply on the front side of the car to turn it left or right.

I do a vector product to find it. The orientation is not changing. I mean by this if I apply a force like Vector3(0,100,0), my object will still go up and the orientation will not change...

I change the matrix of the object each end of frame with the orientation and the position.

In your function addForceAtBodyPoint:


Vector3 pt = getPointInWorldSpace(point);
addForceAtPoint(force, pt);

It appears you're applying the force to some point in world space. Forces should be applied at the object's center of gravity in the object's local frame of reference. The torque due to that force should be the cross-product of the force with the vector from the local point of force to the center-of-mass.

E.g., assuming your Y axis is "up," when a front wheel is turned to steer the vehicle, a friction force F (e.g., ( -10, 0, -1) is applied to the front suspension in the lateral direction (no Y component). Assume the front wheel is at a position P relative to the center-of-gravity of (5, 0, 2) [ 5 units to the front of the CG, 2 units to the side of the CG.] The force F is applied to the CG, and a torque of F x P is accumulated.

Code debugging: if something doesn't produce values you expect, examine your code. It appears you've done that. So, if the code appears to be correct, setup a test case of known simple values for your code. Set a breakpoint somewhere in your code and run the test case. Examine the variable values and confirm/deny that they are correct at the point in your code. If values are correct, step through one or more lines of code and examine the variable values at that point. At some line of code you'll find values that are incorrect. Determine why the values at that point are incorrect.

Using F and P in the example above, set a breakpoint in your code where the force and torque are calculated. Examine the values for force and torque vectors. For a steering force, the torque should be a vector pointing up - that is, the torque vector should have only a Y component.

So - same question as my previous post:


At what point in your code does the problem occur? That is, when you step through your code and examine values, which line of code gives you a result you don't expect?

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.

Okay, thank you for your advices, I found the problem, the rotation is good but its not applicated to the velocity vector. Its applied to the transform matrix of my object. How can i apply the rotation to the velocity vector ? Thank you in advance


How can i apply the rotation to the velocity vector ?

You don't. Rotation results from angular acceleration due to torque on the CG. It affects only the orientation (not the position) of the center-of-gravity (CG). Changes in velocity are affected by linear acceleration. Acceleration results from the application of forces on the CG.

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.

Advertisement

Yes but the velocity vector is my direction vector here (its magnitude is the speed of the car). So i need to rotate it, no ? If I apply a force like Vector3(5000,0,0) it will go always on the direction of the right side of the screen, I want that this direction turn. I dont know if im enough clear, sorry for that ...


the velocity vector is my direction vector here (its magnitude is the speed of the car). So i need to rotate it, no ?

No. Velocity (as a vector) is determined by current velocity vector + the linear acceleration vector * delta-time, not the angular acceleration vector.


If I apply a force like Vector3(5000,0,0) it will go always on the direction of the right side of the screen, I want that this direction turn.

In the following, the bolded quantities are vectors.

Accel = Force / mass

Velocity += Accel * delta-time

If Force is in a different direction than Velocity, Accel will be in a different direction than Velocity. If Accel is in a different direction than Velocity, Velocity will change direction. It's simple vector addition.

E.g.:

if an object's Velocity is along the Y axis (0, 1, 0), and a force is applied along the X axis (forceX, 0, 0), the object will accelerate along the X axis (forceX/mass, 0, 0).

At the next update, velocity += acceleration * delta-time = (0, 1, 0) + (forceX/mass * dt, 0, 0) = (forceX/mass * dt, 1, 0)

The vector (forceX/mass * dt, 1, 0) is the new velocity and has changed direction.

The rotation of the object is determined by the angular acceleration. N.B. The object may not be aligned in the same direction as the velocity. In the example above, IF the force is applied at the center-of-gravity, there is no angular acceleration, and the object will not rotate, though it's velocity vector changes.

As mentioned above, the object will rotate when a force is applied at a point NOT through the CG (e.g., at a front wheel). The result of that application is a combination of that force applied to the CG PLUS a torque about the CG. The force on the CG causes the velocity to change. The torque causes the object to rotate. The change in the velocity (and position) and the change in rotation are entirely separate. The result is that the object changes position (nothing to do with the object's rotation), and is rotated (nothing to do with the velocity) at that new position.

NOTE: the velocity, position and angular velocity must be maintained between updates. Clearing of the "accumulator" should be setting only the force and torque vectors to zero before the next update.

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.

Thank you for that clarification, I understand better these notions :). im sorry but i have one more question. In my case I want to have like one button for accelerate the car, and the two arrows buttons to rotate my car left and right. The car will accelerate in the direction of the head of the car. Like in MicroMachine, or other top down car game. In this case do I need to store the orientation of the car and to apply it, each frames, to the traction force ? And how do i apply it to this traction force ?


The car will accelerate in the direction of the head of the car.

Only for rear-wheel drive vehicles. The traction force is the force resulting from the wheels which are connected to the drive shaft coming in contact with the ground. If the vehicle is front-wheel drive the force will not be in the direction of the head of the car if the wheels are turned for steering.

If you're simulating a rear-wheel drive vehicle, the traction force is in the direction:

vehicle_base_direction * rotation

where vehicle_base_direction is the unrotated orientation of your vehicle.

I don't know what your math library supports but that equation would be vector*matrix (or matrix*vector, depending on how the math is implemented).

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.

This topic is closed to new replies.

Advertisement