Mercurial > hg > octave-lyh
view scripts/quaternion/demoquat.m @ 7583:1d7c23e288d7
__go_draw_axes__: use strcmpi for text properties; use get for hidden properties
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 11 Mar 2008 23:12:17 -0400 |
parents | a1dbe9d80eee |
children |
line wrap: on
line source
## Copyright (C) 1998, 1999, 2000, 2005, 2007 ## Auburn University. All rights reserved. ## ## This file is part of Octave. ## ## Octave is free software; you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or (at ## your option) any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, see ## <http://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} demoquat () ## Demonstrate the functions available for manipulating quaternions. ## ## Thanks to Mr. Charles Hall, Dr. Don Krupp and Dr. Larry Mullins at ## NASA's Marshall Space Flight Center for notes and instruction in ## use and conventions with quaternions. - A. S. Hodel ## @end deftypefn ## Author: A. S. Hodel <a.s.hodel@eng.auburn.edu> ## Adapted-By: jwe function opt = demoquat () opt = 0; quitopt = 5; while (opt != quitopt) opt = menu ("Quaternion function demo (c) 1998 A. S. Hodel, a.s.hodel@eng.auburn.edu", "quaternion construction/data extraction", "simple quaternion functions", "transformation functions", "body-inertial frame demo", "Quit"); switch(opt) case(1) printf("Quaternion construction/data extraction\n"); help quaternion prompt cmd = "q = quaternion(1,2,3,4)"; run_cmd disp("This format stores the i,j,k parts of the quaternion first;") disp("the real part is stored last.") prompt disp(" ") disp("i, j, and k are all square roots of -1; however they do not") disp("commute under multiplication (discussed further with the function") disp("qmult). Therefore quaternions do not commute under multiplcation:") disp(" q1*q2 != q2*q1 (usually)") prompt disp("Quaternions as rotations: unit quaternion to represent") disp("rotation of 45 degrees about the vector [1 1 1]") cmd = "degrees = pi/180; q1 = quaternion([1 1 1],45*degrees)"; run_cmd prompt cmd = "real_q = cos(45*degrees/2)"; run_cmd printf("The real part of the quaternion q(4) is cos(theta/2).\n----\n\n"); cmd = "imag_q = sin(45*degrees/2)*[1 1 1]/norm([1 1 1])" run_cmd disp("The imaginary part of the quaternion is sin(theta/2)*unit vector"); disp("The constructed quaternion is a unit quaternion."); prompt disp("Can also extract both forms of the quaternion:") disp("Vector/angle form of 1i + 2j + 3k + 4:") cmd = "[vv,th] = quaternion(q)"; run_cmd cmd = "vv_norm = norm(vv)"; run_cmd disp("Returns the eigenaxis as a 3-d unit vector"); disp("Check values: ") cmd = "th_deg = th*180/pi"; run_cmd disp("") disp("This concludes the quaternion construction/extraction demo."); prompt case(2) printf("Simple quaternion functions\n"); cmd = "help qconj"; run_cmd cmd = "degrees = pi/180; q1 = quaternion([1 1 1],45*degrees)"; run_cmd cmd = "q2 = qconj(q1)"; run_cmd disp("The conjugate changes the sign of the complex part of the") printf("quaternion.\n\n"); prompt printf("\n\n\nMultiplication of quaternions:\n"); cmd = "help qmult"; run_cmd cmd = "help qinv" run_cmd disp("Inverse quaternion: q*qi = qi*q = 1:") cmd = "q1i = qinv(q1)"; run_cmd cmd = "one = qmult(q1,q1i)"; run_cmd printf("Conclusion of simple quaternion functions"); prompt case(3) printf("Transformation functions\n"); disp("A problem with the discussion of coordinate transformations is that"); disp("one must be clear on what is being transformed: does a rotation of"); disp("theta degrees mean that you're rotating the VECTOR by theta degrees,"); disp("also called the 'active convention,' or does it mean that you rotate "); disp("the COORDINATE FRAME by theta degrees, also called the 'passive convention,' "); disp("which is equivalent to rotating the VECTOR by (-theta) degrees. The"); disp("functions in this demo use the active convention. I'll point out where"); disp("this changes the code as the demo runs."); disp(" -- The author"); prompt printf("\n\n"); disp("Sequences of rotations:") printf("\n\nRotation of a vector by 90 degrees about the reference z axis\n"); cmd = "qz = quaternion([0 0 1], pi/2);"; disp(cmd) ; eval(cmd); printf("\n\nRotation of a vector by 90 degrees about the reference y axis\n"); cmd="qy = quaternion([0 1 0], pi/2);"; disp(cmd) ; eval(cmd); printf("\n\nRotation of a vector by 90 degrees about the reference x axis\n"); cmd="qx = quaternion([1 0 0], pi/2);"; run_cmd printf("\n\nSequence of three rotations: 90 degrees about x, then 90 degrees\n"); disp("about y, then 90 degrees about z (all axes specified in the reference frame):"); qchk = qmult(qz,qmult(qy,qx)); cmd = "[vv,th] = quaternion(qchk), th_deg = th*180/pi"; run_cmd disp("The sequence of the three rotations above is equivalent to a single rotation") disp("of 90 degrees about the y axis. Check:"); cmd = "err = norm(qchk - qy)"; run_cmd disp("Transformation of a quaternion by a quaternion:") disp("The three quaternions above were rotations specified about") disp("a single reference frame. It is often convenient to specify the"); disp("eigenaxis of a rotation in a different frame (e.g., when computing"); disp("the transformation rotation in terms of the Euler angles yaw-pitch-roll)."); cmd = "help qtrans"; run_cmd disp("") disp("NOTE: If the passive convention is used, then the above"); disp("formula changes to v = qinv(q)*v*q instead of ") disp("v = q*v*qinv(q).") prompt disp("") disp("Example: Vectors in Frame 2 are obtained by rotating them from ") disp(" from Frame 1 by 90 degrees about the x axis (quaternion qx)") disp(" A quaternion in Frame 2 rotates a vector by 90 degrees about") disp(" the Frame 2 y axis (quaternion qy). The equivalent rotation") disp(" in the reference frame is:") cmd = "q_eq = qtrans(qy,qx); [vv,th] = quaternion(q_eq)"; run_cmd disp("The rotation is equivalent to rotating about the reference z axis") disp("by 90 degrees (quaternion qz)") prompt disp("Transformation of a vector by a quaternion"); cmd = "help qtransv"; run_cmd disp("NOTE: the above formula changes if the passive quaternion ") disp("is used; the cross product term is subtracted instead of added."); prompt disp("Example: rotate the vector [1,1,1] by 90 degrees about the y axis"); cmd = "vec_r = qtransv([1,1,1],qy)"; run_cmd prompt disp("Equivalently, one may multiply by qtransvmat:") cmd = "help qtransvmat"; run_cmd disp("NOTE: the passive quaternion convention would use the transpose") disp("(inverse) of the orthogonal matrix returned by qtransvmat."); prompt cmd = "vec_r_2 = qtransvmat(qy)*[1;1;1]; vec_err = norm(vec_r - vec_r_2)"; run_cmd disp("") disp("The last transformation function is the derivative of a quaternion") disp("Given rotation rates about the reference x, y, and z axes."); cmd = "help qderivmat"; run_cmd disp("") disp("Example:") disp("Frame is rotating about the z axis at 1 rad/s") cmd = "Omega = [0,0,1]; Dmat = qderivmat(Omega)"; run_cmd disp("Notice that Dmat is skew symmetric, as it should be.") disp("expm(Dmat*t) is orthogonal, so that unit quaternions remain") disp("unit quaternions as the rotating frame precesses."); disp(" ") disp("This concludes the transformation demo."); prompt; case(4) printf("Body-inertial frame demo: Look at the source code for\n"); printf("demoquat.m and qcoordinate_plot.m to see how it's done.\n"); # i,j,k units iv = quaternion(1,0,0,0); jv = quaternion(0,1,0,0); kv = quaternion(0,0,1,0); # construct quaternion to desired view. degrees = pi/180; daz = 45*degrees; del = -30*degrees; qazimuth = quaternion([0,0,1],daz); qelevation = quaternion([cos(daz),sin(daz),0],del); qview = qmult(qelevation,qazimuth); # inertial frame i, j, k axes. iif = iv; jf = qtrans(jv,iv); kf = qtrans(kv,iv); # rotation steps th = 0:5:20; ov = ones(size(th)); myth = [th,max(th)*ov ; 0*ov,th]; # construct yaw-pitch-roll cartoon for kk=1:length(myth(1,:)) thy = myth(1,kk); thp = myth(2,kk); qyaw = quaternion([0,0,1],thy*pi/180); [jvy,th] = quaternion(qtrans(jf,qyaw)); qpitch = quaternion(jvy(1:3),thp*pi/180); qb = qmult(qpitch, qyaw); qi = quaternion([1, 0, 0],180*degrees); printf("yaw=%8.4f, pitch=%8.4f, \n qbi = (%8.4f)i + (%8.4e)j + (%8.4f)k + (%8.4f)\n",thy,thp, ... qb(1), qb(2), qb(3), qb(4)); [vv,th] = quaternion(qb); printf(" = (vector) = [%8.4f %8.4f %8.4f], th=%5.2f deg\n", ... vv(1), vv(2), vv(3), th*180/pi); fflush (stdout); qb = qmult(qb,qi); title(sprintf("yaw=%5.2f deg, pitch=%5.2f deg",thy,thp)) qcoordinate_plot(qi,qb,qview); drawnow (); endfor case(quitopt) printf ("Exiting quaternion demo\n"); otherwise error ("invalid option %f", opt); endswitch endwhile endfunction