# Axis Angle to quaternion and quaternion to Axis angle question

Axis Angle to quaternion and quaternion to Axis angle question

Greetings All (matlab / octave code)

Link to text file in case formatting gets messed up http://db.tt/nVv8Ivj

I created two functions one to convert axis angle to quaternion and another one to convert quaternion to axis angle as far as I can tell the formulas are correct the question I have is when I create a quaternion from the axis angle format example: x=.3 y=.1 z=.6 and the angle is 45 degrees I get (0.962730w 0.119633i 0.039878j 0.239266k) which is correct when I check it. But when I plug this quaternion number back into my function I get back angle is 31.384 degrees x=.44233, y=.14744 z=.88465 I was expecting to get back x=.3 y=.1 z=.6 and the angle of 45 degrees the same thing I put in

Does anyone know what I'm doing wrong? The reason I'm doing it this way is to do rotations on values in arrays and not get gimbal lock. I also plan to plot it and animate it, and the axis angle format (x,y,z angle) is easier to understand when it comes to plotting

Iv'e included the code below with a link above to the text file since the formating sometimes gets messed up.

%Vector taken in [i j k], angle in degrees
%quaterions given in Format [w xi yj zk] or [w x y z]
%
%Example of using function:  ccc=quat([.3 .1 .6],45)
%0.962730w   0.119633i   0.039878j   0.239266k

function Q= quat(vect,theta)
Q = zeros(1,4);
xyz_and_angle=[vect theta]    %displays inputed data and theta angle before deg to rad conversion
%thetaconvert = (theta*pi/180)./norm(theta*pi/180) %convert deg to rad
thetaconvert=theta*pi/180;
px=vect(1,1);py=vect(1,2);pz=vect(1,3);
Q(1,1) = cos(thetaconvert/2); %w value
Q(1,2)= px*sin(thetaconvert/2); % x value
Q(1,3)= py*sin(thetaconvert/2); % y value
Q(1,4)= pz*sin(thetaconvert/2); % z value

q1w=Q(1,1);%qw value
q1x=Q(1,2);%qx value
q1y=Q(1,3);%qy value
q1z=Q(1,4);%qz value

%Normalize Quaternion due to floating point errors
qnorm=sqrt(q1w^2+q1x^2+q1y^2+q1z^2)
Q=Q./qnorm %normalize Q array

%quaterions taken in Format [w xi yj zk] or [w x y z]
%example ccc=[0.962730   0.119633   0.039878   0.239266]
%ccc2=quattoaxis(ccc)
%Answer comes back as angle is 31.384 degrees x=.44233, y=.14744 z=.88465
%not sure if the answer is right I thought it would be
%x=.3 y=.1 z=.6 and the angle of 45 degrees the same thing I put in above

function Q= quattoaxis(quat)
Q = zeros(1,4);
q1w=quat(1,1);q1x=quat(1,2);q1y=quat(1,3);q1z=quat(1,4);
%Get angle from quat

%convert Quaternion to Axis
Q(1,1) = 2*acos(q1w) *180/pi %w / angle, I  also included radians to degrees
Q(1,2)= q1x/sqrt(1-q1w^2)  %x
Q(1,3)= q1y/sqrt(1-q1w^2) %y
Q(1,4)= q1z/sqrt(1-q1w^2)   %z

axisangle=Q(1,1) %w / angle, I  also included radians to degrees
axisx=Q(1,2) %x
axisy=Q(1,3) %y
axisz=Q(1,4)   %z

%Normalize axis angle  due to floating point errors
qnorm=sqrt(axisx^2+axisy^2+axisz^2)
axisx=Q(1,2)/qnorm; %x
axisy=Q(1,3)/qnorm; %y
axisz=Q(1,4)/qnorm;  %z

Q=[axisangle axisx axisy axisz]

-

Right off the bat, a reality check shows something amiss here.

Given ANY axis U = (xi, yj, zk) and a rotational angle alpha, the w (i.e., real) value of the resulting quaternion should be cos(alpha/2). But if alpha is 45 degrees, then w = cos(pi/8.0) should be around 0.924... and not somewhere about 0.963..., as you seem to expect when 'correctly' calculating ccc=quat([.3 .1 .6], 45).

Your error is that the axis rotation quaternion given axis U and rotation angle alpha assumes that U is already normalized (has length 1.0). So your formula should (in an ideal world, without any round-off error) be:

 norm(U)*sin(alpha/2) + cos(alpha/2).


where norm(U) is U, 'normalized' to have length 1. What you have coded up is instead

 norm(U*sin(alpha/2) + cos(alpha/2)).


As a test, try using your existing code to evaluate ccc = quat([300, 100, 600], 45). It will be much more 'off' than your example (where U is 'relatively' close to being normalized).

That should make sense: the quaternion that rotates 45 degrees around the axis (.3, .1, .6) should be exactly the same quaternion that rotates 45 degrees around the axis (300, 100, 600). In both caes, it's really the same axis: the latter is just a 'longer version' of the former.

Since we are not in an idealized world lacking round-off error, what you want to do is first, normalize the axis of rotation U; then construct the quaternion, and then normalize the quaternion:

 norm(norm(U)*sin(alpha/2) + cos(alpha/2))
`

BTW, while it's quite readable, I don't recognize the syntax of the language your are working in. What language is it?

-
It seems to be Matlab. – Hauke Strasdat Nov 4 '11 at 8:44