[ODE] Car Physics

Steve Eckles steve.eckles at team17.com
Fri Apr 16 12:19:23 MST 2004


HI,

Can someone please help me! I am trying to write a simple "car driving over
terrain" type program but I just can't the actual driving to 'feel' right.
I've got a basic test program up and running with a car (ie box with 4
spheres at the corners) driving over a landscape, but the main problems I
have are: 

- It's too slow. But if I increase the speed of the car the if tips over all
the time. If I increase the mass then it slides around to much.
- It too slippery. If I decrease the slippyness then the car becomes very
unstable - flipping over and suchlike. I do want it to be fairly slippy tho
- in an arcade rally racer kind of way 
- I can't get it to go in a straight line!  The turning of the front wheels
(the steering ones) seems to be somewhat random! I'm guessing they are be
'knocked' and rotated by colliding with the landscape but whatever, as I am
driving along the front wheels seem to have a mind of there own sometimes.
- It is 4WD. I would like (say) just RWD but makes the car move very slowly
and the front wheels just get pushed along, rather than rotate. I would
ideally like to do arcade style rear-end power drifts!

The problem is I'm new to ODE and haven't got a clue what I'm doing! I've
been using a combination of the docs, a couple other peoples demo programs &
a lot of such-it-and-see random tweaking of values! What I would really like
is just someone show me the steps involved & values to plug-in ODE to get a
car like simulation.

Here are some snippets of my code:
	
Seting up the joints:     

    for ( int i = 0; i < 4; i ++ )
    {
        m_dJoint[i] = dJointCreateHinge2(m_dWorld,0);
 
dJointAttach(m_dJoint[i],m_CarBody.GetBody(),m_CarWheels[i].GetBody());

        D3DXVECTOR3* pvPos = m_CarWheels[i].GetPosition();
        dJointSetHinge2Anchor(m_dJoint[i],pvPos->x,pvPos->y,pvPos->z);
        dJointSetHinge2Axis1(m_dJoint[i],0,1,0);

        switch (i)
        {
            case 0:
            case 2:
                dJointSetHinge2Axis2(m_dJoint[i],-1,0,0);
                break;

            case 1:
            case 3:
                dJointSetHinge2Axis2(m_dJoint[i],1,0,0);
                break;

        }


        dJointSetHinge2Param (m_dJoint[i],dParamLoStop,0);
        dJointSetHinge2Param (m_dJoint[i],dParamHiStop,0);
        dJointSetHinge2Param (m_dJoint[i],dParamFMax,50);
		dJointSetHinge2Param (m_dJoint[i],dParamFudgeFactor,0.1);

        dJointSetHinge2Param (m_dJoint[i],dParamVel2,0);
        dJointSetHinge2Param (m_dJoint[i],dParamFMax2,200.0);

        dJointSetHinge2Param (m_dJoint[i],dParamSuspensionERP,0.3);
        dJointSetHinge2Param (m_dJoint[i],dParamSuspensionCFM,0.4);
    }


The car UI (during the main game loop)
    static const dReal steeringRate = M_PI * 4 / 3;
	static const dReal steeringLimit = M_PI / 6;

	dReal wheelVelocity = 12 * M_PI * m_fSpeed;

    CLAMP(wheelVelocity,-MAX_SPEED,MAX_SPEED);

	if (fabs (m_fSteer) < 0.1)
		m_fSteer = 0;

	/* Do the steering */ 
	for( int i = 0; i < 4; ++i)
	{
        if ( i == 0 || i == 1 )
            continue; // only the front wheels steer

		double desiredPosition = m_fSteer * ((i > 1) ? -1 : 1);
		double actualPosition = dJointGetHinge2Angle1(m_dJoint[i]);
		double steeringVelocity = (desiredPosition -
actualPosition);

		dJointSetHinge2Param(m_dJoint[i], dParamHiStop,
steeringLimit);
		dJointSetHinge2Param(m_dJoint[i], dParamLoStop,
-steeringLimit);
		dJointSetHinge2Param(m_dJoint[i], dParamVel,
steeringVelocity);
	}

	/* Do the velocity */ 
	for( int i = 0; i < 4; ++i)
    {
		switch ( i )
        {
            case 0:
            case 2:
                dJointSetHinge2Param(m_dJoint[i], dParamVel2,
-wheelVelocity);
                break;

            case 1:
            case 3:
                dJointSetHinge2Param(m_dJoint[i], dParamVel2,
wheelVelocity);
                break;
        }
    }

In the collision handler, I setup the contact joint like so:
			contact[i].surface.mode =  dContactSlip1 |
dContactSlip2 | dContactApprox1;
			contact[i].surface.mu = dInfinity;
			contact[i].surface.slip1 = 0.035;
			contact[i].surface.slip2 = 0.035;
			contact[i].surface.soft_erp = 0.5;
			contact[i].surface.soft_cfm = 0.3;
Any help would be much appreciated, thanks.

Steve.
__________________________________________
Steven Eckles
Programmer,
Team17 Software Ltd.
www.worms3d.com
www.steveneckles.co.uk
__________________________________________




More information about the ODE mailing list