shameless copy of FLP code
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit

This commit is contained in:
Marius Eggert 2023-03-21 17:19:27 +01:00
parent 2be5cdabb0
commit d00cfc420c
2 changed files with 66 additions and 76 deletions

View File

@ -4,6 +4,7 @@
#include <fsfw/globalfunctions/math/MatrixOperations.h> #include <fsfw/globalfunctions/math/MatrixOperations.h>
#include <fsfw/globalfunctions/math/QuaternionOperations.h> #include <fsfw/globalfunctions/math/QuaternionOperations.h>
#include <fsfw/globalfunctions/math/VectorOperations.h> #include <fsfw/globalfunctions/math/VectorOperations.h>
#include <fsfw/globalfunctions/sign.h>
#include <math.h> #include <math.h>
#include "../util/MathOperations.h" #include "../util/MathOperations.h"
@ -70,89 +71,72 @@ ReturnValue_t SafeCtrl::safeMekf(timeval now, double *quatBJ, bool quatBJValid,
return returnvalue::OK; return returnvalue::OK;
} }
// Will be the version in worst case scenario in event of no working MEKF (nor GYRs) // Will be the version in worst case scenario in event of no working MEKF
ReturnValue_t SafeCtrl::safeNoMekf(timeval now, double *susDirB, bool susDirBValid, ReturnValue_t SafeCtrl::safeNoMekf(const double *magneticFieldVector,
double *sunRateB, bool sunRateBValid, double *magFieldB, const double *magneticFieldVectorDerivative,
bool magFieldBValid, double *magRateB, bool magRateBValid, const double *sunVector, const double *sunvectorDerivative,
double *sunDirRef, double *satRateRef, double *outputAngle, double omegaRef, double *torqueCommand, double *spinAxis) {
double *outputMagMomB) { if (0) {
// Check for invalid Inputs
if (!susDirBValid || !magFieldBValid || !magRateBValid) {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
// change unit from uT to T double magneticFieldVectorT[3] = {0, 0, 0};
double magFieldBT[3] = {0, 0, 0}; VectorOperations<double>::mulScalar(magneticFieldVector, 1e-6, magneticFieldVectorT, 3);
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
// normalize sunDir and magDir double commandParallel[3] = {0, 0, 0}, commandAlign[3] = {0, 0, 0}, commandOrtho[3] = {0, 0, 0};
double magDirB[3] = {0, 0, 0};
VectorOperations<double>::normalize(magFieldBT, magDirB, 3);
VectorOperations<double>::normalize(susDirB, susDirB, 3);
// Cosinus angle between sunDir and magDir bool valid;
double cosAngleSunMag = VectorOperations<double>::dot(magDirB, susDirB); double omega = estimateRotationAroundSun(magneticFieldVector, magneticFieldVectorDerivative,
sunVector, &valid);
// Rate parallel to sun direction and magnetic field direction if (valid) {
double dotSunRateMag = VectorOperations<double>::dot(sunRateB, magDirB); VectorOperations<double>::mulScalar(
double dotmagRateSun = VectorOperations<double>::dot(magRateB, susDirB); sunVector,
double rateFactor = 1 - pow(cosAngleSunMag, 2); acsParameters->safeModeControllerParameters.k_parallel_no_mekf * (omegaRef - omega),
double rateParaSun = (dotmagRateSun + cosAngleSunMag * dotSunRateMag) / rateFactor; commandParallel, 3);
double rateParaMag = (dotSunRateMag + cosAngleSunMag * dotmagRateSun) / rateFactor; omega = omega * sign<double>(omega);
// Full rate or estimate
double estSatRate[3] = {0, 0, 0};
double estSatRateMag[3] = {0, 0, 0}, estSatRateSun[3] = {0, 0, 0};
VectorOperations<double>::mulScalar(susDirB, rateParaSun, estSatRateSun, 3);
VectorOperations<double>::add(sunRateB, estSatRateSun, estSatRateSun, 3);
VectorOperations<double>::mulScalar(magDirB, rateParaMag, estSatRateMag, 3);
VectorOperations<double>::add(magRateB, estSatRateMag, estSatRateMag, 3);
VectorOperations<double>::add(estSatRateSun, estSatRateMag, estSatRate, 3);
VectorOperations<double>::mulScalar(estSatRate, 0.5, estSatRate, 3);
/* Only valid if angle between sun direction and magnetic field direction
* is sufficiently large */
double angleSunMag = acos(cosAngleSunMag);
if (angleSunMag < acsParameters->safeModeControllerParameters.sunMagAngleMin) {
return returnvalue::FAILED;
} }
// Rate for Torque Calculation VectorOperations<double>::cross(spinAxis, sunVector, commandAlign);
double diffRate[3] = {0, 0, 0}; /* ADD TO MONITORING */
VectorOperations<double>::subtract(estSatRate, satRateRef, diffRate, 3);
// Torque Align calculation VectorOperations<double>::mulScalar(
double kRateNoMekf = acsParameters->safeModeControllerParameters.k_rate_no_mekf; commandAlign, acsParameters->safeModeControllerParameters.k_align_no_mekf, commandAlign, 3);
double kAlignNoMekf = acsParameters->safeModeControllerParameters.k_align_no_mekf;
double cosAngleAlignErr = VectorOperations<double>::dot(sunDirRef, susDirB); VectorOperations<double>::cross(sunvectorDerivative, sunVector, commandOrtho);
double crossSusSunRef[3] = {0, 0, 0}; VectorOperations<double>::mulScalar(
VectorOperations<double>::cross(sunDirRef, susDirB, crossSusSunRef); commandOrtho, -acsParameters->safeModeControllerParameters.k_ortho_no_mekf, commandOrtho, 3);
double sinAngleAlignErr = VectorOperations<double>::norm(crossSusSunRef, 3);
double torqueAlign[3] = {0, 0, 0}; // only spin up when the angle to the sun is less than a certain angle.
double angleAlignErr = acos(cosAngleAlignErr); // note that we check the cosin, thus "<"
double torqueAlignFactor = kAlignNoMekf * angleAlignErr / sinAngleAlignErr; if (VectorOperations<double>::dot(spinAxis, sunVector) <
VectorOperations<double>::mulScalar(crossSusSunRef, torqueAlignFactor, torqueAlign, 3); acsParameters->safeModeControllerParameters.cosineStartSpin) {
VectorOperations<double>::mulScalar(commandParallel, 0, commandParallel, 3);
}
// Torque Rate Calculations for (uint8_t i = 0; i < 3; i++) {
double torqueRate[3] = {0, 0, 0}; torqueCommand[i] = commandAlign[i] + commandOrtho[i] + commandParallel[i];
VectorOperations<double>::mulScalar(diffRate, -kRateNoMekf, torqueRate, 3); }
// Final torque
double torqueB[3] = {0, 0, 0}, torqueAlignRate[3] = {0, 0, 0};
VectorOperations<double>::add(torqueRate, torqueAlign, torqueAlignRate, 3);
MatrixOperations<double>::multiply(*(acsParameters->inertiaEIVE.inertiaMatrix), torqueAlignRate,
torqueB, 3, 3, 1);
// Magnetic moment
double magMomB[3] = {0, 0, 0};
double crossMagFieldTorque[3] = {0, 0, 0};
VectorOperations<double>::cross(magFieldBT, torqueB, crossMagFieldTorque);
double magMomFactor = pow(VectorOperations<double>::norm(magFieldBT, 3), 2);
VectorOperations<double>::mulScalar(crossMagFieldTorque, 1 / magMomFactor, magMomB, 3);
std::memcpy(outputMagMomB, magMomB, 3 * sizeof(double));
*outputAngle = angleAlignErr;
return returnvalue::OK; return returnvalue::OK;
} }
double SafeCtrl::estimateRotationAroundSun(const double *magneticFieldVector,
const double *magneticFieldVectorDerivative,
const double *sunVector, bool *updated) {
*updated = true;
double vector[3];
VectorOperations<double>::cross(magneticFieldVector, sunVector, vector);
float magLength = VectorOperations<double>::norm(magneticFieldVector, 3);
float length = VectorOperations<double>::norm(vector, 3);
// only check if angle between B and sun is large enough
if (length > (acsParameters->safeModeControllerParameters.sineCalculateOmegaSun * magLength)) {
float omega = VectorOperations<double>::dot(magneticFieldVectorDerivative, vector);
omega = omega / (length * length);
lastCalculatedOmega = omega;
return omega;
} else {
*updated = false;
return lastCalculatedOmega;
}
}

