// Copyright (c) CNES 2008
//
// This software is part of CelestLab, a CNES toolbox for Scilab
//
// This software is governed by the CeCILL license under French law and
// abiding by the rules of distribution of free software. You can use,
// modify and/ or redistribute the software under the terms of the CeCILL
// license as circulated by CEA, CNRS and INRIA at the following URL
// 'http://www.cecill.info'.
function [cireq,jacob] = CL__oe_car2cireq(pos,vel, mu)
// Cartesian to circular equatorial orbital elements
//
// Calling Sequence
// [cireq, jacob] = CL__oe_car2cireq(pos, vel [, mu])
//
// Description
//
//
Converts cartesian orbital elements to orbital elements adapted to near-circular near-equatorial orbits.
//
The transformation jacobian is optionally computed.
//
See Orbital elements for more details.
//
//
//
// Parameters
// pos: Position vector [x;y;z] [m] (3xN)
// vel: Velocity vector [vx;vy;vz] [m/s] (3xN)
// mu : (optional) Gravitational constant. [m^3/s^2] (default value is %CL_mu)
// cireq: Orbital elements adapted to near-circular orbits [sma;ex;ey;ix,iy;L] [m,rad] (6xN)
// jacob: (optional) Transformation jacobian (See Orbital elements for more details) (6x6xN)
//
// Authors
// CNES - DCT/SB
//
// Examples
// // Example 1
// pos = [7000.e3; 1000.e3; -500.e3];
// vel = [1.e3; 2.e3; 7e3];
// cireq = CL__oe_car2cireq(pos, vel);
//
// // Example 2
// pos = [7000.e3; 1000.e3; -500.e3];
// vel = [1.e3; 2.e3; 7e3];
// [cireq, jacob1] = CL__oe_car2cireq(pos, vel);
// [pos2, vel2, jacob2] = CL__oe_cireq2car(cireq);
// pos2 - pos // => zero
// vel2 - vel // => zero
// jacob2 * jacob1 // => identity
// Declarations:
EPS_ORB = CL__dataGetEnv("epsOrb", internal=%t);
// Code:
if (~exists("mu", "local")); mu = CL__dataGetEnv("mu"); end
// Handle [] cases
if (pos == [] | vel == [])
cireq = [];
jacob = [];
return;
end
// Check input sizes
[pos,vel,N] = CL__checkInputs(pos,3, vel,3);
// Check validity of inputs
[isvalid,orbit_type] = CL__oe_isValid("car",[pos;vel],mu);
if (~isvalid); CL__error("Invalid position velocity (zero norm or colinear)"); end;
if (find(orbit_type <> 1) <> []); CL__error("Invalid position velocity (parabolic or hyperbolic orbit)"); end;
// Semi major axis
r = CL_norm(pos);
V = CL_norm(vel);
W = CL_cross(pos,vel);
a = r ./ (2 - r .* V.^2/mu);
esinE = CL_dot(pos,vel) ./ sqrt(mu.*a);
// ecosE = r .* V.^2/mu - 1
// Inclination vector
[Wu, normW] = CL_unitVector(W);
ix = -Wu(2,:) ./ (2*sqrt((1+Wu(3,:))/2));
iy = Wu(1,:) ./ (2*sqrt((1+Wu(3,:))/2));
// Eccentricity vector
// Coordinates in the "natural frame"
// P = first column of matrix R
// Q = second column of matrix R
c = sqrt(1-ix.^2-iy.^2); // cos(i/2)
P = [(1-2*iy.^2); 2*ix.*iy; -2*iy.*c];
Q = [2*ix.*iy; (1-2*ix.^2); 2* ix .* c];
X = CL_dot(pos, P);
Y = CL_dot(pos, Q);
VX = CL_dot(vel, P);
VY = CL_dot(vel, Q);
ex = CL_norm(W) .* VY ./ mu - X ./ r;
ey = -CL_norm(W) .* VX ./ mu - Y ./ r;
// L = mean longitude
// LE = eccentric longitude
nu = 1 ./ (1 + sqrt(1 - ex.^2 - ey.^2));
cosLE = X ./ a + ex - esinE .* nu .* ey;
sinLE = Y ./ a + ey + esinE .* nu .* ex;
L = atan(sinLE,cosLE) - ex .* sinLE + ey .* cosLE;
// Reduce L to [0,2pi[
cireq = [a;ex;ey;ix;iy;CL_rMod(L,2*%pi)];
// Jacobian computation (dcireq/dcar)
if (argn(1) == 2)
// jacob(i,j) = d(cireq_i)/d(car_j)
jacob = zeros(6,6,N);
eta = sqrt(1-ex.^2-ey.^2);
nu = 1 ./ (1+eta);
n = sqrt(mu ./ a.^3);
na2 = sqrt(mu.*a);
// Partial derivatives of X,Y,VX,VY with respect to ex:
dXdex = ey ./ (n .* (1+eta)) .* VX + Y.*VX./(n.*a.*eta) - a;
dYdex = ey ./ (n .* (1+eta)) .* VY - X.*VX./(n.*a.*eta);
dVXdex = VX.*VY./(n.*a.*eta) - na2 ./ r.^3 .* (a.*ey./(1+eta).*X + X.*Y./eta);
dVYdex = -VX.*VX./(n.*a.*eta) - na2 ./ r.^3 .* (a.*ey./(1+eta).*Y - X.*X./eta);
// Partial derivatives of X,Y,VX,VY with respect to ey:
dXdey = -ex ./ (n .* (1+eta)) .* VX + Y.*VY./(n.*a.*eta);
dYdey = -ex ./ (n .* (1+eta)) .* VY - X.*VY./(n.*a.*eta) - a;
dVXdey = VY.*VY./(n.*a.*eta) + na2 ./ r.^3 .* (a.*ex./(1+eta).*X - Y.*Y./eta);
dVYdey = -VX.*VY./(n.*a.*eta) + na2 ./ r.^3 .* (a.*ex./(1+eta).*Y + X.*Y./eta);
// Partial derivatives of W(1,:), W(2,:) and W(3,:) with respect to (x,y,z) and (vx,vy,vz)
dW1dr = [ zeros(n) ; vel(3,:) ; -vel(2,:)];
dW2dr = [-vel(3,:) ; zeros(n) ; vel(1,:)];
dW3dr = [ vel(2,:) ; -vel(1,:); zeros(n)];
dW1dv = [ zeros(n) ; -pos(3,:); pos(2,:)];
dW2dv = [ pos(3,:) ; zeros(n) ; -pos(1,:)];
dW3dv = [-pos(2,:) ; pos(1,:) ; zeros(n)];
// Partial derivatives of the norm of W with respect to (x,y,z) and (vx,vy,vz)
dnormWdr = CL_dMult(CL_cross(vel, W), 1 ./ normW);
dnormWdv = -CL_dMult(CL_cross(pos, W), 1 ./ normW);
// Partial derivatives of Wu(1,:), Wu(2,:) and Wu(3,:) with respect to (x,y,z) and (vx,vy,vz)
dWu1dr = CL_dMult(dW1dr, 1 ./ normW) - CL_dMult(W(1,:) ./ normW.^2, dnormWdr);
dWu2dr = CL_dMult(dW2dr, 1 ./ normW) - CL_dMult(W(2,:) ./ normW.^2, dnormWdr);
dWu3dr = CL_dMult(dW3dr, 1 ./ normW) - CL_dMult(W(3,:) ./ normW.^2, dnormWdr);
dWu1dv = CL_dMult(dW1dv, 1 ./ normW) - CL_dMult(W(1,:) ./ normW.^2, dnormWdv);
dWu2dv = CL_dMult(dW2dv, 1 ./ normW) - CL_dMult(W(2,:) ./ normW.^2, dnormWdv);
dWu3dv = CL_dMult(dW3dv, 1 ./ normW) - CL_dMult(W(3,:) ./ normW.^2, dnormWdv);
for j = 1 : 3
// d(vx,vy,vz)/dex
dvdex = dVXdex .* P(j,:) + dVYdex .* Q(j,:);
// d(vx,vy,vz)/dey
dvdey = dVXdey .* P(j,:) + dVYdey .* Q(j,:);
// da/d(x,y,z) and da/d(vx,vy,vz)
dadr = 2 * a.^2 ./ r.^3 .* pos(j,:);
dadv = 2 ./ (n.^2 .* a) .* vel(j,:);
// dex/d(x,y,z) and dex/d(vx,vy,vz)
dexdr = -a.*nu.*ex.*eta./r.^3 .* pos(j,:) - ey.*(iy.*VX-ix.*VY)./(na2.*eta.*c) .* Wu(j,:) + eta./na2 .* dvdey;
dexdv = 1 ./ mu .* ((2*X.*VY - VX.*Y) .* Q(j,:) - Y.*VY.*P(j,:)) - ey.*(ix.*Y-iy.*X)./(na2.*eta.*c) .* Wu(j,:);
// dey/d(x,y,z) and dey/d(vx,vy,vz)
deydr = -a.*nu.*ey.*eta./r.^3 .* pos(j,:) + ex.*(iy.*VX-ix.*VY)./(na2.*eta.*c) .* Wu(j,:) - eta./na2 .* dvdex;
deydv = 1 ./ mu .* ((2*VX.*Y - X.*VY) .* P(j,:) - X.*VX.*Q(j,:)) + ex.*(ix.*Y-iy.*X)./(na2.*eta.*c) .* Wu(j,:);
// dix/d(x,y,z) and dix/d(vx,vy,vz)
d1 = 1 ./ (2*sqrt((1+Wu(3,:))/2));
dixdr = -Wu(2,:) .* (-dWu3dr(j,:) .* d1.^3) - dWu2dr(j,:) .* d1;
dixdv = -Wu(2,:) .* (-dWu3dv(j,:) .* d1.^3) - dWu2dv(j,:) .* d1;
// diy/d(x,y,z) and diy/d(vx,vy,vz)
diydr = Wu(1,:) .* (-dWu3dr(j,:) .* d1.^3) + dWu1dr(j,:) .* d1;
diydv = Wu(1,:) .* (-dWu3dv(j,:) .* d1.^3) + dWu1dv(j,:) .* d1;
// dL/d(x,y,z) and dL/d(vx,vy,vz)
dLdr = - vel(j,:) ./ na2 + (iy.*VX - ix.*VY) ./ (na2.*eta.*c) .* Wu(j,:) - nu.*eta./na2 .* (ey.*dvdey + ex.*dvdex);
dLdv = -2 ./ na2 .* pos(j,:) + nu .* (ex.*deydv - ey.*dexdv) + 1 ./ (na2.*c) .* (ix.*Y - iy.*X) .* Wu(j,:);
// Assign results to the output jacobian:
jacob(1,j,:) = dadr;
jacob(2,j,:) = dexdr;
jacob(3,j,:) = deydr;
jacob(4,j,:) = dixdr;
jacob(5,j,:) = diydr;
jacob(6,j,:) = dLdr;
jacob(1,j+3,:) = dadv;
jacob(2,j+3,:) = dexdv;
jacob(3,j+3,:) = deydv;
jacob(4,j+3,:) = dixdv;
jacob(5,j+3,:) = diydv;
jacob(6,j+3,:) = dLdv;
end
end
endfunction