An update to xkcd’s cyborg.txt

Back in 2008, Randall Munroe wrote a Python script that used a GPS device to generate point-to-point directions (in the form “three o’clock, target distance 2 kilometres”). This is something that interests me greatly, as it is very useful to get around when walking or cycling. He made the code available on his website, along with a blog post¬†about it.

However, a recent change to how “gpspipe -w” works has stopped the code working on versions of gpsd newer than around 2012. The output seems to now be JSON-based:

Old output:
GPSD,Y=GSV 1159566529.000 9:19 77 228 0 0:1 11 159 0 0:3 50 166 0 0:22 53 63
39 1:18 16 49 22 1:11 30 279 0 0
GPSD,O=GGA 1159566530.000 0.005 50.047378 14.443647 300.70 ?
? ? ? 0.0
GPSD,O=RMC 1159566530.000 0.005 50.047378 14.443647 300.70 15.20 ?
0.0000 0.000 0.000
GPSD,O=GSA 1159566530.000 0.005 50.047378 14.443647 300.70 15.20 21.60
0.0000 0.000 0.000
GPSD,Y=GSV 1159566530.000 9:19 77 228 0 0:1 11 159 0 0:3 50 166 0 0:22 53 63
46 1:18 16 49 21 1:11 30 279 0 0
New output:
{“class”:”TPV”,”device”:”/dev/pts/1″, “time”:”2005-06-08T10:34:48.283Z”,”ept”:0.005, “lat”:46.498293369,”lon”:7.567411672,”alt”:1343.127, “eph”:36.000,”epv”:32.321, “track”:10.3788,”speed”:0.091,”climb”:-0.085,”mode”:3}

So my first instinct was to rewrite the parsing code in Randall’s code (lines 307-326) to work with the new JSON output of gpspipe -w. But I thought a more future-proof way would be to rewrite it to use gpspipe -r, which outputs NMEA data. The NMEA data is unlikely to be changed in the way gpspipe -w was, which makes the code more future-proof.

After finding that a Python library existed for parsing NMEA, writing the replacement parsing code for cyborg.txt is easy. Below are the parts of the code that I changed:

print "Waiting for GPS data ..."
while(1):
line=sys.stdin.readline()
if not line:
exit()
if '$GPGGA' not in line:
continue
nmeaMessage = pynmea2.parse(line, check=False)
nmeaList = line.split(',')
readtime=float(nmeaList[1])
y=float(nmeaMessage.latitude)
x=float(nmeaMessage.longitude)

The rest of the code uses 3 variables from the GPS, y (latitude), x (longitude), and readtime (A time string in the form HHMMSS.) These were easy to get from the data provided by the Python library. My modifications mean that cyborg.txt should now run on any modern Linux system.

You can download my updated code here. It requires gpsd, gpsd-clients, figlet, flite, and pynmea2 (install using pip install pynmea2). Please send bug reports to jamesl.

As the program now uses gpsd -r, it would be started with “gpspipe -r | python cyborg.py (latitude) (longitude)”

Here is a screenshot of the program running on my computer. Screenshot of cyborg.txt running, showing target distance and direction.

Leave a Reply

Your email address will not be published. Required fields are marked *