home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 1
/
HamRadio.cdr
/
satel
/
orbit23
/
orbitr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-01-28
|
8KB
|
293 lines
/* 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;
}