// // P13.cpp // // An implementation of Plan13 in C++ by Mark VandeWettering // // Plan13 is an algorithm for satellite orbit prediction first formulated // by James Miller G3RUH. I learned about it when I saw it was the basis // of the PIC based antenna rotator project designed by G6LVB. // // http://www.g6lvb.com/Articles/LVBTracker2/index.htm // // I ported the algorithm to Python, and it was my primary means of orbit // prediction for a couple of years while I operated the "Easy Sats" with // a dual band hand held and an Arrow antenna. // // I've long wanted to redo the work in C++ so that I could port the code // to smaller processors including the Atmel AVR chips. Bruce Robertson, // VE9QRP started the qrpTracker project to fufill many of the same goals, // but I thought that the code could be made more compact and more modular, // and could serve not just the embedded targets but could be of more // use for more general applications. And, I like the BSD License a bit // better too. // // So, here it is! // #include "P13.h" double RADIANS(double deg) { return deg * M_PI / 180. ; } double DEGREES(double rad) { return rad * 180. / M_PI ; } //---------------------------------------------------------------------- // _ ___ _ _____ _ // __| |__ _ ______ | \ __ _| |_ __|_ _(_)_ __ ___ // / _| / _` (_-<_-< | |) / _` | _/ -_)| | | | ' \/ -_) // \__|_\__,_/__/__/ |___/\__,_|\__\___||_| |_|_|_|_\___| // //---------------------------------------------------------------------- static long fnday(int y, int m, int d) { if (m < 3) { m += 12 ; y -- ; } return (long) (y * YM) + (long) ((m+1)*30.6f) + (long)d - 428L ; } static void fndate(int &y, int &m, int &d, long dt) { dt += 428L ; y = (int) ((dt-122.1)/365.25) ; dt -= (long) (y*365.25) ; m = (int) (dt / 30.61) ; dt -= (long) (m*30.6) ; m -- ; if (m > 12) { m -= 12 ; y++ ; } d = dt ; } SatDateTime::SatDateTime(int year, int month, int day, int h, int m, int s) { settime(year, month, day, h, m, s) ; } SatDateTime::SatDateTime(const SatDateTime &dt) { DN = dt.DN ; TN = dt.TN ; } SatDateTime::SatDateTime() { DN = 0L ; TN = 0. ; } void SatDateTime::gettime(int &year, int &month, int &day, int &h, int &m, int &s) { fndate(year, month, day, DN) ; double t = TN ; t *= 24. ; h = (int) t ; t -= h ; t *= 60 ; m = (int) t ; t -= m ; t *= 60 ; s = (int) t ; } void SatDateTime::settime(int year, int month, int day, int h, int m, int s) { DN = fnday(year, month, day) ; TN = ((double) h + m / 60. + s / 3600.) / 24. ; } void SatDateTime::ascii(char *buf) { int year, mon, day ; int h, m, s ; gettime(year, mon, day, h, m, s) ; sprintf(buf, "%02d/%02d/%4d %02d:%02d:%02d", mon, day, year, h, m, s) ; } void SatDateTime::add(double days) { TN += days ; DN += (long) TN ; TN -= (long) TN ; } void SatDateTime::roundup(double t) { double inc = t-fmod(TN, t) ; TN += inc ; DN += (long) TN ; TN -= (long) TN ; } //---------------------------------------------------------------------- // _ ___ _ // __| |__ _ ______ / _ \| |__ ___ ___ _ ___ _____ _ _ // / _| / _` (_-<_-< | (_) | '_ (_-name = nm ; LA = RADIANS(lat) ; LO = RADIANS(lng) ; HT = hgt / 1000 ; U[0] = cos(LA)*cos(LO) ; U[1] = cos(LA)*sin(LO) ; U[2] = sin(LA) ; E[0] = -sin(LO) ; E[1] = cos(LO) ; E[2] = 0. ; N[0] = -sin(LA)*cos(LO) ; N[1] = -sin(LA)*sin(LO) ; N[2] = cos(LA) ; double RP = RE * (1 - FL) ; double XX = RE * RE ; double ZZ = RP * RP ; double D = sqrt(XX*cos(LA)*cos(LA) + ZZ*sin(LA)*sin(LA)) ; double Rx = XX / D + HT ; double Rz = ZZ / D + HT ; O[0] = Rx * U[0] ; O[1] = Rx * U[1] ; O[2] = Rz * U[2] ; V[0] = -O[1] * W0 ; V[1] = O[0] * W0 ; V[2] = 0 ; } //---------------------------------------------------------------------- // _ ___ _ _ _ _ _ // __| |__ _ ______ / __| __ _| |_ ___| | (_) |_ ___ // / _| / _` (_-<_-< \__ \/ _` | _/ -_) | | | _/ -_) // \__|_\__,_/__/__/ |___/\__,_|\__\___|_|_|_|\__\___| // //---------------------------------------------------------------------- static double getdouble(const char *c, int i0, int i1) { char buf[20] ; int i ; for (i=0; i0+i