1

I have GPSD installed and am using the c library libgps. It works okay, but I've noticed what look like bugs. Specifically if I run the simple program below with the GPS plugged in the program prints GPS data like expected, but if while runnign I unplugged the GPS the program still says it has a GPS fix, and also the lat. and long. values change slightly. Which is obviously very odd. I would guess I'm doing something wrong in the code but I can't figure it out, any ideas?

    #include <gps.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>

int main() {
int rc;
struct timeval tv;

struct gps_data_t gps_data;
if ((rc = gps_open("localhost", "2947", &gps_data)) == -1) {
    printf("code: %d, reason: %s\n", rc, gps_errstr(rc));
    return EXIT_FAILURE;
}
gps_stream(&gps_data, WATCH_ENABLE | WATCH_JSON, NULL);

while (1) {
    /* wait for 2 seconds to receive data */
    if (gps_waiting (&gps_data, 2000000)) {
        /* read data */
        printf("GPS Status: %i, GPS Fix Mode: %i, GPS Lat: %f \n", gps_data.status,gps_data.fix.mode,gps_data.fix.latitude);
        if ((rc = gps_read(&gps_data)) == -1) {
            printf("error occured reading gps data. code: %d, reason: %s\n", rc, gps_errstr(rc));
        } else {
            /* Display data from the GPS receiver. */
            if ((gps_data.status == STATUS_FIX) &&
                (gps_data.fix.mode == MODE_2D || gps_data.fix.mode == MODE_3D) &&
                !isnan(gps_data.fix.latitude) &&
                !isnan(gps_data.fix.longitude)) {
                    //gettimeofday(&tv, NULL); EDIT: tv.tv_sec isn't actually the timestamp!
                    printf("GPS Status: %i, latitude: %f, longitude: %f, speed: %f, timestamp: %lf\n", gps_data.status, gps_data.fix.latitude, gps_data.fix.longitude, gps_data.fix.speed, gps_data.fix.time); //EDIT: Replaced tv.tv_sec with gps_data.fix.time
            } else {
                printf("no GPS data available\n");
            }
        }
    }

    sleep(3);
    printf("out of sleep \n");
}

/* When you are done... */
gps_stream(&gps_data, WATCH_DISABLE, NULL);
gps_close (&gps_data);

return EXIT_SUCCESS;
}

Example of output data with GPS unplugged

GPS Status: 1, GPS Fix Mode: 3, GPS Lat: 34.371312 
GPS Status: 1, latitude: 34.371312, longitude: -117.448095, speed: 0.050000, timestamp: 1551545758.000000
out of sleep 
GPS Status: 1, GPS Fix Mode: 3, GPS Lat: 34.371312 
GPS Status: 1, latitude: 34.371313, longitude: -117.448093, speed: 0.114000, timestamp: 1551545759.000000
out of sleep 
GPS Status: 1, GPS Fix Mode: 2, GPS Lat: 34.371313 
GPS Status: 1, latitude: 34.371313, longitude: -117.448093, speed: 0.114000, timestamp: 1551545759.000000
out of sleep 
GPS Status: 1, GPS Fix Mode: 3, GPS Lat: 34.371313 
GPS Status: 1, latitude: 34.371313, longitude: -117.448093, speed: 0.114000, timestamp: 1551545759.000000
out of sleep 
GPS Status: 1, GPS Fix Mode: 3, GPS Lat: 34.371313 
GPS Status: 1, latitude: 34.371313, longitude: -117.448093, speed: 0.095000, timestamp: 1551545760.000000

I also noticed sometimes the program above says gps_data.status = 0 (no satellite fix), but cgps will have a fix. Both are running at same time (i.e., program above and cgps).

2 Answers 2

2

The

sleep(3);

statement inside your while loop is causing this behaviour.

If you check your timestamp values, you will realize that you are getting 3 readings per second from GPSD.
On the other hand you are only reading 1 message every 3 seconds due to your sleep statement.
This means you are simply reading a lot of old messages from the time where your GPS module was still plugged in.

Removing the sleep(3) from your while loop should fix it.

2
  • Thank you, I was under the impression that whenever you called gps_read(&gps_data) you got the most recent data the GPSD daemon has from the gps hardware. So what your saying is that's not true? The data just builds up?
    – Paul
    Mar 3, 2019 at 4:44
  • Exactly, you are basically reading from a FIFO queue. Btw. welcome to the Raspberry Pi Stackexchange. Please read the tour page to understand, how things work around here. raspberrypi.stackexchange.com/tour
    – oh.dae.su
    Mar 3, 2019 at 5:31
0

There could be 2 causes for this. one is odd logic in your program or example code the other is backlog of data in the serial buffer from your GPS to gpsd. if you unplug it and wait for gpsd to clear it's buffer and register it as disconnected you won't see any other updates. This is very similar to networking issues where you pull the network cable but still get messages till buffers are emptied out.

status == STATUS_FIX is not the guard you want in here. That is just an indication from the GPS of what type of fix it has and not that it has a fix or not. you should be looking at mode and checking isfinite() Also checking set to see if you got a new gps position update

https://gpsd.io/libgps.html has a simple example that covers your question.

// example  gpsd client

// compile this way: // gcc example.c -o example -lgps -lm #include <gps.h> #include <math.h> // for isfinite() #include <unistd.h> // for sleep()

#define MODE_STR_NUM 4 static char *mode_str[MODE_STR_NUM] = { "n/a", "None", "2D", "3D" };

int main(int argc, char *argv[]) { struct gps_data_t gps_data;

if (0 != gps_open("localhost", "2947", &gps_data)) {
    printf("Open error.  Bye, bye\n");
    return 1;
}

(void)gps_stream(&gps_data, WATCH_ENABLE | WATCH_JSON, NULL);

// Wait for data available.
while (gps_waiting(&gps_data, 5000000)) {
    // will not block because we know data is available.
    if (-1 == gps_read(&gps_data, NULL, 0)) {
        printf("Read error.  Bye, bye\n");
        break;
    }
    if (MODE_SET != (MODE_SET & gps_data.set)) {
        // did not even get mode, nothing to see here
        continue;
    }
    if (0 > gps_data.fix.mode ||
        MODE_STR_NUM <= gps_data.fix.mode) {
        gps_data.fix.mode = 0;
    }
    printf("Fix mode: %s (%d) Time: ",
           mode_str[gps_data.fix.mode],
           gps_data.fix.mode);
    if (TIME_SET == (TIME_SET & gps_data.set)) {
        // not 32 bit safe
        printf("%ld.%09ld ", gps_data.fix.time.tv_sec,
               gps_data.fix.time.tv_nsec);
    } else {
        puts("n/a ");
    }
    if (isfinite(gps_data.fix.latitude) &&
        isfinite( gps_data.fix.longitude)) {
        // Display data from the GPS receiver if valid.
        printf("Lat %.6f Lon %.6f\n",
               gps_data.fix.latitude, gps_data.fix.longitude);
    }
}

// When you are done...
(void)gps_stream(&gps_data, WATCH_DISABLE, NULL);
(void)gps_close(&gps_data);
return 0;

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.