001    /*
002     * This file is part of McIDAS-V
003     *
004     * Copyright 2007-2013
005     * Space Science and Engineering Center (SSEC)
006     * University of Wisconsin - Madison
007     * 1225 W. Dayton Street, Madison, WI 53706, USA
008     * https://www.ssec.wisc.edu/mcidas
009     * 
010     * All Rights Reserved
011     * 
012     * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013     * some McIDAS-V source code is based on IDV and VisAD source code.  
014     * 
015     * McIDAS-V is free software; you can redistribute it and/or modify
016     * it under the terms of the GNU Lesser Public License as published by
017     * the Free Software Foundation; either version 3 of the License, or
018     * (at your option) any later version.
019     * 
020     * McIDAS-V is distributed in the hope that it will be useful,
021     * but WITHOUT ANY WARRANTY; without even the implied warranty of
022     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023     * GNU Lesser Public License for more details.
024     * 
025     * You should have received a copy of the GNU Lesser Public License
026     * along with this program.  If not, see http://www.gnu.org/licenses.
027     */
028    /**
029     *   Vallado/CSSI SGP4 propogator
030     *   Converted to Java from C++ by: Shawn E. Gano, 19 June 2009
031     *   The goal of this conversion was to stick as closely to the orginal code
032     *   as possible and not trying to convert it to OO design.
033     *   This code has been compared using the verification TLEs and "SGP4verification.java"
034     *   and the results were virtually identical to the c++ version.
035     *   Only rare differences were found in the results on the order of 0.001 cm.
036     * ----------------------------------------------------------------
037     *
038     *                               sgp4unit.cpp
039     *
040     *    this file contains the sgp4 procedures for analytical propagation
041     *    of a satellite. the code was originally released in the 1980 and 1986
042     *    spacetrack papers. a detailed discussion of the theory and history
043     *    may be found in the 2006 aiaa paper by vallado, crawford, hujsak,
044     *    and kelso.
045     *
046     *                            companion code for
047     *               fundamentals of astrodynamics and applications
048     *                                    2007
049     *                              by david vallado
050     *
051     *       (w) 719-573-2600, email dvallado@agi.com
052     *
053     *    current :
054     *               3 Nov 08  david vallado
055     *                           put returns in for error codes
056     *    changes :
057     *              29 sep 08  david vallado
058     *                           fix atime for faster operation in dspace
059     *                           add operationmode for afspc (a) or improved (i)
060     *                           performance mode
061     *              16 jun 08  david vallado
062     *                           update small eccentricity check
063     *              16 nov 07  david vallado
064     *                           misc fixes for better compliance
065     *              20 apr 07  david vallado
066     *                           misc fixes for constants
067     *              11 aug 06  david vallado
068     *                           chg lyddane choice back to strn3, constants, misc doc
069     *              15 dec 05  david vallado
070     *                           misc fixes
071     *              26 jul 05  david vallado
072     *                           fixes for paper
073     *                           note that each fix is preceded by a
074     *                           comment with "sgp4fix" and an explanation of
075     *                           what was changed
076     *              10 aug 04  david vallado
077     *                           2nd printing baseline working
078     *              14 may 01  david vallado
079     *                           2nd edition baseline
080     *                     80  norad
081     *                           original baseline
082     *       ----------------------------------------------------------------      */
083    
084    package edu.wisc.ssec.mcidasv.data.adde.sgp4;
085    
086    /**
087     *
088     * @author Shawn E. Gano, shawn@gano.name
089     */
090    public class SGP4unit
091    {
092        public static double pi = 3.14159265358979323846;
093    
094        public static enum Gravconsttype
095        {
096            wgs72old,
097            wgs72,
098            wgs84
099        }
100    
101        /** -----------------------------------------------------------------------------
102         * Java version outputs double array: [ep,inclp,nodep,argpp,mp]
103         * -------------------------------------------------------------------------------
104         *
105         *                           procedure dpper
106         *
107         *  this procedure provides deep space long period periodic contributions
108         *    to the mean elements.  by design, these periodics are zero at epoch.
109         *    this used to be dscom which included initialization, but it's really a
110         *    recurring function.
111         *
112         *  author        : david vallado                  719-573-2600   28 jun 2005
113         *
114         *  inputs        :
115         *    e3          -
116         *    ee2         -
117         *    peo         -
118         *    pgho        -
119         *    pho         -
120         *    pinco       -
121         *    plo         -
122         *    se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 -
123         *    t           -
124         *    xh2, xh3, xi2, xi3, xl2, xl3, xl4 -
125         *    zmol        -
126         *    zmos        -
127         *    ep          - eccentricity                           0.0 - 1.0
128         *    inclo       - inclination - needed for lyddane modification
129         *    nodep       - right ascension of ascending node
130         *    argpp       - argument of perigee
131         *    mp          - mean anomaly
132         *
133         *  outputs       :
134         *    ep          - eccentricity                           0.0 - 1.0
135         *    inclp       - inclination
136         *    nodep        - right ascension of ascending node
137         *    argpp       - argument of perigee
138         *    mp          - mean anomaly
139         *
140         *  locals        :
141         *    alfdp       -
142         *    betdp       -
143         *    cosip  , sinip  , cosop  , sinop  ,
144         *    dalf        -
145         *    dbet        -
146         *    dls         -
147         *    f2, f3      -
148         *    pe          -
149         *    pgh         -
150         *    ph          -
151         *    pinc        -
152         *    pl          -
153         *    sel   , ses   , sghl  , sghs  , shl   , shs   , sil   , sinzf , sis   ,
154         *    sll   , sls
155         *    xls         -
156         *    xnoh        -
157         *    zf          -
158         *    zm          -
159         *
160         *  coupling      :
161         *    none.
162         *
163         *  references    :
164         *    hoots, roehrich, norad spacetrack report #3 1980
165         *    hoots, norad spacetrack report #6 1986
166         *    hoots, schumacher and glover 2004
167         *    vallado, crawford, hujsak, kelso  2006
168        ----------------------------------------------------------------------------*/
169    // outputs an array with values for, all outputs are also inputs
170    // [ep,inclp,nodep,argpp,mp]
171        private static double[] dpper(
172                double e3, double ee2, double peo, double pgho, double pho,
173                double pinco, double plo, double se2, double se3, double sgh2,
174                double sgh3, double sgh4, double sh2, double sh3, double si2,
175                double si3, double sl2, double sl3, double sl4, double t,
176                double xgh2, double xgh3, double xgh4, double xh2, double xh3,
177                double xi2, double xi3, double xl2, double xl3, double xl4,
178                double zmol, double zmos, double inclo,
179                char init,
180                double ep, double inclp, double nodep, double argpp, double mp,
181                char opsmode)
182        {
183            // return variables -- all also inputs
184            //double inclp,nodep,argpp,mp; // ep -- input and output
185    
186            /* --------------------- local variables ------------------------ */
187            final double twopi = 2.0 * pi;
188            double alfdp, betdp, cosip, cosop, dalf, dbet, dls,
189                    f2, f3, pe, pgh, ph, pinc, pl,
190                    sel, ses, sghl, sghs, shll, shs, sil,
191                    sinip, sinop, sinzf, sis, sll, sls, xls,
192                    xnoh, zf, zm, zel, zes, znl, zns;
193    
194            /* ---------------------- constants ----------------------------- */
195            zns = 1.19459e-5;
196            zes = 0.01675;
197            znl = 1.5835218e-4;
198            zel = 0.05490;
199    
200            /* --------------- calculate time varying periodics ----------- */
201            zm = zmos + zns * t;
202            // be sure that the initial call has time set to zero
203            if(init == 'y')
204            {
205                zm = zmos;
206            }
207            zf = zm + 2.0 * zes * Math.sin(zm);
208            sinzf = Math.sin(zf);
209            f2 = 0.5 * sinzf * sinzf - 0.25;
210            f3 = -0.5 * sinzf * Math.cos(zf);
211            ses = se2 * f2 + se3 * f3;
212            sis = si2 * f2 + si3 * f3;
213            sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf;
214            sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf;
215            shs = sh2 * f2 + sh3 * f3;
216            zm = zmol + znl * t;
217            if(init == 'y')
218            {
219                zm = zmol;
220            }
221            zf = zm + 2.0 * zel * Math.sin(zm);
222            sinzf = Math.sin(zf);
223            f2 = 0.5 * sinzf * sinzf - 0.25;
224            f3 = -0.5 * sinzf * Math.cos(zf);
225            sel = ee2 * f2 + e3 * f3;
226            sil = xi2 * f2 + xi3 * f3;
227            sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf;
228            sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf;
229            shll = xh2 * f2 + xh3 * f3;
230            pe = ses + sel;
231            pinc = sis + sil;
232            pl = sls + sll;
233            pgh = sghs + sghl;
234            ph = shs + shll;
235    
236            if(init == 'n')
237            {
238                pe = pe - peo;
239                pinc = pinc - pinco;
240                pl = pl - plo;
241                pgh = pgh - pgho;
242                ph = ph - pho;
243                inclp = inclp + pinc;
244                ep = ep + pe;
245                sinip = Math.sin(inclp);
246                cosip = Math.cos(inclp);
247    
248                /* ----------------- apply periodics directly ------------ */
249                //  sgp4fix for lyddane choice
250                //  strn3 used original inclination - this is technically feasible
251                //  gsfc used perturbed inclination - also technically feasible
252                //  probably best to readjust the 0.2 limit value and limit discontinuity
253                //  0.2 rad = 11.45916 deg
254                //  use next line for original strn3 approach and original inclination
255                //  if (inclo >= 0.2)
256                //  use next line for gsfc version and perturbed inclination
257                if(inclp >= 0.2)
258                {
259                    ph = ph / sinip;
260                    pgh = pgh - cosip * ph;
261                    argpp = argpp + pgh;
262                    nodep = nodep + ph;
263                    mp = mp + pl;
264                }
265                else
266                {
267                    /* ---- apply periodics with lyddane modification ---- */
268                    sinop = Math.sin(nodep);
269                    cosop = Math.cos(nodep);
270                    alfdp = sinip * sinop;
271                    betdp = sinip * cosop;
272                    dalf = ph * cosop + pinc * cosip * sinop;
273                    dbet = -ph * sinop + pinc * cosip * cosop;
274                    alfdp = alfdp + dalf;
275                    betdp = betdp + dbet;
276                    nodep = (nodep % twopi);
277                    //  sgp4fix for afspc written intrinsic functions
278                    // nodep used without a trigonometric function ahead
279                    if((nodep < 0.0) && (opsmode == 'a'))
280                    {
281                        nodep = nodep + twopi;
282                    }
283                    xls = mp + argpp + cosip * nodep;
284                    dls = pl + pgh - pinc * nodep * sinip;
285                    xls = xls + dls;
286                    xnoh = nodep;
287                    nodep = Math.atan2(alfdp, betdp);
288                    //  sgp4fix for afspc written intrinsic functions
289                    // nodep used without a trigonometric function ahead
290                    if((nodep < 0.0) && (opsmode == 'a'))
291                    {
292                        nodep = nodep + twopi;
293                    }
294                    if(Math.abs(xnoh - nodep) > pi)
295                    {
296                        if(nodep < xnoh)
297                        {
298                            nodep = nodep + twopi;
299                        }
300                        else
301                        {
302                            nodep = nodep - twopi;
303                        }
304                    }
305                    mp = mp + pl;
306                    argpp = xls - mp - cosip * nodep;
307                }
308            }   // if init == 'n'
309    
310            return new double[]
311                    {
312                        ep, inclp, nodep, argpp, mp
313                    };
314    //#include "debug1.cpp"
315        }  // end dpper
316    
317        /*-----------------------------------------------------------------------------
318         *
319         *                           procedure dscom
320         *
321         *  this procedure provides deep space common items used by both the secular
322         *    and periodics subroutines.  input is provided as shown. this routine
323         *    used to be called dpper, but the functions inside weren't well organized.
324         *
325         *  author        : david vallado                  719-573-2600   28 jun 2005
326         *
327         *  inputs        :
328         *    epoch       -
329         *    ep          - eccentricity
330         *    argpp       - argument of perigee
331         *    tc          -
332         *    inclp       - inclination
333         *    nodep       - right ascension of ascending node
334         *    np          - mean motion
335         *
336         *  outputs       :
337         *    sinim  , cosim  , sinomm , cosomm , snodm  , cnodm
338         *    day         -
339         *    e3          -
340         *    ee2         -
341         *    em          - eccentricity
342         *    emsq        - eccentricity squared
343         *    gam         -
344         *    peo         -
345         *    pgho        -
346         *    pho         -
347         *    pinco       -
348         *    plo         -
349         *    rtemsq      -
350         *    se2, se3         -
351         *    sgh2, sgh3, sgh4        -
352         *    sh2, sh3, si2, si3, sl2, sl3, sl4         -
353         *    s1, s2, s3, s4, s5, s6, s7          -
354         *    ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3         -
355         *    sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33        -
356         *    xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4         -
357         *    nm          - mean motion
358         *    z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33         -
359         *    zmol        -
360         *    zmos        -
361         *
362         *  locals        :
363         *    a1, a2, a3, a4, a5, a6, a7, a8, a9, a10         -
364         *    betasq      -
365         *    cc          -
366         *    ctem, stem        -
367         *    x1, x2, x3, x4, x5, x6, x7, x8          -
368         *    xnodce      -
369         *    xnoi        -
370         *    zcosg  , zsing  , zcosgl , zsingl , zcosh  , zsinh  , zcoshl , zsinhl ,
371         *    zcosi  , zsini  , zcosil , zsinil ,
372         *    zx          -
373         *    zy          -
374         *
375         *  coupling      :
376         *    none.
377         *
378         *  references    :
379         *    hoots, roehrich, norad spacetrack report #3 1980
380         *    hoots, norad spacetrack report #6 1986
381         *    hoots, schumacher and glover 2004
382         *    vallado, crawford, hujsak, kelso  2006
383         *  ----------------------------------------------------------------------------
384         * constructor modified to return an array with all the values that are not contained in the SGP4SatData object
385         * Array returned with these values:
386         * [snodm, cnodm, sinim, cosim, sinomm, cosomm, day, em, emsq, gam, rtemsq, s1, s2, s3,
387         *  s4, s5, s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, sz11, sz12, sz13,
388         * sz21, sz22, sz23, sz31, sz32, sz33, nm, z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33 ]
389         * --------------------------------------------------------------*/
390        private static double[] dscom(
391                // inputs
392                double epoch, double ep, double argpp, double tc, double inclp,
393                double nodep, double np,
394                SGP4SatData satrec //       // not
395                //       double& snodm, double& cnodm, double& sinim,  double& cosim, double& sinomm,
396                //       double& cosomm,double& day,
397                //       //SGP4SatData
398                //       double& e3,     double& ee2,
399                //       // not
400                //       double& em, double& emsq,  double& gam,
401                //       // SGP4SatData
402                //       double& peo,   double& pgho,  double& pho,
403                //       double& pinco, double& plo,
404                //       // not
405                //       double& rtemsq,
406                //       // SGP4SatData
407                //       double& se2,   double& se3,
408                //       double& sgh2,  double& sgh3,  double& sgh4,   double& sh2,   double& sh3,
409                //       double& si2,   double& si3,   double& sl2,    double& sl3,   double& sl4,
410                //       // not
411                //       double& s1,    double& s2,    double& s3,     double& s4,    double& s5,
412                //       double& s6,    double& s7,    double& ss1,    double& ss2,   double& ss3,
413                //       double& ss4,   double& ss5,   double& ss6,    double& ss7,   double& sz1,
414                //       double& sz2,   double& sz3,   double& sz11,   double& sz12,  double& sz13,
415                //       double& sz21,  double& sz22,  double& sz23,   double& sz31,  double& sz32,
416                //       double& sz33,
417                //       // SGP4SatData
418                //       double& xgh2,  double& xgh3,   double& xgh4,  double& xh2,
419                //       double& xh3,   double& xi2,   double& xi3,    double& xl2,   double& xl3,
420                //       double& xl4,
421                //       // not
422                //       double& nm,    double& z1,     double& z2,    double& z3,
423                //       double& z11,   double& z12,   double& z13,    double& z21,   double& z22,
424                //       double& z23,   double& z31,   double& z32,    double& z33,
425                //       // SGP4SatData
426                //       double& zmol, double& zmos
427                )
428        {
429            // Return variables not in SGP4SatData ----------------------------
430            double snodm, cnodm, sinim, cosim, sinomm, cosomm, day, em, emsq, gam, rtemsq,
431                    s1, s2, s3, s4, s5, s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7,
432                    sz1, sz2, sz3, sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33,
433                    nm, z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33;
434    
435            // SEG : it is okay to initalize these here as they are not assigned before this function is called
436            s1 = 0;
437            s2 = 0;
438            s3 = 0;
439            s4 = 0;
440            s5 = 0;
441            s6 = 0;
442            s7 = 0;
443            ss1 = 0;
444            ss2 = 0;
445            ss3 = 0;
446            ss4 = 0;
447            ss5 = 0;
448            ss6 = 0;
449            ss7 = 0;
450            sz1 = 0;
451            sz2 = 0;
452            sz3 = 0;
453            sz11 = 0;
454            sz12 = 0;
455            sz13 = 0;
456            sz21 = 0;
457            sz22 = 0;
458            sz23 = 0;
459            sz31 = 0;
460            sz32 = 0;
461            sz33 = 0;
462            z1 = 0;
463            z2 = 0;
464            z3 = 0;
465            z11 = 0;
466            z12 = 0;
467            z13 = 0;
468            z21 = 0;
469            z22 = 0;
470            z23 = 0;
471            z31 = 0;
472            z32 = 0;
473            z33 = 0;
474    
475            /* -------------------------- constants ------------------------- */
476            final double zes = 0.01675;
477            final double zel = 0.05490;
478            final double c1ss = 2.9864797e-6;
479            final double c1l = 4.7968065e-7;
480            final double zsinis = 0.39785416;
481            final double zcosis = 0.91744867;
482            final double zcosgs = 0.1945905;
483            final double zsings = -0.98088458;
484            final double twopi = 2.0 * pi;
485    
486            /* --------------------- local variables ------------------------ */
487            int lsflg;
488            double a1, a2, a3, a4, a5, a6, a7,
489                    a8, a9, a10, betasq, cc, ctem, stem,
490                    x1, x2, x3, x4, x5, x6, x7,
491                    x8, xnodce, xnoi, zcosg, zcosgl, zcosh, zcoshl,
492                    zcosi, zcosil, zsing, zsingl, zsinh, zsinhl, zsini,
493                    zsinil, zx, zy;
494    
495            nm = np;
496            em = ep;
497            snodm = Math.sin(nodep);
498            cnodm = Math.cos(nodep);
499            sinomm = Math.sin(argpp);
500            cosomm = Math.cos(argpp);
501            sinim = Math.sin(inclp);
502            cosim = Math.cos(inclp);
503            emsq = em * em;
504            betasq = 1.0 - emsq;
505            rtemsq = Math.sqrt(betasq);
506    
507            /* ----------------- initialize lunar solar terms --------------- */
508            satrec.peo = 0.0;
509            satrec.pinco = 0.0;
510            satrec.plo = 0.0;
511            satrec.pgho = 0.0;
512            satrec.pho = 0.0;
513            day = epoch + 18261.5 + tc / 1440.0;
514            xnodce = ((4.5236020 - 9.2422029e-4 * day) % twopi);
515            stem = Math.sin(xnodce);
516            ctem = Math.cos(xnodce);
517            zcosil = 0.91375164 - 0.03568096 * ctem;
518            zsinil = Math.sqrt(1.0 - zcosil * zcosil);
519            zsinhl = 0.089683511 * stem / zsinil;
520            zcoshl = Math.sqrt(1.0 - zsinhl * zsinhl);
521            gam = 5.8351514 + 0.0019443680 * day;
522            zx = 0.39785416 * stem / zsinil;
523            zy = zcoshl * ctem + 0.91744867 * zsinhl * stem;
524            zx = Math.atan2(zx, zy);
525            zx = gam + zx - xnodce;
526            zcosgl = Math.cos(zx);
527            zsingl = Math.sin(zx);
528    
529            /* ------------------------- do solar terms --------------------- */
530            zcosg = zcosgs;
531            zsing = zsings;
532            zcosi = zcosis;
533            zsini = zsinis;
534            zcosh = cnodm;
535            zsinh = snodm;
536            cc = c1ss;
537            xnoi = 1.0 / nm;
538    
539            for(lsflg = 1; lsflg <= 2; lsflg++)
540            {
541                a1 = zcosg * zcosh + zsing * zcosi * zsinh;
542                a3 = -zsing * zcosh + zcosg * zcosi * zsinh;
543                a7 = -zcosg * zsinh + zsing * zcosi * zcosh;
544                a8 = zsing * zsini;
545                a9 = zsing * zsinh + zcosg * zcosi * zcosh;
546                a10 = zcosg * zsini;
547                a2 = cosim * a7 + sinim * a8;
548                a4 = cosim * a9 + sinim * a10;
549                a5 = -sinim * a7 + cosim * a8;
550                a6 = -sinim * a9 + cosim * a10;
551    
552                x1 = a1 * cosomm + a2 * sinomm;
553                x2 = a3 * cosomm + a4 * sinomm;
554                x3 = -a1 * sinomm + a2 * cosomm;
555                x4 = -a3 * sinomm + a4 * cosomm;
556                x5 = a5 * sinomm;
557                x6 = a6 * sinomm;
558                x7 = a5 * cosomm;
559                x8 = a6 * cosomm;
560    
561                z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3;
562                z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4;
563                z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4;
564                z1 = 3.0 * (a1 * a1 + a2 * a2) + z31 * emsq;
565                z2 = 6.0 * (a1 * a3 + a2 * a4) + z32 * emsq;
566                z3 = 3.0 * (a3 * a3 + a4 * a4) + z33 * emsq;
567                z11 = -6.0 * a1 * a5 + emsq * (-24.0 * x1 * x7 - 6.0 * x3 * x5);
568                z12 = -6.0 * (a1 * a6 + a3 * a5) + emsq *
569                        (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5));
570                z13 = -6.0 * a3 * a6 + emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6);
571                z21 = 6.0 * a2 * a5 + emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7);
572                z22 = 6.0 * (a4 * a5 + a2 * a6) + emsq *
573                        (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8));
574                z23 = 6.0 * a4 * a6 + emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8);
575                z1 = z1 + z1 + betasq * z31;
576                z2 = z2 + z2 + betasq * z32;
577                z3 = z3 + z3 + betasq * z33;
578                s3 = cc * xnoi;
579                s2 = -0.5 * s3 / rtemsq;
580                s4 = s3 * rtemsq;
581                s1 = -15.0 * em * s4;
582                s5 = x1 * x3 + x2 * x4;
583                s6 = x2 * x3 + x1 * x4;
584                s7 = x2 * x4 - x1 * x3;
585    
586                /* ----------------------- do lunar terms ------------------- */
587                if(lsflg == 1)
588                {
589                    ss1 = s1;
590                    ss2 = s2;
591                    ss3 = s3;
592                    ss4 = s4;
593                    ss5 = s5;
594                    ss6 = s6;
595                    ss7 = s7;
596                    sz1 = z1;
597                    sz2 = z2;
598                    sz3 = z3;
599                    sz11 = z11;
600                    sz12 = z12;
601                    sz13 = z13;
602                    sz21 = z21;
603                    sz22 = z22;
604                    sz23 = z23;
605                    sz31 = z31;
606                    sz32 = z32;
607                    sz33 = z33;
608                    zcosg = zcosgl;
609                    zsing = zsingl;
610                    zcosi = zcosil;
611                    zsini = zsinil;
612                    zcosh = zcoshl * cnodm + zsinhl * snodm;
613                    zsinh = snodm * zcoshl - cnodm * zsinhl;
614                    cc = c1l;
615                }
616            }
617    
618            satrec.zmol = ((4.7199672 + 0.22997150 * day - gam) % twopi);
619            satrec.zmos = ((6.2565837 + 0.017201977 * day) % twopi);
620    
621            /* ------------------------ do solar terms ---------------------- */
622            satrec.se2 = 2.0 * ss1 * ss6;
623            satrec.se3 = 2.0 * ss1 * ss7;
624            satrec.si2 = 2.0 * ss2 * sz12;
625            satrec.si3 = 2.0 * ss2 * (sz13 - sz11);
626            satrec.sl2 = -2.0 * ss3 * sz2;
627            satrec.sl3 = -2.0 * ss3 * (sz3 - sz1);
628            satrec.sl4 = -2.0 * ss3 * (-21.0 - 9.0 * emsq) * zes;
629            satrec.sgh2 = 2.0 * ss4 * sz32;
630            satrec.sgh3 = 2.0 * ss4 * (sz33 - sz31);
631            satrec.sgh4 = -18.0 * ss4 * zes;
632            satrec.sh2 = -2.0 * ss2 * sz22;
633            satrec.sh3 = -2.0 * ss2 * (sz23 - sz21);
634    
635            /* ------------------------ do lunar terms ---------------------- */
636            satrec.ee2 = 2.0 * s1 * s6;
637            satrec.e3 = 2.0 * s1 * s7;
638            satrec.xi2 = 2.0 * s2 * z12;
639            satrec.xi3 = 2.0 * s2 * (z13 - z11);
640            satrec.xl2 = -2.0 * s3 * z2;
641            satrec.xl3 = -2.0 * s3 * (z3 - z1);
642            satrec.xl4 = -2.0 * s3 * (-21.0 - 9.0 * emsq) * zel;
643            satrec.xgh2 = 2.0 * s4 * z32;
644            satrec.xgh3 = 2.0 * s4 * (z33 - z31);
645            satrec.xgh4 = -18.0 * s4 * zel;
646            satrec.xh2 = -2.0 * s2 * z22;
647            satrec.xh3 = -2.0 * s2 * (z23 - z21);
648    
649            return new double[]
650                    {
651                        snodm, cnodm, sinim, cosim, sinomm, cosomm, day, em, emsq, gam, rtemsq, s1, s2, s3,
652                        s4, s5, s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, sz11, sz12, sz13,
653                        sz21, sz22, sz23, sz31, sz32, sz33, nm, z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33
654                    };
655    
656    //#include "debug2.cpp"
657        }  // end dscom
658    
659        /*-----------------------------------------------------------------------------
660         * Java version returns a double array with these values: [ em, argpm, inclm, mm, nm, nodem, dndt]
661         * -----------------------------------------------------------------------------
662         *                           procedure dsinit
663         *
664         *  this procedure provides deep space contributions to mean motion dot due
665         *    to geopotential resonance with half day and one day orbits.
666         *
667         *  author        : david vallado                  719-573-2600   28 jun 2005
668         *
669         *  inputs        :
670         *    cosim, sinim-
671         *    emsq        - eccentricity squared
672         *    argpo       - argument of perigee
673         *    s1, s2, s3, s4, s5      -
674         *    ss1, ss2, ss3, ss4, ss5 -
675         *    sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 -
676         *    t           - time
677         *    tc          -
678         *    gsto        - greenwich sidereal time                   rad
679         *    mo          - mean anomaly
680         *    mdot        - mean anomaly dot (rate)
681         *    no          - mean motion
682         *    nodeo       - right ascension of ascending node
683         *    nodedot     - right ascension of ascending node dot (rate)
684         *    xpidot      -
685         *    z1, z3, z11, z13, z21, z23, z31, z33 -
686         *    eccm        - eccentricity
687         *    argpm       - argument of perigee
688         *    inclm       - inclination
689         *    mm          - mean anomaly
690         *    xn          - mean motion
691         *    nodem       - right ascension of ascending node
692         *
693         *  outputs       :
694         *    em          - eccentricity
695         *    argpm       - argument of perigee
696         *    inclm       - inclination
697         *    mm          - mean anomaly
698         *    nm          - mean motion
699         *    nodem       - right ascension of ascending node
700         *    irez        - flag for resonance           0-none, 1-one day, 2-half day
701         *    atime       -
702         *    d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433    -
703         *    dedt        -
704         *    didt        -
705         *    dmdt        -
706         *    dndt        -
707         *    dnodt       -
708         *    domdt       -
709         *    del1, del2, del3        -
710         *    ses  , sghl , sghs , sgs  , shl  , shs  , sis  , sls
711         *    theta       -
712         *    xfact       -
713         *    xlamo       -
714         *    xli         -
715         *    xni
716         *
717         *  locals        :
718         *    ainv2       -
719         *    aonv        -
720         *    cosisq      -
721         *    eoc         -
722         *    f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543  -
723         *    g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533  -
724         *    sini2       -
725         *    temp        -
726         *    temp1       -
727         *    theta       -
728         *    xno2        -
729         *
730         *  coupling      :
731         *    getgravconst
732         *
733         *  references    :
734         *    hoots, roehrich, norad spacetrack report #3 1980
735         *    hoots, norad spacetrack report #6 1986
736         *    hoots, schumacher and glover 2004
737         *    vallado, crawford, hujsak, kelso  2006
738        ----------------------------------------------------------------------------*/
739    // returns array containing:
740    // [ em, argpm, inclm, mm, nm, nodem, dndt]
741        private static double[] dsinit(
742                Gravconsttype whichconst,
743                double cosim, double emsq, double argpo, double s1, double s2,
744                double s3, double s4, double s5, double sinim, double ss1,
745                double ss2, double ss3, double ss4, double ss5, double sz1,
746                double sz3, double sz11, double sz13, double sz21, double sz23,
747                double sz31, double sz33, double t, double tc, double gsto,
748                double mo, double mdot, double no, double nodeo, double nodedot,
749                double xpidot, double z1, double z3, double z11, double z13,
750                double z21, double z23, double z31, double z33, double ecco,
751                double eccsq,
752                // return
753                SGP4SatData satrec,
754                double em, // variable is also an INPUT and output - SEG!!
755                double argpm,
756                double inclm,
757                double mm,
758                double nm, // variable is also an INPUT and output - SEG!!
759                double nodem //       // not in SGP4SatData
760                //       double& em,    double& argpm,  double& inclm, double& mm,
761                //       double& nm,    double& nodem,
762                //       // in
763                //       int& irez,
764                //       double& atime, double& d2201, double& d2211,  double& d3210, double& d3222,
765                //       double& d4410, double& d4422, double& d5220,  double& d5232, double& d5421,
766                //       double& d5433, double& dedt,  double& didt,   double& dmdt,
767                //       // not
768                //       double& dndt,
769                //       // in
770                //       double& dnodt, double& domdt, double& del1,   double& del2,  double& del3,
771                //       double& xfact, double& xlamo, double& xli,    double& xni
772                )
773        {
774            // return values ------------------
775            double dndt; // em,nm, inclm, argpm, nodem, mm are also inputs
776    
777            /* --------------------- local variables ------------------------ */
778            final double twopi = 2.0 * pi;
779    
780            double ainv2, aonv = 0.0, cosisq, eoc, f220, f221, f311,
781                    f321, f322, f330, f441, f442, f522, f523,
782                    f542, f543, g200, g201, g211, g300, g310,
783                    g322, g410, g422, g520, g521, g532, g533,
784                    ses, sgs, sghl, sghs, shs, shll, sis,
785                    sini2, sls, temp, temp1, theta, xno2, q22,
786                    q31, q33, root22, root44, root54, rptim, root32,
787                    root52, x2o3, xke, znl, emo, zns, emsqo,
788                    tumin, mu, radiusearthkm, j2, j3, j4, j3oj2;
789    
790            q22 = 1.7891679e-6;
791            q31 = 2.1460748e-6;
792            q33 = 2.2123015e-7;
793            root22 = 1.7891679e-6;
794            root44 = 7.3636953e-9;
795            root54 = 2.1765803e-9;
796            rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec
797            root32 = 3.7393792e-7;
798            root52 = 1.1428639e-7;
799            x2o3 = 2.0 / 3.0;
800            znl = 1.5835218e-4;
801            zns = 1.19459e-5;
802    
803            // sgp4fix identify constants and allow alternate values
804            double[] temp2 = getgravconst(whichconst);
805            tumin = temp2[0];
806            mu = temp2[1];
807            radiusearthkm = temp2[2];
808            xke = temp2[3];
809            j2 = temp2[4];
810            j3 = temp2[5];
811            j4 = temp2[6];
812            j3oj2 = temp2[7];
813    
814            /* -------------------- deep space initialization ------------ */
815            satrec.irez = 0;
816            if((nm < 0.0052359877) && (nm > 0.0034906585))
817            {
818                satrec.irez = 1;
819            }
820            if((nm >= 8.26e-3) && (nm <= 9.24e-3) && (em >= 0.5))
821            {
822                satrec.irez = 2;
823            }
824    
825            /* ------------------------ do solar terms ------------------- */
826            ses = ss1 * zns * ss5;
827            sis = ss2 * zns * (sz11 + sz13);
828            sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq);
829            sghs = ss4 * zns * (sz31 + sz33 - 6.0);
830            shs = -zns * ss2 * (sz21 + sz23);
831            // sgp4fix for 180 deg incl
832            if((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2))
833            {
834                shs = 0.0;
835            }
836            if(sinim != 0.0)
837            {
838                shs = shs / sinim;
839            }
840            sgs = sghs - cosim * shs;
841    
842            /* ------------------------- do lunar terms ------------------ */
843            satrec.dedt = ses + s1 * znl * s5;
844            satrec.didt = sis + s2 * znl * (z11 + z13);
845            satrec.dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq);
846            sghl = s4 * znl * (z31 + z33 - 6.0);
847            shll = -znl * s2 * (z21 + z23);
848            // sgp4fix for 180 deg incl
849            if((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2))
850            {
851                shll = 0.0;
852            }
853            satrec.domdt = sgs + sghl;
854            satrec.dnodt = shs;
855            if(sinim != 0.0)
856            {
857                satrec.domdt = satrec.domdt - cosim / sinim * shll;
858                satrec.dnodt = satrec.dnodt + shll / sinim;
859            }
860    
861            /* ----------- calculate deep space resonance effects -------- */
862            dndt = 0.0;
863            theta = ((gsto + tc * rptim) % twopi);
864            em = em + satrec.dedt * t;
865            inclm = inclm + satrec.didt * t;
866            argpm = argpm + satrec.domdt * t;
867            nodem = nodem + satrec.dnodt * t;
868            mm = mm + satrec.dmdt * t;
869            //   sgp4fix for negative inclinations
870            //   the following if statement should be commented out
871            //if (inclm < 0.0)
872            //  {
873            //    inclm  = -inclm;
874            //    argpm  = argpm - pi;
875            //    nodem = nodem + pi;
876            //  }
877    
878            /* -------------- initialize the resonance terms ------------- */
879            if(satrec.irez != 0)
880            {
881                aonv = Math.pow(nm / xke, x2o3);
882    
883                /* ---------- geopotential resonance for 12 hour orbits ------ */
884                if(satrec.irez == 2)
885                {
886                    cosisq = cosim * cosim;
887                    emo = em;
888                    em = ecco;
889                    emsqo = emsq;
890                    emsq = eccsq;
891                    eoc = em * emsq;
892                    g201 = -0.306 - (em - 0.64) * 0.440;
893    
894                    if(em <= 0.65)
895                    {
896                        g211 = 3.616 - 13.2470 * em + 16.2900 * emsq;
897                        g310 = -19.302 + 117.3900 * em - 228.4190 * emsq + 156.5910 * eoc;
898                        g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc;
899                        g410 = -41.122 + 242.6940 * em - 471.0940 * emsq + 313.9530 * eoc;
900                        g422 = -146.407 + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc;
901                        g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc;
902                    }
903                    else
904                    {
905                        g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc;
906                        g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc;
907                        g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc;
908                        g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc;
909                        g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc;
910                        if(em > 0.715)
911                        {
912                            g520 = -5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc;
913                        }
914                        else
915                        {
916                            g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq;
917                        }
918                    }
919                    if(em < 0.7)
920                    {
921                        g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21 * eoc;
922                        g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc;
923                        g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4 * eoc;
924                    }
925                    else
926                    {
927                        g533 = -37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc;
928                        g521 = -51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc;
929                        g532 = -40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc;
930                    }
931    
932                    sini2 = sinim * sinim;
933                    f220 = 0.75 * (1.0 + 2.0 * cosim + cosisq);
934                    f221 = 1.5 * sini2;
935                    f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq);
936                    f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq);
937                    f441 = 35.0 * sini2 * f220;
938                    f442 = 39.3750 * sini2 * sini2;
939                    f522 = 9.84375 * sinim * (sini2 * (1.0 - 2.0 * cosim - 5.0 * cosisq) +
940                            0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq));
941                    f523 = sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim +
942                            10.0 * cosisq) + 6.56250012 * (1.0 + 2.0 * cosim - 3.0 * cosisq));
943                    f542 = 29.53125 * sinim * (2.0 - 8.0 * cosim + cosisq *
944                            (-12.0 + 8.0 * cosim + 10.0 * cosisq));
945                    f543 = 29.53125 * sinim * (-2.0 - 8.0 * cosim + cosisq *
946                            (12.0 + 8.0 * cosim - 10.0 * cosisq));
947                    xno2 = nm * nm;
948                    ainv2 = aonv * aonv;
949                    temp1 = 3.0 * xno2 * ainv2;
950                    temp = temp1 * root22;
951                    satrec.d2201 = temp * f220 * g201;
952                    satrec.d2211 = temp * f221 * g211;
953                    temp1 = temp1 * aonv;
954                    temp = temp1 * root32;
955                    satrec.d3210 = temp * f321 * g310;
956                    satrec.d3222 = temp * f322 * g322;
957                    temp1 = temp1 * aonv;
958                    temp = 2.0 * temp1 * root44;
959                    satrec.d4410 = temp * f441 * g410;
960                    satrec.d4422 = temp * f442 * g422;
961                    temp1 = temp1 * aonv;
962                    temp = temp1 * root52;
963                    satrec.d5220 = temp * f522 * g520;
964                    satrec.d5232 = temp * f523 * g532;
965                    temp = 2.0 * temp1 * root54;
966                    satrec.d5421 = temp * f542 * g521;
967                    satrec.d5433 = temp * f543 * g533;
968                    satrec.xlamo = ((mo + nodeo + nodeo - theta - theta) % twopi);
969                    satrec.xfact = mdot + satrec.dmdt + 2.0 * (nodedot + satrec.dnodt - rptim) - no;
970                    em = emo;
971                    emsq = emsqo;
972                }
973    
974                /* ---------------- synchronous resonance terms -------------- */
975                if(satrec.irez == 1)
976                {
977                    g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq);
978                    g310 = 1.0 + 2.0 * emsq;
979                    g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq);
980                    f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim);
981                    f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim);
982                    f330 = 1.0 + cosim;
983                    f330 = 1.875 * f330 * f330 * f330;
984                    satrec.del1 = 3.0 * nm * nm * aonv * aonv;
985                    satrec.del2 = 2.0 * satrec.del1 * f220 * g200 * q22;
986                    satrec.del3 = 3.0 * satrec.del1 * f330 * g300 * q33 * aonv;
987                    satrec.del1 = satrec.del1 * f311 * g310 * q31 * aonv;
988                    satrec.xlamo = ((mo + nodeo + argpo - theta) % twopi);
989                    satrec.xfact = mdot + xpidot - rptim + satrec.dmdt + satrec.domdt + satrec.dnodt - no;
990                }
991    
992                /* ------------ for sgp4, initialize the integrator ---------- */
993                satrec.xli = satrec.xlamo;
994                satrec.xni = no;
995                satrec.atime = 0.0;
996                nm = no + dndt;
997            }
998    
999            return new double[]
1000                    {
1001                        em, argpm, inclm, mm, nm, nodem, dndt
1002                    };
1003    
1004    //#include "debug3.cpp"
1005        }  // end dsinit
1006    
1007        /*-----------------------------------------------------------------------------
1008         *
1009         *                           procedure dspace
1010         *
1011         *  this procedure provides deep space contributions to mean elements for
1012         *    perturbing third body.  these effects have been averaged over one
1013         *    revolution of the sun and moon.  for earth resonance effects, the
1014         *    effects have been averaged over no revolutions of the satellite.
1015         *    (mean motion)
1016         *
1017         *  author        : david vallado                  719-573-2600   28 jun 2005
1018         *
1019         *  inputs        :
1020         *    d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 -
1021         *    dedt        -
1022         *    del1, del2, del3  -
1023         *    didt        -
1024         *    dmdt        -
1025         *    dnodt       -
1026         *    domdt       -
1027         *    irez        - flag for resonance           0-none, 1-one day, 2-half day
1028         *    argpo       - argument of perigee
1029         *    argpdot     - argument of perigee dot (rate)
1030         *    t           - time
1031         *    tc          -
1032         *    gsto        - gst
1033         *    xfact       -
1034         *    xlamo       -
1035         *    no          - mean motion
1036         *    atime       -
1037         *    em          - eccentricity
1038         *    ft          -
1039         *    argpm       - argument of perigee
1040         *    inclm       - inclination
1041         *    xli         -
1042         *    mm          - mean anomaly
1043         *    xni         - mean motion
1044         *    nodem       - right ascension of ascending node
1045         *
1046         *  outputs       :
1047         *    atime       -
1048         *    em          - eccentricity
1049         *    argpm       - argument of perigee
1050         *    inclm       - inclination
1051         *    xli         -
1052         *    mm          - mean anomaly
1053         *    xni         -
1054         *    nodem       - right ascension of ascending node
1055         *    dndt        -
1056         *    nm          - mean motion
1057         *
1058         *  locals        :
1059         *    delt        -
1060         *    ft          -
1061         *    theta       -
1062         *    x2li        -
1063         *    x2omi       -
1064         *    xl          -
1065         *    xldot       -
1066         *    xnddt       -
1067         *    xndt        -
1068         *    xomi        -
1069         *
1070         *  coupling      :
1071         *    none        -
1072         *
1073         *  references    :
1074         *    hoots, roehrich, norad spacetrack report #3 1980
1075         *    hoots, norad spacetrack report #6 1986
1076         *    hoots, schumacher and glover 2004
1077         *    vallado, crawford, hujsak, kelso  2006
1078        ----------------------------------------------------------------------------*/
1079    // nm - also added as an input since it may not be changed and it needs to retain its old value
1080    // returns array with these values:
1081    // [em, argpm, inclm, mm,nodem, dndt, nm]
1082        private static double[] dspace(
1083                int irez,
1084                double d2201, double d2211, double d3210, double d3222, double d4410,
1085                double d4422, double d5220, double d5232, double d5421, double d5433,
1086                double dedt, double del1, double del2, double del3, double didt,
1087                double dmdt, double dnodt, double domdt, double argpo, double argpdot,
1088                double t, double tc, double gsto, double xfact, double xlamo,
1089                double no,//
1090                // These variables are both inputs and returned as outputs
1091                double em,
1092                double argpm,
1093                double inclm,
1094                double mm,
1095                double nodem,
1096                // data that is retained with the SGP4SatData object
1097                SGP4SatData satrec,
1098                //       double& atime, double& em,    double& argpm,  double& inclm, double& xli,
1099                //       double& mm,    double& xni,   double& nodem,  double& dndt,  double& nm
1100                double nm // input and output
1101                )
1102        {
1103            // variables that are both inputs and outputs! included in SGP4SatData
1104            // atime, em, argpm, inclm, xli, mm, xni, nodem
1105    
1106            // Return variables (that are not also inputs)---------------------
1107            double dndt;
1108    
1109            final double twopi = 2.0 * pi;
1110            int iretn, iret;
1111            double delt, ft, theta, x2li, x2omi, xl, xldot, xnddt, xndt, xomi, g22, g32,
1112                    g44, g52, g54, fasx2, fasx4, fasx6, rptim, step2, stepn, stepp;
1113    
1114            // SEG -- it is okay to initalize these values here as they are assigned values
1115            xndt = 0;
1116            xnddt = 0;
1117            xldot = 0;
1118    
1119            fasx2 = 0.13130908;
1120            fasx4 = 2.8843198;
1121            fasx6 = 0.37448087;
1122            g22 = 5.7686396;
1123            g32 = 0.95240898;
1124            g44 = 1.8014998;
1125            g52 = 1.0508330;
1126            g54 = 4.4108898;
1127            rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec
1128            stepp = 720.0;
1129            stepn = -720.0;
1130            step2 = 259200.0;
1131    
1132            /* ----------- calculate deep space resonance effects ----------- */
1133            dndt = 0.0;
1134            theta = ((gsto + tc * rptim) % twopi);
1135            em = em + dedt * t;
1136    
1137            inclm = inclm + didt * t;
1138            argpm = argpm + domdt * t;
1139            nodem = nodem + dnodt * t;
1140            mm = mm + dmdt * t;
1141    
1142            //   sgp4fix for negative inclinations
1143            //   the following if statement should be commented out
1144            //  if (inclm < 0.0)
1145            // {
1146            //    inclm = -inclm;
1147            //    argpm = argpm - pi;
1148            //    nodem = nodem + pi;
1149            //  }
1150    
1151            /* - update resonances : numerical (euler-maclaurin) integration - */
1152            /* ------------------------- epoch restart ----------------------  */
1153            //   sgp4fix for propagator problems
1154            //   the following integration works for negative time steps and periods
1155            //   the specific changes are unknown because the original code was so convoluted
1156    
1157            // sgp4fix take out atime = 0.0 and fix for faster operation
1158            ft = 0.0;
1159            if(irez != 0)
1160            {
1161                // sgp4fix streamline check
1162                if((satrec.atime == 0.0) || (t * satrec.atime <= 0.0) || (Math.abs(t) < Math.abs(satrec.atime)))
1163                {
1164                    satrec.atime = 0.0;
1165                    satrec.xni = no;
1166                    satrec.xli = xlamo;
1167                }
1168                // sgp4fix move check outside loop
1169                if(t > 0.0)
1170                {
1171                    delt = stepp;
1172                }
1173                else
1174                {
1175                    delt = stepn;
1176                }
1177    
1178                iretn = 381; // added for do loop
1179                iret = 0; // added for loop
1180                while(iretn == 381)
1181                {
1182                    /* ------------------- dot terms calculated ------------- */
1183                    /* ----------- near - synchronous resonance terms ------- */
1184                    if(irez != 2)
1185                    {
1186                        xndt = del1 * Math.sin(satrec.xli - fasx2) + del2 * Math.sin(2.0 * (satrec.xli - fasx4)) +
1187                                del3 * Math.sin(3.0 * (satrec.xli - fasx6));
1188                        xldot = satrec.xni + xfact;
1189                        xnddt = del1 * Math.cos(satrec.xli - fasx2) +
1190                                2.0 * del2 * Math.cos(2.0 * (satrec.xli - fasx4)) +
1191                                3.0 * del3 * Math.cos(3.0 * (satrec.xli - fasx6));
1192                        xnddt = xnddt * xldot;
1193                    }
1194                    else
1195                    {
1196                        /* --------- near - half-day resonance terms -------- */
1197                        xomi = argpo + argpdot * satrec.atime;
1198                        x2omi = xomi + xomi;
1199                        x2li = satrec.xli + satrec.xli;
1200                        xndt = d2201 * Math.sin(x2omi + satrec.xli - g22) + d2211 * Math.sin(satrec.xli - g22) +
1201                                d3210 * Math.sin(xomi + satrec.xli - g32) + d3222 * Math.sin(-xomi + satrec.xli - g32) +
1202                                d4410 * Math.sin(x2omi + x2li - g44) + d4422 * Math.sin(x2li - g44) +
1203                                d5220 * Math.sin(xomi + satrec.xli - g52) + d5232 * Math.sin(-xomi + satrec.xli - g52) +
1204                                d5421 * Math.sin(xomi + x2li - g54) + d5433 * Math.sin(-xomi + x2li - g54);
1205                        xldot = satrec.xni + xfact;
1206                        xnddt = d2201 * Math.cos(x2omi + satrec.xli - g22) + d2211 * Math.cos(satrec.xli - g22) +
1207                                d3210 * Math.cos(xomi + satrec.xli - g32) + d3222 * Math.cos(-xomi + satrec.xli - g32) +
1208                                d5220 * Math.cos(xomi + satrec.xli - g52) + d5232 * Math.cos(-xomi + satrec.xli - g52) +
1209                                2.0 * (d4410 * Math.cos(x2omi + x2li - g44) +
1210                                d4422 * Math.cos(x2li - g44) + d5421 * Math.cos(xomi + x2li - g54) +
1211                                d5433 * Math.cos(-xomi + x2li - g54));
1212                        xnddt = xnddt * xldot;
1213                    }
1214    
1215                    /* ----------------------- integrator ------------------- */
1216                    // sgp4fix move end checks to end of routine
1217                    if(Math.abs(t - satrec.atime) >= stepp)
1218                    {
1219                        iret = 0;
1220                        iretn = 381;
1221                    }
1222                    else // exit here
1223                    {
1224                        ft = t - satrec.atime;
1225                        iretn = 0;
1226                    }
1227    
1228                    if(iretn == 381)
1229                    {
1230                        satrec.xli = satrec.xli + xldot * delt + xndt * step2;
1231                        satrec.xni = satrec.xni + xndt * delt + xnddt * step2;
1232                        satrec.atime = satrec.atime + delt;
1233                    }
1234                }  // while iretn = 381
1235    
1236                nm = satrec.xni + xndt * ft + xnddt * ft * ft * 0.5;
1237                xl = satrec.xli + xldot * ft + xndt * ft * ft * 0.5;
1238                if(irez != 1)
1239                {
1240                    mm = xl - 2.0 * nodem + 2.0 * theta;
1241                    dndt = nm - no;
1242                }
1243                else
1244                {
1245                    mm = xl - nodem - argpm + theta;
1246                    dndt = nm - no;
1247                }
1248                nm = no + dndt;
1249            }
1250    
1251            return new double[]
1252                    {
1253                        em, argpm, inclm, mm, nodem, dndt, nm
1254                    };
1255    
1256    //#include "debug4.cpp"
1257        }  // end dsspace
1258    
1259        /** -----------------------------------------------------------------------------
1260         *
1261         *                           procedure initl
1262         *
1263         *  this procedure initializes the spg4 propagator. all the initialization is
1264         *    consolidated here instead of having multiple loops inside other routines.
1265         *
1266         *  author        : david vallado                  719-573-2600   28 jun 2005
1267         *
1268         *  inputs        :
1269         *    ecco        - eccentricity                           0.0 - 1.0
1270         *    epoch       - epoch time in days from jan 0, 1950. 0 hr
1271         *    inclo       - inclination of satellite
1272         *    no          - mean motion of satellite
1273         *    satn        - satellite number
1274         *
1275         *  outputs       :
1276         *    ainv        - 1.0 / a
1277         *    ao          - semi major axis
1278         *    con41       -
1279         *    con42       - 1.0 - 5.0 cos(i)
1280         *    cosio       - cosine of inclination
1281         *    cosio2      - cosio squared
1282         *    eccsq       - eccentricity squared
1283         *    method      - flag for deep space                    'd', 'n'
1284         *    omeosq      - 1.0 - ecco * ecco
1285         *    posq        - semi-parameter squared
1286         *    rp          - radius of perigee
1287         *    rteosq      - square root of (1.0 - ecco*ecco)
1288         *    sinio       - sine of inclination
1289         *    gsto        - gst at time of observation               rad
1290         *    no          - mean motion of satellite
1291         *
1292         *  locals        :
1293         *    ak          -
1294         *    d1          -
1295         *    del         -
1296         *    adel        -
1297         *    po          -
1298         *
1299         *  coupling      :
1300         *    getgravconst
1301         *    gstime      - find greenwich sidereal time from the julian date
1302         *
1303         *  references    :
1304         *    hoots, roehrich, norad spacetrack report #3 1980
1305         *    hoots, norad spacetrack report #6 1986
1306         *    hoots, schumacher and glover 2004
1307         *    vallado, crawford, hujsak, kelso  2006
1308         * ----------------------------------------------------------------------------
1309         * @param satn satellite number
1310         * @param whichconst which constants set to use
1311         * @param ecco eccentricity (0,1)
1312         * @param epoch epoch time in days from jan 0, 1950. 0 hr
1313         * @param inclo inclination of satellite
1314         * @param satrec satellite object that stores needed SGP4 data
1315         * @return double array with these values: [ainv, ao, con42, cosio, cosio2, eccsq, omeosq, posq, rp, rteosq, sinio]
1316         */
1317    // outputs not stored in SGP4SatData and are returned by this function:
1318    // [ainv, ao, con42, cosio, cosio2, eccsq, omeosq, posq, rp, rteosq, sinio]
1319        public static double[] initl(
1320                int satn, Gravconsttype whichconst,
1321                double ecco, double epoch, double inclo,
1322                //
1323                SGP4SatData satrec //       //double& no,
1324                //       //char& method,
1325                //       double& ainv, double& ao,
1326                //       //double& con41,
1327                //       double& con42, double& cosio,
1328                //       double& cosio2,double& eccsq, double& omeosq, double& posq,
1329                //       double& rp,    double& rteosq,double& sinio ,
1330                //       //double& gsto, char opsmode
1331                )
1332        {
1333            // no is an input and an output
1334            // return variables ----------------
1335            double ainv, ao, con42, cosio, cosio2, eccsq, omeosq, posq, rp, rteosq, sinio;
1336    
1337            /* --------------------- local variables ------------------------ */
1338            double ak, d1, del, adel, po, x2o3, j2, xke,
1339                    tumin, mu, radiusearthkm, j3, j4, j3oj2;
1340    
1341            // sgp4fix use old way of finding gst
1342            double ds70;
1343            double ts70, tfrac, c1, thgr70, fk5r, c1p2p, thgr, thgro;
1344            final double twopi = 2.0 * pi;
1345    
1346            /* ----------------------- earth constants ---------------------- */
1347            // sgp4fix identify constants and allow alternate values
1348            double[] temp2 = getgravconst(whichconst);
1349            tumin = temp2[0];
1350            mu = temp2[1];
1351            radiusearthkm = temp2[2];
1352            xke = temp2[3];
1353            j2 = temp2[4];
1354            j3 = temp2[5];
1355            j4 = temp2[6];
1356            j3oj2 = temp2[7];
1357    
1358            x2o3 = 2.0 / 3.0;
1359    
1360            /* ------------- calculate auxillary epoch quantities ---------- */
1361            eccsq = ecco * ecco;
1362            omeosq = 1.0 - eccsq;
1363            rteosq = Math.sqrt(omeosq);
1364            cosio = Math.cos(inclo);
1365            cosio2 = cosio * cosio;
1366    
1367            /* ------------------ un-kozai the mean motion ----------------- */
1368            ak = Math.pow(xke / satrec.no, x2o3);
1369            d1 = 0.75 * j2 * (3.0 * cosio2 - 1.0) / (rteosq * omeosq);
1370            del = d1 / (ak * ak);
1371            adel = ak * (1.0 - del * del - del *
1372                    (1.0 / 3.0 + 134.0 * del * del / 81.0));
1373            del = d1 / (adel * adel);
1374            satrec.no = satrec.no / (1.0 + del);
1375    
1376            ao = Math.pow(xke / satrec.no, x2o3);
1377            sinio = Math.sin(inclo);
1378            po = ao * omeosq;
1379            con42 = 1.0 - 5.0 * cosio2;
1380            satrec.con41 = -con42 - cosio2 - cosio2;
1381            ainv = 1.0 / ao;
1382            posq = po * po;
1383            rp = ao * (1.0 - ecco);
1384            satrec.method = 'n';
1385    
1386            // sgp4fix modern approach to finding sidereal time
1387            if(satrec.operationmode == 'a')
1388            {
1389                // sgp4fix use old way of finding gst
1390                // count integer number of days from 0 jan 1970
1391                ts70 = epoch - 7305.0;
1392                ds70 = Math.floor(ts70 + 1.0e-8);
1393                tfrac = ts70 - ds70;
1394                // find greenwich location at epoch
1395                c1 = 1.72027916940703639e-2;
1396                thgr70 = 1.7321343856509374;
1397                fk5r = 5.07551419432269442e-15;
1398                c1p2p = c1 + twopi;
1399                satrec.gsto = ((thgr70 + c1 * ds70 + c1p2p * tfrac + ts70 * ts70 * fk5r) % twopi);
1400                if(satrec.gsto < 0.0)
1401                {
1402                    satrec.gsto = satrec.gsto + twopi;
1403                }
1404            }
1405            else
1406            {
1407                satrec.gsto = gstime(epoch + 2433281.5);
1408            }
1409    
1410            return new double[]
1411                    {
1412                        ainv, ao, con42, cosio, cosio2, eccsq, omeosq, posq, rp, rteosq, sinio
1413                    };
1414    
1415    //#include "debug5.cpp"
1416        }  // end initl
1417    
1418        /**-----------------------------------------------------------------------------
1419         * This method is called from within SGP4utils.readTLEandIniSGP4 and therefore not
1420         * typically called elsewhere.
1421         * -----------------------------------------------------------------------------
1422         *
1423         *                             procedure sgp4init
1424         *
1425         *  this procedure initializes variables for sgp4.
1426         *
1427         *  author        : david vallado                  719-573-2600   28 jun 2005
1428         *
1429         *  inputs        :
1430         *    opsmode     - mode of operation afspc or improved 'a', 'i'
1431         *    whichconst  - which set of constants to use  72, 84
1432         *    satn        - satellite number
1433         *    bstar       - sgp4 type drag coefficient              kg/m2er
1434         *    ecco        - eccentricity
1435         *    epoch       - epoch time in days from jan 0, 1950. 0 hr
1436         *    argpo       - argument of perigee (output if ds)
1437         *    inclo       - inclination
1438         *    mo          - mean anomaly (output if ds)
1439         *    no          - mean motion
1440         *    nodeo       - right ascension of ascending node
1441         *
1442         *  outputs       :
1443         *    satrec      - common values for subsequent calls
1444         *    return code - non-zero on error.
1445         *                   1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er
1446         *                   2 - mean motion less than 0.0
1447         *                   3 - pert elements, ecc < 0.0  or  ecc > 1.0
1448         *                   4 - semi-latus rectum < 0.0
1449         *                   5 - epoch elements are sub-orbital
1450         *                   6 - satellite has decayed
1451         *
1452         *  locals        :
1453         *    cnodm  , snodm  , cosim  , sinim  , cosomm , sinomm
1454         *    cc1sq  , cc2    , cc3
1455         *    coef   , coef1
1456         *    cosio4      -
1457         *    day         -
1458         *    dndt        -
1459         *    em          - eccentricity
1460         *    emsq        - eccentricity squared
1461         *    eeta        -
1462         *    etasq       -
1463         *    gam         -
1464         *    argpm       - argument of perigee
1465         *    nodem       -
1466         *    inclm       - inclination
1467         *    mm          - mean anomaly
1468         *    nm          - mean motion
1469         *    perige      - perigee
1470         *    pinvsq      -
1471         *    psisq       -
1472         *    qzms24      -
1473         *    rtemsq      -
1474         *    s1, s2, s3, s4, s5, s6, s7          -
1475         *    sfour       -
1476         *    ss1, ss2, ss3, ss4, ss5, ss6, ss7         -
1477         *    sz1, sz2, sz3
1478         *    sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33        -
1479         *    tc          -
1480         *    temp        -
1481         *    temp1, temp2, temp3       -
1482         *    tsi         -
1483         *    xpidot      -
1484         *    xhdot1      -
1485         *    z1, z2, z3          -
1486         *    z11, z12, z13, z21, z22, z23, z31, z32, z33         -
1487         *
1488         *  coupling      :
1489         *    getgravconst-
1490         *    initl       -
1491         *    dscom       -
1492         *    dpper       -
1493         *    dsinit      -
1494         *    sgp4        -
1495         *
1496         *  references    :
1497         *    hoots, roehrich, norad spacetrack report #3 1980
1498         *    hoots, norad spacetrack report #6 1986
1499         *    hoots, schumacher and glover 2004
1500         *    vallado, crawford, hujsak, kelso  2006
1501         * ----------------------------------------------------------------------------
1502         * @param whichconst
1503         * @param opsmode
1504         * @param satn
1505         * @param epoch
1506         * @param xbstar
1507         * @param xecco
1508         * @param xargpo
1509         * @param xinclo
1510         * @param xmo
1511         * @param xno
1512         * @param xnodeo
1513         * @param satrec
1514         * @return if initialization was successful
1515         */
1516        public static boolean sgp4init(
1517                Gravconsttype whichconst, char opsmode, final int satn, final double epoch,
1518                final double xbstar, final double xecco, final double xargpo,
1519                final double xinclo, final double xmo, final double xno,
1520                final double xnodeo, SGP4SatData satrec)
1521        {
1522            /* --------------------- local variables ------------------------ */
1523            double ao, ainv, con42, cosio, sinio, cosio2, eccsq,
1524                    omeosq, posq, rp, rteosq,
1525                    cnodm, snodm, cosim, sinim, cosomm, sinomm, cc1sq,
1526                    cc2, cc3, coef, coef1, cosio4, day, dndt,
1527                    em, emsq, eeta, etasq, gam, argpm, nodem,
1528                    inclm, mm, nm, perige, pinvsq, psisq, qzms24,
1529                    rtemsq, s1, s2, s3, s4, s5, s6,
1530                    s7, sfour, ss1, ss2, ss3, ss4, ss5,
1531                    ss6, ss7, sz1, sz2, sz3, sz11, sz12,
1532                    sz13, sz21, sz22, sz23, sz31, sz32, sz33,
1533                    tc, temp, temp1, temp2, temp3, tsi, xpidot,
1534                    xhdot1, z1, z2, z3, z11, z12, z13,
1535                    z21, z22, z23, z31, z32, z33,
1536                    qzms2t, ss, j2, j3oj2, j4, x2o3, //r[3], v[3],
1537                    tumin, mu, radiusearthkm, xke, j3;
1538            double[] r = new double[3];
1539            double[] v = new double[3];
1540    
1541            /* ------------------------ initialization --------------------- */
1542            // sgp4fix divisor for divide by zero check on inclination
1543            // the old check used 1.0 + cos(pi-1.0e-9), but then compared it to
1544            // 1.5 e-12, so the threshold was changed to 1.5e-12 for consistency
1545            final double temp4 = 1.5e-12;
1546    
1547            /* ----------- set all near earth variables to zero ------------ */
1548            satrec.isimp = 0;
1549            satrec.method = 'n';
1550            satrec.aycof = 0.0;
1551            satrec.con41 = 0.0;
1552            satrec.cc1 = 0.0;
1553            satrec.cc4 = 0.0;
1554            satrec.cc5 = 0.0;
1555            satrec.d2 = 0.0;
1556            satrec.d3 = 0.0;
1557            satrec.d4 = 0.0;
1558            satrec.delmo = 0.0;
1559            satrec.eta = 0.0;
1560            satrec.argpdot = 0.0;
1561            satrec.omgcof = 0.0;
1562            satrec.sinmao = 0.0;
1563            satrec.t = 0.0;
1564            satrec.t2cof = 0.0;
1565            satrec.t3cof = 0.0;
1566            satrec.t4cof = 0.0;
1567            satrec.t5cof = 0.0;
1568            satrec.x1mth2 = 0.0;
1569            satrec.x7thm1 = 0.0;
1570            satrec.mdot = 0.0;
1571            satrec.nodedot = 0.0;
1572            satrec.xlcof = 0.0;
1573            satrec.xmcof = 0.0;
1574            satrec.nodecf = 0.0;
1575    
1576            /* ----------- set all deep space variables to zero ------------ */
1577            satrec.irez = 0;
1578            satrec.d2201 = 0.0;
1579            satrec.d2211 = 0.0;
1580            satrec.d3210 = 0.0;
1581            satrec.d3222 = 0.0;
1582            satrec.d4410 = 0.0;
1583            satrec.d4422 = 0.0;
1584            satrec.d5220 = 0.0;
1585            satrec.d5232 = 0.0;
1586            satrec.d5421 = 0.0;
1587            satrec.d5433 = 0.0;
1588            satrec.dedt = 0.0;
1589            satrec.del1 = 0.0;
1590            satrec.del2 = 0.0;
1591            satrec.del3 = 0.0;
1592            satrec.didt = 0.0;
1593            satrec.dmdt = 0.0;
1594            satrec.dnodt = 0.0;
1595            satrec.domdt = 0.0;
1596            satrec.e3 = 0.0;
1597            satrec.ee2 = 0.0;
1598            satrec.peo = 0.0;
1599            satrec.pgho = 0.0;
1600            satrec.pho = 0.0;
1601            satrec.pinco = 0.0;
1602            satrec.plo = 0.0;
1603            satrec.se2 = 0.0;
1604            satrec.se3 = 0.0;
1605            satrec.sgh2 = 0.0;
1606            satrec.sgh3 = 0.0;
1607            satrec.sgh4 = 0.0;
1608            satrec.sh2 = 0.0;
1609            satrec.sh3 = 0.0;
1610            satrec.si2 = 0.0;
1611            satrec.si3 = 0.0;
1612            satrec.sl2 = 0.0;
1613            satrec.sl3 = 0.0;
1614            satrec.sl4 = 0.0;
1615            satrec.gsto = 0.0;
1616            satrec.xfact = 0.0;
1617            satrec.xgh2 = 0.0;
1618            satrec.xgh3 = 0.0;
1619            satrec.xgh4 = 0.0;
1620            satrec.xh2 = 0.0;
1621            satrec.xh3 = 0.0;
1622            satrec.xi2 = 0.0;
1623            satrec.xi3 = 0.0;
1624            satrec.xl2 = 0.0;
1625            satrec.xl3 = 0.0;
1626            satrec.xl4 = 0.0;
1627            satrec.xlamo = 0.0;
1628            satrec.zmol = 0.0;
1629            satrec.zmos = 0.0;
1630            satrec.atime = 0.0;
1631            satrec.xli = 0.0;
1632            satrec.xni = 0.0;
1633    
1634            // sgp4fix - note the following variables are also passed directly via satrec.
1635            // it is possible to streamline the sgp4init call by deleting the "x"
1636            // variables, but the user would need to set the satrec.* values first. we
1637            // include the additional assignments in case twoline2rv is not used.
1638            satrec.bstar = xbstar;
1639            satrec.ecco = xecco;
1640            satrec.argpo = xargpo;
1641            satrec.inclo = xinclo;
1642            satrec.mo = xmo;
1643            satrec.no = xno;
1644            satrec.nodeo = xnodeo;
1645    
1646            // sgp4fix add opsmode
1647            satrec.operationmode = opsmode;
1648    
1649            // SEG -- also save gravity constant type
1650            satrec.gravconsttype = whichconst;
1651    
1652            /* ------------------------ earth constants ----------------------- */
1653            // sgp4fix identify constants and allow alternate values
1654            double[] temp5 = getgravconst(whichconst);//, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 );
1655            tumin = temp5[0];
1656            mu = temp5[1];
1657            radiusearthkm = temp5[2];
1658            xke = temp5[3];
1659            j2 = temp5[4];
1660            j3 = temp5[5];
1661            j4 = temp5[6];
1662            j3oj2 = temp5[7];
1663    
1664            ss = 78.0 / radiusearthkm + 1.0;
1665            qzms2t = Math.pow(((120.0 - 78.0) / radiusearthkm), 4);
1666            x2o3 = 2.0 / 3.0;
1667    
1668            satrec.init = 'y';
1669            satrec.t = 0.0;
1670    
1671            double[] ttemp = initl(satn, whichconst, satrec.ecco, epoch, satrec.inclo, satrec);
1672            ainv = ttemp[0];
1673            ao = ttemp[1];
1674            con42 = ttemp[2];
1675            cosio = ttemp[3];
1676            cosio2 = ttemp[4];
1677            eccsq = ttemp[5];
1678            omeosq = ttemp[6];
1679            posq = ttemp[7];
1680            rp = ttemp[8];
1681            rteosq = ttemp[9];
1682            sinio = ttemp[10];
1683    
1684            satrec.error = 0;
1685    
1686            // sgp4fix remove this check as it is unnecessary
1687            // the mrt check in sgp4 handles decaying satellite cases even if the starting
1688            // condition is below the surface of te earth
1689    //     if (rp < 1.0)
1690    //       {
1691    //         printf("# *** satn%d epoch elts sub-orbital ***\n", satn);
1692    //         satrec.error = 5;
1693    //       }
1694    
1695            if((omeosq >= 0.0) || (satrec.no >= 0.0))
1696            {
1697                satrec.isimp = 0;
1698                if(rp < (220.0 / radiusearthkm + 1.0))
1699                {
1700                    satrec.isimp = 1;
1701                }
1702                sfour = ss;
1703                qzms24 = qzms2t;
1704                perige = (rp - 1.0) * radiusearthkm;
1705    
1706                /* - for perigees below 156 km, s and qoms2t are altered - */
1707                if(perige < 156.0)
1708                {
1709                    sfour = perige - 78.0;
1710                    if(perige < 98.0)
1711                    {
1712                        sfour = 20.0;
1713                    }
1714                    qzms24 = Math.pow(((120.0 - sfour) / radiusearthkm), 4.0);
1715                    sfour = sfour / radiusearthkm + 1.0;
1716                }
1717                pinvsq = 1.0 / posq;
1718    
1719                tsi = 1.0 / (ao - sfour);
1720                satrec.eta = ao * satrec.ecco * tsi;
1721                etasq = satrec.eta * satrec.eta;
1722                eeta = satrec.ecco * satrec.eta;
1723                psisq = Math.abs(1.0 - etasq);
1724                coef = qzms24 * Math.pow(tsi, 4.0);
1725                coef1 = coef / Math.pow(psisq, 3.5);
1726                cc2 = coef1 * satrec.no * (ao * (1.0 + 1.5 * etasq + eeta *
1727                        (4.0 + etasq)) + 0.375 * j2 * tsi / psisq * satrec.con41 *
1728                        (8.0 + 3.0 * etasq * (8.0 + etasq)));
1729                satrec.cc1 = satrec.bstar * cc2;
1730                cc3 = 0.0;
1731                if(satrec.ecco > 1.0e-4)
1732                {
1733                    cc3 = -2.0 * coef * tsi * j3oj2 * satrec.no * sinio / satrec.ecco;
1734                }
1735                satrec.x1mth2 = 1.0 - cosio2;
1736                satrec.cc4 = 2.0 * satrec.no * coef1 * ao * omeosq *
1737                        (satrec.eta * (2.0 + 0.5 * etasq) + satrec.ecco *
1738                        (0.5 + 2.0 * etasq) - j2 * tsi / (ao * psisq) *
1739                        (-3.0 * satrec.con41 * (1.0 - 2.0 * eeta + etasq *
1740                        (1.5 - 0.5 * eeta)) + 0.75 * satrec.x1mth2 *
1741                        (2.0 * etasq - eeta * (1.0 + etasq)) * Math.cos(2.0 * satrec.argpo)));
1742                satrec.cc5 = 2.0 * coef1 * ao * omeosq * (1.0 + 2.75 *
1743                        (etasq + eeta) + eeta * etasq);
1744                cosio4 = cosio2 * cosio2;
1745                temp1 = 1.5 * j2 * pinvsq * satrec.no;
1746                temp2 = 0.5 * temp1 * j2 * pinvsq;
1747                temp3 = -0.46875 * j4 * pinvsq * pinvsq * satrec.no;
1748                satrec.mdot = satrec.no + 0.5 * temp1 * rteosq * satrec.con41 + 0.0625 *
1749                        temp2 * rteosq * (13.0 - 78.0 * cosio2 + 137.0 * cosio4);
1750                satrec.argpdot = -0.5 * temp1 * con42 + 0.0625 * temp2 *
1751                        (7.0 - 114.0 * cosio2 + 395.0 * cosio4) +
1752                        temp3 * (3.0 - 36.0 * cosio2 + 49.0 * cosio4);
1753                xhdot1 = -temp1 * cosio;
1754                satrec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * cosio2) +
1755                        2.0 * temp3 * (3.0 - 7.0 * cosio2)) * cosio;
1756                xpidot = satrec.argpdot + satrec.nodedot;
1757                satrec.omgcof = satrec.bstar * cc3 * Math.cos(satrec.argpo);
1758                satrec.xmcof = 0.0;
1759                if(satrec.ecco > 1.0e-4)
1760                {
1761                    satrec.xmcof = -x2o3 * coef * satrec.bstar / eeta;
1762                }
1763                satrec.nodecf = 3.5 * omeosq * xhdot1 * satrec.cc1;
1764                satrec.t2cof = 1.5 * satrec.cc1;
1765                // sgp4fix for divide by zero with xinco = 180 deg
1766                if(Math.abs(cosio + 1.0) > 1.5e-12)
1767                {
1768                    satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / (1.0 + cosio);
1769                }
1770                else
1771                {
1772                    satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / temp4;
1773                }
1774                satrec.aycof = -0.5 * j3oj2 * sinio;
1775                satrec.delmo = Math.pow((1.0 + satrec.eta * Math.cos(satrec.mo)), 3);
1776                satrec.sinmao = Math.sin(satrec.mo);
1777                satrec.x7thm1 = 7.0 * cosio2 - 1.0;
1778    
1779                /* --------------- deep space initialization ------------- */
1780                if((2 * pi / satrec.no) >= 225.0)
1781                {
1782                    satrec.method = 'd';
1783                    satrec.isimp = 1;
1784                    tc = 0.0;
1785                    inclm = satrec.inclo;
1786    
1787                    double[] ttemp2 = dscom(epoch, satrec.ecco, satrec.argpo, tc, satrec.inclo, satrec.nodeo, satrec.no, satrec);
1788                    // save ouput vars
1789                    snodm = ttemp2[0];
1790                    cnodm = ttemp2[1];
1791                    sinim = ttemp2[2];
1792                    cosim = ttemp2[3];
1793                    sinomm = ttemp2[4];
1794                    cosomm = ttemp2[5];
1795                    day = ttemp2[6];
1796                    em = ttemp2[7];
1797                    emsq = ttemp2[8];
1798                    gam = ttemp2[9];
1799                    rtemsq = ttemp2[10];
1800                    s1 = ttemp2[11];
1801                    s2 = ttemp2[12];
1802                    s3 = ttemp2[13];
1803                    s4 = ttemp2[14];
1804                    s5 = ttemp2[15];
1805                    s6 = ttemp2[16];
1806                    s7 = ttemp2[17];
1807                    ss1 = ttemp2[18];
1808                    ss2 = ttemp2[19];
1809                    ss3 = ttemp2[20];
1810                    ss4 = ttemp2[21];
1811                    ss5 = ttemp2[22];
1812                    ss6 = ttemp2[23];
1813                    ss7 = ttemp2[24];
1814                    sz1 = ttemp2[25];
1815                    sz2 = ttemp2[26];
1816                    sz3 = ttemp2[27];
1817                    sz11 = ttemp2[28];
1818                    sz12 = ttemp2[29];
1819                    sz13 = ttemp2[30];
1820                    sz21 = ttemp2[31];
1821                    sz22 = ttemp2[32];
1822                    sz23 = ttemp2[33];
1823                    sz31 = ttemp2[34];
1824                    sz32 = ttemp2[35];
1825                    sz33 = ttemp2[36];
1826                    nm = ttemp2[37];
1827                    z1 = ttemp2[38];
1828                    z2 = ttemp2[39];
1829                    z3 = ttemp2[40];
1830                    z11 = ttemp2[41];
1831                    z12 = ttemp2[42];
1832                    z13 = ttemp2[43];
1833                    z21 = ttemp2[44];
1834                    z22 = ttemp2[45];
1835                    z23 = ttemp2[46];
1836                    z31 = ttemp2[47];
1837                    z32 = ttemp2[48];
1838                    z33 = ttemp2[49];
1839    
1840                    //dpper(satrec);
1841                    ttemp2 = dpper(
1842                            satrec.e3, satrec.ee2, satrec.peo, satrec.pgho,
1843                            satrec.pho, satrec.pinco, satrec.plo, satrec.se2,
1844                            satrec.se3, satrec.sgh2, satrec.sgh3, satrec.sgh4,
1845                            satrec.sh2, satrec.sh3, satrec.si2, satrec.si3,
1846                            satrec.sl2, satrec.sl3, satrec.sl4, satrec.t,
1847                            satrec.xgh2, satrec.xgh3, satrec.xgh4, satrec.xh2,
1848                            satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2,
1849                            satrec.xl3, satrec.xl4, satrec.zmol, satrec.zmos, inclm, satrec.init,
1850                            satrec.ecco, satrec.inclo, satrec.nodeo, satrec.argpo, satrec.mo,
1851                            satrec.operationmode);
1852                    satrec.ecco = ttemp2[0];
1853                    satrec.inclo = ttemp2[1];
1854                    satrec.nodeo = ttemp2[2];
1855                    satrec.argpo = ttemp2[3];
1856                    satrec.mo = ttemp2[4];
1857    
1858                    argpm = 0.0;
1859                    nodem = 0.0;
1860                    mm = 0.0;
1861    
1862                    double[] ttemp3 = dsinit(whichconst,
1863                            cosim, emsq, satrec.argpo, s1, s2, s3, s4, s5, sinim, ss1, ss2, ss3, ss4,
1864                            ss5, sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33, satrec.t, tc,
1865                            satrec.gsto, satrec.mo, satrec.mdot, satrec.no, satrec.nodeo,
1866                            satrec.nodedot, xpidot, z1, z3, z11, z13, z21, z23, z31, z33,
1867                            satrec.ecco, eccsq,
1868                            satrec,
1869                            em, argpm, inclm, mm, nm, nodem);
1870                    em = ttemp3[0];
1871                    argpm = ttemp3[1];
1872                    inclm = ttemp3[2];
1873                    mm = ttemp3[3];
1874                    nm = ttemp3[4];
1875                    nodem = ttemp3[5];
1876                    dndt = ttemp3[6];
1877                }
1878    
1879                /* ----------- set variables if not deep space ----------- */
1880                if(satrec.isimp != 1)
1881                {
1882                    cc1sq = satrec.cc1 * satrec.cc1;
1883                    satrec.d2 = 4.0 * ao * tsi * cc1sq;
1884                    temp = satrec.d2 * tsi * satrec.cc1 / 3.0;
1885                    satrec.d3 = (17.0 * ao + sfour) * temp;
1886                    satrec.d4 = 0.5 * temp * ao * tsi * (221.0 * ao + 31.0 * sfour) *
1887                            satrec.cc1;
1888                    satrec.t3cof = satrec.d2 + 2.0 * cc1sq;
1889                    satrec.t4cof = 0.25 * (3.0 * satrec.d3 + satrec.cc1 *
1890                            (12.0 * satrec.d2 + 10.0 * cc1sq));
1891                    satrec.t5cof = 0.2 * (3.0 * satrec.d4 +
1892                            12.0 * satrec.cc1 * satrec.d3 +
1893                            6.0 * satrec.d2 * satrec.d2 +
1894                            15.0 * cc1sq * (2.0 * satrec.d2 + cc1sq));
1895                }
1896            } // if omeosq = 0 ...
1897    
1898            /* finally propogate to zero epoch to initialize all others. */
1899            // sgp4fix take out check to let satellites process until they are actually below earth surface
1900    //       if(satrec.error == 0)
1901            boolean sgp4Error = sgp4(satrec, 0.0, r, v);  // SEG removed gravity constant passing
1902    
1903            satrec.init = 'n';
1904    
1905    //#include "debug6.cpp"
1906            //sgp4fix return boolean. satrec.error contains any error codes
1907            return sgp4Error;
1908        }  // end sgp4init
1909    
1910    
1911    
1912        /**
1913         * Similar to sgp4(..) but time parameter is the Julian Date to the propagated to.
1914         * This method was not orgiinally in the CSSI C++ version.
1915         * @param satrec satellite SGP4 data object
1916         * @param jd Julian Date
1917         * @param r position vector [km] return array (needs to be of size 3)
1918         * @param v velocity [km/sec] return array (needs to be of size 3)
1919         * @return
1920         */
1921        public static boolean sgp4Prop2JD(SGP4SatData satrec, double jd, double[] r, double[] v)
1922        {
1923            double tminSinceEpoch = (jd - satrec.jdsatepoch)*24.0*60.0;
1924            return sgp4(satrec, tminSinceEpoch,r, v);
1925        }
1926    
1927        /*-----------------------------------------------------------------------------
1928         *
1929         *                             procedure sgp4
1930         *
1931         *  this procedure is the sgp4 prediction model from space command. this is an
1932         *    updated and combined version of sgp4 and sdp4, which were originally
1933         *    published separately in spacetrack report #3. this version follows the
1934         *    methodology from the aiaa paper (2006) describing the history and
1935         *    development of the code.
1936         *
1937         *  author        : david vallado                  719-573-2600   28 jun 2005
1938         *
1939         *  inputs        :
1940         *    satrec         - initialised structure from sgp4init() call.
1941         *    tsince         - time eince epoch (minutes)
1942         *
1943         *  outputs       :
1944         *    r           - position vector                     km
1945         *    v           - velocity                            km/sec
1946         *  return code - non-zero on error.
1947         *                   1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er
1948         *                   2 - mean motion less than 0.0
1949         *                   3 - pert elements, ecc < 0.0  or  ecc > 1.0
1950         *                   4 - semi-latus rectum < 0.0
1951         *                   5 - epoch elements are sub-orbital
1952         *                   6 - satellite has decayed
1953         *
1954         *  locals        :
1955         *    am          -
1956         *    axnl, aynl        -
1957         *    betal       -
1958         *    cosim   , sinim   , cosomm  , sinomm  , cnod    , snod    , cos2u   ,
1959         *    sin2u   , coseo1  , sineo1  , cosi    , sini    , cosip   , sinip   ,
1960         *    cosisq  , cossu   , sinsu   , cosu    , sinu
1961         *    delm        -
1962         *    delomg      -
1963         *    dndt        -
1964         *    eccm        -
1965         *    emsq        -
1966         *    ecose       -
1967         *    el2         -
1968         *    eo1         -
1969         *    eccp        -
1970         *    esine       -
1971         *    argpm       -
1972         *    argpp       -
1973         *    omgadf      -
1974         *    pl          -
1975         *    r           -
1976         *    rtemsq      -
1977         *    rdotl       -
1978         *    rl          -
1979         *    rvdot       -
1980         *    rvdotl      -
1981         *    su          -
1982         *    t2  , t3   , t4    , tc
1983         *    tem5, temp , temp1 , temp2  , tempa  , tempe  , templ
1984         *    u   , ux   , uy    , uz     , vx     , vy     , vz
1985         *    inclm       - inclination
1986         *    mm          - mean anomaly
1987         *    nm          - mean motion
1988         *    nodem       - right asc of ascending node
1989         *    xinc        -
1990         *    xincp       -
1991         *    xl          -
1992         *    xlm         -
1993         *    mp          -
1994         *    xmdf        -
1995         *    xmx         -
1996         *    xmy         -
1997         *    nodedf      -
1998         *    xnode       -
1999         *    nodep       -
2000         *    np          -
2001         *
2002         *  coupling      :
2003         *    getgravconst-
2004         *    dpper
2005         *    dpspace
2006         *
2007         *  references    :
2008         *    hoots, roehrich, norad spacetrack report #3 1980
2009         *    hoots, norad spacetrack report #6 1986
2010         *    hoots, schumacher and glover 2004
2011         *    vallado, crawford, hujsak, kelso  2006
2012         *  ----------------------------------------------------------------------------
2013         *
2014         * @param satrec satelite sgp4 data object
2015         * @param tsince time eince epoch (minutes)
2016         * @param r position vector [km] return array (needs to be of size 3)
2017         * @param v velocity [km/sec] return array (needs to be of size 3)
2018         * @return true if there were no errors, see satrec.error for error code
2019         */
2020        public static boolean sgp4(
2021                //Gravconsttype whichconst, // SEG removed as it should already be saved into satrec
2022                SGP4SatData satrec, double tsince,
2023                double[] r, double[] v)
2024        {
2025            double am, axnl, aynl, betal, cosim, cnod,
2026                    cos2u, coseo1 = 0, cosi, cosip, cosisq, cossu, cosu,
2027                    delm, delomg, em, emsq, ecose, el2, eo1,
2028                    ep, esine, argpm, argpp, argpdf, pl, mrt = 0.0,
2029                    mvt, rdotl, rl, rvdot, rvdotl, sinim,
2030                    sin2u, sineo1 = 0, sini, sinip, sinsu, sinu,
2031                    snod, su, t2, t3, t4, tem5, temp,
2032                    temp1, temp2, tempa, tempe, templ, u, ux,
2033                    uy, uz, vx, vy, vz, inclm, mm,
2034                    nm, nodem, xinc, xincp, xl, xlm, mp,
2035                    xmdf, xmx, xmy, nodedf, xnode, nodep, tc, dndt,
2036                    twopi, x2o3, j2, j3, tumin, j4, xke, j3oj2, radiusearthkm,
2037                    mu, vkmpersec;
2038            int ktr;
2039    
2040            /* ------------------ set mathematical constants --------------- */
2041            // sgp4fix divisor for divide by zero check on inclination
2042            // the old check used 1.0 + cos(pi-1.0e-9), but then compared it to
2043            // 1.5 e-12, so the threshold was changed to 1.5e-12 for consistency
2044            final double temp4 = 1.5e-12;
2045            twopi = 2.0 * pi;
2046            x2o3 = 2.0 / 3.0;
2047            // sgp4fix identify constants and allow alternate values
2048            double[] temp5 = getgravconst(satrec.gravconsttype);//, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 );
2049            tumin = temp5[0];
2050            mu = temp5[1];
2051            radiusearthkm = temp5[2];
2052            xke = temp5[3];
2053            j2 = temp5[4];
2054            j3 = temp5[5];
2055            j4 = temp5[6];
2056            j3oj2 = temp5[7];
2057    
2058            vkmpersec = radiusearthkm * xke / 60.0;
2059    
2060            /* --------------------- clear sgp4 error flag ----------------- */
2061            satrec.t = tsince;
2062            satrec.error = 0;
2063    
2064            /* ------- update for secular gravity and atmospheric drag ----- */
2065            xmdf = satrec.mo + satrec.mdot * satrec.t;
2066            argpdf = satrec.argpo + satrec.argpdot * satrec.t;
2067            nodedf = satrec.nodeo + satrec.nodedot * satrec.t;
2068            argpm = argpdf;
2069            mm = xmdf;
2070            t2 = satrec.t * satrec.t;
2071            nodem = nodedf + satrec.nodecf * t2;
2072            tempa = 1.0 - satrec.cc1 * satrec.t;
2073            tempe = satrec.bstar * satrec.cc4 * satrec.t;
2074            templ = satrec.t2cof * t2;
2075    
2076            if(satrec.isimp != 1)
2077            {
2078                delomg = satrec.omgcof * satrec.t;
2079                delm = satrec.xmcof *
2080                        (Math.pow((1.0 + satrec.eta * Math.cos(xmdf)), 3) -
2081                        satrec.delmo);
2082                temp = delomg + delm;
2083                mm = xmdf + temp;
2084                argpm = argpdf - temp;
2085                t3 = t2 * satrec.t;
2086                t4 = t3 * satrec.t;
2087                tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 -
2088                        satrec.d4 * t4;
2089                tempe = tempe + satrec.bstar * satrec.cc5 * (Math.sin(mm) -
2090                        satrec.sinmao);
2091                templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof +
2092                        satrec.t * satrec.t5cof);
2093            }
2094    
2095            nm = satrec.no;
2096            em = satrec.ecco;
2097            inclm = satrec.inclo;
2098            if(satrec.method == 'd')
2099            {
2100                tc = satrec.t;
2101                double[] ttemp = dspace(
2102                        satrec.irez,
2103                        satrec.d2201, satrec.d2211, satrec.d3210,
2104                        satrec.d3222, satrec.d4410, satrec.d4422,
2105                        satrec.d5220, satrec.d5232, satrec.d5421,
2106                        satrec.d5433, satrec.dedt, satrec.del1,
2107                        satrec.del2, satrec.del3, satrec.didt,
2108                        satrec.dmdt, satrec.dnodt, satrec.domdt,
2109                        satrec.argpo, satrec.argpdot, satrec.t, tc,
2110                        satrec.gsto, satrec.xfact, satrec.xlamo,
2111                        satrec.no,
2112                        em, argpm, inclm, mm, nodem,
2113                        satrec,
2114                        nm);
2115                // copy variables back
2116                em = ttemp[0];
2117                argpm = ttemp[1];
2118                inclm = ttemp[2];
2119                mm = ttemp[3];
2120                nodem = ttemp[4];
2121                dndt = ttemp[5];
2122                nm = ttemp[6];
2123    
2124            } // if method = d
2125    
2126            if(nm <= 0.0)
2127            {
2128    //         printf("# error nm %f\n", nm);
2129                satrec.error = 2;
2130                // sgp4fix add return
2131                return false;
2132            }
2133            am = Math.pow((xke / nm), x2o3) * tempa * tempa;
2134            nm = xke / Math.pow(am, 1.5);
2135            em = em - tempe;
2136    
2137            // fix tolerance for error recognition
2138            // sgp4fix am is fixed from the previous nm check
2139            if((em >= 1.0) || (em < -0.001)/* || (am < 0.95)*/)
2140            {
2141    //         printf("# error em %f\n", em);
2142                satrec.error = 1;
2143                // sgp4fix to return if there is an error in eccentricity
2144                return false;
2145            }
2146            // sgp4fix fix tolerance to avoid a divide by zero
2147            if(em < 1.0e-6)
2148            {
2149                em = 1.0e-6;
2150            }
2151            mm = mm + satrec.no * templ;
2152            xlm = mm + argpm + nodem;
2153            emsq = em * em;
2154            temp = 1.0 - emsq;
2155    
2156            nodem = (nodem % twopi);
2157            argpm = (argpm % twopi);
2158            xlm = (xlm % twopi);
2159            mm = ((xlm - argpm - nodem) % twopi);
2160    
2161            /* ----------------- compute extra mean quantities ------------- */
2162            sinim = Math.sin(inclm);
2163            cosim = Math.cos(inclm);
2164    
2165            /* -------------------- add lunar-solar periodics -------------- */
2166            ep = em;
2167            xincp = inclm;
2168            argpp = argpm;
2169            nodep = nodem;
2170            mp = mm;
2171            sinip = sinim;
2172            cosip = cosim;
2173            if(satrec.method == 'd')
2174            {
2175                //dpper(satrec);
2176                double[] ttemp = dpper(
2177                        satrec.e3, satrec.ee2, satrec.peo,
2178                        satrec.pgho, satrec.pho, satrec.pinco,
2179                        satrec.plo, satrec.se2, satrec.se3,
2180                        satrec.sgh2, satrec.sgh3, satrec.sgh4,
2181                        satrec.sh2, satrec.sh3, satrec.si2,
2182                        satrec.si3, satrec.sl2, satrec.sl3,
2183                        satrec.sl4, satrec.t, satrec.xgh2,
2184                        satrec.xgh3, satrec.xgh4, satrec.xh2,
2185                        satrec.xh3, satrec.xi2, satrec.xi3,
2186                        satrec.xl2, satrec.xl3, satrec.xl4,
2187                        satrec.zmol, satrec.zmos, satrec.inclo,
2188                        'n', ep, xincp, nodep, argpp, mp, satrec.operationmode);
2189                ep = ttemp[0];
2190                xincp = ttemp[1];
2191                nodep = ttemp[2];
2192                argpp = ttemp[3];
2193                mp = ttemp[4];
2194    
2195                if(xincp < 0.0)
2196                {
2197                    xincp = -xincp;
2198                    nodep = nodep + pi;
2199                    argpp = argpp - pi;
2200                }
2201                if((ep < 0.0) || (ep > 1.0))
2202                {
2203    //            printf("# error ep %f\n", ep);
2204                    satrec.error = 3;
2205                    // sgp4fix add return
2206                    return false;
2207                }
2208            } // if method = d
2209    
2210            /* -------------------- long period periodics ------------------ */
2211            if(satrec.method == 'd')
2212            {
2213                sinip = Math.sin(xincp);
2214                cosip = Math.cos(xincp);
2215                satrec.aycof = -0.5 * j3oj2 * sinip;
2216                // sgp4fix for divide by zero for xincp = 180 deg
2217                if(Math.abs(cosip + 1.0) > 1.5e-12)
2218                {
2219                    satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip);
2220                }
2221                else
2222                {
2223                    satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4;
2224                }
2225            }
2226            axnl = ep * Math.cos(argpp);
2227            temp = 1.0 / (am * (1.0 - ep * ep));
2228            aynl = ep * Math.sin(argpp) + temp * satrec.aycof;
2229            xl = mp + argpp + nodep + temp * satrec.xlcof * axnl;
2230    
2231            /* --------------------- solve kepler's equation --------------- */
2232            u = ((xl - nodep) % twopi);
2233            eo1 = u;
2234            tem5 = 9999.9;
2235            ktr = 1;
2236            //   sgp4fix for kepler iteration
2237            //   the following iteration needs better limits on corrections
2238            while((Math.abs(tem5) >= 1.0e-12) && (ktr <= 10))
2239            {
2240                sineo1 = Math.sin(eo1);
2241                coseo1 = Math.cos(eo1);
2242                tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl;
2243                tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5;
2244                if(Math.abs(tem5) >= 0.95)
2245                {
2246                    tem5 = tem5 > 0.0 ? 0.95 : -0.95;
2247                }
2248                eo1 = eo1 + tem5;
2249                ktr = ktr + 1;
2250            }
2251    
2252            /* ------------- short period preliminary quantities ----------- */
2253            ecose = axnl * coseo1 + aynl * sineo1;
2254            esine = axnl * sineo1 - aynl * coseo1;
2255            el2 = axnl * axnl + aynl * aynl;
2256            pl = am * (1.0 - el2);
2257            if(pl < 0.0)
2258            {
2259    //         printf("# error pl %f\n", pl);
2260                satrec.error = 4;
2261                // sgp4fix add return
2262                return false;
2263            }
2264            else
2265            {
2266                rl = am * (1.0 - ecose);
2267                rdotl = Math.sqrt(am) * esine / rl;
2268                rvdotl = Math.sqrt(pl) / rl;
2269                betal = Math.sqrt(1.0 - el2);
2270                temp = esine / (1.0 + betal);
2271                sinu = am / rl * (sineo1 - aynl - axnl * temp);
2272                cosu = am / rl * (coseo1 - axnl + aynl * temp);
2273                su = Math.atan2(sinu, cosu);
2274                sin2u = (cosu + cosu) * sinu;
2275                cos2u = 1.0 - 2.0 * sinu * sinu;
2276                temp = 1.0 / pl;
2277                temp1 = 0.5 * j2 * temp;
2278                temp2 = temp1 * temp;
2279    
2280                /* -------------- update for short period periodics ------------ */
2281                if(satrec.method == 'd')
2282                {
2283                    cosisq = cosip * cosip;
2284                    satrec.con41 = 3.0 * cosisq - 1.0;
2285                    satrec.x1mth2 = 1.0 - cosisq;
2286                    satrec.x7thm1 = 7.0 * cosisq - 1.0;
2287                }
2288                mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) +
2289                        0.5 * temp1 * satrec.x1mth2 * cos2u;
2290                su = su - 0.25 * temp2 * satrec.x7thm1 * sin2u;
2291                xnode = nodep + 1.5 * temp2 * cosip * sin2u;
2292                xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u;
2293                mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / xke;
2294                rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u +
2295                        1.5 * satrec.con41) / xke;
2296    
2297                /* --------------------- orientation vectors ------------------- */
2298                sinsu = Math.sin(su);
2299                cossu = Math.cos(su);
2300                snod = Math.sin(xnode);
2301                cnod = Math.cos(xnode);
2302                sini = Math.sin(xinc);
2303                cosi = Math.cos(xinc);
2304                xmx = -snod * cosi;
2305                xmy = cnod * cosi;
2306                ux = xmx * sinsu + cnod * cossu;
2307                uy = xmy * sinsu + snod * cossu;
2308                uz = sini * sinsu;
2309                vx = xmx * cossu - cnod * sinsu;
2310                vy = xmy * cossu - snod * sinsu;
2311                vz = sini * cossu;
2312    
2313                /* --------- position and velocity (in km and km/sec) ---------- */
2314                r[0] = (mrt * ux) * radiusearthkm;
2315                r[1] = (mrt * uy) * radiusearthkm;
2316                r[2] = (mrt * uz) * radiusearthkm;
2317                v[0] = (mvt * ux + rvdot * vx) * vkmpersec;
2318                v[1] = (mvt * uy + rvdot * vy) * vkmpersec;
2319                v[2] = (mvt * uz + rvdot * vz) * vkmpersec;
2320            }  // if pl > 0
2321    
2322            // sgp4fix for decaying satellites
2323            if(mrt < 1.0)
2324            {
2325    //         printf("# decay condition %11.6f \n",mrt);
2326                satrec.error = 6;
2327                return false;
2328            }
2329    
2330    //#include "debug7.cpp"
2331            return true;
2332        }  // end sgp4
2333    
2334        /** -----------------------------------------------------------------------------
2335         *
2336         *                           function gstime
2337         *
2338         *  this function finds the greenwich sidereal time.
2339         *
2340         *  author        : david vallado                  719-573-2600    1 mar 2001
2341         *
2342         *  inputs          description                    range / units
2343         *    jdut1       - julian date in ut1             days from 4713 bc
2344         *
2345         *  outputs       :
2346         *    gstime      - greenwich sidereal time        0 to 2pi rad
2347         *
2348         *  locals        :
2349         *    temp        - temporary variable for doubles   rad
2350         *    tut1        - julian centuries from the
2351         *                  jan 1, 2000 12 h epoch (ut1)
2352         *
2353         *  coupling      :
2354         *    none
2355         *
2356         *  references    :
2357         *    vallado       2004, 191, eq 3-45
2358         * ---------------------------------------------------------------------------
2359         * @param jdut1
2360         * @return
2361         */
2362        public static double gstime(double jdut1)
2363        {
2364            final double twopi = 2.0 * pi;
2365            final double deg2rad = pi / 180.0;
2366            double temp, tut1;
2367    
2368            tut1 = (jdut1 - 2451545.0) / 36525.0;
2369            temp = -6.2e-6 * tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 +
2370                    (876600.0 * 3600 + 8640184.812866) * tut1 + 67310.54841;  // sec
2371            temp = ((temp * deg2rad / 240.0) % twopi); //360/86400 = 1/240, to deg, to rad
2372    
2373            // ------------------------ check quadrants ---------------------
2374            if(temp < 0.0)
2375            {
2376                temp += twopi;
2377            }
2378    
2379            return temp;
2380        }  // end gstime
2381    
2382        /* -----------------------------------------------------------------------------
2383         *
2384         *                           function getgravconst
2385         *
2386         *  this function gets constants for the propagator. note that mu is identified to
2387         *    facilitiate comparisons with newer models. the common useage is wgs72.
2388         *
2389         *  author        : david vallado                  719-573-2600   21 jul 2006
2390         *
2391         *  inputs        :
2392         *    whichconst  - which set of constants to use  wgs72old, wgs72, wgs84
2393         *
2394         *  outputs       :
2395         *    tumin       - minutes in one time unit
2396         *    mu          - earth gravitational parameter
2397         *    radiusearthkm - radius of the earth in km
2398         *    xke         - reciprocal of tumin
2399         *    j2, j3, j4  - un-normalized zonal harmonic values
2400         *    j3oj2       - j3 divided by j2
2401         *
2402         *  locals        :
2403         *
2404         *  coupling      :
2405         *    none
2406         *
2407         *  references    :
2408         *    norad spacetrack report #3
2409         *    vallado, crawford, hujsak, kelso  2006
2410        ---------------------------------------------------------------------------
2411         * @param whichconst
2412         * @return [tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2]
2413         */
2414        public static double[] getgravconst(
2415                Gravconsttype whichconst //      double& tumin,
2416                //      double& mu,
2417                //      double& radiusearthkm,
2418                //      double& xke,
2419                //      double& j2,
2420                //      double& j3,
2421                //      double& j4,
2422                //      double& j3oj2
2423                )
2424        {
2425    
2426            // return values
2427            double tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2;
2428    
2429            switch(whichconst)
2430            {
2431                // -- wgs-72 low precision str#3 constants --
2432                case wgs72old:
2433                    mu = 398600.79964;        // in km3 / s2
2434                    radiusearthkm = 6378.135;     // km
2435                    xke = 0.0743669161;
2436                    tumin = 1.0 / xke;
2437                    j2 = 0.001082616;
2438                    j3 = -0.00000253881;
2439                    j4 = -0.00000165597;
2440                    j3oj2 = j3 / j2;
2441                    break;
2442                // ------------ wgs-72 constants ------------
2443                case wgs72:
2444                    mu = 398600.8;            // in km3 / s2
2445                    radiusearthkm = 6378.135;     // km
2446                    xke = 60.0 / Math.sqrt(radiusearthkm * radiusearthkm * radiusearthkm / mu);
2447                    tumin = 1.0 / xke;
2448                    j2 = 0.001082616;
2449                    j3 = -0.00000253881;
2450                    j4 = -0.00000165597;
2451                    j3oj2 = j3 / j2;
2452                    break;
2453                case wgs84:
2454                    // ------------ wgs-84 constants ------------
2455                    mu = 398600.5;            // in km3 / s2
2456                    radiusearthkm = 6378.137;     // km
2457                    xke = 60.0 / Math.sqrt(radiusearthkm * radiusearthkm * radiusearthkm / mu);
2458                    tumin = 1.0 / xke;
2459                    j2 = 0.00108262998905;
2460                    j3 = -0.00000253215306;
2461                    j4 = -0.00000161098761;
2462                    j3oj2 = j3 / j2;
2463                    break;
2464                default:
2465                    System.out.println("unknown gravity option:" + whichconst + ", using wgs84");
2466                    // MODIFIED - SHAWN GANO -- Orginal implementation just returned no values!
2467                    // ------------ wgs-84 constants ------------
2468                    mu = 398600.5;            // in km3 / s2
2469                    radiusearthkm = 6378.137;     // km
2470                    xke = 60.0 / Math.sqrt(radiusearthkm * radiusearthkm * radiusearthkm / mu);
2471                    tumin = 1.0 / xke;
2472                    j2 = 0.00108262998905;
2473                    j3 = -0.00000253215306;
2474                    j4 = -0.00000161098761;
2475                    j3oj2 = j3 / j2;
2476                    break;
2477            }
2478    
2479            return new double[]
2480                    {
2481                        tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2
2482                    };
2483    
2484        }   // end getgravconst
2485    } // SGP4unit