NVIDIAGameWorks / PhysX

NVIDIA PhysX SDK
Other
3.15k stars 796 forks source link

Reduced coordinate articulation revolute joints with small masses/inertia not being driven #484

Open prnthp opened 2 years ago

prnthp commented 2 years ago

Hello,

This issue has been bugging me for several months now. The problem is: given a reduced coordinate articulation with revolute joints, links with a mass or inertia small enough (< 0.01 in mass) will not be driven no matter how high the stiffness is. The joint's friction, damping, nor the scene's solver (PGS/TGS), nor the timestep, nor the sleep settings, etc. seem to be able to do anything.

The issue is present even in Unity. I had to artificially inflate the inertia tensors to get the joints to move.

Given the small mass I knew it had to be some kind of epsilon problem or minimum limit.

After weeks of researching I found this line: https://github.com/NVIDIAGameWorks/PhysX/blob/c3d5537bdebd6f5cd82fcaf87474b838fe6fd5fa/physx/source/lowleveldynamics/src/DyFeatherstoneForwardDynamic.cpp#L149

Changing 1e-5f back to PX_EPS_REAL seems to do the trick.

Is there a specific reason why 1e-5 was chosen? I haven't noticed any instabilities after setting it to float's epsilon.

Appreciate any insights. Thank you!

kstorey-nvidia commented 2 years ago

There were some issues with setting this threshold smaller, but those should be pretty much resolved so you should be safe to use a smaller value. We do even have some models now where PX_EPS_REAL is not small enough and we've been internally testing with an even smaller thresholds without hitting issues. We've been in contact with Unity who has reported this issue to us (this may or may not have originated from a report by you) and they/we have decreased this tolerance in our respective development branches, so hopefully an updated unity release will resolve this.

Having said this, if you are simulating very small robots in SI units, you may find you get better numerical results shifting from m to cm distance units. Similarly, if the masses are very small, you may find shifting from kg to g mass units helps. We recently worked on simulating an articulation with links that were approximately the size of a grain of rice. We were able to simulate it with these thresholds adjusted, but the behavior was measurably better when simulating using cm units than m units.

I don't know if this would be practical for your application, but if you are aiming to mainly work with relatively small robots, you may be able to get good results from the existing unity integration by scaling the robots up to cm units, where the inertia values will be significantly larger. Properties like drive stiffness etc. would increase proportionately, so this kind of unit adjustment does influence quite a few places.

I'm not super familiar with working with unity, so I don't know if they have exposed the PhysX tolerance scales properties. If they are exposed, you can adjust these to tell PhysX how many units per meter and how many units gravity is and it will automatically scale all the tolerances for actors in your scene so that they work consistently in cm and m units so at least you won't need to account for setting contact offsets and various other properties.

prnthp commented 2 years ago

Thank you! I highly appreciate the amount of detail you've provided here.

I wasn't the first to report this to Unity and I just learned that there is now an alpha with a fix in place.

And thank you for the suggestions, unfortunately scaling stuff would be difficult since we're spanning from meter sized to centimeter sized joints, e.g. the human arm.

(Leaving this issue open since this repo is in the "broken" state)