Lately I've been diving deeper into Quaternions, a complex mathematical operation we need in here for rotations.

So I wanted to get down to the nitty gritty of some of the math around it and thought a good way to do this was trying to recreate some of LL's methods we use. I thought a good place to start would be with creating a Quaternion from scratch. In particular implementing the Quaternion.FromEulerAngles(Vector a)

This is the pertinent info on how they do it.

A vector of angles in radians.

Rotates first around X (local/global coincide), then around new local Y, and finally around new local Z.

So I challenge programmers to write this method.

Testing it should involve creating several Quaternions from the Sansar method and then comparing your created one to theirs.

This is a good source of related info https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf

I have been unable to replicate it so far myself.

Some Test Data

` (42,10,22.4) => 0.9060,0.3660,0.0100,0.2110 (39,59.2,69.4) => 0.5800,0.5030,0.2170,0.6020 (9.1,84.9,31.9) => 0.6920,0.2410,0.6310,0.2530 (22.3,2.6,57.8) => 0.8560,0.1800,-0.0740,0.4780 (61.4,89.1,28.8) => 0.5050,0.5020,0.4940,0.4990`

• Skye

Perhaps this would help with some ideas? Just have to port it to C#.

https://github.com/anvaka/math-quaternion/blob/master/index.js

• Gindipple

I bookmarked it to compare to my code, but I have nearly identical structure to it. And yet not coming up with same results as Sansar.

• Skye

Here's a Three.js version of the output using your input values. You can play with that if you want to experiment and stuff. I ordered the results in XYZW.

https://codepen.io/anon/pen/WZQpmP?editors=1111

Edited by Skye
• Gindipple

blah forum ate my post

I couldn't get either of them to match the Sansar Quats

I started from here: https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

Trying numerous rotation sequences to get matching results.

• Gindipple

BTW them input angles are in degrees

My larger test involves 64 combinations of 90 angles in XYZ

• Gindipple

The solution SHOULD be one of the 12 possible sequences of rotations that will look something like this:

` X = SR * CP * CY + CR * SP * SY, Y = CR * SP * CY - SR * CP * SY, Z = CR * CP * CY + SR * SP * CY, W = CR * CP * CY - SR * SP * SY,or W = CY * CPplusR, X = CY * SPplusR, Y = SY * CPminusR, Z = SY * SPminusR,`

Where

` float CR = (float)Math.Cos((Math.PI / 180) * (q.Roll / 2)); float SR = (float)Math.Sin((Math.PI / 180) * (q.Roll / 2)); float CP = (float)Math.Cos((Math.PI / 180) * (q.Pitch / 2)); float SP = (float)Math.Sin((Math.PI / 180) * (q.Pitch / 2)); float CY = (float)Math.Cos((Math.PI / 180) * (q.Yaw / 2)); float SY = (float)Math.Sin((Math.PI / 180) * (q.Yaw / 2)); float CPplusR = (float)Math.Cos((Math.PI / 180) * (q.Pitch + q.Roll) / 2); float SPplusR = (float)Math.Sin((Math.PI / 180) * (q.Pitch + q.Roll) / 2); float CPminusR = (float)Math.Cos((Math.PI / 180) * (q.Pitch - q.Roll) / 2); float SPminusR = (float)Math.Sin((Math.PI / 180) * (q.Pitch - q.Roll) / 2);`

I am using Tait-Bryan angles where Roll = X, Pitch = Y and Yaw = Z, which is maybe throwing me off. Not sure.

• Skye

You're right. I updated the code to convert degrees to radians. Here's the new link. It seems to match closer to yours now and I reordered the results (WXYZ) so it's ordered like yours.

https://codepen.io/anon/pen/WZQpmP?editors=1111

• Gindipple

Drats! I had one typo in it throwing it off. Now I just need to tie the method they used back to one of the 12 sequences in that nasa doc.

• Gindipple

Well I couldn't resolve the equation to one on the nasa doc, in the Talk section on the wiki one guy suggest it corresponds to the 10th rotation sequence but there's also chatter that suggest the wiki is a mess. Somehow the shuttle worked though lol

Anyway Thanks Skye the one you found indeed works!

So the solution in its entirety in C# is:

` private Quaternion FromEulerAngles(Vector a) { a *= (0.5f * Mathf.RadiansPerDegree); return new Quaternion { W = (float)(Math.Cos(a.X) * Math.Cos(a.Y) * Math.Cos(a.Z) - Math.Sin(a.X) * Math.Sin(a.Y) * Math.Sin(a.Z)), X = (float)(Math.Sin(a.X) * Math.Cos(a.Y) * Math.Cos(a.Z) + Math.Cos(a.X) * Math.Sin(a.Y) * Math.Sin(a.Z)), Y = (float)(Math.Cos(a.X) * Math.Sin(a.Y) * Math.Cos(a.Z) - Math.Sin(a.X) * Math.Cos(a.Y) * Math.Sin(a.Z)), Z = (float)(Math.Cos(a.X) * Math.Cos(a.Y) * Math.Sin(a.Z) + Math.Sin(a.X) * Math.Sin(a.Y) * Math.Cos(a.Z)) }; }`

BTW this takes the Vector a in degrees and then converts it to Radians there at the front Unlike the LL version. It also doesn't use static as they do but that's just semantics

Edited by Gindipple
• Skye

Good to see you got it figured out! :)

• DynamicEvolution

2+2 = 5