Append data to array

Hi all,

I'd like to calculate the percentage grade in my data field and thought of the following:

Use two arrays of defined size and populate them with rise and run (e.g. over the course of 5 seconds), then start calculating grade. Each consecutive second, drop the first value and append the most recent value to both arrays, then recalculate grade.

I'm having some trouble finding out how to do the filling of the arrays though, can someone point me in the right direction?

Thanks in advance for any help!
  • What you could do is use the array as a circular buffer.

    You keep the index of the "next for new data" and store the newest data there, and advance the index. You don't move any data, you just changes the index, and when "next place" is larger that the size of the array, it goes back to 0.. You always have the same array, but you you'll know where the last new data is, and were the oldest data is.

    I did an example in mc months ago and I'll see if I can find it.
  • Thanks for the suggestion!

    I've coded something that seems to work.. Do you think I can make it cleaner/leaner?

    function compute(info) {
    if (info.altitude != null && info.currentSpeed != null) {
    arrayAltitude[arrayIndex] = info.altitude;
    arrayDistance[arrayIndex] = info.currentSpeed;

    valueGrade = (arrayAltitude[arrayIndex] - arrayAltitude[mod((arrayIndex - 4), 5)]) /
    (arrayDistance[arrayIndex] + arrayDistance[mod((arrayIndex - 1), 5)] + arrayDistance[mod((arrayIndex - 2), 5)] + arrayDistance[mod((arrayIndex - 3), 5)])
    * 100;

    arrayIndex = mod((arrayIndex + 1), 5);
    }
    else {
    valueGrade = 0;
    }
    }


    Also, right now I define my starting arrayAltitude as [0, 0, 0, 0, 0], which means that when I start populating the array, the initial grade values are huge. How can I initiate the array with current elevation data?

    Thanks a lot for your help!
  • I define my starting arrayAltitude as [0, 0, 0, 0, 0], which means that when I start populating the array, the initial grade values are huge. How can I initiate the array with current elevation data?


    Allocate the array, but don't initialize the values until you have valid data.

    function initialize() {
    arrayDistance = new [5];
    arrayAltitude = new [5];
    }

    function compute(info) {

    if (info.altitude == null && info.currentSpeed == null) {
    return 0;
    }

    // if we haven't got any data, fill with the current data
    if (arrayDistance[arrayIndex] == null) {

    for (var i = 0; i < arrayDistance.size(); ++i) {
    arrayDistance= info.currentSpeed;
    }

    for (var i = 0; i < arrayAltitude.size(); ++i) {
    arrayAltitude= info.altitude;
    }
    }

    // your code...
    }
    [/code]

    Additionally, you store data for the last 5 seconds, but you aren't using the data from 5 seconds back. I believe you should be able to simplify your code to...

    // difference in altitude from now versus 5 seconds ago
    var altitudeChange = (arrayAltitude[arrayIndex] - arrayAltitude[(arrayIndex + 1) % arrayAltitude.size()]);

    // sum of all of the distances travelled for each of the last 5 seconds
    var distanceChange = 0;
    for (var i = 0; i < arrayDistance.size(); ++i) {
    distanceChange += arrayDistance;
    }

    return (100 * altitudeChange) / distanceChange;
    [/code]
  • Additionally, you store data for the last 5 seconds, but you aren't using the data from 5 seconds back. I believe you should be able to simplify your code to...


    Thanks for the initialization fix, code makes a lot of sense!

    About using all distance data: I think to be accurate, I need to sum the last 4 distances travelled, since 4 elevation changes occur, right? It's the delta between last elevation measured and 4 times ago. Could be completely off here though..
  • If you have arrays of length 5, you have 5 different elevation/distance measurements. As your code currently stands, you only access 4 of the 5 distance elements. If you only want 4 measures, then you shouldn't need the 5th data point.
  • I made a small change to my code above. If arrayIndex is the most recent sample, then (arrayIndex + 1) % arrayAltitude.size() is the oldest sample (the one that will get replaced next).
  • If you have arrays of length 5, you have 5 different elevation/distance measurements. As your code currently stands, you only access 4 of the 5 distance elements. If you only want 4 measures, then you shouldn't need the 5th data point.




    The elevation change happens over 4 seconds, since the first elevation is the reference point. It wouldn't make sense to include the 'distance' measured at t0 in the calculation, right? It seems to me, only the sum of t1 through t4 are relevant, compared to the elevation change of e4 over e0.
  • Yes, you are right. The number of 'distance' points you use needs to be one less than the number of 'altitude' points. This is because the 'distance' you capture is not actually distance, but velocity which you are applying over over the next second.
  • Yes, you are right. The number of 'distance' points you use needs to be one less than the number of 'altitude' points. This is because the 'distance' you capture is not actually distance, but velocity which you are applying over over the next second.


    Cool, glad we agree :) I wasn't sure my logic made sense till I made the graph either haha

    Thanks again for all your help!
  • With your suggestions, this is what I'm using now

    // Calculate current slope
    if (info.altitude != null && info.currentSpeed != null) {
    // if we haven't got any data, fill with the current data
    if (arrayDistance[arrayIndex] == null) {
    for (var i = 0; i < arrayDistance.size(); ++i) {
    arrayDistance= info.currentSpeed;
    }

    for (var i = 0; i < arrayAltitude.size(); ++i) {
    arrayAltitude= info.altitude;
    }
    }
    // fill arrays
    arrayAltitude[arrayIndex] = info.altitude;
    arrayDistance[arrayIndex] = info.currentSpeed;

    // calculate altitude change over last 4 seconds
    var altitudeChange = (arrayAltitude[arrayIndex] - arrayAltitude[mod((arrayIndex + 1), arrayAltitude.size())]);

    // calculate horizontal displacement over last 4 seconds
    var distanceChange = 0;

    for (var i = arrayIndex; i > (arrayIndex - (arrayDistance.size() - 1)); --i) {
    var idx = mod(i, arrayDistance.size());
    distanceChange += arrayDistance[idx];
    }
    // calculate percent grade
    valueGrade = (altitudeChange * 100) / distanceChange;

    // advance to next array index
    arrayIndex = mod((arrayIndex + 1), arrayAltitude.size());
    }
    else {
    valueGrade = 0;
    }
    [/CODE]

    Thanks to you awesome people on this forum :)