Merge branch 'main' into gnss-ctrl-improvements
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit

This commit is contained in:
Marius Eggert 2024-03-18 16:55:04 +01:00
commit 3e1ef8bcaf
13 changed files with 50 additions and 13 deletions

View File

@ -16,6 +16,27 @@ will consitute of a breaking change warranting a new major release:
# [unreleased] # [unreleased]
# [v7.7.3] 2024-03-18
- Bumped `eive-fsfw`
## Added
- Added parameter to disable STR input for MEKF.
## Changed
- If a primary heater is set to `EXTERNAL CONTROL` and `ON`, the `TCS Controller` will no
try to control the temperature of that object.
- Set lower OP limit of `PLOC` to -5°C.
## Fixed
- Added prevention of sign jump for target quaternion of GS pointing, which would reduce the
performance of the controller.
- Heaters set to `EXTERNAL CONTROL` no longer can be switched off by the `TCS Controller`, if
they violate the maximum burn duration of the controller.
# [v7.7.2] 2024-03-06 # [v7.7.2] 2024-03-06
## Fixed ## Fixed

View File

@ -11,7 +11,7 @@ cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR 7) set(OBSW_VERSION_MAJOR 7)
set(OBSW_VERSION_MINOR 7) set(OBSW_VERSION_MINOR 7)
set(OBSW_VERSION_REVISION 2) set(OBSW_VERSION_REVISION 3)
# set(CMAKE_VERBOSE TRUE) # set(CMAKE_VERBOSE TRUE)

2
fsfw

@ -1 +1 @@
Subproject commit 47b21caf5fa2a27c7ace89f960141b3f24c329ee Subproject commit 43ea29cb845d4a7d190c87df490eb53c4992618b

View File

@ -180,7 +180,8 @@ void AcsController::performAttitudeControl() {
mode, &susDataProcessed, &mgmDataProcessed, &gyrDataProcessed, &sensorValues, mode, &susDataProcessed, &mgmDataProcessed, &gyrDataProcessed, &sensorValues,
&attitudeEstimationData, timeDelta, &fusedRotRateSourcesData, &fusedRotRateData); &attitudeEstimationData, timeDelta, &fusedRotRateSourcesData, &fusedRotRateData);
result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed, result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
&susDataProcessed, timeDelta, &attitudeEstimationData); &susDataProcessed, timeDelta, &attitudeEstimationData,
acsParameters.kalmanFilterParameters.allowStr);
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING and if (result != MultiplicativeKalmanFilter::MEKF_RUNNING and
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) { result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {

View File

@ -1641,7 +1641,11 @@ bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch re
bool heaterAvailable = true; bool heaterAvailable = true;
HasHealthIF::HealthState mainHealth = heaterHandler.getHealth(switchNr); HasHealthIF::HealthState mainHealth = heaterHandler.getHealth(switchNr);
heater::SwitchState mainState = heaterHandler.getSwitchState(switchNr);
HasHealthIF::HealthState redHealth = heaterHandler.getHealth(redSwitchNr); HasHealthIF::HealthState redHealth = heaterHandler.getHealth(redSwitchNr);
if (mainHealth == HasHealthIF::EXTERNAL_CONTROL and mainState == heater::SwitchState::ON) {
return false;
}
if (mainHealth != HasHealthIF::HEALTHY) { if (mainHealth != HasHealthIF::HEALTHY) {
if (redHealth == HasHealthIF::HEALTHY) { if (redHealth == HasHealthIF::HEALTHY) {
switchNr = redSwitchNr; switchNr = redSwitchNr;
@ -1656,6 +1660,7 @@ bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch re
} else { } else {
ctrlCtx.redSwitchNrInUse = false; ctrlCtx.redSwitchNrInUse = false;
} }
return heaterAvailable; return heaterAvailable;
} }
@ -1792,7 +1797,8 @@ void ThermalController::heaterMaxDurationControl(
for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) { for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) {
// Right now, we only track the maximum duration for heater which were commanded by the TCS // Right now, we only track the maximum duration for heater which were commanded by the TCS
// controller. // controller.
if (currentHeaterStates[i] == heater::SwitchState::ON and if (heaterHandler.getHealth(static_cast<heater::Switch>(i)) != HasHealthIF::EXTERNAL_CONTROL and
currentHeaterStates[i] == heater::SwitchState::ON and
heaterStates[i].trackHeaterMaxBurnTime and heaterStates[i].trackHeaterMaxBurnTime and
heaterStates[i].heaterOnMaxBurnTime.hasTimedOut()) { heaterStates[i].heaterOnMaxBurnTime.hasTimedOut()) {
heaterStates[i].switchTransition = false; heaterStates[i].switchTransition = false;

View File

@ -197,9 +197,9 @@ class ThermalController : public ExtendedControllerBase {
tcsCtrl::TempLimits pcduAcuLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0); tcsCtrl::TempLimits pcduAcuLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits pcduPduLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0); tcsCtrl::TempLimits pcduPduLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits plPcduBoardLimits = tcsCtrl::TempLimits(-55.0, -40.0, 80.0, 85.0, 125.0); tcsCtrl::TempLimits plPcduBoardLimits = tcsCtrl::TempLimits(-55.0, -40.0, 80.0, 85.0, 125.0);
tcsCtrl::TempLimits plocMissionBoardLimits = tcsCtrl::TempLimits(-30.0, -10.0, 40.0, 45.0, 60); tcsCtrl::TempLimits plocMissionBoardLimits = tcsCtrl::TempLimits(-30.0, -5.0, 40.0, 45.0, 60);
tcsCtrl::TempLimits plocProcessingBoardLimits = tcsCtrl::TempLimits plocProcessingBoardLimits =
tcsCtrl::TempLimits(-30.0, -10.0, 40.0, 45.0, 60.0); tcsCtrl::TempLimits(-30.0, -5.0, 40.0, 45.0, 60.0);
tcsCtrl::TempLimits dacLimits = tcsCtrl::TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0); tcsCtrl::TempLimits dacLimits = tcsCtrl::TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0);
tcsCtrl::TempLimits cameraLimits = tcsCtrl::TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0); tcsCtrl::TempLimits cameraLimits = tcsCtrl::TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0);
tcsCtrl::TempLimits droLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); tcsCtrl::TempLimits droLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);

