Closed DarioMaggiari closed 3 years ago
It would be good to create a trivial PyBullet example for this, it should be reproducable. Likely there are conflicting constraints in the constraint solver that cannot be resolved by the LCP solver, such as velocity motor and joint limit. The residual error may cause the issue.
One experiment would be using the Dantzig direct LCP solver instead of the default iterative PGS-style LCP solver.
It is indeed a solver issue, see attached. I'll look into it. Selecting a direct LCP solver fixes it, in the PyBullet example (see attached bug.zip) It looks like PhysX has a similar issue. bug.zip
Indeed, the residual error causes the issue for the iterative solver. Increasing the number of solver iterations to 10000 'solves' it as well.
@erwincoumans thanks for the solver pointer - I tried setting up my testcase from the PhysX issue you linked in Bullet using the Dantzig solver, and it seems to work a lot better than what I was able to set up in PhysX so far.
We should have an improvement for this coming in PhysX soon. See link below demonstrating handling this case with 1 solver iteration:
https://github.com/NVIDIAGameWorks/PhysX/issues/70
The currently-available code can also handle this by limiting the drive force, otherwise we just get into an infinite game of one-upmanship between 2 antagonising constraints. This is actually a fairly reasonable solution given that real motors cannot apply infinite torques.
Thanks Kier, can you briefly explain you improvement that solves it in 2 iteration? Do you solve multiple constraints directly in a block? (instead of iteratively)?
@kstorey-nvidia that sounds great, looking forward to giving it a try!
Hello,
I wrote a simple urdf file (at the end of this message) loaded by the standard urdf multibody example.
You can simply load the urdf with the standard importer example (ImportURDFSetup.cpp), inserting the file name at line 126.
There are 3 links. The blue link is the fixed base, then we have a white link connected to the base via a revolute joint and then the red one connected to the white link with another revolute joint.
I apply a velocity on motorized revolute joint in order to move the white link, but at the end of its superior and inferior limit the red link move itself. Conversely, I've applied a velocity on motorized revolute joint in order to move the red link and, at end of its inferior limit, the white link start to move itself as side effect.
In general this is an unwanted behavior: if I move a motor I don't want to move another motor in any condition, unless applying an explicit velocity on that motor.
You can look at the behavior in the video attached:
https://drive.google.com/open?id=1aMHtXjsiP5sCGLFt-jXhQfcRoP11DRlI
I've tried to modify solving parameter in the stepSimulation method at line 342 (ImportURDFSetup.cpp). Using aggressive parameters, the behavior is a little more "predictable" but still not usable, I think.
m_dynamicsWorld->getSolverInfo().m_numIterations = 100; m_dynamicsWorld->stepSimulation(deltaTime, 100, 1. / 540.);
Thanks, bye
test_joints_MB_urdf.txt