home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / forum16.lzh / SOFTWARE / C / ORBIT / orbit.c < prev    next >
Text File  |  1990-03-24  |  18KB  |  670 lines

  1. /* Copyright (c) 1986,1987,1988,1989,1990 Robert W. Berger N3EMO
  2.    May be freely distributed, provided this notice remains intact. */
  3.  
  4. /* Change Log
  5.     3/7/1990    v3.7 Make Phase III style phase (0-255) the default.
  6.             Ignore case in satellite names.
  7.  
  8.     12/19/1989    v3.6 Use more direct calculations for dates.
  9.             Calculate a new sidereal time reference for each run.
  10.  
  11.     12/8/1988    v3.5 Allow multiple overlapping modes in "mode.dat".
  12.  
  13.     6/28/1988    v3.4 Cleaned up Eclipse code. Fixed leap year handling
  14.             for centesimal years. Added a heuristic to GetDay to
  15.             allow 2 or 4 digit year specifications.
  16.                   
  17.     1/25/1988    v3.2 Rewrote orbitr.c to improve modularity,
  18.             efficiency, and accuracy. Adopted geocentric
  19.             cartesian coordinates as the standard representation
  20.             for position and velocity. Added direct calculation
  21.              of range-rate for better doppler predections.
  22.  
  23.     12/1/1988    v3.1 Allow spaces in satellite names. Provide
  24.             single character aliases for 62 satellites 
  25.             (up from 26).
  26.  
  27.     4/7/87        v3.0 Added eclipses.
  28.  
  29.     4/1/87        v2.4 Added "Flip" option in site file for
  30.             0-180 elevation support.
  31.  
  32.     3/24/87        v2.3 Adapted for new kepler.dat format.
  33.             Allow beacon frequencies in mode.dat.
  34.             Use decay rate for drag compensation.
  35.  
  36.     5/10/86        v2.2 Added single character aliases for satellite
  37.             names.
  38.  
  39.     4/30/86        v2.1 Print blank line if satellite dips below
  40.             horizon and reappears during same orbit and day
  41.  
  42.     4/29/86        v2.0 Changed GetSatelliteParams() to use AMSAT's
  43.             "kepler.dat" file. Moved schedule to "mode.dat" file.
  44.  
  45.         4/22/86         v1.3  Inserted N8FJB's suggestions for variable naming
  46.                         which maintain 8 character uniqueness.
  47.                         Also removed "include" file orbitr.h, which had two
  48.                         definitions of external functions defined in orbit.c
  49.                 -K3MC 
  50.  
  51.         4/1/86          v1.2  Corrected a scanf conversion to %d for an int
  52.                         type.    -K3MC
  53.  
  54.         3/19/86         v1.1  Changed GetSatelliteParams to not pass NULL
  55.                         to sscanf.
  56.                                                                         */
  57.  
  58. #define DRAG 1
  59.  
  60. #include <stdio.h>
  61. #include <math.h>
  62. #include <ctype.h>
  63.  
  64. extern double Kepler();
  65. extern long GetDayNum();
  66.  
  67. #define LC(c) (isupper(c) ? tolower(c) : (c))
  68.  
  69. #ifndef PI
  70. #define PI 3.14159265
  71. #endif
  72.  
  73. #ifdef PI2
  74. #undef PI2
  75. #endif
  76.  
  77. #define PI2 (PI*2)
  78.  
  79. #define MinutesPerDay (24*60.0)
  80. #define SecondsPerDay (60*MinutesPerDay)
  81. #define HalfSecond (0.5/SecondsPerDay)
  82. #define EarthRadius 6378.16             /* Kilometers           */
  83. #define C 2.997925e5                    /* Kilometers/Second    */
  84. #define TropicalYear 365.24199        /* Mean solar days    */
  85. #define EarthEccentricity 0.016713
  86. #define DegreesPerRadian (180/PI)
  87. #define RadiansPerDegree (PI/180)
  88. #define ABS(x) ((x) < 0 ? (-(x)) : (x))
  89. #define SQR(x) ((x)*(x))
  90.  
  91. #define MaxModes 10
  92. typedef struct {
  93.                 int MinPhase,MaxPhase;
  94.                 char ModeStr[20];
  95.                }  ModeRec;
  96.  
  97. char VersionStr[] = "N3EMO Orbit Simulator  v3.7";
  98.  
  99.     /*  Keplerian Elements and misc. data for the satellite              */
  100.     double  EpochDay;                   /* time of epoch                 */
  101.     double EpochMeanAnomaly;            /* Mean Anomaly at epoch         */
  102.     long EpochOrbitNum;                 /* Integer orbit # of epoch      */
  103.     double EpochRAAN;                   /* RAAN at epoch                 */
  104.     double epochMeanMotion;             /* Revolutions/day               */
  105.     double OrbitalDecay;                /* Revolutions/day^2             */
  106.     double EpochArgPerigee;             /* argument of perigee at epoch  */
  107.     double Eccentricity;
  108.     double Inclination;
  109.     char SatName[100];
  110.     int ElementSet;
  111.     double BeaconFreq;                  /* Mhz, used for doppler calc    */
  112.     double MaxPhase;                    /* Phase units in 1 orbit        */
  113.     double perigeePhase;
  114.     int NumModes;
  115.     ModeRec Modes[MaxModes];
  116.     int PrintApogee;
  117.     int PrintEclipses;
  118.     int Flip;
  119.  
  120.     /* Simulation Parameters */
  121.  
  122.     double StartTime,EndTime, StepTime; /* In Days, 1 = New Year        */
  123.                                         /*      of reference year       */
  124.  
  125.     /* Site Parameters */
  126.     char SiteName[100];
  127.     double SiteLat,SiteLong,SiteAltitude,SiteMinElev;
  128.  
  129.  
  130. /* List the satellites in kepler.dat, and return the number found */
  131. ListSatellites()
  132. {
  133.     char str[100];
  134.     FILE *InFile;
  135.     char satchar;
  136.     int NumSatellites;
  137.  
  138.     printf("Available satellites:\n");
  139.  
  140.     if ((InFile = fopen("kepler.dat","r")) == 0)
  141.         {
  142.     printf("\"kepler.dat\" not found\n");
  143.     exit(-1);
  144.     }
  145.  
  146.     satchar = 'a';
  147.     NumSatellites = 0;
  148.     while (fgets(str,100,InFile))
  149.     if (strncmp(str,"Satellite: ",11) == 0)
  150.         {
  151.         printf("    %c) %s",satchar,&str[11]);
  152.         if (satchar == 'z')
  153.         satchar = 'A';
  154.                else if (satchar == 'Z')
  155.            satchar = '0';
  156.                 else satchar++;
  157.         NumSatellites++;
  158.         }
  159.  
  160.     fclose(InFile);
  161.  
  162.     return NumSatellites;
  163. }
  164.  
  165. /* Match and skip over a string in the input file. Exits on failure. */
  166.  
  167. MatchStr(InFile,FileName,Target)
  168. FILE *InFile;
  169. char *FileName,*Target;
  170. {
  171.     char str[100];
  172.  
  173.     fgets(str,strlen(Target)+1,InFile);
  174.     if (strcmp(Target,str))
  175.        {
  176.        printf("%s: found \"%s\" while expecting \"%s\n\"",FileName,str,Target);
  177.        exit(-1);
  178.        }
  179. }
  180.  
  181. LetterNum(c)
  182. char c;
  183. {
  184.     if (c >= 'a' && c <= 'z')
  185.     return c - 'a' + 1;
  186.       else if (c >= 'A' && c <= 'Z')
  187.        return c - 'A'+ 27;
  188.     else if (c >= '0' && c <= '9')
  189.       return c - '0' + 53;
  190. }
  191.       
  192. /* Case insensitive strncmp */
  193. cstrncmp(str1,str2,l)
  194. char *str1,*str2;
  195. {
  196.     int i;
  197.  
  198.     for (i = 0; i < l; i++)
  199.     if (LC(str1[i]) != LC(str2[i]))
  200.         return 1;
  201.  
  202.     return 0;
  203. }
  204.  
  205.  
  206. cstrcmp(str1,str2)
  207. char *str1,*str2;
  208. {
  209.     int i,l;
  210.  
  211.     l = strlen(str1);
  212.     if (strlen(str2) != l)
  213.     return 1;
  214.  
  215.     for (i = 0; i < l; i++)
  216.     if (LC(str1[i]) != LC(str2[i]))
  217.         return 1;
  218.  
  219.     return 0;
  220. }
  221.  
  222.  
  223. GetSatelliteParams()
  224. {
  225.     FILE *InFile;
  226.     char str[100];
  227.     int EpochYear;
  228.     double EpochHour,EpochMinute,EpochSecond;
  229.     int found;
  230.     int i,NumSatellites;
  231.     char satchar;
  232.  
  233.     NumSatellites = ListSatellites();
  234.  
  235.     found = 0;
  236.  
  237.     while (!found)
  238.     {
  239.     printf("Letter or satellite name :");
  240.     gets(SatName);
  241.  
  242.     if ((InFile = fopen("kepler.dat","r")) == 0)
  243.         {
  244.         printf("kepler.dat not found\n");
  245.         exit(-1);
  246.         }
  247.  
  248.     if (strlen(SatName) == 1)
  249.         {            /* use single character label */
  250.         satchar = SatName[0];
  251.         if (LetterNum(satchar) > NumSatellites)
  252.             {
  253.             printf("'%c' is out of range\n",satchar);
  254.         fclose(InFile);
  255.         continue;
  256.         }
  257.  
  258.         for (i = 1; i <= LetterNum(satchar); i++)
  259.         {
  260.         do  /* find line beginning with "Satellite: " */
  261.             fgets(str,100,InFile);
  262.         while (strncmp(str,"Satellite: ",11) != 0);
  263.         }
  264.         found = 1;
  265.         strncpy(SatName,&str[11],strlen(str)-12);
  266.         }
  267.         
  268.      else 
  269.          {
  270.          while (!found)  /* use satellite name */
  271.                 {
  272.             if (! fgets(str,100,InFile))
  273.                 break;    /* EOF */
  274.  
  275.             if (strncmp(str,"Satellite: ",11) == 0)
  276.            if (cstrncmp(SatName,&str[11],strlen(SatName)) == 0)
  277.             found = 1;
  278.             }
  279.  
  280.         if (!found)
  281.         {
  282.         printf("Satellite %s not found\n",SatName);
  283.         fclose(InFile);
  284.         }
  285.         }
  286.     }
  287.  
  288.     BeaconFreq = 146.0;  /* Default value */
  289.  
  290.     fgets(str,100,InFile);    /* Skip line */
  291.  
  292.     MatchStr(InFile,"kepler.dat","Epoch time:");
  293.     fgets(str,100,InFile);
  294.     sscanf(str,"%lf",&EpochDay);
  295.  
  296.     EpochYear = EpochDay / 1000.0;
  297.     EpochDay -= EpochYear*1000.0;
  298.     EpochDay += GetDayNum(EpochYear,1,0);
  299.     fgets(str,100,InFile);
  300.  
  301.     if (sscanf(str,"Element set: %ld",&ElementSet) == 0)
  302.        {   /* Old style kepler.dat */
  303.        MatchStr(InFile,"kepler.dat","Element set:");
  304.        fgets(str,100,InFile);
  305.        sscanf(str,"%d",&ElementSet);
  306.        }
  307.  
  308.     MatchStr(InFile,"kepler.dat","Inclination:");
  309.     fgets(str,100,InFile);
  310.     sscanf(str,"%lf",&Inclination);
  311.     Inclination *= RadiansPerDegree;
  312.  
  313.     MatchStr(InFile,"kepler.dat","RA of node:");
  314.     fgets(str,100,InFile);
  315.     sscanf(str,"%lf",&EpochRAAN);
  316.     EpochRAAN *= RadiansPerDegree;
  317.  
  318.     MatchStr(InFile,"kepler.dat","Eccentricity:");
  319.     fgets(str,100,InFile);
  320.     sscanf(str,"%lf",&Eccentricity);
  321.  
  322.     MatchStr(InFile,"kepler.dat","Arg of perigee:");
  323.     fgets(str,100,InFile);
  324.     sscanf(str,"%lf",&EpochArgPerigee);
  325.     EpochArgPerigee *= RadiansPerDegree;
  326.  
  327.     MatchStr(InFile,"kepler.dat","Mean anomaly:");
  328.     fgets(str,100,InFile);
  329.     sscanf(str,"%lf",&EpochMeanAnomaly);
  330.     EpochMeanAnomaly *= RadiansPerDegree;
  331.  
  332.     MatchStr(InFile,"kepler.dat","Mean motion:");
  333.     fgets(str,100,InFile);
  334.     sscanf(str,"%lf",&epochMeanMotion);
  335.  
  336.     MatchStr(InFile,"kepler.dat","Decay rate:");
  337.     fgets(str,100,InFile);
  338.     sscanf(str,"%lf",&OrbitalDecay);
  339.  
  340.     MatchStr(InFile,"kepler.dat","Epoch rev:");
  341.     fgets(str,100,InFile);
  342.     sscanf(str,"%ld",&EpochOrbitNum);
  343.  
  344.     while (1)
  345.         {
  346.         if (! fgets(str,100,InFile))
  347.         break;    /* EOF */
  348.         if (strlen(str) <= 2)
  349.             break;  /* Blank line */
  350.         sscanf(str,"Beacon: %lf",&BeaconFreq);
  351.         }
  352.  
  353.     PrintApogee = (Eccentricity >= 0.3);
  354.  
  355.     perigeePhase = 0; MaxPhase = 256; /* Default values */
  356.     NumModes = 0;
  357.  
  358.     if ((InFile = fopen("mode.dat","r")) == 0)
  359.     return;
  360.  
  361.     found = 0;
  362.     while (!found)
  363.         {
  364.     if (! fgets(str,100,InFile))
  365.         break;    /* EOF */
  366.     if (sscanf(str,"Satellite: %s",str) == 1
  367.         && cstrcmp(SatName,str) == 0)
  368.         found = 1;
  369.     }
  370.     
  371.     if (found)
  372.     {
  373.     while (1)
  374.         {
  375.         if (! fgets(str,100,InFile))
  376.         break;    /* EOF */
  377.         if (strlen(str) <= 2)
  378.             break;  /* Blank line */
  379.         sscanf(str,"Beacon: %lf",&BeaconFreq);
  380.         sscanf(str,"Perigee phase: %lf",&perigeePhase);
  381.         sscanf(str,"Max phase: %lf",&MaxPhase);
  382.  
  383.         if (sscanf(str,"Mode: %20s from %d to %d",Modes[NumModes].ModeStr,
  384.         &Modes[NumModes].MinPhase,&Modes[NumModes].MaxPhase) == 3
  385.           && NumModes < MaxModes)
  386.           NumModes++;
  387.         }
  388.     fclose(InFile);
  389.     }
  390. }
  391.  
  392.  
  393. GetSiteParams()
  394. {
  395.     FILE *InFile;
  396.     char name[100],str[100];
  397.  
  398.     printf("Site name :");
  399.     gets(name);
  400.     strcat(name,".sit");
  401.  
  402.     if ((InFile = fopen(name,"r")) == 0)
  403.         {
  404.         printf("%s not found\n",name);
  405.         exit(-1);
  406.         }
  407.  
  408.     fgets(SiteName,100,InFile);
  409.  
  410.     fgets(str,100,InFile);
  411.     sscanf(str,"%lf",&SiteLat);
  412.     SiteLat *= RadiansPerDegree;
  413.  
  414.     fgets(str,100,InFile);
  415.     sscanf(str,"%lf",&SiteLong);
  416.     SiteLong *= RadiansPerDegree;
  417.  
  418.     fgets(str,100,InFile);
  419.     sscanf(str,"%lf",&SiteAltitude);
  420.     SiteAltitude /= 1000;   /* convert to km */
  421.  
  422.     fgets(str,100,InFile);
  423.     sscanf(str,"%lf",&SiteMinElev);
  424.     SiteMinElev *= RadiansPerDegree;
  425.  
  426.     Flip = PrintEclipses = 0;
  427.     while (fgets(str,100,InFile))
  428.     {
  429.     if (strncmp(str,"Flip",4) == 0)
  430.         Flip = 1;
  431.       else if (strncmp(str,"Eclipse",7) == 0)
  432.         PrintEclipses = 1;
  433.        else printf("\"%s\" unknown option: %s",name,str);
  434.     }
  435. }
  436.  
  437. GetSimulationParams()
  438. {
  439.     double hour,duration;
  440.     int Month,Day,Year;
  441.  
  442.     printf("Start date (UTC) (Month Day Year) :");
  443.     scanf("%d%d%d",&Month,&Day,&Year);
  444.  
  445.     StartTime = GetDayNum(Year,Month,Day);
  446.     printf("Starting Hour (UTC) :");
  447.     scanf("%lf",&hour);
  448.     StartTime += hour/24;
  449.  
  450.     printf("Duration (Days) :");
  451.     scanf("%lf",&duration);
  452.     EndTime = StartTime + duration;
  453.  
  454.     printf("Time Step (Minutes) :");
  455.     scanf("%lf",&StepTime);
  456.     StepTime /= MinutesPerDay;
  457. }
  458.  
  459. PrintMode(OutFile,Phase)
  460. FILE *OutFile;
  461. {
  462.     int CurMode;
  463.  
  464.     for (CurMode = 0; CurMode < NumModes; CurMode++)
  465.         if ((Phase >= Modes[CurMode].MinPhase
  466.                 && Phase < Modes[CurMode].MaxPhase)
  467.               || ((Modes[CurMode].MinPhase > Modes[CurMode].MaxPhase)
  468.                   && (Phase >= Modes[CurMode].MinPhase
  469.                         || Phase < Modes[CurMode].MaxPhase)))
  470.             {
  471.             fprintf(OutFile,"%s ",Modes[CurMode].ModeStr);
  472.             }
  473. }
  474.  
  475.  
  476. main()
  477. {
  478.     double ReferenceOrbit;      /* Floating point orbit # at epoch */
  479.     double CurrentTime;         /* In Days                         */
  480.     double CurrentOrbit;
  481.     double AverageMotion,       /* Corrected for drag              */
  482.         CurrentMotion;
  483.     double MeanAnomaly,TrueAnomaly;
  484.     double SemiMajorAxis;
  485.     double Radius;              /* From geocenter                  */
  486.     double SatX,SatY,SatZ;    /* In Right Ascension based system */
  487.     double SatVX,SatVY,SatVZ;   /* Kilometers/second           */
  488.     double SiteX,SiteY,SiteZ;
  489.     double SiteVX,SiteVY;
  490.     double SiteMatrix[3][3];
  491.     double Height;
  492.     double RAANPrecession,PerigeePrecession;
  493.     double SSPLat,SSPLong;
  494.     long OrbitNum,PrevOrbitNum;
  495.     long Day,PrevDay;
  496.     double Azimuth,Elevation,Range;
  497.     double RangeRate,Doppler;
  498.     int Phase;
  499.     char FileName[100];
  500.     FILE *OutFile;
  501.     int DidApogee;
  502.     double TmpTime,PrevTime;
  503.     int PrevVisible;
  504.  
  505.     printf("%s\n",VersionStr);
  506.  
  507.  
  508.     GetSatelliteParams();
  509.     GetSiteParams();
  510.     GetSimulationParams();
  511.  
  512.     InitOrbitRoutines((StartTime+EndTime)/2);
  513.  
  514.     printf("Output file (RETURN for TTY) :");
  515.     gets(FileName);     /* Skip previous RETURN */
  516.     gets(FileName);
  517.  
  518.  
  519.     if (strlen(FileName) > 0)
  520.         {
  521.         if ((OutFile = fopen(FileName,"w")) == 0)
  522.             {
  523.             printf("Can't write to %s\n",FileName);
  524.             exit(-1);
  525.             }
  526.         }
  527.       else OutFile = stdout;
  528.  
  529.     fprintf(OutFile,"%s Element Set %d\n",SatName,ElementSet);
  530.  
  531.     fprintf(OutFile,"%s\n",SiteName);
  532.  
  533.     fprintf(OutFile,"Doppler calculated for freq = %lf MHz\n",BeaconFreq);
  534.  
  535.     SemiMajorAxis = 331.25 * exp(2*log(MinutesPerDay/epochMeanMotion)/3);
  536.     GetPrecession(SemiMajorAxis,Eccentricity,Inclination,&RAANPrecession,
  537.                         &PerigeePrecession);
  538.  
  539.     ReferenceOrbit = EpochMeanAnomaly/PI2 + EpochOrbitNum;
  540.  
  541.     PrevDay = -10000; PrevOrbitNum = -10000;
  542.     PrevTime = StartTime-2*StepTime;
  543.  
  544.     BeaconFreq *= 1E6;          /* Convert to Hz */
  545.  
  546.     DidApogee = 0;
  547.  
  548.     for (CurrentTime = StartTime; CurrentTime <= EndTime;
  549.                 CurrentTime += StepTime)
  550.         {
  551.  
  552.         AverageMotion = epochMeanMotion
  553.        + (CurrentTime-EpochDay)*OrbitalDecay/2;
  554.         CurrentMotion = epochMeanMotion
  555.        + (CurrentTime-EpochDay)*OrbitalDecay;
  556.  
  557.         SemiMajorAxis = 331.25 * exp(2*log(MinutesPerDay/CurrentMotion)/3);
  558.  
  559.         CurrentOrbit = ReferenceOrbit +
  560.                         (CurrentTime-EpochDay)*AverageMotion;
  561.         OrbitNum = CurrentOrbit;
  562.  
  563.         MeanAnomaly = (CurrentOrbit-OrbitNum)*PI2;
  564.  
  565.         TmpTime = CurrentTime;
  566.         if (MeanAnomaly < PI)
  567.             DidApogee = 0;
  568.         if (PrintApogee && !DidApogee && MeanAnomaly > PI)
  569.             {                   /* Calculate Apogee */
  570.             TmpTime -= StepTime;   /* So we pick up later where we left off */
  571.             MeanAnomaly = PI;
  572.             CurrentTime=EpochDay+(OrbitNum-ReferenceOrbit+0.5)/AverageMotion;
  573.             }
  574.  
  575.         TrueAnomaly = Kepler(MeanAnomaly,Eccentricity);
  576.  
  577.     GetSatPosition(EpochDay,EpochRAAN,EpochArgPerigee,SemiMajorAxis,
  578.         Inclination,Eccentricity,RAANPrecession,PerigeePrecession,
  579.         CurrentTime,TrueAnomaly,&SatX,&SatY,&SatZ,&Radius,
  580.         &SatVX,&SatVY,&SatVZ);
  581.  
  582.     GetSitPosition(SiteLat,SiteLong,SiteAltitude,CurrentTime,
  583.         &SiteX,&SiteY,&SiteZ,&SiteVX,&SiteVY,SiteMatrix);
  584.  
  585.  
  586.     GetBearings(SatX,SatY,SatZ,SiteX,SiteY,SiteZ,SiteMatrix,
  587.         &Azimuth,&Elevation);
  588.  
  589.  
  590.         if (Elevation >= SiteMinElev && CurrentTime >= StartTime)
  591.             {
  592.  
  593.             Day = CurrentTime + HalfSecond;
  594.             if (((double) Day) > CurrentTime+HalfSecond)
  595.                 Day -= 1;    /* Correct for truncation of negative values */
  596.  
  597.         if (OrbitNum == PrevOrbitNum && Day == PrevDay && !PrevVisible)
  598.             fprintf(OutFile,"\n");    /* Dipped out of sight; print blank */
  599.  
  600.             if (OrbitNum != PrevOrbitNum || Day != PrevDay)
  601.                 {                       /* Print Header */
  602.         PrintDayOfWeek(OutFile,(long) Day);
  603.         fprintf(OutFile," ");
  604.                 PrintDate(OutFile,(long) Day);
  605.                 fprintf(OutFile,"  ----Orbit # %ld-----\n",OrbitNum);
  606.                 fprintf(OutFile," U.T.C.   Az  El  ");
  607.         if (Flip)
  608.                     fprintf(OutFile," Az'  El' ");
  609.  
  610.         fprintf(OutFile,"Doppler Range");
  611.                 fprintf(OutFile," Height  Lat  Long  Phase(%3.0lf)\n",
  612.                                 MaxPhase);
  613.                 }
  614.             PrevOrbitNum = OrbitNum; PrevDay = Day;
  615.             PrintTime(OutFile,CurrentTime + HalfSecond);
  616.  
  617.             fprintf(OutFile,"  %3.0lf %3.0lf",Azimuth*DegreesPerRadian,
  618.                 Elevation*DegreesPerRadian);
  619.         if (Flip)
  620.         {
  621.         Azimuth += PI;
  622.         if (Azimuth >= PI2)
  623.             Azimuth -= PI2;
  624.         Elevation = PI-Elevation;
  625.         fprintf(OutFile,"  %3.0lf  %3.0lf",Azimuth*DegreesPerRadian,
  626.             Elevation*DegreesPerRadian);
  627.         }
  628.  
  629.           GetRange(SiteX,SiteY,SiteZ,SiteVX,SiteVY,
  630.         SatX,SatY,SatZ,SatVX,SatVY,SatVZ,&Range,&RangeRate);
  631.             Doppler = -BeaconFreq*RangeRate/C;
  632.             fprintf(OutFile,"  %6.0lf %6.0lf",Doppler,Range);
  633.  
  634.         GetSubSatPoint(SatX,SatY,SatZ,CurrentTime,
  635.             &SSPLat,&SSPLong,&Height);
  636.             fprintf(OutFile," %6.0lf  %3.0lf  %4.0lf",
  637.                 Height,SSPLat*DegreesPerRadian,
  638.                 SSPLong*DegreesPerRadian);
  639.  
  640.             Phase = (MeanAnomaly/PI2*MaxPhase + perigeePhase);
  641.             while (Phase < 0)
  642.                 Phase += MaxPhase;
  643.             while (Phase >= MaxPhase)
  644.                 Phase -= MaxPhase;
  645.  
  646.             fprintf(OutFile," %4d  ", Phase);
  647.             PrintMode(OutFile,Phase);
  648.  
  649.             if (PrintApogee && (MeanAnomaly == PI))
  650.                 fprintf(OutFile,"    Apogee");
  651.  
  652.         if (PrintEclipses)
  653.         if (Eclipsed(SatX,SatY,SatZ,Radius,CurrentTime))
  654.             fprintf(OutFile,"  Eclipse");
  655.  
  656.             fprintf(OutFile,"\n");
  657.         PrevVisible = 1;
  658.             }
  659.      else
  660.         PrevVisible = 0;    
  661.         if (PrintApogee && (MeanAnomaly == PI))
  662.             DidApogee = 1;
  663.  
  664.  
  665.         PrevTime = CurrentTime;
  666.         CurrentTime = TmpTime;
  667.         }
  668.     fclose(OutFile);
  669. }
  670.