1 // ------------------------------------------------------------------------ //
2 // This source file is part of the 'ESA Advanced Concepts Team's //
3 // Space Mechanics Toolbox' software. //
5 // The source files are for research use only, //
6 // and are distributed WITHOUT ANY WARRANTY. Use them on your own risk. //
8 // Copyright (c) 2004-2007 European Space Agency //
9 // ------------------------------------------------------------------------ //
11 // File: propageteKEP.cpp
16 #include "Astro_Functions.h"
17 #include "propagateKEP.h"
20 Origin: MATLAB code programmed by Dario Izzo (ESA/ACT)
22 C++ version by Tamas Vinko (ESA/ACT)
25 r0: column vector for the non dimensional position
26 v0: column vector for the non dimensional velocity
27 t: non dimensional time
30 r: column vector for the non dimensional position
31 v: column vector for the non dimensional velocity
33 Comments: The function works in non dimensional units, it takes an
34 initial condition and it propagates it as in a kepler motion analytically.
39 void propagateKEP(const double *r0_in
, const double *v0_in
, const double &t
, const double &mu
,
44 The matrix DD will be almost always the unit matrix, except for orbits
45 with little inclination in which cases a rotation is performed so that
46 par2IC is always defined
49 double DD
[9] = {1, 0, 0,
53 double ih
[3] = {0,0,0};
54 double temp1
[3] = {0,0,0}, temp2
[3] = {0,0,0};
74 if (fabs(fabs(ih
[2])-1.0) < 1e-3) // the abs is needed in cases in which the orbit is retrograde,
75 { // that would held ih=[0,0,-1]!!
76 DD
[0] = 1; DD
[1] = 0; DD
[2] = 0;
77 DD
[3] = 0; DD
[4] = 0; DD
[5] = 1;
78 DD
[6] = 0; DD
[7] = -1; DD
[8] = 0;
80 // Random rotation matrix that make the Euler angles well defined for the case
81 // For orbits with little inclination another ref. frame is used.
83 for (int i
=0; i
<3; i
++)
85 temp1
[0] += DD
[i
]*r0
[i
];
86 temp1
[1] += DD
[i
+3]*r0
[i
];
87 temp1
[2] += DD
[i
+6]*r0
[i
];
88 temp2
[0] += DD
[i
]*v0
[i
];
89 temp2
[1] += DD
[i
+3]*v0
[i
];
90 temp2
[2] += DD
[i
+6]*v0
[i
];
92 for (int i
=0; i
<3; i
++)
99 // for practical reason we take the transpose of the matrix DD here (will be used at the end of the function)
100 DD
[0] = 1; DD
[1] = 0; DD
[2] = 0;
101 DD
[3] = 0; DD
[4] = 0; DD
[5] = -1;
102 DD
[6] = 0; DD
[7] = 1; DD
[8] = 0;
105 IC2par(r0
, v0
, mu
, E
);
108 M0
= E
[5] - E
[1]*sin(E
[5]);
109 M
=M0
+sqrt(mu
/pow(E
[0],3))*t
;
113 M0
= E
[1]*tan(E
[5]) - log(tan(0.5*E
[5] + M_PI_4
));
114 M
=M0
+sqrt(mu
/pow(-E
[0],3))*t
;
117 E
[5]=Mean2Eccentric(M
, E
[1]);
121 for (int j
=0; j
<3; j
++)
123 temp1
[0] += DD
[j
]*r
[j
];
124 temp1
[1] += DD
[j
+3]*r
[j
];
125 temp1
[2] += DD
[j
+6]*r
[j
];
126 temp2
[0] += DD
[j
]*v
[j
];
127 temp2
[1] += DD
[j
+3]*v
[j
];
128 temp2
[2] += DD
[j
+6]*v
[j
];
130 for (int i
=0; i
<3; i
++)
143 Origin: MATLAB code programmed by Dario Izzo (ESA/ACT)
145 C++ version by Tamas Vinko (ESA/ACT) 12/09/2006
148 r0: column vector for the position
149 v0: column vector for the velocity
152 E: Column Vectors containing the six keplerian parameters,
153 (a,e,i,OM,om,Eccentric Anomaly (or Gudermannian whenever e>1))
155 Comments: The parameters returned are, of course, referred to the same
156 ref. frame in which r0,v0 are given. Units have to be consistent, and
157 output angles are in radians
158 The algorithm used is quite common and can be found as an example in Bate,
159 Mueller and White. It goes singular for zero inclination
162 void IC2par(const double *r0
, const double *v0
, const double &mu
, double *E
)
183 k
[0] = 0; k
[1] = 0; k
[2] = 1;
188 temp
+= pow(n
[i
], 2);
197 vett(v0
, h
, Dum_Vec
);
200 evett
[i
] = Dum_Vec
[i
]/mu
- r0
[i
]/R0
;
204 e
+= pow(evett
[i
], 2);
210 E
[2] = acos(h
[2]/norm2(h
));
218 if (evett
[2] < 0) E
[4] = 2*M_PI
- E
[4];
221 if (n
[1] < 0) E
[3] = 2*M_PI
-E
[3];
225 temp
+=evett
[i
]*r0
[i
];
227 ni
= acos(temp
/e
/R0
); // danger, the argument could be improper.
233 if (temp
<0.0) ni
= 2*M_PI
- ni
;
236 E
[5] = 2.0*atan(sqrt((1-e
)/(1+e
))*tan(ni
/2.0)); // algebraic kepler's equation
238 E
[5] =2.0*atan(sqrt((e
-1)/(e
+1))*tan(ni
/2.0)); // algebraic equivalent of kepler's equation in terms of the Gudermannian
242 Origin: MATLAB code programmed by Dario Izzo (ESA/ACT)
244 C++ version by Tamas Vinko (ESA/ACT)
246 Usage: [r0,v0] = IC2par(E,mu)
249 r0: column vector for the position
250 v0: column vector for the velocity
253 E: Column Vectors containing the six keplerian parameters,
254 (a (negative for hyperbolas),e,i,OM,om,Eccentric Anomaly)
255 mu: gravitational constant
257 Comments: The parameters returned are, of course, referred to the same
258 ref. frame in which r0,v0 are given. a can be given either in kms or AUs,
259 but has to be consistent with mu.All the angles must be given in radians.
260 This function does work for hyperbolas as well.
263 void par2IC(const double *E
, const double &mu
, double *r0
, double *v0
)
271 double b
, n
, xper
, yper
, xdotper
, ydotper
;
273 double cosomg
, cosomp
, sinomg
, sinomp
, cosi
, sini
;
276 // Grandezze definite nel piano dell'orbita
281 n
= sqrt(mu
/(a
*a
*a
));
285 xdotper
= -(a
*n
*sin(EA
))/(1-e
*cos(EA
));
286 ydotper
=(b
*n
*cos(EA
))/(1-e
*cos(EA
));
291 n
= sqrt(-mu
/(a
*a
*a
));
293 dNdZeta
= e
* (1+tan(EA
)*tan(EA
))-(0.5+0.5*pow(tan(0.5*EA
+ M_PI_4
),2))/tan(0.5*EA
+ M_PI_4
);
295 xper
= a
/cos(EA
) - a
*e
;
298 xdotper
= a
*tan(EA
)/cos(EA
)*n
/dNdZeta
;
299 ydotper
= b
/pow(cos(EA
), 2)*n
/dNdZeta
;
302 // Matrice di trasformazione da perifocale a ECI
312 R
[0][0]=cosomg
*cosomp
-sinomg
*sinomp
*cosi
;
313 R
[0][1]=-cosomg
*sinomp
-sinomg
*cosomp
*cosi
;
315 R
[1][0]=sinomg
*cosomp
+cosomg
*sinomp
*cosi
;
316 R
[1][1]=-sinomg
*sinomp
+cosomg
*cosomp
*cosi
;
317 R
[1][2]=-cosomg
*sini
;
322 // Posizione nel sistema inerziale
325 double temp
[3] = {xper
, yper
, 0.0};
326 double temp2
[3] = {xdotper
, ydotper
, 0};
328 for (int j
= 0; j
<3; j
++)
330 r0
[j
] = 0.0; v0
[j
] = 0.0;
331 for (int k
= 0; k
<3; k
++)
333 r0
[j
]+=R
[j
][k
]*temp
[k
];
334 v0
[j
]+=R
[j
][k
]*temp2
[k
];