jovandeginste / workout-tracker

A workout tracking web application for personal use (or family, friends), geared towards running and other GPX-based activities
Other
945 stars 31 forks source link

Graphs for performance data: heart rate, cadence etc stats #137

Closed saaste closed 4 months ago

saaste commented 5 months ago

I have just tested the app and it looks great!

What I'm still missing are the other performance graphs that are usually visible in services like Garmin Connect and Strava. I mean things like heart rate, cadence, altitude, performance condition, vertical ratio etc.

~I don't know if Garmin's FIT files contain all this information, but I assume they do.~ I quickly checked the GPX and TCX exports from Garmin Connect and they include heart rate, cadence and temperature, but not all the other things that are visible in Garmin Connect.

I can provide sample files if that helps :relaxed:

Update: I checked a FIT file and it seems to contain all the data just as I assumed.

jovandeginste commented 5 months ago

I know there is a lot of extra information, the question quickly becomes how to model and show it consistently, conveniently, without becoming Garmin...

saaste commented 5 months ago

I could spend some time trying to understand how the data is modeled in FIT/GPX/TCX files and if these things are somehow standardized or manufacturer-specific. I just need to find files from other manufacturers.

I'm a Go developer myself, so if you don't mind, I could try to figure out something and then propose it to you so that you don't have to do all the heavy lifting. Already forked the repo ☺️

jovandeginste commented 5 months ago

I use libraries to extract the information; I also have some Garmin files with heart rate.

theowoo commented 4 months ago

I know there is a lot of extra information, the question quickly becomes how to model and show it consistently, conveniently, without becoming Garmin...

Thanks for the app. I'm trying it out and would be happy to see heart rate included too. May I suggest a similar implementation to what OpenTracks (screenshot for illustration) is doing?

jovandeginste commented 4 months ago

Added heart rate and cadence for now, should clean up the Javascript code to be more flexible...

TheBig-O commented 2 months ago

Thanks for building this!! I've been looking for something like this for a LONG time! I'm really liking this app and appreciate the hard work you've put into it. Is there some trick to getting the heart rate to show up on the graphs and tables. I know the GPX files have that data in them, but do not see it anywhere within the app.

jovandeginste commented 2 months ago

If you open a workout, and scroll down to the graph, you can show the heart rate / cadence:

image

TheBig-O commented 2 months ago

