Isaac Sim Version
[√] 4.5.0
Operating System
[√] Windows 11
[√] Windows 10
Topic Description
Detailed Description
Hi everyone,
I’m trying to achieve an effect where a gripper remains fixed at a point in space, but can freely rotate around the X, Y, and Z axes—essentially, a 3-DoF rotational joint with no translation.
I’m using an external USD file for the gripper, which has the following structure:
-gripper # Xform
--Looks # Scope
----DefaultMaterial # Material
------DefaultMaterial # Shader
--PARTassembly # Mesh Group
----PARTassembly # Mesh
For reference, I tested my setup using a DynamicCone, where the tip of the cone is fixed in mid-air and it can rotate freely—this worked exactly as expected.
# Add ConeGripper
gripper = DynamicCone(
prim_path="/World/Gripper",
radius=0.5,
height=1.0,
color=np.array([0, 1.0, 0.0]),
mass=1.0
)
# set the initial poses of the gripper
gripper.set_world_pose(position=np.array([0, 0, 4])/ get_stage_units(), orientation=np.array([1., 0., 0., 0.]))
anchor = DynamicCuboid(
prim_path="/World/anchor",
name="anchor",
position=np.array([0, 0, 5]),
scale=np.array([1, 1, 1]),
color=np.array([0, 0, 1.0]),
)
anchor.disable_rigid_body_physics()
anchor.set_visibility(visible=False)
from pxr import UsdPhysics, Gf
def fix_to_ground(stage, joint_path, prim_path, anchor_pos):
# D6 fixed joint
d6FixedJoint = UsdPhysics.Joint.Define(stage, joint_path)
d6FixedJoint.CreateBody0Rel().SetTargets(["/World/anchor"])
d6FixedJoint.CreateBody1Rel().SetTargets([prim_path])
d6FixedJoint.CreateLocalPos0Attr().Set(anchor_pos)
d6FixedJoint.CreateLocalRot0Attr().Set(Gf.Quatf(1.0, Gf.Vec3f(0, 0, 0)))
d6FixedJoint.CreateLocalPos1Attr().Set(Gf.Vec3f(0, 0, 0.5))
d6FixedJoint.CreateLocalRot1Attr().Set(Gf.Quatf(1.0, Gf.Vec3f(0, 0, 0)))
# lock all DOF (lock - low is greater than high)
d6Prim = stage.GetPrimAtPath(joint_path)
limitAPI = UsdPhysics.LimitAPI.Apply(d6Prim, "transX")
limitAPI.CreateLowAttr(1.0)
limitAPI.CreateHighAttr(-1.0)
limitAPI = UsdPhysics.LimitAPI.Apply(d6Prim, "transY")
limitAPI.CreateLowAttr(1.0)
limitAPI.CreateHighAttr(-1.0)
limitAPI = UsdPhysics.LimitAPI.Apply(d6Prim, "transZ")
limitAPI.CreateLowAttr(1.0)
limitAPI.CreateHighAttr(-1.0)
fix_to_ground(stage, joint_path="/World/Gripper_anchor", prim_path="/World/Gripper", anchor_pos=Gf.Vec3f(0, 0, 0))
However, when I apply the same setup/code to my gripper model, it behaves incorrectly: the gripper spins uncontrollably and doesn’t stay oriented as intended.
# load gripper model
gripper_path = "G:/gripper.usd".replace("\\", "/").strip()
gripper_prim_path = "/World/gripper"
add_reference_to_stage(usd_path=gripper_path, prim_path=gripper_prim_path)
my_world.scene.add(
XFormPrim(
prim_paths_expr=gripper_prim_path,
name="gripper",
positions=np.array([[0,0,0.5]]),
#translations=np.array([[0,0,1]]),
orientations=np.array([[0.70710678, 0.70710678, 0, 0]]),
scales=np.array([[0.001, 0.001, 0.001]])
)
)
gripper_rigid_prim = RigidPrim("/World/gripper")
gripper_rigid_prim.set_masses(np.full(1, 1))
gripper_geometry_prim = GeometryPrim("/World/gripper/PARTassembly/PARTassembly")
gripper_geometry_prim.apply_collision_apis()
gripper_geometry_prim.set_collision_approximations(["sdf"])
from pxr import UsdPhysics, Gf
def fix_gripper_to_anchor(stage, joint_path, prim_path, anchor_pos):
# D6 fixed joint
d6FixedJoint = UsdPhysics.Joint.Define(stage, joint_path)
d6FixedJoint.CreateBody0Rel().SetTargets(["/World/anchor"])
d6FixedJoint.CreateBody1Rel().SetTargets([prim_path])
d6FixedJoint.CreateLocalPos0Attr().Set(Gf.Vec3f(0, 0, 0)) # Set to 0,0,0 because we want anchor to be at the center of the cuboid
d6FixedJoint.CreateLocalRot0Attr().Set(Gf.Quatf(1.0, Gf.Vec3f(0, 0, 0)))
d6FixedJoint.CreateLocalPos1Attr().Set(Gf.Vec3f(0, 0, 0))
d6FixedJoint.CreateLocalRot1Attr().Set(Gf.Quatf(1.0, Gf.Vec3f(0, 0, 0)))
# lock all DOF (lock - low is greater than high)
d6Prim = stage.GetPrimAtPath(joint_path)
limitAPI = UsdPhysics.LimitAPI.Apply(d6Prim, "transX")
limitAPI.CreateLowAttr(1.0)
limitAPI.CreateHighAttr(-1.0)
limitAPI = UsdPhysics.LimitAPI.Apply(d6Prim, "transY")
limitAPI.CreateLowAttr(1.0)
limitAPI.CreateHighAttr(-1.0)
limitAPI = UsdPhysics.LimitAPI.Apply(d6Prim, "transZ")
limitAPI.CreateLowAttr(1.0)
limitAPI.CreateHighAttr(-1.0)
fix_gripper_to_anchor(stage, joint_path="/World/gripper_anchor", prim_path="/World/gripper/PARTassembly", anchor_pos=Gf.Vec3f(0, 0, 0))
Has anyone encountered similar behavior with custom USD assets or mesh-based models? Could there be something in the USD hierarchy or mesh configuration that might cause this instability?
Any guidance would be greatly appreciated!
Thanks in advance.