Skip to content

Instantly share code, notes, and snippets.

@ncoder-1
Last active July 1, 2022 09:07
Show Gist options
  • Save ncoder-1/8313815ac387e6757f751dc8960f03d7 to your computer and use it in GitHub Desktop.
Save ncoder-1/8313815ac387e6757f751dc8960f03d7 to your computer and use it in GitHub Desktop.
example C++17 gpsd program using libgpsmm
// Example C++17 gpsd program using libgpsmm
// Has no actual purpose other than output some of libgpsmm struct variables of your choosing.
// reference declarations: https://fossies.org/dox/gpsd-3.22/index.html
//
// compiles without warning as follows:
// g++ -std=c++17 -Wall -pedantic -pthread $(pkg-config --cflags --libs libgps) gpsd-example.cpp -o gpsd-example
// clang++ -std=c++17 -Wall -pedantic -pthread $(pkg-config --cflags --libs libgps) gpsd-example.cpp -o gpsd-example
// Free for the taking.
// Version 1.84
#include <libgpsmm.h>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <thread>
enum TimeFormat { LOCALTIME, UTC, UNIX, ISO_8601 };
auto TimespecToTimeStr(const timespec& gpsd_time, TimeFormat time_format = LOCALTIME) {
// example showing different ways of formating GPSD's timespec, depending on requirement
std::ostringstream oss;
switch (time_format) {
case LOCALTIME: {
// convert timespec_t into localtime (dd-mm-YY HH:MM:SS)
const auto tm = *std::localtime(&gpsd_time.tv_sec);
oss << std::put_time(&tm, "%d-%m-%Y %H:%M:%S");
break;
}
case UTC: {
// convert timespec_t into UTC (dd-mm-YY HH:MM:SS)
const auto tm = *std::gmtime(&gpsd_time.tv_sec);
oss << std::put_time(&tm, "%d-%m-%Y %H:%M:%S");
break;
}
case UNIX:
// returns seconds since the Epoch
oss << gpsd_time.tv_sec;
break;
case ISO_8601: {
// convert timespec_t into ISO8601 UTC time (yyyy-MM-dd'T'HH:mm:ss'Z')
constexpr size_t kScrSize{128};
std::array<char, kScrSize> scr{};
timespec_to_iso8601(gpsd_time, scr.data(), kScrSize);
oss << scr.data();
break;
}
}
return oss.str();
}
auto main() -> int {
gpsmm gps_rec("localhost", DEFAULT_GPSD_PORT);
if (gps_rec.stream(WATCH_ENABLE | WATCH_JSON) == nullptr) {
std::cerr << "No GPSD running.\n";
return 1;
}
constexpr auto kWaitingTime{1000000}; // 1000000 is 1 second
for (;;) {
if (!gps_rec.waiting(kWaitingTime)) {
continue;
}
struct gps_data_t* gpsd_data;
if ((gps_rec.read()) == nullptr) {
std::cerr << "GPSD read error.\n";
return 1;
}
while (((gpsd_data = gps_rec.read()) == nullptr) || (gpsd_data->fix.mode < MODE_2D)) {
// Do nothing until fix, block execution for 1 second (busy wait mitigation)
std::this_thread::sleep_for(std::chrono::seconds(1));
}
const auto latitude{gpsd_data->fix.latitude};
const auto longitude{gpsd_data->fix.longitude};
const auto hdop{gpsd_data->dop.hdop};
const auto vdop{gpsd_data->dop.vdop};
const auto pdop{gpsd_data->dop.pdop};
const auto s_vis{gpsd_data->satellites_visible};
const auto s_used{gpsd_data->satellites_used};
const auto time_str{TimespecToTimeStr(gpsd_data->fix.time, ISO_8601)}; // you can change the 2nd argument to LOCALTIME, UTC, UNIX or ISO8601
std::cout << std::setprecision(8) << std::fixed; // set output to fixed floating point, 8 decimal precision
std::cout << time_str << "," << latitude << "," << longitude << "," << hdop << "," << vdop << "," << pdop << "," << s_vis << "," << s_used << '\n';
}
}
@ncoder-1
Copy link
Author

ncoder-1 commented Mar 29, 2020

@garyv100, I've had a USB unit (u-blox driver) running for about 40 minutes and a raw UART (nmea driver) running for about 20 minutes and both aren't showing the drift (other than the normal cold boot drift which is quickly corrected as satellites are received). I suggest you post an issue here: https://gitlab.com/gpsd/gpsd/issues and the main gpsd dev (also named Gary) can maybe help if it's a driver issue with your hardware or within the gpsd code itself. I suggest you link this gist so he can get some context as well. Wish I could be of more help.

edit: are you seeing the same behavior with gpsd's cgps tool?

@garyv100
Copy link

garyv100 commented Mar 29, 2020

@ncoder-1, I am using VK-162 GPS Receiver Dongle Navigation Module USB Interface G-mouse Antenna DEN. I think this is the problem. Not the Linux drivers or software. Can you recommend a different receiver for Linux?
Thank you for your help.
Gary

@ncoder-1
Copy link
Author

@garyv100, I use a GR-8013 USB GPS (one of the rare USB ones that also have PPS) and also the ND-100S which both work well with gpsd.

@garyv100
Copy link

garyv100 commented Mar 29, 2020

@ncoder-1, I tried to lookup GR-8013 USB GPS, but I am coming up w/ all kind of stuff. If you could send me the link - it would be great.
Thanks,
Gary

@ncoder-1
Copy link
Author

@garyv100, they are quite rare now, but this is the one I have: https://www.globalsources.com/gsol/I/PC-PDA/p/sm/1147069913.htm#1147069913

@garyv100
Copy link

garyv100 commented Mar 29, 2020

@ncoder-1, Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment