Simulating vehicle body

Official forum for the Chipmunk2D Physics Library.
joe
Posts: 10
Joined: Sun Dec 02, 2007 3:27 pm
Contact:

Simulating vehicle body

Post by joe »

Hello,

I'm currently replacing a physics-engine I wrote myself by Chipmunk. Congratulations, it seems to do an awesome job. Especially the great documentation and highly intuitive API impressed me and finally convinced me to switch.

The project I'm working at is a little game. It features diffent types of vehicles: A tank, a jeep, a bugyy and a helicopter. Now I'm currently trying to get the tank to work right:

Code: Select all

   if (Key_Acceleration) {
      cpVect f = cpvforangle(VehicleShape->body->a);
      cpBodyApplyForce(VehicleShape->body, f, cpvzero);
   } else if (Key_Deceleration) {
      cpVect f = cpvneg(cpvforangle(VehicleShape->body->a));
      cpBodyApplyForce(VehicleShape->body, f, cpvzero);
   } else {
      cpBodyResetForces(VehicleShape->body);
   }

   cpFloat v = cpvlength(VehicleShape->body->v);
   if (v > Current_MaxSpeed) {
      VehicleShape->body->v = cpvmult(VehicleShape->body->v, Current_MaxSpeed / v);
   }

   if (Key_Left) {
      VehicleShape->body->a += (-3.0 / 180.0 * M_PI);
      if (VehicleShape->body->a < 0) VehicleShape->body->a += 2 * M_PI;
   } else if (Key_Right) {
      VehicleShape->body->a += (3.0 / 180.0 * M_PI);
      if (VehicleShape->body->a > 2 * M_PI) VehicleShape->body->a -= 2 * M_PI;
   }
The problem is, of course, that when the steering is changed during movement, the tank still flies in that same direction. The above model fits the helicopter, actually. Now as I'm not very sure how exactly the physics engine works - what parameters do I need to adjust to make my rigid body behave like a ground-vehicle? Currently it's kind of like this space shooting game Asteroids: rotation is direct, but it still behaves like a spacecraft.

It's hard to explain (even more so since English is not my first language), I hope you unterstand :-/

Greetings,
Thanks in advance,
Johannes

PS: I noticed some minor flaws in the documentation: cpCircleShapeNew's prototype is given as cpBody*, cpVect, cpFloat - it is, however, cpBody*, cpFloat, cpVect. Also the prototype of cpSpaceNew takes one parameter (int) in the documentation whereas the implementation says it takes no paramters. And the cpSpaceFreeChildren() prototype is duplicate in the documentation.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Simulating vehicle body

Post by slembcke »

I assume that this game has a top down view? If that's the case you might have gotten less than you bargained. Chipmunk doesn't know how to deal with forces that are orthogonal to the simulation plane (such as friction between the ground and the tank). You'll have to calculate these forces yourself.

I remember there being a good tutorial on exactly what you are looking for. Unfortunately the site for it has been down for a while. Internet archive is the best you are going to get. http://web.archive.org/web/200511251048 ... utcar.html

Also, instead of:

Code: Select all

cpvforangle(VehicleShape->body->a)
do this:

Code: Select all

VehicleShape->rot
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
joe
Posts: 10
Joined: Sun Dec 02, 2007 3:27 pm
Contact:

Re: Simulating vehicle body

Post by joe »

slembcke wrote:I assume that this game has a top down view? If that's the case you might have gotten less than you bargained. Chipmunk doesn't know how to deal with forces that are orthogonal to the simulation plane (such as friction between the ground and the tank). You'll have to calculate these forces yourself.
Yes, it has a top down view. And the ground friction calculation I'm already doing, that wasn't such a great deal. Nevertheless I think switching to Chipmunk was the right choice, especially because of the great collision detection. Don't be so modest, you wrote an awesome piece of software :-)
I remember there being a good tutorial on exactly what you are looking for. Unfortunately the site for it has been down for a while. Internet archive is the best you are going to get. http://web.archive.org/web/200511251048 ... utcar.html
Alright, I'll have a look at that, thanks. As soon as I figure out how to do it nicely, I'll leave a short note.
Also, instead of:

