Seeking wisdom for two-wheeled vehicle character

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Skwerl
Posts: 3
Joined: Thu Apr 09, 2009 3:03 am

Seeking wisdom for two-wheeled vehicle character

Post by Skwerl »

I'm having some trouble on a couple different fronts, so I am hoping some of the brains around here can offer suggestions about what route I should take. In my game, the player rides on a two-wheeled vehicle (think Segway) that can fall from 100 units or more, and uses a triangle group from a mesh as the level.
Since my player object has wheels, I immediately tried to shoehorn the VehicleInput and Vehicle classes from the demos into my project, removing and moving a couple weels and configuring the vehicle's body as a simple, squat (1 x 1 x .25) Box object. Is this going to be a reasonable route to take, or is the Vehicle class just not meant for something like this? Would starting from the CharacterController class be a better idea? Or will neither, or something simpler suit my purpose?
If the Vehicle class is a good choice, I'm wondering if someone could give me some general tips on how to set this up, since I've had a lot of trouble thus far. I have tried tweaking the values used in the ConvexCastWheel constructor and the UprightConstraint for more hours that I care to mention, and nothing allows me to drop my player and have it cleanly sit on the ground. When dropped, depending on the height from which I drop it, I have a couple different outcomes. Either the vehicle ends up bouncing from side to side on its wheels for several seconds until it eventually settles (or never does, even with high suspension stiffness and damping values), or it nearly instantly settles upon contact with the ground, but is tilted despite the very restrictive UprightConstraint I put on it.

I'm grateful for any suggestions, as I feel like I'm sort of at a point where trial and error are going to end up with me spinning my wheels (no pun intended) for a lot of time. I've pasted some applicable code below, in case it is of interest. It's basically just a modified version of what's used in the VehicleInput constructor, with some values declared at the beginning of the method for readability.

Code: Select all

public void InitializePhysics(Space owningSpace, float boundsLength, float boundsWidth, float boundsHeight, float mass, float wheelThickness, float wheelRadius, Vector3 leftWheelOffset)
		{
			float forwardAcceleration = 7;
			float backwardsAcceleration = -4;
			float suspensionLength = .3f;
			float suspensionStiffness = 2f;
			float perpendicularSlidingFriction = .8f;
			float rollFriction = .02f;
			float grip = .8f;
			float maxSuspensionForce = 1000000f;
			float suspensionDampening = 100000.8f;

Code: Select all

Entity body = new Box(Vector3.Zero, boundsWidth, boundsHeight, boundsLength, mass);
			vehicle = new Vehicle(body, maxForwardSpeed, maxBackwardSpeed);

			//Increase the inertia parallel to the vehicle to prevent rolling a little.
			Matrix inertiaTensorInverse = vehicle.body.localSpaceInertiaTensorInverse;
			inertiaTensorInverse.M31 *= .5f;
			inertiaTensorInverse.M32 *= .5f;
			inertiaTensorInverse.M33 *= .5f;
			vehicle.body.localSpaceInertiaTensorInverse = inertiaTensorInverse;
			vehicle.body.collisionMargin = .1f;

			Quaternion initialWheelRotation = Quaternion.CreateFromAxisAngle(Vector3.Forward, MathHelper.PiOver2);

Code: Select all

			//Left wheel
			Entity wheelShape = new Cylinder(Vector3.Zero, wheelThickness, wheelRadius);
			wheelShape.collisionMargin = 0;
			vehicle.addWheel(new ConvexCastWheel(leftWheelOffset, initialWheelRotation,
				wheelShape, wheelRadius,Vector3.Down, Vector3.Backward, suspensionLength, suspensionStiffness,perpendicularSlidingFriction, rollFriction, grip, maxSuspensionForce, suspensionDampening));
			
			//Right wheel:
			wheelShape = new Cylinder(Vector3.Zero, wheelThickness, wheelRadius);
			wheelShape.collisionMargin = 0;
			Vector3 wheelOffsetRight = new Vector3(-leftWheelOffset.X, leftWheelOffset.Y, leftWheelOffset.Z);

Code: Select all

			vehicle.addWheel(new ConvexCastWheel(wheelOffsetRight, initialWheelRotation,
							wheelShape, wheelRadius, Vector3.Down, Vector3.Backward, suspensionLength, suspensionStiffness, perpendicularSlidingFriction, rollFriction, grip, maxSuspensionForce, suspensionDampening));


			space = owningSpace;
			uprightConstraint = new UprightConstraint(body, Vector3.Up, (float)Math.PI / 32, (float)Math.PI / 2, 100);
			space.add(uprightConstraint);
			space.add(vehicle);
		}
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Seeking wisdom for two-wheeled vehicle character

Post by Norbo »

The vehicle sounds like a pretty good starting point. You can always fake it more and use some arbitrary system, though.

I would suggest reducing the power of the upright constraint as a first step. Right now, it tries to push the object back upwards once it goes beyond about 6 degrees which, combined with a strong correction force, would generate oscillations. Pushing out the minimum to angles that usually only occur in exceptional cases, like falling off a cliff, should help with steadiness. If you find yourself needing to arbitrarily balance the forward/back tilting of your segway (as opposed to accelerating/decelerating enough to keep it upright), it may be worth it to create a custom upright constraint which takes into account the tilt angle/axis and applies a corrective force.

Then on top of that, increase your suspension stiffness until it feels right. Note that damping values should be between 0 and 1; values outside of this range are clamped internally. Suspension forces will still be applied each frame despite the damping, however.
Post Reply