NVIDIAGameWorks / PhysX

NVIDIA PhysX SDK
Other
3.15k stars 794 forks source link

Joint Stiffness of PxArticulationReducedCoordinate depends on elapsedTime #112

Open smartcam3d opened 5 years ago

smartcam3d commented 5 years ago

Hello, i am writing a robotics simulator for industrial robots. Large industrial robots typically have a joint stiffness of ~ 10^6-10^7 Nm/rad. I noticed a strong dependence of the deflection of the robot on the time step of the simulation when applying a static force. Shorter timesteps lead to a higher stiffness / a smaller deflection. Due to the high stiffness and high Eigenfrequencies of the system (> 10 Hz), I chose the timestep in the range of 0.01 - 10 ms.

The most important function calls for the model creation are: Creation of the articulation: articulation = gPhysics->createArticulationReducedCoordinate();

Creation of multiple links:

        PxArticulationLink* pxLink = articulation->createLink( parent, currentPose);
        pxLink->setLinearDamping(0.0000);
        pxLink->setAngularDamping(0.0000);
        pxLink->setMaxLinearVelocity(100.0);
        pxLink->setMaxAngularVelocity(100.0);
        pxLink->setMass(childLink->mass);
        pxLink->setMassSpaceInertiaTensor(PxVec3(childLink->I1,childLink->I2,childLink->I3));
        pxLink->setCMassLocalPose(QMatrix2PxTransform(childLink->interiaPose));

Connection of the links via spherical joints:

            PxArticulationJointReducedCoordinate* pxJointTilt = 
                    static_cast<PxArticulationJointReducedCoordinate*>(pxLinkTilt->getInboundJoint());
            pxJointTilt->setJointType(PxArticulationJointType::eSPHERICAL);
            pxJointTilt->setParentPose(*T_parent_joint);
            pxJointTilt->setChildPose(*T_child_joint);
            pxJointTilt->setMotion(PxArticulationAxis::eTWIST,  PxArticulationMotion::eLIMITED);
            pxJointTilt->setMotion(PxArticulationAxis::eSWING1, PxArticulationMotion::eLIMITED);
            pxJointTilt->setMotion(PxArticulationAxis::eSWING2, PxArticulationMotion::eLIMITED);
            pxJointTilt->setLimit(PxArticulationAxis::eTWIST,-1.25f,1.25f);
            pxJointTilt->setLimit(PxArticulationAxis::eSWING1,-1.25f,1.25f);
            pxJointTilt->setLimit(PxArticulationAxis::eSWING2,-3.13f,3.13f);
            pxJointTilt->setFrictionCoefficient(0.0f);
            pxJointTilt->setMaxJointVelocity(1000.0);
            /// set Drive to 0 position with target velocity 0
            pxJointTilt->setDrive(PxArticulationAxis::eTWIST, joint->mechanical.stiffRotX,0.000f,PX_MAX_F32,PxArticulationDriveType::eFORCE);
            pxJointTilt->setDrive(PxArticulationAxis::eSWING1,joint->mechanical.stiffRotY,0.000f,PX_MAX_F32,PxArticulationDriveType::eFORCE);
            pxJointTilt->setDrive(PxArticulationAxis::eSWING2,joint->mechanical.stiffRotZ,0.000f,PX_MAX_F32,PxArticulationDriveType::eFORCE);
            pxJointTilt->setDriveTarget(PxArticulationAxis::eTWIST,0.0f);
            pxJointTilt->setDriveTarget(PxArticulationAxis::eSWING1,0.0f);
            pxJointTilt->setDriveTarget(PxArticulationAxis::eSWING2,0.0f);
            pxJointTilt->setDriveVelocity(PxArticulationAxis::eTWIST,0.0f);
            pxJointTilt->setDriveVelocity(PxArticulationAxis::eSWING1,0.0f);
            pxJointTilt->setDriveVelocity(PxArticulationAxis::eSWING2,0.0f);

The solver properties for the articulation are adjusted and the articulation is added to the scene:

        articulation->setStabilizationThreshold(0.0f);
        articulation->setSolverIterationCounts(100,50);
        gScene->addArticulation(*articulation);

