NVIDIA / NVIDIA/simready-foundation

physics_driven_joints: DJ.001 crashes on mimic joints, DJ.007 rejects prismatic mimic axes, DJ.004 unsatisfiable for PhysX linear couplings

Open
#18 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
88
Forks
18
PR merge metrics
No merged PRs in 30d

Description

Summary

Validating a robot with a coupled parallel gripper (one motor, two opposed racks, so the two finger joints are rigidly 1:1) surfaces three separate problems in physics_driven_joints. The first is a crash, the second makes the requirement unsatisfiable for linear joints, and the third asks for an asset configuration that PhysX does not currently honour.

All three are reproducible with small standalone scripts; none need the original robot.

Environment: simready-foundation @ main, simready-validate 2026.4.9, omniverse-asset-validator 1.18.0, Isaac Sim 6.1 (PhysX 110.1.13), Linux aarch64.


1. DJ.001 crashes on any joint carrying PhysxMimicJointAPI

nv_core/sr_specs/docs/capabilities/physics_bodies/physics_driven_joints/validation.py:

255  for drive, joint_state in zip(drives, joint_states):
256      stiffness = drive.GetStiffnessAttr().Get()      # -> float
257      damping = drive.GetDampingAttr().Get()          # -> float
258      if (stiffness and stiffness.Get() != 0.0) or (damping and damping.Get() != 0.0):
                                ^^^^^^^^^^^^^^^ float has no .Get()

Lines 256–257 already resolve the attributes to floats; line 258 calls .Get() on the float. Reported as:

Uncaught error: 'float' object has no attribute 'Get'
FET022_DRIVEN_JOINTS_NEUTRAL: failing requirements: ['DJ.001']

The branch is only reachable when a joint has PhysxMimicJointAPI and non-zero drive gains, which is presumably why it has gone unnoticed — it needs a coupled mechanism (parallel gripper, differential, belt drive) to trigger.

The same expression appears twice, at line 258 (neutral) and line 535 (PhysX variant). Line 621 uses stiffness.Get() correctly, because there stiffness is the attribute.

Suggested fix:

if (stiffness and stiffness != 0.0) or (damping and damping != 0.0):

With that one-line change applied locally, our asset goes from [FAILED] to [PASSED] on Robot-Body-Neutral.

Minimal reproducer (builds a 2-joint stage from scratch)
from pxr import PhysxSchema, Usd, UsdGeom, UsdPhysics

stage = Usd.Stage.CreateNew("/tmp/mimic.usda")
root = UsdGeom.Xform.Define(stage, "/Robot")
stage.SetDefaultPrim(root.GetPrim())
UsdPhysics.ArticulationRootAPI.Apply(root.GetPrim())

base = UsdGeom.Cube.Define(stage, "/Robot/base")
UsdPhysics.RigidBodyAPI.Apply(base.GetPrim())

for name in ("left", "right"):
    link = UsdGeom.Cube.Define(stage, f"/Robot/{name}")
    UsdPhysics.RigidBodyAPI.Apply(link.GetPrim())
    joint = UsdPhysics.PrismaticJoint.Define(stage, f"/Robot/joint_{name}")
    joint.CreateBody0Rel().SetTargets([base.GetPath()])
    joint.CreateBody1Rel().SetTargets([link.GetPath()])
    joint.CreateAxisAttr().Set("Z")
    drive = UsdPhysics.DriveAPI.Apply(joint.GetPrim(), "linear")
    drive.CreateStiffnessAttr().Set(5000.0)      # non-zero: reaches line 258
    drive.CreateDampingAttr().Set(41.28)
    drive.CreateMaxForceAttr().Set(1904.0)
    PhysxSchema.JointStateAPI.Apply(joint.GetPrim(), "linear")

follower = stage.GetPrimAtPath("/Robot/joint_right")
mimic = PhysxSchema.PhysxMimicJointAPI.Apply(follower, "Z")
mimic.CreateReferenceJointRel().SetTargets([stage.GetPrimAtPath("/Robot/joint_left").GetPath()])
mimic.CreateGearingAttr().Set(-1.0)
stage.GetRootLayer().Save()

# now: simready-validate /tmp/mimic.usda --profile Robot-Body-Neutral --version 1.0.0

Result: mimic absent -> rule passes, mimic present -> AttributeError: 'float' object has no attribute 'Get'.


