Accuracy of an Android cell phone GPS in the UK

Even cheap smart phones in the UK now have GPS capability. The rapid expansion in spatially aware devices has been driven by the potential for commercial use of location data.  Location to nearest postcode is good enough for many of these purposes, but more accurate fixes are needed for Sat Nav. Contemporary phones therefore use a combination of network based methods and satellite GPS to obtain a fix. Accuracy, once a GPS fix has been obtained, is assumed to be within 10m.

Students carrying out field research projects could therefore potentially use their own mobile phones to log positions. However are phones suitable for scientific use? Do they provide reliable data? In order to be used for research is vitally important to have some measure of the reliability of positional information. How accurate are cell phone GPS fixes? How does accuracy vary?

I recently acquired two new, but low end Android phones (Hyundai Pulse Mini) for family use. These cost just thirty pounds (600 pesos) each, plus ten pounds phone credit. Almost unbelievably cheap. These phones are clearly bottom end devices. Nevertheless I have been pleasantly surprised by how useful they are.  They provide me with all the usual smart phone services I need, including perfectly acceptable Sat Nav and  good general mapping capability including the recording of apparently reliable track logs and waypoints in gpx format.  The Android operating system is very intuitive to use. The only real problem with the devices themselves is short battery life. But, could they be used for georeferencing research sites?

This was not an easy question to answer as I could find no detailed information online regarding the specifications of the GPS chipset that they contain. It is not even clear whether such phones use EGNOS (the European equivalent of WAAS). All cell phones have “enhanced GPS”, but this refers to the method used for improving the speed of the fix by using network signals in built up areas. EGPS does not improve accuracy as such. So the main issue for research applications is lack of knowledge regarding how precision may vary and what factors influence variability.

The android Market has a large number of useful GPS tools, including the default Google maps,a useful app called “GPS essentials” and the Locus app. A promising little tool for analysing positional error and correcting it is GPS averaging.This tool logs the position at regular intervals and calculates the mean position over a time period. If errors were random over time then the mean should provide a very accurate fix. I tested this by running the app for several ten minute periods.

The good news was that the overall accuracy of the GPS was always within 4 metres of the target. The bad news was that positional errors were correlated over relatively short time periods, so taking a mean did not increase accuracy by much, due to the overall bias over all the measurements.

First run. The mean distance from the known position was 3.28 metres.

Second run. The mean distance was 2.24 metres, but note that the bias has now shifted to the South East.


I tried this test several times over the space of a few days. The pattern was always similar. The GPS fixes tended to have a correlated bias over a period of up to an hour or more. Overall accuracy was always within 5m, but apart from removing the effect of odd extreme outlier, averaging did not improve the precision by much.  A more systematic study over a longer period would provide more quantitative details and even reveal patterns in the bias that may be associated with the satellite positions.

However, I had another idea. I have two very similar phones. It occurred to me that if the positional error turns out to be the same for both I could build my own differential GPS by connecting them using Blue Tooth and sending the position of one to the other. I couldn’t find a pre-built app for this so I tried out the Python scripting environment for Android. This can be downloaded and installed here.

I had never programmed in Python, so the code is very scrappy. However it was not difficult to adapt some of the code given in the example scripts in order to cobble together a very rough and ready proof of concept script.

It ran fine, but the results were  not as I expected. I found that each phone registered quite different positions when placed together (something I could in fact have easily tested before by taking a tracklog or using GPS averaging without  the need to write the Python script!). The error turned out to be as much as 6m, but tended to fall over time to around 50 cm over the space of twenty minutes under a clear sky. So the two phones could not really be used as a differential GPS, although the overall accuracy of either seems to be acceptable for many general types of field work that do not involve site surveying.

Anyway the Python code I came up with is provided below in case it is of use to anyone. The script can be downloaded by clicking here — differentialgps.py

There are some known issues with the code. If these were tackled it might be possible to improve the results I got. The most important defect was that the readLocation() method did not always return a result, so I used getLastKnownLocation() instead, in order to get the script working. This meant that the two fixes may not have been calculated at identical times. Even taking this into account the readings from the two phones had much larger differences than I expected. Another obvious issue with the general approach I used here is the limited range of blue tooth and the fact that I did not add any way of handling exceptions when the Bluetooth signal was lost.

