/* * SusConverter.cpp * * Created on: 17.01.2022 * Author: Timon Schwarz */ #include "SusConverter.h" #include //for atan2 #include #include #include #include void SunSensor::checkSunSensorData(uint8_t susNumber) { uint16_t channelValueSum; // Check individual channel values for (int k = 0; k < 4; k++) { // iteration above all photodiode quarters if (susChannelValues[susNumber][k] <= channelValueCheckLow || susChannelValues[susNumber][k] > channelValueCheckHigh) { // Channel values out of range for 12 bit SUS // channel measurement range? validFlag[susNumber] = returnvalue::FAILED; /*printf( "The value of channel %i from sun sensor %i is not inside the borders of valid data with " "a value of %i \n", k, susNumber, ChannelValue[k]);*/ } else if (susChannelValues[susNumber][k] > susChannelValues[susNumber][4]) { // Channel values higher than zero current threshold GNDREF? validFlag[susNumber] = returnvalue::FAILED; /*printf( "The value of channel %i from sun sensor %i is higher than the zero current threshold " "GNDREF\n", k, susNumber);*/ }; }; // check sum of all channel values to check if sun sensor is illuminated by the sun (sum is // smaller than a treshold --> sun sensor is not illuminated by the sun, but by the moon // reflection or earth albedo) channelValueSum = 4 * susChannelValues[susNumber][4] - (susChannelValues[susNumber][0] + susChannelValues[susNumber][1] + susChannelValues[susNumber][2] + susChannelValues[susNumber][3]); if ((channelValueSum < channelValueSumHigh) && (channelValueSum > channelValueSumLow)) { validFlag[susNumber] = returnvalue::FAILED; //printf("Sun sensor %i is not illuminated by the sun\n", susNumber); }; } void SunSensor::calcAngle(uint8_t susNumber) { float xout, yout; float s = 0.03; // s=[mm] gap between diodes uint8_t d = 5; // d=[mm] edge length of the quadratic aperture uint8_t h = 1; // h=[mm] distance between diodes and aperture int ch0, ch1, ch2, ch3; // Substract measurement values from GNDREF zero current threshold ch0 = susChannelValues[susNumber][4] - susChannelValues[susNumber][0]; ch1 = susChannelValues[susNumber][4] - susChannelValues[susNumber][1]; ch2 = susChannelValues[susNumber][4] - susChannelValues[susNumber][2]; ch3 = susChannelValues[susNumber][4] - susChannelValues[susNumber][3]; // Calculation of x and y xout = ((d - s) / 2) * (ch2 - ch3 - ch0 + ch1) / (ch0 + ch1 + ch2 + ch3); //[mm] yout = ((d - s) / 2) * (ch2 + ch3 - ch0 - ch1) / (ch0 + ch1 + ch2 + ch3); //[mm] // Calculation of the angles alphaBetaRaw[susNumber][0] = atan2(xout, h) * (180 / M_PI); //[°] alphaBetaRaw[susNumber][1] = atan2(yout, h) * (180 / M_PI); //[°] } void SunSensor::setCalibrationCoefficients(uint8_t susNumber) { switch (susNumber) { // search for the correct calibration coefficients for each SUS case 0: for (uint8_t row = 0; row < 9; row++) { // save the correct coefficients in the right SUS class for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus0coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus0coeffBeta[row][column]; } } break; case 1: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus1coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus1coeffBeta[row][column]; } } break; case 2: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus2coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus2coeffBeta[row][column]; } } break; case 3: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus3coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus3coeffBeta[row][column]; } } break; case 4: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus4coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus4coeffBeta[row][column]; } } break; case 5: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus5coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus5coeffBeta[row][column]; } } break; case 6: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus6coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus6coeffBeta[row][column]; } } break; case 7: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus7coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus7coeffBeta[row][column]; } } break; case 8: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus8coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus8coeffBeta[row][column]; } } break; case 9: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus9coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus9coeffBeta[row][column]; } } break; case 10: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus10coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus10coeffBeta[row][column]; } } break; case 11: for (uint8_t row = 0; row < 9; row++) { for (uint8_t column = 0; column < 10; column++) { coeffAlpha[susNumber][row][column] = acsParameters.susHandlingParameters.sus11coeffAlpha[row][column]; coeffBeta[susNumber][row][column] = acsParameters.susHandlingParameters.sus11coeffBeta[row][column]; } } break; } } void SunSensor::Calibration(uint8_t susNumber) { float alpha_m, beta_m, alpha_calibrated, beta_calibrated, k, l; uint8_t index; alpha_m = alphaBetaRaw[susNumber][0]; //[°] beta_m = alphaBetaRaw[susNumber][1]; //[°] // while loop iterates above all calibration cells to use the different calibration functions in // each cell k = 0; while (k < 3) { k = k + 1; l = 0; while (l < 3) { l = l + 1; // if-condition to check in which cell the data point has to be if ((alpha_m > ((completeCellWidth * ((k - 1) / 3)) - halfCellWidth) && alpha_m < ((completeCellWidth * (k / 3)) - halfCellWidth)) && (beta_m > ((completeCellWidth * ((l - 1) / 3)) - halfCellWidth) && beta_m < ((completeCellWidth * (l / 3)) - halfCellWidth))) { index = (3 * (k - 1) + l) - 1; // calculate the index of the datapoint for the right cell // -> first cell has number 0 alphaBetaCalibrated[susNumber][0] = coeffAlpha[susNumber][index][0] + coeffAlpha[susNumber][index][1] * alpha_m + coeffAlpha[susNumber][index][2] * beta_m + coeffAlpha[susNumber][index][3] * alpha_m * alpha_m + coeffAlpha[susNumber][index][4] * alpha_m * beta_m + coeffAlpha[susNumber][index][5] * beta_m * beta_m + coeffAlpha[susNumber][index][6] * alpha_m * alpha_m * alpha_m + coeffAlpha[susNumber][index][7] * alpha_m * alpha_m * beta_m + coeffAlpha[susNumber][index][8] * alpha_m * beta_m * beta_m + coeffAlpha[susNumber][index][9] * beta_m * beta_m * beta_m; //[°] alphaBetaCalibrated[susNumber][1] = coeffBeta[susNumber][index][0] + coeffBeta[susNumber][index][1] * alpha_m + coeffBeta[susNumber][index][2] * beta_m + coeffBeta[susNumber][index][3] * alpha_m * alpha_m + coeffBeta[susNumber][index][4] * alpha_m * beta_m + coeffBeta[susNumber][index][5] * beta_m * beta_m + coeffBeta[susNumber][index][6] * alpha_m * alpha_m * alpha_m + coeffBeta[susNumber][index][7] * alpha_m * alpha_m * beta_m + coeffBeta[susNumber][index][8] * alpha_m * beta_m * beta_m + coeffBeta[susNumber][index][9] * beta_m * beta_m * beta_m; //[°] } } } } void SunSensor::CalculateSunVector(uint8_t susNumber) { float alpha, beta; alpha = alphaBetaCalibrated[susNumber][0]; //[°] beta = alphaBetaCalibrated[susNumber][1]; //[°] // Calculate the normalized Sun Vector sunVectorBodyFrame[susNumber][0] = (tan(alpha * (M_PI / 180)) / (sqrt((powf(tan(alpha * (M_PI / 180)), 2)) + powf(tan((beta * (M_PI / 180))), 2) + (1)))); sunVectorBodyFrame[susNumber][1] = (tan(beta * (M_PI / 180)) / (sqrt(powf((tan(alpha * (M_PI / 180))), 2) + powf(tan((beta * (M_PI / 180))), 2) + (1)))); sunVectorBodyFrame[susNumber][2] = (-1 / (sqrt(powf((tan(alpha * (M_PI / 180))), 2) + powf((tan(beta * (M_PI / 180))), 2) + (1)))); } float* SunSensor::getSunVectorBodyFrame(uint8_t susNumber) { // return function for the sun vector in the body frame float* SunVectorBodyFrameReturn = 0; SunVectorBodyFrameReturn = new float[3]; SunVectorBodyFrameReturn[0] = sunVectorBodyFrame[susNumber][0]; SunVectorBodyFrameReturn[1] = sunVectorBodyFrame[susNumber][1]; SunVectorBodyFrameReturn[2] = sunVectorBodyFrame[susNumber][2]; return SunVectorBodyFrameReturn; } bool SunSensor::getValidFlag(uint8_t susNumber) { return validFlag[susNumber]; } float* SunSensor::TransferSunVector() { float* sunVectorEIVE = 0; sunVectorEIVE = new float[3]; uint8_t susAvail = 12; int8_t basisMatrixUse[3][3]; float sunVectorMatrixEIVE[3][12] = {0}; float sunVectorMatrixBodyFrame[3][12]; for (uint8_t susNumber = 0; susNumber < 12; susNumber++) { // save the sun vector of each SUS in their body frame into an array for // further processing float* SunVectorBodyFrame = &SunVectorBodyFrame[susNumber]; sunVectorMatrixBodyFrame[0][susNumber] = SunVectorBodyFrame[0]; sunVectorMatrixBodyFrame[1][susNumber] = SunVectorBodyFrame[1]; sunVectorMatrixBodyFrame[2][susNumber] = SunVectorBodyFrame[2]; } for (uint8_t susNumber = 0; susNumber < 12; susNumber++) { if (getValidFlag(susNumber) == returnvalue::FAILED) { susAvail -= 1; } // if the SUS data is not valid -> for (uint8_t c1 = 0; c1 < 3; c1++) { for (uint8_t c2 = 0; c2 < 3; c2++) { switch (susNumber) { case 0: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus0orientationMatrix[c1][c2]; break; case 1: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus1orientationMatrix[c1][c2]; break; case 2: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus2orientationMatrix[c1][c2]; break; case 3: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus3orientationMatrix[c1][c2]; break; case 4: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus4orientationMatrix[c1][c2]; break; case 5: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus5orientationMatrix[c1][c2]; break; case 6: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus6orientationMatrix[c1][c2]; break; case 7: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus7orientationMatrix[c1][c2]; break; case 8: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus8orientationMatrix[c1][c2]; break; case 9: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus9orientationMatrix[c1][c2]; break; case 10: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus10orientationMatrix[c1][c2]; break; case 11: basisMatrixUse[c1][c2] = acsParameters.susHandlingParameters.sus11orientationMatrix[c1][c2]; break; } } } // matrix multiplication for transition in EIVE coordinatesystem for (uint8_t p = 0; p < 3; p++) { for (uint8_t q = 0; q < 3; q++) { // normal matrix multiplication sunVectorMatrixEIVE[p][susNumber] += (basisMatrixUse[p][q] * sunVectorMatrixBodyFrame[q][susNumber]); } } } if (susAvail > 0) { // Calculate one sun vector out of all sun vectors from the different SUS for (uint8_t i = 0; i < 3; i++) { float sum = 0; for (uint8_t susNumber = 0; susNumber < 12; susNumber++) { if (getValidFlag(susNumber) == returnvalue::OK){ sum += sunVectorMatrixEIVE[i][susNumber]; //printf("%f\n", SunVectorMatrixEIVE[i][susNumber]); } } // ToDo: decide on length on sun vector sunVectorEIVE[i] = sum; } VectorOperations::normalize(sunVectorEIVE, sunVectorEIVE, 3); } else { // No sus is valid throw std::invalid_argument("No sun sensor is valid"); // throw error } return sunVectorEIVE; }