2. DJ.007 cannot be satisfied by a prismatic mimic joint

Lines 664–676 match the mimic axis against rotational tokens only:

match axis:
    case "rotX": ...
    case "rotY": ...
    case "rotZ": ...
    case _:
        self._AddFailedCheck(
            requirement=DrivenJointsCapReq.DJ_007,
            message=f"Joint {prim.GetPath()} has unknown mimic axis: {axis}, aborting checks",

A linear coupled DOF — which is what a parallel gripper is — authors transX/transY/transZ (or the X/Y/Z short form). UsdPhysics.Tokens defines transX, transY, transZ, PhysxSchema.PhysxMimicJointAPI.Apply() accepts them, and PhysX's own Newton migration checker explicitly documents mimic support for PhysicsPrismaticJoint:

NewtonMimicAPI is single-apply per joint and supports single-DOF followers and leaders only (PhysicsRevoluteJoint / PhysicsPrismaticJoint).

So today no parallel-jaw gripper can pass FET022_DRIVEN_JOINTS_PHYSX/_ISAAC, regardless of how it is authored. Adding transX/transY/transZ (and the short X/Y/Z spelling) to the match would close it.


3. DJ.004 asks for zero gains, but PhysX does not enforce a prismatic mimic

DJ.004 fails a joint that has both a mimic API and non-zero drive gains:

Joint .../joint_right has both drive and mimic API

For a revolute follower that is the correct model — one motor, one drive, the constraint carries the other DOF. We applied it, then measured the result in Isaac Sim 6.1:

follower drive finger deviation left/right asymmetry
0 / 0 (DJ.004 compliant) 51.50 mm 51.50 mm
5000 / 41.28 0.006 mm 0.012 mm
500 / 4.13 0.092 mm 0.097 mm

A follow-up A/B shows why: on a prismatic joint, PhysX does not enforce PhysxMimicJointAPI at all. Removing the API entirely produces numbers identical to four decimal places:

case mimic slew deviation asymmetry leader → 40 mm follower
mimic + follower drive True 0.0064 mm 0.0123 mm 40.000 20.000
no mimic + follower drive False 0.0064 mm 0.0123 mm 40.000 20.000
mimic + zero gains True 51.5009 mm 51.4996 mm 40.000 0.941
no mimic + zero gains False 51.5009 mm 51.4996 mm 40.000 0.941

The same probe on a revolute pair does show the constraint acting. So DJ.004 is right in general and wrong for linear DOFs on PhysX: complying makes the gripper physically worse than the bug it was authored to fix.

Newton (NewtonMimicAPI) and MuJoCo (<equality joint>) both honour the coupling, so an asset that must work across all three ends up keeping the constraint and the drive — which DJ.004 rejects.

Suggestion: scope DJ.004 to DOF types where the runtime actually enforces the constraint, or downgrade it to a warning when the follower is prismatic.


Why this came up

We are bringing Seeed-Projects/reBot-Isaacsim into SimReady conformance. The arm's gripper is a single RobStride motor driving two opposed racks through one pinion, so the two finger joints are rigidly coupled — modelling them as independent DOFs let the jaws drift 2.3 mm under arm motion and sag 7.4 mm under gravity.

With items 1–3 addressed, Robot-Body-Neutral passes. Happy to test any proposed fix against the asset and against the standalone reproducers.


Separately, and possibly worth its own issue: the validate venv installs usd-exchange, whose pxr build does not ship PhysxSchema. Every rule that touches PhysxSchema.JointStateAPI / PhysxMimicJointAPI then reports "PhysxSchema is not available in this environment" as a FAILURE rather than skipping or erroring loudly — on this asset that was 161 messages, and DJ.001/DJ.002/DJ.003 all reported as failing requirements when the asset satisfied two of them. Running the same validator against a pxr that does provide PhysxSchema cleared DJ.002 and DJ.003 immediately.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in nv_core/sr_specs/docs/capabilities/physics_bodies/physics_driven_joints/validation.py, especially the checks around lines 255-258, 535, 621, and 664-676, then run the standalone mimic-joint reproducers from the issue. Done means the validator no longer crashes on driven mimic joints, accepts supported linear mimic axes, and applies an appropriate DJ.004 result to prismatic PhysX couplings.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.