#include "AttitudeEstimation.h" AttitudeEstimation::AttitudeEstimation(AcsParameters *acsParameters_) { acsParameters = acsParameters_; } AttitudeEstimation::~AttitudeEstimation() {} void AttitudeEstimation::quest(acsctrl::SusDataProcessed *susData, acsctrl::MgmDataProcessed *mgmData, acsctrl::AttitudeEstimationData *attitudeEstimationData) { if (not(susData->susVecTot.isValid() and susData->sunIjkModel.isValid() and mgmData->mgmVecTot.isValid() and mgmData->magIgrfModel.isValid())) { { PoolReadGuard pg{attitudeEstimationData}; if (pg.getReadResult() == returnvalue::OK) { std::memcpy(attitudeEstimationData->quatQuest.value, ZERO_VEC4, 4 * sizeof(double)); attitudeEstimationData->quatQuest.setValid(false); } } return; } // Normalize Data double normMgmB[3] = {0, 0, 0}, normMgmI[3] = {0, 0, 0}, normSusB[3] = {0, 0, 0}, normSusI[3] = {0, 0, 0}; VectorOperations::normalize(susData->susVecTot.value, normSusB, 3); VectorOperations::normalize(susData->sunIjkModel.value, normSusI, 3); VectorOperations::normalize(mgmData->mgmVecTot.value, normMgmB, 3); VectorOperations::normalize(mgmData->magIgrfModel.value, normMgmI, 3); if ((std::acos(VectorOperations::dot(normSusB, normMgmB)) < acsParameters->onBoardParams.questAngleLimit) or (std::acos(VectorOperations::dot(normSusI, normMgmI)) < acsParameters->onBoardParams.questAngleLimit)) { { PoolReadGuard pg{attitudeEstimationData}; if (pg.getReadResult() == returnvalue::OK) { std::memcpy(attitudeEstimationData->quatQuest.value, ZERO_VEC4, 4 * sizeof(double)); attitudeEstimationData->quatQuest.setValid(false); } } return; } // Create Helper Vectors double normHelperB[3] = {0, 0, 0}, normHelperI[3] = {0, 0, 0}, helperCross[3] = {0, 0, 0}, helperSum[3] = {0, 0, 0}; VectorOperations::cross(normSusB, normMgmB, normHelperB); VectorOperations::cross(normSusI, normMgmI, normHelperI); VectorOperations::normalize(normHelperB, normHelperB, 3); VectorOperations::normalize(normHelperI, normHelperI, 3); VectorOperations::cross(normHelperB, normHelperI, helperCross); VectorOperations::add(normHelperB, normHelperI, helperSum, 3); // Sensor Weights double kSus = 0, kMgm = 0; kSus = std::pow(acsParameters->kalmanFilterParameters.sensorNoiseSus, -2); kMgm = std::pow(acsParameters->kalmanFilterParameters.sensorNoiseMgm, -2); // Weighted Vectors double weightedSusB[3] = {0, 0, 0}, weightedMgmB[3] = {0, 0, 0}, kSusVec[3] = {0, 0, 0}, kMgmVec[3] = {0, 0, 0}, kSumVec[3] = {0, 0, 0}; VectorOperations::mulScalar(normSusB, kSus, weightedSusB, 3); VectorOperations::mulScalar(normMgmB, kMgm, weightedMgmB, 3); VectorOperations::cross(weightedSusB, normSusI, kSusVec); VectorOperations::cross(weightedMgmB, normMgmI, kMgmVec); VectorOperations::add(kSusVec, kMgmVec, kSumVec, 3); // Some weird Angles double alpha = (1 + VectorOperations::dot(normHelperB, normHelperI)) * (VectorOperations::dot(weightedSusB, normSusI) + VectorOperations::dot(weightedMgmB, normMgmI)) + VectorOperations::dot(helperCross, kSumVec); double beta = VectorOperations::dot(helperSum, kSumVec); double gamma = std::sqrt(std::pow(alpha, 2) + std::pow(beta, 2)); // I don't even know what this is supposed to be double constPlus = 1. / (2 * std::sqrt(gamma * (gamma + alpha) * (1 + VectorOperations::dot(normHelperB, normHelperI)))); double constMinus = 1. / (2 * std::sqrt(gamma * (gamma - alpha) * (1 + VectorOperations::dot(normHelperB, normHelperI)))); // Calculate Quaternion double qBI[4] = {0, 0, 0, 0}, qRotVecTot[3] = {0, 0, 0}, qRotVecPt0[3] = {0, 0, 0}, qRotVecPt1[3] = {0, 0, 0}; if (alpha >= 0) { // Scalar Part qBI[3] = (gamma + alpha) * (1 + VectorOperations::dot(normHelperB, normHelperI)); // Rotational Vector Part VectorOperations::mulScalar(helperCross, gamma + alpha, qRotVecPt0, 3); VectorOperations::mulScalar(helperSum, beta, qRotVecPt1, 3); VectorOperations::add(qRotVecPt0, qRotVecPt1, qRotVecTot, 3); std::memcpy(qBI, qRotVecTot, sizeof(qRotVecTot)); VectorOperations::mulScalar(qBI, constPlus, qBI, 4); QuaternionOperations::normalize(qBI, qBI); } else { // Scalar Part qBI[3] = (beta) * (1 + VectorOperations::dot(normHelperB, normHelperI)); // Rotational Vector Part VectorOperations::mulScalar(helperCross, beta, qRotVecPt0, 3); VectorOperations::mulScalar(helperSum, gamma - alpha, qRotVecPt1, 3); VectorOperations::add(qRotVecPt0, qRotVecPt1, qRotVecTot, 3); std::memcpy(qBI, qRotVecTot, sizeof(qRotVecTot)); VectorOperations::mulScalar(qBI, constMinus, qBI, 4); QuaternionOperations::normalize(qBI, qBI); } // Low Pass if (VectorOperations::norm(qOld, 4) != 0.0) { QuaternionOperations::slerp(qBI, qOld, acsParameters->onBoardParams.questFilterWeight, qBI); } { PoolReadGuard pg{attitudeEstimationData}; if (pg.getReadResult() == returnvalue::OK) { std::memcpy(attitudeEstimationData->quatQuest.value, qBI, 4 * sizeof(double)); attitudeEstimationData->quatQuest.setValid(true); } } }