Raspberry Pi[56] gpsdライブラリを使ってC言語で緯度・経度を取得

前に作ったGPSデータを取得するプログラムはUSBでNMEAをシリアルで受信して解析するものでした。しかし、GPSの時刻同期で使用した gpsd からNMEAのデータを取得することができるようなので、gpsd から取得してみました。gpsdから取得すると GPS受信機が一つで、時刻同期したり緯度経度取得したりすることができます。また、必要な情報は構造体で取得できるので、変換を自分ですることも必要なくなります。

gpsd の立ち上げはGPSに時刻同期ブログを見てください。

【目的】

Raspberry Pi上で gpsd ライブラリを使い、C言語でリアルタイムに緯度・経度・速度を取得するプログラムを作成。


✅ ステップ1:gpsd開発ライブラリの確認・導入

bashコピーする編集するsudo apt install libgps-dev gpsd gpsd-clients

✅ ステップ2:基本的なCのコードを作成

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

int main() {
    struct gps_data_t gps_data;

    if (gps_open("localhost", "2947", &gps_data) != 0) {
        fprintf(stderr, "Error: gps_open failed\n");
        return 1;
    }

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

    while (1) {
        if (gps_waiting(&gps_data, 5000000)) {
            if (gps_read(&gps_data, NULL, 0) == -1) {
                fprintf(stderr, "Error: gps_read failed\n");
            } else {
                if (gps_data.fix.mode >= MODE_2D && isnan(gps_data.fix.latitude) == 0) {
                    printf("Lat: %.8f, Lon: %.8f, Speed: %.2f km/h\n",
                        gps_data.fix.latitude,
                        gps_data.fix.longitude,
                        gps_data.fix.speed * 3.6);
                } else {
                    printf("Waiting for fix...\n");
                }
            }
        }
        sleep(1);
    }

    gps_stream(&gps_data, WATCH_DISABLE, NULL);
    gps_close(&gps_data);
    return 0;
}

✅ ステップ3:ビルド

bashコピーする編集するgcc gps_read.c -o gps_read -lgps -lm

✅ ステップ4:実行時の注意点と解決法

  • 最初 gps_read()too few arguments エラー → libgps v3.22では gps_read() は3引数必要(char *message, int len
gps_read(&gps_data, NULL, 0);

✅ ステップ5:gps_data.fix の内容確認

  • gps_data.fix.latitude, longitude, speed は全て double(単位:度、m/s)
  • 緯度経度はすでに変換済みの10進度表記 → 自分でNMEAの度分から変換する必要はなし

✅ ステップ6:Fixされない時の条件

  • gps_data.fix.mode < MODE_2D の場合、まだ位置取得中(No Fix)
  • シミュレーションNMEAでも、GGA の fix が 1 以上(例:4)であれば MODE_3D に達する

✅ ステップ7:ボーレート自動設定のための override.conf

[Service]
ExecStartPre=/usr/bin/stty -F /dev/ttyUSB0 115200

/etc/systemd/system/gpsd.service.d/override.conf に保存し、
systemctl daemon-reexecdaemon-reloadrestart gpsd で反映

ボーレートが変わったかを確かめるには。

sudo systemctl stop gpsd
stty -F /dev/ttyUSB0