Linear Position Drive and Constraint Forces

I am attempting to build a physics-based vehicle prototype/testbed. My current wheel model needs to know the wheel’s loading to calculate maximum grip, etc. It appears that there is no way to know how much force a Linear Position Drive on a physics constraint component is applying. Using “Get Constraint Force” returns the forces for the locked linear axes, but it completely ignores the forces applied by the linear position drive. Here are the steps to produce this effect.

Make a new actor with 2 cubes with physics simulated on one of them.

Move one cube some distance above the other, so the constraint can act as a spring between them.

Add a constraint between the 2 cubes with all 6 degrees of freedom locked.

OnTickEvent -> Get Constraint Force -> Print the resultant linear force vector.

Observe the output, it should be mostly in the z direction and it should reflect the weight of whatever cube is being held up.

Set the constraint’s Linear ZMotion to Free, and enable the Linear Position and Velocity drives with default settings.

Observe the output, it will read zero on the Z axis, even though the constraint is clearly applying a force through the position drive.

If anyone has any ideas or workarounds for discovering the force applied by the position drive, I would be incredibly grateful. I’m pretty much stalled on my work until I figure out how to do this.

https://www.youtube.com/watch?v=MX0CEJSZzDQ

Here’s a video I made to demonstrate the problem I’m having.

Anyone have any idea?

Indeed, it returns just rubbish. Did you submitted it as a bug report already?

What I see is that when linear drive is switched off, you seam to be getting proper results. With linear drive on, you see only what is left there. Maybe you know the scale of units for Linear Position Strength?

the way the physx d6 joint is implemented internally is that it has two separate sets of constraints. The ‘drive’ constraints are separate from the regular limit/locked constraints. technically both sets could be active at the same time. So with your wheel example the drive z-constraint would be like the springs/shocks that allow a little bit of movement and the limit z constraint would be something else (car-frame) that prevents the axle from moving beyond a certain point.

It sounds like the blueprint interface is just providing the impulse/force being applied with the regular (non-drive) set of constraints.

A possible workaround… The drive constraints by default use a ‘spring’ mode (or hooke’s law), rather than ‘use as much force as i’m allowed’, to return to their goal position/orientation. Therefore you can simply use the difference between the target position and the actual position to know what the force is (at least approximately due to time-step integration). It should be a linear response. Indeed, from the nvidia docs, assuming just position drive, you get: force = spring * (targetPosition - position).

I just whipped up a quick test with a default cube attached to a drive spring with 100 position strength (and 10000 force limit, but any big number should do). When simulated it bobs about 10 units below the target height. One weird thing i noticed is that this position strength parameter seems to be taking the attached actor’s mass into account since adjusting the mass by itself didn’t cause it to dip lower. Trying another approach… adding a second cube resting on top (doubleing the weight), it bobs about 20 units below the target height. If i double the weight of the 2nd cube on top (triple total weight), it bobs down 30 units.

I’ve submitted it as a bug: [Bug] Get constraint force - doesn't includes linear drive - World Creation - Unreal Engine Forums
Not sure if it’s a bug in UE4 or Physx does it like that.
Do you remember if they had a formula for velocity drive? Because estimating only spring won’t get it to a proper result. So far I just made my own suspension with SphereTrace, but using more complicated collision shape would be so much better.

To answer your second question, yes they do have a formula that includes velocity drive, but if that is turned off and just position drive is on, then the formula is simple and there should be a linear relationship between the force and how far the spring is from its rest length (how much the body is displaced from its target position). Hence that might suffice for a workaround.

After my previous post (above) from my home account, I went to the office and dug into the code a bit deeper this afternoon, and for the limit/fixed constraints there is a flag (Px1DConstraintFlag::eOUTPUT_FORCE) for writing back the applied force. For some reason this flag does not appear to get set for the drive constraints.

I then noticed that in an older version of physx (3.2), that this flag looks like it would be set for drive constraints. I did have an physx3.2 executable to confirm, but the code is pretty clear. I sent an email to nvidia to see if this change was intentional or an oversight.

