2011-03-24 16:08:24 +00:00
|
|
|
#include "Tle.h"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdlib>
|
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
Tle::Tle(const std::string& line_one, const std::string& line_two) {
|
|
|
|
|
|
|
|
name_.erase();
|
|
|
|
line_one_ = line_one;
|
|
|
|
line_two_ = line_two;
|
|
|
|
|
|
|
|
Initialize();
|
|
|
|
}
|
|
|
|
|
2011-03-24 16:08:24 +00:00
|
|
|
Tle::Tle(const std::string& name, const std::string& line_one, const std::string& line_two) {
|
2011-04-07 13:42:25 +00:00
|
|
|
|
2011-03-24 16:08:24 +00:00
|
|
|
name_ = name;
|
|
|
|
line_one_ = line_one;
|
|
|
|
line_two_ = line_two;
|
|
|
|
|
|
|
|
Initialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
Tle::Tle(const Tle& tle) {
|
2011-04-07 13:42:25 +00:00
|
|
|
|
2011-03-24 16:08:24 +00:00
|
|
|
name_ = tle.name_;
|
|
|
|
line_one_ = tle.line_one_;
|
|
|
|
line_two_ = tle.line_two_;
|
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
norad_number_ = tle.norad_number_;
|
|
|
|
international_designator_ = tle.international_designator_;
|
|
|
|
epoch_ = tle.epoch_;
|
|
|
|
mean_motion_dot_ = tle.mean_motion_dot_;
|
|
|
|
mean_motion_dot2_ = tle.mean_motion_dot2_;
|
|
|
|
bstar_ = tle.bstar_;
|
|
|
|
inclination_ = tle.inclination_;
|
|
|
|
right_ascending_node_ = tle.right_ascending_node_;
|
|
|
|
eccentricity_ = tle.eccentricity_;
|
|
|
|
argument_perigee_ = tle.argument_perigee_;
|
|
|
|
mean_anomaly_ = tle.mean_anomaly_;
|
|
|
|
mean_motion_ = tle.mean_motion_;
|
|
|
|
orbit_number_ = tle.orbit_number_;
|
2011-03-24 16:08:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Tle::~Tle() {
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-04-07 13:42:25 +00:00
|
|
|
* convert a tle raw string into an exponent string
|
2011-03-24 16:08:24 +00:00
|
|
|
*/
|
|
|
|
std::string Tle::ExpToDecimal(const std::string& str) {
|
2011-04-07 13:42:25 +00:00
|
|
|
|
|
|
|
static const int START_SIGN = 0;
|
|
|
|
static const int LENGTH_SIGN = 1;
|
|
|
|
static const int START_MANTISSA = 1;
|
|
|
|
static const int LENGTH_MANTISSA = 5;
|
|
|
|
static const int START_EXP = 6;
|
|
|
|
static const int LENGTH_EXP = 2;
|
2011-03-24 16:08:24 +00:00
|
|
|
|
|
|
|
assert(8 == str.length());
|
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
std::string value = str.substr(START_SIGN, LENGTH_SIGN);
|
2011-03-24 16:08:24 +00:00
|
|
|
value += ".";
|
2011-04-07 13:42:25 +00:00
|
|
|
value += str.substr(START_MANTISSA, LENGTH_MANTISSA);
|
2011-03-24 16:08:24 +00:00
|
|
|
value += "e";
|
2011-04-07 13:42:25 +00:00
|
|
|
value += str.substr(START_EXP, LENGTH_EXP);
|
2011-03-24 16:08:24 +00:00
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* extract all variables
|
|
|
|
*/
|
|
|
|
void Tle::Initialize() {
|
2011-04-07 13:42:25 +00:00
|
|
|
|
|
|
|
std::string temp;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* trim whitespace
|
|
|
|
*/
|
2011-03-24 16:19:34 +00:00
|
|
|
TrimLeft(name_);
|
|
|
|
TrimRight(name_);
|
|
|
|
TrimLeft(line_one_);
|
|
|
|
TrimRight(line_one_);
|
|
|
|
TrimLeft(line_two_);
|
|
|
|
TrimRight(line_two_);
|
2011-03-30 17:16:37 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
/*
|
|
|
|
* check the two lines are valid
|
|
|
|
*/
|
|
|
|
assert(IsValidPair(line_one_, line_two_));
|
2011-03-26 12:47:53 +00:00
|
|
|
|
2011-03-24 16:08:24 +00:00
|
|
|
/*
|
|
|
|
* line 1
|
|
|
|
*/
|
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
temp = line_one_.substr(TLE1_COL_NORADNUM, TLE1_LEN_NORADNUM).c_str();
|
|
|
|
norad_number_ = atoi(temp.c_str());
|
|
|
|
/*
|
|
|
|
* if blank use norad number
|
|
|
|
*/
|
|
|
|
if (name_.empty())
|
|
|
|
name_ = temp;
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
international_designator_ = line_one_.substr(TLE1_COL_INTLDESC_A, TLE1_LEN_INTLDESC_A + TLE1_LEN_INTLDESC_B + TLE1_LEN_INTLDESC_C);
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
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());
|
|
|
|
/*
|
|
|
|
* generate julian date for epoch
|
|
|
|
*/
|
|
|
|
if (year < 57)
|
|
|
|
year += 2000;
|
|
|
|
else
|
|
|
|
year += 1900;
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
epoch_ = Julian(year, day);
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
if (line_one_[TLE1_COL_MEANMOTIONDT] == '-') {
|
|
|
|
temp = "-0";
|
|
|
|
} else
|
|
|
|
temp = "0";
|
|
|
|
temp += line_one_.substr(TLE1_COL_MEANMOTIONDT + 1, TLE1_LEN_MEANMOTIONDT);
|
|
|
|
mean_motion_dot_ = atof(temp.c_str());
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
temp = ExpToDecimal(line_one_.substr(TLE1_COL_MEANMOTIONDT2, TLE1_LEN_MEANMOTIONDT2));
|
|
|
|
mean_motion_dot2_ = atof(temp.c_str());
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
temp = ExpToDecimal(line_one_.substr(TLE1_COL_BSTAR, TLE1_LEN_BSTAR).c_str());
|
|
|
|
bstar_ = atof(temp.c_str());
|
2011-03-24 16:08:24 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* line 2
|
|
|
|
*/
|
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
temp = line_two_.substr(TLE2_COL_INCLINATION, TLE2_LEN_INCLINATION);
|
|
|
|
TrimLeft(temp);
|
|
|
|
inclination_ = atof(temp.c_str());
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
temp = line_two_.substr(TLE2_COL_RAASCENDNODE, TLE2_LEN_RAASCENDNODE);
|
|
|
|
TrimLeft(temp);
|
|
|
|
right_ascending_node_ = atof(temp.c_str());
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
temp = "0.";
|
|
|
|
temp += line_two_.substr(TLE2_COL_ECCENTRICITY, TLE2_LEN_ECCENTRICITY);
|
|
|
|
eccentricity_ = atof(temp.c_str());
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
temp = line_two_.substr(TLE2_COL_ARGPERIGEE, TLE2_LEN_ARGPERIGEE);
|
|
|
|
TrimLeft(temp);
|
|
|
|
argument_perigee_ = atof(temp.c_str());
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
temp = line_two_.substr(TLE2_COL_MEANANOMALY, TLE2_LEN_MEANANOMALY);
|
|
|
|
TrimLeft(temp);
|
|
|
|
mean_anomaly_ = atof(temp.c_str());
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
temp = line_two_.substr(TLE2_COL_MEANMOTION, TLE2_LEN_MEANMOTION);
|
|
|
|
TrimLeft(temp);
|
|
|
|
mean_motion_ = atof(temp.c_str());
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
temp = line_two_.substr(TLE2_COL_REVATEPOCH, TLE2_LEN_REVATEPOCH);
|
|
|
|
TrimLeft(temp);
|
|
|
|
orbit_number_ = atoi(temp.c_str());
|
|
|
|
}
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
/*
|
|
|
|
* check the two lines have matching norad numbers
|
|
|
|
* and that the lines themselves are valid
|
|
|
|
*/
|
|
|
|
bool Tle::IsValidPair(const std::string& line1, const std::string& line2) {
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
if (!IsValidLine(line1, 1))
|
|
|
|
return false;
|
2011-03-30 17:16:37 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
if (!IsValidLine(line2, 2))
|
|
|
|
return false;
|
|
|
|
|
2011-05-08 12:39:20 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
return true;
|
2011-03-24 16:08:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* validate a line
|
|
|
|
*/
|
2011-04-07 13:42:25 +00:00
|
|
|
bool Tle::IsValidLine(const std::string& str, const unsigned char line_number) {
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-05-08 12:39:20 +00:00
|
|
|
static const std::string line1_pattern = "1 NNNNNC XXXXXXXX NNNNN.NNNNNNNN +.NNNNNNNN +NNNNN-N +NNNNN-N N NNNNN";
|
2011-04-07 13:42:25 +00:00
|
|
|
static const std::string line2_pattern = "2 NNNNN NNN.NNNN NNN.NNNN NNNNNNN NNN.NNNN NNN.NNNN NN.NNNNNNNNNNNNNN";
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
/*
|
|
|
|
* validate line against the pattern
|
|
|
|
*/
|
|
|
|
if (1 == line_number) {
|
|
|
|
if (!ValidateLine(str, line1_pattern))
|
2011-03-24 16:08:24 +00:00
|
|
|
return false;
|
2011-04-07 13:42:25 +00:00
|
|
|
} else if (2 == line_number) {
|
|
|
|
if (!ValidateLine(str, line2_pattern))
|
2011-03-24 16:08:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
/*
|
|
|
|
* last char in string is modulo 10 checksum
|
2011-04-11 09:58:10 +00:00
|
|
|
* edited out as checksum isnt consistent
|
|
|
|
*
|
|
|
|
* int chk = CheckSum(str);
|
|
|
|
* if (chk != (str[TLE_LEN_LINE_DATA - 1] - '0'))
|
|
|
|
* return false;
|
2011-04-07 13:42:25 +00:00
|
|
|
*/
|
2011-03-24 16:08:24 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* validate line given a pattern
|
|
|
|
*/
|
2011-04-07 13:42:25 +00:00
|
|
|
bool Tle::ValidateLine(const std::string& line, const std::string& pattern) {
|
2011-04-05 23:53:11 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
/*
|
|
|
|
* check length of lines match
|
|
|
|
*/
|
2011-04-11 09:58:10 +00:00
|
|
|
if (line.length() < pattern.length()) {
|
2011-04-05 23:53:11 +00:00
|
|
|
return false;
|
|
|
|
}
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
std::string::const_iterator pattern_itr = pattern.begin();
|
|
|
|
std::string::const_iterator line_itr = line.begin();
|
2011-03-24 16:08:24 +00:00
|
|
|
|
2011-04-07 13:42:25 +00:00
|
|
|
while (pattern_itr != pattern.end()) {
|
|
|
|
|
|
|
|
if (isdigit(*pattern_itr) || *pattern_itr == ' ' ||
|
2011-04-09 23:52:11 +00:00
|
|
|
*pattern_itr == '.') {
|
2011-04-07 13:42:25 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* these characters should match exactly
|
|
|
|
*/
|
|
|
|
if (*pattern_itr != *line_itr)
|
2011-03-24 16:08:24 +00:00
|
|
|
return false;
|
2011-04-07 13:42:25 +00:00
|
|
|
|
|
|
|
} else if (*pattern_itr == 'N') {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if pattern value is 'N' then either a number or a ' '
|
|
|
|
*/
|
|
|
|
if (!isdigit(*line_itr) && *line_itr != ' ')
|
|
|
|
return false;
|
|
|
|
|
|
|
|
} else if (*pattern_itr == '+') {
|
|
|
|
|
|
|
|
/*
|
2011-05-08 12:39:20 +00:00
|
|
|
* if pattern value is '+' then either a '+' or '-' or ' ' or '0'
|
2011-04-07 13:42:25 +00:00
|
|
|
*/
|
2011-05-08 12:39:20 +00:00
|
|
|
if (*line_itr != '+' && *line_itr != '-' && *line_itr != ' ' && *line_itr != '0')
|
2011-03-24 16:08:24 +00:00
|
|
|
return false;
|
2011-04-09 23:52:11 +00:00
|
|
|
|
|
|
|
} else if (*pattern_itr == '-') {
|
|
|
|
|
|
|
|
/*
|
2011-05-08 12:39:20 +00:00
|
|
|
* if pattern value is '+' or '-'
|
2011-04-09 23:52:11 +00:00
|
|
|
*/
|
|
|
|
if (*line_itr != '+' && *line_itr != '-')
|
|
|
|
return false;
|
2011-03-24 16:08:24 +00:00
|
|
|
}
|
2011-04-07 13:42:25 +00:00
|
|
|
|
|
|
|
pattern_itr++;
|
|
|
|
line_itr++;
|
2011-03-24 16:08:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* compute checksum
|
|
|
|
*/
|
|
|
|
int Tle::CheckSum(const std::string& str) {
|
2011-04-07 13:42:25 +00:00
|
|
|
|
2011-03-24 16:08:24 +00:00
|
|
|
size_t len = str.size() - 1;
|
|
|
|
int xsum = 0;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
2011-04-07 13:42:25 +00:00
|
|
|
|
2011-03-24 16:08:24 +00:00
|
|
|
char ch = str[i];
|
2011-04-07 13:42:25 +00:00
|
|
|
|
2011-03-24 16:08:24 +00:00
|
|
|
if (isdigit(ch))
|
|
|
|
xsum += (ch - '0');
|
2011-04-07 13:42:25 +00:00
|
|
|
else
|
|
|
|
if (ch == '-')
|
2011-03-24 16:08:24 +00:00
|
|
|
xsum++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (xsum % 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* trim left of string
|
|
|
|
*/
|
2011-04-07 13:42:25 +00:00
|
|
|
void Tle::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);
|
2011-03-24 16:08:24 +00:00
|
|
|
|
|
|
|
if (pos != std::string::npos)
|
2011-04-07 13:42:25 +00:00
|
|
|
str.erase(0, pos);
|
2011-03-24 16:08:24 +00:00
|
|
|
else
|
2011-04-07 13:42:25 +00:00
|
|
|
str.clear();
|
2011-03-24 16:08:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* trim right of string
|
|
|
|
*/
|
2011-04-07 13:42:25 +00:00
|
|
|
void Tle::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);
|
2011-03-24 16:08:24 +00:00
|
|
|
|
|
|
|
if (pos != std::string::npos)
|
2011-04-07 13:42:25 +00:00
|
|
|
str.erase(pos + 1);
|
2011-03-24 16:08:24 +00:00
|
|
|
else
|
2011-04-07 13:42:25 +00:00
|
|
|
str.clear();
|
2011-03-24 16:08:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|