eive-obsw/mission/controller/acs/control/PtgCtrl.cpp

188 lines
9.0 KiB
C++
Raw Normal View History

2022-09-20 13:43:26 +02:00
#include "PtgCtrl.h"
2022-12-01 15:56:55 +01:00
2022-09-27 11:06:11 +02:00
#include <fsfw/globalfunctions/constants.h>
#include <fsfw/globalfunctions/math/MatrixOperations.h>
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
#include <fsfw/globalfunctions/math/VectorOperations.h>
#include <fsfw/globalfunctions/sign.h>
2022-09-20 13:43:26 +02:00
#include <math.h>
2022-12-01 15:56:55 +01:00
#include "../util/MathOperations.h"
2022-09-20 13:43:26 +02:00
2023-02-28 10:47:37 +01:00
PtgCtrl::PtgCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameters_; }
2022-09-20 13:43:26 +02:00
2022-12-01 15:56:55 +01:00
PtgCtrl::~PtgCtrl() {}
2022-09-20 13:43:26 +02:00
2023-01-23 16:34:52 +01:00
void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters,
2023-02-17 15:57:07 +01:00
const double *errorQuat, const double *deltaRate, const double *rwPseudoInv,
2023-01-23 16:34:52 +01:00
double *torqueRws) {
2022-12-01 15:56:55 +01:00
//------------------------------------------------------------------------------------------------
// Compute gain matrix K and P matrix
//------------------------------------------------------------------------------------------------
2023-01-12 15:19:21 +01:00
double om = pointingLawParameters->om;
double zeta = pointingLawParameters->zeta;
double qErrorMin = pointingLawParameters->qiMin;
double omMax = pointingLawParameters->omMax;
2022-12-01 15:56:55 +01:00
2023-02-17 15:57:07 +01:00
double qError[3] = {errorQuat[0], errorQuat[1], errorQuat[2]};
2022-12-01 15:56:55 +01:00
double cInt = 2 * om * zeta;
double kInt = 2 * pow(om, 2);
double qErrorLaw[3] = {0, 0, 0};
for (int i = 0; i < 3; i++) {
if (abs(qError[i]) < qErrorMin) {
qErrorLaw[i] = qErrorMin;
} else {
qErrorLaw[i] = abs(qError[i]);
}
}
double qErrorLawNorm = VectorOperations<double>::norm(qErrorLaw, 3);
double gain1 = cInt * omMax / qErrorLawNorm;
double gainVector[3] = {0, 0, 0};
VectorOperations<double>::mulScalar(qErrorLaw, gain1, gainVector, 3);
double gainMatrixDiagonal[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
double gainMatrix[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
gainMatrixDiagonal[0][0] = gainVector[0];
gainMatrixDiagonal[1][1] = gainVector[1];
gainMatrixDiagonal[2][2] = gainVector[2];
MatrixOperations<double>::multiply(*gainMatrixDiagonal,
*(acsParameters->inertiaEIVE.inertiaMatrixDeployed),
*gainMatrix, 3, 3, 3);
2022-12-01 15:56:55 +01:00
// Inverse of gainMatrix
double gainMatrixInverse[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
gainMatrixInverse[0][0] = 1 / gainMatrix[0][0];
gainMatrixInverse[1][1] = 1 / gainMatrix[1][1];
gainMatrixInverse[2][2] = 1 / gainMatrix[2][2];
double pMatrix[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
2023-02-28 10:47:37 +01:00
MatrixOperations<double>::multiply(
*gainMatrixInverse, *(acsParameters->inertiaEIVE.inertiaMatrixDeployed), *pMatrix, 3, 3, 3);
2022-12-01 15:56:55 +01:00
MatrixOperations<double>::multiplyScalar(*pMatrix, kInt, *pMatrix, 3, 3);
//------------------------------------------------------------------------------------------------
// Torque Calculations for the reaction wheels
//------------------------------------------------------------------------------------------------
double pError[3] = {0, 0, 0};
MatrixOperations<double>::multiply(*pMatrix, qError, pError, 3, 3, 1);
double pErrorSign[3] = {0, 0, 0};
for (int i = 0; i < 3; i++) {
2022-12-13 11:51:03 +01:00
if (abs(pError[i]) > 1) {
pErrorSign[i] = sign(pError[i]);
} else {
pErrorSign[i] = pError[i];
}
}
2023-03-10 11:39:31 +01:00
// torque for quaternion error
2022-12-13 11:51:03 +01:00
double torqueQuat[3] = {0, 0, 0};
MatrixOperations<double>::multiply(*gainMatrix, pErrorSign, torqueQuat, 3, 3, 1);
VectorOperations<double>::mulScalar(torqueQuat, -1, torqueQuat, 3);
2023-03-10 11:39:31 +01:00
// torque for rate error
2022-12-13 11:51:03 +01:00
double torqueRate[3] = {0, 0, 0};
MatrixOperations<double>::multiply(*(acsParameters->inertiaEIVE.inertiaMatrixDeployed), deltaRate,
2023-02-28 10:47:37 +01:00
torqueRate, 3, 3, 1);
2022-12-13 11:51:03 +01:00
VectorOperations<double>::mulScalar(torqueRate, cInt, torqueRate, 3);
VectorOperations<double>::mulScalar(torqueRate, -1, torqueRate, 3);
2023-03-10 11:39:31 +01:00
// final commanded Torque for every reaction wheel
2022-12-13 11:51:03 +01:00
double torque[3] = {0, 0, 0};
VectorOperations<double>::add(torqueRate, torqueQuat, torque, 3);
MatrixOperations<double>::multiply(rwPseudoInv, torque, torqueRws, 4, 3, 1);
VectorOperations<double>::mulScalar(torqueRws, -1, torqueRws, 4);
2022-09-20 13:43:26 +02:00
}
2023-01-23 16:34:52 +01:00
void PtgCtrl::ptgDesaturation(AcsParameters::PointingLawParameters *pointingLawParameters,
double *magFieldEst, bool magFieldEstValid, double *satRate,
2022-10-12 15:06:24 +02:00
int32_t *speedRw0, int32_t *speedRw1, int32_t *speedRw2,
int32_t *speedRw3, double *mgtDpDes) {
2023-01-12 15:19:21 +01:00
if (!(magFieldEstValid) || !(pointingLawParameters->desatOn)) {
2022-10-12 15:06:24 +02:00
mgtDpDes[0] = 0;
mgtDpDes[1] = 0;
mgtDpDes[2] = 0;
return;
}
2023-03-10 11:39:31 +01:00
// calculating momentum of satellite and momentum of reaction wheels
double speedRws[4] = {(double)*speedRw0, (double)*speedRw1, (double)*speedRw2, (double)*speedRw3};
2022-10-12 15:06:24 +02:00
double momentumRwU[4] = {0, 0, 0, 0}, momentumRw[3] = {0, 0, 0};
2023-02-28 10:47:37 +01:00
VectorOperations<double>::mulScalar(speedRws, acsParameters->rwHandlingParameters.inertiaWheel,
momentumRwU, 4);
MatrixOperations<double>::multiply(*(acsParameters->rwMatrices.alignmentMatrix), momentumRwU,
momentumRw, 3, 4, 1);
2022-10-12 15:06:24 +02:00
double momentumSat[3] = {0, 0, 0}, momentumTotal[3] = {0, 0, 0};
MatrixOperations<double>::multiply(*(acsParameters->inertiaEIVE.inertiaMatrixDeployed), satRate,
2023-02-28 10:47:37 +01:00
momentumSat, 3, 3, 1);
2022-10-12 15:06:24 +02:00
VectorOperations<double>::add(momentumSat, momentumRw, momentumTotal, 3);
2023-03-10 11:39:31 +01:00
// calculating momentum error
2022-10-12 15:06:24 +02:00
double deltaMomentum[3] = {0, 0, 0};
2023-01-23 16:34:52 +01:00
VectorOperations<double>::subtract(momentumTotal, pointingLawParameters->desatMomentumRef,
deltaMomentum, 3);
2023-03-10 11:39:31 +01:00
// resulting magnetic dipole command
2022-10-12 15:06:24 +02:00
double crossMomentumMagField[3] = {0, 0, 0};
VectorOperations<double>::cross(deltaMomentum, magFieldEst, crossMomentumMagField);
double normMag = VectorOperations<double>::norm(magFieldEst, 3), factor = 0;
2023-01-12 15:19:21 +01:00
factor = (pointingLawParameters->deSatGainFactor) / normMag;
2022-10-12 15:06:24 +02:00
VectorOperations<double>::mulScalar(crossMomentumMagField, factor, mgtDpDes, 3);
2022-09-20 13:43:26 +02:00
}
2023-01-23 16:34:52 +01:00
void PtgCtrl::ptgNullspace(AcsParameters::PointingLawParameters *pointingLawParameters,
const int32_t *speedRw0, const int32_t *speedRw1,
2022-10-12 15:06:24 +02:00
const int32_t *speedRw2, const int32_t *speedRw3, double *rwTrqNs) {
double speedRws[4] = {(double)*speedRw0, (double)*speedRw1, (double)*speedRw2, (double)*speedRw3};
2022-10-12 15:06:24 +02:00
double wheelMomentum[4] = {0, 0, 0, 0};
double rpmOffset[4] = {1, 1, 1, -1}, factor = 350 * 2 * Math::PI / 60;
2023-03-10 11:39:31 +01:00
// conversion to [rad/s] for further calculations
2022-10-12 15:06:24 +02:00
VectorOperations<double>::mulScalar(rpmOffset, factor, rpmOffset, 4);
VectorOperations<double>::mulScalar(speedRws, 2 * Math::PI / 60, speedRws, 4);
double diffRwSpeed[4] = {0, 0, 0, 0};
VectorOperations<double>::subtract(speedRws, rpmOffset, diffRwSpeed, 4);
2023-02-28 10:47:37 +01:00
VectorOperations<double>::mulScalar(diffRwSpeed, acsParameters->rwHandlingParameters.inertiaWheel,
2022-10-12 15:06:24 +02:00
wheelMomentum, 4);
2023-01-12 15:19:21 +01:00
double gainNs = pointingLawParameters->gainNullspace;
2022-10-12 15:06:24 +02:00
double nullSpaceMatrix[4][4] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
2023-02-28 10:47:37 +01:00
MathOperations<double>::vecTransposeVecMatrix(acsParameters->rwMatrices.nullspace,
acsParameters->rwMatrices.nullspace,
2022-10-12 15:06:24 +02:00
*nullSpaceMatrix, 4);
MatrixOperations<double>::multiply(*nullSpaceMatrix, wheelMomentum, rwTrqNs, 4, 4, 1);
VectorOperations<double>::mulScalar(rwTrqNs, gainNs, rwTrqNs, 4);
VectorOperations<double>::mulScalar(rwTrqNs, -1, rwTrqNs, 4);
2022-09-20 13:43:26 +02:00
}
2023-03-10 17:21:52 +01:00
void PtgCtrl::rwAntistiction(ACS::SensorValues *sensorValues, int32_t *rwCmdSpeeds) {
bool rwAvailable[4] = {
(sensorValues->rw1Set.state.value && sensorValues->rw1Set.state.isValid()),
(sensorValues->rw2Set.state.value && sensorValues->rw2Set.state.isValid()),
(sensorValues->rw3Set.state.value && sensorValues->rw3Set.state.isValid()),
(sensorValues->rw4Set.state.value && sensorValues->rw4Set.state.isValid())};
2023-03-10 17:21:52 +01:00
int32_t currRwSpeed[4] = {
sensorValues->rw1Set.currSpeed.value, sensorValues->rw2Set.currSpeed.value,
sensorValues->rw3Set.currSpeed.value, sensorValues->rw4Set.currSpeed.value};
2022-12-13 11:51:03 +01:00
for (uint8_t i = 0; i < 4; i++) {
if (rwAvailable[i]) {
2023-03-10 17:21:52 +01:00
if (rwCmdSpeeds[i] != 0) {
if (rwCmdSpeeds[i] > -acsParameters->rwHandlingParameters.stictionSpeed &&
rwCmdSpeeds[i] < acsParameters->rwHandlingParameters.stictionSpeed) {
if (currRwSpeed[i] == 0) {
if (rwCmdSpeeds[i] > 0) {
rwCmdSpeeds[i] = acsParameters->rwHandlingParameters.stictionSpeed;
} else if (rwCmdSpeeds[i] < 0) {
rwCmdSpeeds[i] = -acsParameters->rwHandlingParameters.stictionSpeed;
}
} else if (currRwSpeed[i] < -acsParameters->rwHandlingParameters.stictionSpeed) {
rwCmdSpeeds[i] = acsParameters->rwHandlingParameters.stictionSpeed;
} else if (currRwSpeed[i] > acsParameters->rwHandlingParameters.stictionSpeed) {
rwCmdSpeeds[i] = -acsParameters->rwHandlingParameters.stictionSpeed;
2022-12-13 11:51:03 +01:00
}
}
}
}
}
}