OSM Tools

Tips for Creating a GPX file from ANT+/Wahoo FIT files & Strava Segments

Fit-Tools
Fit Converter showing all blocks & data
converting FIT to GPX & CSV
Showing min/max heart data

 

Reading a FIT file

The following should give you some understanding of the basic 'FIT protocols and structure'.

We assume that you are familiar with hex readers.

Yes, there are documents available which give a deeper understanding of the FIT structures but they are not written for beginners and the information is often hidden deep in a small file.

Header

We shall ignore the header for the time being; for our purpose it does not contain important information except the length of the data contained in the file.

0 x 0 length of header (&e)

0 x 4 size of data (4 bytes) , ie the block taken from &h0E

There are no pointers to specific fields in the header.

Let's begin

The structure is a series of definition blocks and data blocks, nothing else.

Data always follows a definition, not the other way around.

The definition block includes the size of the data block - if it didn't, we would have real difficulty knowing where the data block starts and where it begins!

Definition block with 6 bytes, always 6 bytes - we call this the 40 block

ANT+ FIT header

Highlighted in RED are the '40' blocks

Highlighted in Yellow are the Fields

Highlighted in GREEN : Data

Encircled in RED , number of fields

 

Example 40 00 01 00 00 4

The last of the 6 bytes tells you how many fields(sub headings) there are; in our case 4

(File Type ID is this number mod 16)

In our case the File TYP id=0

4D 00 01 etc is the start of File Type 13 (&d) etc

The 01 is the third byte of this block which tells how your data is stored, ie left to right or right to left (Little or Big Endian)

In fact, immediately after the header ,one of those 40blocks can be seen

Fields are always 3 bytes!

example : 01 02 84 , 02 04 86 , fd 04 86 , 00 01 00

middle byte

The middle byte tells you how many bytes are need,ie 2 , 4 , 4 , 1

last byte

The last byte tells you what type of variable you are dealing with, ie could it included negatives or it could be letters

02 23 07 (; 07 means string )

first byte

The first number refers to what is named the Field Definition Number, ie Speed, Latitude, Longitude, Temperature etc

However the meaning depends on 2 bytes in the 40 block - see below.

Fields are arranged numerically according to the first byte.

If the 40 block contains 14 (see below 40 00 01 00 14) ) then the numbers relate to Speed, Latitude, Longitude, Temperature

Data

Now we know that the next bytes contain data for each field.

In our case the length of the data block would be
11 (2 + 4 + 4 + 1)

The FIT file consists of a series of defining blocks for various File ID Types , ie 1 ,2 6,12 - some numbers are not known

When writing your FIT file you can just stick to File Type = 0 - but that's another chapter.

You can redefine the fields etc of a 0 File TYPE (40 )

This happens a lot ; you often see various 40 00 etc ; its an easy way of grouping different types of data , ie

We keep all the file id's as 0 (40, not 41 or 4D etc). Just make sure the last 40 block contains 14 - see below

Garmin FIT files

Garmin FIT files look very complicated, it being difficult to see a structure of any kind.

However, it just contains a series of blocks. Not all blocks have the same lengths.

So,when we read a FIT file, we just follow a block to its end, then check the next block type's length and parse that block until the next block

The principle is as follows.

Filetype Definition,Filetype Data,Filetype definition, Filetype Data

The start of Each Filetype definition for our purpose is in the range of 40 to 4F , 40 00 etc up to 4F 00 --

At the end of your data block , there may be another data block, not necessarily a new/revised Filetype Definition

Example

Define FTP 0x1 (41 00 etc) Total length: def-length1

Data 1 Total Length data-lenght1 as defined above

Data 1 Length data-lenght1

Data 1 Length data-lenght1

Define FTP 0x2 (42 00 etc) Total : def-length2

Data 2 data-lenght2

Data 1 data-lenght1

Define FTP 0x3 (43 00 etc) Total : def-length3

Data 2 data-lenght2 (just for the sake of showing that this in theory is possible)

Data 1 data-lenght1

