1
0
Fork 0
sattools/src/sgdp4h.h

496 lines
11 KiB
C

/* > sgdp4h.h
*
*
* (c) Paul Crawford & Andrew Brooks 1994-2019
* University of Dundee
* psc (at) sat.dundee.ac.uk
* arb (at) sat.dundee.ac.uk
*
* Released under the terms of the GNU LGPL V3
* http://www.gnu.org/licenses/lgpl-3.0.html
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* 2.00 psc Sun May 28 1995 - Modified for non-Dundee use.
*
*/
#ifndef _SGDP4H_H
#define _SGDP4H_H
/*
* Set up standard system-dependent names UNIX, LINUX, RISCOS, MSDOS, WIN32
*/
#if defined( unix )
#define UNIX
#if defined( linux ) && !defined( LINUX )
#define LINUX
#endif
#elif defined( __riscos ) && !defined( RISCOS )
#define RISCOS
#elif !defined( MSDOS ) && !defined( WIN32 ) && !defined( __CYGWIN__ )
#define MSDOS
#endif
/*
* Include files
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <memory.h>
#include <time.h>
#include <sys/types.h>
#ifdef UNIX
#include <unistd.h>
#endif
#ifdef SUN4
#include <memory.h>
#endif
#ifdef sun
#include <sys/time.h> /* solaris 7 has struct timeval in here */
#include <sunmath.h> /* for sincos() which is in libsunmath */
#endif
#ifdef linux
#include <stdint.h>
void sincos (double x, double *s, double *c); /* declared where? */
#endif
/*
* ================= SYSTEM SPECIFIC DEFINITIONS =====================
*/
/* Use INLINE keyword when declaring inline functions */
#ifdef WIN32
#define INLINE __inline
#elif defined( MSDOS )
#define INLINE
#else
/*UNIX?*/
#define INLINE inline
#endif
/* Sun C compiler has automatic inline and doesn't understand inline keyword */
#ifdef __SUNPRO_C
#undef INLINE
#define INLINE
#define MACROS_ARE_SAFE
#endif
/* Some very common constants. */
#ifndef M_PI
#define M_PI 3.141592653589793
#endif /* MSDOS */
#ifndef PI
#define PI M_PI
#endif
#define TWOPI (2.0*PI) /* Optimising compiler will deal with this! */
#define PB2 (0.5*PI)
#define PI180 (PI/180.0)
#define SOLAR_DAY (1440.0) /* Minutes per 24 hours */
#define SIDERIAL_DAY (23.0*60.0 + 56.0 + 4.09054/60.0) /* Against stars */
#define EQRAD (6378.137) /* Earth radius at equator, km */
#define LATCON (1.0/298.257) /* Latitude radius constant */
#define ECON ((1.0-LATCON)*(1.0-LATCON))
#define JD1900 2415020.5 /* Julian day number for Jan 1st, 00:00 hours 1900 */
/*
* =============================== MACROS ============================
*
*
* Define macro for sign transfer, double to nearest (long) integer,
* to square an expression (not nested), and A "safe" square, uses test
* to force correct sequence of evaluation when the macro is nested.
*/
/*
* These macros are safe since they make no assignments.
*/
#define SIGN(a, b) ((b) >= 0 ? fabs(a) : -fabs(a))
/* Coordinate conversion macros */
#define DEG(x) ((x)/PI180)
#define RAD(x) ((x)*PI180)
#define GEOC(x) (atan(ECON*tan(x))) /* Geographic to geocentric. */
#define GEOG(x) (atan(tan(x)/ECON))
/*
* All other compilers can have static inline functions.
* (SQR is used badly here: do_cal.c, glat2lat.c, satpos.c, vmath.h).
*/
static INLINE int
NINT (double a)
{
return (int) (a > 0 ? a + 0.5 : a - 0.5);
}
static INLINE long
NLONG (double a)
{
return (long) (a > 0 ? a + 0.5 : a - 0.5);
}
static INLINE double
DSQR (double a)
{
return (a * a);
}
static INLINE float
FSQR (float a)
{
return (a * a);
}
static INLINE int
ISQR (int a)
{
return (a * a);
}
static INLINE double
DCUBE (double a)
{
return (a * a * a);
}
static INLINE float
FCUBE (float a)
{
return (a * a * a);
}
static INLINE int
ICUBE (int a)
{
return (a * a * a);
}
static INLINE double
DPOW4 (double a)
{
a *= a;
return (a * a);
}
static INLINE float
FPOW4 (float a)
{
a *= a;
return (a * a);
}
static INLINE int
IPOW4 (int a)
{
a *= a;
return (a * a);
}
static INLINE double
DMAX (double a, double b)
{
if (a > b)
return a;
else
return b;
}
static INLINE float
FMAX (float a, float b)
{
if (a > b)
return a;
else
return b;
}
static INLINE int
IMAX (int a, int b)
{
if (a > b)
return a;
else
return b;
}
static INLINE double
DMIN (double a, double b)
{
if (a < b)
return a;
else
return b;
}
static INLINE float
FMIN (float a, float b)
{
if (a < b)
return a;
else
return b;
}
static INLINE int
IMIN (int a, int b)
{
if (a < b)
return a;
else
return b;
}
static INLINE double
MOD2PI (double a)
{
a = fmod (a, TWOPI);
return a < 0.0 ? a + TWOPI : a;
}
static INLINE double
MOD360 (double a)
{
a = fmod (a, 360.0);
return a < 0.0 ? a + 360.0 : a;
}
/*
* Unless you have higher than default optimisation the Sun compiler
* would prefer to be told explicitly about inline functions after their
* declaration.
*/
#if defined(__SUNPRO_C) && !defined(MACROS_ARE_SAFE)
#pragma inline_routines(NINT, NLONG, DSQR, FSQR, ISQR, DCUBE, FCUBE, ICUBE, DPOW4, FPOW4, IPOW4)
#pragma inline_routines(DMAX, FMAX, IMAX, DMIN, FMIN, IMIN, MOD2PI, MOD360, S_GEOC, S_GEOG)
#endif
/* ==================================================================== */
typedef struct orbit_s
{
/* Add the epoch time if required. */
int ep_year; /* Year of epoch, e.g. 94 for 1994, 100 for 2000AD */
double ep_day; /* Day of epoch from 00:00 Jan 1st ( = 1.0 ) */
double rev; /* Mean motion, revolutions per day */
double bstar; /* Drag term . */
double eqinc; /* Equatorial inclination, radians */
double ecc; /* Eccentricity */
double mnan; /* Mean anomaly at epoch from elements, radians */
double argp; /* Argument of perigee, radians */
double ascn; /* Right ascension (ascending node), radians */
double smjaxs; /* Semi-major axis, km */
double ndot2, nddot6; /* Mean motion derivatives */
char desig[10]; /* International designation */
long norb; /* Orbit number, for elements */
int satno; /* Satellite number. */
} orbit_t;
typedef struct xyz_s
{
double x;
double y;
double z;
} xyz_t;
typedef struct kep_s
{
double theta; /* Angle "theta" from equatorial plane (rad) = U. */
double ascn; /* Right ascension (rad). */
double eqinc; /* Equatorial inclination (rad). */
double radius; /* Radius (km). */
double rdotk;
double rfdotk;
/*
* Following are without short-term perturbations but used to
* speed searches.
*/
double argp; /* Argument of perigee at 'tsince' (rad). */
double smjaxs; /* Semi-major axis at 'tsince' (km). */
double ecc; /* Eccentricity at 'tsince'. */
} kep_t;
/* ================ Single or Double precision options. ================= */
#define DEFAULT_TO_SNGL 0
#if defined( SGDP4_SNGL ) || (DEFAULT_TO_SNGL && !defined( SGDP4_DBLE ))
/* Single precision option. */
typedef float real;
#ifndef SGDP4_SNGL
#define SGDP4_SNGL
#endif
#else
/* Double precision option. */
typedef double real;
#ifndef SGDP4_DBLE
#define SGDP4_DBLE
#endif
#endif /* Single or double choice. */
/* Something silly ? */
#if defined( SGDP4_SNGL ) && defined( SGDP4_DBLE )
#error sgdp4h.h - Cannot have both single and double precision defined
#endif
/* =========== Do we have sincos() functions available or not ? ======= */
/*
We can use the normal ANSI 'C' library functions in sincos() macros, but if
we have sincos() functions they are much faster (25% under some tests). For
DOS programs we use our assembly language functions using the 80387 (and
higher) coprocessor FSINCOS instruction:
void sincos(double x, double *s, double *c);
void sincosf(float x, float *s, float *c);
For the Sun 'C' compiler there is only the system supplied double precision
version of these functions.
*/
#ifdef MACRO_SINCOS
#define sincos(x,s,c) {double sc__tmp=(x);\
*(s)=sin(sc__tmp);\
*(c)=cos(sc__tmp);}
#define SINCOS(x,s,c) {double sc__tmp=(double)(x);\
*(s)=(real)sin(sc__tmp);\
*(c)=(real)cos(sc__tmp);}
#elif !defined( sun )
/* For Microsoft C6.0 compiler, etc. */
#ifdef SGDP4_SNGL
#define SINCOS sincosf
#else
#define SINCOS sincos
#endif /* ! SGDP4_SNGL */
void sincos (double, double *, double *);
void sincosf (float, float *, float *);
#else
/* Sun 'C' compiler. */
#ifdef SGDP4_SNGL
/* Use double function and cast results to single precision. */
#define SINCOS(x,s,c) {double s__tmp, c__tmp;\
sincos((double)(x), &s__tmp, &c__tmp);\
*(s)=(real)s__tmp;\
*(c)=(real)c__tmp);}
#else
#define SINCOS sincos
#endif /* ! SGDP4_SNGL */
#endif /* ! MACRO_SINCOS */
/* ================= Stack space problems ? ======================== */
#if !defined( MSDOS )
/* Automatic variables, faster (?) but needs more stack space. */
#define LOCAL_REAL real
#define LOCAL_DOUBLE double
#else
/* Static variables, slower (?) but little stack space. */
#define LOCAL_REAL static real
#define LOCAL_DOUBLE static double
#endif
/* ======== Macro fixes for float/double in math.h type functions. ===== */
#if defined( SGDP4_SNGL )
#define SIN(x) sinf(x)
#define COS(x) cosf(x)
#define SQRT(x) sqrtf(x)
#define FABS(x) fabsf(x)
#define POW(x,y) powf(x, y)
#define FMOD(x,y) fmodf(x, y)
#define ATAN2(x,y) atan2f(x, y)
#elif defined( SGDP4_DBLE )
#define SIN(x) sin(x)
#define COS(x) cos(x)
#define SQRT(x) sqrt(x)
#define FABS(x) fabs(x)
#define POW(x,y) pow(x, y)
#define FMOD(x,y) fmod(x, y)
#define ATAN2(x,y) atan2(x, y)
#else
#error "Incompatible choices for SGDP4_SNGL / SGDP4_DBLE"
#endif
#ifdef SGDP4_SNGL
#define CUBE FCUBE
#define POW4 FPOW4
#else
#define CUBE DCUBE
#define POW4 DPOW4
#endif
/* SGDP4 function return values. */
typedef enum
{
SGDP4_ERROR = (-1),
SGDP4_NOT_INIT = 0,
SGDP4_ZERO_ECC = 1,
SGDP4_NEAR_SIMP = 2,
SGDP4_NEAR_NORM = 3,
SGDP4_DEEP_NORM = 4,
SGDP4_DEEP_RESN = 5,
SGDP4_DEEP_SYNC = 6
} sgdp4_mode_t;
#include "satutl.h"
/* ======================= Function prototypes ====================== */
#ifdef __cplusplus
extern "C"
{
#endif
/** deep.c **/
sgdp4_mode_t SGDP4_dpinit (double epoch, real omegao, real xnodeo, real xmo,
real orb_eo, real orb_xincl, real aodp,
double xlldot, real omgdot, real xnodot,
double xnodp);
int SGDP4_dpsec (double *xll, real * omgasm, real * xnodes, real * em,
real * xinc, double *xn, double tsince);
int SGDP4_dpper (real * em, real * xinc, real * omgasm, real * xnodes,
double *xll, double tsince);
/** sgdp4.c **/
sgdp4_mode_t init_sgdp4 (orbit_t * orb);
sgdp4_mode_t sgdp4 (double tsince, int withvel, kep_t * kep);
void kep2xyz (kep_t * K, xyz_t * pos, xyz_t * vel);
sgdp4_mode_t satpos_xyz (double jd, xyz_t * pos, xyz_t * vel);
#ifdef __cplusplus
}
#endif
#endif /* !_SGDP4H_H */