Evan Savage

Persistent Location Tracking: Picking The Right Tool

In this post, I compare Google Latitude and InstaMapper, two popular services
for persistent location tracking. I walk through installation and data
extraction via API for each service, then provide some subjective first
impressions as to which one better suits my location-tracking needs.

Evaluating Tools #

As the ecosystem of self-tracking tools grows exponentially,
choosing the right tool is becoming an increasingly daunting task.
To add to the complexity of this decision, self-tracking tools are
highly personal.

How do I pick the best tool for me?

This question is far from monolithic:

Without a searchable database of self-tracking tools, these questions can be
difficult to answer. The main Quantified Self website includes a
Guide to Self-Tracking Tools, but their implementation is subject to
criticism:

In a report to RWJF, Project Director Alexandra C. Carmichael noted that the guide was more a catalog of tools than a useful manual for people wanting to choose and use these tools.

This is a point worth repeating. Simply listing tools is not enough; a
database of tools must answer these basic questions to be useful. A quick
search on the Guide for location-related tools
comes up short:

Why is MoodPanda listed? I suppose it must location-tag mood entries,
but that isn't made explicit in the description.
Momento makes a bit more sense, but it's primarily a journalling app.
Foursquare is definitely location-based, but anyone unfamiliar with
it must read its description closely to realize that it relies on
manual check-ins.

In lieu of a useful tool database, the only effective option is direct
evaluation. By investigating two popular location tracking tools, I'll
demonstrate how such an evaluation might be carried out.

The Tools #

Google Latitude #

Google Latitude bills itself primarily as a social location sharing service:

Social capacities aside, the Location History
functionality can be used as a persistent location-tracking tool.

InstaMapper #

I first heard of InstaMapper from
Ted Power's talk on geo-tracking. Unlike Google
Latitude, InstaMapper focuses more on personal tracking:

The Criteria #

My ideal location tracking tool is:

Both tools are Android-compatible, automatic, and persistent already,
which narrows down the list of criteria to evaluate.

Installation #

Google Latitude #

Enabling automatic location tracking on Android requires only a single
setting change:

InstaMapper #

I followed the Android installation directions here.
After you register for an InstaMapper account, you install
InstaMapper's GPS Tracker app:

Comparison #

Both tools are easily installed, but Google Latitude wins on simplicity. This
is unsurprising, as Google Latitude comes pre-installed.

Data Export #

Google Latitude #

To export data from the Location History dashboard, click on Export KML
under the calendar widget:

InstaMapper #

Head to the data page for your device:

Here's where this process gets weird. To export your data, you first have to
define a track:

Once the track is created, you can visit the Track Manager to
export your track data in a variety of formats:

Comparison #

This one goes to Google Latitude. Aside from the terrible UI flow,
InstaMapper has some other problems:

API Fetching #

Tailers and Streams #

Many real-time APIs provide REST endpoints for fetching
time-bounded chunks of data:

https://www.googleapis.com/latitude/v1/location?key=INSERT-YOUR-KEY&min-time=1111&max-time=2222&max-results=10

By keeping track of a since time to fetch after, we can easily turn this
into a stream:

def request(since):
# TODO: actually fetch data
pass

def sleep(since, freq):
elapsed = time.time() - since
wait = freq - elapsed
if wait < 0:
return
time.sleep(wait)

def poll(freq):
since = time.time()
while True:
sleep(since, freq)
locations = request(since)
if not locations:
continue
doSomething(locations)
since = locations[-1].timestamp

This pattern is often referred to as a tailer. Why? Suppose we have a simple
implementation of doSomething():

def doSomething(locations):
for location in locations:
print location

This prints out locations as they are received, similar to UNIX tail -F. By
adjusting freq I can make different real-time guarantees, although at some
point the upstream API will start throttling my requests.

Google Latitude #

You can see a working tailer implementation here.

To access the Google Latitude API, you first need to
register an application. This gives you the necessary
parameters YOUR_KEY, YOUR_SECRET for stepping through the OAuth flow.

With the Python library oauthclient2, retrieving OAuth credentials is
relatively painless:

from oauth2client.client import OAuth2WebServerFlow
from oauth2client.file import Storage
from oauth2client.tools import run

def getCredentials(key, secret):
flow = OAuth2WebServerFlow(
client_id=key,
client_secret=secret,
scope='https://www.googleapis.com/auth/latitude.all.best',
redirect_uri='http://localhost:8080/oauth2callback'
)
storage = Storage('.creds')
return run(flow, storage)

oauth2client.tools.run() invokes a browser window and starts an HTTP server
to receive the OAuth callback. With the credentials, we can make a signed API
request:

import httplib2
import urllib
import json

def request(self, since):
http = httplib2.Http()
credentials = getCredentials(YOUR_KEY, YOUR_SECRET)
credentials.authorize(http)
url = 'https://www.googleapis.com/latitude/v1/location?%s' % urllib.urlencode({
'max-results': 10,
'min-time': since,
'max-time': since + 10 * (15 * 1000),
'granularity': 'best'
})
resp, content = http.request(url)
data = json.loads(content)
if data.get('error') is not None:
return None
return data['data'].get('items', [])

There are some minor details:

InstaMapper #

You can see a working tailer implementation here.

InstaMapper doesn't use OAuth; instead, it uses a unique key
YOUR_KEY that is passed as a GET parameter to the REST API:

import httplib
import json
import urllib

def request(self, since):
params = {
'action': 'getPositions',
'key': YOUR_KEY,
'num': 10,
'from_ts': since,
'format': 'json',
}
url = 'http://www.instamapper.com/api?{1}'.format(APIHOST, urllib.urlencode(params))
conn = httplib.HTTPConnection('www.instamapper.com')
conn.request('GET', url)
resp = conn.getresponse()
if resp.status != 200:
raise Exception('HTTP {0} {1}'.format(resp.status, resp.reason))
data = json.loads(resp.read())
conn.close()
return data['positions']

Comparison #

Although InstaMapper's API is arguably simpler to use, I'll award this one to
Google Latitude:

Battery Usage #

To find out how battery-friendly the two Android apps are, I check the
Battery Manager:

Comparison #

Google Latitude wins this one as well. InstaMapper keeps the GPS radio
running almost constantly, whereas Google Latitude manages to sip radio
access. I'm guessing that it uses WiFi, cell towers, and other non-GPS sources
where possible.

Without these power consumption improvements, InstaMapper's GPS Tracker uses
an order of magnitude more energy
than Google Latitude. Ouch.

First Impressions #

After a day of persistent location tracking with both Google Latitude and
InstaMapper, Google Latitude wins hands-down. It's easy to install, it
provides simple and secure data access via oauth2client, and it preserves
battery life nicely.