Grade Calc - Community Project

I'm still not happy with CIQ Grade calcs. I live in Florida (mostly flat) so I really don't have a lot of real world opportunities to test Grade. On the other hand, these subtle rollers are some of the most challenging use cases to test the algorithm. The problem seems to be that barometric values aren't updated quickly - and then they tend to jump in a step function when they do change.

Even up steeper grades like Colorado passes that I got to ride last weekend, barometric data isn't smooth. A balance is needed between grade being noisey (due to barometric jumps) or slow to respond (due to smoothing out those jumps). I've tried to make the balance factor adaptive. So it detects a slope inversion or a transition to/from flat roads faster.

Even the native grade values are slow to respond. However, Garmin apparently did a lot of work on this problem in the new Garmin EDGE 1050 (according to DC Rainmaker's beta evals) and now the native grade is dramatically better. As soon as you hit a steep grade from a flat road, for example, grade will reflect a legit value, not slowly adjust over 10-15 seconds. Maybe using the accelerometer sensor to assist?

Anyway, Garmin still refuses to expose native Grade to CIQ. So we have to figure this out on our own.

I am thinking about a Community Effort to optimize the CIQ Grade calcs. I'll create a DF that only generates grade, and that writes to the FIT file, with some User Settings for various variables. I'll display the current grade as well as a line graph of grade to show how our algorithm adapts to slope changes, slope inversion, and transitions to/from flat roads. And I can display this and the EDGE's native grade on the same screen to compare.

I'll post the CIQ Code in GIT Hub and allow contributors to check out, and update. I bet we can come up with a barrel pretty quick that does a great job.

This image shows a pretty steep sustained grade (grey is the elevation profile, blue is my current GRADE calc). Now that I write a FIT graph I have more visibility into the dynamics and I clearly need to smooth it a bit more. I had tried a Kalman Filter at one point that also seemed ok, but not good enough.

If you are interested in joining the project, let me know.

  • For example, https://github.com/mizamae/GarminSlopeDatafield seems to be a great project but without a license nobody can reuse their code.

    They're still maintaining the project (last update was 10 days ago.) You could always ask them if they'd be willing to license it.

  • Hello guys,

    I am the developer of Garmin Slope Datafield. I will add a MIT license so that everyone can use it freely.

    If you need further help, just let me know.

    Regards 

  • Fantastic!!! I'll check it out after my ride today. I haven't looked at your code yet. I've played with all the barometric sensor data, and it appears that the Activity.altitude is the best data to get the most responsive and also filtered elevation data. I assume they internally use the best data they have from possibly barometric, GPS and maybe other data. I've noticed on my new 1050 (and it is reported they maybe some major changes to grade) that testing in a car at least, as I slow for a stop, as I'm slowing on a flat road, the native GRADE can report 2-3%... so that is an artifact as the change in distance reduces quickly per second, due to the altitude updating on a less frequent basis.... this is also something we have to account for. Thanks again!

  • I've now experimented a bit and recorded the live altitude and speed data directly. It seems that actually the altimeter data is quite precise. In any case, I struck the following compromise between responsiveness and stability: 1. Collect altitude and speed information for 8 seconds. 2. Average the past 4 seconds of altitude and deduct from this the average previous 4 seconds of altitude. 3. Divide the result by the average of the "middle" four seconds of speed. In other words: ((a8+a7+a6+a5)-(a4+a3+a2+a1))/(s6+s5+s4+s3). For an Edge 530 device this gave believable numbers. The grade is of course lagged by 4.5s in this way. On the upside, it does not require any curve fitting or Kalman filters. Instead of using only the four "middle" seconds of speed, you can also use all 8 seconds and use a factor of 2, like so: 2*((a8+a7+a6+a5)-(a4+a3+a2+a1))/(s8+s7+s6+s5+s4+s3+s2+s1).

  • Why do you divide altitude change by speed and not distance (d6-d3)?

  • Why do you divide altitude change by speed and not distance (d6-d3)?

    I think, because the speed of every second = distance of that second (m/s).

  • Right, using the sum of speed or distance should be the same thing, I just happen to also need the speed values. By the way, if you want to know the average grade of a longer climb, it is probably best to use 30s or even 1 minute of data. It will lag but you will get a very precise grade estimate once you are on a climb. When pacing up a longer hill, this might be the best approach.

  • But this feature doesn't estimate the grade of a course/route. It estimates the grade based on where you are/were a few seconds ago. And then it's better to see the "local" value, rather than the outdated/lagging 30 seconds later value.

  • That's right. I guess there are different use cases. The "local value" from 1 sec of past data is very noisy. Estimating an entire route is afaik impossible within CIQ since Garmin at most gives you the "next point" on the route. You would need to upload the route separately to an API and then download the data via cell phone connection (but then you can calculate the gradients better in your API directly). Another use case is the average climbing gradient of the ride so far. That would be well estimated by summing over all the positive values in the proposed algorithm.

  • Regarding average climbing gradient so far: What's the difference between doing what you wrote (comlicated) vs (current_elevation-starting_elevation)/distance?