Sergey S / MODGPS

Fork of MODGPS by Andy K

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GPS_Time.cpp Source File

GPS_Time.cpp

00001 /*
00002     Copyright (c) 2010 Andy Kirkham
00003  
00004     Permission is hereby granted, free of charge, to any person obtaining a copy
00005     of this software and associated documentation files (the "Software"), to deal
00006     in the Software without restriction, including without limitation the rights
00007     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008     copies of the Software, and to permit persons to whom the Software is
00009     furnished to do so, subject to the following conditions:
00010  
00011     The above copyright notice and this permission notice shall be included in
00012     all copies or substantial portions of the Software.
00013  
00014     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020     THE SOFTWARE.
00021 */
00022 
00023 #include "GPS_Time.h"
00024 
00025 GPS_Time::GPS_Time() {
00026     year = 2000;
00027     month = 1;
00028     day = 1;
00029     hour = 0;
00030     minute = 0;
00031     second = 0;
00032     tenths = 0;
00033     hundreths = 0;
00034     status = 'V';
00035     velocity = 0;
00036     track = 0;    
00037     magvar_dir = 'W';
00038     magvar = 0;
00039 }
00040 
00041 time_t GPS_Time::to_C_tm(bool set) {
00042     GPS_Time t;
00043     tm       ct;
00044     time_t   q;
00045     
00046     timeNow(&t);
00047     ct.tm_sec       = t.second;
00048     ct.tm_min       = t.minute;
00049     ct.tm_hour      = t.hour;
00050     ct.tm_mday      = t.day;
00051     ct.tm_mon       = t.month - 1;
00052     ct.tm_year      = t.year - 1900;
00053     ct.tm_isdst     = 0; // GPS has no understanding of DST.    
00054     
00055     q = mktime(&ct);
00056     if (set) {
00057         set_time(q);
00058     }
00059     return q;
00060 }
00061 
00062 GPS_Time * GPS_Time::timeNow(GPS_Time *n) {
00063     if (n == NULL) 
00064         n = new GPS_Time;
00065     
00066     do {
00067         memcpy(n, this, sizeof(GPS_Time));
00068     }
00069     while (memcmp(n, this, sizeof(GPS_Time)));
00070     return n;    
00071 }
00072 
00073 void GPS_Time::operator++() {
00074     hundreths++;
00075     if (hundreths == 10) {
00076         hundreths = 0;
00077         tenths++;
00078         if (tenths == 10) {
00079             tenths = hundreths = 0;
00080         }
00081     }
00082 }
00083 
00084 void GPS_Time::operator++(int) {
00085     const int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
00086     bool dateInc = false;
00087     
00088     tenths = hundreths = 0;
00089     second++;
00090     
00091     if (second == 60) {
00092         second = 0;
00093         minute++;
00094         if (minute == 60) {
00095             minute = 0;
00096             hour++;
00097             if (hour == 24) {
00098                 hour = 0;
00099                 dateInc = true;
00100             }
00101         }
00102     }
00103     
00104     if (dateInc) {
00105         /* Handle February leap year. */    
00106         int leap_year = ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 1 : 0;
00107         int days_this_month = days[month - 1];
00108         if (month == 2 && leap_year) days_this_month++;        
00109         day++;
00110         if (day > days_this_month) {
00111             day = 1;
00112             month++;
00113             if (month == 13) {
00114                 year++;
00115             }
00116         }
00117     }
00118 }
00119 
00120 // $GPRMC,112709.735,A,5611.5340,N,00302.0306,W,000.0,307.0,150411,,,A*70
00121 void GPS_Time::nmea_rmc(char *s) {
00122     char *token;
00123     int  token_counter = 0;
00124     char *time   = (char *)NULL;
00125     char *date   = (char *)NULL;
00126     char *stat   = (char *)NULL;
00127     char *vel    = (char *)NULL;
00128     char *trk    = (char *)NULL;
00129     char *magv   = (char *)NULL;
00130     char *magd   = (char *)NULL;
00131 
00132     token = strtok(s, ",");
00133     while (token) {
00134         switch (token_counter) {
00135             case 9:  date   = token; break;
00136             case 1:  time   = token; break;
00137             case 2:  stat   = token; break;
00138             case 7:  vel    = token; break;
00139             case 8:  trk    = token; break;
00140             case 10: magv   = token; break;
00141             case 11: magd   = token; break;
00142         }
00143         token = strtok((char *)NULL, ",");
00144         token_counter++;
00145     }
00146     
00147     if (stat && date && time) {
00148         hour       = (char)((time[0] - '0') * 10) + (time[1] - '0');
00149         minute     = (char)((time[2] - '0') * 10) + (time[3] - '0');
00150         second     = (char)((time[4] - '0') * 10) + (time[5] - '0');
00151         day        = (char)((date[0] - '0') * 10) + (date[1] - '0');
00152         month      = (char)((date[2] - '0') * 10) + (date[3] - '0');
00153         year       =  (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
00154         status     = stat[0];
00155         velocity   = atof(vel);
00156         track      = atof(trk);
00157         magvar     = atof(magv);
00158         magvar_dir = magd[0];
00159     }    
00160 }
00161 
00162 double GPS_Time::julian_day_number(GPS_Time *t) {
00163     double wikipedia_jdn = (double)(1461 * ((int)t->year + 4800 + ((int)t->month - 14) / 12)) / 4 + (367 * ((int)t->month - 2 - 12 * (((int)t->month - 14) / 12))) / 12 - (3 * (((int)t->year + 4900 + ((int)t->month - 14) / 12 ) / 100)) / 4 + (int)t->day - 32075;    
00164     return wikipedia_jdn;
00165 }
00166 
00167 double GPS_Time::julian_date(GPS_Time *t) {
00168     double hour, minute, second, jd;
00169     hour   = (double)t->hour;
00170     minute = (double)t->minute;
00171     second = (double)t->second + ((double)t->tenths / 10.) + ((double)t->hundreths / 100.);
00172                                  
00173     jd = julian_day_number(t) -  0.5 +
00174          ((hour - 12.) / 24.) +
00175          (minute / 1440.) + 
00176          (second / 86400.);        
00177         
00178     return jd;
00179 }
00180 
00181 double GPS_Time::siderealDegrees(double jd, double longitude) {
00182     double sidereal, gmst, lmst;
00183     double T  = jd - 2451545.0;
00184     double T1 = T / 36525.0;
00185     double T2 = T1 * T1;
00186     double T3 = T2 * T1;
00187      
00188     /* Calculate gmst angle. */
00189     sidereal = 280.46061837 + (360.98564736629 * T) + (0.000387933 * T2) - (T3 / 38710000.0);
00190      
00191     /* Convert to degrees. */
00192     sidereal = fmod(sidereal, 360.0);
00193     if (sidereal < 0.0) sidereal += 360.0;
00194  
00195     gmst = sidereal;
00196     lmst = gmst + longitude;
00197     return lmst;
00198 }
00199 
00200 double GPS_Time::siderealDegrees(GPS_Time *t, double longitude) {
00201     if (t == NULL) t = new GPS_Time;
00202     return siderealDegrees(julian_date(t), longitude);
00203 }
00204 
00205 double GPS_Time::siderealHA(double jd, double longitude) {
00206     double lmst = siderealDegrees(jd, longitude);
00207     return lmst / 360.0 * 24.0;
00208 }
00209 
00210 double GPS_Time::siderealHA(GPS_Time *t, double longitude) {
00211     double lmst = siderealDegrees(t, longitude);
00212     return lmst / 360.0 * 24.0;
00213 }
00214