From a couple references (i.e., http://en.wikipedia.org/wiki/Rotation_matrix "Rotation matrix from axis and angle", and exercise 5.15 in "Computer Graphics - Principles and Practice" by Foley et al, 2nd edition in C), I've seen this definition of a rotation matrix (implemented below in Octave) that rotates points by a specified angle about a specified vector. Although I have used it before, I'm now seeing rotation problems that appear to be related to orientation. The problem is recreated in the following Octave code that
- takes two unit vectors: src (green in figures) and dst (red in figures),
- calculates the angle between them: theta,
- calculates the vector normal to both: pivot (blue in figures),
and finally attempts to rotate src into dst by rotating it about vector pivot by angle theta.
% This test fails: rotated unit vector is not at expected location and is no longer normalized. s = [-0.49647; -0.82397; -0.27311] d = [ 0.43726; -0.85770; -0.27048] test_rotation(s, d, 1); % Determine rotation matrix that rotates the source and normal vectors to the x and z axes, respectively. normal = cross(s, d); normal /= norm(normal); R = zeros(3,3); R(1,:) = s; R(2,:) = cross(normal, s); R(3,:) = normal; R % After rotation of the source and destination vectors, this test passes. s2 = R * s d2 = R * d test_rotation(s2, d2, 2); function test_rotation(src, dst, iFig) norm_src = norm(src) norm_dst = norm(dst) % Determine rotation axis (i.e., normal to two vectors) and rotation angle. pivot = cross(src, dst); theta = asin(norm(pivot)) theta_degrees = theta * 180 / pi pivot /= norm(pivot) % Initialize matrix to rotate by an angle theta about pivot vector. ct = cos(theta); st = sin(theta); omct = 1 - ct; M(1,1) = ct - pivot(1)*pivot(1)*omct; M(1,2) = pivot(1)*pivot(2)*omct - pivot(3)*st; M(1,3) = pivot(1)*pivot(3)*omct + pivot(2)*st; M(2,1) = pivot(1)*pivot(2)*omct + pivot(3)*st; M(2,2) = ct - pivot(2)*pivot(2)*omct; M(2,3) = pivot(2)*pivot(3)*omct - pivot(1)*st; M(3,1) = pivot(1)*pivot(3)*omct - pivot(2)*st; M(3,2) = pivot(2)*pivot(3)*omct + pivot(1)*st; M(3,3) = ct - pivot(3)*pivot(3)*omct; % Rotate src about pivot by angle theta ... and check the result. dst2 = M * src dot_dst_dst2 = dot(dst, dst2) if (dot_dst_dst2 >= 0.99999) "success" else "FAIL" end % Draw the vectors: green is source, red is destination, blue is normal. figure(iFig); x(1) = y(1) = z(1) = 0; ubounds = [-1.25 1.25 -1.25 1.25 -1.25 1.25]; x(2)=src(1); y(2)=src(2); z(2)=src(3); plot3(x,y,z,'g-o'); hold on x(2)=dst(1); y(2)=dst(2); z(2)=dst(3); plot3(x,y,z,'r-o'); x(2)=pivot(1); y(2)=pivot(2); z(2)=pivot(3); plot3(x,y,z,'b-o'); x(2)=dst2(1); y(2)=dst2(2); z(2)=dst2(3); plot3(x,y,z,'k.o'); axis(ubounds, 'square'); view(45,45); xlabel("xd"); ylabel("yd"); zlabel("zd"); hold off end
Here are the resulting figures. Figure 1 shows an orientation that doesn't work. Figure 2 shows an orientation that works: the same src and dst vectors but rotated into the first quadrant.
I was expecting the src vector to always rotate onto the dst vector, as shown in Figure 2 by the black circle covering the red circle, for all vector orientations. However Figure 1 shows an orientation where the src vector does not rotate onto the dst vector (i.e., the black circle is not on top of the red circle, and is not even on the unit sphere).
For what it's worth, the references that defined the rotation matrix did not mention orientation limitations, and I derived (in a few hours and a few pages) the rotation matrix equation and didn't spot any orientation limitations there. I'm hoping the problem is an implementation error on my part, but I haven't been able to find it yet in either of my implementations: C and Octave. Have you experienced orientation limitations when implementing this rotation matrix? If so, how did you work around them? I would prefer to avoid the extra translation into the first quadrant if it isn't necessary.
Thanks,
Greg