diff --git a/CoordGeodetic.h b/CoordGeodetic.h index e5b81c8..97faaa9 100644 --- a/CoordGeodetic.h +++ b/CoordGeodetic.h @@ -2,6 +2,7 @@ #define COORDGEODETIC_H_ #include "Globals.h" +#include "Util.h" #include #include @@ -27,8 +28,8 @@ public: } else { - latitude = DegreesToRadians(lat); - longitude = DegreesToRadians(lon); + latitude = Util::DegreesToRadians(lat); + longitude = Util::DegreesToRadians(lon); } altitude = alt; } @@ -69,8 +70,8 @@ public: { std::stringstream ss; ss << std::right << std::fixed << std::setprecision(2); - ss << "Lat: " << std::setw(7) << RadiansToDegrees(latitude); - ss << ", Lon: " << std::setw(7) << RadiansToDegrees(longitude); + ss << "Lat: " << std::setw(7) << Util::RadiansToDegrees(latitude); + ss << ", Lon: " << std::setw(7) << Util::RadiansToDegrees(longitude); ss << ", Alt: " << std::setw(9) << altitude; return ss.str(); } diff --git a/CoordTopographic.h b/CoordTopographic.h index 60b1892..cfb3196 100644 --- a/CoordTopographic.h +++ b/CoordTopographic.h @@ -2,6 +2,7 @@ #define COORDTOPOGRAPHIC_H_ #include "Globals.h" +#include "Util.h" #include #include @@ -57,8 +58,8 @@ public: { std::stringstream ss; ss << std::right << std::fixed << std::setprecision(2); - ss << "Az: " << std::setw(7) << RadiansToDegrees(azimuth); - ss << ", El: " << std::setw(7) << RadiansToDegrees(elevation); + ss << "Az: " << std::setw(7) << Util::RadiansToDegrees(azimuth); + ss << ", El: " << std::setw(7) << Util::RadiansToDegrees(elevation); ss << ", Rng: " << std::setw(9) << range; ss << ", Rng Rt: " << std::setw(6) << range_rate; return ss.str(); diff --git a/Eci.cpp b/Eci.cpp index cb5ec1b..6054a26 100644 --- a/Eci.cpp +++ b/Eci.cpp @@ -1,5 +1,7 @@ #include "Eci.h" +#include "Util.h" + void Eci::ToEci(const Julian& date, const CoordGeodetic &g) { /* @@ -47,7 +49,7 @@ void Eci::ToEci(const Julian& date, const CoordGeodetic &g) CoordGeodetic Eci::ToGeodetic() const { - const double theta = AcTan(position_.y, position_.x); + const double theta = Util::AcTan(position_.y, position_.x); // 0 >= lon < 360 // const double lon = Fmod2p(theta - date_.ToGreenwichSiderealTime()); @@ -59,7 +61,7 @@ CoordGeodetic Eci::ToGeodetic() const static const double e2 = kF * (2.0 - kF); - double lat = AcTan(position_.z, r); + double lat = Util::AcTan(position_.z, r); double phi = 0.0; double c = 0.0; int cnt = 0; @@ -69,7 +71,7 @@ CoordGeodetic Eci::ToGeodetic() const phi = lat; const double sinphi = sin(phi); c = 1.0 / sqrt(1.0 - e2 * sinphi * sinphi); - lat = AcTan(position_.z + kXKMPER * c * e2 * sinphi, r); + lat = Util::AcTan(position_.z + kXKMPER * c * e2 * sinphi, r); cnt++; } while (fabs(lat - phi) >= 1e-10 && cnt < 10); diff --git a/Globals.cpp b/Globals.cpp deleted file mode 100644 index 47140b7..0000000 --- a/Globals.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "Globals.h" - -void TrimLeft(std::string& str) { - - std::string whitespaces(" \t\f\n\r"); - - if (!str.empty()) { - std::string::size_type pos = str.find_first_not_of(whitespaces); - - if (pos != std::string::npos) - str.erase(0, pos); - else - str.clear(); - } -} - -void TrimRight(std::string& str) { - - std::string whitespaces(" \t\f\n\r"); - - if (!str.empty()) { - std::string::size_type pos = str.find_last_not_of(whitespaces); - - if (pos != std::string::npos) - str.erase(pos + 1); - else - str.clear(); - } -} - -void Trim(std::string& str) { - - TrimLeft(str); - TrimRight(str); -} - diff --git a/Globals.h b/Globals.h index 72a3825..0ef1e3d 100644 --- a/Globals.h +++ b/Globals.h @@ -2,7 +2,6 @@ #define GLOBALS_H_ #include -#include const double kAE = 1.0; const double kQ0 = 120.0; @@ -54,7 +53,6 @@ const double kSECONDS_PER_DAY = 86400.0; const double kMINUTES_PER_DAY = 1440.0; const double kHOURS_PER_DAY = 24.0; - // Jan 1.0 1900 = Jan 1 1900 00h UTC const double kEPOCH_JAN1_00H_1900 = 2415019.5; @@ -64,43 +62,5 @@ const double kEPOCH_JAN1_12H_1900 = 2415020.0; // Jan 1.5 2000 = Jan 1 2000 12h UTC const double kEPOCH_JAN1_12H_2000 = 2451545.0; -inline double Fmod2p(const double arg) { - - double modu = fmod(arg, kTWOPI); - if (modu < 0.0) - modu += kTWOPI; - - return modu; -} - -inline double DegreesToRadians(const double degrees) { - - return degrees * kPI / 180.0; -} - -inline double RadiansToDegrees(const double radians) { - - return radians * 180.0 / kPI; -} - -inline double AcTan(const double sinx, const double cosx) { - - if (cosx == 0.0) { - if (sinx > 0.0) - return kPI / 2.0; - else - return 3.0 * kPI / 2.0; - } else { - if (cosx > 0.0) - return atan(sinx / cosx); - else - return kPI + atan(sinx / cosx); - } -} - -void TrimLeft(std::string& str); -void TrimRight(std::string& str); -void Trim(std::string& str); - #endif diff --git a/Makefile b/Makefile index e8d45c9..3b3aaa3 100644 --- a/Makefile +++ b/Makefile @@ -11,14 +11,14 @@ endif LDFLAGS= SOURCES=Eci.cpp \ - Globals.cpp \ Julian.cpp \ Observer.cpp \ OrbitalElements.cpp \ SGP4.cpp \ SolarPosition.cpp \ Timespan.cpp \ - Tle.cpp + Tle.cpp \ + Util.cpp OBJECTS=$(SOURCES:.cpp=.o) SGP4LIB=libsgp4.a diff --git a/PassPredict.cpp b/PassPredict.cpp index 5954acf..f81b233 100644 --- a/PassPredict.cpp +++ b/PassPredict.cpp @@ -1,5 +1,6 @@ #include "Observer.h" #include "SGP4.h" +#include "Util.h" #include #include @@ -186,7 +187,7 @@ void AOSLOS(const CoordGeodetic& user_geo, SGP4& sgp4, const Julian& start_time, found_los = false; end_of_pass = true; double max_elevation = FindMaxElevation(user_geo, sgp4, aos_time, los_time); - std::cout << "AOS: " << aos_time << ", LOS: " << los_time << ", Max El: " << RadiansToDegrees(max_elevation) << std::endl; + std::cout << "AOS: " << aos_time << ", LOS: " << los_time << ", Max El: " << Util::RadiansToDegrees(max_elevation) << std::endl; } } @@ -214,7 +215,7 @@ void AOSLOS(const CoordGeodetic& user_geo, SGP4& sgp4, const Julian& start_time, los_time = end_time; double max_elevation = FindMaxElevation(user_geo, sgp4, aos_time, los_time); - std::cout << "AOS: " << aos_time << ", LOS: " << los_time << ", Max El: " << RadiansToDegrees(max_elevation) << std::endl; + std::cout << "AOS: " << aos_time << ", LOS: " << los_time << ", Max El: " << Util::RadiansToDegrees(max_elevation) << std::endl; } } diff --git a/RunTest.cpp b/RunTest.cpp index 18aaebd..8ab56cb 100644 --- a/RunTest.cpp +++ b/RunTest.cpp @@ -2,6 +2,7 @@ #include "Tle.h" #include "SGP4.h" #include "Globals.h" +#include "Util.h" #include "Observer.h" #include "CoordGeodetic.h" #include "CoordTopographic.h" @@ -141,7 +142,7 @@ void RunTest(const char* infile) std::string line; std::getline(file, line); - Trim(line); + Util::Trim(line); /* * skip blank lines or lines starting with # diff --git a/SGP4.cpp b/SGP4.cpp index dd59a13..c97353a 100644 --- a/SGP4.cpp +++ b/SGP4.cpp @@ -1,5 +1,6 @@ #include "SGP4.h" +#include "Util.h" #include "Vector.h" #include "SatelliteException.h" @@ -626,7 +627,7 @@ void SGP4::DeepSpaceInitialise(const double& eosq, const double& sinio, const do const double zcoshl = sqrt(1.0 - zsinhl * zsinhl); const double c = 4.7199672 + 0.22997150 * jday; const double gam = 5.8351514 + 0.0019443680 * jday; - deepspace_consts_.zmol = Fmod2p(c - gam); + deepspace_consts_.zmol = Util::Fmod2p(c - gam); double zx = 0.39785416 * stem / zsinil; double zy = zcoshl * ctem + 0.91744867 * zsinhl * stem; zx = atan2(zx, zy); @@ -634,7 +635,7 @@ void SGP4::DeepSpaceInitialise(const double& eosq, const double& sinio, const do const double zcosgl = cos(zx); const double zsingl = sin(zx); - deepspace_consts_.zmos = Fmod2p(6.2565837 + 0.017201977 * jday); + deepspace_consts_.zmos = Util::Fmod2p(6.2565837 + 0.017201977 * jday); /* * do solar terms diff --git a/SatTrack.cpp b/SatTrack.cpp index cb5afbe..fb36308 100644 --- a/SatTrack.cpp +++ b/SatTrack.cpp @@ -6,9 +6,9 @@ int main() { Observer obs(51.507406923983446, -0.12773752212524414, 0.05); - Tle tle = Tle("ISS (ZARYA) ", - "1 25544U 98067A 11146.36888985 .00025753 00000-0 16912-3 0 4201", - "2 25544 51.6504 272.6534 0003891 329.5510 71.2188 15.75539412717473"); + Tle tle = Tle("UK-DMC 2 ", + "1 35683U 09041C 11356.17214994 .00000411 00000-0 77254-4 0 6826", + "2 35683 98.0512 251.8127 0001492 79.4611 280.6776 14.69611889128518"); SGP4 sgp4(tle); while(1) diff --git a/SolarPosition.cpp b/SolarPosition.cpp index fc5e13f..8a8cc3c 100644 --- a/SolarPosition.cpp +++ b/SolarPosition.cpp @@ -1,6 +1,7 @@ #include "SolarPosition.h" #include "Globals.h" +#include "Util.h" #include @@ -9,23 +10,23 @@ Eci SolarPosition::FindPosition(const Julian& j) const double mjd = j.FromJan1_12h_1900(); const double year = 1900 + mjd / 365.25; const double T = (mjd + Delta_ET(year) / kSECONDS_PER_DAY) / 36525.0; - const double M = DegreesToRadians(Modulus(358.47583 + const double M = Util::DegreesToRadians(Modulus(358.47583 + Modulus(35999.04975 * T, 360.0) - (0.000150 + 0.0000033 * T) * T * T, 360.0)); - const double L = DegreesToRadians(Modulus(279.69668 + const double L = Util::DegreesToRadians(Modulus(279.69668 + Modulus(36000.76892 * T, 360.0) + 0.0003025 * T*T, 360.0)); const double e = 0.01675104 - (0.0000418 + 0.000000126 * T) * T; - const double C = DegreesToRadians((1.919460 + const double C = Util::DegreesToRadians((1.919460 - (0.004789 + 0.000014 * T) * T) * sin(M) + (0.020094 - 0.000100 * T) * sin(2 * M) + 0.000293 * sin(3 * M)); - const double O = DegreesToRadians(Modulus(259.18 - 1934.142 * T, 360.0)); + const double O = Util::DegreesToRadians(Modulus(259.18 - 1934.142 * T, 360.0)); const double Lsa = Modulus(L + C - - DegreesToRadians(0.00569 - 0.00479 * sin(O)), kTWOPI); + - Util::DegreesToRadians(0.00569 - 0.00479 * sin(O)), kTWOPI); const double nu = Modulus(M + C, kTWOPI); double R = 1.0000002 * (1 - e * e) / (1 + e * cos(nu)); - const double eps = DegreesToRadians(23.452294 - (0.0130125 + const double eps = Util::DegreesToRadians(23.452294 - (0.0130125 + (0.00000164 - 0.000000503 * T) * T) * T + 0.00256 * cos(O)); R = R * kAU; diff --git a/Tle.cpp b/Tle.cpp index c52f591..f00aaaf 100644 --- a/Tle.cpp +++ b/Tle.cpp @@ -1,6 +1,6 @@ #include "Tle.h" -#include +#include "Util.h" namespace { @@ -109,12 +109,12 @@ void Tle::Initialize() /* * trim whitespace */ - TrimLeft(name_); - TrimRight(name_); - TrimLeft(line_one_); - TrimRight(line_one_); - TrimLeft(line_two_); - TrimRight(line_two_); + Util::TrimLeft(name_); + Util::TrimRight(name_); + Util::TrimLeft(line_one_); + Util::TrimRight(line_one_); + Util::TrimLeft(line_two_); + Util::TrimRight(line_two_); /* * check the two lines are valid @@ -126,7 +126,11 @@ void Tle::Initialize() */ temp = ExtractNoradNumber(line_one_, 1); - norad_number_ = atoi(temp.c_str()); + if (!Util::FromString(temp, norad_number_)) + { + throw TleException("Conversion failed"); + } + /* * if blank use norad number for name */ @@ -138,10 +142,18 @@ void Tle::Initialize() international_designator_ = line_one_.substr(TLE1_COL_INTLDESC_A, TLE1_LEN_INTLDESC_A + TLE1_LEN_INTLDESC_B + TLE1_LEN_INTLDESC_C); - int year = atoi(line_one_.substr(TLE1_COL_EPOCH_A, - TLE1_LEN_EPOCH_A).c_str()); - double day = atof(line_one_.substr(TLE1_COL_EPOCH_B, - TLE1_LEN_EPOCH_B).c_str()); + int year; + double day; + if (!Util::FromString(line_one_.substr(TLE1_COL_EPOCH_A, + TLE1_LEN_EPOCH_A), year)) + { + throw TleException("Conversion failed"); + } + if (!Util::FromString(line_one_.substr(TLE1_COL_EPOCH_B, + TLE1_LEN_EPOCH_B), day)) + { + throw TleException("Conversion failed"); + } /* * generate julian date for epoch */ @@ -156,47 +168,77 @@ void Tle::Initialize() } else temp = "0"; temp += line_one_.substr(TLE1_COL_MEANMOTIONDT + 1, TLE1_LEN_MEANMOTIONDT); - mean_motion_dot_ = atof(temp.c_str()); + if (!Util::FromString(temp, mean_motion_dot_)) + { + throw TleException("Conversion failed"); + } temp = ExpToDecimal(line_one_.substr(TLE1_COL_MEANMOTIONDT2, TLE1_LEN_MEANMOTIONDT2)); - mean_motion_dot2_ = atof(temp.c_str()); + if (!Util::FromString(temp, mean_motion_dot2_)) + { + throw TleException("Conversion failed"); + } temp = ExpToDecimal(line_one_.substr(TLE1_COL_BSTAR, TLE1_LEN_BSTAR).c_str()); - bstar_ = atof(temp.c_str()); + if (!Util::FromString(temp, bstar_)) + { + throw TleException("Conversion failed"); + } /* * line 2 */ temp = line_two_.substr(TLE2_COL_INCLINATION, TLE2_LEN_INCLINATION); - TrimLeft(temp); - inclination_ = atof(temp.c_str()); + Util::TrimLeft(temp); + if (!Util::FromString(temp, inclination_)) + { + throw TleException("Conversion failed"); + } temp = line_two_.substr(TLE2_COL_RAASCENDNODE, TLE2_LEN_RAASCENDNODE); - TrimLeft(temp); - right_ascending_node_ = atof(temp.c_str()); + Util::TrimLeft(temp); + if (!Util::FromString(temp, right_ascending_node_)) + { + throw TleException("Conversion failed"); + } temp = "0."; temp += line_two_.substr(TLE2_COL_ECCENTRICITY, TLE2_LEN_ECCENTRICITY); - eccentricity_ = atof(temp.c_str()); + if (!Util::FromString(temp, eccentricity_)) + { + throw TleException("Conversion failed"); + } temp = line_two_.substr(TLE2_COL_ARGPERIGEE, TLE2_LEN_ARGPERIGEE); - TrimLeft(temp); - argument_perigee_ = atof(temp.c_str()); + Util::TrimLeft(temp); + if (!Util::FromString(temp, argument_perigee_)) + { + throw TleException("Conversion failed"); + } temp = line_two_.substr(TLE2_COL_MEANANOMALY, TLE2_LEN_MEANANOMALY); - TrimLeft(temp); - mean_anomaly_ = atof(temp.c_str()); + Util::TrimLeft(temp); + if (!Util::FromString(temp, mean_anomaly_)) + { + throw TleException("Conversion failed"); + } temp = line_two_.substr(TLE2_COL_MEANMOTION, TLE2_LEN_MEANMOTION); - TrimLeft(temp); - mean_motion_ = atof(temp.c_str()); + Util::TrimLeft(temp); + if (!Util::FromString(temp, mean_motion_)) + { + throw TleException("Conversion failed"); + } temp = line_two_.substr(TLE2_COL_REVATEPOCH, TLE2_LEN_REVATEPOCH); - TrimLeft(temp); - orbit_number_ = atoi(temp.c_str()); + Util::TrimLeft(temp); + if (!Util::FromString(temp, orbit_number_)) + { + throw TleException("Conversion failed"); + } } /* @@ -281,81 +323,90 @@ void Tle::ValidateLine(const std::string& line, const std::string& pattern) throw TleException("Invalid line length."); } - std::string::const_iterator pattern_itr = pattern.begin(); - std::string::const_iterator line_itr = line.begin(); - - while (pattern_itr != pattern.end()) + for (size_t i = 0; i < pattern.length(); i++) { - if (isdigit(*pattern_itr) || *pattern_itr == ' ' || - *pattern_itr == '.') - { - /* - * should match exactly - */ - if (*pattern_itr != *line_itr) - { - throw TleException("Invalid character."); - } + char ptrn = pattern[i]; + char mtch = line[i]; - } - else if (*pattern_itr == 'N') + switch (ptrn) { - /* - * 'N' = number or ' ' - */ - if (!isdigit(*line_itr) && *line_itr != ' ') + case '1': + case '2': + case ' ': + case '.': { - throw TleException("Invalid character."); + /* + * should match exactly + */ + if (ptrn != mtch) + { + throw TleException("Invalid character"); + } + break; } - - } - else if (*pattern_itr == '+') - { - /* - * '+' = '+' or '-' or ' ' or '0' - */ - if (*line_itr != '+' && *line_itr != '-' && - *line_itr != ' ' && *line_itr != '0') + case 'N': { - throw TleException("Invalid character."); + /* + * number or ' ' + */ + if (!isdigit(mtch) && mtch != ' ') + { + throw TleException("Invalid character"); + } + break; } - - } - else if (*pattern_itr == '-') - { - /* - * '-' = '+' or '-' - */ - if (*line_itr != '+' && *line_itr != '-') + case '+': { - throw TleException("Invalid character."); + /* + * + or - or space or 0 or digit + */ + if (mtch != '+' && mtch != '-' + && mtch != ' ' && mtch != '0' + && !isdigit(mtch)) + { + throw TleException("Invalid character"); + } + break; } - - } - else if (*pattern_itr == 'C') - { - /* - * 'C' = 'U' or 'S' - */ - if (*line_itr != 'U' && *line_itr != 'S') + case '-': { - throw TleException("Invalid character."); + /* + * + or - + */ + if (mtch != '+' && mtch != '-') + { + throw TleException("Invalid character"); + } + break; } - - } - else if (*pattern_itr == 'X') - { - /* - * 'X' = A-Z or ' ' - */ - if (!(*line_itr >= 'A' || *line_itr <= 'Z') && *line_itr != ' ') + case 'C': { - throw TleException("Invalid character."); + /* + * U or S + */ + if (mtch != 'U' && mtch != 'S') + { + throw TleException("Invalid character"); + } + break; + } + case 'X': + { + /* + * alpha or ' ' + */ + if (!isupper(mtch) && !isalpha(mtch) && mtch != ' ') + { + throw TleException("Invalid character"); + } + break; + } + default: + { + throw TleException("Invalid pattern character"); + break; } } - - pattern_itr++; - line_itr++; } } @@ -399,11 +450,11 @@ std::string Tle::ExtractNoradNumber(const std::string& str, int line_number) /* * extract string */ - if (1 == line_number) + if (line_number == 1) { norad_number = str.substr(TLE1_COL_NORADNUM, TLE1_LEN_NORADNUM); } - else if (2 == line_number) + else if (line_number == 2) { norad_number = str.substr(TLE2_COL_NORADNUM, TLE2_LEN_NORADNUM); } diff --git a/Tle.h b/Tle.h index d79c472..693a6b9 100644 --- a/Tle.h +++ b/Tle.h @@ -2,6 +2,7 @@ #define TLE_H_ #include "Globals.h" +#include "Util.h" #include "Julian.h" #include "TleException.h" @@ -88,7 +89,7 @@ public: } else { - return DegreesToRadians(inclination_); + return Util::DegreesToRadians(inclination_); } } @@ -100,7 +101,7 @@ public: } else { - return DegreesToRadians(right_ascending_node_); + return Util::DegreesToRadians(right_ascending_node_); } } @@ -117,7 +118,7 @@ public: } else { - return DegreesToRadians(argument_perigee_); + return Util::DegreesToRadians(argument_perigee_); } } @@ -129,7 +130,7 @@ public: } else { - return DegreesToRadians(mean_anomaly_); + return Util::DegreesToRadians(mean_anomaly_); } } diff --git a/Util.cpp b/Util.cpp new file mode 100644 index 0000000..eb56926 --- /dev/null +++ b/Util.cpp @@ -0,0 +1,39 @@ +#include "Util.h" + +namespace Util +{ + void TrimLeft(std::string& str) + { + std::string whitespaces(" \t\f\n\r"); + + if (!str.empty()) { + std::string::size_type pos = str.find_first_not_of(whitespaces); + + if (pos != std::string::npos) + str.erase(0, pos); + else + str.clear(); + } + } + + void TrimRight(std::string& str) + { + std::string whitespaces(" \t\f\n\r"); + + if (!str.empty()) { + std::string::size_type pos = str.find_last_not_of(whitespaces); + + if (pos != std::string::npos) + str.erase(pos + 1); + else + str.clear(); + } + } + + void Trim(std::string& str) + { + TrimLeft(str); + TrimRight(str); + } + +} diff --git a/Util.h b/Util.h new file mode 100644 index 0000000..56824e6 --- /dev/null +++ b/Util.h @@ -0,0 +1,71 @@ +#ifndef UTIL_H_ +#define UTIL_H_ + +#include "Globals.h" + +#include + +namespace Util +{ + template + + bool FromString(const std::string& str, T& val) + { + std::stringstream ss(str); + return !(ss >> val).fail(); + } + + + inline double Fmod2p(const double arg) + { + double modu = fmod(arg, kTWOPI); + if (modu < 0.0) + { + modu += kTWOPI; + } + + return modu; + } + + inline double DegreesToRadians(const double degrees) + { + return degrees * kPI / 180.0; + } + + inline double RadiansToDegrees(const double radians) + { + return radians * 180.0 / kPI; + } + + inline double AcTan(const double sinx, const double cosx) + { + if (cosx == 0.0) + { + if (sinx > 0.0) + { + return kPI / 2.0; + } + else + { + return 3.0 * kPI / 2.0; + } + } + else + { + if (cosx > 0.0) + { + return atan(sinx / cosx); + } + else + { + return kPI + atan(sinx / cosx); + } + } + } + + void TrimLeft(std::string& str); + void TrimRight(std::string& str); + void Trim(std::string& str); +} + +#endif