Agent Skills: gpsd Knowledge Patch

gpsd changes since training cutoff (latest: latest) — altHAE/altMSL, ECEF/NED fields, TOFF/PPS timing, gps_mainloop(), shared-memory API. Load before working with gpsd.

UncategorizedID: nevaberry/nevaberry-plugins/gpsd-knowledge-patch

Install this agent skill to your local

pnpm dlx add-skill https://github.com/Nevaberry/nevaberry-plugins/tree/HEAD/plugins/gpsd-knowledge-patch/skills/gpsd-knowledge-patch

Skill Files

Browse the full folder contents for gpsd-knowledge-patch.

Download Skill

Loading file tree…

plugins/gpsd-knowledge-patch/skills/gpsd-knowledge-patch/SKILL.md

Skill Metadata

Name
gpsd-knowledge-patch
Description
"gpsd changes since training cutoff (latest: latest) — altHAE/altMSL, ECEF/NED fields, TOFF/PPS timing, gps_mainloop(), shared-memory API. Load before working with gpsd."

gpsd Knowledge Patch

Covers gpsd JSON protocol fields, libgps C client API, and timing interfaces. Claude knows gpsd daemon basics, gpspipe, cgps, and JSON protocol fundamentals, but is unaware of the specific field semantics, deprecations, and API patterns below.

Index

| Topic | Reference | Key content | |---|---|---| | TPV message fields | references/tpv-message.md | altHAE/altMSL, status codes, ECEF/NED, float validity | | Timing & PPS | references/timing-pps.md | TOFF/PPS reports, sawtooth correction, NTP integration | | Client API (libgps) | references/client-api.md | gps_mainloop(), shared-memory interface, usage patterns |


Essential Quick Reference

ECEF and NED Velocity/Position Fields

TPV can include ECEF (Earth-Centered, Earth-Fixed) coordinates and NED (North-East-Down) components:

{
  "class": "TPV",
  "ecefx": 3981234.56,
  "ecefy": 123456.78,
  "ecefz": 4966789.01,
  "ecefpAcc": 2.5,
  "ecefvx": 0.12,
  "ecefvy": -0.05,
  "ecefvz": 0.03,
  "ecefvAcc": 0.1,
  "velN": 0.12,
  "velE": -0.05,
  "velD": -0.03,
  "relN": 1.234,
  "relE": -0.567,
  "relD": 0.089
}

relN/relE/relD are RTK baseline vectors relative to a base station (meters). Only populated when the receiver reports RTK baseline data.

TPV Key Fields

| Field | Type | Unit | Description | |-------|------|------|-------------| | altHAE | float | meters | Height Above Ellipsoid (WGS84) — raw GPS altitude | | altMSL | float | meters | Mean Sea Level altitude — what maps show | | geoidSep | float | meters | Geoid separation: altHAE - altMSL | | status | int | — | Fix quality: 2=DGPS, 3=RTK Fixed, 4=RTK Float, 5=DR | | ecefx/y/z | float | meters | ECEF position from Earth center | | ecefpAcc | float | meters | ECEF 3D position accuracy | | velN/E/D | float | m/s | North/East/Down velocity components | | relN/E/D | float | meters | RTK baseline relative to base station |

Altitude — "alt" Is Deprecated

The alt field in TPV is deprecated and undefined. Always use altHAE or altMSL:

{
  "class": "TPV",
  "altHAE": 120.345,
  "altMSL": 85.678,
  "geoidSep": 34.667
}

altMSL is what most users want (matches map elevations). altHAE is the raw GPS measurement.

Float Validity — Use isfinite(), Not isnan()

Unknown/invalid floats in gpsd are NaN. Always check with isfinite():

// WRONG: misses infinity
if (!isnan(gpsdata->fix.speed)) { ... }

// CORRECT: catches NaN AND infinity
if (isfinite(gpsdata->fix.speed)) { ... }

TPV Status Field Values

The status field modifies mode (not a replacement). Values 0 (Unknown) and 1 (Normal) are omitted from JSON output — if absent, assume Normal:

| Value | Meaning | Accuracy | |-------|---------|----------| | 2 | DGPS | Sub-meter | | 3 | RTK Fixed | Centimeter | | 4 | RTK Floating | Decimeter | | 5 | DR | Dead Reckoning | | 6 | GNSSDR | GNSS + DR combined | | 7 | Time (surveyed) | Time-only mode | | 8 | Simulated | Test data | | 9 | P(Y) | Military code |


Timing — Enable TOFF/PPS

?WATCH={"enable":true,"json":true,"pps":true}

Both TOFF and PPS carry real_sec/real_nsec (GPS time) and clock_sec/clock_nsec (system time).

| Report | Source | Precision | Extra fields | |--------|--------|-----------|--------------| | TOFF | Serial data stream | ~1–10 ms | — | | PPS | Hardware 1PPS pulse | ~0.1–1 µs | precision, shm, qErr |

PPS qErr is the sawtooth correction in picoseconds — subtract from measured offset for higher accuracy.


Client API Patterns

gps_mainloop() — Simple Event Loop

int gps_mainloop(struct gps_data_t *gpsdata, int timeout,
                 void (*hook)(struct gps_data_t *gpsdata));

timeout is in microseconds. Returns -1 on timeout or error. Calls hook on each data arrival.

#include <gps.h>
#include <math.h>

void on_gps(struct gps_data_t *gpsdata) {
    if (gpsdata->fix.mode >= MODE_2D && isfinite(gpsdata->fix.latitude))
        printf("%.6f, %.6f\n", gpsdata->fix.latitude, gpsdata->fix.longitude);
}

int main(void) {
    struct gps_data_t gpsdata;
    gps_open("localhost", "2947", &gpsdata);
    gps_stream(&gpsdata, WATCH_ENABLE | WATCH_JSON, NULL);
    gps_mainloop(&gpsdata, 5000000, on_gps);  /* 5s timeout */
    gps_stream(&gpsdata, WATCH_DISABLE, NULL);
    gps_close(&gpsdata);
}

Shared-Memory Interface

Pass GPSD_SHARED_MEMORY as host for fast local-only access. Cannot use gps_stream(), gps_send(), gps_waiting(), or gps_data(). gps_read() always returns current snapshot; gps_fd is always -1.

struct gps_data_t gpsdata;
gps_open(GPSD_SHARED_MEMORY, NULL, &gpsdata);
if (gps_read(&gpsdata, NULL, 0) > 0) {
    if (isfinite(gpsdata.fix.latitude))
        printf("%.6f, %.6f\n", gpsdata.fix.latitude, gpsdata.fix.longitude);
}
gps_close(&gpsdata);

Use for: embedded systems, simple pollers, monitoring scripts (local only). Avoid when: you need streaming (gps_stream), device filtering, gps_waiting(), or remote access.

Shared Memory vs TCP Socket

| Feature | TCP Socket | Shared Memory | |---------|-----------|---------------| | gps_stream() | Yes | No | | gps_send() | Yes | No | | gps_waiting() | Yes | No | | Device filtering | Yes | No | | gps_read() behavior | Blocks for new data | Returns current snapshot | | gps_fd | Socket fd | Always -1 | | Remote access | Yes | No (local only) |

gpsd Knowledge Patch Skill | Agent Skills