Yumi's Blog

Extract GPS data from Suunto's MovesCount

I have been using Suunto Ambit 2 as the device for recording any sports activities e.g. running, trekking, or swimming. Recorded activities can be updated in the cloud Suunto Movescount, and see the summary of activities, e.g., speed, pace, elevation gain or elevation loss. Suunto Movescount is a growing sports community where you can create your own sports diary to collect and share your activities as well as customize your compatible Suunto watch.

Sometimes, when I do not have a watch with me, I use my iphone's MovesCount app to record the activities as alternative. Unfortunatelly, With the iphone and watch the recording performance varies substantially:
When there is no signal, the recording performances of iphone's MovesCount app, especially the net elevation gain and loss, are just awefully unreliable.

In this post, I attempt to clean the GPS data from the iphone's MovesCount app, and make the performance conparable to the watch.

First, let's look at the GPS data from the two devices.

I recorded my hiking activity in Nepal using the two devices: Mountaineering move with Suunto Ambit 2 watch and Trekking move with Phone.

I downloaded the GPS data from my movescount page.

  • Click Tools -> Exprot as KML.
In [1]:
from IPython.display import Image
Image("kml_photo.png",width='100%',height=100)
Out[1]:

The exported kml files are saved in the two locations.

In [2]:
dir_move = "./data/"
path_phone_move_kml = dir_move + '/phone/Move_2018_05_01_06_52_33_Trekking.kml' 
path_watch_move_kml = dir_move + '/Move_2018_05_01_06_51_39_Mountaineering_Lobche_Gorekshep_EBC.kml' 

Extract the GPS coordinate infomation and the altitude infomation from the kml file, and save it into a panda dataframe.

In [3]:
import os 
import numpy as np
import fastkml
import pandas as pd 
import matplotlib.pyplot as plt
In [4]:
def get_coordinates(path_kml):
    '''
    extract lat, lon, altitude info from the kml data
    '''
    doc = open(path_kml, 'rb+').read()
    k = fastkml.KML()
    k.from_string(doc)
    kmlstr = k.to_string()
    coordstr = kmlstr.split("")[1].split("")[0]
    coordlst = coordstr.split(" ")
    l = []
    for point in coordlst:
        pointlst = point.split(",")
        l.append(pointlst)
    df = pd.DataFrame(l,columns = ["lon","lat","altitude"])
    for col in df.columns:
        df[col] = pd.to_numeric(df[col], errors='coerce')
    return(df)



df_phone = get_coordinates(path_phone_move_kml)
df_watch = get_coordinates(path_watch_move_kml)

## In this activity, the first 230 samples from the watch and the 14500 samples from the phone roughtly agree
df_watch = df_watch.iloc[1:230,:]
df_phone = df_phone.iloc[:14500,:]

print(df_phone.shape,df_watch.shape)
df_phone[:5]
No geometries found
Object does not have a geometry
No geometries found
Object does not have a geometry
(14500, 3) (229, 3)
Out[4]:
lon lat altitude
0 86.810962 27.948544 4923.200195
1 86.810972 27.948542 4923.291324
2 86.810975 27.948541 4925.231034
3 86.810979 27.948542 4927.935645
4 86.810985 27.948542 4927.390356

Let's plot the GPS coordinate infos from the two devices using gmplot

The latitude and longitude pairs seem to agree between the records from the two devies.

In [5]:
from gmplot import gmplot

filenm = "my_map.html"
# Place map
gmap = gmplot.GoogleMapPlotter(27.971815, 86.828963, 14)

gmap.plot(df_phone["lat"], df_phone["lon"], 'cornflowerblue', edge_width=2)
gmap.plot(df_watch["lat"], df_watch["lon"], '#3B0B39', edge_width=2)

# Draw
gmap.draw(filenm)
In [6]:
import sys
sys.path.append("../../trip/")
## my google api key
from personal import MY_API_KEY 

def jupyter_display(gmplot_filename, google_api_key):
    """
    Hack to display a gmplot map in Jupyter
    reference
    https://github.com/vgm64/gmplot/issues/16
    """
    with open(gmplot_filename, "r+") as f:
        f_string = f.read()
        url_pattern = "https://maps.googleapis.com/maps/api/js?libraries=visualization&sensor;=true_or_false"
        f_string = f_string.replace(url_pattern, url_pattern + "&key;=%s" % google_api_key)
        f.write(f_string)
    
jupyter_display(filenm, MY_API_KEY)
Image("my_map.png",width='100%',height=100)
## from IPython.display import IFrame
## IFrame(filenm, width=990, height=800)
Out[6]: