summaryrefslogtreecommitdiff
path: root/gpsd_json.c
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2010-03-27 10:52:17 -0400
committerEric S. Raymond <esr@thyrsus.com>2010-03-27 10:52:17 -0400
commit8fe2f3ee9778f40f7e4e94934118240d5bcca5a2 (patch)
treeaaf8daaa4a4e743725a6670584cdc6e609896b30 /gpsd_json.c
parenta01d14fab52678a7a42d8640a510a3bf34c1d03a (diff)
downloadgpsd-8fe2f3ee9778f40f7e4e94934118240d5bcca5a2.tar.gz
Suppress JSON reporting of fields the fix quality won't support.
This should suppress a bug reported by Greg Troxel where, due to numeric instability in geodetic fix computations, wecwere getting cross-archirecture differences in the low-order digits of altitude for invalid fixes on SiRF-II chips. This required that ten regression test be rebuilt; I eyeballed the diffs to make sure we didn't lose actual data.
Diffstat (limited to 'gpsd_json.c')
-rw-r--r--gpsd_json.c128
1 files changed, 70 insertions, 58 deletions
diff --git a/gpsd_json.c b/gpsd_json.c
index 2fdaa591..81407ada 100644
--- a/gpsd_json.c
+++ b/gpsd_json.c
@@ -125,64 +125,76 @@ void json_tpv_dump(const struct gps_data_t *gpsdata,
replylen-strlen(reply),
"\"ept\":%.3f,",
gpsdata->fix.ept);
- if (isnan(gpsdata->fix.latitude)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"lat\":%.9f,",
- gpsdata->fix.latitude);
- if (isnan(gpsdata->fix.longitude)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"lon\":%.9f,",
- gpsdata->fix.longitude);
- if (isnan(gpsdata->fix.altitude)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"alt\":%.3f,",
- gpsdata->fix.altitude);
- if (isnan(gpsdata->fix.epx)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"epx\":%.3f,",
- gpsdata->fix.epx);
- if (isnan(gpsdata->fix.epy)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"epy\":%.3f,",
- gpsdata->fix.epy);
- if (isnan(gpsdata->fix.epv)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"epv\":%.3f,",
- gpsdata->fix.epv);
- if (isnan(gpsdata->fix.track)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"track\":%.4f,",
- gpsdata->fix.track);
- if (isnan(gpsdata->fix.speed)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"speed\":%.3f,",
- gpsdata->fix.speed);
- if (isnan(gpsdata->fix.climb)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"climb\":%.3f,",
- gpsdata->fix.climb);
- if (isnan(gpsdata->fix.epd)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"epd\":%.4f,",
- gpsdata->fix.epd);
- if (isnan(gpsdata->fix.eps)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"eps\":%.2f,", gpsdata->fix.eps);
- if (isnan(gpsdata->fix.epc)==0)
- (void)snprintf(reply+strlen(reply),
- replylen-strlen(reply),
- "\"epc\":%.2f,", gpsdata->fix.epc);
+ /*
+ * Suppressing TPV fields that would be invalid because the fix
+ * quality doesn't support them is nice for cutting down on the
+ * volume of meaningless output, but the real reason to do it is
+ * that we've observed that geodetic fix computation is unstable
+ * in a way that tends to change low-order digits in invalid
+ * fixes. Dumping these tends to cause cross-architecture failures
+ * in the regression tests. Rgus effect has been seen on SiRF-II
+ * chips, which are quite common.
+ */
+ if (gpsdata->fix.mode >= MODE_2D) {
+ if (isnan(gpsdata->fix.latitude)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"lat\":%.9f,",
+ gpsdata->fix.latitude);
+ if (isnan(gpsdata->fix.longitude)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"lon\":%.9f,",
+ gpsdata->fix.longitude);
+ if (gpsdata->fix.mode >= MODE_3D && isnan(gpsdata->fix.altitude)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"alt\":%.3f,",
+ gpsdata->fix.altitude);
+ if (isnan(gpsdata->fix.epx)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"epx\":%.3f,",
+ gpsdata->fix.epx);
+ if (isnan(gpsdata->fix.epy)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"epy\":%.3f,",
+ gpsdata->fix.epy);
+ if ((gpsdata->fix.mode >= MODE_3D) && isnan(gpsdata->fix.epv)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"epv\":%.3f,",
+ gpsdata->fix.epv);
+ if (isnan(gpsdata->fix.track)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"track\":%.4f,",
+ gpsdata->fix.track);
+ if (isnan(gpsdata->fix.speed)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"speed\":%.3f,",
+ gpsdata->fix.speed);
+ if ((gpsdata->fix.mode >= MODE_3D) && isnan(gpsdata->fix.climb)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"climb\":%.3f,",
+ gpsdata->fix.climb);
+ if (isnan(gpsdata->fix.epd)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"epd\":%.4f,",
+ gpsdata->fix.epd);
+ if (isnan(gpsdata->fix.eps)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"eps\":%.2f,", gpsdata->fix.eps);
+ if ((gpsdata->fix.mode >= MODE_3D) && isnan(gpsdata->fix.epc)==0)
+ (void)snprintf(reply+strlen(reply),
+ replylen-strlen(reply),
+ "\"epc\":%.2f,", gpsdata->fix.epc);
+ }
(void)snprintf(reply+strlen(reply),
replylen-strlen(reply),
"\"mode\":%d,", gpsdata->fix.mode);