I tried those two toggles and all that shows up on the chart is a flat line along the bottom as though there's no data. Is it possible there is an issue with the database or a configuration that isn't pulling the information? I looked at the logs and don't see any errors and can't find where that field is in the database. (Or if it is aggregated with another field, I'm not seeing it.)

image

This chart is from a walk last night, using my apple watch which shows the heart rate in the workouts app.

jovandeginste commented 2 months ago

Did you add the workout recently, or did you add it a long time ago?

TheBig-O commented 2 months ago

I added it last night?

jovandeginste commented 2 months ago

Was it by uploading a GPX file? If so, can you open the GPX file with a text editor, and see if it contains the string "ns3:hr" ?

TheBig-O commented 2 months ago

well, that might explain it. "ns3:hr" does not seem exist in any of my gpx files. Gonna have to figure out why that information is not being exported. (Assuming there's no other pace where HR is stored...)

jovandeginste commented 2 months ago

It might be exported with a different attribute name; can you share a snippet of the gpx file?

TheBig-O commented 2 months ago

Here's a small section. I left top and bottom and a few of the track points. Let me know if you need more. It looks like both HR and CAD are in the the file, but listed as "gpxtpx:hr" and "gpxtpx:cad"

<?xml version="1.0" encoding="UTF-8"?>
<gpx creator="HealthFit" version="1.1"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1
http://www.topografix.com/GPX/11.xsd"
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
xmlns="http://www.topografix.com/GPX/1/1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3">
    <trk>
        <type>walking</type>
        <trkseg>
            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:13:42.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:cad>39</gpxtpx:cad>
                        <gpxtpx:course>336.738121</gpxtpx:course>
                        <gpxtpx:hAcc>4.756983</gpxtpx:hAcc>
                        <gpxtpx:vAcc>3.925446</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>
            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:13:43.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:hr>106</gpxtpx:hr>
                        <gpxtpx:cad>39</gpxtpx:cad>
                        <gpxtpx:course>334.829081</gpxtpx:course>
                        <gpxtpx:hAcc>4.185982</gpxtpx:hAcc>
                        <gpxtpx:vAcc>3.496731</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>
            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:13:44.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:hr>106</gpxtpx:hr>
                        <gpxtpx:cad>39</gpxtpx:cad>
                        <gpxtpx:course>332.866251</gpxtpx:course>
                        <gpxtpx:hAcc>3.821722</gpxtpx:hAcc>
                        <gpxtpx:vAcc>3.148560</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>
            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:13:45.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:hr>106</gpxtpx:hr>
                        <gpxtpx:cad>39</gpxtpx:cad>
                        <gpxtpx:course>331.398088</gpxtpx:course>
                        <gpxtpx:hAcc>3.534698</gpxtpx:hAcc>
                        <gpxtpx:vAcc>2.850688</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>
            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:13:46.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:hr>105</gpxtpx:hr>
                        <gpxtpx:cad>39</gpxtpx:cad>
                        <gpxtpx:course>332.099557</gpxtpx:course>
                        <gpxtpx:hAcc>3.260993</gpxtpx:hAcc>
                        <gpxtpx:vAcc>2.590735</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>
            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:13:47.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:hr>105</gpxtpx:hr>
                        <gpxtpx:cad>39</gpxtpx:cad>
                        <gpxtpx:course>335.800750</gpxtpx:course>
                        <gpxtpx:hAcc>2.965889</gpxtpx:hAcc>
                        <gpxtpx:vAcc>2.361057</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>
            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:13:48.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:hr>104</gpxtpx:hr>
                        <gpxtpx:cad>39</gpxtpx:cad>
                        <gpxtpx:course>343.322975</gpxtpx:course>
                        <gpxtpx:hAcc>2.665942</gpxtpx:hAcc>
                        <gpxtpx:vAcc>2.157039</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>
            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:13:49.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:hr>104</gpxtpx:hr>
                        <gpxtpx:cad>39</gpxtpx:cad>
                        <gpxtpx:course>354.775719</gpxtpx:course>
                        <gpxtpx:hAcc>2.437019</gpxtpx:hAcc>
                        <gpxtpx:vAcc>1.975840</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>
            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:13:50.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:hr>103</gpxtpx:hr>
                        <gpxtpx:cad>39</gpxtpx:cad>
                        <gpxtpx:course>13.389090</gpxtpx:course>
                        <gpxtpx:hAcc>2.335155</gpxtpx:hAcc>
                        <gpxtpx:vAcc>1.815764</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>

...         

            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:55:47.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:course>344.754224</gpxtpx:course>
                        <gpxtpx:hAcc>2.076780</gpxtpx:hAcc>
                        <gpxtpx:vAcc>1.254393</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>
            <trkpt lat="REMOVED" lon="REMOVED">
                <ele>REMOVED</ele>
                <time>2024-07-28T23:55:48.000Z</time>
                <extensions>
                    <gpxtpx:TrackPointExtension>
                        <gpxtpx:course>347.371322</gpxtpx:course>
                        <gpxtpx:hAcc>2.497319</gpxtpx:hAcc>
                        <gpxtpx:vAcc>1.402276</gpxtpx:vAcc>
                    </gpxtpx:TrackPointExtension>
                </extensions>
            </trkpt>
        </trkseg>
    </trk>
</gpx>
jovandeginste commented 2 months ago

Should do it; I see "hr" with something that could be a heart rate (and some other metrics). I'll try to add them tomorrow or so.

TheBig-O commented 2 months ago

Awesome! I know that HR and some other metrics are not part of the GPX standard so I'm not surprised they're represented differently by different apps and platforms. PS: "ele" should be elevation

jovandeginste commented 2 months ago

Yes, ele is a standard part - you see it in your graph as well

jovandeginste commented 2 months ago

For my convenience, could you mail me one gpx file? You can find my mail address in the git commit log.

jovandeginste commented 2 months ago

Never mind, it's even in my own test files!

jovandeginste commented 2 months ago

It is added now; you should refresh all previously uploaded GPX files again (there is a button for this in your profile page, "Refresh all your workouts")

jovandeginste commented 2 months ago

It should also show the fact that heading information (the "course" field) is now detected; we don't do anything useful with that for now. The screenshot shows the extra metrics for one of my test-files, with "heart rate" but without "course". You should see a compass icon too for the file you shared.

image

TheBig-O commented 2 months ago

This is excellent! I hit the refresh button on the workout I shared with you (and a few more) and it works perfectly! I'll try refreshing the rest as soon as I get home. I'm out much of the day today. Thanks for the update! Really liking your app!!

jovandeginste commented 2 months ago

Like I said, there is a single button to refresh all your workouts

TheBig-O commented 2 months ago

I tried the button to refresh all the workouts and unfortunately, something went wrong. When I clicked the button, it worked for a few minutes and then the container crashed. Worse, it won't restart. The error I get is:

workout-tracker  | {"time":"2024-07-31T02:15:21.36365838Z","level":"INFO","msg":"Updating workout 1328","app":"workout-tracker","version":"master","sha":"REMOVED-SHA-NUMBER","module":"app","module":"worker"}
workout-tracker  | panic: runtime error: invalid memory address or nil pointer dereference
workout-tracker  | [signal SIGSEGV: segmentation violation code=0x1 addr=0x90 pc=0xd68083]
workout-tracker  | 
workout-tracker  | goroutine 12 [running]:
workout-tracker  | github.com/jovandeginste/workout-tracker/pkg/database.(*Workout).AsGPX(...)
workout-tracker  |      /app/pkg/database/workouts.go:235
workout-tracker  | github.com/jovandeginste/workout-tracker/pkg/database.(*Workout).UpdateData(0xc00059a240, 0xc00052ae40)
workout-tracker  |      /app/pkg/database/workouts.go:253 +0x23
workout-tracker  | github.com/jovandeginste/workout-tracker/pkg/app.(*App).UpdateWorkout(0xc00015a840, 0x25f3a68?)
workout-tracker  |      /app/pkg/app/background.go:193 +0x47
workout-tracker  | github.com/jovandeginste/workout-tracker/pkg/app.(*App).updateWorkout(0xc00015a840, 0xc000526000)
workout-tracker  |      /app/pkg/app/background.go:181 +0x225
workout-tracker  | github.com/jovandeginste/workout-tracker/pkg/app.(*App).BackgroundWorker(0xc00015a840)
workout-tracker  |      /app/pkg/app/background.go:30 +0xae
workout-tracker  | created by github.com/jovandeginste/workout-tracker/pkg/app.(*App).Serve in goroutine 1
workout-tracker  |      /app/pkg/app/app.go:64 +0x56

Any idea what may be going on? And yes, I backed up the database before hitting refresh.

jovandeginste commented 2 months ago

Could you open a new issue for this? If you have time, restore your backup and check if workout with id 1328 is working...

jovandeginste commented 2 months ago

I found the probable cause, and fixed it in #203

TheBig-O commented 1 month ago

Could you open a new issue for this? If you have time, restore your backup and check if workout with id 1328 is working...

I hit the refresh and 1328 worked. I just ran a complete refresh now and everything updated just fine. (I'll update this comment here and add a comment on #203 Thanks!!! Love how quickly you're adding to this app!