I’m new to Quaternions so to learn more about them I decided to read up on various resources and try to construct my own elementary Quaternion library in python and then validate it with results from Unity.

So what I do is create a new project and place a cube in space. I then add to that cube a new script that simply copies its transform.rotation to a public variable that I call “myQuaternion”. A snippet of the innards of the script are:

```
public Quaternion myQuaternion;
void Update() {
myQuaternion = transform.rotation;
}
```

So that seems to be working as expected, I can inspect the cube, change its rotation and get different values in myQuaternion. Great.

So now based on this wikipedia section: Conversion between quaternions and Euler angles - Wikipedia

I create this python function:

```
def euler_to_quaternion(phi,theta,psi):
return [math.cos(math.pi*phi/360)*math.cos(math.pi*theta/360)*math.cos(math.pi*psi/360)+
math.sin(math.pi*phi/360)*math.sin(math.pi*theta/360)*math.sin(math.pi*psi/360),
math.sin(math.pi*phi/360)*math.cos(math.pi*theta/360)*math.cos(math.pi*psi/360)-
math.cos(math.pi*phi/360)*math.sin(math.pi*theta/360)*math.sin(math.pi*psi/360),
math.cos(math.pi*phi/360)*math.sin(math.pi*theta/360)*math.cos(math.pi*psi/360)+
math.sin(math.pi*phi/360)*math.cos(math.pi*theta/360)*math.sin(math.pi*psi/360),
math.cos(math.pi*phi/360)*math.cos(math.pi*theta/360)*math.sin(math.pi*psi/360)-
math.sin(math.pi*phi/360)*math.sin(math.pi*theta/360)*math.cos(math.pi*psi/360)]
```

So now I run some tests:

**For rotation (45,0,0):**

- Unity: w=0.9238795325112867

x=0.3826834323650898 y=0.0 z=0.0 - Python: w=0.9238795325112867

x=0.3826834323650898 y=0.0 z=0.0

Looks good, they match

**For rotation (0,45,0):**

- Unity: w=0.9238795325112867 x=0.0

y=0.3826834323650898 z=0.0 - Python:

w=0.9238795325112867 x=0.0

y=0.3826834323650898 z=0.0

Again, a match

**For rotation (0,0,45):**

- Unity: w=0.9238795325112867 x=0.0 y=0.0 z=0.3826834323650898
- Python: w=0.9238795325112867 x=0.0 y=0.0 z=0.3826834323650898

Again, a match

So here’s the problem:

**For rotation (0,45,45):**

- Unity: w=0.8535533905932737
**x=0.14644660940672624**y=0.3535533905932738 z=0.3535533905932738 - Python: w=0.8535533905932737
**x=-0.14644660940672624**y=0.3535533905932738 z=0.3535533905932738

So the polarity for the value of x is different, not good…

**For rotation (45,45,0):**

- Unity: w= 0.8446231986207332
**x=0.46193976625564337****y=0.1913417161825449**z=0.1913417161825449 - Python: w= 0.8446231986207332
**x= 0.1913417161825449****y=0.46193976625564337**z= 0.1913417161825449

Now things look even more confusing, any idea what is going on?

Update: Doing more research and working through this issue, I’ve discovered that order of operations is very important when doing rotations. I found that I needed to break the rotations into 3 separate quaternions and then multiply them in a specific order, here’s some additional python code:

```
def quaternion_mult(q,r):
return [r[0]*q[0]-r[1]*q[1]-r[2]*q[2]-r[3]*q[3],
r[0]*q[1]+r[1]*q[0]-r[2]*q[3]+r[3]*q[2],
r[0]*q[2]+r[1]*q[3]+r[2]*q[0]-r[3]*q[1],
r[0]*q[3]-r[1]*q[2]+r[2]*q[1]+r[3]*q[0]]
def unity_euler_to_quaternion(x,y,z):
return quaternion_mult(quaternion_mult(euler_to_quaternion(0,y,0),
euler_to_quaternion(x,0,0)),
euler_to_quaternion(0,0,z))
```

Now when I do a unity_euler_to_quaternion(45,45,45), the answers match.

Whew!