Code: Select all

cpvforangle(VehicleShape->body->a)
do this:

Code: Select all

VehicleShape->rot
[/quote]

Okay, I'll do that. Thanks a lot!

Greetings,
Johannes
joe
Posts: 10
Joined: Sun Dec 02, 2007 3:27 pm
Contact:

Re: Simulating vehicle body

Post by joe »

slembcke wrote:Also, instead of:

Code: Select all

cpvforangle(VehicleShape->body->a)
do this:

Code: Select all

VehicleShape->rot
Humm, I just tried that and noticed a Shape does not have a "rot" member - did you mean something else? Does the shape not become rotate with the associated rigid body?

Greets,
Johannes
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Simulating vehicle body

Post by slembcke »

Oops. Sorry.

Code: Select all

VehicleShape->body->rot
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
joe
Posts: 10
Joined: Sun Dec 02, 2007 3:27 pm
Contact:

Re: Simulating vehicle body

Post by joe »

slembcke wrote:Oops. Sorry.

Code: Select all

VehicleShape->body->rot
Okay, I used that one. When manually setting these components, which is the authorative one? Do both need to be set correctly so the whole rigid body is in a consistent state after the operation?

I got the vehicle simulation running pretty well (tanks feel like tanks, jeeps feel like jeeps and the buggy can drift, pretty neat). Now I'm trying to implement collisions (simply walls, currently, with INFINITY inertia and mass, bound to a line shape) and sense numeric instability at the point of collision - the problem may be interlinked with my above question, I'm not sure right now. Sometimes after a collision my tank just automatically rotates around its own axis, not stopping - is this intentional? I'm kind of having a hard time understanding what's happening right now.

Thanks for your help,
Johannes


PS: For anybody interested looking for the car physics I used, here's the code. It should be pretty self-explanatory. All coefficient starting with "C" are vehicle specific.

Code: Select all

        float Local_CMinSpeed, Local_CMaxSpeed;
        Local_CMinSpeed = TileSpeed * CMinSpeed;
        Local_CMaxSpeed = TileSpeed * CMaxSpeed;

        cpVect FaceDir = cpvnormalize(VehicleShape->body->rot);

        float a = 0;
        if (Key_Acceleration) {
                if (Velocity > 0) a = CAcceleration;
                        else a = CDeceleration;
        } else if (Key_Deceleration) {
                if (Velocity > 0) a = -CDeceleration;
                        else a = -CAcceleration;
        } else {
                if (Velocity > CEpsilonVelocity) a = -CRollDeceleration;
                        else if (Velocity < -CEpsilonVelocity) a = CRollDeceleration;
        }
        Velocity += a;

        if (Velocity > Local_CMaxSpeed) {
                Velocity = Local_CMaxSpeed;
        } else  if (Velocity < Local_CMinSpeed) {
                Velocity = Local_CMinSpeed;
        }

        if (Key_Left) {
                VehicleShape->body->a += (-CTurnRatio - (Velocity * CSteerTurnRatio)) / (180.0 * M_PI);
        } else if (Key_Right) {
                VehicleShape->body->a += (CTurnRatio + (Velocity * CSteerTurnRatio)) / (180.0 * M_PI);
        }

        float TileDriftFactor = CurTile.DriftFactor / 255.0;
        float TileOversteerRatio = TileDriftFactor * COversteerRatio;
        VehicleShape->body->a = NormAngle(VehicleShape->body->a);
        if (std::abs(SteeringDirection - VehicleShape->body->a) < M_PI) {
                SteeringDirection = (TileOversteerRatio * SteeringDirection) +  ((1 - TileOversteerRatio) * VehicleShape->body->a);
        } else {
                /* Angle overflow */
                SteeringDirection = NormAngle((TileOversteerRatio * NormAngle(SteeringDirection + M_PI)) + ((1 - TileOversteerRatio) * NormAngle(VehicleShape->body->a + M_PI)) - M_PI);
        }

        cpVect SteerDir;
        SteerDir.x = cos(SteeringDirection);
        SteerDir.y = sin(SteeringDirection);
        float Drift = (1 / (1 + exp((std::abs(Velocity) - CDriftLimit) * CDriftSteepness)));
        VehicleShape->body->v = cpvadd(cpvmult(FaceDir, Velocity * Drift), cpvmult(SteerDir, Velocity * (1 - Drift)));

