diff options
author | Helmut Schmidt <Helmut.3.Schmidt@continental-corporation.com> | 2016-09-16 15:12:27 +0200 |
---|---|---|
committer | Helmut Schmidt <Helmut.3.Schmidt@continental-corporation.com> | 2016-09-16 15:12:27 +0200 |
commit | cca2e8710939fbe58fda48079efa325968de700e (patch) | |
tree | 9914a5c274abc54feddd506924a5a5a02d95f29c /gnss-service | |
parent | f341b4a2cb216d6204136794d33076170ab1bf80 (diff) | |
download | positioning-cca2e8710939fbe58fda48079efa325968de700e.tar.gz |
Positioning Poc: Multiconstellation NMEA support
Diffstat (limited to 'gnss-service')
-rw-r--r-- | gnss-service/src/gnss-use-nmea.cpp | 129 | ||||
-rw-r--r-- | gnss-service/src/hnmea.cpp | 302 | ||||
-rw-r--r-- | gnss-service/src/hnmea.h | 65 |
3 files changed, 278 insertions, 218 deletions
diff --git a/gnss-service/src/gnss-use-nmea.cpp b/gnss-service/src/gnss-use-nmea.cpp index 6286a6c..5ee9b02 100644 --- a/gnss-service/src/gnss-use-nmea.cpp +++ b/gnss-service/src/gnss-use-nmea.cpp @@ -124,32 +124,32 @@ void setGNSSStatus(EGNSSStatus newStatus) } /** - * Convert GPS data from NMEA parser to TGNSSPosition struct - * @param gps_data [IN] GPS data decoded from NMEA parser + * Convert GNSS data from NMEA parser to TGNSSPosition struct + * @param gns_data [IN] GNSS data decoded from NMEA parser * @param timestamp [IN] timestamp in milliseconds - * @param gnss_pos [OUT] TGNSSPosition struct which will be filled with gps_data and timestamp + * @param gnss_pos [OUT] TGNSSPosition struct which will be filled with gns_data and timestamp * @return conversion has been successful */ -bool extractPosition(const GPS_DATA& gps_data, uint64_t timestamp, TGNSSPosition& gnss_pos) +bool extractPosition(const GNS_DATA& gns_data, uint64_t timestamp, TGNSSPosition& gnss_pos) { gnss_pos.validityBits = 0; gnss_pos.timestamp = timestamp; - if (gps_data.valid & GPS_DATA_LAT) + if (gns_data.valid & GNS_DATA_LAT) { - gnss_pos.latitude = gps_data.lat; + gnss_pos.latitude = gns_data.lat; gnss_pos.validityBits |= GNSS_POSITION_LATITUDE_VALID; } - if (gps_data.valid & GPS_DATA_LON) + if (gns_data.valid & GNS_DATA_LON) { - gnss_pos.longitude = gps_data.lon; + gnss_pos.longitude = gns_data.lon; gnss_pos.validityBits |= GNSS_POSITION_LONGITUDE_VALID; } - if (gps_data.valid & GPS_DATA_ALT) + if (gns_data.valid & GNS_DATA_ALT) { - gnss_pos.altitudeMSL = gps_data.alt; + gnss_pos.altitudeMSL = gns_data.alt; gnss_pos.validityBits |= GNSS_POSITION_ALTITUDEMSL_VALID; - if (gps_data.valid & GPS_DATA_GEOID) + if (gns_data.valid & GNS_DATA_GEOID) { //Geoid separation terminology might be difficult to understand //You can cross check your NMEA output and calculation results @@ -157,51 +157,51 @@ bool extractPosition(const GPS_DATA& gps_data, uint64_t timestamp, TGNSSPosition // http://www.unavco.org/software/geodetic-utilities/geoid-height-calculator/geoid-height-calculator.html // http://earth-info.nga.mil/GandG/wgs84/gravitymod/wgs84_180/intptWhel.html // http://geographiclib.sourceforge.net/cgi-bin/GeoidEval - gnss_pos.altitudeEll = gps_data.alt+gps_data.geoid; + gnss_pos.altitudeEll = gns_data.alt+gns_data.geoid; gnss_pos.validityBits |= GNSS_POSITION_ALTITUDEELL_VALID; } } - if (gps_data.valid & GPS_DATA_SPEED) + if (gns_data.valid & GNS_DATA_SPEED) { - gnss_pos.hSpeed = gps_data.speed; + gnss_pos.hSpeed = gns_data.speed; gnss_pos.validityBits |= GNSS_POSITION_HSPEED_VALID; } gnss_pos.vSpeed = 9999; //not available - if (gps_data.valid & GPS_DATA_SPEED) + if (gns_data.valid & GNS_DATA_COURSE) { - gnss_pos.heading = gps_data.course; - gnss_pos.validityBits |= GPS_DATA_COURSE; + gnss_pos.heading = gns_data.course; + gnss_pos.validityBits |= GNSS_POSITION_HEADING_VALID; } - if (gps_data.valid & GPS_DATA_PDOP) + if (gns_data.valid & GNS_DATA_PDOP) { - gnss_pos.pdop = gps_data.pdop; + gnss_pos.pdop = gns_data.pdop; gnss_pos.validityBits |= GNSS_POSITION_PDOP_VALID; } - if (gps_data.valid & GPS_DATA_HDOP) + if (gns_data.valid & GNS_DATA_HDOP) { - gnss_pos.hdop = gps_data.hdop; + gnss_pos.hdop = gns_data.hdop; gnss_pos.validityBits |= GNSS_POSITION_HDOP_VALID; } - if (gps_data.valid & GPS_DATA_VDOP) + if (gns_data.valid & GNS_DATA_VDOP) { - gnss_pos.vdop = gps_data.vdop; + gnss_pos.vdop = gns_data.vdop; gnss_pos.validityBits |= GNSS_POSITION_VDOP_VALID; } - if (gps_data.valid & GPS_DATA_USAT) + if (gns_data.valid & GNS_DATA_USAT) { - gnss_pos.usedSatellites = gps_data.usat; + gnss_pos.usedSatellites = gns_data.usat; gnss_pos.validityBits |= GNSS_POSITION_USAT_VALID; } gnss_pos.trackedSatellites = 9999; //not available gnss_pos.visibleSatellites = 9999; //not available - if (gps_data.valid & GPS_DATA_HACC) + if (gns_data.valid & GNS_DATA_HACC) { - gnss_pos.sigmaHPosition = gps_data.hacc; + gnss_pos.sigmaHPosition = gns_data.hacc; gnss_pos.validityBits |= GNSS_POSITION_SHPOS_VALID; } - if (gps_data.valid & GPS_DATA_HACC) + if (gns_data.valid & GNS_DATA_VACC) { - gnss_pos.sigmaAltitude = gps_data.vacc; + gnss_pos.sigmaAltitude = gns_data.vacc; gnss_pos.validityBits |= GNSS_POSITION_SALT_VALID; } @@ -211,14 +211,14 @@ bool extractPosition(const GPS_DATA& gps_data, uint64_t timestamp, TGNSSPosition gnss_pos.validityBits |= GNSS_POSITION_STAT_VALID; //always valid gnss_pos.fixStatus = GNSS_FIX_STATUS_NO; - if (gps_data.valid & GPS_DATA_FIX2D) + if (gns_data.valid & GNS_DATA_FIX2D) { - if (gps_data.fix2d) + if (gns_data.fix2d) { gnss_pos.fixStatus = GNSS_FIX_STATUS_2D; } } - if ( (gps_data.valid & GPS_DATA_FIX3D) && (gps_data.fix3d) ) + if ( (gns_data.valid & GNS_DATA_FIX3D) && (gns_data.fix3d) ) { gnss_pos.fixStatus = GNSS_FIX_STATUS_3D; } @@ -230,36 +230,44 @@ bool extractPosition(const GPS_DATA& gps_data, uint64_t timestamp, TGNSSPosition gnss_pos.validityBits |= GNSS_POSITION_ASYS_VALID; gnss_pos.usedSystems = GNSS_SYSTEM_GPS; gnss_pos.validityBits |= GNSS_POSITION_USYS_VALID; - + //check whether GLONASS is active in addition to GPS + //TODO check explicitly for GPS to cover GLONASS only + if ( (gns_data.valid_ext & GNS_DATA_USAT_GLO) && (gns_data.usat_glo > 0) ) + { + gnss_pos.activatedSystems |= GNSS_SYSTEM_GLONASS; + gnss_pos.usedSystems |= GNSS_SYSTEM_GLONASS; + gnss_pos.fixTypeBits |= GNSS_FIX_TYPE_MULTI_CONSTELLATION; + } + return true; } /** - * Convert GPS data from NMEA parser to TGNSSTime struct - * @param gps_data [IN] GPS data decoded from NMEA parser + * Convert GNSS data from NMEA parser to TGNSSTime struct + * @param gns_data [IN] GNSS data decoded from NMEA parser * @param timestamp [IN] timestamp in milliseconds - * @param gnss_time [OUT] TGNSSTime struct which will be filled with gps_data and timestamp + * @param gnss_time [OUT] TGNSSTime struct which will be filled with gns_data and timestamp * @return conversion has been successful */ -bool extractTime(const GPS_DATA& gps_data, uint64_t timestamp, TGNSSTime& gnss_time) +bool extractTime(const GNS_DATA& gns_data, uint64_t timestamp, TGNSSTime& gnss_time) { gnss_time.validityBits = 0; gnss_time.timestamp = timestamp; - if (gps_data.valid & GPS_DATA_TIME) + if (gns_data.valid & GNS_DATA_TIME) { - gnss_time.hour = gps_data.time_hh; - gnss_time.minute = gps_data.time_mm; - gnss_time.second = gps_data.time_ss; - gnss_time.ms = gps_data.time_ms; + gnss_time.hour = gns_data.time_hh; + gnss_time.minute = gns_data.time_mm; + gnss_time.second = gns_data.time_ss; + gnss_time.ms = gns_data.time_ms; gnss_time.validityBits |= GNSS_TIME_TIME_VALID; } - if (gps_data.valid & GPS_DATA_DATE) + if (gns_data.valid & GNS_DATA_DATE) { - gnss_time.year = gps_data.date_yyyy; - gnss_time.month = gps_data.date_mm-1; - gnss_time.day = gps_data.date_dd; + gnss_time.year = gns_data.date_yyyy; + gnss_time.month = gns_data.date_mm-1; + gnss_time.day = gns_data.date_dd; gnss_time.validityBits |= GNSS_TIME_DATE_VALID; } @@ -353,6 +361,13 @@ int open_GNSS_NMEA_device(const char* gps_device, unsigned int baudrate) /* Done */ +#ifdef NMEA_PRINT_RAW + //http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_12.html#SEC237 + //http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_27.html#SEC465 + //http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_27.html#SEC468 + //printf("MAX_CANON: %d\n", fpathconf(fd, _PC_MAX_CANON)); + //printf("MAX_INPUT: %d\n", fpathconf(fd, _PC_MAX_INPUT)); +#endif //LOG_DEBUG(gContext, "OPEN successful %d\n", fd); return fd; } @@ -372,10 +387,10 @@ void* loop_GNSS_NMEA_device(void* dev) //read failure - used to trigger restart bool read_failure = false; //trigger message - NMEA_RESULT trigger = NMEA_GPRMC; - //gps data as returned by NMEA parser - GPS_DATA gps_data; - HNMEA_Init_GPS_DATA(&gps_data); + NMEA_RESULT trigger = NMEA_RMC; + //gnss data as returned by NMEA parser + GNS_DATA gns_data; + HNMEA_Init_GNS_DATA(&gns_data); /* loop until we have a terminating condition */ //LOG_DEBUG(gContext, "entering NMEA reading loop %d\n", fd); @@ -413,18 +428,18 @@ void* loop_GNSS_NMEA_device(void* dev) printf("%"PRIu64",0,%s",gnss_get_timestamp(), buf); fflush(stdout); #endif - NMEA_RESULT nmea_res = HNMEA_Parse(buf, &gps_data); + NMEA_RESULT nmea_res = HNMEA_Parse(buf, &gns_data); //most receivers sent GPRMC as last, but u-blox send as first: use other trigger //determine most suitable trigger on actually received messages #ifdef GNSS_CHIPSET_UBLOX - if (nmea_res == NMEA_GPGST) //highest precedence + if (nmea_res == NMEA_GST) //highest precedence { - trigger = NMEA_GPGST; + trigger = NMEA_GST; } - if ((nmea_res == NMEA_GPGSA) && (trigger == NMEA_GPRMC)) //GSA better than RMC + if ((nmea_res == NMEA_GSA) && (trigger == NMEA_RMC)) //GSA better than RMC { - trigger = NMEA_GPGSA; + trigger = NMEA_GSA; } #endif if (nmea_res == trigger) @@ -433,7 +448,7 @@ void* loop_GNSS_NMEA_device(void* dev) uint64_t timestamp = gnss_get_timestamp() - GNSS_DELAY; TGNSSTime gnss_time = { 0 }; TGNSSPosition gnss_pos = { 0 }; - if (extractTime(gps_data, timestamp, gnss_time)) + if (extractTime(gns_data, timestamp, gnss_time)) { updateGNSSTime(&gnss_time, 1); @@ -453,7 +468,7 @@ void* loop_GNSS_NMEA_device(void* dev) fflush(stdout); #endif } - if (extractPosition(gps_data, timestamp, gnss_pos)) + if (extractPosition(gns_data, timestamp, gnss_pos)) { updateGNSSPosition(&gnss_pos,1 ); } diff --git a/gnss-service/src/hnmea.cpp b/gnss-service/src/hnmea.cpp index d176c9e..a7ec73d 100644 --- a/gnss-service/src/hnmea.cpp +++ b/gnss-service/src/hnmea.cpp @@ -34,32 +34,35 @@ char test_gpgs3[] = "$GPGSV,3,3,12,09,08,259,29,26,65,304,45,24,02,263,,17,08,13 -void HNMEA_Init_GPS_DATA(GPS_DATA* gps_data) +void HNMEA_Init_GNS_DATA(GNS_DATA* gns_data) { - gps_data->valid = 0; - gps_data->valid_new = 0; - gps_data->lat = 999.99; - gps_data->lon = 999.99; - gps_data->alt = -1000.0; - gps_data->geoid = -1000.0; - gps_data->date_yyyy = -1; - gps_data->date_mm = -1; - gps_data->date_dd = -1; - gps_data->time_hh = -1; - gps_data->time_mm = -1; - gps_data->time_ss = -1; - gps_data->time_ms = -1; - gps_data->course = -999.99; - gps_data->speed = -999.99; - gps_data->hdop = -999.99; - gps_data->vdop = -999.99; - gps_data->pdop = -999.99; - gps_data->usat = -99; - gps_data->fix2d = -1; - gps_data->fix3d = -1; - gps_data->hacc = 999.9; - gps_data->vacc = 999.9; - + gns_data->valid = 0; + gns_data->valid_new = 0; + gns_data->valid_ext = 0; + gns_data->valid_ext_new = 0; + gns_data->lat = 999.99; + gns_data->lon = 999.99; + gns_data->alt = -1000.0; + gns_data->geoid = -1000.0; + gns_data->date_yyyy = -1; + gns_data->date_mm = -1; + gns_data->date_dd = -1; + gns_data->time_hh = -1; + gns_data->time_mm = -1; + gns_data->time_ss = -1; + gns_data->time_ms = -1; + gns_data->course = -999.99; + gns_data->speed = -999.99; + gns_data->hdop = -999.99; + gns_data->vdop = -999.99; + gns_data->pdop = -999.99; + gns_data->usat = -99; + gns_data->fix2d = -1; + gns_data->fix3d = -1; + gns_data->hacc = 999.9; + gns_data->vacc = 999.9; + gns_data->usat_gps = -99; + gns_data->usat_glo = -99; } @@ -113,7 +116,7 @@ int HNMEA_Checksum_Valid(char* line) return ret; } -void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) +void HNMEA_Parse_RMC(char* line, GNS_DATA* gns_data) { enum { MAX_FIELD_LEN = 128}; char field[MAX_FIELD_LEN]; @@ -123,7 +126,8 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) int stop = 0; // stop flag int len = strlen(line); - gps_data->valid_new = 0; + gns_data->valid_new = 0; + gns_data->valid_ext_new = 0; //outer loop - stop at line end while ( (l < len ) && (stop == 0) ) @@ -139,10 +143,10 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) switch (i) { - case 0: //$GPRMC + case 0: //$GPRMC or $GNRMC { //cross-check for sentence name - if (strncmp (field, "$GPRMC", 6) != 0) + if ((strncmp (field, "$GPRMC", 6) != 0) && (strncmp (field, "$GNRMC", 6) != 0)) { // force termination of loop stop = 1; @@ -154,13 +158,13 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) //length check if (strlen (field) >=6) { - gps_data->time_ss = atoi(field+4); - gps_data->time_ms = (atof(field+4)-gps_data->time_ss)*1000; + gns_data->time_ss = atoi(field+4); + gns_data->time_ms = (atof(field+4)-gns_data->time_ss)*1000; field[4] = '\0'; - gps_data->time_mm = atoi(field+2); + gns_data->time_mm = atoi(field+2); field[2] = '\0'; - gps_data->time_hh = atoi(field); - gps_data->valid_new |= GPS_DATA_TIME; + gns_data->time_hh = atoi(field); + gns_data->valid_new |= GNS_DATA_TIME; } break; } @@ -171,20 +175,20 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) { if (field[0] == 'A') { - gps_data->fix2d = 1; + gns_data->fix2d = 1; } else { - gps_data->fix2d = 0; + gns_data->fix2d = 0; } - gps_data->valid_new |= GPS_DATA_FIX2D; + gns_data->valid_new |= GNS_DATA_FIX2D; } break; } case 3: //latitude - absolute value { //check for minimum length + evaluate only if status ok - if ( ((gps_data->valid_new & GPS_DATA_FIX2D)!=0) && (gps_data->fix2d) && (strlen (field) >=2) ) + if ( ((gns_data->valid_new & GNS_DATA_FIX2D)!=0) && (gns_data->fix2d) && (strlen (field) >=2) ) { double fraction = 0.0; if (strlen (field) >=3) @@ -192,8 +196,8 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) fraction = atof(field+2)/60.0; } field[2]=0; - gps_data->lat = atoi(field) + fraction; - gps_data->valid_new |= GPS_DATA_LAT; + gns_data->lat = atoi(field) + fraction; + gns_data->valid_new |= GNS_DATA_LAT; } break; } @@ -204,7 +208,7 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) { if ((field[0] == 'S') || (field[0] == 's')) { - gps_data->lat = - gps_data->lat; + gns_data->lat = - gns_data->lat; } } break; @@ -212,7 +216,7 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) case 5: //longitude - absolute value { //check for minimum length + evaluate only if status ok - if ( ((gps_data->valid_new & GPS_DATA_FIX2D)!=0) && (gps_data->fix2d) && (strlen (field) >=3) ) + if ( ((gns_data->valid_new & GNS_DATA_FIX2D)!=0) && (gns_data->fix2d) && (strlen (field) >=3) ) { double fraction = 0.0; if (strlen (field) >=4) @@ -220,8 +224,8 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) fraction = atof(field+3)/60.0; } field[3]=0; - gps_data->lon = atoi(field) + fraction; - gps_data->valid_new |= GPS_DATA_LON; + gns_data->lon = atoi(field) + fraction; + gns_data->valid_new |= GNS_DATA_LON; } break; } @@ -232,7 +236,7 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) { if ((field[0] == 'W') || (field[0] == 'w')) { - gps_data->lon = - gps_data->lon; + gns_data->lon = - gns_data->lon; } } break; @@ -240,20 +244,20 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) case 7: //speed - knots { //length check + evaluate only if status ok - if (((gps_data->valid_new & GPS_DATA_FIX2D)!=0) && (gps_data->fix2d) && (strlen (field) >=1) ) + if (((gns_data->valid_new & GNS_DATA_FIX2D)!=0) && (gns_data->fix2d) && (strlen (field) >=1) ) { - gps_data->speed = atof(field)*1.852/3.6; - gps_data->valid_new |= GPS_DATA_SPEED; + gns_data->speed = atof(field)*1.852/3.6; + gns_data->valid_new |= GNS_DATA_SPEED; } break; } case 8: //course - degrees { //length check + evaluate only if status ok - if (((gps_data->valid_new & GPS_DATA_FIX2D)!=0) && (gps_data->fix2d) && (strlen (field) >=1) ) + if (((gns_data->valid_new & GNS_DATA_FIX2D)!=0) && (gns_data->fix2d) && (strlen (field) >=1) ) { - gps_data->course = atof(field); - gps_data->valid_new |= GPS_DATA_COURSE; + gns_data->course = atof(field); + gns_data->valid_new |= GNS_DATA_COURSE; } break; } @@ -262,12 +266,12 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) //length check if (strlen (field) >=6) { - gps_data->date_yyyy = 2000 + atoi(field+4); + gns_data->date_yyyy = 2000 + atoi(field+4); field[4] = '\0'; - gps_data->date_mm = atoi(field+2); + gns_data->date_mm = atoi(field+2); field[2] = '\0'; - gps_data->date_dd = atoi(field); - gps_data->valid_new |= GPS_DATA_DATE; + gns_data->date_dd = atoi(field); + gns_data->valid_new |= GNS_DATA_DATE; } stop = 1; //ignore all other fields break; @@ -297,10 +301,11 @@ void HNMEA_Parse_GPRMC(char* line, GPS_DATA* gps_data) } //update validity mask with new data - gps_data->valid |= gps_data->valid_new; + gns_data->valid |= gns_data->valid_new; + gns_data->valid_ext |= gns_data->valid_ext_new; } -void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) +void HNMEA_Parse_GGA(char* line, GNS_DATA* gns_data) { enum { MAX_FIELD_LEN = 128}; char field[MAX_FIELD_LEN]; @@ -317,7 +322,8 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) double alt = 0.0; double geoid = 0.0; - gps_data->valid_new = 0; + gns_data->valid_new = 0; + gns_data->valid_ext_new = 0; //outer loop - stop at line end while ( (l < len ) && (stop == 0) ) @@ -333,10 +339,10 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) switch (i) { - case 0: //$GPGGA + case 0: //$GPGGA or $GNGGA { //cross-check for sentence name - if (strncmp (field, "$GPGGA", 6) != 0) + if ((strncmp (field, "$GPGGA", 6) != 0) && (strncmp (field, "$GNGGA", 6) != 0)) { // force termination of loop stop = 1; @@ -348,13 +354,13 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) //length check if (strlen (field) >=6) { - gps_data->time_ss = atoi(field+4); - gps_data->time_ms = (atof(field+4)-gps_data->time_ss)*1000; + gns_data->time_ss = atoi(field+4); + gns_data->time_ms = (atof(field+4)-gns_data->time_ss)*1000; field[4] = '\0'; - gps_data->time_mm = atoi(field+2); + gns_data->time_mm = atoi(field+2); field[2] = '\0'; - gps_data->time_hh = atoi(field); - gps_data->valid_new |= GPS_DATA_TIME; + gns_data->time_hh = atoi(field); + gns_data->valid_new |= GNS_DATA_TIME; } break; } @@ -370,7 +376,7 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) } field[2]=0; lat = atoi(field) + fraction; - gps_data->valid_new |= GPS_DATA_LAT; + gns_data->valid_new |= GNS_DATA_LAT; } break; } @@ -398,7 +404,7 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) } field[3]=0; lon = atoi(field) + fraction; - gps_data->valid_new |= GPS_DATA_LON; + gns_data->valid_new |= GNS_DATA_LON; } break; } @@ -421,16 +427,16 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) { if ( (field[0] == '1') || (field[0] == '2') || (field[0] == '6') ) { - gps_data->fix2d = 1; - gps_data->lat = lat; - gps_data->lon = lon; + gns_data->fix2d = 1; + gns_data->lat = lat; + gns_data->lon = lon; } else { - gps_data->fix2d = 0; - gps_data->valid_new &= ~(GPS_DATA_LAT | GPS_DATA_LON); + gns_data->fix2d = 0; + gns_data->valid_new &= ~(GNS_DATA_LAT | GNS_DATA_LON); } - gps_data->valid_new |= GPS_DATA_FIX2D; + gns_data->valid_new |= GNS_DATA_FIX2D; } break; } @@ -439,8 +445,8 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) //length check if (strlen (field) >=1) { - gps_data->usat = atoi(field); - gps_data->valid_new |= GPS_DATA_USAT; + gns_data->usat = atoi(field); + gns_data->valid_new |= GNS_DATA_USAT; } break; } @@ -449,8 +455,8 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) //length check if (strlen (field) >=1) { - gps_data->hdop = atof(field); - gps_data->valid_new |= GPS_DATA_HDOP; + gns_data->hdop = atof(field); + gns_data->valid_new |= GNS_DATA_HDOP; } break; } @@ -460,7 +466,7 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) if (strlen (field) >=1) { alt = atof(field); - gps_data->valid_new |= GPS_DATA_ALT; + gns_data->valid_new |= GNS_DATA_ALT; } break; } @@ -469,13 +475,13 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) //length check if (strlen (field) >=1) { - if ( (field[0] == 'M') && (gps_data->fix2d) ) + if ( (field[0] == 'M') && (gns_data->fix2d) ) { - gps_data->alt = alt; + gns_data->alt = alt; } else { - gps_data->valid_new &= ~(GPS_DATA_ALT); + gns_data->valid_new &= ~(GNS_DATA_ALT); } } break; @@ -486,7 +492,7 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) if (strlen (field) >=1) { geoid = atof(field); - gps_data->valid_new |= GPS_DATA_GEOID; + gns_data->valid_new |= GNS_DATA_GEOID; } break; } @@ -497,11 +503,11 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) { if (field[0] == 'M') { - gps_data->geoid = geoid; + gns_data->geoid = geoid; } else { - gps_data->valid_new &= ~(GPS_DATA_GEOID); + gns_data->valid_new &= ~(GNS_DATA_GEOID); } } stop = 1; //ignore all other fields @@ -532,11 +538,12 @@ void HNMEA_Parse_GPGGA(char* line, GPS_DATA* gps_data) } //update validity mask with valid_new data - gps_data->valid |= gps_data->valid_new; + gns_data->valid |= gns_data->valid_new; + gns_data->valid_ext |= gns_data->valid_ext_new; } -void HNMEA_Parse_GPGSA(char* line, GPS_DATA* gps_data) +void HNMEA_Parse_GSA(char* line, GNS_DATA* gns_data) { enum { MAX_FIELD_LEN = 128}; char field[MAX_FIELD_LEN]; @@ -547,8 +554,12 @@ void HNMEA_Parse_GPGSA(char* line, GPS_DATA* gps_data) int len = strlen(line); int usat = 0; //counter for used satellites + //NMEA 4.1: GSA has additional field systemId after VDOP + //1=GPS 2=GLONASS 3=Galileo 4=BeiDou + int systemId = 0; - gps_data->valid_new = 0; + gns_data->valid_new = 0; + gns_data->valid_ext_new = 0; //outer loop - stop at line end while ( (l < len ) && (stop == 0) ) @@ -564,10 +575,10 @@ void HNMEA_Parse_GPGSA(char* line, GPS_DATA* gps_data) switch (i) { - case 0: //$GPGSA + case 0: //$GPGSA or $GNGSA { //cross-check for sentence name - if (strncmp (field, "$GPGSA", 6) != 0) + if ((strncmp (field, "$GPGSA", 6) != 0) && (strncmp (field, "$GNGSA", 6) != 0)) { // force termination of loop stop = 1; @@ -585,21 +596,21 @@ void HNMEA_Parse_GPGSA(char* line, GPS_DATA* gps_data) { if (field[0] == '2') { - gps_data->fix2d = 1; - gps_data->fix3d = 0; + gns_data->fix2d = 1; + gns_data->fix3d = 0; } else if (field[0] == '3') { - gps_data->fix2d = 1; - gps_data->fix3d = 1; + gns_data->fix2d = 1; + gns_data->fix3d = 1; } else { - gps_data->fix2d = 0; - gps_data->fix3d = 0; + gns_data->fix2d = 0; + gns_data->fix3d = 0; } - gps_data->valid_new |= GPS_DATA_FIX2D; - gps_data->valid_new |= GPS_DATA_FIX3D; + gns_data->valid_new |= GNS_DATA_FIX2D; + gns_data->valid_new |= GNS_DATA_FIX3D; } break; } @@ -627,8 +638,8 @@ void HNMEA_Parse_GPGSA(char* line, GPS_DATA* gps_data) //length check if (strlen (field) >=1) { - gps_data->pdop = atof(field); - gps_data->valid_new |= GPS_DATA_PDOP; + gns_data->pdop = atof(field); + gns_data->valid_new |= GNS_DATA_PDOP; } break; } @@ -637,8 +648,8 @@ void HNMEA_Parse_GPGSA(char* line, GPS_DATA* gps_data) //length check if (strlen (field) >=1) { - gps_data->hdop = atof(field); - gps_data->valid_new |= GPS_DATA_HDOP; + gns_data->hdop = atof(field); + gns_data->valid_new |= GNS_DATA_HDOP; } break; } @@ -647,12 +658,21 @@ void HNMEA_Parse_GPGSA(char* line, GPS_DATA* gps_data) //length check if (strlen (field) >=1) { - gps_data->vdop = atof(field); - gps_data->valid_new |= GPS_DATA_VDOP; + gns_data->vdop = atof(field); + gns_data->valid_new |= GNS_DATA_VDOP; } - stop = 1; //ignore all other fields break; } + case 18: //NMEA 4.1 systemId + { + //length check + if (strlen (field) >=1) + { + systemId = atoi(field); + } + stop = 1; //ignore all other fields + break; + } default: { stop = 1; @@ -679,15 +699,29 @@ void HNMEA_Parse_GPGSA(char* line, GPS_DATA* gps_data) if (usat > 0) { - gps_data->usat = usat; - gps_data->valid_new |= GPS_DATA_USAT; + if (systemId == 0) //unspecified + { + gns_data->usat = usat; + gns_data->valid_new |= GNS_DATA_USAT; + } + else if (systemId == 1) //GPS + { + gns_data->usat_gps = usat; + gns_data->valid_ext_new |= GNS_DATA_USAT_GPS; + } + else if (systemId == 2) //GLONASS + { + gns_data->usat_glo = usat; + gns_data->valid_ext_new |= GNS_DATA_USAT_GLO; + } } //update validity mask with new data - gps_data->valid |= gps_data->valid_new; + gns_data->valid |= gns_data->valid_new; + gns_data->valid_ext |= gns_data->valid_ext_new; } -void HNMEA_Parse_GPGST(char* line, GPS_DATA* gps_data) +void HNMEA_Parse_GST(char* line, GNS_DATA* gns_data) { enum { MAX_FIELD_LEN = 128}; char field[MAX_FIELD_LEN]; @@ -703,7 +737,8 @@ void HNMEA_Parse_GPGST(char* line, GPS_DATA* gps_data) float lon_std = 0.0; float alt_std = 0.0; - gps_data->valid_new = 0; + gns_data->valid_new = 0; + gns_data->valid_ext_new = 0; //outer loop - stop at line end while ( (l < len ) && (stop == 0) ) @@ -722,7 +757,7 @@ void HNMEA_Parse_GPGST(char* line, GPS_DATA* gps_data) case 0: //$GPGST { //cross-check for sentence name - if (strncmp (field, "$GPGST", 6) != 0) + if ((strncmp (field, "$GPGST", 6) != 0) && (strncmp (field, "$GNGST", 6) != 0)) { // force termination of loop stop = 1; @@ -734,13 +769,13 @@ void HNMEA_Parse_GPGST(char* line, GPS_DATA* gps_data) //length check if (strlen (field) >=6) { - gps_data->time_ss = atoi(field+4); - gps_data->time_ms = (atof(field+4)-gps_data->time_ss)*1000; + gns_data->time_ss = atoi(field+4); + gns_data->time_ms = (atof(field+4)-gns_data->time_ss)*1000; field[4] = '\0'; - gps_data->time_mm = atoi(field+2); + gns_data->time_mm = atoi(field+2); field[2] = '\0'; - gps_data->time_hh = atoi(field); - gps_data->valid_new |= GPS_DATA_TIME; + gns_data->time_hh = atoi(field); + gns_data->valid_new |= GNS_DATA_TIME; } break; } @@ -780,8 +815,8 @@ void HNMEA_Parse_GPGST(char* line, GPS_DATA* gps_data) if ((strlen (field) >=1) && (lat_std_valid)) { lon_std = atof(field); - gps_data->hacc = sqrt(lat_std*lat_std + lon_std*lon_std); - gps_data->valid_new |= GPS_DATA_HACC; + gns_data->hacc = sqrt(lat_std*lat_std + lon_std*lon_std); + gns_data->valid_new |= GNS_DATA_HACC; } break; } @@ -791,8 +826,8 @@ void HNMEA_Parse_GPGST(char* line, GPS_DATA* gps_data) if (strlen (field) >=1) { alt_std = atof(field); - gps_data->vacc = alt_std; - gps_data->valid_new |= GPS_DATA_VACC; + gns_data->vacc = alt_std; + gns_data->valid_new |= GNS_DATA_VACC; } break; } @@ -821,56 +856,57 @@ void HNMEA_Parse_GPGST(char* line, GPS_DATA* gps_data) } //update validity mask with new data - gps_data->valid |= gps_data->valid_new; + gns_data->valid |= gns_data->valid_new; + gns_data->valid_ext |= gns_data->valid_ext_new; } -NMEA_RESULT HNMEA_Parse(char* line, GPS_DATA* gps_data) +NMEA_RESULT HNMEA_Parse(char* line, GNS_DATA* gns_data) { NMEA_RESULT ret = NMEA_UKNOWN; - if (strncmp (line, "$GPRMC", 6) == 0) + if ((strncmp (line, "$GPRMC", 6) == 0) || (strncmp (line, "$GNRMC", 6) == 0)) { if (HNMEA_Checksum_Valid(line)) { - HNMEA_Parse_GPRMC(line, gps_data); - ret = NMEA_GPRMC; + HNMEA_Parse_RMC(line, gns_data); + ret = NMEA_RMC; } else { ret = NMEA_BAD_CHKSUM; } } - if (strncmp (line, "$GPGGA", 6) == 0) + else if ((strncmp (line, "$GPGGA", 6) == 0) || (strncmp (line, "$GNGGA", 6) == 0)) { if (HNMEA_Checksum_Valid(line)) { - HNMEA_Parse_GPGGA(line, gps_data); - ret = NMEA_GPGGA; + HNMEA_Parse_GGA(line, gns_data); + ret = NMEA_GGA; } else { ret = NMEA_BAD_CHKSUM; } } - if (strncmp (line, "$GPGSA", 6) == 0) + else if ((strncmp (line, "$GPGSA", 6) == 0) || (strncmp (line, "$GNGSA", 6) == 0)) { if (HNMEA_Checksum_Valid(line)) { - HNMEA_Parse_GPGSA(line, gps_data); - ret = NMEA_GPGSA; + HNMEA_Parse_GSA(line, gns_data); + ret = NMEA_GSA; } else { ret = NMEA_BAD_CHKSUM; } } - if (strncmp (line, "$GPGST", 6) == 0) + else if ((strncmp (line, "$GPGST", 6) == 0) || (strncmp (line, "$GNGST", 6) == 0)) { if (HNMEA_Checksum_Valid(line)) { - HNMEA_Parse_GPGST(line, gps_data); - ret = NMEA_GPGST; + HNMEA_Parse_GST(line, gns_data); + ret = NMEA_GST; } else { diff --git a/gnss-service/src/hnmea.h b/gnss-service/src/hnmea.h index 2e9a489..a73aefd 100644 --- a/gnss-service/src/hnmea.h +++ b/gnss-service/src/hnmea.h @@ -29,36 +29,43 @@ typedef enum { NMEA_INIT, //initial value - will never be returned by the parser NMEA_UKNOWN, //unknown content NMEA_BAD_CHKSUM, //BAD NMEA Checksum - NMEA_GPRMC, //GPRMC Sentence - NMEA_GPGGA, //GPGGA Sentence - NMEA_GPGSA, //GPGSA Sentence - NMEA_GPGSV, //GPGSV Sentence - NMEA_GPGST //GPGST Sentence + NMEA_RMC, //GxRMC Sentence + NMEA_GGA, //GxGGA Sentence + NMEA_GSA, //GxGSA Sentence + NMEA_GSV, //GxGSV Sentence + NMEA_GST //GxGST Sentence } NMEA_RESULT; -//bitmap for GPS data +//bitmaps for GNSS data typedef enum { - GPS_DATA_LAT = 0x0001, //latitude - GPS_DATA_LON = 0x0002, //longitude - GPS_DATA_ALT = 0x0004, //altitude - GPS_DATA_GEOID = 0x0008, //geoid separation - GPS_DATA_DATE = 0x0010, //date - GPS_DATA_TIME = 0x0020, //time - GPS_DATA_COURSE = 0x0040, //course (heading) - GPS_DATA_SPEED = 0x0080, //speed - GPS_DATA_HDOP = 0x0100, //HDOP - GPS_DATA_VDOP = 0x0200, //VDOP - GPS_DATA_PDOP = 0x0400, //PDOP - GPS_DATA_USAT = 0x0800, //number of used satellites - GPS_DATA_FIX2D = 0x1000, //at least 2D Fix - GPS_DATA_FIX3D = 0x2000, //3D Fix (GPS_DATA_FIX2D will be set also) - GPS_DATA_HACC = 0x4000, //horizontal accuracy - GPS_DATA_VACC = 0x8000 //vertical accuracy -} GPS_DATA_TYPE; + GNS_DATA_LAT = 0x0001, //latitude + GNS_DATA_LON = 0x0002, //longitude + GNS_DATA_ALT = 0x0004, //altitude + GNS_DATA_GEOID = 0x0008, //geoid separation + GNS_DATA_DATE = 0x0010, //date + GNS_DATA_TIME = 0x0020, //time + GNS_DATA_COURSE = 0x0040, //course (heading) + GNS_DATA_SPEED = 0x0080, //speed + GNS_DATA_HDOP = 0x0100, //HDOP + GNS_DATA_VDOP = 0x0200, //VDOP + GNS_DATA_PDOP = 0x0400, //PDOP + GNS_DATA_USAT = 0x0800, //number of used satellites + GNS_DATA_FIX2D = 0x1000, //at least 2D Fix + GNS_DATA_FIX3D = 0x2000, //3D Fix (GPS_DATA_FIX2D will be set also) + GNS_DATA_HACC = 0x4000, //horizontal accuracy + GNS_DATA_VACC = 0x8000 //vertical accuracy +} GNS_DATA_TYPE; + +typedef enum { + GNS_DATA_USAT_GPS = 0x0001, //number of used GPS satellites + GNS_DATA_USAT_GLO = 0x0002 //number of used GLONASS satellites +} GNS_DATA_EXT_TYPE; typedef struct { - int valid; //bitmask of GPS_DATA_TYPE for cumulative valid fields - int valid_new; //bitmask of GPS_DATA_TYPE for new valid fields + int valid; //bitmask of GNS_DATA_TYPE for cumulative valid fields + int valid_new; //bitmask of GNS_DATA_TYPE for new valid fields + int valid_ext; //bitmask of GNS_DATA_EXT_TYPE for cumulative valid fields + int valid_ext_new; //bitmask of GNS_DATA_EXT_TYPE for new valid fields double lat; //latitude in degrees - negative values are south of equator double lon; //longitude in degrees - negative values are west of Greenwich double alt; //altitude in meter above sea level @@ -80,11 +87,13 @@ typedef struct { int fix3d; //GPS status: 3D Fix - fix2d will be set also float hacc; //horizontal accuracy in m float vacc; //vertical accuracy in m -} GPS_DATA; + int usat_gps; //number of GPS satellites + int usat_glo; //number of GLONASS satellites +} GNS_DATA; -void HNMEA_Init_GPS_DATA(GPS_DATA* gps_data); +void HNMEA_Init_GNS_DATA(GNS_DATA* gns_data); -NMEA_RESULT HNMEA_Parse(char* line, GPS_DATA* gps_data); +NMEA_RESULT HNMEA_Parse(char* line, GNS_DATA* gns_data); #endif //_HNMEA_H |