Help understanding physx joint

I have several misunderstanding of physx joint, could anyone help me to understand it?

  1. the joint create by the interface:
physx::createXXJoint(actor_0, local_frame_0, actor_1, local_frame_1).

Since the joint has a global pose, why physx need two local frames, shouldn’t they be equivalent to the global pose in world space.

  1. For the revolute joint, the document says: “A revolute joint removes all but a single rotational degree of freedom from two objects. The axis along which the two bodies may rotate is specified by the common origin of the joint frames and their common x-axis”.

What’s the meaning of common x-axis, does it mean that the x-axis in these two local frames must be coincident, and the twist limit limits each actor in their respective local frame?

“Since the joint has a global pose, why physx need two local frames,”

I don’t see a global pose in that function call. In fact I don’t see a global pose in any of the classes PxJoint, PxSphericalJoint, etc. There is no redundant information here; regardless of the API you need to specify the relationship between the joint’s reference frame and the two actor reference frames.

–>.What’s the meaning of common x-axis, does it mean that the x-axis in these two local frames must be coincident, and the twist limit limits each actor in their respective local frame?

It means that you set the local_frame_0 and local_frame_1 such that the x-axes of the local frames are the hinge axes in the two actor frames. If the x-axis of actor frames line up automatically, like a knee joint for an upper leg and lower leg whose x-axes are parallel to the hips and horizontal, then you can use identity for the local frames.

–Mike

I know this is an old thread, but hopefully someone will be able to see this and help.

I am trying to use articulations, and am having troubles understanding how to use articulationjoints.

I am using the following template /pseudo-code to create articulation, links and joints, based on the ArticulationSnippet.

articulation = Physics->createArticulation()
//for each link
link  = articulation->createLink(parent, LINK_POSE)

joint = link->getInboundJoint()

if(joint)
joint->setParentPose(PARENT_POSE)
joint->setChildPose(CHILD_POSE)

// define the rest of the joint

I need clarifications regarding the three required poses (LINK, PARENT and CHILD)

My understanding is as follows:

LINK_POSE is the initial pose of the new link in the world frame. This is inconvenient because it would be much easier to express this pose relative to the previous link, but at least it is manageable by keeping track of the previous link poses.

PARENT_POSE is the pose of new joint expressed in the frame of the parent link. The translation component is easily visualized as an offset from the link frame (which is usually in the middle of the geometry mesh). The rotation component can (? I am not sure) be use to orient the new joint frame any way you want. To mimic a revolute joint, you would ideally want to orient the X (twist) axis of the joint as the main rotation axis.

CHILD_POSE is where I get confused. I believe it is the pose of the new joint expressed in the frame of the child link. Again, the translation component is easily visualized as an offset from the link frame to the attach point. HOWEVER, I feel like the orientation component of this transform is already fully defined by the LINK_POSE and the PARENT_POSE.

i.e.: (newLink2World_transform)(childLink2Joint_transform)^-1 = (parentLink2World_transform)(parentLink2Joint_transform)^-1

All terms in italic are previously known (world transforms are either the original transforms from LINK_POSE or deduced from its evolution over time), leaving the child_pose fully defined.

There MUST be something wrong with my understanding, but the documentation can’t help me figure it out, so any help would be greatly appreciated.

Did you take a look at the snippets? They’re really simple scenes implemented in a single file that show you how to use various PhysX features.

The parent pose and child pose are basically the joint frame (location and orientation of the joint) in the space of the parent link and the child link respectively. This is the same as the 2 parameters passed to the joints. We use these local frames to compute the current joint configuration each frame (anchor location and current angles).

For example, if you had 2 boxes with dimensions(1, 0.1, 0.1) at locations (10,0,0) and (12,0,0) respectively and you wanted to place the joint anchor at the top-right corner of the first box, your joint frames might be as follows

parentPose = PxTransform(PxVec3(1, 0.1, 0.1));
childPose = PxTransform(PxVec3(-1,0.1,0.1));

The rotational part of the joint frame is used to rotate the joint frames. You generally only need to do this if you are using limits. The articulation joints support high/low limits for the twist axis and a cone for the swing axes, with the swing cone centered around the twist axis. You may need to rotate this frame to ensure that rotations and limits operate around your desired space. Both child and parent spaces don’t always need to line up - when they don’t line up, you’re effectively offsetting the zero angle pose of the joints (much like initially-perfectly-aligned frames would no longer line up once the links rotated).

Yes I did. That is how I managed to understand some of it. However the snippet only illustrates the use of the translation part of the transform in each pose, which was indeed pretty clear.

I am using limits, because I am trying to reproduce the behaviour of a revolute joint about the twist axis (but joints are unstable in my simulation). I’d rather even have unlimited rotation about the twist axis, but let’s keep that question for another day.

Can you validate that the following understanding makes sense? I will reuse the notation I used in my post above and consider that I am making 1DOF revolute joints about the twist axis, leaving the swing axis limited to very small angles.

LINK_POSE locates the child frame. It’s only purpose is to locate the CHILD_POSE relative to it.

PARENT_POSE locates the joint frame relative to the parent link frame. The orientation part of this pose is static, meaning that if I know the direction of the twist axis from the parent link, I can effectively decide which way the joint will rotate. (I have not tested this)

CHILD_POSE locates the joint frame relative to the parent link frame. The orientation part of this pose is variable, meaning that the rotation of the joint should not occur relative to this frame. The purpose of this pose is to set the initial orientation and calculate the joint rotation using something like:

(PARENT_POSE.q.inverse()*CHILD_POSE.q2).toRadiansAndUnitAxis()

But what if I set the CHILD_POSE so that its orientation corresponds to the orientation of the PARENT_POSE rotated about a swing axis (which is supposed to be locked in my example)? I obviously won’t do this on purpose, but how will it work? Will it actually still rotate about the twist axis from the PARENT_POSE?

Yes, the axes that the joint permits rotation around are defined by the parent pose joint frame.

The parent pose is the frame relative to the parent link’s pose.

The child pose is the frame relative to the child link’s pose.

Therefore, to compute the angle/axis as in your example, you would need to first calculate the joint frame in the same space, e.g. world space.

For example, you would do something like this:

PxTransform cA2w = parentLink.getGlobalPose() * PARENT_POSE;
PxTransform cB2w = childLink.getGlobalPose() * CHILD_POSE;

(cA2w.q.getInverse() * cB2w.q).toRadiansAndUnitAxis();

The CHILD_POSE and PARENT_POSE transforms are constant properties of the joint while the global pose or each link changes as the simulation progresses.

You actually can’t lock an axis using the articulation joints - you only have access to limits. You can set very tiny limit ranges on the swing axes so you can produce something that looks pretty close to a revolute joint, but it wouldn’t be exactly a revolute.

If this is insufficient, you could alternatively use a PxD6Joint on the articulation and use that to lock the 2 swing axes. There is very little difference in terms of quality between using the native limits in the articulations or using a D6 joint to implement those limits, although the D6 approach is potentially a little bit more expensive.

If you did use a D6, please make sure you set the eX, eY, eZ axes to free - the articulations will implicitly impose these joints so these constraints would be completely redundant.

Thank you, this is very helpful (and should definitely be put somewhere in the documentation).