View File

@ -734,6 +734,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
case 0x5: case 0x5:
parameterWrapper->set(kalmanFilterParameters.sensorNoiseGyrBs); parameterWrapper->set(kalmanFilterParameters.sensorNoiseGyrBs);
break; break;
case 0x6:
parameterWrapper->set(kalmanFilterParameters.allowStr);
break;
default: default:
return INVALID_IDENTIFIER_ID; return INVALID_IDENTIFIER_ID;
} }

View File

@ -947,6 +947,8 @@ class AcsParameters : public HasParametersIF {
double sensorNoiseGyrArw = 3. * 0.0043 / sqrt(10) * DEG2RAD; // Angular Random Walk double sensorNoiseGyrArw = 3. * 0.0043 / sqrt(10) * DEG2RAD; // Angular Random Walk
double sensorNoiseGyrBs = 3. / 3600. * DEG2RAD; // Bias Stability double sensorNoiseGyrBs = 3. / 3600. * DEG2RAD; // Bias Stability
uint8_t allowStr = false;
} kalmanFilterParameters; } kalmanFilterParameters;
struct MagnetorquerParameter { struct MagnetorquerParameter {

View File

@ -244,6 +244,8 @@ void Guidance::limitReferenceRotation(const double xAxisIX[3], double quatIX[4])
return; return;
} }
QuaternionOperations::preventSignJump(quatIX, quatIXprev);
// check required rotation and return if below limit // check required rotation and return if below limit
double quatXprevX[4] = {0, 0, 0, 0}, quatXprevI[4] = {0, 0, 0, 0}; double quatXprevX[4] = {0, 0, 0, 0}, quatXprevI[4] = {0, 0, 0, 0};
QuaternionOperations::inverse(quatIXprev, quatXprevI); QuaternionOperations::inverse(quatIXprev, quatXprevI);

View File

