PDA

View Full Version : Quaternions


roman_suvorov
05-23-2008, 02:41 PM
Hello, can anyone tell me the exact meaning of the [x,y,z,w] components of a quaternion returned by a .getQuat() function? I am particularly interested in the range these values can take, especially w.

This might seem like a silly question, but are the two quats returned in this script in the exact same format (i.e., same ordering of components, scaled in the same way, etc.)?

...
inertiaCube = viz.add('intersense.dls') # Add inertiaCube
print inertiaCube.getQuat() # 1st quaternion
vicon = viz.add('vicon.dle', 0, ipAddressAndPort) # Add the Vicon system
firstBody = vicon.getBody(0) # Get the first body
print firstBody.getQuat() # 2nd quaternion
...

farshizzo
05-27-2008, 05:51 PM
The meaning of the x,y,z,w components of a quaternion are similar to the meaning of axis-angle components. the [x,y,z] values represent the axis of rotation. The amount of rotation about that axis in radians is, 2 * acos(w). Keep in mind that Vizard uses a left-handed coordinate system.

All the plugins should return quaternions in the same order (x,y,z,w). I'm assuming most devices will return normalized quaternions as well, but I'm not 100% sure about that.

roman_suvorov
05-28-2008, 10:51 AM
Thanks farshizzo, I appreciate it.
Now knowing that my math is all wrong you can disregard the script I've sent you (as mentioned here (http://www.worldviz.com/forum/showthread.php?t=1470)).

roman_suvorov
06-11-2008, 05:34 PM
All right, I've read QUITE A BIT about quaternions at this point but still don't get them .. :(

Here's some sample code. Copy/paste and run this:


import viz
viz.go(viz.FULLSCREEN)

ROTATION_INC = 2
TRANSLATE_INC = 0.1

i = 0
while (i < 50):
redBall = viz.add("white_ball.wrl")
redBall.setPosition([i, 0, 0])
redBall.color([255, 0, 0])

greenBall = viz.add("white_ball.wrl")
greenBall.setPosition([0, i, 0])
greenBall.color([0, 255, 0])

blueBall = viz.add("white_ball.wrl")
blueBall.setPosition([0, 0, i])
blueBall.color([0, 0, 255])

i += 0.1

viz.MainView.setQuat([0,1,0,0])
viz.MainView.setPosition(5, 0, 0.5)

vizact.whilekeydown(viz.KEY_UP, viz.move, 0, 0, TRANSLATE_INC)
vizact.whilekeydown(viz.KEY_DOWN, viz.move, 0, 0, -TRANSLATE_INC)
vizact.whilekeydown(viz.KEY_LEFT, viz.rotate, viz.BODY_ORI, -ROTATION_INC, 0, 0)
vizact.whilekeydown(viz.KEY_RIGHT, viz.rotate, viz.BODY_ORI, ROTATION_INC, 0, 0)
vizact.whilekeydown(viz.KEY_PAGE_UP, viz.rotate, viz.HEAD_ORI, 0, -ROTATION_INC, 0)
vizact.whilekeydown(viz.KEY_PAGE_DOWN, viz.rotate, viz.HEAD_ORI, 0, ROTATION_INC, 0)


You will see a red "line" in front of you. Look around using left/right arrow keys, tilt your "head" up/down using PgUp/PgDown keys, move forward/backward using up/down arrow keys.
What this is meant to be is "training grounds" for understanding quaternions. If you look at the code inside the while loop you'll see that X-axis is traced with red dots, Y with green, Z with blue (X-Y-Z -> R-G-B was my logic :o).
MainView's originally just slightly off red Y-axis and the rotation is set to [x,y,z,w] = [0,1,0,0].
What I'm trying to understand now that we have a well-defined system of coordinates right in front of us :) is how quaternions work: [0,1,0,0] SHOULD have defined a rotation of 0 degrees around axis [0,1,0] - the Y-axis, so the camera originally should just look down the green Y-axis. Instead we're looking down X!
I hope someone more experienced with quaternions can explain to me how they work in Vizard using this simple script, that would be great. Thanks!

farshizzo
06-11-2008, 05:48 PM
In my previous post I explained what the values mean. So given the quaternion rotation of [0,1,0,0], this would mean a 180 degree rotation around the Y axis (2 * acos(0) = 180 degrees). Printing the euler and axis-angle values of the main view after applying the quaternion will confirm this. Adding the following code at the end of the script:print viz.MainView.getEuler()
print viz.MainView.getAxisAngle()resulted in the following output:[-180.0, 0.0, 0.0]
[0.0, -1.0, 0.0, 180.0]FYI, Vizard color values range from 0-1, not 0-255.

roman_suvorov
06-11-2008, 06:05 PM
Damn, forgot about that acos. Then to get no rotation I need to use w=-1: 2*acos(-1) = 360 degrees. Thanks again farshizzo!

EDIT: The following code makes MainView look down X.

import viz
viz.go(viz.FULLSCREEN)

ROTATION_INC = 2
TRANSLATE_INC = 0.1

i = 0
while (i < 10):
redBall = viz.add("white_ball.wrl")
redBall.setPosition([i, 0, 0])
redBall.color([1 - 0.1*i, 0, 0])

greenBall = viz.add("white_ball.wrl")
greenBall.setPosition([0, i, 0])
greenBall.color([0, 1 - 0.1*i, 0])

blueBall = viz.add("white_ball.wrl")
blueBall.setPosition([0, 0, i])
blueBall.color([0, 0, 1 - 0.1*i])

i += 0.1

viz.MainView.setQuat([0,1,0,-1])
viz.MainView.setPosition(5, 0, 0.5)

vizact.whilekeydown(viz.KEY_UP, viz.move, 0, 0, TRANSLATE_INC)
vizact.whilekeydown(viz.KEY_DOWN, viz.move, 0, 0, -TRANSLATE_INC)
vizact.whilekeydown(viz.KEY_LEFT, viz.rotate, viz.BODY_ORI, -ROTATION_INC, 0, 0)
vizact.whilekeydown(viz.KEY_RIGHT, viz.rotate, viz.BODY_ORI, ROTATION_INC, 0, 0)
vizact.whilekeydown(viz.KEY_PAGE_UP, viz.rotate, viz.HEAD_ORI, 0, -ROTATION_INC, 0)
vizact.whilekeydown(viz.KEY_PAGE_DOWN, viz.rotate, viz.HEAD_ORI, 0, ROTATION_INC, 0)


and also produces much prettier axes. :D Hold on though, why [0,1,0]? We're speciifying no rotation around Y, not X as it seems?

farshizzo
06-12-2008, 10:02 AM
Now you're dealing with non-normalized quaternions, so all bets are off. In general, you don't need to deal with quaternions at such a low level. You can use Vizards matrix routines to deal with rotation transformations.

roman_suvorov
06-17-2008, 10:13 AM
Now you're dealing with non-normalized quaternions, so all bets are off.
Do you then know by any chance what course of action does Vizard take if you try to set an object's quaternion to [x,y,z,w] such that x^2+y^2+z^2+w^2 > 1?
For example, add this function definition to my previous code:

# Normalizes the passed quaternion (which is assumed to have the form
# [x,y,z,w]) so that the vector [x,y,z,w] has unit length.
# Note: normalization is done in place (i.e., the correct way
# of calling this function is 'normalizeQuat(q1)' rather than 'q1 = normalizeQuat(q2)'.
def normalizeQuat (quat):
i = 0
normFactor = 0
while (i < len(quat)):
normFactor += quat[i]**2
i += 1
normFactor = normFactor**0.5

i = 0
while (i < len(quat)):
quat[i] /= normFactor
i += 1

Now if you normalize quat [0,1,0,-1] we get the same MainView orientation as with the unnormalized quaternion. Is this behavior expected? Does a function similar to my 'normalizeQuat' get called in Vizard behind the scenes if you try to set an object's quaternion to an unnormalized one?
In general, you don't need to deal with quaternions at such a low level. You can use Vizards matrix routines to deal with rotation transformations.
Unfortunately, seems like I do. This little script is just a way to fill in the gaps I have in my understanding of quaternions.

farshizzo
06-17-2008, 10:40 AM
Yes, Vizard will internally normalize all quaternions that are passed to the setQuat function of nodes, views, and bones.