rigid-body-no-nesting-without-joint#
Code |
RB.012 |
|---|---|
Validator |
|
Compatibility |
|
Tags |
Summary#
Rigid bodies should not be nested unless they are connected by a joint.
Description#
This is an enhanced version of rigid-body-no-nesting designed for multi-body assets such as robots and articulated mechanisms.
When two UsdPhysicsRigidBodyAPI prims are nested in the scene hierarchy (one is an ancestor of the other), there must be a UsdPhysicsJoint somewhere in the stage whose physics:body0 and physics:body1 relationships connect the two rigid bodies. Without a joint, the physics engine has no constraint information linking the bodies, leading to unpredictable simulation behaviour.
The validator performs a stage-wide scan of all joints because a joint can be defined anywhere in the scene — not necessarily between the nested prims in the hierarchy. For each joint, the body0 and body1 relationship targets are resolved; if a target points to a collision mesh, the mesh’s parent is treated as the rigid body (matching standard USD joint authoring conventions). Every nested rigid-body pair is then checked against the collected set of joint-connected pairs.
Why is it required?#
In multi-body hierarchies (e.g. robots), rigid bodies are intentionally nested to represent link-joint chains. Each parent-child rigid body pair must be connected by a joint so the physics solver can compute the correct constrained motion.
A nested rigid body without a connecting joint will be simulated independently of its parent, causing the bodies to drift apart or interpenetrate during simulation.
This check complements RB.006 (which requires
!resetXformStack!for nested rigid bodies) by ensuring the structural correctness of articulated assets where nesting is expected.
Examples#
# Invalid: Nested rigid bodies with no joint connecting them
def Xform "Robot" () {
prepend apiSchemas = ["PhysicsRigidBodyAPI"]
def Xform "Link1" () {
prepend apiSchemas = ["PhysicsRigidBodyAPI"]
}
}
# Valid: Nested rigid bodies connected by a joint
def Xform "Robot" () {
prepend apiSchemas = ["PhysicsRigidBodyAPI"]
def Xform "Link1" () {
prepend apiSchemas = ["PhysicsRigidBodyAPI"]
}
def PhysicsRevoluteJoint "Joint1" () {
rel physics:body0 = </Robot>
rel physics:body1 = </Robot/Link1>
}
}
# Valid: Joint defined elsewhere in the scene (not between the nested prims)
def Xform "Robot" () {
prepend apiSchemas = ["PhysicsRigidBodyAPI"]
def Xform "Arm" () {
prepend apiSchemas = ["PhysicsRigidBodyAPI"]
}
}
def PhysicsRevoluteJoint "ExternalJoint" () {
rel physics:body0 = </Robot>
rel physics:body1 = </Robot/Arm>
}
How to comply#
For every pair of nested rigid bodies, ensure a
UsdPhysicsJoint(or subtype such asPhysicsRevoluteJoint,PhysicsPrismaticJoint,PhysicsFixedJoint, etc.) exists in the stage with itsphysics:body0andphysics:body1relationships targeting the two rigid body prims.The joint does not need to be a child of either rigid body — it can be authored anywhere in the scene graph.