Car Spindle Joint Issue

Hi all!

I am simulating a car spindle/wheels so that it can turn and roll in the direction its wheels are pointing.

And this works very nicely when the car itself is not heavy (40 units). When I set it heavier, an issue with the spindle becomes apparent.

Here’s how it is set up:

The axle is the parent of two spindles (left/right) and each spindle has a wheel attached. The spindles are attached to the axle (actually, the car parent body) via free hinges (local z axis, see below) and the wheels are attached to the spindles via free hinges as well (local x axis, see below).

The spindle rotates around the local z axis (Hinge Axis Local Z set to 1):


The wheel rotates around the local x axis (Hinge Axis Local X set to 1):

As I said, without the correct car weight, this works nicely when I appy an angular velocity to the wheels, the car rolls forward, and when I constrain the rotation of the spindle via script, the car turns. So far, great!

Sadly, when I start setting the main car body’s mass to higher values, this happens:
5249564--524402--cronk.gif

My question:
Why is the spindle joint not constrained to only rotating around its local z axis?

Many thanks in advance!
Florian

1 Like

Hello Florian,

The constraints are solved by gauss seidel, which can’t handle large mass ratios between bodies because it iteratively solves the constraints one at a time. For example, say you have a 1kg box sitting on the ground, and you stack a 1000kg box on top of it. Gravity pushes both bodies down. Then the ground pushes the 1kg box back up. But then the 1000kg box pushes the 1kg box back down into the ground again, because it can’t “see” the constraint that the 1kg box has with the ground, and it’s too heavy for the 1kg box to push it up significantly. It would take thousands of iterations for gauss seidel to get close to the correct solution. This is probably what’s happening with your wheels.

One idea to improve it would be to artificially increase the mass of the wheels. It’s not physically accurate, but it should enable them to push the car back up against gravity. Another thing you could do would be to increase or make infinite the wheels’ inertia about the axes that are not free. If you did that, they should not rotate incorrectly, but they would still get pushed into the ground as in the example with the light and heavy boxes.

Many vehicle simulations don’t use rigid bodies for wheels at all, and instead use queries to determine how close the chassis is to the ground and apply the appropriate suspension forces. Another reason for doing this is to enable custom simulation of the friction forces on the tires, since rigid body friction is a lot simpler.

1 Like

Regarding artificially increasing the mass or inertia of the wheels, note that you can do that virtually just in the context of one or more of your constraints by using JacobianHeader.MassFactors - i.e. you don’t have to change its actual mass properties. That allows you to apply a targeted workaround.

1 Like

If not wishing to use queries as Max suggests, then along with tweaking the mass or inertia of the wheels as suggested by Rory, you may also wish to fake the contact velocity between the wheel and the surface and not have the wheel roll at all. The ModifyContactJacobians demo is a good one to look at for this sort of customisation.

Thanks so much Max, Rory, and Stevee for your suggestions!

I had looked at all the Physics samples beforehand and saw the RaycastCar example, but decided to not go this route as I intended to not fake as much as possible, since down the road I want the (most) correct behaviour when e.g. a wheel is blown off. In hindsight, the RaycastCar example was a big sign that if the way I’d like to do it is workable, then you guys would have done it that way :smile:

Ok, so from your suggestions I have quite a few options available of making this work by trading in a bit of “realism”:

  1. Use (spatial) queries to detemine wheel distance from the ground and lots more (as in the RaycastCar example).
  2. Apply JacobianHeader.MassFactors on the constraints that virtually boost their mass. This is nice since the spindle and wheel can keep their realistic mass, but will have to calculate the correct MassFactors based on each vehicle’s structure (there are quite a few of them).

Extra: Disable angular friction this have the wheels slide instead of roll (since I assume the rolling will cause issues when I for performance or other reasons need to reduce the granularity of the PhysicsShape on the wheel). Here I’ll have to switch to normal contact once the wheel is taken/blown off.

  1. Perhaps I could also use springs on the wheels that are constrained on a up/down axis and have the wheels simply slide. over the ground, the vehicle’s wheels being pulled in the direction they are pulling (which is close to solution 1 again).
  2. Perhaps I could virtually reduce the car’s weight (4 tons) to leave the mass setting untouched, and combine that with the disabled angular friction to not get any wheel bumpiness when wheel shapes are low res.

One thing I have to keep in mind is that I’ll have tanks as well. I’m hoping I can reuse the solution, but using more wheels and a much higher friction to simulate tank tracks.

I’ll try these solutions – thanks so much again – and report back :slight_smile:

1 Like

Speaking of tanks - for reference we built a demo of a tank driven by surface velocity some years ago, it behaved quite nicely:

It is really just a bunch of cylinders on springs and one “skid” between each. So more like a pair of bendy skis really. All the motion comes from having a high friction and applying a virtual surface velocity to the contact jacobians, nothing actually rotates in the physics. The rotation of the wheels and tracks are purely in the graphics side, with the tracks curved using a spline.

1 Like

Thanks! This looks very realistic. Can I ask why the skids were necessary? I am thinking about using a
StiffSpringJoint, combined with a LimitDOFJoint for the wheels, and have the wheels collide with the ground, applying a surface velocity. Do the skids provide a more consistent contact surface?

Yeah, the skids were just to provide a surface representing the tracks. It helps avoid the avoid pointy bits of the landscape, or other bodies, getting wedged in between the wheels, e.g:
5275086--528432--upload_2019-12-12_13-1-3.png
I would suggest starting with just the wheels to prove out the idea, and adding the skids later if you need that higher fidelity.

1 Like

Thanks for the suggestion, @Rory_Havok , I’ll go the route you suggest!

Thanks again for the help!

I’ve now set up system of a stiff spring joint and a limit DOF joint (to get a vertical spring on the wheels), using – for now – box colliders.

Also, I’ve used the very nice callbacks (PostCreateContacts, PostCreateContactJacobians) and ModifiableJacobianHeader to set a forward velocity on the wheels:

jacHeader.SurfaceVelocity = new SurfaceVelocity {
    LinearVelocity = math.rotate(localToWorld.Value, new float3(0.0f, 0.0f, wheel.currentLinearVelocity)),
    AngularVelocity = new float3(0.0f, 0.0f, 0.0f)
};

This works quite nicely already! However, there’s a jitter:

5285505--530067--wheel-jitter.gif
5285505--530070--wheel-jitter-gizmos.gif

Not sure if it’s very well visible in the GIFs, but there is a forwards/backwards jitter. From a naïve standpoint, I’d expect no forward backwards movement by the wheels to happen, due to the Limit DOF, expecting that the SurfaceVelocity instantly applies to the whole vehicle.
But I assume there are two systems fighting against each other – the DOF constraint vs. the velocity being applied.
Is my assumption correct? If so, how could I avoid the jitter?

Many thanks in advance for any pointers