279 lines
5.7 KiB
C
279 lines
5.7 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <ctype.h>
|
|
#include "sgdp4h.h"
|
|
#include "satutl.h"
|
|
#include <getopt.h>
|
|
|
|
#define R2D 180.0/M_PI
|
|
#define D2R M_PI/180.0
|
|
#define LIM 128
|
|
#define XKMPER 6378.135
|
|
#define XMNPDA 1440.0 /* Minutes per day */
|
|
#define XKE 0.743669161e-1
|
|
|
|
int fgetline (FILE * file, char *s, int lim);
|
|
void mjd2date (double mjd, int *year, int *month, double *day);
|
|
double date2mjd (int year, int month, double day);
|
|
double mjd2doy (double mjd, int *yr);
|
|
void format_tle (orbit_t orb, char *line1, char *line2);
|
|
double modulo (double x, double y);
|
|
|
|
void
|
|
convert (char *line)
|
|
{
|
|
int no, so;
|
|
int year, month, day, hour, min, sec;
|
|
int foy, fom, fod, gap;
|
|
float sma, incl, raan, ecc, argl, argp, a2m, mag, dm;
|
|
double mjd, doy;
|
|
orbit_t orb;
|
|
char line1[70], line2[70], line0[70];
|
|
double e, v;
|
|
float perigee, apogee;
|
|
|
|
dm = 5.0 * log10 (1000.0 / 40000.0);
|
|
|
|
// Read line
|
|
sscanf (line,
|
|
"%4d,%6d,%2d%2d%4d,%2d%2d%4d %2d%2d%2d,%4d,%f,%f,%f,%f,%f,%f,%f,%f",
|
|
&no, &so, &fod, &fom, &foy, &day, &month, &year, &hour, &min, &sec,
|
|
&gap, &sma, &incl, &raan, &ecc, &argl, &argp, &a2m, &mag);
|
|
|
|
// Use date of first observed as a designation
|
|
mjd = date2mjd (foy, fom, fod);
|
|
doy = mjd2doy (mjd, &foy);
|
|
if (foy >= 2000)
|
|
sprintf (orb.desig, "%02d%3.0fA", foy - 2000, doy + 500);
|
|
else
|
|
sprintf (orb.desig, "%02d%3.0fA", foy - 1900, doy + 500);
|
|
|
|
// Find epoch
|
|
mjd =
|
|
date2mjd (year, month, day + hour / 24.0 + min / 1440.0 + sec / 86400.0);
|
|
orb.ep_day = mjd2doy (mjd, &orb.ep_year);
|
|
|
|
// Set values
|
|
orb.satno = no;
|
|
orb.eqinc = incl * D2R;
|
|
orb.argp = argp * D2R;
|
|
orb.ascn = raan * D2R;
|
|
orb.ecc = ecc;
|
|
orb.bstar = 0.0;
|
|
orb.rev = XKE * pow (sma / XKMPER, -1.5) * XMNPDA / (2.0 * M_PI);
|
|
|
|
// Mean anomaly
|
|
v = argl - argp;
|
|
e = 2 * atan (sqrt ((1.0 - ecc) / (1.0 + ecc)) * tan (v * D2R / 2.0));
|
|
orb.mnan = modulo ((e - ecc * sin (e)), 2.0 * M_PI);
|
|
|
|
// Orbit
|
|
perigee = sma * (1.0 - ecc) - XKMPER;
|
|
apogee = sma * (1.0 + ecc) - XKMPER;
|
|
|
|
sprintf (line0,
|
|
"SO %6d %4.1f %7.0fkm x%7.0fkm",
|
|
so, mag + dm, perigee, apogee);
|
|
|
|
// Format line
|
|
format_tle (orb, line1, line2);
|
|
printf ("%s\n%s\n%s\n", line0, line1, line2);
|
|
|
|
return;
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
FILE *file;
|
|
char line[LIM], *fname;
|
|
int arg = 0;
|
|
|
|
// Decode options
|
|
while ((arg = getopt (argc, argv, "f:")) != -1)
|
|
{
|
|
switch (arg)
|
|
{
|
|
|
|
case 'f':
|
|
fname = optarg;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
file = fopen (fname, "r");
|
|
while (fgetline (file, line, LIM) > 0)
|
|
convert (line);
|
|
fclose (file);
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Read a line of maximum length int lim from file FILE into string s
|
|
int
|
|
fgetline (FILE * file, char *s, int lim)
|
|
{
|
|
int c, i = 0;
|
|
|
|
while (--lim > 0 && (c = fgetc (file)) != EOF && c != '\n')
|
|
s[i++] = c;
|
|
if (c == '\n')
|
|
s[i++] = c;
|
|
s[i] = '\0';
|
|
return i;
|
|
}
|
|
|
|
// Compute Date from Julian Day
|
|
void
|
|
mjd2date (double mjd, int *year, int *month, double *day)
|
|
{
|
|
double f, jd;
|
|
int z, alpha, a, b, c, d, e;
|
|
|
|
jd = mjd + 2400000.5;
|
|
jd += 0.5;
|
|
|
|
z = floor (jd);
|
|
f = fmod (jd, 1.);
|
|
|
|
if (z < 2299161)
|
|
a = z;
|
|
else
|
|
{
|
|
alpha = floor ((z - 1867216.25) / 36524.25);
|
|
a = z + 1 + alpha - floor (alpha / 4.);
|
|
}
|
|
b = a + 1524;
|
|
c = floor ((b - 122.1) / 365.25);
|
|
d = floor (365.25 * c);
|
|
e = floor ((b - d) / 30.6001);
|
|
|
|
*day = b - d - floor (30.6001 * e) + f;
|
|
if (e < 14)
|
|
*month = e - 1;
|
|
else
|
|
*month = e - 13;
|
|
|
|
if (*month > 2)
|
|
*year = c - 4716;
|
|
else
|
|
*year = c - 4715;
|
|
|
|
return;
|
|
}
|
|
|
|
// Compute Julian Day from Date
|
|
double
|
|
date2mjd (int year, int month, double day)
|
|
{
|
|
int a, b;
|
|
double jd;
|
|
|
|
if (month < 3)
|
|
{
|
|
year--;
|
|
month += 12;
|
|
}
|
|
|
|
a = floor (year / 100.);
|
|
b = 2. - a + floor (a / 4.);
|
|
|
|
if (year < 1582)
|
|
b = 0;
|
|
if (year == 1582 && month < 10)
|
|
b = 0;
|
|
if (year == 1582 && month == 10 && day <= 4)
|
|
b = 0;
|
|
|
|
jd =
|
|
floor (365.25 * (year + 4716)) + floor (30.6001 * (month + 1)) + day + b -
|
|
1524.5;
|
|
|
|
return jd - 2400000.5;
|
|
}
|
|
|
|
// MJD to DOY
|
|
double
|
|
mjd2doy (double mjd, int *yr)
|
|
{
|
|
int year, month, k = 2;
|
|
double day, doy;
|
|
|
|
mjd2date (mjd, &year, &month, &day);
|
|
|
|
if (year % 4 == 0 && year % 400 != 0)
|
|
k = 1;
|
|
|
|
doy =
|
|
floor (275.0 * month / 9.0) - k * floor ((month + 9.0) / 12.0) + day - 30;
|
|
|
|
*yr = year;
|
|
|
|
return doy;
|
|
}
|
|
|
|
// Format TLE
|
|
void
|
|
format_tle (orbit_t orb, char *line1, char *line2)
|
|
{
|
|
int i, csum;
|
|
char sbstar[] = " 00000-0", bstar[13];
|
|
|
|
// Format Bstar term
|
|
if (fabs (orb.bstar) > 1e-9)
|
|
{
|
|
sprintf (bstar, "%11.4e", 10 * orb.bstar);
|
|
sbstar[0] = bstar[0];
|
|
sbstar[1] = bstar[1];
|
|
sbstar[2] = bstar[3];
|
|
sbstar[3] = bstar[4];
|
|
sbstar[4] = bstar[5];
|
|
sbstar[5] = bstar[6];
|
|
sbstar[6] = bstar[8];
|
|
sbstar[7] = bstar[10];
|
|
sbstar[8] = '\0';
|
|
}
|
|
// Print lines
|
|
sprintf (line1, "1 %05dU %-8s %2d%012.8f .00000000 00000-0 %8s 0 0",
|
|
orb.satno, orb.desig, orb.ep_year - 2000, orb.ep_day, sbstar);
|
|
sprintf (line2, "2 %05d %8.4f %8.4f %07.0f %8.4f %8.4f %11.8f 0",
|
|
orb.satno, DEG (orb.eqinc), DEG (orb.ascn), 1E7 * orb.ecc,
|
|
DEG (orb.argp), DEG (orb.mnan), orb.rev);
|
|
|
|
// Compute checksums
|
|
for (i = 0, csum = 0; i < strlen (line1); i++)
|
|
{
|
|
if (isdigit (line1[i]))
|
|
csum += line1[i] - '0';
|
|
else if (line1[i] == '-')
|
|
csum++;
|
|
}
|
|
sprintf (line1, "%s%d", line1, csum % 10);
|
|
for (i = 0, csum = 0; i < strlen (line2); i++)
|
|
{
|
|
if (isdigit (line2[i]))
|
|
csum += line2[i] - '0';
|
|
else if (line2[i] == '-')
|
|
csum++;
|
|
}
|
|
sprintf (line2, "%s%d", line2, csum % 10);
|
|
|
|
return;
|
|
}
|
|
|
|
// Return x modulo y [0,y)
|
|
double
|
|
modulo (double x, double y)
|
|
{
|
|
x = fmod (x, y);
|
|
if (x < 0.0)
|
|
x += y;
|
|
|
|
return x;
|
|
}
|