x


Problem finding relative rotation from one quaternion to another

I want to find a relative rotation between two quaternions quatA and quatB, i.e. quatC is a quaternion rotation that if applied to quatA would result in quatB. Basically I want something like this:

quatC = Quaternion.RelativeRotation( quatA, quatB );

The only way I can think of to do it is to make two Transforms modA and modB, with modB the child of modA, and use the following code:

modA.rotation = quatA;
modB.rotation = quatB;
quatC = modB.localRotation;

However I would prefer not to use Transforms, and just use quaternions instead.

This previous answer suggests the following code would work:

Quaternion rotationDelta = Quaternion.FromToRotation(modelA.transform.forward, modelB.transform.forward);

But it doesn't appear to work after all, as it only inputs two direction vectors, not rotations. To demonstrate this, attach the following script to a basic cube dragged into an empty scene. The code will position and size the cube.

Modify rotations for models A and/or B. Model C should display the RELATIVE rotation FROM A TO B. In other words, applying C's rotation to A's rotation should result in B's rotation.

Model D shows the ACTUAL result of applying C's rotation to A's rotation. If C showed the actual relative rotation, D would be identical to B. As you will see, this is NOT the case. Hopefully I'm just missing something, but if not, is there a way to get quatC only with code?

var modA : Transform; var modB : Transform; var modC : Transform; var modD : Transform; var D_Rot_Equals_B_Rot = true;

// Nothing in Start is important to the question, it just sets up // other objects to help demonstrate the problem function Start() { modA = transform; modA.gameObject.name = "Model A"; modA.position = Vector3(0,0,0); modA.rotation = Quaternion.identity; modA.localScale = Vector3(.1,.1,.8); modB = GameObject.CreatePrimitive(PrimitiveType.Cube).transform; modB.gameObject.name = "Model B"; modB.position = Vector3(1,0,0); modB.localScale = Vector3(.1,.1,.8); modC = GameObject.CreatePrimitive(PrimitiveType.Cube).transform; modC.gameObject.name = "Model C"; modC.position = Vector3(2,0,0); modC.localScale = Vector3(.1,.1,.8); modD = GameObject.CreatePrimitive(PrimitiveType.Cube).transform; modD.gameObject.name = "Model D"; modD.position = Vector3(3,0,0); modD.localScale = Vector3(.1,.1,.8); var bump : Transform; bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; bump.gameObject.name = "Angle Helper"; bump.localScale = Vector3(.2,.2,.2); bump.position = Vector3(0,.15,-.3); bump.parent = modA; bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; bump.gameObject.name = "Angle Helper"; bump.localScale = Vector3(.2,.2,.2); bump.position = Vector3(1,.15,-.3); bump.parent = modB; bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; bump.gameObject.name = "Angle Helper"; bump.localScale = Vector3(.2,.2,.2); bump.position = Vector3(2,.15,-.3); bump.parent = modC; bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; bump.gameObject.name = "Angle Helper"; bump.localScale = Vector3(.2,.2,.2); bump.position = Vector3(3,.15,-.3); bump.parent = modD; }

function Update () {

 // Modify rotations for models A and/or B.
 // Model C should display the RELATIVE rotation FROM A TO B.
 // In other words, applying C's rotation to A's rotation should result in B's rotation.
 // Model D shows the ACTUAL result of applying C's rotation to A's rotation.
 // If C showed the actual relative rotation, D would be identical to B.
 // As you will see, this is NOT the case.

 modC.rotation = Quaternion.FromToRotation(modA.forward, modB.forward);
 modD.rotation = modA.rotation * modC.rotation;

 if (modD.rotation==modB.rotation) {
     D_Rot_Equals_B_Rot = true;
 } else {
     D_Rot_Equals_B_Rot = false;
 }

}

more ▼

asked Nov 26, 2010 at 12:36 PM

robinking gravatar image

robinking
835 197 152 163

(comments are locked)
10|3000 characters needed characters left

1 answer: sort voted first

This should do it:

Quaternion relative = Quaternion.Inverse(a) * b;
more ▼

answered Nov 26, 2010 at 12:57 PM

Mike 3 gravatar image

Mike 3
33k 21 84 292

Nearly! I tested it both ways and it's actually the other way round - "Quaternion relative = Quaternion.Inverse(a) * b;" works a charm. Thanks! I'll tick this answer, maybe you could update it?

Nov 27, 2010 at 05:23 PM robinking

Oh strange, I tested that like 5 times, I must have had a thinko when I wrote it in here. Fixing it now

Nov 27, 2010 at 05:50 PM Mike 3

Thanks! It helped me too. I used to have headache from some problem with planets, and had been suffered with that for weeks, and with this solution anything got to work. Thanks again.:)

Mar 30, 2012 at 08:44 AM Mahamed9628

Very handy!

Sep 22, 2012 at 06:03 AM Favo Yang

Thank you! That took far too long to find X_X

Jul 14, 2013 at 05:41 PM Khada
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x9247
x3775
x786

asked: Nov 26, 2010 at 12:36 PM

Seen: 7495 times

Last Updated: Jul 23 at 09:12 PM