Simulating vehicle body

Official forum for the Chipmunk2D Physics Library.

Simulating vehicle body

Postby joe » Sun Dec 02, 2007 3:38 pm

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.
joe
 
Posts: 10
Joined: Sun Dec 02, 2007 3:27 pm

Re: Simulating vehicle body

Postby slembcke » Sun Dec 02, 2007 4:42 pm

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/
User avatar
slembcke
Site Admin
 
Posts: 4164
Joined: Tue Aug 14, 2007 7:13 pm

Re: Simulating vehicle body

Postby joe » Sun Dec 02, 2007 4:56 pm

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

Re: Simulating vehicle body

Postby joe » Sun Dec 02, 2007 7:51 pm

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
joe
 
Posts: 10
Joined: Sun Dec 02, 2007 3:27 pm

Re: Simulating vehicle body

Postby slembcke » Sun Dec 02, 2007 8:45 pm

Oops. Sorry.
Code: Select all
VehicleShape->body->rot
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
User avatar
slembcke
Site Admin
 
Posts: 4164
Joined: Tue Aug 14, 2007 7:13 pm

Re: Simulating vehicle body

Postby joe » Mon Dec 03, 2007 5:13 pm

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

Re: Simulating vehicle body

Postby joe » Mon Dec 03, 2007 10:39 pm

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

Postby lucas » Tue Dec 04, 2007 4:40 am

Instead of setting the velocity every step, use cpBodyApplyForce
Tangame - a tangram puzzle game with physics.
http://code.google.com/p/tangame/
lucas
 
Posts: 54
Joined: Wed Sep 26, 2007 2:34 am

Re: Simulating vehicle body

Postby joe » Tue Dec 04, 2007 7:37 am

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

Postby citrys » Tue Dec 04, 2007 9:33 am

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.
citrys
 
Posts: 16
Joined: Thu Nov 15, 2007 12:26 am

Next

Return to Chipmunk2D Physics

Who is online

Users browsing this forum: No registered users and 0 guests