diff --git a/Julian.cpp b/Julian.cpp index 1e9145c..93e9c66 100755 --- a/Julian.cpp +++ b/Julian.cpp @@ -159,13 +159,13 @@ std::ostream & operator<<(std::ostream& stream, const Julian& julian) { std::stringstream out; struct Julian::DateTimeComponents datetime; julian.ToGregorian(&datetime); - out << std::right << std::fixed << std::setprecision(7) << std::setfill('0'); + out << std::right << std::fixed << std::setprecision(3) << std::setfill('0'); out << std::setw(4) << datetime.years << "-"; out << std::setw(2) << datetime.months << "-"; out << std::setw(2) << datetime.days << " "; out << std::setw(2) << datetime.hours << ":"; out << std::setw(2) << datetime.minutes << ":"; - out << std::setw(10) << datetime.seconds; + out << std::setw(6) << datetime.seconds << " UTC"; stream << out.str(); return stream; } diff --git a/RunTest.cpp b/RunTest.cpp index 3dae99b..2062497 100755 --- a/RunTest.cpp +++ b/RunTest.cpp @@ -58,8 +58,8 @@ void RunTle(Tle tle, double start, double end, double inc) { std::cout.width(14); std::cout << velocity.z << std::endl; - } catch (std::exception* ex) { - std::cout << ex->what() << std::endl; + } catch (SatelliteException& e) { + std::cout << e.what() << std::endl; running = false; } if ((first_run && current == 0.0) || !first_run) { @@ -144,15 +144,15 @@ void RunTest(const char* infile) { */ if (!got_first_line) { - if (Tle::IsValidLine(line, 1)) { + try { + Tle::IsValidLine(line, 1); /* * store line and now read in second line */ got_first_line = true; line1 = line; - - } else { - std::cerr << "Error: Badly formatted first line:" << std::endl; + } catch (TleException& e) { + std::cerr << "Error: " << e.what() << std::endl; std::cerr << line << std::endl; } } else { @@ -182,12 +182,13 @@ void RunTest(const char* infile) { /* * following line must be the second line */ - if (Tle::IsValidLine(line2, 2)) { + try { + Tle::IsValidLine(line2, 2); Tle tle("Test", line1, line2); RunTle(tle, start, end, inc); - } else { - std::cerr << "Error: Badly formatted second line:" << std::endl; - std::cerr << line2 << std::endl; + } catch (TleException& e) { + std::cerr << "Error: " << e.what() << std::endl; + std::cerr << line << std::endl; } } } diff --git a/SGP4.cpp b/SGP4.cpp old mode 100644 new mode 100755 index aaadee9..4933358 --- a/SGP4.cpp +++ b/SGP4.cpp @@ -43,11 +43,11 @@ void SGP4::SetTle(const Tle& tle) { * error checks */ if (eccentricity_ < 0.0 || eccentricity_ > 1.0 - 1.0e-3) { - throw new SatelliteException("Eccentricity out of range"); + throw SatelliteException("Eccentricity out of range"); } if (inclination_ < 0.0 || eccentricity_ > kPI) { - throw new SatelliteException("Inclination out of range"); + throw SatelliteException("Inclination out of range"); } Initialize(); @@ -273,7 +273,7 @@ void SGP4::FindPositionSDP4(Eci* eci, double tsince) const { DeepSpaceSecular(tsince, &xmdf, &omgadf, &xnode, &e, &xincl, &xn); if (xn <= 0.0) { - throw new SatelliteException("Error: #2 (xn <= 0.0)"); + throw SatelliteException("Error: #2 (xn <= 0.0)"); } a = pow(kXKE / xn, kTWOTHIRD) * pow(tempa, 2.0); @@ -283,7 +283,7 @@ void SGP4::FindPositionSDP4(Eci* eci, double tsince) const { * fix tolerance for error recognition */ if (e >= 1.0 || e < -0.001) { - throw new SatelliteException("Error: #1 (e >= 1.0 || e < -0.001)"); + throw SatelliteException("Error: #1 (e >= 1.0 || e < -0.001)"); } /* * fix tolerance to avoid a divide by zero @@ -318,7 +318,7 @@ void SGP4::FindPositionSDP4(Eci* eci, double tsince) const { omega = omgadf; if (e < 0.0 || e > 1.0) { - throw new SatelliteException("Error: #3 (e < 0.0 || e > 1.0)"); + throw SatelliteException("Error: #3 (e < 0.0 || e > 1.0)"); } /* @@ -402,14 +402,14 @@ void SGP4::FindPositionSGP4(Eci* eci, double tsince) const { xl = xmp + omega + xnode + RecoveredMeanMotion() * templ; if (xl <= 0.0) { - throw new SatelliteException("Error: #2 (xl <= 0.0)"); + throw SatelliteException("Error: #2 (xl <= 0.0)"); } /* * fix tolerance for error recognition */ if (e >= 1.0 || e < -0.001) { - throw new SatelliteException("Error: #1 (e >= 1.0 || e < -0.001)"); + throw SatelliteException("Error: #1 (e >= 1.0 || e < -0.001)"); } /* * fix tolerance to avoid a divide by zero @@ -519,7 +519,7 @@ void SGP4::CalculateFinalPositionVelocity(Eci* eci, const double& tsince, const const double pl = a * temp; if (pl < 0.0) { - throw new SatelliteException("Error: #4 (pl < 0.0)"); + throw SatelliteException("Error: #4 (pl < 0.0)"); } const double r = a * (1.0 - ecose); @@ -549,7 +549,7 @@ void SGP4::CalculateFinalPositionVelocity(Eci* eci, const double& tsince, const const double rfdotk = rfdot + xn * temp1 * (x1mth2 * cos2u + 1.5 * x3thm1); if (rk < 1.0) { - throw new SatelliteException("Error: #6 Satellite decayed (rk < 1.0)"); + throw SatelliteException("Error: #6 Satellite decayed (rk < 1.0)"); } /* diff --git a/SGP4.h b/SGP4.h old mode 100644 new mode 100755 index 3bdada0..7077899 --- a/SGP4.h +++ b/SGP4.h @@ -3,6 +3,7 @@ #include "Tle.h" #include "Eci.h" +#include "SatelliteException.h" class SGP4 { public: diff --git a/Tle.cpp b/Tle.cpp index 057e807..5c87837 100755 --- a/Tle.cpp +++ b/Tle.cpp @@ -5,7 +5,6 @@ Tle::Tle(const std::string& line_one, const std::string& line_two) { - name_.erase(); line_one_ = line_one; line_two_ = line_two; @@ -57,7 +56,9 @@ std::string Tle::ExpToDecimal(const std::string& str) { static const int START_EXP = 6; static const int LENGTH_EXP = 2; - assert(8 == str.length()); + if ((LENGTH_SIGN + LENGTH_MANTISSA + LENGTH_EXP) != str.length()) { + throw TleException("Invalid string length for exponential conversion."); + } std::string value = str.substr(START_SIGN, LENGTH_SIGN); value += "."; @@ -88,16 +89,16 @@ void Tle::Initialize() { /* * check the two lines are valid */ - assert(IsValidPair(line_one_, line_two_)); + IsValidPair(line_one_, line_two_); /* * line 1 */ - temp = line_one_.substr(TLE1_COL_NORADNUM, TLE1_LEN_NORADNUM).c_str(); + temp = ExtractNoradNumber(line_one_, 1); norad_number_ = atoi(temp.c_str()); /* - * if blank use norad number + * if blank use norad number for name */ if (name_.empty()) name_ = temp; @@ -113,7 +114,6 @@ void Tle::Initialize() { year += 2000; else year += 1900; - epoch_ = Julian(year, day); if (line_one_[TLE1_COL_MEANMOTIONDT] == '-') { @@ -164,43 +164,49 @@ void Tle::Initialize() { /* * check the two lines have matching norad numbers - * and that the lines themselves are valid + * and that the lines themselves are equal */ -bool Tle::IsValidPair(const std::string& line1, const std::string& line2) { +void Tle::IsValidPair(const std::string& line1, const std::string& line2) { - if (!IsValidLine(line1, 1)) - return false; + /* + * validate each line + */ + IsValidLine(line1, 1); + IsValidLine(line2, 2); - if (!IsValidLine(line2, 2)) - return false; + /* + * extract norad numbers + */ + std::string norad_1 = ExtractNoradNumber(line1, 1); + std::string norad_2 = ExtractNoradNumber(line2, 2); - if (atoi(line1.substr(TLE1_COL_NORADNUM, TLE1_LEN_NORADNUM).c_str()) != - atoi(line2.substr(TLE2_COL_NORADNUM, TLE2_LEN_NORADNUM).c_str())) - return false; - - - return true; + /* + * make sure they match + */ + if (norad_1.compare(norad_2) != 0) + throw TleException("Norad numbers do not match."); } /* * validate a line */ -bool Tle::IsValidLine(const std::string& str, const unsigned char line_number) { +void Tle::IsValidLine(const std::string& str, const unsigned char line_number) { - static const std::string line1_pattern = "1 NNNNNC XXXXXXXX NNNNN.NNNNNNNN +.NNNNNNNN +NNNNN-N +NNNNN-N N NNNNN"; + /* + * validation patterns + */ + static const std::string line1_pattern = "1 NNNNNC NNNNNXXX NNNNN.NNNNNNNN +.NNNNNNNN +NNNNN-N +NNNNN-N N NNNNN"; static const std::string line2_pattern = "2 NNNNN NNN.NNNN NNN.NNNN NNNNNNN NNN.NNNN NNN.NNNN NN.NNNNNNNNNNNNNN"; /* * validate line against the pattern */ if (1 == line_number) { - if (!ValidateLine(str, line1_pattern)) - return false; + ValidateLine(str, line1_pattern); } else if (2 == line_number) { - if (!ValidateLine(str, line2_pattern)) - return false; + ValidateLine(str, line2_pattern); } else { - return false; + throw TleException("Invalid line number to check."); } /* @@ -211,20 +217,23 @@ bool Tle::IsValidLine(const std::string& str, const unsigned char line_number) { * if (chk != (str[TLE_LEN_LINE_DATA - 1] - '0')) * return false; */ +} - return true; +bool Tle::IsValidLineLength(const std::string& str) { + + return str.length() == GetLineLength() ? true : false; } /* * validate line given a pattern */ -bool Tle::ValidateLine(const std::string& line, const std::string& pattern) { +void Tle::ValidateLine(const std::string& line, const std::string& pattern) { /* - * check length of lines match + * check length of line */ - if (line.length() < pattern.length()) { - return false; + if (!IsValidLineLength(line)) { + throw TleException("Invalid line length."); } std::string::const_iterator pattern_itr = pattern.begin(); @@ -236,47 +245,67 @@ bool Tle::ValidateLine(const std::string& line, const std::string& pattern) { *pattern_itr == '.') { /* - * these characters should match exactly + * should match exactly */ - if (*pattern_itr != *line_itr) - return false; + if (*pattern_itr != *line_itr) { + throw TleException("Invalid character."); + } } else if (*pattern_itr == 'N') { /* - * if pattern value is 'N' then either a number or a ' ' + * 'N' = number or ' ' */ - if (!isdigit(*line_itr) && *line_itr != ' ') - return false; + if (!isdigit(*line_itr) && *line_itr != ' ') { + throw TleException("Invalid character."); + } } else if (*pattern_itr == '+') { /* - * if pattern value is '+' then either a '+' or '-' or ' ' or '0' + * '+' = '+' or '-' or ' ' or '0' */ - if (*line_itr != '+' && *line_itr != '-' && *line_itr != ' ' && *line_itr != '0') - return false; + if (*line_itr != '+' && *line_itr != '-' && *line_itr != ' ' && *line_itr != '0') { + throw TleException("Invalid character."); + } } else if (*pattern_itr == '-') { /* - * if pattern value is '+' or '-' + * '-' = '+' or '-' */ - if (*line_itr != '+' && *line_itr != '-') - return false; + if (*line_itr != '+' && *line_itr != '-') { + throw TleException("Invalid character."); + } + + } else if (*pattern_itr == 'C') { + + /* + * 'C' = 'U' or 'S' + */ + if (*line_itr != 'U' && *line_itr != 'S') { + throw TleException("Invalid character."); + } + + } else if (*pattern_itr == 'X') { + + /* + * 'X' = A-Z or ' ' + */ + if (!(*line_itr >= 'A' || *line_itr <= 'Z') && *line_itr != ' ') { + throw TleException("Invalid character."); + } } pattern_itr++; line_itr++; } - - return true; } /* * compute checksum */ -int Tle::CheckSum(const std::string& str) { +int Tle::CheckSum(const std::string & str) { size_t len = str.size() - 1; int xsum = 0; @@ -294,3 +323,28 @@ int Tle::CheckSum(const std::string& str) { return (xsum % 10); } + +std::string Tle::ExtractNoradNumber(const std::string& str, const unsigned char line_number) { + + std::string norad_number; + + /* + * check length + */ + if (!IsValidLineLength(str)) { + throw TleException("Invalid line length."); + } + + /* + * extract string + */ + if (1 == line_number) { + norad_number = str.substr(TLE1_COL_NORADNUM, TLE1_LEN_NORADNUM); + } else if (2 == line_number) { + norad_number = str.substr(TLE2_COL_NORADNUM, TLE2_LEN_NORADNUM); + } else { + throw TleException("Invalid line number to check."); + } + + return norad_number; +} diff --git a/Tle.h b/Tle.h index b6e1609..fa9107a 100755 --- a/Tle.h +++ b/Tle.h @@ -3,6 +3,7 @@ #include "Globals.h" #include "Julian.h" +#include "TleException.h" #include @@ -101,8 +102,8 @@ public: static unsigned int GetLineLength() { return TLE_LEN_LINE_DATA; } - static bool IsValidPair(const std::string& line1, const std::string& line2); - static bool IsValidLine(const std::string& str, unsigned char line_number); + static void IsValidPair(const std::string& line1, const std::string& line2); + static void IsValidLine(const std::string& str, unsigned char line_number); private: /* @@ -116,12 +117,16 @@ private: /* * validate a line against a pattern */ - static bool ValidateLine(const std::string& line, const std::string& pattern); + static void ValidateLine(const std::string& line, const std::string& pattern); /* * compute checksum */ static int CheckSum(const std::string& str); + static std::string ExtractNoradNumber(const std::string& str, const unsigned char line_number); + + static bool IsValidLineLength(const std::string& str); + private: /* * raw tle data diff --git a/TleException.h b/TleException.h new file mode 100755 index 0000000..e047f33 --- /dev/null +++ b/TleException.h @@ -0,0 +1,25 @@ +#ifndef TLEEXCEPTION_H_ +#define TLEEXCEPTION_H_ + +#include +#include + +class TleException : public std::exception { +public: + + TleException(const char* message) + : message_(message) { + } + + virtual ~TleException(void) throw () { + } + + virtual const char* what() const throw () { + return message_.c_str(); + } + +private: + std::string message_; +}; + +#endif \ No newline at end of file