/[PAMELA software]/YodaProfiler/src/cTle.cpp
ViewVC logotype

Contents of /YodaProfiler/src/cTle.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations) (download)
Fri Oct 20 11:39:39 2006 UTC (18 years, 1 month ago) by mocchiut
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
FILE REMOVED
Create libsgp4.so shared lib; unified sgp4 code

1 //
2 // cTle.cpp
3 // This class encapsulates a single set of standard NORAD two line elements.
4 //
5 // Copyright 1996-2005 Michael F. Henry
6 //
7 #include "stdafx.h"
8
9 #include "cTle.h"
10
11 // Note: The column offsets are ZERO based.
12
13 // Name
14 const int TLE_LEN_LINE_DATA = 69; const int TLE_LEN_LINE_NAME = 22;
15
16 // Line 1
17 const int TLE1_COL_SATNUM = 2; const int TLE1_LEN_SATNUM = 5;
18 const int TLE1_COL_INTLDESC_A = 9; const int TLE1_LEN_INTLDESC_A = 2;
19 const int TLE1_COL_INTLDESC_B = 11; const int TLE1_LEN_INTLDESC_B = 3;
20 const int TLE1_COL_INTLDESC_C = 14; const int TLE1_LEN_INTLDESC_C = 3;
21 const int TLE1_COL_EPOCH_A = 18; const int TLE1_LEN_EPOCH_A = 2;
22 const int TLE1_COL_EPOCH_B = 20; const int TLE1_LEN_EPOCH_B = 12;
23 const int TLE1_COL_MEANMOTIONDT = 33; const int TLE1_LEN_MEANMOTIONDT = 10;
24 const int TLE1_COL_MEANMOTIONDT2 = 44; const int TLE1_LEN_MEANMOTIONDT2 = 8;
25 const int TLE1_COL_BSTAR = 53; const int TLE1_LEN_BSTAR = 8;
26 const int TLE1_COL_EPHEMTYPE = 62; const int TLE1_LEN_EPHEMTYPE = 1;
27 const int TLE1_COL_ELNUM = 64; const int TLE1_LEN_ELNUM = 4;
28
29 // Line 2
30 const int TLE2_COL_SATNUM = 2; const int TLE2_LEN_SATNUM = 5;
31 const int TLE2_COL_INCLINATION = 8; const int TLE2_LEN_INCLINATION = 8;
32 const int TLE2_COL_RAASCENDNODE = 17; const int TLE2_LEN_RAASCENDNODE = 8;
33 const int TLE2_COL_ECCENTRICITY = 26; const int TLE2_LEN_ECCENTRICITY = 7;
34 const int TLE2_COL_ARGPERIGEE = 34; const int TLE2_LEN_ARGPERIGEE = 8;
35 const int TLE2_COL_MEANANOMALY = 43; const int TLE2_LEN_MEANANOMALY = 8;
36 const int TLE2_COL_MEANMOTION = 52; const int TLE2_LEN_MEANMOTION = 11;
37 const int TLE2_COL_REVATEPOCH = 63; const int TLE2_LEN_REVATEPOCH = 5;
38
39 /////////////////////////////////////////////////////////////////////////////
40 cTle::cTle(string& strName, string& strLine1, string& strLine2)
41 {
42 m_strName = strName;
43 m_strLine1 = strLine1;
44 m_strLine2 = strLine2;
45
46 Initialize();
47 }
48
49 /////////////////////////////////////////////////////////////////////////////
50 cTle::cTle(const cTle &tle)
51 {
52 m_strName = tle.m_strName;
53 m_strLine1 = tle.m_strLine1;
54 m_strLine2 = tle.m_strLine2;
55
56 for (int fld = FLD_FIRST; fld < FLD_LAST; fld++)
57 {
58 m_Field[fld] = tle.m_Field[fld];
59 }
60
61 m_mapCache = tle.m_mapCache;
62 }
63
64 /////////////////////////////////////////////////////////////////////////////
65 cTle::~cTle()
66 {
67 }
68
69 /////////////////////////////////////////////////////////////////////////////
70 // getField()
71 // Return requested field as a double (function return value) or as a text
72 // string (*pstr) in the units requested (eUnit). Set 'bStrUnits' to true
73 // to have units appended to text string.
74 //
75 // Note: numeric return values are cached; asking for the same field more
76 // than once incurs minimal overhead.
77 double cTle::getField(eField fld,
78 eUnits units, /* = U_NATIVE */
79 string *pstr /* = NULL */,
80 bool bStrUnits /* = false */) const
81 {
82 assert((FLD_FIRST <= fld) && (fld < FLD_LAST));
83 assert((U_FIRST <= units) && (units < U_LAST));
84
85 if (pstr)
86 {
87 // Return requested field in string form.
88 *pstr = m_Field[fld];
89
90 if (bStrUnits)
91 *pstr += getUnits(fld);
92
93 return 0.0;
94 }
95 else
96 {
97 // Return requested field in floating-point form.
98 // Return cache contents if it exists, else populate cache
99 FldKey key = Key(units, fld);
100
101 if (m_mapCache.find(key) == m_mapCache.end())
102 {
103 // Value not in cache; add it
104 double valNative = atof(m_Field[fld].c_str());
105 double valConv = ConvertUnits(valNative, fld, units);
106 m_mapCache[key] = valConv;
107
108 return valConv;
109 }
110 else
111 {
112 // return cached value
113 return m_mapCache[key];
114 }
115 }
116 }
117
118 //////////////////////////////////////////////////////////////////////////////
119 // Convert the given field into the requested units. It is assumed that
120 // the value being converted is in the TLE format's "native" form.
121 double cTle::ConvertUnits(double valNative, // value to convert
122 eField fld, // what field the value is
123 eUnits units) // what units to convert to
124 {
125 switch (fld)
126 {
127 case FLD_I:
128 case FLD_RAAN:
129 case FLD_ARGPER:
130 case FLD_M:
131 {
132 // The native TLE format is DEGREES
133 if (units == U_RAD)
134 return valNative * RADS_PER_DEG;
135 }
136
137 case FLD_NORADNUM:
138 case FLD_INTLDESC:
139 case FLD_SET:
140 case FLD_EPOCHYEAR:
141 case FLD_EPOCHDAY:
142 case FLD_ORBITNUM:
143 case FLD_E:
144 case FLD_MMOTION:
145 case FLD_MMOTIONDT:
146 case FLD_MMOTIONDT2:
147 case FLD_BSTAR:
148 case FLD_LAST:
149 { // do nothing
150
151 }
152
153 }
154
155 return valNative; // return value in unconverted native format
156 }
157
158 //////////////////////////////////////////////////////////////////////////////
159 string cTle::getUnits(eField fld) const
160 {
161 static const string strDegrees = " degrees";
162 static const string strRevsPerDay = " revs / day";
163 static const string strNull;
164
165 switch (fld)
166 {
167 case FLD_I:
168 case FLD_RAAN:
169 case FLD_ARGPER:
170 case FLD_M:
171 return strDegrees;
172
173 case FLD_MMOTION:
174 return strRevsPerDay;
175
176 default:
177 return strNull;
178 }
179 }
180
181 /////////////////////////////////////////////////////////////////////////////
182 // ExpToDecimal()
183 // Converts TLE-style exponential notation of the form [ |-]00000[+|-]0 to
184 // decimal notation. Assumes implied decimal point to the left of the first
185 // number in the string, i.e.,
186 // " 12345-3" = 0.00012345
187 // "-23429-5" = -0.0000023429
188 // " 40436+1" = 4.0436
189 string cTle::ExpToDecimal(const string &str)
190 {
191 const int COL_EXP_SIGN = 6;
192 const int LEN_EXP = 2;
193
194 const int LEN_BUFREAL = 32; // max length of buffer to hold floating point
195 // representation of input string.
196 int nMan;
197 int nExp;
198
199 // sscanf(%d) will read up to the exponent sign
200 sscanf(str.c_str(), "%d", &nMan);
201
202 double dblMan = nMan;
203 bool bNeg = (nMan < 0);
204
205 if (bNeg)
206 dblMan *= -1;
207
208 // Move decimal place to left of first digit
209 while (dblMan >= 1.0)
210 dblMan /= 10.0;
211
212 if (bNeg)
213 dblMan *= -1;
214
215 // now read exponent
216 sscanf(str.substr(COL_EXP_SIGN, LEN_EXP).c_str(), "%d", &nExp);
217
218 double dblVal = dblMan * pow(10.0, nExp);
219 char szVal[LEN_BUFREAL];
220
221 snprintf(szVal, sizeof(szVal), "%.9f", dblVal);
222
223 string strVal = szVal;
224
225 return strVal;
226
227 } // ExpToDecimal()
228
229 /////////////////////////////////////////////////////////////////////////////
230 // Initialize()
231 // Initialize the string array.
232 void cTle::Initialize()
233 {
234 // Have we already been initialized?
235 if (m_Field[FLD_NORADNUM].size())
236 return;
237
238 assert(!m_strName.empty());
239 assert(!m_strLine1.empty());
240 assert(!m_strLine2.empty());
241
242 m_Field[FLD_NORADNUM] = m_strLine1.substr(TLE1_COL_SATNUM, TLE1_LEN_SATNUM);
243 m_Field[FLD_INTLDESC] = m_strLine1.substr(TLE1_COL_INTLDESC_A,
244 TLE1_LEN_INTLDESC_A +
245 TLE1_LEN_INTLDESC_B +
246 TLE1_LEN_INTLDESC_C);
247 m_Field[FLD_EPOCHYEAR] =
248 m_strLine1.substr(TLE1_COL_EPOCH_A, TLE1_LEN_EPOCH_A);
249
250 m_Field[FLD_EPOCHDAY] =
251 m_strLine1.substr(TLE1_COL_EPOCH_B, TLE1_LEN_EPOCH_B);
252
253 if (m_strLine1[TLE1_COL_MEANMOTIONDT] == '-')
254 {
255 // value is negative
256 m_Field[FLD_MMOTIONDT] = "-0";
257 }
258 else
259 m_Field[FLD_MMOTIONDT] = "0";
260
261 m_Field[FLD_MMOTIONDT] += m_strLine1.substr(TLE1_COL_MEANMOTIONDT + 1,
262 TLE1_LEN_MEANMOTIONDT);
263
264 // decimal point assumed; exponential notation
265 m_Field[FLD_MMOTIONDT2] = ExpToDecimal(
266 m_strLine1.substr(TLE1_COL_MEANMOTIONDT2,
267 TLE1_LEN_MEANMOTIONDT2));
268 // decimal point assumed; exponential notation
269 m_Field[FLD_BSTAR] = ExpToDecimal(m_strLine1.substr(TLE1_COL_BSTAR,
270 TLE1_LEN_BSTAR));
271 //TLE1_COL_EPHEMTYPE
272 //TLE1_LEN_EPHEMTYPE
273 m_Field[FLD_SET] = m_strLine1.substr(TLE1_COL_ELNUM, TLE1_LEN_ELNUM);
274
275 TrimLeft(m_Field[FLD_SET]);
276
277 //TLE2_COL_SATNUM
278 //TLE2_LEN_SATNUM
279
280 m_Field[FLD_I] = m_strLine2.substr(TLE2_COL_INCLINATION,
281 TLE2_LEN_INCLINATION);
282 TrimLeft(m_Field[FLD_I]);
283
284 m_Field[FLD_RAAN] = m_strLine2.substr(TLE2_COL_RAASCENDNODE,
285 TLE2_LEN_RAASCENDNODE);
286 TrimLeft(m_Field[FLD_RAAN]);
287
288 // decimal point is assumed
289 m_Field[FLD_E] = "0.";
290 m_Field[FLD_E] += m_strLine2.substr(TLE2_COL_ECCENTRICITY,
291 TLE2_LEN_ECCENTRICITY);
292
293 m_Field[FLD_ARGPER] = m_strLine2.substr(TLE2_COL_ARGPERIGEE,
294 TLE2_LEN_ARGPERIGEE);
295 TrimLeft(m_Field[FLD_ARGPER]);
296
297 m_Field[FLD_M] = m_strLine2.substr(TLE2_COL_MEANANOMALY,
298 TLE2_LEN_MEANANOMALY);
299 TrimLeft(m_Field[FLD_M]);
300
301 m_Field[FLD_MMOTION] = m_strLine2.substr(TLE2_COL_MEANMOTION,
302 TLE2_LEN_MEANMOTION);
303 TrimLeft(m_Field[FLD_MMOTION]);
304
305 m_Field[FLD_ORBITNUM] = m_strLine2.substr(TLE2_COL_REVATEPOCH,
306 TLE2_LEN_REVATEPOCH);
307 TrimLeft(m_Field[FLD_ORBITNUM]);
308
309 } // InitStrVars()
310
311 /////////////////////////////////////////////////////////////////////////////
312 // IsTleFormat()
313 // Returns true if "str" is a valid data line of a two-line element set,
314 // else false.
315 //
316 // To be valid a line must:
317 // Have as the first character the line number
318 // Have as the second character a blank
319 // Be TLE_LEN_LINE_DATA characters long
320 // Have a valid checksum (note: no longer required as of 12/96)
321 //
322 bool cTle::IsValidLine(string& str, eTleLine line)
323 {
324 TrimLeft(str);
325 TrimRight(str);
326
327 size_t nLen = str.size();
328
329 if (nLen != (uint)TLE_LEN_LINE_DATA)
330 return false;
331
332 // First char in string must be line number
333 if ((str[0] - '0') != line)
334 return false;
335
336 // Second char in string must be blank
337 if (str[1] != ' ')
338 return false;
339
340 /*
341 NOTE: 12/96
342 The requirement that the last char in the line data must be a valid
343 checksum is too restrictive.
344
345 // Last char in string must be checksum
346 int nSum = CheckSum(str);
347
348 if (nSum != (str[TLE_LEN_LINE_DATA - 1] - '0'))
349 return false;
350 */
351
352 return true;
353
354 } // IsTleFormat()
355
356 /////////////////////////////////////////////////////////////////////////////
357 // CheckSum()
358 // Calculate the check sum for a given line of TLE data, the last character
359 // of which is the current checksum. (Although there is no check here,
360 // the current checksum should match the one we calculate.)
361 // The checksum algorithm:
362 // Each number in the data line is summed, modulo 10.
363 // Non-numeric characters are zero, except minus signs, which are 1.
364 //
365 int cTle::CheckSum(const string& str)
366 {
367 // The length is "- 1" because we don't include the current (existing)
368 // checksum character in the checksum calculation.
369 size_t len = str.size() - 1;
370 int xsum = 0;
371
372 for (size_t i = 0; i < len; i++)
373 {
374 char ch = str[i];
375 if (isdigit(ch))
376 xsum += (ch - '0');
377 else if (ch == '-')
378 xsum++;
379 }
380
381 return (xsum % 10);
382
383 } // CheckSum()
384
385 /////////////////////////////////////////////////////////////////////////////
386 void cTle::TrimLeft(string& s)
387 {
388 while (s[0] == ' ')
389 s.erase(0, 1);
390 }
391
392 /////////////////////////////////////////////////////////////////////////////
393 void cTle::TrimRight(string& s)
394 {
395 while (s[s.size() - 1] == ' ')
396 s.erase(s.size() - 1);
397 }
398

  ViewVC Help
Powered by ViewVC 1.1.23