# What's the equation of spring constraint/hard constraint?

/**
Each constraint is either a hard constraint or a spring. We define the velocity at the constraint to be
the quantity

v = body0vel.dot(lin0,ang0) - body1vel.dot(lin1, ang1)

For a hard constraint, the solver attempts to generate

1. a set of velocities for the objects which, when integrated, respect the constraint errors:

v + (geometricError / timestep) = velocityTarget

1. a set of velocities for the objects which respect the constraints:

v = velocityTarget

Hard constraints support restitution: if the impact velocity exceeds the bounce threshold, then the target velocity
of the constraint will be set to restitution * -v

Alternatively, the solver can attempt to resolve the velocity constraint as an implicit spring:

F = stiffness * -geometricError + damping * (velocityTarget - v)

where F is the constraint force or acceleration. Springs are fully implicit: that is, the force or acceleration
is a function of the position and velocity after the solve.

All constraints support limits on the minimum or maximum impulse applied.
*/

[b]I think The comment above is not easy to understand.
I’m not clear about
v = body0vel.dot(lin0,ang0) - body1vel.dot(lin1, ang1)
F = stiffness * -geometricError + damping * (velocityTarget - v)

How to compute the Jacobian of the constraints?
I just know how to solve a linear equations.
J * u = b;
So I think Px1DConstraint is just a row of J,But Why compute a row in this way?

``````PxVec3				linear0;				//!< linear component of velocity jacobian in world space
PxReal				geometricError;			//!< geometric error of the constraint along this axis
PxVec3				angular0;				//!< angular component of velocity jacobian in world space
PxReal				velocityTarget;			//!< velocity target for the constraint along this axis

PxVec3				linear1;				//!< linear component of velocity jacobian in world space
PxReal				minImpulse;				//!< minimum impulse the solver may apply to enforce this constraint
PxVec3				angular1;				//!< angular component of velocity jacobian in world space
PxReal				maxImpulse;				//!< maximum impulse the solver may apply to enforce this constraint
``````

[/b]

Could you provide some more context?

When I learn Bullet,The author said it didn’t use a spring to solve constraint because it’s hard to tune
Bullet used a soft constraint model instead:
[b]
Newton’s Law
m*dv/dt=lambda

velocity constraint
Jv+softnesslambda+bias = 0;

the integrator solver is semi-implicit

So What’s the equation used in PhysX?
[/b]

The spring constraint is only active when the spring exceeds the spring limit. In normal operation of the vehicle the spring constraint does absolutely nothing. It is only there to help the car over kerb-stones and sudden bumps by giving the rigid body an extra impulse. All it does is add an impulse to resolve the difference between the computed geometric compression and the maximum allowed compression specified by vehicle parameters. This will not affect the normal handling of the simulated vehicle.

I also avoided using the spring constraint because it is hard to tune. Using a physx spring constraint would also have introduced a frame delay between the spring force and the tire load used for the tire force computation. There were some other performance and API concerns that led to the choice of an explicit spring.

The spring code in PxVehicleUpdate.cpp is the code that you want to look at. PhysX vehicles use an explicit spring model to compute the spring forces. It is simple as F = stiffnessdisplacement + dampingspeed.

Why compute v in this way?
v = body0vel.dot(lin0,ang0) - body1vel.dot(lin1, ang1)

We’re not doing it in any specific way and nothing out of the ordinary is happening. That is just the equation for computing the relative velocity of the constraint. The “dot” is perhaps a bit of a misleading term because this is really more of a velocity projection involving the sum of two dot products.

The relative velocity is just:

constaint vel = [dot(body0.linVel, constraint.linear0) + dot(body0.angVel, constraint.angular0)] -
[dot(body1.linVel, constraint.linear1) + dot(body1.angVel, constraint.angular1)]

That is all that we’re doing there. We could have chosen other data formats and representations but the maths would remain the same.