@ -626,11 +626,11 @@ void MultiplicativeKalmanFilter::updateDataSet(
} }
} }
void MultiplicativeKalmanFilter::setStrData(double qX, double qY, double qZ, double qW, void MultiplicativeKalmanFilter::setStrData(double qX, double qY, double qZ, double qW, bool valid,
bool valid) { bool allowStr) {
strData.strQuat.value[0] = qX; strData.strQuat.value[0] = qX;
strData.strQuat.value[1] = qY; strData.strQuat.value[1] = qY;
strData.strQuat.value[2] = qZ; strData.strQuat.value[2] = qZ;
strData.strQuat.value[3] = qW; strData.strQuat.value[3] = qW;
strData.strQuat.valid = valid; strData.strQuat.valid = (valid and allowStr);
} }

View File

@ -38,7 +38,7 @@ class MultiplicativeKalmanFilter {
void updateStandardDeviations(const AcsParameters *acsParameters); void updateStandardDeviations(const AcsParameters *acsParameters);
void setStrData(const double qX, const double qY, const double qZ, const double qW, void setStrData(const double qX, const double qY, const double qZ, const double qW,
const bool valid); const bool valid, const bool allowStr);
static constexpr uint8_t IF_MEKF_ID = CLASS_ID::ACS_MEKF; static constexpr uint8_t IF_MEKF_ID = CLASS_ID::ACS_MEKF;
static constexpr ReturnValue_t MEKF_UNINITIALIZED = returnvalue::makeCode(IF_MEKF_ID, 2); static constexpr ReturnValue_t MEKF_UNINITIALIZED = returnvalue::makeCode(IF_MEKF_ID, 2);

View File

@ -9,11 +9,12 @@ ReturnValue_t Navigation::useMekf(const ACS::SensorValues *sensorValues,
const acsctrl::MgmDataProcessed *mgmDataProcessed, const acsctrl::MgmDataProcessed *mgmDataProcessed,
const acsctrl::SusDataProcessed *susDataProcessed, const acsctrl::SusDataProcessed *susDataProcessed,
const double timeDelta, const double timeDelta,
acsctrl::AttitudeEstimationData *attitudeEstimationData) { acsctrl::AttitudeEstimationData *attitudeEstimationData,
const bool allowStr) {
multiplicativeKalmanFilter.setStrData( multiplicativeKalmanFilter.setStrData(
sensorValues->strSet.caliQx.value, sensorValues->strSet.caliQy.value, sensorValues->strSet.caliQx.value, sensorValues->strSet.caliQy.value,
sensorValues->strSet.caliQz.value, sensorValues->strSet.caliQw.value, sensorValues->strSet.caliQz.value, sensorValues->strSet.caliQw.value,
sensorValues->strSet.caliQx.isValid()); sensorValues->strSet.caliQx.isValid(), allowStr);
if (mekfStatus == MultiplicativeKalmanFilter::MEKF_UNINITIALIZED) { if (mekfStatus == MultiplicativeKalmanFilter::MEKF_UNINITIALIZED) {
mekfStatus = multiplicativeKalmanFilter.init(susDataProcessed, mgmDataProcessed, mekfStatus = multiplicativeKalmanFilter.init(susDataProcessed, mgmDataProcessed,

View File

@ -17,7 +17,8 @@ class Navigation {
const acsctrl::GyrDataProcessed *gyrDataProcessed, const acsctrl::GyrDataProcessed *gyrDataProcessed,
const acsctrl::MgmDataProcessed *mgmDataProcessed, const acsctrl::MgmDataProcessed *mgmDataProcessed,
const acsctrl::SusDataProcessed *susDataProcessed, const double timeDelta, const acsctrl::SusDataProcessed *susDataProcessed, const double timeDelta,
acsctrl::AttitudeEstimationData *attitudeEstimationData); acsctrl::AttitudeEstimationData *attitudeEstimationData,
const bool allowStr);
void resetMekf(acsctrl::AttitudeEstimationData *mekfData); void resetMekf(acsctrl::AttitudeEstimationData *mekfData);
ReturnValue_t useSpg4(timeval now, acsctrl::GpsDataProcessed *gpsDataProcessed); ReturnValue_t useSpg4(timeval now, acsctrl::GpsDataProcessed *gpsDataProcessed);