Custom Suspension Model

This is in reference to my other post about wheel physics, last year. Related to the project: https://github.com/Murph9/RallyGame

The game engine (JMonkeyEngine3) has a built in VehicleControl which handles suspension forces and wheel translation which used a translation of bullet (C++) called jbullet (Java).

I moved to bullet (C++) as I thought jbullet isn’t as supported as it was before in jme 3.2 - but this broke how I was accessing the built in VehicleControl class as some internal fields became inaccessable (as I was extending the PhysicsVehicle class).

This meant that I needed to basically rewrite the jbullet class myself. Since then I have found that it should still work it was just my project setup that failed me but the underlying rigidbody was hidden in the way I was accessing it. Although updateing the suspension been a long time coming as the suspension model didn’t have sway bars (more on this soon). And so to spoiler this early I’ve ‘finished’ it, I decided it would be a good time to explain problems that I have had.


First I found the sources for all the classes involved, this is the jme3 VehicleControl class, the jbullet class and a source for the bullet class. So some copy/paste happened, I had a low level class which handled everything with at least 300 errors in the editor. Added all the references the solution had available but still I was getting a lot of errors.

After that came was translating raycasting using bullet library rather than jbullet, decided to add a source to the methods into the editor for quick reference at this point. Skipping over any details, the raycast returns a method in “world” space which is decidedly not. From what the source did it could only mean that it was backwards causing this line in the raycast class: rd.hitNormalInWorld = result.getHitNormalLocal(); It is still right as of now, who knows, but it leads into the next problem.

The Vector3(f) classes weren’t compatible in the 2 reference files below (along with Quaternion and Matrix classes as well) - lets just say that a method translation reference notepad++ file was made to map them. https://github.com/bubblecloud/jbullet/blob/master/src/main/java/com/bulletphysics/dynamics/vehicle/RaycastVehicle.java vs https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-jbullet/src/main/java/com/jme3/bullet/objects/PhysicsVehicle.java Methods that differred basically boiled down to order of arguments and whether or not it returned the value as well. A few methods did very different things .sub() being a good example, there is also heavy use of Transform which the game library doesn’t use much. And finally the translation seemed successful and I could at least continue.

Next main problem was that the class I had in my game MyPhysicsVehicle was doing everything, from input control to traction curve calculations - this had to go and did. I decided to split the files into RayCar (suspension and traction), RayCarPowered (engine torque and braking), RayCarControl (jme3 integration i.e. visual model and input control). Honestly an arbatory split.

The suspension itself caused the most problems as the world->local->world translation of the forces caused many NaN and inf vector values due to either positive feedback loops or div by small or 0 numbers. The body.impulse(force, pos) method in jme3 doesn’t explicitly say whether its in local or world space - although in bullet there is no concept of local space so this should have been obvious in retrospect. Later I found the suspension force was being incorrectly converted to local space, which meant that driving on slopes caused you to slide up them unpowered, very small commit for the largest change that one.

The next and hopefully last large problem was deciphering what the constants being sent to the suspension model where, values like suspensionRestLength and maxSuspensionTravelCm which didn’t sit with how I wanted the suspension to work. My new model works closer to values you can retrieve from the real world. My model a preload force, which defines the suspension force at maximum suspension travel (wheel furthest from the car body), and a force which is linear from that point up until the minimum suspension travel (closest to the car body).

And lastly I finally got to add a new feature, sway-bars (or anti-rol bars) which basically just try and keep the wheels and the same suspension travel with each other.

Current tests of this system work really well, but the last outstanding problem is that the spring constant seems off compared to real world values.