Seit circa einem Monat versuche ich regelmäßig laufen zu gehen, sprich ungefähr alle 2-3 Tage, einerseits um mir fehlende Endorphine zu holen die mir zeit meiner letzten Zigarette fehlen, aber auch um zu sehen um wieviel ich mich steigern kann wenn ich nicht rauche. Es ist für mich also Überlebenshilfe und Motivation in einem. Um zu sehen um wieviel ich mich verbessere brauche ich aber Daten, am Besten wäre natürlich Lungenvolumen, Puls, Geschwindigkeit, Atmungsregelmäßigkeit, etc. Allerdings übersteigt das etwas meine Mittel also muss der GPS-Empfänger auf meinem Android Smartphone reichen.
Auf meinen heutigen Lauf bin ich zugegeben etwas Stolz, heute hab ich zum ersten Mal die 10km/h Durchschnittsgeschwindigkeit gebrochen.
20100826 Atzgersdorf-Schwarzenhaidestraße auf einer größeren Karte anzeigen
Als Informatiker gebe ich mich allerdings nicht damit zufrieden meine Tracks mitzuschneiden und sie mir nachher auf Karten anzusehen, die meiste Zeit laufe ich sowieso dieselbe Strecke! Interessant wäre Geschwindigkeitsprofil, Gesamtlaufzeit, Gesamtstrecke, Zeit die ich für einen Kilometer brauche, etc.
Ich habe also wieder ein bisschen mit Ruby herumgespielt und versuche nun aussagekräftige Daten zu bekommen, im Idealfall würde ich zum Jahresabschluss gerne ein Motivationsbuch mit Latex schaffen wo jeder Lauf enthalten ist.
Zu Beginn wird mal ein Blick in ein GPX File reingeworfen:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="details.xsl"?>
<gpx
version="1.0"
creator="My Tracks for the G1 running Android"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.topografix.com/GPX/1/0"
xmlns:topografix="http://www.topografix.com/GPX/Private/TopoGrafix/0/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd">
<trk>
<name><![CDATA[Atzgersdorf-Schwarzenhaidestraße]]></name>
<desc><![CDATA[Gemütlich. Nicht außer Atem]]></desc>
<number>4</number>
<topografix:color>c0c0c0</topografix:color>
<trkseg>
<trkpt lat="48.145564" lon="16.294216">
<ele>236.6999969482422</ele>
<time>2010-07-23T16:14:23Z</time>
</trkpt>,
<trkpt lat="48.1456" lon="16.29428">
<ele>245.60000610351563</ele>
<time>2010-07-23T16:14:24Z</time>
</trkpt>
<trkpt lat="48.145566" lon="16.294354">
<ele>250.0</ele>
<time>2010-07-23T16:14:25Z</time>
</trkpt>
Das kann ja meine Oma parsen!
Öffnen einen GPX Files und Ausgabe von Name und Beschreibung mit ein bisschen Ruby-Liebe:
require ‘rexml/document’
file = File.open("track1.gpx","r")
doc = REXML::Document.new(file)
doc.elements.each(‘gpx/trk’) { |track|
puts track.elements["name"].text
puts track.elements["desc"].text
}
Wenn man durch alle Trackpoints iterieren will (wird notwendig sein um Streckenlänge und Geschwindigkeit zu berechnen):
doc.elements.each(‘gpx/trk/trkseg/trkpt’) { |point|
currLat = point.attributes["lat"].to_f #breitengrad
currLon = point.attributes["lon"].to_f #laengengrad
currTime = Time.parse(point.elements["time"].text) #zeitpunkt
currElevation = point.elements["ele"].text.to_i #hoehe
}
So, spätestens jetzt haben auch die unaufmerksamen Leser bemerkt das die Daten die man bekommt relativ unhandlich sind für so simple Fragen wie “Wie weit bin ich gelaufen?”. Da wir nur Breiten- und Längengrade zur Verfügung haben muss man für eine Auswertung ein bisschen in der Mathematik-Kiste graben. Da wünscht man sich ja glatt das die Erde eine Scheibe wäre, oder zumindestens rund! Nein, sie muss ja ein rotationssymetrisches Ellipsoid sein 
Naja, nach ein wenig googlen hab ich eine Formel gefunden mit der man den Abstand zwischen zwei Koordinationpuntken berechnen kann (tut mir ehrlich leid ich finde die Quelle nicht mehr):
def haversine_distance
(lat1, lon1, lat2, lon2
)
earthRadius =
6371
radPerDegree =
Math::PI/
180
deltaLatRad =
(lat2 – lat1
) * radPerDegree
deltaLonRad =
(lon2 – lon1
) * radPerDegree
lat1Rad = lat1 * radPerDegree
lat2Rad = lat2 * radPerDegree
lon1Rad = lon1 * radPerDegree
lon2Rad = lon2 * radPerDegree
a = (Math.sin(deltaLatRad/2))**2 + Math.cos(lat1Rad) * Math.cos(lat2Rad) * (Math.sin(deltaLonRad/2))**2
c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a))
return c * earthRadius * 1000
end
Damit konnte ich jetzt schon Daten aus den GPX Files extrahieren, ich habe auch schon versucht das Höhen- und Geschwindigkeitsprofile zu plotten, allerdings ist dabei noch nichts schönes rausgekommen.
Für die Numeriker unter uns hab ich auch ein kleines XSL File das so nebenbei entstanden ist, das macht das GPX File vielleicht ein bisschen lesbarer.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:gpx="http://www.topografix.com/GPX/1/0">
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="gpx:gpx/gpx:trk/gpx:name"/></title>
</head>
<body>
<h1><xsl:value-of select="gpx:gpx/gpx:trk/gpx:name"/></h1>
<p><xsl:value-of select="gpx:gpx/gpx:trk/gpx:desc"/></p>
<table>
<tr>
<th>Longitude</th>
<th>Latitude</th>
<th>Elevation</th>
<th>Time</th>
</tr>
<xsl:for-each select="gpx:gpx/gpx:trk/gpx:trkseg/gpx:trkpt">
<tr>
<td><xsl:value-of select="@lon"/></td>
<td><xsl:value-of select="@lat"/></td>
<td><xsl:value-of select="gpx:ele"/></td>
<td><xsl:value-of select="gpx:time"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Tags: data, gps, gpx, map, ruby, run