Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TGS unstable when using non-zero rest offsets #21

Closed
kermado opened this issue Dec 26, 2018 · 8 comments
Closed

TGS unstable when using non-zero rest offsets #21

kermado opened this issue Dec 26, 2018 · 8 comments

Comments

@kermado
Copy link

kermado commented Dec 26, 2018

I thought I'd test the capability of the new TGS solver to handle large mass ratios. To this end, I created a simple test case involving a vertical stack of 5 boxes, where adjacent boxes have a 100:1 mass ratio (the masses are 0.1Kg and 10Kg). The boxes are dimensioned 0.4m x 0.4m x 0.4m and set to use a contact offset of 1mm and a rest offset of 0.5mm. The friction offset is also set to 1mm on the scene descriptor.

I use a constant time-step of 0.01s and each box is set to use 40 positional iterations and 10 velocity iterations. This is using the same 8:2 ratio which I believe is the default but scaled up 5 fold.

This stack is stable using the PGS solver (and will eventually sleep):
pgs

If I switch to using the TGS solver then the stack is immediately unstable and collapses.
tgs

The stack is stable using the TGS solver if I set the rest offsets to 0. Also, if I increase the number of velocity iterations to 40 or so then the stack is stable.

Source code for the snippet.

@kstorey-nvidia
Copy link

kstorey-nvidia commented Jan 2, 2019

This issue is related to your contact offset and friction offset values - 0.001. These define the distance at which contacts at which contacts begin to be created and friction constraints begin to be created. Contact offset is summed, whereas friction offset is not. Contact offsets are defined on a per-shape basis and are summed, whereas friction offset is a per-scene value. Therefore, these settings result in contacts being generated once the shapes are within 0.2mm of each other, and friction beginning to be solved once the shapes are within 0.1mm of each other. These values are very small and leave very little tolerance for any error in the solver.

When you add in 0.05mm of rest offset to each shape (again defined on a per-shape basis and summed), this reduces the tolerance ranges because we now aim to hold the shapes separated by 0.1mm (cutting the tolerance achieved by contact offset of 0.2mm by half).

The PGS solver manages to handle this case because it undershoots error correction - basically, there is usually always some small residual error. Given sufficient iterations, it reaches a stable state but there's a small amount of residual penetration which means that it doesn't show issues with these small tolerances because it doesn't actually achieve separations of exactly 0.

The TGS solver, on the contrary, usually manages to remove all the error. In fact, it often overshoots slightly, but this corrects itself over a few frames as it oscillates around the required result (zero error) a little before finding a resting state.

To make your test work as expected, please increase contact offset and friction offset. Unless you have a really good reason to reduce them, I'd suggest leaving them as their default values.

There are some cases (piles of very thing shapes, like tiles), where reducing contact offset can have a positive impact on performance because it reduces the number of pairs that have to be processed, but this always needs to be weighed off against the stability of the simulation. Contact offsets are critical at reducing jitter because it helps the solver to hold a contact at (or very close to) zero penetration rather than pushing risking pushing shapes out of a penetrating state (and losing a contact) only to have the shapes fall back into a contacting state again in a subsequent frame and repeating the process indefinitely.

@kstorey-nvidia
Copy link

Are you happy with this answer? If so, I'd like to close this issue

@erwincoumans
Copy link

erwincoumans commented Jan 20, 2019

I'm seeing some contact instabilities with TGS too:
https://www.youtube.com/watch?v=u8UHEO71l7o
This is all using default settings (0.02 for contact/rest offset), at 32 solver iterations.
With PGS it is all fine:
https://www.youtube.com/watch?v=EhD_Y_iolWM

I've been trying to tune contact and friction offset, but didn't make it fully stable. Are there other parameters to tune to reduce/remove this instability? It seems related to position stabilization (penetration recovery). Is there some 'maximum penetration recovery' feature?

@kstorey-nvidia
Copy link

Hi Erwin

Would it be possible to provide a repro of the issue?

The most likely property to resolve this issue would be maxDepenetrationVelocity (a bias clamp used to clamp the bias used to correct errors), but I would prefer to try to debug the issue before we resort to adjusting values to try to tune it away.

Thanks

Kier

@erwincoumans
Copy link

erwincoumans commented Jan 21, 2019

Hi Kier,

Yes, it appears the issue causes some normal and friction forces/impulses to be way too big.

Currently this is part of PyBullet, using a URDF importer for PhysX.
For a repro case, do you want

  1. SnippetURDF loader, a few files with only dependency on tinyxml2
  2. A SnippetR2D2 without URDF loader, just a single file reproducing the issue?

Thanks!
Erwin

@kstorey-nvidia
Copy link

Whichever is easiest for you to provide.

@erwincoumans
Copy link

erwincoumans commented Jan 22, 2019

Attached is an attempt to re-create the issue, just copy over SnippetArticulation. It could be self-collision related.
SnippetArticulation.zip
If you run it, watch out for odd contact restitutions. When disabling self-collisions using the aggregate, odd collisions seem to happen less.

@kstorey-nvidia
Copy link

Thanks for the repro. I've spent a bit of time with it and I am now confirming a fix for this issue. This fix is specific to articulation collisions (so unrelated to the original issue, which was a misconfigured value). I need to test in a few internal projects to really make sure that it doesn't cause regressions, and then I'll check into mainline. All things going well, it should appear in the next code-drop. Penetrations are still corrected more aggressively with TGS that PGS, but the overall result looks more correct to me.

I'd also recommend adjusting maxDepenetrationVelocity to a smallish value like 5 or 10. This clamps how much velocity the solver can introduce to correct penetrations. As this was an addition to PhysX in 3.3, we defaulted this value to max_f32, but it is generally a good idea to set this to something smaller. This means that larger penetrations may not be resolved in a single frame, but this is usually a good trade-off against uncontrolled and aggressive penetration correction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants