1 | #include "slalib.h"
|
---|
2 | #include "slamac.h"
|
---|
3 | void slaPv2el ( double pv[], double date, double pmass, int jformr,
|
---|
4 | int *jform, double *epoch, double *orbinc,
|
---|
5 | double *anode, double *perih, double *aorq, double *e,
|
---|
6 | double *aorl, double *dm, int *jstat )
|
---|
7 | /*
|
---|
8 | ** - - - - - - - - -
|
---|
9 | ** s l a P v 2 e l
|
---|
10 | ** - - - - - - - - -
|
---|
11 | **
|
---|
12 | ** Heliocentric osculating elements obtained from instantaneous position
|
---|
13 | ** and velocity.
|
---|
14 | **
|
---|
15 | ** Given:
|
---|
16 | ** pv double[6] heliocentric x,y,z,xdot,ydot,zdot of date,
|
---|
17 | ** J2000 equatorial triad (AU,AU/s; Note 1)
|
---|
18 | ** date double date (TT Modified Julian Date = JD-2400000.5)
|
---|
19 | ** pmass double mass of the planet (Sun=1; Note 2)
|
---|
20 | ** jformr int requested element set (1-3; Note 3)
|
---|
21 | **
|
---|
22 | ** Returned:
|
---|
23 | ** jform double* element set actually returned (1-3; Note 4)
|
---|
24 | ** epoch double* epoch of elements (TT MJD)
|
---|
25 | ** orbinc double* inclination (radians)
|
---|
26 | ** anode double* longitude of the ascending node (radians)
|
---|
27 | ** perih double* longitude or argument of perihelion (radians)
|
---|
28 | ** aorq double* mean distance or perihelion distance (AU)
|
---|
29 | ** e double* eccentricity
|
---|
30 | ** aorl double* mean anomaly or longitude (radians, jform=1,2 only)
|
---|
31 | ** dm double* daily motion (radians, jform=1 only)
|
---|
32 | ** jstat int* status: 0 = OK
|
---|
33 | ** -1 = illegal pmass
|
---|
34 | ** -2 = illegal jformr
|
---|
35 | ** -3 = position/velocity out of range
|
---|
36 | **
|
---|
37 | ** Notes
|
---|
38 | **
|
---|
39 | ** 1 The pv 6-vector is with respect to the mean equator and equinox of
|
---|
40 | ** epoch J2000. The orbital elements produced are with respect to
|
---|
41 | ** the J2000 ecliptic and mean equinox.
|
---|
42 | **
|
---|
43 | ** 2 The mass, pmass, is important only for the larger planets. For
|
---|
44 | ** most purposes (e.g. asteroids) use 0.0. Values less than zero
|
---|
45 | ** are illegal.
|
---|
46 | **
|
---|
47 | ** 3 Three different element-format options are supported:
|
---|
48 | **
|
---|
49 | ** Option jformr=1, suitable for the major planets:
|
---|
50 | **
|
---|
51 | ** epoch = epoch of elements (TT MJD)
|
---|
52 | ** orbinc = inclination i (radians)
|
---|
53 | ** anode = longitude of the ascending node, big omega (radians)
|
---|
54 | ** perih = longitude of perihelion, curly pi (radians)
|
---|
55 | ** aorq = mean distance, a (AU)
|
---|
56 | ** e = eccentricity, e
|
---|
57 | ** aorl = mean longitude L (radians)
|
---|
58 | ** dm = daily motion (radians)
|
---|
59 | **
|
---|
60 | ** Option jformr=2, suitable for minor planets:
|
---|
61 | **
|
---|
62 | ** epoch = epoch of elements (TT MJD)
|
---|
63 | ** orbinc = inclination i (radians)
|
---|
64 | ** anode = longitude of the ascending node, big omega (radians)
|
---|
65 | ** perih = argument of perihelion, little omega (radians)
|
---|
66 | ** aorq = mean distance, a (AU)
|
---|
67 | ** e = eccentricity, e
|
---|
68 | ** aorl = mean anomaly M (radians)
|
---|
69 | **
|
---|
70 | ** Option jformr=3, suitable for comets:
|
---|
71 | **
|
---|
72 | ** epoch = epoch of perihelion (TT MJD)
|
---|
73 | ** orbinc = inclination i (radians)
|
---|
74 | ** anode = longitude of the ascending node, big omega (radians)
|
---|
75 | ** perih = argument of perihelion, little omega (radians)
|
---|
76 | ** aorq = perihelion distance, q (AU)
|
---|
77 | ** e = eccentricity, e
|
---|
78 | **
|
---|
79 | ** 4 It may not be possible to generate elements in the form
|
---|
80 | ** requested through jformr. The caller is notified of the form
|
---|
81 | ** of elements actually returned by means of the jform argument:
|
---|
82 | **
|
---|
83 | ** jformr jform meaning
|
---|
84 | **
|
---|
85 | ** 1 1 OK - elements are in the requested format
|
---|
86 | ** 1 2 never happens
|
---|
87 | ** 1 3 orbit not elliptical
|
---|
88 | **
|
---|
89 | ** 2 1 never happens
|
---|
90 | ** 2 2 OK - elements are in the requested format
|
---|
91 | ** 2 3 orbit not elliptical
|
---|
92 | **
|
---|
93 | ** 3 1 never happens
|
---|
94 | ** 3 2 never happens
|
---|
95 | ** 3 3 OK - elements are in the requested format
|
---|
96 | **
|
---|
97 | ** 5 The arguments returned for each value of jform (cf Note 5: jform
|
---|
98 | ** may not be the same as jformr) are as follows:
|
---|
99 | **
|
---|
100 | ** jform 1 2 3
|
---|
101 | ** epoch t0 t0 T
|
---|
102 | ** orbinc i i i
|
---|
103 | ** anode Omega Omega Omega
|
---|
104 | ** perih curly pi omega omega
|
---|
105 | ** aorq a a q
|
---|
106 | ** e e e e
|
---|
107 | ** aorl L M -
|
---|
108 | ** dm n - -
|
---|
109 | **
|
---|
110 | ** where:
|
---|
111 | **
|
---|
112 | ** t0 is the epoch of the elements (MJD, TT)
|
---|
113 | ** T " epoch of perihelion (MJD, TT)
|
---|
114 | ** i " inclination (radians)
|
---|
115 | ** Omega " longitude of the ascending node (radians)
|
---|
116 | ** curly pi " longitude of perihelion (radians)
|
---|
117 | ** omega " argument of perihelion (radians)
|
---|
118 | ** a " mean distance (AU)
|
---|
119 | ** q " perihelion distance (AU)
|
---|
120 | ** e " eccentricity
|
---|
121 | ** L " longitude (radians, 0-2pi)
|
---|
122 | ** M " mean anomaly (radians, 0-2pi)
|
---|
123 | ** n " daily motion (radians)
|
---|
124 | ** - means no value is set
|
---|
125 | **
|
---|
126 | ** 6 At very small inclinations, the longitude of the ascending node
|
---|
127 | ** anode becomes indeterminate and under some circumstances may be
|
---|
128 | ** set arbitrarily to zero. Similarly, if the orbit is close to
|
---|
129 | ** circular, the true anomaly becomes indeterminate and under some
|
---|
130 | ** circumstances may be set arbitrarily to zero. In such cases,
|
---|
131 | ** the other elements are automatically adjusted to compensate,
|
---|
132 | ** and so the elements remain a valid description of the orbit.
|
---|
133 | **
|
---|
134 | ** Reference: Sterne, Theodore E., "An Introduction to Celestial
|
---|
135 | ** Mechanics", Interscience Publishers, 1960
|
---|
136 | **
|
---|
137 | ** Called: slaDranrm
|
---|
138 | **
|
---|
139 | ** Last revision: 21 February 1999
|
---|
140 | **
|
---|
141 | ** Copyright P.T.Wallace. All rights reserved.
|
---|
142 | */
|
---|
143 |
|
---|
144 | /* Seconds to days */
|
---|
145 | #define DAY 86400.0
|
---|
146 |
|
---|
147 | /* Gaussian gravitational constant (exact) */
|
---|
148 | #define GCON 0.01720209895
|
---|
149 |
|
---|
150 | /* Sin and cos of J2000 mean obliquity (IAU 1976) */
|
---|
151 | #define SE 0.3977771559319137
|
---|
152 | #define CE 0.9174820620691818
|
---|
153 |
|
---|
154 | /* Minimum allowed distance (AU) and speed (AU/day) */
|
---|
155 | #define RMIN 1e-3
|
---|
156 | #define VMIN 1e-8
|
---|
157 |
|
---|
158 | /* How close to unity the eccentricity has to be to call it a parabola */
|
---|
159 | #define PARAB 1e-8
|
---|
160 |
|
---|
161 | {
|
---|
162 | double x, y, z, xd, yd, zd, r, v2, v, rdv, gmu, hx, hy, hz,
|
---|
163 | hx2py2, h2, h, oi, bigom, ar, e2, ecc, s, c, at, u, om,
|
---|
164 | gar3, em1, ep1, hat, shat, chat, ae, am, dn, pl,
|
---|
165 | el, q, tp, that, thhf, f;
|
---|
166 | int jf;
|
---|
167 |
|
---|
168 |
|
---|
169 | /* Validate arguments pmass and jformr. */
|
---|
170 | if ( pmass < 0.0 ) {
|
---|
171 | *jstat = -1;
|
---|
172 | return;
|
---|
173 | }
|
---|
174 | if ( jformr < 1 || jformr > 3 ) {
|
---|
175 | *jstat = -2;
|
---|
176 | return;
|
---|
177 | }
|
---|
178 |
|
---|
179 | /* Provisionally assume the elements will be in the chosen form. */
|
---|
180 | jf = jformr;
|
---|
181 |
|
---|
182 | /* Rotate the position from equatorial to ecliptic coordinates. */
|
---|
183 | x = pv [ 0 ];
|
---|
184 | y = pv [ 1 ] * CE + pv [ 2 ] * SE;
|
---|
185 | z = - pv [ 1 ] * SE + pv [ 2 ] * CE;
|
---|
186 |
|
---|
187 | /* Rotate the velocity similarly, scaling to AU/day. */
|
---|
188 | xd = DAY * pv [ 3 ];
|
---|
189 | yd = DAY * ( pv [ 4 ] * CE + pv [ 5 ] * SE );
|
---|
190 | zd = DAY * ( - pv [ 4 ] * SE + pv [ 5 ] * CE );
|
---|
191 |
|
---|
192 | /* Distance and speed. */
|
---|
193 | r = sqrt ( x * x + y * y + z * z );
|
---|
194 | v2 = xd * xd + yd * yd + zd * zd;
|
---|
195 | v = sqrt ( v2 );
|
---|
196 |
|
---|
197 | /* Reject unreasonably small values. */
|
---|
198 | if ( r < RMIN || v < VMIN ) {
|
---|
199 | *jstat = -3;
|
---|
200 | return;
|
---|
201 | }
|
---|
202 |
|
---|
203 | /* R dot V. */
|
---|
204 | rdv = x * xd + y * yd + z * zd;
|
---|
205 |
|
---|
206 | /* Mu. */
|
---|
207 | gmu = ( 1.0 + pmass ) * GCON * GCON;
|
---|
208 |
|
---|
209 | /* Vector angular momentum per unit reduced mass. */
|
---|
210 | hx = y * zd - z * yd;
|
---|
211 | hy = z * xd - x * zd;
|
---|
212 | hz = x * yd - y * xd;
|
---|
213 |
|
---|
214 | /* Areal constant. */
|
---|
215 | hx2py2 = hx * hx + hy * hy;
|
---|
216 | h2 = hx2py2 + hz * hz;
|
---|
217 | h = sqrt ( h2 );
|
---|
218 |
|
---|
219 | /* Inclination. */
|
---|
220 | oi = atan2 ( sqrt ( hx2py2 ), hz );
|
---|
221 |
|
---|
222 | /* Longitude of ascending node. */
|
---|
223 | if ( hx != 0.0 || hy != 0.0 ) {
|
---|
224 | bigom = atan2 ( hx, -hy );
|
---|
225 | } else {
|
---|
226 | bigom = 0.0;
|
---|
227 | }
|
---|
228 |
|
---|
229 | /* Reciprocal of mean distance etc. */
|
---|
230 | ar = 2.0 / r - v2 / gmu;
|
---|
231 |
|
---|
232 | /* Eccentricity. */
|
---|
233 | e2 = 1.0 - ar * h2 / gmu;
|
---|
234 | ecc = ( e2 >= 0.0 ) ? sqrt ( e2 ) : 0.0;
|
---|
235 |
|
---|
236 | /* True anomaly. */
|
---|
237 | s = h * rdv;
|
---|
238 | c = h2 - r * gmu;
|
---|
239 | if ( s != 0.0 && c != 0.0 ) {
|
---|
240 | at = atan2 ( s, c );
|
---|
241 | } else {
|
---|
242 | at = 0.0;
|
---|
243 | }
|
---|
244 |
|
---|
245 | /* Argument of the latitude. */
|
---|
246 | s = sin ( bigom );
|
---|
247 | c = cos ( bigom );
|
---|
248 | u = atan2 ( ( - x * s + y * c ) * cos ( oi ) + z * sin ( oi ),
|
---|
249 | x * c + y * s );
|
---|
250 |
|
---|
251 | /* Argument of perihelion. */
|
---|
252 | om = u - at;
|
---|
253 |
|
---|
254 | /* Capture near-parabolic cases. */
|
---|
255 | if ( fabs ( ecc - 1.0 ) < PARAB ) ecc = 1.0;
|
---|
256 |
|
---|
257 | /* Comply with jformr = 1 or 2 only if orbit is elliptical. */
|
---|
258 | if ( ecc >= 1.0 ) jf = 3;
|
---|
259 |
|
---|
260 | /* Functions. */
|
---|
261 | gar3 = gmu * ar * ar * ar;
|
---|
262 | em1 = ecc - 1.0;
|
---|
263 | ep1 = ecc + 1.0;
|
---|
264 | hat = at / 2.0;
|
---|
265 | shat = sin ( hat );
|
---|
266 | chat = cos ( hat );
|
---|
267 |
|
---|
268 | /* Ellipse? */
|
---|
269 | if ( ecc < 1.0 ) {
|
---|
270 |
|
---|
271 | /* Eccentric anomaly. */
|
---|
272 | ae = 2.0 * atan2 ( sqrt ( -em1 ) * shat, sqrt ( ep1 ) * chat );
|
---|
273 |
|
---|
274 | /* Mean anomaly. */
|
---|
275 | am = ae - ecc * sin ( ae );
|
---|
276 |
|
---|
277 | /* Daily motion. */
|
---|
278 | dn = sqrt ( gar3 );
|
---|
279 | }
|
---|
280 |
|
---|
281 | /* "Major planet" element set? */
|
---|
282 | if ( jf == 1 ) {
|
---|
283 |
|
---|
284 | /* Longitude of perihelion. */
|
---|
285 | pl = bigom + om;
|
---|
286 |
|
---|
287 | /* Longitude at epoch. */
|
---|
288 | el = pl + am;
|
---|
289 | }
|
---|
290 |
|
---|
291 | /* "Comet" element set? */
|
---|
292 | if ( jf == 3 ) {
|
---|
293 |
|
---|
294 | /* Perihelion distance. */
|
---|
295 | q = h2 / ( gmu * ep1 );
|
---|
296 |
|
---|
297 | /* Ellipse, parabola, hyperbola? */
|
---|
298 | if ( ecc < 1.0 ) {
|
---|
299 |
|
---|
300 | /* Ellipse: epoch of perihelion. */
|
---|
301 | tp = date - am / dn;
|
---|
302 | } else {
|
---|
303 |
|
---|
304 | /* Parabola or hyperbola: evaluate tan ( ( true anomaly ) / 2 ) */
|
---|
305 | that = shat / chat;
|
---|
306 | if ( ecc == 1.0 ) {
|
---|
307 |
|
---|
308 | /* Parabola: epoch of perihelion. */
|
---|
309 | tp = date - that * ( 1.0 + that * that / 3.0 ) * h * h2 /
|
---|
310 | ( 2.0 * gmu * gmu );
|
---|
311 | } else {
|
---|
312 |
|
---|
313 | /* Hyperbola: epoch of perihelion. */
|
---|
314 | thhf = sqrt ( em1 / ep1 ) * that;
|
---|
315 | f = log ( 1.0 + thhf ) - log ( 1.0 - thhf );
|
---|
316 | tp = date - ( ecc * sinh ( f ) - f ) / sqrt ( - gar3 );
|
---|
317 | }
|
---|
318 | }
|
---|
319 | }
|
---|
320 |
|
---|
321 | /* Return the appropriate set of elements. */
|
---|
322 | *jform = jf;
|
---|
323 | *orbinc = oi;
|
---|
324 | *anode = slaDranrm ( bigom );
|
---|
325 | *e = ecc;
|
---|
326 | if ( jf == 1 ) {
|
---|
327 | *perih = slaDranrm ( pl );
|
---|
328 | *aorl = slaDranrm ( el );
|
---|
329 | *dm = dn;
|
---|
330 | } else {
|
---|
331 | *perih = slaDranrm ( om );
|
---|
332 | if ( jf == 2 ) *aorl = slaDranrm ( am );
|
---|
333 | }
|
---|
334 | if ( jf != 3 ) {
|
---|
335 | *epoch = date;
|
---|
336 | *aorq = 1.0 / ar;
|
---|
337 | } else {
|
---|
338 | *epoch = tp;
|
---|
339 | *aorq = q;
|
---|
340 | }
|
---|
341 | *jstat = 0;
|
---|
342 |
|
---|
343 | }
|
---|