.FIT and .TCX file formats.
The .FIT file format for the Garmin Edge 800 and 500 (and other models? I don't know) is binary, unlike the .TCX file format that earlier Garmin models (e.g. Edge 705) use: the .TCX files are readable XML, which although it is convenient to read and to parse, results in fairly large files which quickly fill up the Garmin's internal memory card. So I understand why they decided to switch to binary.
This week I downloaded and started using the .FIT SDK, which conveniently enough comes with source code and examples for C, C#, C++ and Java. I found the Java .FIT decode example very easy to expand upon, and in no time at all had an expanded example app which gives me various details about the few .FIT files I have at the moment (I haven't used the Edge 800 I recently bought all that much, yet).
Garmin Connect no longer suitable for me.
What made me decide to start working on my .FIT file parser is that I couldn't just use the following workaround to convert .FIT to .TCX files:
- Upload the .FIT file to Garmin Connect;
- Export the resulting Garmin Connect trip entry as a .TCX file; then
- Read the .TCX file into my Java app.
* The pauses had been stripped out by the file only having a single XML "Track" node under the "Activity" node. For a typical trip with various pauses, e.g. a red traffic lights, the .TCX "Activity" node will contain multiple "Track" nodes, where each "Track" node corresponds to a period of continuous movement, and then each "Track" node contains multiple "Trackpoint" nodes, which are the instantaneous position/altitude/timestamp measurements received by the GPS receiver from the satellites. The pauses are then the time difference between the last timestamp of a "Track" node and the first timestamp of the next "Track" node.
.FIT file fields.
Something else I noticed is that the GPS position data stored in the .FIT file is in WGS-84 "semicircle" units, in which a 180° arc is comprised of 2^31 (i.e. 2 to the power of 31) semicircles, so to convert between semicircles and decimal degrees requires the following:
- Code: Select all
degrees = semicircles * ( 180 / 2^31 )
semicircles = degrees * ( 2^31 / 180 )
I also found that some of the .FIT "records" (these are the data items corresponding to the XML "Trackpoint" nodes in the .TCX files) have the accumulated distance field and the lat/long fields set to null. For my example .FIT file (generated on one of my home --> work commutes), I had exactly 2 out of the total 4225* records that had this null position data, right at the point where I stopped the timer prior to entering the basement carpark, but about 1 minute before I held down the Reset button to save the trip. So this may have something to do with stopping the timer.
* The 4225 records corresponds to the number of seconds in the trip's moving time, roughly. For this trip, the moving time (as retrieved from the Activity summary) was 01:10:09, which is 4209 seconds. However, for each period of n seconds of continuous movement, you will have n+1 records/trackpoints, which I think explains why I have 4225 records instead of just 4209.
The .FIT file also has nothing corresponding to the XML "Track" node in a .TCX file. However, I did find that by retrieving the Lap start and finish times, you can work out what records/trackpoints belong to each Lap.
So it looks like my Java app will shortly have the capability to import .FIT files as well as .TCX files .
Hope you found this interesting, and if not: well, I can't help it, I'm a software geek and love it!