View File

@ -23,10 +23,14 @@ class SafeCtrl {
double *satRatRef, // From Guidance (!) double *satRatRef, // From Guidance (!)
double *outputAngle, double *outputMagMomB); double *outputAngle, double *outputMagMomB);
ReturnValue_t safeNoMekf(timeval now, double *susDirB, bool susDirBValid, double *sunRateB, ReturnValue_t safeNoMekf(const double *magneticFieldVector,
bool sunRateBValid, double *magFieldB, bool magFieldBValid, const double *magneticFieldVectorDerivative, const double *sunVector,
double *magRateB, bool magRateBValid, double *sunDirRef, const double *sunvectorDerivative, double omegaRef,
double *satRateRef, double *outputAngle, double *outputMagMomB); double *torqueCommand, double *spinAxis);
double estimateRotationAroundSun(const double *magneticFieldVector,
const double *magneticFieldVectorDerivative,
const double *sunvector, bool *updated);
protected: protected:
private: private:
@ -35,6 +39,8 @@ class SafeCtrl {
double magFieldBState[3]; double magFieldBState[3];
timeval magFieldBStateTime; timeval magFieldBStateTime;
float lastCalculatedOmega = 0.0;
}; };
#endif /* ACS_CONTROL_SAFECTRL_H_ */ #endif /* ACS_CONTROL_SAFECTRL_H_ */