[Math] Axis Angle to quaternion and quaternion to Axis angle question

quaternions

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)  
%Answer should be ->
%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]

Best Answer

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?

Related Question