/[PAMELA software]/yodaUtility/sgp4/cTle.cpp
ViewVC logotype

Annotation of /yodaUtility/sgp4/cTle.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations) (download)
Sun Apr 30 11:08:15 2006 UTC (18 years, 7 months ago) by kusanagi
Branch point for: MAIN
Initial revision

1 kusanagi 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    
138     return valNative; // return value in unconverted native format
139     }
140    
141     //////////////////////////////////////////////////////////////////////////////
142     string cTle::getUnits(eField fld) const
143     {
144     static const string strDegrees = " degrees";
145     static const string strRevsPerDay = " revs / day";
146     static const string strNull;
147    
148     switch (fld)
149     {
150     case FLD_I:
151     case FLD_RAAN:
152     case FLD_ARGPER:
153     case FLD_M:
154     return strDegrees;
155    
156     case FLD_MMOTION:
157     return strRevsPerDay;
158    
159     default:
160     return strNull;
161     }
162     }
163    
164     /////////////////////////////////////////////////////////////////////////////
165     // ExpToDecimal()
166     // Converts TLE-style exponential notation of the form [ |-]00000[+|-]0 to
167     // decimal notation. Assumes implied decimal point to the left of the first
168     // number in the string, i.e.,
169     // " 12345-3" = 0.00012345
170     // "-23429-5" = -0.0000023429
171     // " 40436+1" = 4.0436
172     string cTle::ExpToDecimal(const string &str)
173     {
174     const int COL_EXP_SIGN = 6;
175     const int LEN_EXP = 2;
176    
177     const int LEN_BUFREAL = 32; // max length of buffer to hold floating point
178     // representation of input string.
179     int nMan;
180     int nExp;
181    
182     // sscanf(%d) will read up to the exponent sign
183     sscanf(str.c_str(), "%d", &nMan);
184    
185     double dblMan = nMan;
186     bool bNeg = (nMan < 0);
187    
188     if (bNeg)
189     dblMan *= -1;
190    
191     // Move decimal place to left of first digit
192     while (dblMan >= 1.0)
193     dblMan /= 10.0;
194    
195     if (bNeg)
196     dblMan *= -1;
197    
198     // now read exponent
199     sscanf(str.substr(COL_EXP_SIGN, LEN_EXP).c_str(), "%d", &nExp);
200    
201     double dblVal = dblMan * pow(10.0, nExp);
202     char szVal[LEN_BUFREAL];
203    
204     snprintf(szVal, sizeof(szVal), "%.9f", dblVal);
205    
206     string strVal = szVal;
207    
208     return strVal;
209    
210     } // ExpToDecimal()
211    
212     /////////////////////////////////////////////////////////////////////////////
213     // Initialize()
214     // Initialize the string array.
215     void cTle::Initialize()
216     {
217     // Have we already been initialized?
218     if (m_Field[FLD_NORADNUM].size())
219     return;
220    
221     assert(!m_strName.empty());
222     assert(!m_strLine1.empty());
223     assert(!m_strLine2.empty());
224    
225     m_Field[FLD_NORADNUM] = m_strLine1.substr(TLE1_COL_SATNUM, TLE1_LEN_SATNUM);
226     m_Field[FLD_INTLDESC] = m_strLine1.substr(TLE1_COL_INTLDESC_A,
227     TLE1_LEN_INTLDESC_A +
228     TLE1_LEN_INTLDESC_B +
229     TLE1_LEN_INTLDESC_C);
230     m_Field[FLD_EPOCHYEAR] =
231     m_strLine1.substr(TLE1_COL_EPOCH_A, TLE1_LEN_EPOCH_A);
232    
233     m_Field[FLD_EPOCHDAY] =
234     m_strLine1.substr(TLE1_COL_EPOCH_B, TLE1_LEN_EPOCH_B);
235    
236     if (m_strLine1[TLE1_COL_MEANMOTIONDT] == '-')
237     {
238     // value is negative
239     m_Field[FLD_MMOTIONDT] = "-0";
240     }
241     else
242     m_Field[FLD_MMOTIONDT] = "0";
243    
244     m_Field[FLD_MMOTIONDT] += m_strLine1.substr(TLE1_COL_MEANMOTIONDT + 1,
245     TLE1_LEN_MEANMOTIONDT);
246    
247     // decimal point assumed; exponential notation
248     m_Field[FLD_MMOTIONDT2] = ExpToDecimal(
249     m_strLine1.substr(TLE1_COL_MEANMOTIONDT2,
250     TLE1_LEN_MEANMOTIONDT2));
251     // decimal point assumed; exponential notation
252     m_Field[FLD_BSTAR] = ExpToDecimal(m_strLine1.substr(TLE1_COL_BSTAR,
253     TLE1_LEN_BSTAR));
254     //TLE1_COL_EPHEMTYPE
255     //TLE1_LEN_EPHEMTYPE
256     m_Field[FLD_SET] = m_strLine1.substr(TLE1_COL_ELNUM, TLE1_LEN_ELNUM);
257    
258     TrimLeft(m_Field[FLD_SET]);
259    
260     //TLE2_COL_SATNUM
261     //TLE2_LEN_SATNUM
262    
263     m_Field[FLD_I] = m_strLine2.substr(TLE2_COL_INCLINATION,
264     TLE2_LEN_INCLINATION);
265     TrimLeft(m_Field[FLD_I]);
266    
267     m_Field[FLD_RAAN] = m_strLine2.substr(TLE2_COL_RAASCENDNODE,
268     TLE2_LEN_RAASCENDNODE);
269     TrimLeft(m_Field[FLD_RAAN]);
270    
271     // decimal point is assumed
272     m_Field[FLD_E] = "0.";
273     m_Field[FLD_E] += m_strLine2.substr(TLE2_COL_ECCENTRICITY,
274     TLE2_LEN_ECCENTRICITY);
275    
276     m_Field[FLD_ARGPER] = m_strLine2.substr(TLE2_COL_ARGPERIGEE,
277     TLE2_LEN_ARGPERIGEE);
278     TrimLeft(m_Field[FLD_ARGPER]);
279    
280     m_Field[FLD_M] = m_strLine2.substr(TLE2_COL_MEANANOMALY,
281     TLE2_LEN_MEANANOMALY);
282     TrimLeft(m_Field[FLD_M]);
283    
284     m_Field[FLD_MMOTION] = m_strLine2.substr(TLE2_COL_MEANMOTION,
285     TLE2_LEN_MEANMOTION);
286     TrimLeft(m_Field[FLD_MMOTION]);
287    
288     m_Field[FLD_ORBITNUM] = m_strLine2.substr(TLE2_COL_REVATEPOCH,
289     TLE2_LEN_REVATEPOCH);
290     TrimLeft(m_Field[FLD_ORBITNUM]);
291    
292     } // InitStrVars()
293    
294     /////////////////////////////////////////////////////////////////////////////
295     // IsTleFormat()
296     // Returns true if "str" is a valid data line of a two-line element set,
297     // else false.
298     //
299     // To be valid a line must:
300     // Have as the first character the line number
301     // Have as the second character a blank
302     // Be TLE_LEN_LINE_DATA characters long
303     // Have a valid checksum (note: no longer required as of 12/96)
304     //
305     bool cTle::IsValidLine(string& str, eTleLine line)
306     {
307     TrimLeft(str);
308     TrimRight(str);
309    
310     size_t nLen = str.size();
311    
312     if (nLen != TLE_LEN_LINE_DATA)
313     return false;
314    
315     // First char in string must be line number
316     if ((str[0] - '0') != line)
317     return false;
318    
319     // Second char in string must be blank
320     if (str[1] != ' ')
321     return false;
322    
323     /*
324     NOTE: 12/96
325     The requirement that the last char in the line data must be a valid
326     checksum is too restrictive.
327    
328     // Last char in string must be checksum
329     int nSum = CheckSum(str);
330    
331     if (nSum != (str[TLE_LEN_LINE_DATA - 1] - '0'))
332     return false;
333     */
334    
335     return true;
336    
337     } // IsTleFormat()
338    
339     /////////////////////////////////////////////////////////////////////////////
340     // CheckSum()
341     // Calculate the check sum for a given line of TLE data, the last character
342     // of which is the current checksum. (Although there is no check here,
343     // the current checksum should match the one we calculate.)
344     // The checksum algorithm:
345     // Each number in the data line is summed, modulo 10.
346     // Non-numeric characters are zero, except minus signs, which are 1.
347     //
348     int cTle::CheckSum(const string& str)
349     {
350     // The length is "- 1" because we don't include the current (existing)
351     // checksum character in the checksum calculation.
352     size_t len = str.size() - 1;
353     int xsum = 0;
354    
355     for (size_t i = 0; i < len; i++)
356     {
357     char ch = str[i];
358     if (isdigit(ch))
359     xsum += (ch - '0');
360     else if (ch == '-')
361     xsum++;
362     }
363    
364     return (xsum % 10);
365    
366     } // CheckSum()
367    
368     /////////////////////////////////////////////////////////////////////////////
369     void cTle::TrimLeft(string& s)
370     {
371     while (s[0] == ' ')
372     s.erase(0, 1);
373     }
374    
375     /////////////////////////////////////////////////////////////////////////////
376     void cTle::TrimRight(string& s)
377     {
378     while (s[s.size() - 1] == ' ')
379     s.erase(s.size() - 1);
380     }
381    

  ViewVC Help
Powered by ViewVC 1.1.23