The script must be placed on both phones and run in a console in SL4A. First run the script on one phone to make it a server then connect the second as a client. Close the server first for a clean exit. The results are written to two files on the client phone.

import android
import time
import math

droid = android.Android()
droid.startLocating()

fclient = open('GpsClientLog.txt', 'w')
fserver = open('GpsServerLog.txt', 'w')

droid.toggleBluetoothState(True)
droid.dialogCreateAlert('Be a server or client?')
droid.dialogSetPositiveButtonText('Server')
droid.dialogSetNegativeButtonText('Client')
droid.dialogShow()
result = droid.dialogGetResponse()
is_server = result.result['which'] == 'positive'
if is_server:
 droid.bluetoothMakeDiscoverable()
 droid.bluetoothAccept()
 timelapse = droid.getInput('GPS server', 'Enter number of seconds between readings').result
 while True:
  time.sleep(int(timelapse))
  event=droid.readLocation()
  location = droid.getLastKnownLocation().result
  if location['gps'] is not None:
   location = location['gps']
   method="gps"
  else:
   location = location['network']
   method="network"
  lat=location['latitude']
  lon=location['longitude']
  print method+','+str(lon)+','+str(lat)
  fserver.write(str(lon)+','+str(lat)+'\n')
  droid.bluetoothWrite(method+','+str(lon) +','+str(lat)+ '\n')
 fserver.close()

else:
 droid.toggleBluetoothState(True)
 droid.bluetoothConnect()
 while True:
  ServerPosition = droid.bluetoothReadLine().result
  print ServerPosition
  event=droid.readLocation()
  location = droid.getLastKnownLocation().result
  if location['gps'] is not None:
   location = location['gps']
   method="gps"
  else:
   location = location['network']
   method="network"
  lat=location['latitude']
  lon=location['longitude']
  slon=float(ServerPosition.split(',')[1])
  slat=float(ServerPosition.split(',')[2])
  dist=round(math.sqrt(math.pow((slon-lon)*69930,2)+math.pow((slat-lat)*111122,2)),2)
  print "Approximate distance="+str(dist)+"metres"
  print method+','+str(lon)+','+str(lat)
  fclient.write(time.asctime()+','+method+','+str(lon)+','+str(lat)+'\n')
  fserver.write(time.asctime()+','+ServerPosition+'\n')
 fserver.close()
 fclient.close()

7 thoughts on “Accuracy of an Android cell phone GPS in the UK

  1. Brilliant! Kudos to you sir! I’ve been trawling for inoframtion on accuracy and you are top of the GPS pops! Wikipedia covers all history on this popular topic, but doesnt get to the point… How accurate is it!

    Thank you so much for the effort and saving me hours doing research.

  2. If I am reading this right, your code is comparing the locations calculated by two roving recievers. Even if one of them is stationary, it’s not doing “differential correction”. It’s just seeing if the two GPS receivers get the same error. You would need one of the recievers to be a base station with a known or well established location. This is usually done by having a reciever “sit” on a spot for an hour or more…. Am I reading this right?

    • Well yes, at some point you would of course need to establish an accurate fix for the “base station”. What I was testing was whether I could get very accurate differences between the two receivers. If I could do that, then it would be possible to map an area very precisely with respect to any known reference point. Unfortunately it didn’t work quite as I expected as the two cellphones did not report the same error at the same time. This could be down to the way I got the gps fix from the phone using the api, but I think the problem is at source. It might work with more expensive phones.
      Also, I found that leaving the reciever for an hour doesn’t get a very accurate fix. This is because the errors are temporally autocorrelated, rather than being independent. So you need to take the mean over a much longer period in order to allow the random walk to move around the true centre.

  3. Very interesting, Plenty of ideas to improve my accuracy.

    Currently recording data with osmtracker on a google nexus 4.
    I seem to be getting better accuracy than might be expected, currently 2-3m. This is fine for me as I’m plotting road drainage features. The software is worth a try as it’s customisable, quick and outputs gpx files.

    Keep up the good work, much appreciated

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s