mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-17 02:52:12 +01:00
Better separation between UBX and NMEA parser
Make GPS protocol a user selectable option Support for UBX protocol on CopterControl
This commit is contained in:
parent
29fd85f0e2
commit
0424172398
@ -199,6 +199,8 @@ SRC += $(OPUAVSYNTHDIR)/attitudesettings.c
|
||||
SRC += $(OPUAVSYNTHDIR)/camerastabsettings.c
|
||||
SRC += $(OPUAVSYNTHDIR)/cameradesired.c
|
||||
SRC += $(OPUAVSYNTHDIR)/gpsposition.c
|
||||
SRC += $(OPUAVSYNTHDIR)/gpsvelocity.c
|
||||
SRC += $(OPUAVSYNTHDIR)/gpssettings.c
|
||||
SRC += $(OPUAVSYNTHDIR)/hwsettings.c
|
||||
SRC += $(OPUAVSYNTHDIR)/gcsreceiver.c
|
||||
SRC += $(OPUAVSYNTHDIR)/receiveractivity.c
|
||||
|
@ -58,7 +58,8 @@
|
||||
#define PIOS_INCLUDE_TELEMETRY_RF
|
||||
#define PIOS_INCLUDE_GPS
|
||||
#define PIOS_GPS_MINIMAL
|
||||
|
||||
#define PIOS_INCLUDE_GPS_NMEA_PARSER /* Include the NMEA protocol parser */
|
||||
#define PIOS_INCLUDE_GPS_UBX_PARSER /* Include the UBX protocol parser */
|
||||
#define PIOS_INCLUDE_SERVO
|
||||
#define PIOS_INCLUDE_SPI
|
||||
#define PIOS_INCLUDE_SYS
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "openpilot.h"
|
||||
#include "GPS.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
//#include <stdbool.h>
|
||||
|
||||
#include "NMEA.h"
|
||||
|
||||
@ -41,6 +41,8 @@
|
||||
#include "homelocation.h"
|
||||
#include "gpstime.h"
|
||||
#include "gpssatellites.h"
|
||||
#include "gpsvelocity.h"
|
||||
#include "gpssettings.h"
|
||||
#include "WorldMagModel.h"
|
||||
#include "CoordinateConversions.h"
|
||||
#include "hwsettings.h"
|
||||
@ -62,19 +64,17 @@ static float GravityAccel(float latitude, float longitude, float altitude);
|
||||
|
||||
#define GPS_TIMEOUT_MS 500
|
||||
|
||||
#if defined(REVOLUTION)
|
||||
#define NMEA_MAX_PACKET_LENGTH MAX_SVINFO_MSG_SIZE
|
||||
#else
|
||||
#define NMEA_MAX_PACKET_LENGTH 96 // 82 max NMEA msg size plus 12 margin (because some vendors add custom crap) plus CR plus Linefeed
|
||||
// same as in COM buffer
|
||||
#endif
|
||||
|
||||
#ifdef PIOS_GPS_SETS_HOMELOCATION
|
||||
// Unfortunately need a good size stack for the WMM calculation
|
||||
#define STACK_SIZE_BYTES 950
|
||||
#define STACK_SIZE_BYTES 750
|
||||
#else
|
||||
#if defined(PIOS_GPS_MINIMAL)
|
||||
#define STACK_SIZE_BYTES 500
|
||||
#else
|
||||
#define STACK_SIZE_BYTES 650
|
||||
#endif
|
||||
#endif // PIOS_GPS_MINIMAL
|
||||
#endif // PIOS_GPS_SETS_HOMELOCATION
|
||||
|
||||
#define TASK_PRIORITY (tskIDLE_PRIORITY + 1)
|
||||
|
||||
@ -124,6 +124,7 @@ int32_t GPSStart(void)
|
||||
int32_t GPSInitialize(void)
|
||||
{
|
||||
gpsPort = PIOS_COM_GPS;
|
||||
uint8_t gpsProtocol;
|
||||
|
||||
#ifdef MODULE_GPS_BUILTIN
|
||||
gpsEnabled = true;
|
||||
@ -141,6 +142,7 @@ int32_t GPSInitialize(void)
|
||||
|
||||
if (gpsPort && gpsEnabled) {
|
||||
GPSPositionInitialize();
|
||||
GPSVelocityInitialize();
|
||||
#if !defined(PIOS_GPS_MINIMAL)
|
||||
GPSTimeInitialize();
|
||||
GPSSatellitesInitialize();
|
||||
@ -150,7 +152,19 @@ int32_t GPSInitialize(void)
|
||||
#endif
|
||||
updateSettings();
|
||||
|
||||
gps_rx_buffer = pvPortMalloc(NMEA_MAX_PACKET_LENGTH);
|
||||
if (gpsPort && gpsEnabled) {
|
||||
GPSSettingsInitialize();
|
||||
GPSSettingsDataProtocolGet(&gpsProtocol);
|
||||
switch (gpsProtocol) {
|
||||
case GPSSETTINGS_DATAPROTOCOL_NMEA:
|
||||
gps_rx_buffer = pvPortMalloc(NMEA_MAX_PACKET_LENGTH);
|
||||
break;
|
||||
case GPSSETTINGS_DATAPROTOCOL_UBX:
|
||||
gps_rx_buffer = pvPortMalloc(sizeof(UBXPacket));
|
||||
break;
|
||||
default:
|
||||
gps_rx_buffer = NULL;
|
||||
}
|
||||
PIOS_Assert(gps_rx_buffer);
|
||||
|
||||
return 0;
|
||||
@ -169,14 +183,13 @@ MODULE_INITCALL(GPSInitialize, GPSStart)
|
||||
static void gpsTask(void *parameters)
|
||||
{
|
||||
portTickType xDelay = 100 / portTICK_RATE_MS;
|
||||
uint32_t timeNowMs = xTaskGetTickCount() * portTICK_RATE_MS;;
|
||||
GPSPositionData GpsData;
|
||||
|
||||
uint8_t rx_count = 0;
|
||||
bool start_flag = false;
|
||||
bool found_cr = false;
|
||||
int32_t gpsRxOverflow = 0;
|
||||
|
||||
uint32_t timeNowMs = xTaskGetTickCount() * portTICK_RATE_MS;
|
||||
|
||||
GPSPositionData gpsposition;
|
||||
uint8_t gpsProtocol;
|
||||
|
||||
GPSSettingsDataProtocolGet(&gpsProtocol);
|
||||
|
||||
numUpdates = 0;
|
||||
numChecksumErrors = 0;
|
||||
numParsingErrors = 0;
|
||||
@ -184,202 +197,65 @@ static void gpsTask(void *parameters)
|
||||
timeOfLastUpdateMs = timeNowMs;
|
||||
timeOfLastCommandMs = timeNowMs;
|
||||
|
||||
GPSPositionGet(&gpsposition);
|
||||
// Loop forever
|
||||
while (1)
|
||||
{
|
||||
uint8_t c;
|
||||
// NMEA or SINGLE-SENTENCE GPS mode
|
||||
|
||||
// This blocks the task until there is something on the buffer
|
||||
while (PIOS_COM_ReceiveBuffer(gpsPort, &c, 1, xDelay) > 0)
|
||||
{
|
||||
|
||||
// detect start while acquiring stream
|
||||
if (!start_flag && (c == '$'))
|
||||
{
|
||||
case START: // detect protocol
|
||||
switch (c)
|
||||
{
|
||||
case UBX_SYNC1: // first UBX sync char found
|
||||
proto_state = UBX_SY2;
|
||||
continue;
|
||||
case '$': // NMEA identifier found
|
||||
proto_state = NMEA;
|
||||
found_cr = false;
|
||||
rx_count = 0;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
int res;
|
||||
switch (gpsProtocol) {
|
||||
#if defined(PIOS_INCLUDE_GPS_NMEA_PARSER)
|
||||
case GPSSETTINGS_DATAPROTOCOL_NMEA:
|
||||
res = parse_nmea_stream (c,gps_rx_buffer, &gpsposition);
|
||||
break;
|
||||
case UBX_SY2:
|
||||
if (c == UBX_SYNC2) // second UBX sync char found
|
||||
{
|
||||
proto_state = UBX_CLASS;
|
||||
found_cr = false;
|
||||
rx_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
proto_state = START; // reset state
|
||||
}
|
||||
continue;
|
||||
case UBX_CLASS:
|
||||
ubx->header.class = c;
|
||||
proto_state = UBX_ID;
|
||||
continue;
|
||||
case UBX_ID:
|
||||
ubx->header.id = c;
|
||||
proto_state = UBX_LEN1;
|
||||
continue;
|
||||
case UBX_LEN1:
|
||||
ubx->header.len = c;
|
||||
proto_state = UBX_LEN2;
|
||||
continue;
|
||||
case UBX_LEN2:
|
||||
ubx->header.len += (c << 8);
|
||||
if ((sizeof (UBXHeader)) + ubx->header.len > NMEA_MAX_PACKET_LENGTH)
|
||||
{
|
||||
gpsRxOverflow++;
|
||||
proto_state = START;
|
||||
found_cr = false;
|
||||
rx_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
proto_state = UBX_PAYLOAD;
|
||||
}
|
||||
continue;
|
||||
case UBX_PAYLOAD:
|
||||
if (rx_count < ubx->header.len)
|
||||
{
|
||||
ubx->payload.payload[rx_count] = c;
|
||||
if (++rx_count == ubx->header.len)
|
||||
proto_state = UBX_CHK1;
|
||||
}
|
||||
else
|
||||
proto_state = START;
|
||||
continue;
|
||||
case UBX_CHK1:
|
||||
ubx->header.ck_a = c;
|
||||
proto_state = UBX_CHK2;
|
||||
continue;
|
||||
case UBX_CHK2:
|
||||
ubx->header.ck_b = c;
|
||||
if (checksum_ubx_message(ubx)) // message complete and valid
|
||||
{
|
||||
parse_ubx_message(ubx, &GpsData);
|
||||
timeNowMs = xTaskGetTickCount() * portTICK_RATE_MS;
|
||||
timeOfLastUpdateMs = timeNowMs;
|
||||
timeOfLastCommandMs = timeNowMs;
|
||||
}
|
||||
proto_state = START;
|
||||
continue;
|
||||
case NMEA:
|
||||
#endif
|
||||
#if defined(PIOS_INCLUDE_GPS_UBX_PARSER)
|
||||
case GPSSETTINGS_DATAPROTOCOL_UBX:
|
||||
res = parse_ubx_stream (c,gps_rx_buffer, &gpsposition);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
res = NO_PARSER; // this should not happen
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (!start_flag)
|
||||
continue;
|
||||
|
||||
if (rx_count >= NMEA_MAX_PACKET_LENGTH)
|
||||
{
|
||||
// The buffer is already full and we haven't found a valid NMEA sentence.
|
||||
// Flush the buffer and note the overflow event.
|
||||
gpsRxOverflow++;
|
||||
start_flag = false;
|
||||
found_cr = false;
|
||||
rx_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
gps_rx_buffer[rx_count] = c;
|
||||
rx_count++;
|
||||
}
|
||||
|
||||
// look for ending '\r\n' sequence
|
||||
if (!found_cr && (c == '\r') )
|
||||
found_cr = true;
|
||||
else
|
||||
if (found_cr && (c != '\n') )
|
||||
found_cr = false; // false end flag
|
||||
else
|
||||
if (found_cr && (c == '\n') )
|
||||
{
|
||||
// The NMEA functions require a zero-terminated string
|
||||
// As we detected \r\n, the string as for sure 2 bytes long, we will also strip the \r\n
|
||||
gps_rx_buffer[rx_count-2] = 0;
|
||||
|
||||
// prepare to parse next sentence
|
||||
start_flag = false;
|
||||
found_cr = false;
|
||||
rx_count = 0;
|
||||
// Our rxBuffer must look like this now:
|
||||
// [0] = '$'
|
||||
// ... = zero or more bytes of sentence payload
|
||||
// [end_pos - 1] = '\r'
|
||||
// [end_pos] = '\n'
|
||||
//
|
||||
// Prepare to consume the sentence from the buffer
|
||||
|
||||
// Validate the checksum over the sentence
|
||||
if (!NMEA_checksum(&gps_rx_buffer[1]))
|
||||
{ // Invalid checksum. May indicate dropped characters on Rx.
|
||||
//PIOS_DEBUG_PinHigh(2);
|
||||
++numChecksumErrors;
|
||||
//PIOS_DEBUG_PinLow(2);
|
||||
}
|
||||
else
|
||||
{ // Valid checksum, use this packet to update the GPS position
|
||||
if (!NMEA_update_position(&gps_rx_buffer[1])) {
|
||||
//PIOS_DEBUG_PinHigh(2);
|
||||
++numParsingErrors;
|
||||
//PIOS_DEBUG_PinLow(2);
|
||||
}
|
||||
else
|
||||
++numUpdates;
|
||||
|
||||
timeNowMs = xTaskGetTickCount() * portTICK_RATE_MS;
|
||||
timeOfLastUpdateMs = timeNowMs;
|
||||
timeOfLastCommandMs = timeNowMs;
|
||||
}
|
||||
if (res == PARSER_COMPLETE) {
|
||||
timeNowMs = xTaskGetTickCount() * portTICK_RATE_MS;
|
||||
timeOfLastUpdateMs = timeNowMs;
|
||||
timeOfLastCommandMs = timeNowMs;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for GPS timeout
|
||||
timeNowMs = xTaskGetTickCount() * portTICK_RATE_MS;
|
||||
if ((timeNowMs - timeOfLastUpdateMs) >= GPS_TIMEOUT_MS)
|
||||
{ // we have not received any valid GPS sentences for a while.
|
||||
if ((timeNowMs - timeOfLastUpdateMs) >= GPS_TIMEOUT_MS) {
|
||||
// we have not received any valid GPS sentences for a while.
|
||||
// either the GPS is not plugged in or a hardware problem or the GPS has locked up.
|
||||
|
||||
GPSPositionGet(&GpsData);
|
||||
GpsData.Status = GPSPOSITION_STATUS_NOGPS;
|
||||
GPSPositionSet(&GpsData);
|
||||
uint8_t status = GPSPOSITION_STATUS_NOGPS;
|
||||
GPSPositionStatusSet(&status);
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_GPS, SYSTEMALARMS_ALARM_ERROR);
|
||||
|
||||
}
|
||||
else
|
||||
{ // we appear to be receiving GPS sentences OK, we've had an update
|
||||
|
||||
GPSPositionGet(&GpsData);
|
||||
|
||||
#ifdef PIOS_GPS_SETS_HOMELOCATION
|
||||
HomeLocationData home;
|
||||
HomeLocationGet(&home);
|
||||
|
||||
if ((GpsData.Status == GPSPOSITION_STATUS_FIX3D) && (home.Set == HOMELOCATION_SET_FALSE))
|
||||
setHomeLocation(&GpsData);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
// we appear to be receiving GPS sentences OK, we've had an update
|
||||
//criteria for GPS-OK taken from this post...
|
||||
//http://forums.openpilot.org/topic/1523-professors-insgps-in-svn/page__view__findpost__p__5220
|
||||
if ((GpsData.PDOP < 3.5) && (GpsData.Satellites >= 7))
|
||||
if ((gpsposition.PDOP < 3.5) && (gpsposition.Satellites >= 7) &&
|
||||
(gpsposition.Status == GPSPOSITION_STATUS_FIX3D)) {
|
||||
AlarmsClear(SYSTEMALARMS_ALARM_GPS);
|
||||
else
|
||||
if (GpsData.Status == GPSPOSITION_STATUS_FIX3D)
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_GPS, SYSTEMALARMS_ALARM_WARNING);
|
||||
else
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_GPS, SYSTEMALARMS_ALARM_CRITICAL);
|
||||
#ifdef PIOS_GPS_SETS_HOMELOCATION
|
||||
HomeLocationData home;
|
||||
HomeLocationGet(&home);
|
||||
|
||||
if (home.Set == HOMELOCATION_SET_FALSE)
|
||||
setHomeLocation(&gpsposition);
|
||||
#endif
|
||||
} else if (gpsposition.Status == GPSPOSITION_STATUS_FIX3D)
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_GPS, SYSTEMALARMS_ALARM_WARNING);
|
||||
else
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_GPS, SYSTEMALARMS_ALARM_CRITICAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,10 +30,15 @@
|
||||
|
||||
#include "openpilot.h"
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_GPS_NMEA_PARSER)
|
||||
|
||||
#include "gpsposition.h"
|
||||
#include "NMEA.h"
|
||||
#include "gpsposition.h"
|
||||
#include "gpstime.h"
|
||||
#include "gpssatellites.h"
|
||||
#include "GPS.h"
|
||||
|
||||
//#define ENABLE_DEBUG_MSG ///< define to enable debug-messages
|
||||
#define DEBUG_PORT PIOS_COM_TELEM_RF ///< defines which serial port is ued for debug-messages
|
||||
@ -75,6 +80,9 @@ static bool nmeaProcessGPGSA(GPSPositionData * GpsData, bool* gpsDataUpdated, ch
|
||||
static bool nmeaProcessGPGSV(GPSPositionData * GpsData, bool* gpsDataUpdated, char* param[], uint8_t nbParam);
|
||||
#endif //PIOS_GPS_MINIMAL
|
||||
|
||||
static uint32_t numUpdates;
|
||||
static uint32_t numChecksumErrors;
|
||||
static uint32_t numParsingErrors;
|
||||
|
||||
static struct nmea_parser nmea_parsers[] = {
|
||||
{
|
||||
@ -111,6 +119,88 @@ static struct nmea_parser nmea_parsers[] = {
|
||||
#endif //PIOS_GPS_MINIMAL
|
||||
};
|
||||
|
||||
int parse_nmea_stream (uint8_t c, char *gps_rx_buffer, GPSPositionData *GpsData)
|
||||
{
|
||||
static uint8_t rx_count = 0;
|
||||
static bool start_flag = false;
|
||||
static bool found_cr = false;
|
||||
|
||||
// detect start while acquiring stream
|
||||
if (!start_flag && (c == '$')) // NMEA identifier found
|
||||
{
|
||||
start_flag = true;
|
||||
found_cr = false;
|
||||
rx_count = 0;
|
||||
}
|
||||
else
|
||||
if (!start_flag)
|
||||
return PARSER_ERROR;
|
||||
|
||||
if (rx_count >= NMEA_MAX_PACKET_LENGTH)
|
||||
{
|
||||
// The buffer is already full and we haven't found a valid NMEA sentence.
|
||||
// Flush the buffer and note the overflow event.
|
||||
// gpsRxOverflow++;
|
||||
start_flag = false;
|
||||
found_cr = false;
|
||||
rx_count = 0;
|
||||
return PARSER_OVERRUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
gps_rx_buffer[rx_count] = c;
|
||||
rx_count++;
|
||||
}
|
||||
|
||||
// look for ending '\r\n' sequence
|
||||
if (!found_cr && (c == '\r') )
|
||||
found_cr = true;
|
||||
else
|
||||
if (found_cr && (c != '\n') )
|
||||
found_cr = false; // false end flag
|
||||
else
|
||||
if (found_cr && (c == '\n') )
|
||||
{
|
||||
// The NMEA functions require a zero-terminated string
|
||||
// As we detected \r\n, the string as for sure 2 bytes long, we will also strip the \r\n
|
||||
gps_rx_buffer[rx_count-2] = 0;
|
||||
|
||||
// prepare to parse next sentence
|
||||
start_flag = false;
|
||||
found_cr = false;
|
||||
rx_count = 0;
|
||||
// Our rxBuffer must look like this now:
|
||||
// [0] = '$'
|
||||
// ... = zero or more bytes of sentence payload
|
||||
// [end_pos - 1] = '\r'
|
||||
// [end_pos] = '\n'
|
||||
//
|
||||
// Prepare to consume the sentence from the buffer
|
||||
|
||||
// Validate the checksum over the sentence
|
||||
if (!NMEA_checksum(&gps_rx_buffer[1]))
|
||||
{ // Invalid checksum. May indicate dropped characters on Rx.
|
||||
//PIOS_DEBUG_PinHigh(2);
|
||||
++numChecksumErrors;
|
||||
//PIOS_DEBUG_PinLow(2);
|
||||
return PARSER_ERROR;
|
||||
}
|
||||
else
|
||||
{ // Valid checksum, use this packet to update the GPS position
|
||||
if (!NMEA_update_position(&gps_rx_buffer[1], GpsData)) {
|
||||
//PIOS_DEBUG_PinHigh(2);
|
||||
++numParsingErrors;
|
||||
//PIOS_DEBUG_PinLow(2);
|
||||
}
|
||||
else
|
||||
++numUpdates;
|
||||
|
||||
return PARSER_COMPLETE;
|
||||
}
|
||||
}
|
||||
return PARSER_INCOMPLETE;
|
||||
}
|
||||
|
||||
static struct nmea_parser *NMEA_find_parser_by_prefix(const char *prefix)
|
||||
{
|
||||
if (!prefix) {
|
||||
@ -352,7 +442,7 @@ bool NMEA_update_position(char *nmea_sentence)
|
||||
|
||||
|
||||
// All is fine :) Update object if data has changed
|
||||
if (gpsDataUpdated) {
|
||||
if (gpsDataUpdated || (GpsData->Status == GPSPOSITION_STATUS_NOFIX)) {
|
||||
#ifdef DEBUG_MGSID_IN
|
||||
DEBUG_MSG("U");
|
||||
#endif
|
||||
@ -400,6 +490,12 @@ static bool nmeaProcessGPGGA(GPSPositionData * GpsData, bool* gpsDataUpdated, ch
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// check for invalid GPS fix
|
||||
if (param[6][0] == '0') {
|
||||
// return false;
|
||||
GpsData->Status = GPSPOSITION_STATUS_NOFIX; // treat invalid fix as NOFIX
|
||||
}
|
||||
// get number of satellites used in GPS solution
|
||||
GpsData->Satellites = atoi(param[7]);
|
||||
|
||||
@ -669,3 +765,4 @@ static bool nmeaProcessGPGSA(GPSPositionData * GpsData, bool* gpsDataUpdated, ch
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // PIOS_INCLUDE_GPS_NMEA_PARSER
|
||||
|
@ -30,11 +30,96 @@
|
||||
|
||||
#include "openpilot.h"
|
||||
#include "pios.h"
|
||||
#include "gpsvelocity.h"
|
||||
#include "gpssatellites.h"
|
||||
#include "gpsposition.h"
|
||||
#include "gpstime.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_GPS_UBX_PARSER)
|
||||
|
||||
#include "UBX.h"
|
||||
#include "gps.h"
|
||||
|
||||
static uint32_t gpsRxReceived = 0;
|
||||
static uint32_t gpsRxChkSumError = 0;
|
||||
static uint32_t gpsRxOverflow = 0;
|
||||
|
||||
// parse incoming character stream for messages in UBX binary format
|
||||
|
||||
int parse_ubx_stream (uint8_t c, char *gps_rx_buffer, GPSPositionData *GpsData)
|
||||
{
|
||||
enum proto_states {START,UBX_SY2,UBX_CLASS,UBX_ID,UBX_LEN1,
|
||||
UBX_LEN2,UBX_PAYLOAD,UBX_CHK1,UBX_CHK2,FINISHED};
|
||||
static enum proto_states proto_state = START;
|
||||
static uint8_t rx_count = 0;
|
||||
UBXPacket *ubx = (UBXPacket *)gps_rx_buffer;
|
||||
|
||||
switch (proto_state) {
|
||||
case START: // detect protocol
|
||||
if (c == UBX_SYNC1) // first UBX sync char found
|
||||
proto_state = UBX_SY2;
|
||||
break;
|
||||
case UBX_SY2:
|
||||
if (c == UBX_SYNC2) // second UBX sync char found
|
||||
proto_state = UBX_CLASS;
|
||||
else
|
||||
proto_state = START; // reset state
|
||||
break;
|
||||
case UBX_CLASS:
|
||||
ubx->header.class = c;
|
||||
proto_state = UBX_ID;
|
||||
break;
|
||||
case UBX_ID:
|
||||
ubx->header.id = c;
|
||||
proto_state = UBX_LEN1;
|
||||
break;
|
||||
case UBX_LEN1:
|
||||
ubx->header.len = c;
|
||||
proto_state = UBX_LEN2;
|
||||
break;
|
||||
case UBX_LEN2:
|
||||
ubx->header.len += (c << 8);
|
||||
if (ubx->header.len > sizeof(UBXPayload)) {
|
||||
gpsRxOverflow++;
|
||||
proto_state = START;
|
||||
} else {
|
||||
rx_count = 0;
|
||||
proto_state = UBX_PAYLOAD;
|
||||
}
|
||||
break;
|
||||
case UBX_PAYLOAD:
|
||||
if (rx_count < ubx->header.len) {
|
||||
ubx->payload.payload[rx_count] = c;
|
||||
if (++rx_count == ubx->header.len)
|
||||
proto_state = UBX_CHK1;
|
||||
} else {
|
||||
gpsRxOverflow++;
|
||||
proto_state = START;
|
||||
}
|
||||
break;
|
||||
case UBX_CHK1:
|
||||
ubx->header.ck_a = c;
|
||||
proto_state = UBX_CHK2;
|
||||
break;
|
||||
case UBX_CHK2:
|
||||
ubx->header.ck_b = c;
|
||||
if (checksum_ubx_message(ubx)) { // message complete and valid
|
||||
parse_ubx_message(ubx, GpsData);
|
||||
proto_state = FINISHED;
|
||||
} else {
|
||||
gpsRxChkSumError++;
|
||||
proto_state = START;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (proto_state == START)
|
||||
return PARSER_ERROR; // parser couldn't use this byte
|
||||
else if (proto_state == FINISHED) {
|
||||
gpsRxReceived++;
|
||||
proto_state = START;
|
||||
return PARSER_COMPLETE; // message complete & processed
|
||||
}
|
||||
|
||||
return PARSER_INCOMPLETE; // message not (yet) complete
|
||||
}
|
||||
|
||||
|
||||
// Keep track of various GPS messages needed to make up a single UAVO update
|
||||
@ -50,25 +135,21 @@
|
||||
|
||||
static struct msgtracker{
|
||||
uint32_t currentTOW; // TOW of the message set currently in progress
|
||||
uint8_t msg_received; // Flag received messages
|
||||
uint8_t msg_received; // keep track of received message types
|
||||
} msgtracker;
|
||||
|
||||
// Check if a message belongs to the current data set and register it as 'received'
|
||||
bool check_msgtracker (uint32_t tow, uint8_t msg_flag)
|
||||
{
|
||||
if ((tow > msgtracker.currentTOW) || // start of a new message set
|
||||
(tow < 60000 && msgtracker.currentTOW > (7*24-1)*3600*1000)) // TOW wrap around
|
||||
{
|
||||
|
||||
if (tow > msgtracker.currentTOW ? true // start of a new message set
|
||||
: (msgtracker.currentTOW - tow > 6*24*3600*1000)) { // 6 days, TOW wrap around occured
|
||||
msgtracker.currentTOW = tow;
|
||||
msgtracker.msg_received = NONE_RECEIVED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tow < msgtracker.currentTOW) // message outdated (don't process)
|
||||
} else if (tow < msgtracker.currentTOW) // message outdated (don't process)
|
||||
return false;
|
||||
}
|
||||
|
||||
msgtracker.msg_received |= msg_flag;
|
||||
msgtracker.msg_received |= msg_flag; // register reception of this msg type
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -89,137 +170,133 @@ bool checksum_ubx_message (UBXPacket *ubx)
|
||||
ck_a += ubx->header.len >> 8;
|
||||
ck_b += ck_a;
|
||||
|
||||
|
||||
|
||||
for (i = 0; i < ubx->header.len; i++)
|
||||
{
|
||||
for (i = 0; i < ubx->header.len; i++) {
|
||||
ck_a += ubx->payload.payload[i];
|
||||
ck_b += ck_a;
|
||||
}
|
||||
|
||||
if (ubx->header.ck_a == ck_a &&
|
||||
ubx->header.ck_b == ck_b)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void parse_ubx_nav_posllh (UBXPayload payload, GPSPositionData *gpsposition)
|
||||
void parse_ubx_nav_posllh (UBX_NAV_POSLLH *posllh, GPSPositionData *GpsPosition)
|
||||
{
|
||||
if (check_msgtracker(payload.nav_posllh.iTOW, POSLLH_RECEIVED))
|
||||
{
|
||||
gpsposition->Altitude = (float)payload.nav_posllh.hMSL*0.001f;
|
||||
gpsposition->GeoidSeparation = (float)(payload.nav_posllh.height -
|
||||
payload.nav_posllh.hMSL)*0.001f;
|
||||
gpsposition->Latitude = payload.nav_posllh.lat;
|
||||
gpsposition->Longitude = payload.nav_posllh.lon;
|
||||
}
|
||||
}
|
||||
|
||||
void parse_ubx_nav_status (UBXPayload payload, GPSPositionData *gpsposition)
|
||||
{
|
||||
if (check_msgtracker(payload.nav_status.iTOW, STATUS_RECEIVED))
|
||||
{
|
||||
switch (payload.nav_status.gpsFix)
|
||||
{
|
||||
case STATUS_GPSFIX_2DFIX:
|
||||
gpsposition->Status = GPSPOSITION_STATUS_FIX2D;
|
||||
break;
|
||||
case STATUS_GPSFIX_3DFIX:
|
||||
gpsposition->Status = GPSPOSITION_STATUS_FIX3D;
|
||||
break;
|
||||
default: gpsposition->Status = GPSPOSITION_STATUS_NOFIX;
|
||||
if (check_msgtracker(posllh->iTOW, POSLLH_RECEIVED)) {
|
||||
if (GpsPosition->Status != GPSPOSITION_STATUS_NOFIX) {
|
||||
GpsPosition->Altitude = (float)posllh->hMSL*0.001f;
|
||||
GpsPosition->GeoidSeparation = (float)(posllh->height - posllh->hMSL)*0.001f;
|
||||
GpsPosition->Latitude = posllh->lat;
|
||||
GpsPosition->Longitude = posllh->lon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parse_ubx_nav_sol (UBXPayload payload, GPSPositionData *gpsposition)
|
||||
void parse_ubx_nav_status (UBX_NAV_STATUS *status, GPSPositionData *GpsPosition)
|
||||
{
|
||||
if (check_msgtracker(payload.nav_dop.iTOW, SOL_RECEIVED))
|
||||
{
|
||||
gpsposition->Satellites = (float)payload.nav_sol.numSV;
|
||||
switch (payload.nav_sol.gpsFix)
|
||||
{
|
||||
#if 0 // we already get this info from NAV_SOL
|
||||
if (check_msgtracker(status->iTOW, STATUS_RECEIVED)) {
|
||||
switch (status->gpsFix) {
|
||||
case STATUS_GPSFIX_2DFIX:
|
||||
gpsposition->Status = GPSPOSITION_STATUS_FIX2D;
|
||||
GpsPosition->Status = GPSPOSITION_STATUS_FIX2D;
|
||||
break;
|
||||
case STATUS_GPSFIX_3DFIX:
|
||||
gpsposition->Status = GPSPOSITION_STATUS_FIX3D;
|
||||
GpsPosition->Status = GPSPOSITION_STATUS_FIX3D;
|
||||
break;
|
||||
default: gpsposition->Status = GPSPOSITION_STATUS_NOFIX;
|
||||
default: GpsPosition->Status = GPSPOSITION_STATUS_NOFIX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void parse_ubx_nav_dop (UBXPayload payload, GPSPositionData *gpsposition)
|
||||
void parse_ubx_nav_sol (UBX_NAV_SOL *sol, GPSPositionData *GpsPosition)
|
||||
{
|
||||
if (check_msgtracker(payload.nav_dop.iTOW, DOP_RECEIVED))
|
||||
{
|
||||
gpsposition->HDOP = (float)payload.nav_dop.hDOP * 0.01f;
|
||||
gpsposition->VDOP = (float)payload.nav_dop.vDOP * 0.01f;
|
||||
gpsposition->PDOP = (float)payload.nav_dop.pDOP * 0.01f;
|
||||
if (check_msgtracker(sol->iTOW, SOL_RECEIVED)) {
|
||||
GpsPosition->Satellites = sol->numSV;
|
||||
|
||||
if (sol->flags & STATUS_FLAGS_GPSFIX_OK) {
|
||||
switch (sol->gpsFix) {
|
||||
case STATUS_GPSFIX_2DFIX:
|
||||
GpsPosition->Status = GPSPOSITION_STATUS_FIX2D;
|
||||
break;
|
||||
case STATUS_GPSFIX_3DFIX:
|
||||
GpsPosition->Status = GPSPOSITION_STATUS_FIX3D;
|
||||
break;
|
||||
default: GpsPosition->Status = GPSPOSITION_STATUS_NOFIX;
|
||||
}
|
||||
}
|
||||
else // fix is not valid so we make sure to treat is as NOFIX
|
||||
GpsPosition->Status = GPSPOSITION_STATUS_NOFIX;
|
||||
}
|
||||
}
|
||||
|
||||
void parse_ubx_nav_velned (UBXPayload payload, GPSPositionData *gpsposition)
|
||||
void parse_ubx_nav_dop (UBX_NAV_DOP *dop, GPSPositionData *GpsPosition)
|
||||
{
|
||||
if (check_msgtracker(dop->iTOW, DOP_RECEIVED)) {
|
||||
GpsPosition->HDOP = (float)dop->hDOP * 0.01f;
|
||||
GpsPosition->VDOP = (float)dop->vDOP * 0.01f;
|
||||
GpsPosition->PDOP = (float)dop->pDOP * 0.01f;
|
||||
}
|
||||
}
|
||||
|
||||
void parse_ubx_nav_velned (UBX_NAV_VELNED *velned, GPSPositionData *GpsPosition)
|
||||
{
|
||||
GPSVelocityData GpsVelocity;
|
||||
|
||||
GpsVelocity.North = (float)payload.nav_velned.velN/100.0f;
|
||||
GpsVelocity.East = (float)payload.nav_velned.velE/100.0f;
|
||||
GpsVelocity.Down = (float)payload.nav_velned.velD/100.0f;
|
||||
|
||||
GPSVelocitySet(&GpsVelocity);
|
||||
|
||||
if (check_msgtracker(payload.nav_velned.iTOW, VELNED_RECEIVED))
|
||||
{
|
||||
gpsposition->Groundspeed = (float)payload.nav_velned.gSpeed * 0.01f;
|
||||
gpsposition->Heading = (float)payload.nav_velned.heading * 1.0e-5f;
|
||||
if (check_msgtracker(velned->iTOW, VELNED_RECEIVED)) {
|
||||
if (GpsPosition->Status != GPSPOSITION_STATUS_NOFIX) {
|
||||
GpsVelocity.North = (float)velned->velN/100.0f;
|
||||
GpsVelocity.East = (float)velned->velE/100.0f;
|
||||
GpsVelocity.Down = (float)velned->velD/100.0f;
|
||||
GPSVelocitySet(&GpsVelocity);
|
||||
GpsPosition->Groundspeed = (float)velned->gSpeed * 0.01f;
|
||||
GpsPosition->Heading = (float)velned->heading * 1.0e-5f;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void parse_ubx_nav_timeutc (UBXPayload payload)
|
||||
#if !defined(PIOS_GPS_MINIMAL)
|
||||
void parse_ubx_nav_timeutc (UBX_NAV_TIMEUTC *timeutc)
|
||||
{
|
||||
if (!(payload.nav_timeutc.valid & TIMEUTC_VALIDUTC))
|
||||
if (!(timeutc->valid & TIMEUTC_VALIDUTC))
|
||||
return;
|
||||
|
||||
GPSTimeData gpst;
|
||||
GPSTimeData GpsTime;
|
||||
|
||||
gpst.Year = payload.nav_timeutc.year;
|
||||
gpst.Month = payload.nav_timeutc.month;
|
||||
gpst.Day = payload.nav_timeutc.day;
|
||||
gpst.Hour = payload.nav_timeutc.hour;
|
||||
gpst.Minute = payload.nav_timeutc.min;
|
||||
gpst.Second = payload.nav_timeutc.sec;
|
||||
GpsTime.Year = timeutc->year;
|
||||
GpsTime.Month = timeutc->month;
|
||||
GpsTime.Day = timeutc->day;
|
||||
GpsTime.Hour = timeutc->hour;
|
||||
GpsTime.Minute = timeutc->min;
|
||||
GpsTime.Second = timeutc->sec;
|
||||
|
||||
GPSTimeSet(&gpst);
|
||||
GPSTimeSet(&GpsTime);
|
||||
}
|
||||
#endif
|
||||
|
||||
void parse_ubx_nav_svinfo (UBXPayload payload)
|
||||
#if !defined(PIOS_GPS_MINIMAL)
|
||||
void parse_ubx_nav_svinfo (UBX_NAV_SVINFO *svinfo)
|
||||
{
|
||||
GPSSatellitesData svdata;
|
||||
uint8_t chan;
|
||||
GPSSatellitesData svdata;
|
||||
|
||||
svdata.SatsInView = 0;
|
||||
for (chan = 0; chan < payload.nav_svinfo.numCh; chan++)
|
||||
{
|
||||
if ((payload.nav_svinfo.sv[chan].elev > 0) && // some unhealthy SV report negative elevation
|
||||
(svdata.SatsInView < GPSSATELLITES_PRN_NUMELEM))
|
||||
{
|
||||
svdata.Azimuth[svdata.SatsInView] = (float)payload.nav_svinfo.sv[chan].azim;
|
||||
svdata.Elevation[svdata.SatsInView] = (float)payload.nav_svinfo.sv[chan].elev;
|
||||
svdata.PRN[svdata.SatsInView] = payload.nav_svinfo.sv[chan].svid;
|
||||
svdata.SNR[svdata.SatsInView] = payload.nav_svinfo.sv[chan].cno;
|
||||
for (chan = 0; chan < svinfo->numCh; chan++) {
|
||||
if ((svinfo->sv[chan].elev > 0) && // some unhealthy SV report negative elevation
|
||||
(svdata.SatsInView < GPSSATELLITES_PRN_NUMELEM)) {
|
||||
svdata.Azimuth[svdata.SatsInView] = (float)svinfo->sv[chan].azim;
|
||||
svdata.Elevation[svdata.SatsInView] = (float)svinfo->sv[chan].elev;
|
||||
svdata.PRN[svdata.SatsInView] = svinfo->sv[chan].svid;
|
||||
svdata.SNR[svdata.SatsInView] = svinfo->sv[chan].cno;
|
||||
svdata.SatsInView++;
|
||||
}
|
||||
|
||||
}
|
||||
// fill remaining slots (if any)
|
||||
for (chan = svdata.SatsInView; chan < GPSSATELLITES_PRN_NUMELEM; chan++)
|
||||
{
|
||||
for (chan = svdata.SatsInView; chan < GPSSATELLITES_PRN_NUMELEM; chan++) {
|
||||
svdata.Azimuth[chan] = (float)0.0f;
|
||||
svdata.Elevation[chan] = (float)0.0f;
|
||||
svdata.PRN[chan] = 0;
|
||||
@ -228,51 +305,51 @@ void parse_ubx_nav_svinfo (UBXPayload payload)
|
||||
|
||||
GPSSatellitesSet(&svdata);
|
||||
}
|
||||
#endif
|
||||
|
||||
// UBX message parser
|
||||
// returns true on valid position updates
|
||||
// returns UAVObjectID if a UAVObject structure is ready for further processing
|
||||
|
||||
bool parse_ubx_message (UBXPacket *ubx, GPSPositionData *gpsposition)
|
||||
uint32_t parse_ubx_message (UBXPacket *ubx, GPSPositionData *GpsPosition)
|
||||
{
|
||||
#if defined(REVOLUTION)
|
||||
uint32_t id = 0;
|
||||
|
||||
switch (ubx->header.class)
|
||||
{
|
||||
switch (ubx->header.class) {
|
||||
case UBX_CLASS_NAV:
|
||||
switch (ubx->header.id)
|
||||
{
|
||||
switch (ubx->header.id) {
|
||||
case UBX_ID_POSLLH:
|
||||
parse_ubx_nav_posllh (ubx->payload, gpsposition);
|
||||
parse_ubx_nav_posllh (&ubx->payload.nav_posllh, GpsPosition);
|
||||
break;
|
||||
case UBX_ID_STATUS:
|
||||
parse_ubx_nav_status (ubx->payload, gpsposition);
|
||||
parse_ubx_nav_status (&ubx->payload.nav_status, GpsPosition);
|
||||
break;
|
||||
case UBX_ID_DOP:
|
||||
parse_ubx_nav_dop (ubx->payload, gpsposition);
|
||||
parse_ubx_nav_dop (&ubx->payload.nav_dop, GpsPosition);
|
||||
break;
|
||||
case UBX_ID_SOL:
|
||||
parse_ubx_nav_sol (ubx->payload, gpsposition);
|
||||
parse_ubx_nav_sol (&ubx->payload.nav_sol, GpsPosition);
|
||||
break;
|
||||
case UBX_ID_VELNED:
|
||||
parse_ubx_nav_velned (ubx->payload, gpsposition);
|
||||
parse_ubx_nav_velned (&ubx->payload.nav_velned, GpsPosition);
|
||||
break;
|
||||
#if !defined(PIOS_GPS_MINIMAL)
|
||||
case UBX_ID_TIMEUTC:
|
||||
parse_ubx_nav_timeutc (ubx->payload);
|
||||
parse_ubx_nav_timeutc (&ubx->payload.nav_timeutc);
|
||||
break;
|
||||
case UBX_ID_SVINFO:
|
||||
parse_ubx_nav_svinfo (ubx->payload);
|
||||
parse_ubx_nav_svinfo (&ubx->payload.nav_svinfo);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (msgtracker.msg_received == ALL_RECEIVED)
|
||||
{
|
||||
GPSPositionSet(gpsposition);
|
||||
if (msgtracker.msg_received == ALL_RECEIVED) {
|
||||
GPSPositionSet(GpsPosition);
|
||||
msgtracker.msg_received = NONE_RECEIVED;
|
||||
return true;
|
||||
id = GPSPOSITION_OBJID;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
return id;
|
||||
}
|
||||
|
||||
#endif // PIOS_INCLUDE_GPS_UBX_PARSER
|
||||
|
||||
|
@ -1,44 +1,55 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup OpenPilotModules OpenPilot Modules
|
||||
* @{
|
||||
* @addtogroup GSPModule GPS Module
|
||||
* @brief Process GPS information
|
||||
* @{
|
||||
*
|
||||
* @file GPS.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Include file of the GPS module.
|
||||
* As with all modules only the initialize function is exposed all other
|
||||
* interactions with the module take place through the event queue and
|
||||
* objects.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef GPS_H
|
||||
#define GPS_H
|
||||
|
||||
int32_t GPSInitialize(void);
|
||||
|
||||
#endif // GPS_H
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup OpenPilotModules OpenPilot Modules
|
||||
* @{
|
||||
* @addtogroup GSPModule GPS Module
|
||||
* @brief Process GPS information
|
||||
* @{
|
||||
*
|
||||
* @file GPS.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Include file of the GPS module.
|
||||
* As with all modules only the initialize function is exposed all other
|
||||
* interactions with the module take place through the event queue and
|
||||
* objects.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef GPS_H
|
||||
#define GPS_H
|
||||
|
||||
#include "gpsvelocity.h"
|
||||
#include "gpssatellites.h"
|
||||
#include "gpsposition.h"
|
||||
#include "gpstime.h"
|
||||
|
||||
#define NO_PARSER -3 // no parser available
|
||||
#define PARSER_OVERRUN -2 // message buffer overrun before completing the message
|
||||
#define PARSER_ERROR -1 // message unparsable by this parser
|
||||
#define PARSER_INCOMPLETE 0 // parser needs more data to complete the message
|
||||
#define PARSER_COMPLETE 1 // parser has received a complete message and finished processing
|
||||
|
||||
int32_t GPSInitialize(void);
|
||||
|
||||
#endif // GPS_H
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
@ -34,7 +34,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern bool NMEA_update_position(char *nmea_sentence);
|
||||
#define NMEA_MAX_PACKET_LENGTH 96 // 82 max NMEA msg size plus 12 margin (because some vendors add custom crap) plus CR plus Linefeed
|
||||
|
||||
extern bool NMEA_update_position(char *nmea_sentence, GPSPositionData *GpsData);
|
||||
extern bool NMEA_checksum(char *nmea_sentence);
|
||||
extern int parse_nmea_stream(uint8_t, char *, GPSPositionData *);
|
||||
|
||||
#endif /* NMEA_H */
|
||||
|
@ -31,6 +31,7 @@
|
||||
#ifndef UBX_H
|
||||
#define UBX_H
|
||||
#include "openpilot.h"
|
||||
#include "gpsposition.h"
|
||||
|
||||
#define UBX_SYNC1 0xb5 // UBX protocol synchronization characters
|
||||
#define UBX_SYNC2 0x62
|
||||
@ -53,13 +54,13 @@
|
||||
|
||||
// Geodetic Position Solution
|
||||
typedef struct {
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
int32_t lon; // Longitude (deg*1e-7)
|
||||
int32_t lat; // Latitude (deg*1e-7)
|
||||
int32_t height; // Height above Ellipoid (mm)
|
||||
int32_t hMSL; // Height abobe mean sea level (mm)
|
||||
uint32_t hAcc; // Horizontal Accuracy Estimate (mm)
|
||||
uint32_t vAcc; // Vertical Accuracy Estimate (mm)
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
int32_t lon; // Longitude (deg*1e-7)
|
||||
int32_t lat; // Latitude (deg*1e-7)
|
||||
int32_t height; // Height above Ellipoid (mm)
|
||||
int32_t hMSL; // Height abobe mean sea level (mm)
|
||||
uint32_t hAcc; // Horizontal Accuracy Estimate (mm)
|
||||
uint32_t vAcc; // Vertical Accuracy Estimate (mm)
|
||||
} UBX_NAV_POSLLH;
|
||||
|
||||
// Receiver Navigation Status
|
||||
@ -77,61 +78,61 @@ typedef struct {
|
||||
#define STATUS_FLAGS_TOWSET (1 << 3)
|
||||
|
||||
typedef struct {
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
uint8_t gpsFix; // GPS fix type
|
||||
uint8_t flags; // Navigation Status Flags
|
||||
uint8_t fixStat; // Fix Status Information
|
||||
uint8_t flags2; // Additional navigation output information
|
||||
uint32_t ttff; // Time to first fix (ms)
|
||||
uint32_t msss; // Milliseconds since startup/reset (ms)
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
uint8_t gpsFix; // GPS fix type
|
||||
uint8_t flags; // Navigation Status Flags
|
||||
uint8_t fixStat; // Fix Status Information
|
||||
uint8_t flags2; // Additional navigation output information
|
||||
uint32_t ttff; // Time to first fix (ms)
|
||||
uint32_t msss; // Milliseconds since startup/reset (ms)
|
||||
} UBX_NAV_STATUS;
|
||||
|
||||
// Dilution of precision
|
||||
typedef struct {
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
uint16_t gDOP; // Geometric DOP
|
||||
uint16_t pDOP; // Position DOP
|
||||
uint16_t tDOP; // Time DOP
|
||||
uint16_t vDOP; // Vertical DOP
|
||||
uint16_t hDOP; // Horizontal DOP
|
||||
uint16_t nDOP; // Northing DOP
|
||||
uint16_t eDOP; // Easting DOP
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
uint16_t gDOP; // Geometric DOP
|
||||
uint16_t pDOP; // Position DOP
|
||||
uint16_t tDOP; // Time DOP
|
||||
uint16_t vDOP; // Vertical DOP
|
||||
uint16_t hDOP; // Horizontal DOP
|
||||
uint16_t nDOP; // Northing DOP
|
||||
uint16_t eDOP; // Easting DOP
|
||||
} UBX_NAV_DOP;
|
||||
|
||||
// Navigation solution
|
||||
|
||||
typedef struct {
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
int32_t fTOW; // fracional nanoseconds (ns)
|
||||
int16_t week; // GPS week
|
||||
uint8_t gpsFix; // GPS fix type
|
||||
uint8_t flags; // Fix status flags
|
||||
int32_t ecefX; // ECEF X coordinate (cm)
|
||||
int32_t ecefY; // ECEF Y coordinate (cm)
|
||||
int32_t ecefZ; // ECEF Z coordinate (cm)
|
||||
uint32_t pAcc; // 3D Position Accuracy Estimate (cm)
|
||||
int32_t ecefVX; // ECEF X coordinate (cm/s)
|
||||
int32_t ecefVY; // ECEF Y coordinate (cm/s)
|
||||
int32_t ecefVZ; // ECEF Z coordinate (cm/s)
|
||||
uint32_t sAcc; // Speed Accuracy Estimate
|
||||
uint16_t pDOP; // Position DOP
|
||||
uint8_t reserved1; // Reserved
|
||||
uint8_t numSV; // Number of SVs used in Nav Solution
|
||||
uint32_t reserved2; // Reserved
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
int32_t fTOW; // fracional nanoseconds (ns)
|
||||
int16_t week; // GPS week
|
||||
uint8_t gpsFix; // GPS fix type
|
||||
uint8_t flags; // Fix status flags
|
||||
int32_t ecefX; // ECEF X coordinate (cm)
|
||||
int32_t ecefY; // ECEF Y coordinate (cm)
|
||||
int32_t ecefZ; // ECEF Z coordinate (cm)
|
||||
uint32_t pAcc; // 3D Position Accuracy Estimate (cm)
|
||||
int32_t ecefVX; // ECEF X coordinate (cm/s)
|
||||
int32_t ecefVY; // ECEF Y coordinate (cm/s)
|
||||
int32_t ecefVZ; // ECEF Z coordinate (cm/s)
|
||||
uint32_t sAcc; // Speed Accuracy Estimate
|
||||
uint16_t pDOP; // Position DOP
|
||||
uint8_t reserved1; // Reserved
|
||||
uint8_t numSV; // Number of SVs used in Nav Solution
|
||||
uint32_t reserved2; // Reserved
|
||||
} UBX_NAV_SOL;
|
||||
|
||||
// North/East/Down velocity
|
||||
|
||||
typedef struct {
|
||||
uint32_t iTOW; // ms GPS Millisecond Time of Week
|
||||
int32_t velN; // cm/s NED north velocity
|
||||
int32_t velE; // cm/s NED east velocity
|
||||
int32_t velD; // cm/s NED down velocity
|
||||
uint32_t speed; // cm/s Speed (3-D)
|
||||
uint32_t gSpeed; // cm/s Ground Speed (2-D)
|
||||
int32_t heading; // 1e-5 *deg Heading of motion 2-D
|
||||
uint32_t sAcc; // cm/s Speed Accuracy Estimate
|
||||
uint32_t cAcc; // 1e-5 *deg Course / Heading Accuracy Estimate
|
||||
uint32_t iTOW; // ms GPS Millisecond Time of Week
|
||||
int32_t velN; // cm/s NED north velocity
|
||||
int32_t velE; // cm/s NED east velocity
|
||||
int32_t velD; // cm/s NED down velocity
|
||||
uint32_t speed; // cm/s Speed (3-D)
|
||||
uint32_t gSpeed; // cm/s Ground Speed (2-D)
|
||||
int32_t heading; // 1e-5 *deg Heading of motion 2-D
|
||||
uint32_t sAcc; // cm/s Speed Accuracy Estimate
|
||||
uint32_t cAcc; // 1e-5 *deg Course / Heading Accuracy Estimate
|
||||
} UBX_NAV_VELNED;
|
||||
|
||||
// UTC Time Solution
|
||||
@ -141,51 +142,51 @@ typedef struct {
|
||||
#define TIMEUTC_VALIDUTC (1 << 2)
|
||||
|
||||
typedef struct {
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
uint32_t tAcc; // Time Accuracy Estimate (ns)
|
||||
int32_t nano; // Nanoseconds of second
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
uint32_t tAcc; // Time Accuracy Estimate (ns)
|
||||
int32_t nano; // Nanoseconds of second
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
uint8_t hour;
|
||||
uint8_t min;
|
||||
uint8_t sec;
|
||||
uint8_t valid; // Validity Flags
|
||||
uint8_t valid; // Validity Flags
|
||||
} UBX_NAV_TIMEUTC;
|
||||
|
||||
// Space Vehicle (SV) Information
|
||||
|
||||
// Single SV information block
|
||||
|
||||
#define SVUSED (1 << 0) // This SV is used for navigation
|
||||
#define DIFFCORR (1 << 1) // Differential correction available
|
||||
#define ORBITAVAIL (1 << 2) // Orbit information available
|
||||
#define ORBITEPH (1 << 3) // Orbit information is Ephemeris
|
||||
#define UNHEALTHY (1 << 4) // SV is unhealthy
|
||||
#define ORBITALM (1 << 5) // Orbit information is Almanac Plus
|
||||
#define ORBITAOP (1 << 6) // Orbit information is AssistNow Autonomous
|
||||
#define SMOOTHED (1 << 7) // Carrier smoothed pseudoranges used
|
||||
#define SVUSED (1 << 0) // This SV is used for navigation
|
||||
#define DIFFCORR (1 << 1) // Differential correction available
|
||||
#define ORBITAVAIL (1 << 2) // Orbit information available
|
||||
#define ORBITEPH (1 << 3) // Orbit information is Ephemeris
|
||||
#define UNHEALTHY (1 << 4) // SV is unhealthy
|
||||
#define ORBITALM (1 << 5) // Orbit information is Almanac Plus
|
||||
#define ORBITAOP (1 << 6) // Orbit information is AssistNow Autonomous
|
||||
#define SMOOTHED (1 << 7) // Carrier smoothed pseudoranges used
|
||||
|
||||
typedef struct {
|
||||
uint8_t chn; // Channel number
|
||||
uint8_t svid; // Satellite ID
|
||||
uint8_t flags; // Misc SV information
|
||||
uint8_t quality; // Misc quality indicators
|
||||
uint8_t cno; // Carrier to Noise Ratio (dbHz)
|
||||
int8_t elev; // Elevation (integer degrees)
|
||||
int16_t azim; // Azimuth (integer degrees)
|
||||
int32_t prRes; // Pseudo range residual (cm)
|
||||
uint8_t chn; // Channel number
|
||||
uint8_t svid; // Satellite ID
|
||||
uint8_t flags; // Misc SV information
|
||||
uint8_t quality; // Misc quality indicators
|
||||
uint8_t cno; // Carrier to Noise Ratio (dbHz)
|
||||
int8_t elev; // Elevation (integer degrees)
|
||||
int16_t azim; // Azimuth (integer degrees)
|
||||
int32_t prRes; // Pseudo range residual (cm)
|
||||
} UBX_NAV_SVINFO_SV;
|
||||
|
||||
// SV information message
|
||||
#define MAX_SVINFO_MSG_SIZE 208
|
||||
#define MAX_SVS 16
|
||||
|
||||
typedef struct {
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
uint8_t numCh; // Number of channels
|
||||
uint8_t globalFlags; //
|
||||
uint16_t reserved2; // Reserved
|
||||
UBX_NAV_SVINFO_SV sv[16]; // Repeated 'numCh' times
|
||||
uint32_t iTOW; // GPS Millisecond Time of Week (ms)
|
||||
uint8_t numCh; // Number of channels
|
||||
uint8_t globalFlags; //
|
||||
uint16_t reserved2; // Reserved
|
||||
UBX_NAV_SVINFO_SV sv[MAX_SVS]; // Repeated 'numCh' times
|
||||
} UBX_NAV_SVINFO;
|
||||
|
||||
typedef union {
|
||||
@ -195,8 +196,10 @@ typedef union {
|
||||
UBX_NAV_DOP nav_dop;
|
||||
UBX_NAV_SOL nav_sol;
|
||||
UBX_NAV_VELNED nav_velned;
|
||||
#if !defined(PIOS_GPS_MINIMAL)
|
||||
UBX_NAV_TIMEUTC nav_timeutc;
|
||||
UBX_NAV_SVINFO nav_svinfo;
|
||||
#endif
|
||||
} UBXPayload;
|
||||
|
||||
typedef struct {
|
||||
@ -213,5 +216,7 @@ typedef struct {
|
||||
} UBXPacket;
|
||||
|
||||
bool checksum_ubx_message(UBXPacket *);
|
||||
bool parse_ubx_message(UBXPacket *, GPSPositionData *);
|
||||
uint32_t parse_ubx_message(UBXPacket *, GPSPositionData *);
|
||||
int parse_ubx_stream(uint8_t, char *, GPSPositionData *);
|
||||
|
||||
#endif /* UBX_H */
|
||||
|
@ -96,6 +96,8 @@
|
||||
#define PIOS_TELEM_PRIORITY_QUEUE /* Enable a priority queue in telemetry */
|
||||
#define PIOS_QUATERNION_STABILIZATION /* Stabilization options */
|
||||
//#define PIOS_GPS_SETS_HOMELOCATION /* GPS options */
|
||||
#define PIOS_INCLUDE_GPS_NMEA_PARSER /* Include the NMEA protocol parser */
|
||||
#define PIOS_INCLUDE_GPS_UBX_PARSER /* Include the UBX protocol parser */
|
||||
|
||||
/* Alarm Thresholds */
|
||||
#define HEAP_LIMIT_WARNING 4000
|
||||
|
@ -46,6 +46,7 @@ UAVOBJSRCFILENAMES += flighttelemetrystats
|
||||
UAVOBJSRCFILENAMES += gcstelemetrystats
|
||||
UAVOBJSRCFILENAMES += gpsposition
|
||||
UAVOBJSRCFILENAMES += gpssatellites
|
||||
UAVOBJSRCFILENAMES += gpssettings
|
||||
UAVOBJSRCFILENAMES += gpstime
|
||||
UAVOBJSRCFILENAMES += guidancesettings
|
||||
UAVOBJSRCFILENAMES += homelocation
|
||||
|
@ -52,6 +52,8 @@ HEADERS += $$UAVOBJECT_SYNTHETICS/accessorydesired.h \
|
||||
$$UAVOBJECT_SYNTHETICS/gpsposition.h \
|
||||
$$UAVOBJECT_SYNTHETICS/gpstime.h \
|
||||
$$UAVOBJECT_SYNTHETICS/gpssatellites.h \
|
||||
$$UAVOBJECT_SYNTHETICS/gpssettings.h \
|
||||
$$UAVOBJECT_SYNTHETICS/gpsvelocity.h \
|
||||
$$UAVOBJECT_SYNTHETICS/positionactual.h \
|
||||
$$UAVOBJECT_SYNTHETICS/flightbatterystate.h \
|
||||
$$UAVOBJECT_SYNTHETICS/homelocation.h \
|
||||
@ -112,6 +114,8 @@ SOURCES += $$UAVOBJECT_SYNTHETICS/accessorydesired.cpp \
|
||||
$$UAVOBJECT_SYNTHETICS/gpsposition.cpp \
|
||||
$$UAVOBJECT_SYNTHETICS/gpstime.cpp \
|
||||
$$UAVOBJECT_SYNTHETICS/gpssatellites.cpp \
|
||||
$$UAVOBJECT_SYNTHETICS/gpssettings.cpp \
|
||||
$$UAVOBJECT_SYNTHETICS/gpsvelocity.cpp \
|
||||
$$UAVOBJECT_SYNTHETICS/positionactual.cpp \
|
||||
$$UAVOBJECT_SYNTHETICS/flightbatterystate.cpp \
|
||||
$$UAVOBJECT_SYNTHETICS/homelocation.cpp \
|
||||
|
Loading…
x
Reference in New Issue
Block a user