[gameprogrammer] RayCast vehicle - I think it's almost done

Hi,

I think I'm almost there, the suspension is working fine, and I also think
I'm considering all forces, including the normals (since the wheels don't
exist physicly, I add this force manually as the wheels were there applying
this forces over the body - the point where the forces are applied is
susAct, locally, and posSusAct, its global coordinates).

 

Anyway, this code, i think, should works fine, I'm killing lateral forces
and when I steer the wheels I apply a perpendicular force to that wheels to
kill that acceleration too and that way I think the car should make the
turn, but it isn't and that's the reason of my post.

But that's not what happens :( It actually starts "shaking" and making turns
right then left then right again and so on not repecting my inputs, I think
it might be a problem with the math, wrong angle calculation and velocity
components.

 

Here is the main code, any help will be appreciated

 

Thanks,

Dirso

 

[code]Ogre::Quaternion quat = getOrientation();

Ogre::Vector3 velocityVector(me->getVelocity());

Ogre::Real mass = _loader._carMass;

Ogre::Vector3 com = me->getCenterOfMass() + _loader._CoM;

// that's because Newton give me getCenterOfMass as an offset of the
original CoM

 

// gravity force

Ogre::Vector3 Fg = Ogre::Vector3(0,-9.8, 0) * mass;

me->addForce(Fg);

// local vars

Ogre::Real deltaT = me->getWorld()->getTimeStep();

 

// for each wheel calculates all forces on each wheel

for(RayCastTireListIt it = _tires.begin(); it != _tires.end(); it++)

{

            // draw the rotation

            Quaternion WheelYaw((*it)->_steer * mSteerAngle, _worldOr);

            // suspension

            Ogre::Vector3
posSusAct((*it)->_wheelSusAct->getWorldPosition());

            Ogre::Real r = (*it)->_radius;

            Ogre::Real rayLength = r + (*it)->_susLength;

            Ogre::Vector3 uVector(quat*_worldOr);

            OgreNewt::BasicRaycast ray(mWorld, posSusAct, posSusAct -
uVector*rayLength);

            OgreNewt::BasicRaycast::BasicRaycastInfo info =
ray.getFirstHit();

            //

            Ogre::Vector3 susAct = (*it)->_wheelSusAct->getPosition();

            Ogre::Vector3 dWheel1 = (*it)->_wheelNode->getPosition();

            Ogre::Vector3 dWheel2;

            if(info.mBody)

            {

                        // orientation vector

                        Ogre::Vector3 rVector(quat*WheelYaw*(*it)->_pin);

                        Ogre::Vector3 wheelVelocity(velocityVector + (susAct
- com)*me->getOmega());

                        Ogre::Vector3 wheelVelocityN(wheelVelocity);

                        Ogre::Real velocityLen(wheelVelocityN.normalise());

                        Ogre::Real cos1(rVector.dotProduct(wheelVelocityN)),

                                   cos2(uVector.dotProduct(wheelVelocityN)),

                                   sin1(Math::Sqrt(1 - cos1*cos1)),

                                   cosUp(uVector.dotProduct(_worldOr));

                        if(cos2 < 0.0) sin1 = -sin1;

                        // calculate the new position of the wheel

                        dWheel2 = susAct - (info.mDistance*rayLength -
r)*uVector;

                        // calculate the suspension force

                        Ogre::Real dist1 =
MathHelperClass::getDistance(dWheel2, susAct),

                                   dist2 =
MathHelperClass::getDistance(dWheel1, susAct);

                        Ogre::Real Fs = (*it)->_susSpring*((*it)->_susLength
- dist1),

                                   Fd = (dist2 - dist1)*(*it)->_susShock;

                        Ogre::Vector3 Fn(-Fg*Math::Abs(cosUp)/4.0);

                        Ogre::Vector3 Ft(Fn + quat*(Fd + Fs)*_worldOr);

                        // drive force

                        if(((*it)->_drive > 0.01) && (wheel_torque > 0.01))

                        {

                                   Ogre::Vector3
driveForce(quat*_carAccelDir * 

                                               ((*it)->_drive * wheel_torque
/ (*it)->_radius)         );

                                   Ft += driveForce;

                        }

                        // calculate the steering forces

                        Ogre::Vector3
friction(velocityLen*sin1*rVector*mass/4.0);

                        friction.y = 0.0f;

                        Ft += friction;

                        // set the final force

                        me->addLocalForce(Ft,
(*it)->_wheelSusAct->getPosition());

            }

            else

            {

                        dWheel2 = susAct - uVector*(*it)->_susLength;

            }

            (*it)->_wheelNode->setPosition(dWheel2);

            (*it)->setOmega(getVelocity() / (*it)->_radius);

 

            mCurrRotZ += Ogre::Radian((*it)->getOmega()*deltaT);

            Quaternion WheelRotation(mCurrRotZ, (*it)->_pin);

            (*it)->_wheelNode->setOrientation(WheelYaw*WheelRotation); 

}[/code]

Other related posts: