Add FixedJoint attritube not work!

Hi everyone,
I tried to add a Fixedjoint by program, when I setup the FixedJoint’s attribute values to the Isaac Sim, the result is different. My Isaac Sim version is 2022.1.1. Following is my code. Any one can help me to know why it didn’t work?

stage = get_context().get_stage()
fixedJoint = UsdPhysics.FixedJoint.Define(stage, “/World/ST2_GoldenJig/FixedJoint”)
fixedJoint.CreateBody0Rel().SetTargets([“/World/Epson_LS20/Epson_LS20_01/Robot_J4/ST2”])
fixedJoint.CreateBody1Rel().SetTargets([“/World/ST2_GoldenJig”])
fixedJoint.CreateLocalPos0Attr().Set(Gf.Vec3f(0,0,0))
fixedJoint.CreateLocalRot0Attr().Set(Gf.Quatf(0.688,0,0,0.726))
fixedJoint.CreateLocalPos1Attr().Set(Gf.Vec3f(0,0,0))
fixedJoint.CreateLocalRot1Attr().Set(Gf.Quatf(1,0,0,0))

Pos0,Rot0,Pos1,Rot1 are all different in Isaac Sim.

Hi @vic-chen , can you share what errors you are getting?

Hi @rthaker , sorry about reply you so late. Because of NDA, I need to confirm it.
The following video is my test video, and I edited my scene usd file and try to add fixed joint.
It looks good.

The following video is I tried to add the reference usd file to the stage by program,
and I add the fixed joint, and you can see in the video’s fixed joint attribute values is different.

The following picture is I add fixed joint’s code. I think it should be the same with what I setup doesn’t it?

And I also tried the surface gripper like following video.

When I add the reference usd file to the stage, it seems different.

Hi,
For a fixed joint the localPose0/1 must be set in a way that the body0/1 * localpose0/1 match the same transformation. Otherwise the simulation will snap to the transformation0, which is what I believe is happening on your video.
This is the code for reference we use to make sure this is setup right (Add->Physics->Joint):

def createJoint(stage, joint_type, from_prim, to_prim):
    # for single selection use to_prim
    if to_prim is None:
        to_prim = from_prim
        from_prim = None

    from_path = from_prim.GetPath().pathString if from_prim is not None and from_prim.IsValid() else ""
    to_path = to_prim.GetPath().pathString if to_prim is not None and to_prim.IsValid() else ""
    single_selection = from_path == "" or to_path == ""

    # to_path can be not writable as in case of instancing, find first writable path
    joint_base_path = to_path
    base_prim = stage.GetPrimAtPath(joint_base_path)
    while base_prim != stage.GetPseudoRoot():
        if base_prim.IsInMaster():
            base_prim = base_prim.GetParent()
        elif base_prim.IsInstanceProxy():
            base_prim = base_prim.GetParent()
        elif base_prim.IsInstanceable():
            base_prim = base_prim.GetParent()
        else:
            break
    joint_base_path = str(base_prim.GetPrimPath())
    if joint_base_path == '/':
        joint_base_path = ''

    joint_name = "/" + create_unused_path(stage, joint_base_path, joint_type + "Joint")
    joint_path = joint_base_path + joint_name

    if joint_type == "Fixed":
        component = UsdPhysics.FixedJoint.Define(stage, joint_path)
    elif joint_type == "Revolute":
        component = UsdPhysics.RevoluteJoint.Define(stage, joint_path)
        component.CreateAxisAttr("X")
    elif joint_type == "Prismatic":
        component = UsdPhysics.PrismaticJoint.Define(stage, joint_path)
        component.CreateAxisAttr("X")
    elif joint_type == "Spherical":
        component = UsdPhysics.SphericalJoint.Define(stage, joint_path)
        component.CreateAxisAttr("X")
    elif joint_type == "Distance":
        component = UsdPhysics.DistanceJoint.Define(stage, joint_path)
        component.CreateMinDistanceAttr(0.0)
        component.CreateMaxDistanceAttr(0.0)
    elif joint_type == "Gear":
        component = PhysxSchema.PhysxPhysicsGearJoint.Define(stage, joint_path)
    elif joint_type == "RackAndPinion":
        component = PhysxSchema.PhysxPhysicsRackAndPinionJoint.Define(stage, joint_path)
    else:
        component = UsdPhysics.Joint.Define(stage, joint_path)
        prim = component.GetPrim()
        for limit_name in ["transX", "transY", "transZ", "rotX", "rotY", "rotZ"]:
            limit_api = UsdPhysics.LimitAPI.Apply(prim, limit_name)
            limit_api.CreateLowAttr(1.0)
            limit_api.CreateHighAttr(-1.0)

    xfCache = UsdGeom.XformCache()

    if not single_selection:
        to_pose = xfCache.GetLocalToWorldTransform(to_prim)
        from_pose = xfCache.GetLocalToWorldTransform(from_prim)
        rel_pose = to_pose * from_pose.GetInverse()
        rel_pose = rel_pose.RemoveScaleShear()
        pos1 = Gf.Vec3f(rel_pose.ExtractTranslation())
        rot1 = Gf.Quatf(rel_pose.ExtractRotationQuat())

        component.CreateBody0Rel().SetTargets([Sdf.Path(from_path)])
        component.CreateBody1Rel().SetTargets([Sdf.Path(to_path)])
        component.CreateLocalPos0Attr().Set(pos1)
        component.CreateLocalRot0Attr().Set(rot1)
        component.CreateLocalPos1Attr().Set(Gf.Vec3f(0.0))
        component.CreateLocalRot1Attr().Set(Gf.Quatf(1.0))
    else:
        to_pose = xfCache.GetLocalToWorldTransform(to_prim)
        to_pose = to_pose.RemoveScaleShear()
        pos1 = Gf.Vec3f(to_pose.ExtractTranslation())
        rot1 = Gf.Quatf(to_pose.ExtractRotationQuat())

        component.CreateBody1Rel().SetTargets([Sdf.Path(to_path)])
        component.CreateLocalPos0Attr().Set(pos1)
        component.CreateLocalRot0Attr().Set(rot1)
        component.CreateLocalPos1Attr().Set(Gf.Vec3f(0.0))
        component.CreateLocalRot1Attr().Set(Gf.Quatf(1.0))

    component.CreateBreakForceAttr().Set(MAX_FLOAT)
    component.CreateBreakTorqueAttr().Set(MAX_FLOAT)

    return stage.GetPrimAtPath(joint_base_path + joint_name)

Hope that helps.

Regards,
Ales

1 Like

Hi @AlesBorovicka and @rthaker ,
Thanks for your help, it finally works. I really appreciate your solution make my still alive.
Best Regards to you!!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.