## Simulating vehicle body

Official forum for the Chipmunk2D Physics Library.

### Simulating vehicle body

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,
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.
joe

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

### Re: Simulating vehicle body

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

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/

slembcke

Posts: 4164
Joined: Tue Aug 14, 2007 7:13 pm

### Re: Simulating vehicle body

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.

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

### Re: Simulating vehicle body

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
joe

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

### Re: Simulating vehicle body

Oops. Sorry.
Code: Select all
`VehicleShape->body->rot`
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/

slembcke

Posts: 4164
Joined: Tue Aug 14, 2007 7:13 pm

### Re: Simulating vehicle body

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.

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

### Re: Simulating vehicle body

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
joe

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

### Re: Simulating vehicle body

Instead of setting the velocity every step, use cpBodyApplyForce
Tangame - a tangram puzzle game with physics.
lucas

Posts: 54
Joined: Wed Sep 26, 2007 2:34 am

### Re: Simulating vehicle body

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
joe

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

### Re: Simulating vehicle body

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.rotvelocity_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 velocitylong_vect = velocity_vect.project(head_vect * velocity_vect.length)lateral_vect = velocity_vect.project(normal_vect * velocity_vect.length)# Reduce the x componentvehicle.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.
citrys

Posts: 16
Joined: Thu Nov 15, 2007 12:26 am

Next