前往
大廳
主題

【Unity】 Get current rotation of the configurable joint in the joint axis space

夏洛爾 | 2022-09-21 17:26:58 | 巴幣 12 | 人氣 515


Abstract
If you want to get current rotation of the configurable joint in the joint axis space or compute the target rotation of the joint into world space. This tutorial can help.

Key
1.MUST get and keep the initial local rotation of the joint in its connected body space.
2.Change the target rotation from the coordinate system of the joint axis space to the coordinate system of the joint local space
3.The target rotation of the joint is actually represented in "Inversed" form. Must do inverse.

All the function that could help

public Quaternion GetJointLocalRotationInConnectedBodySpace(ConfigurableJoint joint)
{
return Quaternion.Inverse(joint.connectedBody.transform.rotation) * joint.transform.rotation;
}
public Quaternion GetJointTargetRotationInWorldSpace(ConfigurableJoint joint, Quaternion initLocalRot)
{
Quaternion JointAxisCoordRot = Quaternion.LookRotation(Vector3.Cross(joint.axis, joint.secondaryAxis), joint.secondaryAxis);
return joint.connectedBody.transform.rotation * initLocalRot * Quaternion.Inverse(SwitchQuaternionCoordinateSystem( joint.targetRotation, JointAxisCoordRot ));
}
public Quaternion GetJointRotationInJointAxisSpace(ConfigurableJoint joint, Quaternion initLocalRot)
{
Quaternion JointAxisCoordRot = Quaternion.LookRotation(Vector3.Cross(joint.axis, joint.secondaryAxis), joint.secondaryAxis);
return SwitchQuaternionCoordinateSystem(Quaternion.Inverse(Quaternion.Inverse(initLocalRot) * Quaternion.Inverse(joint.connectedBody.transform.rotation) * joint.transform.rotation ), Quaternion.Inverse(JointAxisCoordRot));
}
public Quaternion SwitchQuaternionCoordinateSystem(Quaternion q, Quaternion coordRotation)
{
return coordRotation * q * Quaternion.Inverse( coordRotation );
}


Example:

0.Initialization
【IMPORTANT, required for every following example】
//Compute the initial local rotation of the joints and keep it somewhere. Better done this before game starts, such as using editor script.

ConfigurableJoint[] joints;  //Assign your joints
Quaternion initRot[] = new Quaternion[joints.Length];

for(int i=0; i<joints.Length; i++)
{
initRot[i] = GetJointLocalRotationInConnectedBodySpace(joints[i]);
}

1.Get the target rotation of the joint in world space
targetRotationInworld = GetJointTargetRotationInWorldSpace(joints[i], initRot[i])

2.Get the current rotation of the joint in joint axis space
currentRotationInJointAxisSpace = GetJointRotationInJointAxisSpace(joints[i], initRot[i])

3.Compute any rotation from world space into joint axis space
Edit the GetJointRotationInJointAxisSpace(), replace the "joint.transform.rotation" with your rotation.
For scenario like you want your joint points to a rotation in world space. You can transform the rotation from world space into joint axis space, then set it as new target rotation of the joint.

4.Compute any rotation from joint axis space into world space
Edit the GetJointTargetRotationInWorldSpace(), replace the "joint.targetRotation" with your rotation


Reference
(If you need to change chirality as well)

Postscript
Since I could not find any resource or tutorial on the internet, I fought for three days to solve these function.
Although the concept of quaternion is quite hard, but the hidden inverse of the target rotation of the joint as mentioned in Key 3 took me a long journey to discover. Especially when the math should be logically correct but the result showed the mismatch made the situation really confused.

After using some objects to represent the results of the rotation , I finally found that there exists a hidden inverse of the rotation of the joint by Unity system (But even now, I am not completely sure. This is quaternion!)

Hence, I decided to make this tutorial. Although my English is not fluent, but I wish the tutorial could help other developers to save time and get the concept much more clearly. Good luck!

創作回應

更多創作