shameless copy of FLP code
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit
This commit is contained in:
parent
2be5cdabb0
commit
d00cfc420c
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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_ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user