mysqlfloating-pointgpslocationgeo

Why is the GPS reporting insane longitude numbers?


I have taken responsibility of maintaining and developing an app that is heavily dependent on tracking the user's driving route using the GPS in their smartphone device.

The Issue

The issue is the GPS coordinate is inaccurate (to a bizarre degree). I'm not talking about couple hundred meters, I'm talking like thousands of meters. My client is in New Zealand, and the GPS coordinate is a location in the middle of the ocean, west of Australia.

Here is an sample of the recorded bad data from my client that the phones are recording:

Sample of bad data

As you can see, it appears that the latitude values appear to be correct, or sane enough. But the longitude values are all fixed at 100, which is not sane at all.

The Technology

The app is built using cordova-android 5.22, and cordova-ios 4.2.1, however we are seeing the same issue with the older version of our app that is using Appcelerator's titanium framework (again only with New Zealand clients), so I don't believe this issue is specific to cordova or titanium. We are also unable to reproduce the issue (development team is located in Canada).

Unfortunately, at this time I do not know whether the client is using Android or iOS, or what version of the OS they are using. I'll update the question as soon as that information becomes available to me.

The application does not do anything with the latitude/longitude values other than read them and write to a log file, which gets uploaded to our server and the data is read and stored to a MySQL database, using a FLOAT length 16,14

The Code The Cordova App:

geoWatchId = navigator.geolocation.watchPosition(logGeoItem, loggingFailure, {enableHighAccuracy: true});

...

function logGeoItem(geoPoint){
if(loggingState.isLogging){
    console.log(JSON.stringify(geoPoint));
    var newLogItem = {latitude: geoPoint.coords.latitude, longitude: geoPoint.coords.longitude, heading: geoPoint.coords.heading, altitude: geoPoint.coords.altitude, created_datetime: Date.now()};
    loggingState.currentGeoLoggingData.push(newLogItem);
}

}

Yes, the watchPosition code is wrapped inside a deviceready event.

NodeJS GPS data storing in MySQL DB

for(var j=0; j<data.location.length; j++) {
    var sqlLocation = "INSERT INTO location (session_id, heading, altitude, latitude, longitude, created_datetime) VALUES";
    sqlLocation += "('" + data.location[j].session_id + "','" + data.location[j].heading + "','" + data.location[j].altitude + "','" + data.location[j].latitude + "','" + data.location[j].longitude + "','" + data.location[j].created_datetime + "');";
    connection.query(sqlLocation, function(err, result){
      log.info(err);
      log.info(result);
      if(err) {
        connection.rollback(function(){
          callback({ result: 'error', errorMsg: constants.errors.ERROR_UPLOAD_LOCATION_DATA });
        });
      }
    });
  }

The Research

I've crawled through the net and found several different articles and stack overflow post describing inaccurate GPS positions, but these describe where the GPS is still is potentinally sane.

The issue on hand is that the longitude value is completely insane, and the longitude value appears to be consistently at 100.

I haven't found anything that indicates why longitude is so far out of whack, and why it is consistently 100. If my issue was actually simply inaccuracy readings, I'd expect for a variety of longitude values, not a constant 100.

Can anyone provide me with suggestions on how to proceed with debugging? Why would only the longitude be fixed at 100?


Solution

  • The issue is the longitude value is actually exceeding the maximum allowed digits set in MySQL.

    FLOAT (16,14)

    Means that you can have a maximum of 16 digits, 14 of which belong to digits after the decimal point.

    Parts of New Zealand could potentially have longitude value >= 100. For example, Whangarei Northland, New Zealand is: -35.725043, 174.319490

    Because 174.319490 is a number that breaks the 16/14 rule (even if the number itself doesn't contain 14 digits after the decimal point), it appears to be capping out at 100 and zero-filling.

    If I alter the table to be type FLOAT (17,14) allowing a third digit before the decimal point, the data is stored properly.

    Tested on MySQL 5.6.21