Applying a constant / static Force to the last link before each simulation step:

pxLastLink->addForce(force);

The difference in the simulated deflection seems to be less dependant on the time step when using PxForceMode::eIMPULSE when using the method addForce.

EDIT: The problem seems to appear with the new temporal Gauss-Seidel solver. The projected solver seems to be less dependant on the step size.

The PhysX Setup is set as follows:

    gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, errorCallback_);
    tolScale.speed = 1.0f;
    tolScale.length = 1.0f;
    gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, tolScale, true, gPvd);
    PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
    sceneDesc.gravity = { 0.0f, 0.0f, -9.81f };
    gDispatcher = PxDefaultCpuDispatcherCreate(1);
    sceneDesc.cpuDispatcher = gDispatcher;
    sceneDesc.filterShader = PxDefaultSimulationFilterShader; //PxDefaultSimulationFilterShader
    sceneDesc.solverType = PxSolverType::eTGS;
    gScene = gPhysics->createScene(sceneDesc);

Is the variing stiffness of the reduced articulation a known issue? Is there a workaround? Shouldn't the deflection be independent of the time step for static loads?

Thank you for your help!

Best regards,

Florian

kstorey-nvidia commented 5 years ago

Hi

The underlying formula being used is an implicit PD controller. It is intended to be time-step agnostic, but time-step size will still impact behaviour because this controls the frequency at which positional errors are sampled. The higher frequency, the more frequently the PD controller detects and corrects error, so the the less error there will be. However, it should naturally converge. This is unavoidable because we are simulating continuous motion using discrete sampling.

The TGS technique, however, updates the positional error and velocity error terms fed into the PD controller formula each solver iteration. This can lead to it correcting error very quickly when there is relatively high joint stiffness and small time-steps. We have recently changed how these joint drives are simulated (not yet released), and this should give a much more consistent result regardless of iteration count or time-step.

I will try to verify this with a similar configuration ASAP (probably later this week).

Thanks

Kier

smartcam3d commented 5 years ago

Hi,

thank you for the very fast response and helpful information! I also tried to write the reaction torques directly to the cache of the articulation. I think this method is well suited for slowly changing reaction torques and slow movements. For fast changes in drive error, I noticed, that it would be very beneficial if one could update the joint torques between every substep of the simulation. When only updating the torques once per simulation step (not once per iteration of the solver), the system very quickly gets unstable.

Is there a possibility to provide an abstract drive, where one could implement the function for the reaction torque by a custom implementation? This would give us the freedom of implementing very complex reaction torques (e. g. with backlash, actuation or a sophisticated friction model).

I am very impressed by the work behind PhysX and want to thank every developer pushing the library forward!

Best regards,

Florian

kstorey-nvidia commented 5 years ago

Actuation callbacks (per-iteration user-provided joint torques) are already on our TODO list. I don't have an ETA on this feature, but hopefully it should be added in the near future. The intention is that you would gain access to the full articulation state (joint position and velocity) and could use this to implement e.g. your own high-frequency updated PD controller

smartcam3d commented 5 years ago

Hello,

per-iteration user-provided joint torques sound great and would expand the scope of application for PhysX for all kinds of robotic simulations!

Have you been able to reproduce the step-dependant static stiffness issue? Maybe there is mixup between an applied force / impulse? I am not yet very familiar with the internal structure of PhysX. Do you have a recommendation at which parts of the source code I could focus, to identify the problem?

Thank you for your support!

Best regards

Florian

smartcam3d commented 5 years ago

Hello,

@kstorey-nvidia Did you have any luck in reproducing the described effect of the issue?

Thank you for your help and investigation!

Best regards,

Florian

kstorey-nvidia commented 5 years ago

We do have something that should improve/resolve this issue coming in the next release. That release is currently expected some time in the next few weeks

Thanks

Kier

smartcam3d commented 4 years ago

Hello Kier,

is there any update on the planned release date of the next release? Thank you for your support!

Best regards,

Florian