Changed Tle to used exceptions

feature/19
Daniel Warner 2011-05-31 12:06:22 +00:00
parent 1cf4c38d1a
commit e58928e887
7 changed files with 155 additions and 69 deletions

View File

@ -159,13 +159,13 @@ std::ostream & operator<<(std::ostream& stream, const Julian& julian) {
std::stringstream out; std::stringstream out;
struct Julian::DateTimeComponents datetime; struct Julian::DateTimeComponents datetime;
julian.ToGregorian(&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(4) << datetime.years << "-";
out << std::setw(2) << datetime.months << "-"; out << std::setw(2) << datetime.months << "-";
out << std::setw(2) << datetime.days << " "; out << std::setw(2) << datetime.days << " ";
out << std::setw(2) << datetime.hours << ":"; out << std::setw(2) << datetime.hours << ":";
out << std::setw(2) << datetime.minutes << ":"; out << std::setw(2) << datetime.minutes << ":";
out << std::setw(10) << datetime.seconds; out << std::setw(6) << datetime.seconds << " UTC";
stream << out.str(); stream << out.str();
return stream; return stream;
} }

View File

@ -58,8 +58,8 @@ void RunTle(Tle tle, double start, double end, double inc) {
std::cout.width(14); std::cout.width(14);
std::cout << velocity.z << std::endl; std::cout << velocity.z << std::endl;
} catch (std::exception* ex) { } catch (SatelliteException& e) {
std::cout << ex->what() << std::endl; std::cout << e.what() << std::endl;
running = false; running = false;
} }
if ((first_run && current == 0.0) || !first_run) { if ((first_run && current == 0.0) || !first_run) {
@ -144,15 +144,15 @@ void RunTest(const char* infile) {
*/ */
if (!got_first_line) { if (!got_first_line) {
if (Tle::IsValidLine(line, 1)) { try {
Tle::IsValidLine(line, 1);
/* /*
* store line and now read in second line * store line and now read in second line
*/ */
got_first_line = true; got_first_line = true;
line1 = line; line1 = line;
} catch (TleException& e) {
} else { std::cerr << "Error: " << e.what() << std::endl;
std::cerr << "Error: Badly formatted first line:" << std::endl;
std::cerr << line << std::endl; std::cerr << line << std::endl;
} }
} else { } else {
@ -182,12 +182,13 @@ void RunTest(const char* infile) {
/* /*
* following line must be the second line * following line must be the second line
*/ */
if (Tle::IsValidLine(line2, 2)) { try {
Tle::IsValidLine(line2, 2);
Tle tle("Test", line1, line2); Tle tle("Test", line1, line2);
RunTle(tle, start, end, inc); RunTle(tle, start, end, inc);
} else { } catch (TleException& e) {
std::cerr << "Error: Badly formatted second line:" << std::endl; std::cerr << "Error: " << e.what() << std::endl;
std::cerr << line2 << std::endl; std::cerr << line << std::endl;
} }
} }
} }

18
SGP4.cpp Normal file → Executable file
View File

@ -43,11 +43,11 @@ void SGP4::SetTle(const Tle& tle) {
* error checks * error checks
*/ */
if (eccentricity_ < 0.0 || eccentricity_ > 1.0 - 1.0e-3) { 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) { if (inclination_ < 0.0 || eccentricity_ > kPI) {
throw new SatelliteException("Inclination out of range"); throw SatelliteException("Inclination out of range");
} }
Initialize(); Initialize();
@ -273,7 +273,7 @@ void SGP4::FindPositionSDP4(Eci* eci, double tsince) const {
DeepSpaceSecular(tsince, &xmdf, &omgadf, &xnode, &e, &xincl, &xn); DeepSpaceSecular(tsince, &xmdf, &omgadf, &xnode, &e, &xincl, &xn);
if (xn <= 0.0) { 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); 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 * fix tolerance for error recognition
*/ */
if (e >= 1.0 || e < -0.001) { 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 * fix tolerance to avoid a divide by zero
@ -318,7 +318,7 @@ void SGP4::FindPositionSDP4(Eci* eci, double tsince) const {
omega = omgadf; omega = omgadf;
if (e < 0.0 || e > 1.0) { 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; xl = xmp + omega + xnode + RecoveredMeanMotion() * templ;
if (xl <= 0.0) { if (xl <= 0.0) {
throw new SatelliteException("Error: #2 (xl <= 0.0)"); throw SatelliteException("Error: #2 (xl <= 0.0)");
} }
/* /*
* fix tolerance for error recognition * fix tolerance for error recognition
*/ */
if (e >= 1.0 || e < -0.001) { 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 * 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; const double pl = a * temp;
if (pl < 0.0) { 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); 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); const double rfdotk = rfdot + xn * temp1 * (x1mth2 * cos2u + 1.5 * x3thm1);
if (rk < 1.0) { if (rk < 1.0) {
throw new SatelliteException("Error: #6 Satellite decayed (rk < 1.0)"); throw SatelliteException("Error: #6 Satellite decayed (rk < 1.0)");
} }
/* /*

1
SGP4.h Normal file → Executable file
View File

@ -3,6 +3,7 @@
#include "Tle.h" #include "Tle.h"
#include "Eci.h" #include "Eci.h"
#include "SatelliteException.h"
class SGP4 { class SGP4 {
public: public:

144
Tle.cpp
View File

@ -5,7 +5,6 @@
Tle::Tle(const std::string& line_one, const std::string& line_two) { Tle::Tle(const std::string& line_one, const std::string& line_two) {
name_.erase();
line_one_ = line_one; line_one_ = line_one;
line_two_ = line_two; 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 START_EXP = 6;
static const int LENGTH_EXP = 2; 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); std::string value = str.substr(START_SIGN, LENGTH_SIGN);
value += "."; value += ".";
@ -88,16 +89,16 @@ void Tle::Initialize() {
/* /*
* check the two lines are valid * check the two lines are valid
*/ */
assert(IsValidPair(line_one_, line_two_)); IsValidPair(line_one_, line_two_);
/* /*
* line 1 * 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()); norad_number_ = atoi(temp.c_str());
/* /*
* if blank use norad number * if blank use norad number for name
*/ */
if (name_.empty()) if (name_.empty())
name_ = temp; name_ = temp;
@ -113,7 +114,6 @@ void Tle::Initialize() {
year += 2000; year += 2000;
else else
year += 1900; year += 1900;
epoch_ = Julian(year, day); epoch_ = Julian(year, day);
if (line_one_[TLE1_COL_MEANMOTIONDT] == '-') { if (line_one_[TLE1_COL_MEANMOTIONDT] == '-') {
@ -164,43 +164,49 @@ void Tle::Initialize() {
/* /*
* check the two lines have matching norad numbers * 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())) * make sure they match
return false; */
if (norad_1.compare(norad_2) != 0)
throw TleException("Norad numbers do not match.");
return true;
} }
/* /*
* validate a line * 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"; static const std::string line2_pattern = "2 NNNNN NNN.NNNN NNN.NNNN NNNNNNN NNN.NNNN NNN.NNNN NN.NNNNNNNNNNNNNN";
/* /*
* validate line against the pattern * validate line against the pattern
*/ */
if (1 == line_number) { if (1 == line_number) {
if (!ValidateLine(str, line1_pattern)) ValidateLine(str, line1_pattern);
return false;
} else if (2 == line_number) { } else if (2 == line_number) {
if (!ValidateLine(str, line2_pattern)) ValidateLine(str, line2_pattern);
return false;
} else { } 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')) * if (chk != (str[TLE_LEN_LINE_DATA - 1] - '0'))
* return false; * return false;
*/ */
}
return true; bool Tle::IsValidLineLength(const std::string& str) {
return str.length() == GetLineLength() ? true : false;
} }
/* /*
* validate line given a pattern * 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()) { if (!IsValidLineLength(line)) {
return false; throw TleException("Invalid line length.");
} }
std::string::const_iterator pattern_itr = pattern.begin(); 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 == '.') { *pattern_itr == '.') {
/* /*
* these characters should match exactly * should match exactly
*/ */
if (*pattern_itr != *line_itr) if (*pattern_itr != *line_itr) {
return false; throw TleException("Invalid character.");
}
} else if (*pattern_itr == 'N') { } 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 != ' ') if (!isdigit(*line_itr) && *line_itr != ' ') {
return false; throw TleException("Invalid character.");
}
} else if (*pattern_itr == '+') { } 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') if (*line_itr != '+' && *line_itr != '-' && *line_itr != ' ' && *line_itr != '0') {
return false; throw TleException("Invalid character.");
}
} else if (*pattern_itr == '-') { } else if (*pattern_itr == '-') {
/* /*
* if pattern value is '+' or '-' * '-' = '+' or '-'
*/ */
if (*line_itr != '+' && *line_itr != '-') if (*line_itr != '+' && *line_itr != '-') {
return false; 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++; pattern_itr++;
line_itr++; line_itr++;
} }
return true;
} }
/* /*
* compute checksum * compute checksum
*/ */
int Tle::CheckSum(const std::string& str) { int Tle::CheckSum(const std::string & str) {
size_t len = str.size() - 1; size_t len = str.size() - 1;
int xsum = 0; int xsum = 0;
@ -294,3 +323,28 @@ int Tle::CheckSum(const std::string& str) {
return (xsum % 10); 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;
}

11
Tle.h
View File

@ -3,6 +3,7 @@
#include "Globals.h" #include "Globals.h"
#include "Julian.h" #include "Julian.h"
#include "TleException.h"
#include <iostream> #include <iostream>
@ -101,8 +102,8 @@ public:
static unsigned int GetLineLength() { static unsigned int GetLineLength() {
return TLE_LEN_LINE_DATA; return TLE_LEN_LINE_DATA;
} }
static bool IsValidPair(const std::string& line1, const std::string& line2); static void IsValidPair(const std::string& line1, const std::string& line2);
static bool IsValidLine(const std::string& str, unsigned char line_number); static void IsValidLine(const std::string& str, unsigned char line_number);
private: private:
/* /*
@ -116,12 +117,16 @@ private:
/* /*
* validate a line against a pattern * 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 * compute checksum
*/ */
static int CheckSum(const std::string& str); 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: private:
/* /*
* raw tle data * raw tle data

25
TleException.h Executable file
View File

@ -0,0 +1,25 @@
#ifndef TLEEXCEPTION_H_
#define TLEEXCEPTION_H_
#include <exception>
#include <iostream>
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