Permalink
Browse files

Added GPX converter, Bearing Tracker, minor changes to behaviour

  • Loading branch information...
1 parent 997cc5f commit 7faefc31c4a2448c8a343dd9b2878872fb3bf293 @toastwaffle toastwaffle committed May 2, 2012
Showing with 190 additions and 10 deletions.
  1. +17 −5 README.txt
  2. +110 −0 bearing_recorder.py
  3. +54 −0 conv2gpx.py
  4. +2 −0 get_output_files.sh
  5. +3 −1 gps_recorder.py
  6. +4 −2 sensor_recorder.py
  7. +0 −2 util.py
View
22 README.txt
@@ -6,7 +6,7 @@
Python!
-## Usage
+## Usage
To run the recorder, start gps_recorder.py on the Android phone using
SL4A. Instructions for this can be found on the SL4A site:
http://code.google.com/p/android-scripting/wiki/RemoteControl
@@ -15,15 +15,27 @@
the phone.
You can parse and plot the output using the utilty functions in
- data_viewer.py
+ data_viewer.py.
+
+ You can also use the conv2gpx script to convert the recorded
+ tracks to the commongly uses GPX (GPS Exchange) Format used by geotagging and
+ tracking software such as Google Earth. The script will load all the gps
+ recordings into one file, with one track per file, split into sub-tracks if no
+ data was captured for a short period.
To record the sensor data from the phone instead of GPS, use
sensor_recorder.py. This is a direct copy/pasta from gps_recorder.py,
written as a last minute hack to try to get high frequency data out of the
phone. It should work fine. See the blog post for more info.
-
-## Changelog
+ To record the apparent bearing from the device, use bearing_recorder.py. This
+ uses the accelerometer to determine which axis is vertical, and then works out
+ the apparent magnetic bearing. This may not be accurate. Bearings are measured
+ clockwise from the positive x-axis around the vertical axis, unless x is
+ vertical, in which case the bearings are made from the positive z-axis.
+
+
+## Changelog
v1.00: Initial release!
@@ -36,5 +48,5 @@
## License
- Copyright Topher Brown <topher200@gmail.com>, 2011. Released under the MIT
+ Copyright Topher Brown <topher200@gmail.com>, 2011. Released under the MIT
license.
View
110 bearing_recorder.py
@@ -0,0 +1,110 @@
+#!/usr/bin/python2.6
+from __future__ import with_statement
+from util import get_last_fileid
+import android
+import json
+import math
+
+VERTICAL_THRESHOLD = 9.2
+OUTPUT_FILENAME_TEMPLATE = 'bearing_output_{0}.json'
+
+def record():
+ # Start location messages
+ droid = android.Android()
+ droid.startSensingTimed(1, 1000)
+ droid.makeToast("Starting Bearing drill")
+
+ # Show a dialog box
+ droid.dialogCreateInput("Bearing Recorder running", "Add message to log")
+ droid.dialogSetPositiveButtonText("Log message")
+ droid.dialogSetNegativeButtonText("Exit")
+ droid.dialogShow()
+
+ out_filename = OUTPUT_FILENAME_TEMPLATE.format(get_last_fileid() + 1)
+ with open(out_filename, 'w') as out_file:
+ running = True
+ while running:
+ # Wait until we get an event
+ res = droid.eventWait(1000).result
+ if res == None:
+ print "SensorListener timeout"
+ elif res['name'] == "dialog":
+ # User used the dialog
+ if (res[u'data'][u'which'] == u'positive'):
+ droid.makeToast("Saving log message")
+ message = '# {0}'.format(res[u'data'][u'value'])
+ print message
+ out_file.write('{0}\n'.format(message))
+ droid.dialogShow()
+ else:
+ print "User requested exit"
+ running = False
+ elif res['name'] == 'sensors':
+ data = {}
+ data['time'] = res['data']['time']
+ xforce = float(res['data']['xforce'])
+ yforce = float(res['data']['yforce'])
+ zforce = float(res['data']['zforce'])
+ xmag = float(res['data']['xMag'])
+ ymag = float(res['data']['yMag'])
+ zmag = float(res['data']['zMag'])
+ if abs(xforce) > abs(yforce) and abs(xforce) > abs(zforce):
+ if xforce > VERTICAL_THRESHOLD:
+ angle = math.atan2(-(ymag),zmag)
+ if angle < 0:
+ angle = angle + (2 * math.pi)
+ bearing = int(math.degrees(angle))
+ data['bearing'] = bearing
+ elif xforce < -(VERTICAL_THRESHOLD):
+ angle = math.atan2(ymag,zmag)
+ if angle < 0:
+ angle = angle + (2 * math.pi)
+ bearing = int(math.degrees(angle))
+ data['bearing'] = bearing
+ elif xforce > 0:
+ data['bearing'] = None
+ else:
+ data['bearing'] = None
+ elif abs(yforce) > abs(xforce) and abs(yforce) > abs(zforce):
+ if yforce > VERTICAL_THRESHOLD:
+ angle = math.atan2(-(zmag),xmag)
+ if angle < 0:
+ angle = angle + (2 * math.pi)
+ bearing = int(math.degrees(angle))
+ data['bearing'] = bearing
+ elif yforce < -(VERTICAL_THRESHOLD):
+ angle = math.atan2(zmag,xmag)
+ if angle < 0:
+ angle = angle + (2 * math.pi)
+ data['bearing'] = int(math.degrees(angle))
+ elif yforce > 0:
+ data['bearing'] = None
+ else:
+ data['bearing'] = None
+ elif abs(zforce) > abs(yforce) and abs(zforce) > abs(xforce):
+ if zforce > VERTICAL_THRESHOLD:
+ angle = math.atan2(ymag,xmag)
+ if angle < 0:
+ angle = angle + (2 * math.pi)
+ data['bearing'] = int(math.degrees(angle))
+ elif zforce < -(VERTICAL_THRESHOLD):
+ angle = math.atan2(-(ymag),xmag)
+ if angle < 0:
+ angle = angle + (2 * math.pi)
+ data['bearing'] = int(math.degrees(angle))
+ elif zforce > 0:
+ data['bearing'] = None
+ else:
+ data['bearing'] = None
+ else:
+ data['bearing'] = None
+ print(data)
+ out_file.write(json.dumps(data) + '\n')
+
+
+ # Shutdown
+ droid.stopSensing()
+
+
+if __name__ == '__main__':
+ record()
View
54 conv2gpx.py
@@ -0,0 +1,54 @@
+import os
+from xml.dom import getDOMImplementation
+import json
+import time
+import re
+
+impl = getDOMImplementation()
+doc = impl.createDocument(None,'gpx',None)
+top_element = doc.documentElement
+top_element.setAttribute('version','1.0')
+top_element.setAttribute('creator','Android GPS Tracker')
+top_element.setAttribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance')
+top_element.setAttribute('xmlns','http://www.topografix.com/GPX/1/0')
+top_element.setAttribute('xsi:schemaLocation','http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd')
+
+OUTPUT_FILENAME_TEMPLATE = 'gps_output_{0}.json'
+
+for filename in os.listdir(os.getcwd()):
+ match = re.match(OUTPUT_FILENAME_TEMPLATE.format('(\d*)'), filename)
+ try:
+ id = int(match.group(1))
+ except AttributeError:
+ continue
+ track = doc.createElement('trk')
+ track.appendChild(doc.createElement('name')).appendChild(doc.createTextNode('Track {0}'.format(id)))
+ trackseg = doc.createElement('trkseg')
+ lasttime = 0
+ f = open(filename,'r')
+ for line in f:
+ try:
+ point = json.loads(line)
+ if ((int(point['time'])-lasttime) > 1000) and trackseg.hasChildNodes():
+ track.appendChild(trackseg)
+ trackseg = doc.createElement('trkseg')
+ lasttime = int(point['time'])
+ trackpoint = doc.createElement('trkpt')
+ trackpoint.setAttribute('latitude',str(point['latitude']))
+ trackpoint.setAttribute('longitude',str(point['longitude']))
+ trackpoint.appendChild(doc.createElement('time')).appendChild(doc.createTextNode(str(time.strftime('%Y-%m-%dT%H-%M-%S',time.gmtime(float(point['time'])/1000)))))
+ trackpoint.appendChild(doc.createElement('ele')).appendChild(doc.createTextNode(str(point['altitude'])))
+ trackpoint.appendChild(doc.createElement('speed')).appendChild(doc.createTextNode(str(point['speed'])))
+ trackpoint.appendChild(doc.createElement('pdop')).appendChild(doc.createTextNode(str(point['accuracy'])))
+ trackpoint.appendChild(doc.createElement('fix')).appendChild(doc.createTextNode('3d'))
+ trackseg.appendChild(trackpoint)
+ except ValueError:
+ print 'Invalid JSON: ' + line
+ continue
+ f.close()
+ track.appendChild(trackseg)
+ top_element.appendChild(track)
+
+f = open('gpstrack.gpx','w+')
+f.write(doc.toxml())
+f.close
View
2 get_output_files.sh
@@ -2,4 +2,6 @@
for i in $(seq 20); do
adb pull /sdcard/sl4a/gps_output_$i.json
+ adb pull /sdcard/sl4a/sensor_output_$i.json
+ adb pull /sdcard/sl4a/bearing_output_$i.json
done
View
4 gps_recorder.py
@@ -1,9 +1,11 @@
#!/usr/bin/python2.6
from __future__ import with_statement
-from util import OUTPUT_FILENAME_TEMPLATE, get_last_fileid
+from util import get_last_fileid
import android
import json
+OUTPUT_FILENAME_TEMPLATE = 'gps_output_{0}.json'
+
def record():
# Start location messages
droid = android.Android()
View
6 sensor_recorder.py
@@ -1,10 +1,12 @@
#!/usr/bin/python2.6
from __future__ import with_statement
-from util import OUTPUT_FILENAME_TEMPLATE, get_last_fileid
+from util import get_last_fileid
import android
import json
import time
+OUTPUT_FILENAME_TEMPLATE = 'sensor_output_{0}.json'
+
def record():
# Start location messages
droid = android.Android()
@@ -26,7 +28,7 @@ def record():
res = droid.eventWait(1000).result
print res
if res == None:
- print "LocationListener timeout"
+ print "SensorListener timeout"
elif res['name'] == "dialog":
# User saving a comment
if (res[u'data'][u'which'] == u'positive'):
View
2 util.py
@@ -2,8 +2,6 @@
import os
import re
-OUTPUT_FILENAME_TEMPLATE = 'gps_output_{0}.json'
-
def get_last_fileid():
last_id = 0
for filename in os.listdir(os.getcwd()):

0 comments on commit 7faefc3

Please sign in to comment.