Quaternions to Axis Angles

–Skip to the bold words to get to the real questions–

Hi, I have been having troubles with the conversion between quaternions to axis angles. I know that there are two problems when converting and that’s 0 degrees and 180 degrees, since they are both “flat”, it’s hard to tell the difference between them (or I think that’s why).

I was reading up on quaternions because I need to figure out how steep a surface is, e.g. 45 degrees on the x or 45 degrees on the y. Then I need to figure out how to tell whether the player is going up the slant or down the slant. I want to check the axis angles to see how steep they are, but I don’t know how.

Right now all I know about quaternions is that there is one real axis, and the other three are imaginary.

My brain isn’t developed well enough to understand the rest, but simple put:

1. I want to find a way to tell whether a slant is steep or not (which is why I am asking for conversion between quats and axis angles)

2. A way to tell whether the player is going up or down the slant.

Thanks everyone! Bye.
Linkxgl

If you have a mathutils quaternion, you can just use the to_euler() function.


vec = quat.to_euler()

And what are you getting a quaternion from?

Well, from bone rotation in blender, but that’s not even in the question :stuck_out_tongue:

For some reason I get an error when converting the a matrix orientation to euler, so I first convert it to a quaternion. I was able to do it afterwards. I don’t understand how eulers work though.

An euler is a vector representing the amount of rotation about the three axises. While eulers can be defined in any order, the one you will get from Blender is usually XYZ. So euler[0] is the amount of rotation about the x axis. This should be more intuitive than a quaternion or matrix (it is also the way the rotations are often represented in the Blender ui).

So what if the euler[0] is equal to -0.785, but it’s turned 45 degrees on the x?

First of all, the measurements are in radians, and not degrees. There are functions for doing the conversion for you.

You may just want to find the angle between the character and the global z axis. This might be easier, especially since it might be possible to describe the same orientation with different euler values.

Alright, thanks Kupoman! I will look into that, if I can’t figure it out, I’ll revive the thread.

Hi Linkxgl,

I made this script for the airplane usage, but it can us with ground vehicles as well.
/uploads/default/original/3X/0/8/081fb6ea08904e9c1353480de0cd44cc01ab8a9f.blendd=1313179382

Append the ‘ATTITUDE’ named group to your project and then parent the ‘ATTITUDE’ named object to the target object.

You could use the cross product to tell if the player is going up or down the slope.

The x component of the the cross product of the slope’s normal and the player’s velocity vector multiplied by the inverse of the player’s orientation matrix should give you the direction. (Assuming y+ is forward)

That is:

hit_norm = player.rayCast(...)[1]
vel = player.worldLinearVelocity
oriI = plaer.worldOrientation.inverted()

dir = hit_norm.cross(vel) * oriI

if dir[0] < 0:
    # travelling up
elif dir[0] > 0:
    # travelling down
else:
    # travelling along slope

Hey Andrew, sorry for the super late reply. I was on a mini vacation. Anyways, you’re a funny guy. For some reason I actually thought “cross()” was an actual function, so I was trying it out, and after 3 minutes I realized that I was just being stupid, hahaha.

Alright, so it’s working very well. I think you made a few mistakes, or maybe I made a few mistakes. It didn’t seem to work with the cross product of x, but it worked fine with the cross product of y. I’m still actually not sure what a cross product is though, which is why I think I made a mistake. I figured it’s when you multiply two vectors to get a perpendicular vector? You can see I have no idea what I’m talking about, I have trouble understanding this stuff, especially from wikipedia. Would you mind explaining it in simpler terms please?

Here’s the .blend I made using your idea which worked out perfectly.
math_stuffs.blend (350 KB)

Since this thread is a little bit about quaternions, I have another problem. I want to align a bone to a normal, so it looks like a foot is stepping on the ground. Here’s what I got so far, but it doesn’t seem to be working. The bone has kind of an “inverted” rotation. The .blend below is a quick example. I have no idea how to fix, so if someone could help me out that’d be cool.
try_foot.blend (366 KB)

Oh Kupoman and Andrew, thanks a lot for all the help, everything is working fine now, thanks so much. If you have any ideas on my second problem, help me out please :slight_smile:

cross() is a function of the Vector class, so simply change hit_n = own[‘normals’] to Vector(own[‘normals’]) to make use of it.

You pretty much have the idea of the cross product down, the result will be orthogonal to the other two vectors. Its a handy little thing.

I’ve realised my above method doesn’t work for all situations, try this one:

from math import pi

import bge
from mathutils import *

own = bge.logic.getCurrentController().owner

slope_normal = own.rayCast(own.worldPosition + Vector([0,0,-1]), own)[2]
vel = own.worldLinearVelocity

vec1 = slope_normal.cross(Vector([0,0,1]))
vec2 = slope_normal * Matrix.Rotation(pi/2, 3, vec1)
angle = vec2.angle(vel)

if abs(angle - pi/2) < 0.005:
    # travelling along slope - travelling on flat ground
elif angle < pi/2:
    # up
elif angle > pi/2:
    # down

That should work. I tested it this time.

I’m not too sure about quaternions, sorry.

Hey Andrew sorry for the late reply, again, I wasn’t actually able to try this out until today, so I didn’t want to reply. I wanted to know what was the problem with the old code, and the what you did to fix it in the version above. If you wouldn’t mind briefly explaining.

@Everyone:

Since this thread is a little bit about quaternions, I have another problem. I want to align a bone to a normal, so it looks like a foot is stepping on the ground. Here’s what I got so far, but it doesn’t seem to be working. The bone has kind of an “inverted” rotation. The .blend below is a quick example. I have no idea how to fix, so if someone could help me out that’d be cool.
[ATTACH]152055[/ATTACH]

Its not so much a problem with the code but a problem with the idea. It doesn’t work for all cases.