joe
Posts: 10
Joined: Sun Dec 02, 2007 3:27 pm
Contact:

Re: Simulating vehicle body

Post by joe »

Hi,

I've looked a little more into the problem - first I answered my question from the last post by RTFMing (sorry for that :-/) and am now using the "Set angle" functions where appropriate. But that didn't resolve the problem.

The actual problem is that I control the whole car physics, e.g. before every time step, I'm manually setting speed and direction and so on. When a collision occours, the vehicle is somehow rotated/decelerated, but my code immediately accelerates it back in the next timestep. This is *bad*.

Does anything come to your mind except resolving all vehicle/xyz-collisions manually? That would, I imagine, be kind of hard to do...

Greetings,
Johannes
lucas
Posts: 54
Joined: Wed Sep 26, 2007 2:34 am
Contact:

Re: Simulating vehicle body

Post by lucas »

Instead of setting the velocity every step, use cpBodyApplyForce
Tangame - a tangram puzzle game with physics.
http://code.google.com/p/tangame/
joe
Posts: 10
Joined: Sun Dec 02, 2007 3:27 pm
Contact:

Re: Simulating vehicle body

Post by joe »

lucas wrote:Instead of setting the velocity every step, use cpBodyApplyForce
Hmm, this solves the problem with simulation, however it destroys the car physics. It then behaves like a "spaceship" again. How can I use ApplyForce or ApplyImpuse in a way so I get the desired *velocity* vector in the next timestep? Is that possible?

Thanks,
Johannes
citrys
Posts: 16
Joined: Thu Nov 15, 2007 12:26 am
Contact:

Re: Simulating vehicle body

Post by citrys »

joe wrote:The actual problem is that I control the whole car physics, e.g. before every time step, I'm manually setting speed and direction and so on. When a collision occours, the vehicle is somehow rotated/decelerated, but my code immediately accelerates it back in the next timestep. This is *bad*.
Have you added collision callback functions yet? When there's a collision, it might be a good idea to update your local speed/direction values from the physics engine. Or even let it simulate for a couple of steps, then do the update.

If you go the full simulation route, it seems like you ought to be able to simulate a friction force but I'm having trouble visualizing it. Since a vehicle probably has very little longitudinal friction and a lot of lateral friction, you might need to compute lateral velocity vectors relative to the vehicle angle and subtract them (or a portion thereof) from the vehicle's velocity vector.

In Ruby:

Code: Select all

head_vect = vehicle.shape.body.rot
velocity_vect = vehicle.shape.body.v

# Use whichever normal vector the velocity projects onto (either left or right will work if velocity is straight ahead)
normal_vect = velocity_vect.dot(head_vect.perp) > 0 ? head_vect.perp : -head_vect.perp

# Get the vehicle-relative x/y components of the velocity
long_vect = velocity_vect.project(head_vect * velocity_vect.length)
lateral_vect = velocity_vect.project(normal_vect * velocity_vect.length)

# Reduce the x component
vehicle.shape.body.v = long_vect + lateral_vect * 0.1  # or a value related to the slipperiness of the tile
There's a good chance I've left something out; I don't have a good representation of the system in my head. But I hope it gives you some ideas.

EDIT: Indeed I did leave at least one something out--velocities in half the coordinate system! Updated code to pick the left or right heading normal vector depending on which way the velocity swings. And yes, this is faking it. =)
Last edited by citrys on Tue Dec 04, 2007 12:21 pm, edited 2 times in total.
Post Reply

Who is online

Users browsing this forum: No registered users and 14 guests