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-reexec
→ daemon-reload
→ restart gpsd
で反映
ボーレートが変わったかを確かめるには。
sudo systemctl stop gpsd
stty -F /dev/ttyUSB0