Code covered by the BSD License  

Highlights from
Keplerian State Transition Matrix

from Keplerian State Transition Matrix by Dmitry Savransky
Given initial positions and velocities, calculate the keplerian state transition matrix for an orbit

keplerSTM(x0,dt,mu)
function Phi = keplerSTM(x0,dt,mu)
% keplerSTM - Generate the state transition matrix for keplerian orbits.
%   Phi = keplerSTM(x0,dt,mu) will return the state transition matrix Phi
%   for a set of objects described by initial positions and velocities (x0)
%   with gravitational parameters mu, propogated along Keplerian orbits for
%   time dt.
% 
%   x0 must be a row vector of length 6n where n is the number of planets. 
%   For each planet, x0 must include the 3 position and 3 velocity values
%   in the order [r1,r2,r3,v1,v2,v3].' These positions and velocities are 
%   measured in a cartesian coordinate system with the central object 
%   (i.e. star) at the origin.  For multiple planets, simply stack
%   several of these vectors on top of each other.  mu must contain n
%   values equal to G(m+ms) where G is the gravitational constant, m is the
%   mass of the orbiting object, and ms is the mass of the central object.
%   dt is a scalar value of time to propogate. 
%   NOTE: All units should be consistent.  If the positions are in AU and
%   velocities are in AU/day, then dt must be in days, and mu must be in
%   AU^3/day^2.
% 
%   This is calculated using the algorithm described in Shepperd, 1984
%   which employs Goodyear's universal variables and solves the Kepler
%   problem using continued fractions.
% 
%   Example:
%       %propogate a planet 10 days along its orbit:
%       x0 = [-0.8684, -0.6637, 0.7207, 0.0039, 0.0056, 0.0120].';
%       x1 = keplerSTM(x0,10,2.6935e-04)*x0;
% 
%   Written by Dmitry Savransky, 22 April 2008
%   17 November 2008 - Fixed several bugs associated with calculations for
%   more than one planet

%determine number of planets and validate input
nplanets = length(x0)/6;
if nplanets - floor(nplanets) > 0
    disp('The length of the input vector must be a multiple of 6.');
    Phi = -1;
    return;
end
if length(mu) ~= nplanets
    disp('The mu vector must contain the same number of values as the length of the input vector divided by 6.');
    Phi = -2;
    return;
end

%orient mu properly
mu = mu(:).';

%create position and velocity matrices
x0 = reshape(x0,6,nplanets);
r0 = x0(1:3,:);
v0 = x0(4:6,:);

%constants
r0norm = sqrt(sum(r0.^2));
nu0 = dot(r0,v0);
beta = 2*mu./r0norm - dot(v0,v0);

%initialization
u = zeros(1,nplanets);

%For elliptic orbits, calculate period effects
deltaU = zeros(1,length(beta));
eorbs = beta > 0;
if sum(eorbs) > 0
    P = 2*pi*mu(eorbs).*beta(eorbs).^(-3/2);
    n = floor((dt + P/2 - 2*nu0(eorbs)./beta(eorbs))./P);
    deltaU(eorbs) = 2*pi*n.*beta(eorbs).^(-5/2);
end

%continued fraction constants
a = 5;
b = 0;
c = 5/2;
k = 1 - 2*(a-b);
l = 2*(c-1);
d = 4*c*(c-1);
n = 4*b*(c-a);

%kepler iteration loop
t = zeros(1,nplanets);
counter = 0;
%loop until convergence of the time array to the time step
while sum(abs((t-dt)/dt*100)) > 1e-3 && counter < 1000;
    q = beta.*u.^2./(1+beta.*u.^2);
    U0w2 = 1 - 2*q;
    U1w2 = 2*(1-q).*u;
    U = 16/15*U1w2.^5 .* contFrac(q) + deltaU;
    U0 = 2*U0w2.^2-1;
    U1 = 2*U0w2.*U1w2;
    U2 = 2*U1w2.^2;
    U3 = beta.*U + U1.*U2/3;
    r = r0norm.*U0 + nu0.*U1 + mu.*U2;
    t = r0norm.*U1 + nu0.*U2 + mu.*U3;
    u = u - (t-dt)./(4*(1-q).*r);
    counter = counter+1;
end
if counter == 1000
    disp('Failed to converge on t');
end

%kepler solution
f = 1 - mu./r0norm.*U2;
g = r0norm.*U1 + nu0.*U2;
F = -mu.*U1./r./r0norm;
G = 1 - mu./r.*U2;

%construct the state transition matrix
Phi = zeros(6*nplanets);
for j=1:nplanets
    st = (j-1)*6+1;
    Phi(st:st+5,st:st+5) = [eye(3)*f(j)  eye(3)*g(j);eye(3)*F(j) eye(3)*G(j)];
end

    %calculate continued fraction
    function G = contFrac(x)
        
        %initialize arrays
        A = zeros(1,length(x))+1;
        B = zeros(1,length(x))+1;
        G = zeros(1,length(x))+1;

        Gprev = zeros(1,length(x))+2;
        counter = 0;
        %loop until convergence of continued fraction
        while sum(abs((G-Gprev)./G*100)) > 1e-3 && counter < 1000
            k = -k;
            l = l+2;
            d = d+4*l;
            n = n+(1+k)*l;
            A = d./(d - n*A.*x);
            B = (A-1).*B;
            Gprev = G;
            G = G + B;
            counter = counter+1;
        end
        if counter == 1000
            disp('Failed to converge on G');
        end
    end
end

Contact us at files@mathworks.com