This commit to gpxpy library includes additional parsing for Garmin 1.1 extensions. However it appears the code has changed a lot since this commit and it appears that extensions are parsed automatically now.
However I've been unable to figure out how to extract heart rate data or other extension data from a gpx file using gpxpy. Has anyone done this with gpxpy? How is it done?
Edit to avoid closing this question:
If you look at the code additions in the commit I linked above, it modifies the TrackPoint class to add "atemp" and "hr"
class GPXTrackPoint(mod_geo.Location):
def __init__(self, latitude, longitude, elevation=None, time=None, symbol=None, comment=None,
horizontal_dilution=None, vertical_dilution=None, position_dilution=None, speed=None,
name=None, atemp = None, hr = None):
Then later in the parser.py you see this routine added
def __parse_track_point_extension(self, node):
+ atemp_node = self.xml_parser.get_first_child(node, 'atemp')
+ atemp = mod_utils.to_number(self.xml_parser.get_node_data(atemp_node))
+
+ hr_node = self.xml_parser.get_first_child(node, 'hr')
+ hr = mod_utils.to_number(self.xml_parser.get_node_data(hr_node))
+ extensions = {"atemp":atemp, "hr":hr}
+ return extensions
However in the current code the structure appears very different from when that original commit was made, but it seems to allow for parsing extensions in a more generic way. But I'm not proficient enough with python to understand how to get it to parse these tags. My question is an attempt to understand what I'm missing in how the new code works. My instinct is to just add a line like this into the gpx.py code around line 74.
mod_gpxfield.GPXField('heart_rate', 'hr', type=mod_gpxfield.FLOAT_TYPE),
However I'm hoping someone experienced can look through the code and see if there's something I'm missing like specifying a list extensions=[hr, atemp] and have them parsed generically when reading the data. It seems odd that this commit was made in the past, but now the feature has been lost, so I assume I'm missing something.
The portion of the heart rate xml look like this inside the trkpt as compared to their test schema
<trkpt lat="1.6685718186199665069580078125" lon="-101.03414486162364482879638671875">
<time>2018-02-10T19:24:06.000Z</time>
<extensions>
<ns3:TrackPointExtension>
<ns3:hr>106</ns3:hr>
</ns3:TrackPointExtension>
</extensions>
</trkpt>
And in their test.py you can see them testing their test extensions in their gpx test file:
<trkpt lat="10.1" lon="-20.2">
<ele>11.1</ele>
<time>2013-01-01T12:00:04</time>
<extensions>
<last>true</last>
</extensions>
Which is testing for the tag:
self.assertEquals('true',gpx.tracks[0].segments[0].points[0].extensions['last'])
And while I don't understand how it was parsed does this mean doing something like this:
hr=gpx.tracks[0].segments[0].points[0].extensions['hr']
Would return the data? Using python debugger, I can't see these loaded into the gpx.tracks data structure.
It appears that if any of the extended extensions in the DOM that are complex, the child nodes do not get parsed.
This is a long standing issue apparently with the code: https://github.com/tkrajina/gpxpy/issues/73
Edit: Here's a practical example, but it depends a bit on your structure.
heart_rate = gpx.tracks[0].segments[0].points[0].extensions[0]['hr']