Data 3 data-lenght3 (this doesn't have to follow the definition immediately but it makes sense not to have it here)

AND NOT

Define FTp 0x1 (41 00 etc) Total length def-length1

Data 1 Total Length data-lenght1 as defined above

Data 2 ( we have no idea how long this block is)

Coordinates

These are generally/always 4 bytes (0x84)

Coordinates are represented in various ways

Here are the main ones

00 04 85 Position Lat - Latitude requires 4 bytes
01 04 85 Position Long - Longitude requires 4 bytes

The bytes are stored as semicircles and not Garmin units; they may be little or Big endian, meaning you may have to reverse the order.they are stored ( a bit is set in the 40 header box - see above)

so 00 9d dc 23 may need to be read as 23 dc 9d 00

Data becomes 7F FF FF FF if no gps fix could be established

Which block contains crucial GPX data?

Coordinates are defined in a 40 block which contain the number (ANT speak : global message) for a 'record' - This number is 20 or &h14 (Some fit files contain (Strava) route segments - they have a different number - see below)

The 40 block include 2 bytes to define the global messages highlighted below:

40 00 01 00 00 ...

If there are several 40 blocks defined which ones contain the Latitude/Longitude data for our gpx file?

 

40 00 01 00 14

 

&14 stands for 'record'

Below the results using our FIT - GPX for Windows

Fields (6)

00 '04' 85 PositionLat
01 '04' 85 PositionLong = 1
02 '02' 84 Altitude = 2
FD '04' 86 Timestamp
06 '02' 84 Speed = 6
05 '04' 86 Distance = 5

1) Latitude 2) Longitude 3) Height 4) Timestamp 5) speed 6) distance

gpx data

Most FIT files also include temperature readings, heart rate & cadence (steps per minute)

These can also be added to your gpx file.

Tip : Import your FIT file into Basecamp then export it as a gpx and check the code.

When you create your GPX file only start when the GPX has kicked in; ie check if the Latitude is not 7FFFFFFF

Check your gpx file in Basecamp/Mapsource for possible 'unknown' errors - Garmin's archaic parsers are known to be intolerant and unfriendly!

More on Global Messages in 40 blocks

The following explains the headings given in the FITtoCSV converter given our example in picture above.

FileID :4th byte=0

&E ******************************** FILE_ID (0) 40 00 00 00 00
Fields (7)
03 04 8C
04 04 86
07 04 86
01 02 84
02 02 84
05 02 84
00 01 00
&29 Data 00 06 BF AE C5 | 66 6E F4 38 | FF FF FF FF | 01 00 | 2C 0A | FF FF | 04 |

FILE_CREATOR : 4th byte = &31 ( dec 49)

&3D ******************************** FILE_CREATOR (49) 41 00 00 31 00
Fields (3)
02 14 07
00 02 84
01 01 02
&4C Data 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 76 07 | FF |

EVENT 4th byte=&h15 (dec 21)

&64 ******************************** EVENT (21) 42 00 00 15 00
Fields (7)
FD 04 86
03 04 86

RECORD : fourth/fifth byte = &14 (dec 20)

******************************** RECORD (20) 4C 00 00 14 00 or 4C 00 01 00 14
Fields (9)
FD 04 86 Timestamp
00 04 85 PositionLat
01 04 85 PositionLong = 1
05 04 86 Distance = 5
02 02 84 Altitude = 2
06 02 84 Speed = 6
03 01 02 HeartRate = 3
04 01 02 Cadence = 4
0D 01 01 Temperature = &D (dec13)

Strava Segments

:RECORD (150) 40 00 00 96 00 or 40 00 01 00 96

Fields (6)

01 04 85 Position Lat
02 04 85 Position Long
04 02 84 Altitude
03 04 86| Distance
FE 02 84 message
05 08 86| Timestamp

Strava segments show &96 in the fourth byte

These segments are mostly short linear routes

Course Points

:RECORD (32) 40 00 00 20 00 or 40 00 01 00 20

01 04 86 Timestamp
02 04 85 Position Lat
03 04 85 Position Long
04 04 86 Distance
06 10 07 Instruction
FE 02 84 message
05 01 00| type

They behave more like waypoints and are fundamentally used for a turn by turn direction

The data blocks contain the coordinates for the point and an instruction.

These points represent parts of a track where a new instruction is given. From a gpx point of view such points are not very useful.

Often used on  Garmin Edge Devices.

These can be best described as instructions, ie turn left, turn sharp right , keep going, drink water etc

The instructions are numbered 0 to 255, each number representing particular instruction

here are some

0 = "Generic"
1= "Summit"
2 = "Valley"
3 = "Water"
4= "Food"
5 = "Danger"
6 = "Turn Left"
7 = "Turn Right"
8 = "Straight Ahead"
9 = "First Aid"
15= "Sprint"
16 = "Left Fork"
17 = "Right Fork"
18 = "Middle Fork"
19 = "Continue Bear Left"
20) = "Sharp Left"
21) = "Continue Bear Right"
22) = "Sharp Right"
23) = "UTurn"
24 = "Segment Start"
25 = "Segment End"
course points in a fit file

Picture shows course with coursepoints

The definition contains a string,longitude, latitude, instruction number