GRADE and ELEVATION

I'm really happy with my GRADE field. I write out the GRADE and ELEVATION to the FIT file. My elevation line graph is much better than the default one, which doesn't seem to auto-scale so you can't see the undulations when the topology isn't very bumpy.

One strange finding. I write out the ELEVATION every second, along with my GRADE calculation. Elevation data comes straight from  "Activity.getActivityInfo().altitude", so it should be time sync'ed with what my device is seeing. The strange thing is my GRADE uses a rolling 6 reading queue and then smooths the resulting GRADE by averaging the derived grade over the last 3 readings. So the GRADE value should be delayed -vs- the current (change in) elevation. The PURPLE grade line should be to the right of the GRAY elevation line. But for some reason, GRADE is plotted earlier than ELEVATION. No big deal at all. I just can't explain it.

That bump is a highway overpass - the biggest hill on my 25 mile out/back ride in Florida LOL. I hit that one outbound and back inbound.

  • One strange finding. I write out the ELEVATION every second, along with my GRADE calculation. Elevation data comes straight from  "Activity.getActivityInfo().altitude", so it should be time sync'ed with what my device is seeing

    This has been discussed before, but FitContributor.Field.setData[] does not literally write data, it sets the next value to be written. That's why it's called setData[] and not writeData[]. It's Garmin code that decides how often data is written, not your app code.

    For example, if you called setData[] twice in a second, it's likely that only the 2nd value would be written.

    As another example, if your device is set to 1-second recording mode, and you only call setData[] once at the beginning of the activity, then the same value would be written every second, regardless of the fact that you're not calling setData() every second.

    I'm not saying that what you're seeing makes sense in light of the above. I'd expect writes to separate fields to be synchronized with each other, if you're constantly calling setData with new values. But I think it's important to understand how FIT field recording actually works.

    If you can reproduce this problem consistently, it might be worth filing a bug report. Is your elevation dev field synced with the native elevation field, based on the charts in Connect? If even your elevation dev field lags behind the native elevation field, then it would be pretty strong evidence that something is broken, and a pretty simple reproduction procedure.

  • But that only explains a 1 second difference and not the more than 10 seconds we see on the image. And especially not how the grade that should be about 9 seconds "late" compared to the elevation.

    Dave, my guess is that the value you get from the SDK, isn't the same as the value Garmin writes to the fit file (and maybe not the same as the value it displays). I guess you could reverse engineer this somewhat, i.e by recording yourself via a camera, and running up and down on some stairs, reading out loudly what you see, and then later syncing the fit file with the video.

  • But that only explains a 1 second difference and not the more than 10 seconds we see on the image. And especially not how the grade that should be about 9 seconds "late" compared to the elevation.

    Yeah, I already said that it's not an explanation for what he's seeing.

    I'm not saying that what you're seeing makes sense in light of the above. I'd expect writes to separate fields to be synchronized with each other, if you're constantly calling setData with new values. But I think it's important to understand how FIT field recording actually works.

    I just wanted to clarify [again] that the app does not directly control the writing of FIT file data. I happen to think that when discussing technical matters, precision is important. Yes, we all know what he meant, but someone else reading the thread might not. And I also think that when you use the wrong words / concepts to describe something, you also tend to adopt the associated incorrect line of thinking, whether it's intentional or not.

    IOW, personally, if I were to constantly say that setData[] writes data, I might end up accidentally believing it, which is why I try not to say that. Again, it is pretty clear to me that there's a good reason setData is not called writeData.

    Dave, my guess is that the value you get from the SDK, isn't the same as the value Garmin writes to the fit file (and maybe not the same as the value it displays). I guess you could reverse engineer this somewhat, i.e by recording yourself via a camera, and running up and down on some stairs, reading out loudly what you see, and then later syncing the fit file with the video.

    Or he could just compare the value of his elevation dev field with the value of the native elevation activity field, by looking at graphs in Connect, as I suggested. Although I'm not 100% sure what you're suggesting here:

    - are you suggesting that the native activity elevation field is not the same as Activity.getActivityInfo[].altitude? That's what I understood you to mean, but it would not explain what he's seeing. Presumably Activity.getActivityInfo[].altitude is what's written to the dev elevation FIT field [it's hard to imagine that calling setData[x] would in fact causes a different value y to be written], and the dev grade field is based on the dev elevation value, so even if Activity.getActivityInfo[].altitude is different than the "real" elevation. it wouldn't matter since the dev grade would be based on the dev elevation in any case.

    - or are you suggesting that somehow calling setData[x] actually causes a different value y to be written? I find this highly unlikely [but it's not what I understood you to mean.] If it did, that would be a huge bug.

    I think both of these hypotheses could be tested by logging Activity.getActivityInfo[].altitude and the derived grade with System.println[], along with activity timestamps, rather than going to the extremes like yelling out elevation values on video. Sure, there's a limit of 12 KB to on-device text logs [last time OP checked anyway], but that should be enough for a few minutes of logging at least.

    And if there's some need to compare "SDK altitude" [Activity.getActivityInfo[].altitude] with the native activity altitude, native activity altitude is already available in the Connect graphs.

    But again a mismatch between SDK altitude and native altitude wouldn't explain this problem. Since derived grade seems to come from Activity.getActivityInfo[].altitude, it should be consistent with Activity.getActivityInfo[].altitude. Any mismatch between Activity.getActivityInfo[].altitude and "native altitude" would not have any bearing on a mismatch between Activity.getActivityInfo[].altitude and derived grade.

  • I meant that maybe the native elevation field is displaying something other than what is written to the fit and that can also be different from what is being returned in the SDK. At least that's how it looks like from the graph.

    As for testing: logging only will not give you much info, because you can only log what the SDK returns. That's why I recommended a way to write to the fit, that way it'll be easily compared to what Garmin writes to the fit. And because there's also a theoretical possibility that the displayed (by Garmin) value is something else I recommended the yelling out, so it would be possible to later figure all this out when analyzing the video + the fit file.

    I agree with all what you wrote why these possibilities are small and why they don't make sense, but we already saw interesting things from Garmin occasionally, so who knows. It is possible that they intentionaly use the raw value in one place and a smoothed out value in another place.

  • I meant that maybe the native elevation field is displaying something other than what is written to the fit and that can also be different from what is being returned in the SDK. At least that's how it looks like from the graph.

    Yes that's exactly what I understood you to mean.

    And I tried to explain it doesn't matter. OP isn't comparing calculated grade to the native elevation field, OP is comparing calculated grade to what's returned in the SDK (Activity.getActivityInfo().altitude). OP said they're happy with what's returned in the SDK ("My elevation line graph is much better than the default one, which doesn't seem to auto-scale so you can't see the undulations when the topology isn't very bumpy."). With that in mind, the question of the native elevation field is almost irrelevant (although I assume what's returned in the SDK matches the native field, to OP's satisfaction.)

    OP states:

    "I write out the ELEVATION every second, along with my GRADE calculation. Elevation data comes straight from  "Activity.getActivityInfo().altitude", so it should be time sync'ed with what my device is seeing. The strange thing is my GRADE uses a rolling 6 reading queue and then smooths the resulting GRADE by averaging the derived grade over the last 3 readings. "

    And implies that "GRADE" comes from "ELEVATION" ("Activity.getActivityInfo().altitude"). Again, note that both of these things are written to the FIT file.

    Also, I think the screeenshot in OP is of the dev elevation field not the native elevation field. You can see that the label is "Elev", while the native elevation field would be labelled "Elevation". Besides, OP referred to their "dev elevation field" as "ELEVATION" multiple times, including the part where he talks about the graph. Plus, he talks about the "GRADE" and "ELEVATION" graphs right after he talks about writing them to the FIT file, which strongly implies that both of the graphs are of the dev fields.

    Even if I'm wrong about that, it would be very easy for OP to compare the dev elevation field and the native elevation, and to see if he still sees the same problem. If he doesn't, it would support your hypothesis that native elevation and sdk elevation are different.

    That's why I recommended a way to write to the fit, that way it'll be easily compared to what Garmin writes to the fit.

    Yes, and the "dev elevation field" ("Activity.getActivityInfo().altitude") is already written to the FIT file, so OP can easily compare it to the what's written to the native elevation field (in fact, they already said that they like the dev elevation field better than the native field.)

    And because there's also a theoretical possibility that the displayed (by Garmin) value is something else I recommended the yelling out, so it would be possible to later figure all this out when analyzing the video + the fit file.

    If that's indeed what's happening, then it's not really relevant to the complaint in the OP, assuming that they are indeed comparing the dev elevation value to the dev calculated grade.

    Sure, it would be a problem, but I don't think it's the problem OP is complaining about.

  • the screeenshot in OP is of the dev elevation field not the native elevation field

    Yeah, now I see it. This was what I missed earlier. I thought it's plotted the native elevation + the calculated grade.

  • I thought it's plotted the native elevation + the calculated grade.

    Yeah I kinda figured. Should've pointed that out right off the bat.

    Either way it's an interesting situation.