home *** CD-ROM | disk | FTP | other *** search
- /* N3EMO Orbit Simulator routines */
-
- /* Copyright (C) 1986 Robert W. Berger
- May be used for non-commercial purposes without prior written permission. */
-
- #include <stdio.h>
- #include <math.h>
-
- #define PI 3.14159265
- #define PI2 (PI*2)
- #define MinutesPerDay (24*60.0)
- #define SecondsPerDay (60*MinutesPerDay)
- #define HalfSecond (0.5/SecondsPerDay)
- #define EarthRadius 6378.16 /* Kilometers */
- #define EarthFlat (1/298.25) /* Earth Flattening Coeff. */
- #define SiderealSolar 1.0027379093
- #define DegreesPerRadian (180/PI)
- #define RadiansPerDegree (PI/180)
- #define ABS(x) ((x) < 0 ? (-(x)) : (x))
- #define SQR(x) ((x)*(x))
-
- #define RefYear 79
- #define RefSidereal 0.27518504
- #define RefDay 0 /* Day of week */
-
- char *MonthNames[] = { "Jan","Feb","Mar","Apr","May","Jun","Jul",
- "Aug","Sep","Oct","Nov","Dec" };
-
- int MonthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31};
-
- char *DayNames[] = { "Sunday","Monday","Tuesday","Wednesday","Thursday",
- "Friday","Saturday"};
-
- /* Solve Kepler's equation */
- /* Inputs: */
- /* MeanAnomaly Time since last perigee, in radians. */
- /* PI2 = one complete orbit. */
- /* Eccentricity Eccentricity of orbit's ellipse. */
- /* Output: */
- /* TrueAnomaly Angle between perigee, geocenter, and */
- /* current position. */
-
- double Kepler(MeanAnomaly,Eccentricity)
- register double MeanAnomaly,Eccentricity;
-
- {
- register double E; /* Eccentric Anomaly */
- register double Error;
- register double TrueAnomaly;
-
- E = MeanAnomaly; /* Initial guess */
- do
- {
- Error = (E - Eccentricity*sin(E) - MeanAnomaly)
- / (1 - Eccentricity*cos(E));
- E -= Error;
- }
- while (ABS(Error) >= 0.000001);
-
- if (ABS(E-PI) < 0.000001)
- TrueAnomaly = PI;
- else
- TrueAnomaly = 2*atan(sqrt((1+Eccentricity)/(1-Eccentricity))
- *tan(E/2));
- if (TrueAnomaly < 0)
- TrueAnomaly += PI2;
-
- return TrueAnomaly;
- }
-
- GetSubSatPoint(EpochTime,EpochRAAN,EpochArgPerigee,Inclination,
- Eccentricity,RAANPrecession,PerigeePrecession,Time,TrueAnomaly,
- Latitude,Longitude)
-
- double EpochTime,EpochRAAN,EpochArgPerigee,Inclination,Eccentricity;
- double RAANPrecession,PerigeePrecession,Time;
- double TrueAnomaly,*Longitude,*Latitude;
- {
- double RAAN,ArgPerigee;
- int i;
-
- ArgPerigee = EpochArgPerigee + (Time-EpochTime)*PerigeePrecession;
-
- *Latitude = asin(sin(Inclination)*sin(ArgPerigee+TrueAnomaly));
-
- RAAN = EpochRAAN - (Time-EpochTime)*RAANPrecession;
-
- *Longitude = -acos(cos(TrueAnomaly+ArgPerigee)/cos(*Latitude));
- if ((Inclination > PI/2 && *Latitude < 0)
- || (Inclination < PI/2 && *Latitude > 0))
- *Longitude = -*Longitude;
- *Longitude += RAAN;
-
- /* Convert from celestial to terrestrial coordinates */
- *Longitude -= PI2*(Time*SiderealSolar + RefSidereal);
-
- /* Make West be positive */
- *Longitude = -*Longitude;
-
- /* i = floor(Longitude/2*pi) */
- i = *Longitude/PI2;
- if(i < 0)
- i--;
-
- *Longitude -= i*PI2;
- }
-
-
- GetPrecession(SemiMajorAxis,Eccentricity,Inclination,
- RAANPrecession,PerigeePrecession)
- double SemiMajorAxis,Eccentricity,Inclination;
- double *RAANPrecession,*PerigeePrecession;
- {
- *RAANPrecession = 9.95*pow(EarthRadius/SemiMajorAxis,3.5) * cos(Inclination)
- / SQR(1-SQR(Eccentricity)) * RadiansPerDegree;
-
- *PerigeePrecession = 4.97*pow(EarthRadius/SemiMajorAxis,3.5)
- * (5*SQR(cos(Inclination))-1)
- / SQR(1-SQR(Eccentricity)) * RadiansPerDegree;
- }
-
- GetBearings(SiteLat,SiteLong,SiteAltitude,
- SatLat,SatLong,Radius,Azimuth,Elevation,Range)
- double SiteLat,SiteLong,SiteAltitude,SatLat,SatLong,Radius;
- double *Azimuth,*Elevation,*Range;
- {
- double SinSiteLat,sinSiteLong,SinSatLat,SinSatLong;
- double CosSiteLat,cosSiteLong,CosSatLat,CosSatLong;
- double CosBeta,SinBeta;
- double LongDiff;
-
- SinSiteLat = sin(SiteLat); sinSiteLong = sin(SiteLong);
- CosSiteLat = cos(SiteLat); cosSiteLong = cos(SiteLong);
- SinSatLat = sin(SatLat); SinSatLong = sin(SatLong);
- CosSatLat = cos(SatLat); CosSatLong = cos(SatLong);
-
- LongDiff = SiteLong - SatLong;
- CosBeta = SinSiteLat*SinSatLat+CosSiteLat*CosSatLat*cos(LongDiff);
- SinBeta = sqrt(1-SQR(CosBeta));
-
- *Azimuth = acos((SinSatLat- SinSiteLat*CosBeta)/CosSiteLat/SinBeta);
-
- if (LongDiff < -PI)
- LongDiff += PI2;
- if (LongDiff > PI)
- LongDiff -= PI2;
-
- if (LongDiff < 0)
- *Azimuth = PI2 - *Azimuth;
-
- /* Convert to geocentric radius */
- SiteAltitude += EarthRadius*(1-EarthFlat/2+EarthFlat/2*cos(2*SiteLat));
-
- *Elevation = atan((Radius*CosBeta-(SiteAltitude))
- /(Radius*SinBeta));
-
- *Range = sqrt(SQR(Radius) + SQR(SiteAltitude)
- -2*Radius*SiteAltitude*CosBeta);
- }
-
-
- SPrintDate(Str,Day)
- char *Str;
- {
- int Month,Year,DayOfWeek;
-
- DayOfWeek = (Day-RefDay) % 7;
-
- Year = RefYear;
-
- while (Day <= 0)
- {
- Year -= 1;
- if (Year%4 == 0)
- Day += 366;
- else
- Day += 365;
- }
-
- while ((Year%4 == 0 && Day > 366) || (Year%4 != 0 && Day > 365))
- {
- if (Year%4 == 0)
- Day -= 366;
- else
- Day -= 365;
- Year += 1;
- }
-
- if (Year%4 == 0)
- MonthDays[1] += 1; /* Leap year */
-
- Month = 0;
- while (Day > MonthDays[Month])
- {
- Day -= MonthDays[Month];
- Month += 1;
- }
-
- sprintf(Str,"%s %d %s %d",DayNames[DayOfWeek],Day,
- MonthNames[Month],Year);
-
- if (Year%4 == 0)
- MonthDays[1] -= 1; /* Leap year */
- }
-
-
- SPrintTime(Str,Time)
- char *Str;
- double Time;
- {
- int day,hours,minutes,seconds;
-
- day = Time;
- Time -= day;
- if (Time < 0)
- Time += 1.0; /* Correct for truncation problems with negatives */
-
- hours = Time*24;
- Time -= hours/24.0;
-
- minutes = Time*MinutesPerDay;
- Time -= minutes/MinutesPerDay;
-
- seconds = Time*SecondsPerDay;
- seconds -= seconds/SecondsPerDay;
-
- sprintf(Str,"%02d%02d:%02d",hours,minutes,seconds);
- }
-
- PrintDate(OutFile,Day)
- FILE *OutFile;
- {
- char str[100];
-
- SPrintDate(str,Day);
- fprintf(OutFile,"%s",str);
- }
-
- PrintTime(OutFile,Time)
- FILE *OutFile;
- double Time;
- {
- char str[100];
-
- SPrintTime(str,Time);
- fprintf(OutFile,"%s",str);
- }
-
-
- /* Get the Day Number for a given date. January 1 of the reference year
- is day 1. Note that the Day Number may be negative, if the sidereal
- reference is in the future. */
-
- double GetDay(Year,Month,Day)
- double Day;
- {
- int TmpYear;
-
- TmpYear = Year;
-
- while (TmpYear > RefYear)
- {
- TmpYear -= 1;
- if (TmpYear%4 == 0)
- Day += 366;
- else
- Day += 365;
- }
-
- while (TmpYear < RefYear)
- {
- if (TmpYear%4 == 0)
- Day -= 366;
- else
- Day -= 365;
- TmpYear += 1;
- }
-
- if (Year%4 == 0)
- MonthDays[1] += 1; /* Leap year */
-
- while (Month > 1)
- {
- Month -= 1;
- Day += MonthDays[Month-1];
- }
-
- if (Year%4 == 0)
- MonthDays[1] -= 1; /* Leap year */
-
- return Day;
- }
-