Code covered by the BSD License  

Highlights from
quaternion.m

image thumbnail
from quaternion.m by Mark Tincknell
quaternion class, vectorized, converts among rotation representations, numerical Euler propagation

quaterniondemo( time, sap, DCMin, interval )
function quaterniondemo( time, sap, DCMin, interval )
% function quaterniondemo( time, sap, DCMin, interval )
% quaternion demo, compare numerical and analytical rotational motion
% solutions
% Inputs:
%  time(nt)     time series array (s)
%  sap(3)       [spin rate (Hz), precession cone half angle (rad),
%               precession rate (Hz)]
%  DCMin(3,3) [OPTIONAL] initial Direction Cosine Matrix; default = eye(3)
%  interval   [OPTIONAL] plot update pause interval (s); default = 0.1
% Outputs:
%  2 figures ploting axis orientations for the time series from matlab's
%  ode45 (Ordinary Differential Equation) numerical solution using the
%  quaternion class and PropagateEulerEq method, and the analytical
%  solution for axisymmetric objects computed in the spinprecess function.
% Author:
%  Mark Tincknell, 4 January 2011

if (nargin < 3) || isempty(DCMin)
    DCMin   = eye(3);
end
if (nargin < 4) || isempty(interval)
    interval    = 0.1;
end
ws      = 2 * pi * sap(1);
theta   = sap(2);
wp      = 2 * pi * sap(3);
costh   = cos( theta );
if (abs( costh ) < eps) || (ws == 0)
    w0  = [ 0; -wp; 0 ];
    I   = [ 1; 1; 1 ];
else
    mu  = 1 + ws /( wp * costh );
    w0  = [ ws /( 1 - 1/mu ); -ws * tan( theta )/( mu - 1 ); 0 ];
    I   = [ 1; mu; mu ];
end
q0      = quaternion.angleaxis( theta, [0;0;1] );
[q1 w1] = PropagateEulerEq( q0, w0, I, time );
q1      = quaternion.rotationmatrix( DCMin ) .* q1;
PlotRotation( q1, interval );
title( 'quaternion' );

DCM     = spinprecess( time, sap, DCMin );
plotRotation( DCM, interval );
title( 'spinprecess' );

end % quaterniondemo

function plotRotation( DCM, interval )
% function plotRotation( DCM, interval )
% Plot rotation axes for a series of Direction Cosine Matrices, adapted
% from the quaternion PlotRotation method
if ~exist( 'interval', 'var' )
    interval    = 0.1;
end
nel = size( DCM, 3 );
or  = zeros(1,3);
ax  = eye(3);
alx = zeros( nel, 3, 3 );
figure;
for iel = 1 : nel
%     plot3( [ or; ax(:,1).' ], [ or ; ax(:,2).' ], [ or; ax(:,3).' ], ':' );
    plot3( [ or; ax(1,:) ], [ or ; ax(2,:) ], [ or; ax(3,:) ], ':' );
    hold on
    set( gca, 'Xlim', [-1 1], 'Ylim', [-1 1], 'Zlim', [-1 1] );
    xlabel( 'x' );
    ylabel( 'y' );
    zlabel( 'z' );
    grid on
    nax = DCM(:,:,iel);
    alx(iel,:,:)    = nax; 
%     plot3( [ or; nax(:,1).' ], [ or ; nax(:,2).' ], [ or; nax(:,3).' ], '-', 'LineWidth', 2 );
    plot3( [ or; nax(1,:) ], [ or ; nax(2,:) ], [ or; nax(3,:) ], '-', 'LineWidth', 2 );
%     plot3( alx(1:iel,:,1), alx(1:iel,:,2), alx(1:iel,:,3), '*' );
    plot3( squeeze(alx(1:iel,1,:)), squeeze(alx(1:iel,2,:)), squeeze(alx(1:iel,3,:)), '*' );
    if interval
        pause( interval );
    end
    hold off
end % for
end % plotRotation

function [DCMout, Omega] = spinprecess( time, sap, DCMin )
% function [DCMout, Omega] = spinprecess( time, sap, DCMin )
% Direction Cosine (Rotation) Matrices for a spinning, precessing
% axisymmetric object.  "x" ([1;0;0]) is the principal body axis.
% Inputs:
%  time(nt)     times (s)
%  sap(3)       [spin rate (Hz), prec. cone angle (rad), prec. rate (Hz)]
%  DCMin(3,3) [OPTIONAL] initial Direction Cosine Matrix; default = eye(3)
% Outputs:
%  DCMout(3,3,nt)   Direction Cosine Matrices
%  Omega(3,3,nt)    Rotational velocity matrices
% Application:
%  x_rot = DCMout * x (where x is a 3 element column position vector)
%  v_rot = Omega * x + v (where v is the translational velocity vector)
% Calls:
%  rodrigues(axis,theta)    Rotation by theta about axis
% Author:
%  Mark Tincknell, MIT LL, 23 Nov. 2004
%                  revised 14 Dec. 2009

if (nargin < 3) || isempty(DCMin)
    DCMin   = eye(3);
end
nt      = length( time );
Rang    = rodrigues( [0;0;1], sap(2) ); % precession cone angle
omegas  = 2 * pi * sap(1);              % spin
omegap  = 2 * pi * sap(3);              % precession
for it = nt : -1 : 1
    [Rs, dRs]   = rodrigues( [1;0;0], omegas * time(it) );
    [Rp, dRp]   = rodrigues( [1;0;0], omegap * time(it) );
    DCMout(:,:,it)  = DCMin * Rp * Rang * Rs;
    Omega(:,:,it)   = DCMin *( omegap * dRp * Rang * Rs + ...
                               omegas * Rp * Rang * dRs );
end
end % spinprecess

function [R, dR] = rodrigues( u, theta )
% function [R, dR] = rodrigues( u, theta )
% Computes rotation matrix (Direction Cosine Matrix) from Rodrigues'
% rotation formula. See http://mathworld.wolfram.com/RodriguesRotationFormula.html
% Inputs:
%  u(3)     fixed axis of rotation
%  theta    rotation angle in radians
% Outputs:
%  R(3,3)   rotation matrix
%  dR(3,3)  differential of R
% Application:
%  x_rot = R * x (where x is a 3 element column vector)
%  v_rot = omega * dR * x (where omega is d(theta)/dt)
% Authors:
%  Douglas Lanman, Mark Tincknell, MIT LL, 8 August 2003

% Normalize u (fixed-axis of rotation)
u   = u/norm(u);

% Skew-symmetric matrix W
W   = [ 0    -u(3)  u(2);
        u(3)  0    -u(1);
       -u(2)  u(1)  0];
W2  = W^2;

% Trig functions
sth = sin( theta );
cth = cos( theta );

% Rotation matrix R, differential rotation matrix dR
R   = eye(3) + sth * W + (1 - cth) * W2;
dR  = cth * W + sth * W2;

end % rodrigues

Contact us