跳转至

GNSS篇(四) - 整活你的定位模块(GPSD 使用)

本章节主要介绍GPSD 的使用,简单来说GPSD 是一个开源项目,适用于各种不同的GNSS模块创建的一个中间层服务,应用层可以方便的与GPSD服务进行交互获取相关的数据,更重要的意义来说统一了应用层调用接口,采用网络方式进行通信,采用统一的JSON 数据格式进行交互。当然在你的项目中,GPSD也不是非必须得服务,也可以不用这样,可以直接进行GNSS数据的分析到应用层。

1. 认识GPSD

GPSD 是一个开放源代码的守护进程,用于从 GPS 接收器收集位置信息,并将其标准化为应用程序可以轻松读取的格式。可以将数据标准化并通过 TCP/IP 套接字提供给多个客户端应用程序。它支持多种 GPS 硬件设备,并能够解析各种 NMEA 数据协议。

特点:

  • 支持多种设备:GPSD 支持许多不同的 GPS 接收器和其他 GNSS (全球导航卫星系统) 设备。
  • 标准化数据:GPSD 将来自不同 GPS 设备的原始数据标准化,以便客户端应用程序可以使用一致的 API 来访问位置信息。
  • 多客户端支持:多个客户端可以同时连接到 GPSD,并从同一 GPS 接收器接收位置信息。
  • 数据格式:GPSD 使用 JSON 格式传递数据,使得解析和使用数据变得简单。
  • 时间同步:GPSD 还可以用于高精度的时间同步,从 GPS 接收器获取时间信息来同步系统时钟。

应用场景:

  • 导航系统:GPSD 可以用于汽车导航系统,提供实时的位置信息和导航数据。
  • 地理信息系统 (GIS):在 GIS 应用中,GPSD 可以提供准确的位置信息用于地理数据的收集和分析。
  • 时间同步:一些系统需要高精度的时间同步,GPSD 可以从 GPS 信号中提取时间信息并同步系统时钟。
  • 移动应用:在移动设备或应用程序中使用 GPSD,可以实时获取设备的位置和移动轨迹。

总结来说这个一个开源统一管理各种GPS的工具,广泛应用于各种场景,不过目前是支持在Linux 系统下,如果放在其他系统下需要做一个修改。

2. 安装GPSD

以Ubuntu 为例子:

sudo apt-get install gpsd gpsd-clients

image-20240829210250753

启动服务,服务控制:

# 启动
sudo systemctl start gpsd

# restart
sudo systemctl restart gpsd

# 停止
sudo systemctl stop gpsd

# 查询状态
sudo systemctl satus gpsd

# 停止
sudo systemctl stop gpsd
sudo systemctl stop gpsd.socket

2.1 确定串口设备

确定哪个串口,查看数据:

sudo stty -F /dev/ttyUSB0 9600 cs8 -cstopb -parenb
sudo cat /dev/ttyUSB0

image-20240830102359685

2.2 配置GPSD

GPSD 主要配置文件/etc/default/gpsd/lib/systemd/system/gpsd.service

$ cat /etc/default/gpsd
# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES="/dev/ttyUSB0"

# Other options you want to pass to gpsd
GPSD_OPTIONS="-F /var/run/gpsd.sock"

# Automatically hot add/remove USB GPS devices via gpsdctl
USBAUTO="true"

配置完毕后GPSD需要重新启动一次服务;

其他命令

命令 说明
gpsd 最重要的 GPSD 服务守护进程。
gpsprof 一个为错误统计和设备超时产生报告的分析器。
gpsctl 一个调整设备设置的公共程序。
gpsdecode 一个把传感器日志批量转换成可读的 JSON 的程序。
gpsfake 一个能够连接任意数目的活动传感器日志的测试套件,可以重复运行有错误报告的传感器日志来重新产生特定的问题。
cgps 将 GPS 结果以图形化显示。
gpsmon 将 GPS 结果以图形化显示。

查看GPS数据

cgps

image-20240901162533627

gpsmon

image-20240901162730931

2. 应用程序接入

这里以C语言为demo, 创建gsp_app.c

先安装依赖相关:

sudo apt-get install libgps-dev libjansson-dev

2.1 代码编译运行

gps_app.c 代码demo

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

#define GPSD_HOST "localhost"
#define GPSD_PORT "2947"

void print_gps_data(struct gps_data_t *gps_data) {
    if (gps_data->fix.mode >= MODE_2D) {
        printf("Latitude: %f\n", gps_data->fix.latitude);
        printf("Longitude: %f\n", gps_data->fix.longitude);
        printf("Altitude: %f\n", gps_data->fix.altitude);

        // Time is stored as a struct timespec, so we need to check if tv_sec is non-zero
        if (gps_data->fix.time.tv_sec != 0) {
            printf("Time: %ld.%09ld\n",
                   gps_data->fix.time.tv_sec, gps_data->fix.time.tv_nsec);
        } else {
            printf("Time: N/A\n");
        }
    } else {
        printf("GPS data not available.\n");
    }
}

int main(void) {
    struct gps_data_t gps_data;
    char buf[256];
    int ret;

    // Initialize GPSD library
    if (gps_open(GPSD_HOST, GPSD_PORT, &gps_data) != 0) {
        fprintf(stderr, "Could not connect to GPSD\n");
        return 1;
    }

    // Configure GPSD to provide data
    gps_stream(&gps_data, WATCH_ENABLE, NULL);

    while (1) {
        // Read GPS data with appropriate arguments
        ret = gps_read(&gps_data, buf, sizeof(buf));
        if (ret == -1) {
            fprintf(stderr, "Error reading GPS data\n");
            break;
        }
        print_gps_data(&gps_data);
        sleep(1);  // Update interval
    }

    gps_stream(&gps_data, WATCH_DISABLE, NULL);
    gps_close(&gps_data);

    return 0;
}

image-20240901162432149

通过应用程序已经可以获取到经纬度,时间相关的信息。

3. 总结

通过GPSD 获取设备的GNSS 信息来说难度不大,通过GPSD 已经将GNSS 数据包协议已经解析,支持多用户获取实时的相关数据,对于不想去深究其中可以采用添加GPSD 服务的方式进行处理GNSS 数据,但是对于嵌入式设备,还需要涉及一个交叉编译的过程,对于交叉编译将后续进行展开。