If anybody cares for the gritty details, see public domain file:
http://physx3.googlecode.com/svn/trunk/PhysX-3.2_PC_SDK_Core/Source/PhysXExtensions/src/ExtConstraintHelper.h
then look for function Constraint::Helper::linear() which is a function that gets called for each dimension where a restriction/constraint is added. See file:
http://physx3.googlecode.com/svn/trunk/PhysX-3.2_PC_SDK_Core/Source/PhysXExtensions/src/ExtD6JointSolverPrep.cpp
to understand how this helper gets used.

What’s different now is the current version of the same code (assuming you have the same that I do, i dont know of a public link to the source) looks like its been refactored slightly from the previous version and doesn’t set this flag. It gets set in other places but only for the other constraints types mentioned, unfortunately not for drive constraints.

Not sure if this change was intentional, or an oversight. So i fired off an email to nvidia asking for clarification on this.

Thank you for your help, Stan! So in principal I could try to set that flag myself, but I would need to recompile both physx and UE4 for that, right?
I’ll try this approximation today. For the reference, if other people read this discussion, full formula for linear drive with force and velocity: force = spring * (targetPosition - position) + damping * (targetVelocity - velocity) [https://developer.nvidia.com/sites/default/files/akamai/physx/Manual/Joints.html]

So this is a test project I’ve made (ignore misleading name). https://www.dropbox.com/s/h78g5cmfl9k52fw/SuspensionEstimation.rar?dl=0
Simple cylinder on four legs with physics constraints to simulate suspension.
What I do, is estimate full equation “force = spring * (targetPosition - position) + damping * (targetVelocity - velocity)” but velocity drive have a zero force both in constrains and estimation so it can be ignored.
Suspension force is estimated for each leg separately and summed up, finally divided by 980 to get the mass. Result doesn’t match. Maybe I’ve made a mistake somewhere, as I’m rather tired right now, but code is really simple.
Results don’t match with override mass or without it, they are off by a magnitude actually.

I see you guys have ran with this quite a bit since I posted. I’m still tinkering around with it, I’ve found traces of something called a PhysicsSpringComponent but can’t find anything concrete on it. I’ll experiment with estimating the forces from Hooke’s law. Since I got you in here Stan, do you know any way to get get the normal force on a physics contact? I could use that for my wheel’s loading and bypass the whole suspension system, but I haven’t found a way to get that information either. Thanks for all the help.

You could try to derive it from collision impulse. But I’m not sure how it will work when you drive over objects which simulate physics. Another potential issue is that as suspension settles you won’t be getting any collision events.

unfortunately, yes, this would require a recompile of the physx libs, this setting is something set from (and only visable to) deep within the physx code.

So I’ve tried to estimate mass from collision impulse. J = v * m, if we ignore T as impact detection and reaction are instant. It means we need to calculate velocity of impact as we already know J - impulse.
Calculate velocity of object at impact point -> project it on impact normal -> divide Normal Impulse by projected velocity to get mass. This doesn’t work. Not sure what is going on. How can I check if Normal Impulse is calculated properly by engine?

This is the test project with all code: https://www.dropbox.com/s/3ol7xt2d7mewzyo/NormalForceEstimation%204.9.rar?dl=0

I just used yours to do a quick and dirty shock test on a 1000 kg cube because I can’t handle the flakiness of the constraints - I simply multiplied the force by the mass of the cube and it worked perfectly with 0.5 as spring and damper value, grabbed the z of the linear velocity and applied it along the impact normal as an impulse per tick.

Worked perfectly. It appears the settled force is around 9900. Thanks for the formula!

Interesting. Could you elaborate on this?
Some weeks ago I thought that this didn’t worked because I forgot about Force/Impulse conversion. But at some point I’ve started to apply spring force manually, leaving physics constraint only to handle limits. This way I can have exponential grow of force, asymmetrical dampener and other goodies.