What's the constraint type of suspension limits constraints?

In the SampleVehicle
In PxVehicleWhees::setup
I’m not clear about the constraint type of suspension limits constraints.
Is there any paper or pdf link explain it ?

//Set up the suspension limits constraints.
	for(PxU32 i=0;i<numSuspWheelTire4;i++)
	{
		PxVehicleConstraintShader& shader=mWheelsDynData.mWheels4DynData[i].getVehicletConstraintShader();
		for(PxU32 j=0;j<4;j++)
		{
			shader.mData.mSuspLimitData.mCMOffsets[j]=wheelsData.mWheels4SimData[i].getSuspForceAppPointOffset(j);
			shader.mData.mSuspLimitData.mDirs[j]=wheelsData.mWheels4SimData[i].getSuspTravelDirection(j);
			shader.mData.mSuspLimitData.mErrors[j]=0.0f;
			shader.mData.mSuspLimitData.mActiveFlags[j]=false;

			shader.mData.mStickyTireForwardData.mCMOffsets[j]=PxVec3(0,0,0);
			shader.mData.mStickyTireForwardData.mDirs[j]=PxVec3(0,0,0);
			shader.mData.mStickyTireForwardData.mTargetSpeeds[j]=0.0f;
			shader.mData.mStickyTireForwardData.mActiveFlags[j]=false;

			shader.mData.mStickyTireSideData.mCMOffsets[j]=PxVec3(0,0,0);
			shader.mData.mStickyTireSideData.mDirs[j]=PxVec3(0,0,0);
			shader.mData.mStickyTireSideData.mTargetSpeeds[j]=0.0f;
			shader.mData.mStickyTireSideData.mActiveFlags[j]=false;
		}


		shader.mConstraint=physics->createConstraint(vehActor, NULL, shader, t, sizeof(PxVehicleConstraintShader::VehicleConstraintData));
		shader.mConstraint->markDirty();
	}

Take a look at the method vehicleSuspLimitConstraintSolverPrep. That sets up the 12 constraints used for suspension. There are 4 suspension limits, 4 sticky tire friction constraints acting in the forward direction and 4 sticky tire friction constraints acting in the sideways direction. The suspension limit constraints appear to be hard one sided positional limits but I’m not sure what axis they act in or for what purpose. The other two are dampers which apply an acceleration in their respective directions equal to to 1000 times the target speed for each wheel (I am assuming the 4 constraints are for 4 wheels).

This is referring to PhysX 3.3.4. I haven’t checked 3.4 but presumably it’s similar.

I can add a little more detail to asdasdasdasdasdf’s comment.

The suspension has travel limits but sometimes we need to compress the wheel beyond the travel limit in order to place it on the ground plane. That can happen if the wheel drives over a kerb or a sharp incline. If we push the wheel beyond the suspension limit it will start to visibly penetrate the car. However, if we place the wheel at the suspension limit it will visibly penetrate the ground. We need some extra code to solve this problem.

If the wheel needs to move P distance along the suspension travel direction to place it on the ground but the suspension limit is L (P >L) then the wheel is placed at L and the suspension spring reacts to a suspension compression of L. The remainder (P-L) is passed to a hard constraint. The hard constraint works on the rigid body at the suspension point and pushes it upwards along the suspension travel direction to resolve the remainder (P-L) at the next simulate call. The car gets an impulse at the suspension point that is just large enough to push the wheel out of the ground and maintain the wheel at the suspension limit.

The remaining constraints are the sticky tire constraints along the lateral and longitudinal direction of each tire. The problem is that at very small slip values the slip tends to oscillate around zero. It is actually a computationally difficult problem to bring the car smoothly to rest. This can be solved by reducing the timestep but that is a computationally expensive solution. PhysX vehicles instead use a velocity constraint. The basic idea is that the code records the lateral and longitudinal speeds at each tire. If the longitudinal speed is less than a small threshold speed and has maintained that condition for a threshold time then the constraint kicks in for that tire. The constraint attempts to enforce a velocity constraint on the rigid body along the longitudinal tire direction. The target velocity reduces each frame and asymptotically approaches zero. The same process is repeated for the lateral speed of each tire. I can’t remember the exact details but I think the logic is that the lateral constraints always start after the longitudinal constraints. The sticky tire constraints are broken as soon as the tire is driven by an engine torque.

PhysX allows 12 1d constraints for each custom joint. That worked out great for 4-wheeled cars: 4 suspension limit constraints, 4 lateral velocity constraints, 4 longitudinal velocity constraints. Most of the time zero constraints are active but a 4-wheeled car could theoretically make all 12 active. In practice, I can’t imagine a case where we need a sticky tire constraint and a suspension limit constraint but let’s ignore that for the moment. You might have noticed that the code in PxVehicleUpdate.cpp breaks vehicles up into blocks of 4 wheels and handles 4 wheels at a time. One of the reasons for that is that each block of 4 wheels needs to grab a physx constraint that is made up of 12 1d constraints.

I hope this helps.

Is there any particular advantage to having a single joint that generates 12 constrains rather than 4 joints that generate 3 each or 12 that generate 1 each?

There are a few advantages. It is significantly faster to have just a single joint because it makes better use of cache. After placing the rigid body data into cache it is much better to work on those bodies as much possible. It also helps with convergence to have a single joint because prior to the solver the joint is disagonalised. That means the effect of each 1d constraint on the others in the joint is accounted. That is quite important for the vehicles because the constraints aren’t orthogonal. The book-keeping is also easier if we have a single joint rather than 4 or 12. I only need to manage a single joint rather than work out which 1d constraint matches with joint.

Thanks for your response. That makes sense.

So as a general rule would you recommend one joint per body pair in order to improve performance and convergence?

Yes, that would be my general rule.

awesome. thanks. I’ll keep it in mind.