Creating an Array within a Struct in ROBOTC

I’m trying to create an array to store RPM values that I will then use to calculate an exponential moving average of the RPM values the take-back-half algorithm for our flywheels will use.

The structure of the take-back-half algorithm is a struct (pun somewhat intended); it’s a derivative of jpearman’s take-back-half algorithm. I like this version of the algorithm because we have 2 independently moving flywheels, so each one needs its own velocity controller, and this lets us have the two instances without having to have 2 copies of the code (the only duplication is that each side of the flywheel needs its own controller task).

Here’s the relevant code for the moving average:

typedef struct _fw_controller {
    long            counter;                ///< loop counter used for debug

    // encoder tick per revolution
    float           ticks_per_rev;          ///< encoder ticks per revolution

    // Encoder
    long            e_current;              ///< current encoder count
    long            e_last;                 ///< current encoder count

    // velocity measurement
    float           v_current;              ///< current velocity in rpm
    int							termsInAvg = 0;					///< number of terms included in the average; the exponential weighted average calculation changes slightly if this value is less than 10
    float						v_last10[10];						///< array holding last 10 RPM calculations - this line causes a compiler error: "**Error**:Initializing expressions not allowed within 'struct' definition."
    float						v_avg;									///< weighted exponential average of the last 10 RPM measurements that is used to calculate error
    long            v_time;                 ///< Time of last velocity calculation

    // TBH control algorithm variables
    long            target;                 ///< target velocity
    long            current;                ///< current velocity
    long            last;                   ///< last velocity
    float           error;                  ///< error between actual and target velocities
    float           last_error;             ///< error last time update called
    float           gain;                   ///< gain
    float           drive;                  ///< final drive out of TBH (0.0 to 1.0)
    float           drive_at_zero;          ///< drive at last zero crossing
    long            first_cross;            ///< flag indicating first zero crossing
    float           drive_approx;           ///< estimated open loop drive
    float						MOTOR_TPR;							///< ticks per rev for IME

    // final motor drive
    long            motor_drive;            ///< final motor control value
    } fw_controller;

//a few functions in here


void
updateRPMAverage(fw_controller *fw, float array, float newRPM) {
	
	//shift values up one; a side effect will be that the oldest value will be removed if there are more than 10 RPM values
	for (int i = 1; i <= 9; i++) {
			array* = array*;
	}

	//set the newest RPM value to index 9 of the array
	array[9] = newRPM;
	
	float sum = 0;
	int weightedNumTerms = 0; //number to divide by
	int stopIndex = fw->termsInAvg == 10 ? 0 : 9 - fw->termsInAvg;
	//computed the new weighted average
	for (int i = 9; i >= stopIndex; i--) {
		sum += pow(array*, i + 1);
		weightedNumTerms += i + 1; //if i is 9, then array* is included in the average 10 times to weight it; thus, we need to divide i by 10
	}
	fw->termsInAvg = fw->termsInAvg + 1 > 10 ? 10 : fw->termsInAvg + 1;
	fw->v_avg = sum / (float) weightedNumTerms; //cast weightedNumTerms as a float so we don't mistakenly end up with integer division
}

/*-----------------------------------------------------------------------------*/
/** @brief      Calculate the current flywheel motor velocity                  */
/** @param[in]  fw pointer to flywheel controller structure                    */
/*-----------------------------------------------------------------------------*/
void
FwCalculateSpeed( fw_controller *fw, long encoderValue )
{
    int     delta_ms;
    int     delta_enc;

    // Get current encoder value
    fw->e_current = encoderValue;

    // This is just used so we don't need to know how often we are called
    // how many mS since we were last here
    delta_ms   = nSysTime - fw->v_time;
    fw->v_time = nSysTime;

    // Change in encoder count
    delta_enc = (fw->e_current - fw->e_last);

    // save last position
    fw->e_last = fw->e_current;

    // Calculate velocity in rpm
    fw->v_current = (1000.0 / delta_ms) * delta_enc * 60.0 / fw->ticks_per_rev;
    updateRPMAverage(fw, fw->v_current);
}

The error I’m getting is


**Error**:Initializing expressions not allowed within 'struct' definition.

on the line that is supposed to create the array to hold the last 10 RPM values, which are then used to calculate the average.

My questions are:

  1. Is there any reason I can’t create this array within a struct?
  2. Is there a way around this? I’d rather not have to use individual variables for each of the 10 past RPM values because of how much cleaner an array would be.

Thanks in advance for any help!****

That particular error is caused by this line of code in the struct definition.


    int							termsInAvg = 0;	

Look for the red “X” or double click on the error and you will be taken to the line of code where the compiler thinks there is an error.

You can create arrays as part of a struct.

You will also need to update a couple of other lines of code before this will work correctly.
This

void
updateRPMAverage(fw_controller *fw, float array, float newRPM) {

Will need to be this.

void
updateRPMAverage(fw_controller *fw, float *array, float newRPM) {

this


updateRPMAverage(fw, fw->v_current);

will need to be this (I think this is what you intend).


updateRPMAverage(fw, fw->v_last10, fw->v_current);

don’t forget to initialize the ticks_per_rev entry or will get a divide by zero exception.