NVIDIAGameWorks / PhysX

NVIDIA PhysX SDK
Other
3.14k stars 793 forks source link

PxArticulationJointReducedCoordinate setDriveVelocity inconsistent for prismatic joints #411

Open fbxiang opened 3 years ago

fbxiang commented 3 years ago

For prismatic joints with positive damping and 0 stiffness, calling setDriveVelocity with a positive value moves the joint towards the negative direction. However, setDriveTarget with positive stiffness and 0 damping moves the joint towards the positive direction (at the start). This seems inconsistent with the documentation force = spring * (targetPosition - position) + damping * (targetVelocity - velocity).

For regular joints and revolute joint in PxArticulationJointReducedCoordinate, setDriveVelocity and setDriveTarget work as expected.

Any idea why it is designed this way?

Here is my code to reproduce this behavior.

#include <PxPhysicsAPI.h>
#include <extensions/PxExtensionsAPI.h>
#include <iostream>

using namespace physx;

void test() {
  static PxDefaultErrorCallback gDefaultErrorCallback;
  static PxDefaultAllocator gDefaultAllocatorCallback;
  auto foundation = PxCreateFoundation(PX_PHYSICS_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback);
  auto physics = PxCreatePhysics(PX_PHYSICS_VERSION, *foundation,
                                 PxTolerancesScale(), true);
  PxInitExtensions(*physics, nullptr);
  PxRegisterArticulations(*physics);

  PxSceneDesc sceneDesc(physics->getTolerancesScale());
  sceneDesc.gravity = PxVec3(0,0,0);
  sceneDesc.filterShader = PxDefaultSimulationFilterShader;
  auto cpuDispatcher = PxDefaultCpuDispatcherCreate(0);
  sceneDesc.cpuDispatcher = cpuDispatcher;

  PxScene *scene = physics->createScene(sceneDesc);

  PxArticulationReducedCoordinate* articulation = physics->createArticulationReducedCoordinate();

  auto mat = physics->createMaterial(0.5, 0.5, 0.1);

  PxArticulationLink *root =
      articulation->createLink(nullptr, PxTransform(PxIdentity));
  PxRigidActorExt::createExclusiveShape(*root, PxBoxGeometry(PxVec3{1,1,1}), *mat);
  PxRigidBodyExt::updateMassAndInertia(*root, 1.0f);

  PxArticulationLink *child =
      articulation->createLink(root, PxTransform(PxIdentity));
  PxRigidActorExt::createExclusiveShape(*child, PxBoxGeometry(PxVec3{1,1,1}), *mat);
  PxRigidBodyExt::updateMassAndInertia(*child, 1.0f);

  auto joint = static_cast<PxArticulationJointReducedCoordinate*>(child->getInboundJoint());
  joint->setJointType(PxArticulationJointType::ePRISMATIC);
  joint->setParentPose(PxTransform(PxIdentity));
  joint->setChildPose(PxTransform(PxIdentity));
  joint->setMotion(PxArticulationAxis::eX, PxArticulationMotion::eFREE);
  joint->setFrictionCoefficient(0);

  articulation->setArticulationFlag(PxArticulationFlag::eFIX_BASE, true);
  scene->addArticulation(*articulation);

  // case 1: target position
  // joint->setDrive(PxArticulationAxis::eX, 100, 0, PX_MAX_F32);
  // joint->setDriveTarget(PxArticulationAxis::eX, 100);
  // end case 1

  // case2: target velocity
  joint->setDrive(PxArticulationAxis::eX, 0, 100, PX_MAX_F32);
  joint->setDriveVelocity(PxArticulationAxis::eX, 100);
  // end case 2

  for (uint32_t i = 0; i < 10; ++i) {
    scene->simulate(0.01);
    scene->fetchResults(true);
    auto pose = child->getGlobalPose();
    auto vel = child->getLinearVelocity();
    std::cout << "Pos " << pose.p.x << " " << pose.p.y << " " << pose.p.z << "\n";
    std::cout << "Vel " << vel.x << " " << vel.y << " " << vel.z << "\n\n";
  }

}

int main() {
  test();
}
kstorey-nvidia commented 3 years ago

Thanks for reporting. I'll do some internal testing and get back to you.

kstorey-nvidia commented 3 years ago

I can confirm that this looks like a bug with prismatic joint velocity targets. Working on a fix

kstorey-nvidia commented 3 years ago

The fix is extremely simple. It will be included in the next spot fix. If you want the fix sooner, please edit the following code:

In void FeatherstoneArticulation::setupInternalConstraintsRecursive(...) in DyFeatherstoneArticulation.cpp

Search for this line:

const PxReal targetVelocity = -jointTranDatum.targetJointVelocity[dofId];

and remove the "-" from it as this is incorrect.