Unfortunately, there is very little example code out there for GPSd's C library, libgps (gps.h). Here is my experience with the library, as well as the code that I came up with.
From what I can understand about how GPSd and GPS mouses work together, the mouse is actually constantly looking for a fix. This was a little counter-intuitive to me, since I am used to working with Android where the device doesn't actually look for a fix unless you register with it. The GPS mouse sends status updates to GPSd on a regular basis, so what your code actually needs to do is ask GPSd to give you the next update, and determine if it's a fix or not. If the mouse currently does not have a fix, the function exits (and you should try again later when the mouse says you do have a fix)
Here is my shoddily documented code:
int getGPSData(gps_data_t *gpsdata){ //connect to GPSd if(gps_open("localhost", "2947", gpsdata)<0){ fprintf(stderr,"Could not connect to GPSd\n"); return(-1); } //register for updates gps_stream(gpsdata, WATCH_ENABLE | WATCH_JSON, NULL); fprintf(stderr,"Waiting for gps lock."); //when status is >0, you have data. while(gpsdata->status==0){ //block for up to .5 seconds if (gps_waiting(gpsdata, 500)){ //dunno when this would happen but its an error if(gps_read(gpsdata)==-1){ fprintf(stderr,"GPSd Error\n"); gps_stream(gpsdata, WATCH_DISABLE, NULL); gps_close(gpsdata); return(-1); break; } else{ //status>0 means you have data if(gpsdata->status>0){ //sometimes if your GPS doesnt have a fix, it sends you data anyways //the values for the fix are NaN. this is a clever way to check for NaN. if(gpsdata->fix.longitude!=gpsdata->fix.longitude || gpsdata->fix.altitude!=gpsdata->fix.altitude){ fprintf(stderr,"Could not get a GPS fix.\n"); gps_stream(gpsdata, WATCH_DISABLE, NULL); gps_close(gpsdata); return(-1); } //otherwise you have a legitimate fix! else fprintf(stderr,"\n"); } //if you don't have any data yet, keep waiting for it. else fprintf(stderr,"."); } } //apparently gps_stream disables itself after a few seconds.. in this case, gps_waiting returns false. //we want to re-register for updates and keep looping! we dont have a fix yet. else gps_stream(gpsdata, WATCH_ENABLE | WATCH_JSON, NULL); //just a sleep for good measure. sleep(1); } //cleanup gps_stream(gpsdata, WATCH_DISABLE, NULL); gps_close(gpsdata); }
This works fine with my GlobalSat BU-353 GPS mouse. I guess there is always more testing to be done, but this works consistently.
Here is how you might print the results:
void debugDump(gps_data_t *gpsdata){ fprintf(stderr,"Longitude: %lf\nLatitude: %lf\nAltitude: %lf\nAccuracy: %lf\n\n", gpsdata->fix.latitude, gpsdata->fix.longitude, gpsdata->fix.altitude, (gpsdata->fix.epx>gpsdata->fix.epy)?gpsdata->fix.epx:gpsdata->fix.epy); }
I'm not entirely sure that's the best way to determine the accuracy. I'm not sure exactly what the ep attributes mean, they weren't explained well in the gps.h header file. My goal is to record something analogous to Android's getAccuracy() method. If anyone knows if my solution (just grabbing the larger of the two numbers) works or not, please comment and let me know!
Something to keep in mind when working with libgps/gps.h (and I'm sure this is common sense, but I'm an idiot sometimes), you need to use the -lgps compiler flag!
thank you for your nice tutorial!
ReplyDeleteYour tutorial and comments have been REALLY helpful in demystifying GPSD for me. I'm trying to run my own GPSD code, and having problems with accessing gps.h. My compile command is:
ReplyDeletegcc -o gps_test gps_test.c -l gps
And it returns the following error:
fata error: gps.h: No such file or directory compilation terminated.
It seems that I don't have the libraries installed, but I have already installed them by the following commands:
sudo apt-get install gpsd gpsd-clients python-gps
sudo apt-get install gpsd
Am I missing something? Where do I install or access gps.h?
Hi Micah! Glad I could be of some help. Unfortunately it's been a long time since I've used GPSd. The first thing I would recommend trying is installing the libgps-dev package. Since it seems you are missing dev headers, that is the likely solution.
DeleteIf that doesn't work, you could try building GPSd from scratch. Here is how I used to do it on Ubuntu 12.04:
wget http://download-mirror.savannah.gnu.org/releases/gpsd/gpsd-3.7.tar.gz
tar -xzf gpsd-3.7.tar.gz
cd gpsd-3.7
scons prefix=/usr
sudo scons udev-install
This comment has been removed by a blog administrator.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDelete