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

Annotation of /YodaProfiler/src/cTle.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide 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 mocchiut 1.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