Merge remote-tracking branch 'origin/main' into small-scex-fix
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
This commit is contained in:
commit
5615f51ae7
@ -2,7 +2,7 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CMakeSharedSettings">
|
<component name="CMakeSharedSettings">
|
||||||
<configurations>
|
<configurations>
|
||||||
<configuration PROFILE_NAME="Debug Q7S" ENABLED="true" CONFIG_NAME="Debug" TOOLCHAIN_NAME="Q7S" GENERATION_OPTIONS="-DTGT_BSP="arm/q7s"" NO_GENERATOR="true">
|
<configuration PROFILE_NAME="Debug Q7S" ENABLED="true" CONFIG_NAME="Debug" TOOLCHAIN_NAME="Default" GENERATION_OPTIONS="-DTGT_BSP="arm/q7s"" NO_GENERATOR="true">
|
||||||
<ADDITIONAL_GENERATION_ENVIRONMENT>
|
<ADDITIONAL_GENERATION_ENVIRONMENT>
|
||||||
<envs>
|
<envs>
|
||||||
<env name="ZYNQ_7020_ROOTFS" value="/opt/xiphos/sdk/ark/sysroots/cortexa9hf-neon-xiphos-linux-gnueabi" />
|
<env name="ZYNQ_7020_ROOTFS" value="/opt/xiphos/sdk/ark/sysroots/cortexa9hf-neon-xiphos-linux-gnueabi" />
|
||||||
@ -10,6 +10,7 @@
|
|||||||
</envs>
|
</envs>
|
||||||
</ADDITIONAL_GENERATION_ENVIRONMENT>
|
</ADDITIONAL_GENERATION_ENVIRONMENT>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" NO_GENERATOR="true" />
|
||||||
</configurations>
|
</configurations>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
16
CHANGELOG.md
16
CHANGELOG.md
@ -16,6 +16,10 @@ will consitute of a breaking change warranting a new major release:
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
|
# [v6.2.0] 2023-07-26
|
||||||
|
|
||||||
|
- `eive-tmtc`: v5.3.1
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
- STR missed reply handling is now moved to DHB rather than the COM interface. The COM IF will
|
- STR missed reply handling is now moved to DHB rather than the COM interface. The COM IF will
|
||||||
@ -24,6 +28,15 @@ will consitute of a breaking change warranting a new major release:
|
|||||||
- Re-ordered some functions of the core controller in the initialize function.
|
- Re-ordered some functions of the core controller in the initialize function.
|
||||||
- Rad sensor is now only polled every 30 minutes instead of every device cycle to reduce wear of
|
- Rad sensor is now only polled every 30 minutes instead of every device cycle to reduce wear of
|
||||||
the RADFET electronics.
|
the RADFET electronics.
|
||||||
|
- The SD cards will still be switched OFF on a reboot, but this is done in a non-blocking manner
|
||||||
|
now with a timeout of 10 seconds where the reboot will be performed in any case.
|
||||||
|
- ACS Controller now includes the safe mode from FLP, which will calculate its rotational rate
|
||||||
|
from SUS and MGM measurements. To accommodate these changes, low-pass filters for SUS
|
||||||
|
measurements and rates as well as MGM measurements and rates are included. Usage of the new
|
||||||
|
controller as well as settings of the low-pass filters can be handled via parameter commands.
|
||||||
|
- Simplify and fix the chip and copy protection functions in the core controller. This mechanism
|
||||||
|
now is always performed for the target chip and target copy in the reboot handlers.
|
||||||
|
- Improvement in FSFW: HK generation is now countdown based.
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
@ -41,6 +54,9 @@ will consitute of a breaking change warranting a new major release:
|
|||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
- General bugs in the SD card state machine. This might fix some other known bugs for certain
|
||||||
|
combinations of switching ON and OFF SD cards and also makes the whole state machine a lot more
|
||||||
|
robust against hanging up.
|
||||||
- SUS dummy handler went to `MODE_NORMAL` for ON commands.
|
- SUS dummy handler went to `MODE_NORMAL` for ON commands.
|
||||||
- PL PCDU dummy went to `MODE_NORMAL` for ON commands.
|
- PL PCDU dummy went to `MODE_NORMAL` for ON commands.
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
set(OBSW_VERSION_MAJOR 6)
|
set(OBSW_VERSION_MAJOR 6)
|
||||||
set(OBSW_VERSION_MINOR 1)
|
set(OBSW_VERSION_MINOR 2)
|
||||||
set(OBSW_VERSION_REVISION 0)
|
set(OBSW_VERSION_REVISION 0)
|
||||||
|
|
||||||
# set(CMAKE_VERBOSE TRUE)
|
# set(CMAKE_VERBOSE TRUE)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 301 translations.
|
* @brief Auto-generated event translation file. Contains 301 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-07-21 11:04:23
|
* Generated on: 2023-07-26 12:51:20
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 171 translations.
|
* Contains 171 translations.
|
||||||
* Generated on: 2023-07-21 11:04:23
|
* Generated on: 2023-07-26 12:51:20
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
|
@ -218,15 +218,30 @@ void Q7STestTask::testProtHandler() {
|
|||||||
bool opPerformed = false;
|
bool opPerformed = false;
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
// If any chips are unlocked, lock them here
|
// If any chips are unlocked, lock them here
|
||||||
result = coreController->setBootCopyProtection(xsc::Chip::ALL_CHIP, xsc::Copy::ALL_COPY, true,
|
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_0, xsc::Copy::COPY_0,
|
||||||
opPerformed, true);
|
true);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||||
|
}
|
||||||
|
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_0, xsc::Copy::COPY_1,
|
||||||
|
true);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||||
|
}
|
||||||
|
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_0,
|
||||||
|
true);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||||
|
}
|
||||||
|
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
|
||||||
|
true);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unlock own copy
|
// unlock own copy
|
||||||
result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, false,
|
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::SELF_CHIP,
|
||||||
opPerformed, true);
|
xsc::Copy::SELF_COPY, false);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||||
}
|
}
|
||||||
@ -239,8 +254,8 @@ void Q7STestTask::testProtHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lock own copy
|
// lock own copy
|
||||||
result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
|
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::SELF_CHIP,
|
||||||
opPerformed, true);
|
xsc::Copy::SELF_COPY, true);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||||
}
|
}
|
||||||
@ -253,8 +268,8 @@ void Q7STestTask::testProtHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unlock specific copy
|
// unlock specific copy
|
||||||
result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, false,
|
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
|
||||||
opPerformed, true);
|
false);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||||
}
|
}
|
||||||
@ -267,8 +282,8 @@ void Q7STestTask::testProtHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lock specific copy
|
// lock specific copy
|
||||||
result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, true,
|
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
|
||||||
opPerformed, true);
|
true);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -554,21 +554,24 @@ ReturnValue_t CoreController::sdStateMachine() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This lambda checks the non-blocking operation of the SD card manager and assigns the new
|
// This lambda checks the non-blocking operation of the SD card manager and assigns the new
|
||||||
// state on success. It returns true for an operation success and false otherwise
|
// state on success. It returns 0 for an operation success, -1 for failed operations, and 1
|
||||||
|
// for pending operations
|
||||||
auto nonBlockingSdcOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount,
|
auto nonBlockingSdcOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount,
|
||||||
std::string opPrintout) {
|
std::string opPrintout) {
|
||||||
SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation);
|
SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation);
|
||||||
if (status == SdCardManager::OpStatus::SUCCESS) {
|
if (status == SdCardManager::OpStatus::SUCCESS or sdInfo.cycleCount > maxCycleCount) {
|
||||||
sdFsmState = newStateOnSuccess;
|
sdFsmState = newStateOnSuccess;
|
||||||
sdInfo.commandPending = false;
|
sdInfo.commandPending = false;
|
||||||
|
if (sdInfo.cycleCount > maxCycleCount) {
|
||||||
|
sif::warning << "CoreController::sdStateMachine: " << opPrintout << " takes too long"
|
||||||
|
<< std::endl;
|
||||||
|
sdInfo.cycleCount = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
sdInfo.cycleCount = 0;
|
sdInfo.cycleCount = 0;
|
||||||
return true;
|
return 0;
|
||||||
} else if (sdInfo.cycleCount > 4) {
|
};
|
||||||
sif::warning << "CoreController::sdStateMachine: " << opPrintout << " takes too long"
|
return 1;
|
||||||
<< std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sdFsmState == SdStates::UPDATE_SD_INFO_START) {
|
if (sdFsmState == SdStates::UPDATE_SD_INFO_START) {
|
||||||
@ -644,7 +647,7 @@ ReturnValue_t CoreController::sdStateMachine() {
|
|||||||
sdFsmState = tgtState;
|
sdFsmState = tgtState;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) {
|
if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state") <= 0) {
|
||||||
sdInfo.activeState = sd::SdState::ON;
|
sdInfo.activeState = sd::SdState::ON;
|
||||||
currentStateSetter(sdInfo.active, sd::SdState::ON);
|
currentStateSetter(sdInfo.active, sd::SdState::ON);
|
||||||
// Skip the two cycles now.
|
// Skip the two cycles now.
|
||||||
@ -672,7 +675,7 @@ ReturnValue_t CoreController::sdStateMachine() {
|
|||||||
result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar);
|
result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar);
|
||||||
sdInfo.commandPending = true;
|
sdInfo.commandPending = true;
|
||||||
} else {
|
} else {
|
||||||
if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) {
|
if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card") <= 0) {
|
||||||
sdcMan->setActiveSdCard(sdInfo.active);
|
sdcMan->setActiveSdCard(sdInfo.active);
|
||||||
currMntPrefix = sdcMan->getCurrentMountPrefix();
|
currMntPrefix = sdcMan->getCurrentMountPrefix();
|
||||||
sdInfo.activeState = sd::SdState::MOUNTED;
|
sdInfo.activeState = sd::SdState::MOUNTED;
|
||||||
@ -714,12 +717,7 @@ ReturnValue_t CoreController::sdStateMachine() {
|
|||||||
sdInfo.commandPending = true;
|
sdInfo.commandPending = true;
|
||||||
} else {
|
} else {
|
||||||
if (nonBlockingSdcOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10,
|
if (nonBlockingSdcOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10,
|
||||||
"Switching off other SD card")) {
|
"Switching off other SD card") <= 0) {
|
||||||
sdInfo.otherState = sd::SdState::OFF;
|
|
||||||
currentStateSetter(sdInfo.other, sd::SdState::OFF);
|
|
||||||
} else {
|
|
||||||
// Continue.. avoid being stuck here..
|
|
||||||
sdFsmState = SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE;
|
|
||||||
sdInfo.otherState = sd::SdState::OFF;
|
sdInfo.otherState = sd::SdState::OFF;
|
||||||
currentStateSetter(sdInfo.other, sd::SdState::OFF);
|
currentStateSetter(sdInfo.other, sd::SdState::OFF);
|
||||||
}
|
}
|
||||||
@ -730,12 +728,7 @@ ReturnValue_t CoreController::sdStateMachine() {
|
|||||||
sdInfo.commandPending = true;
|
sdInfo.commandPending = true;
|
||||||
} else {
|
} else {
|
||||||
if (nonBlockingSdcOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10,
|
if (nonBlockingSdcOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10,
|
||||||
"Switching on other SD card")) {
|
"Switching on other SD card") <= 0) {
|
||||||
sdInfo.otherState = sd::SdState::ON;
|
|
||||||
currentStateSetter(sdInfo.other, sd::SdState::ON);
|
|
||||||
} else {
|
|
||||||
// Contnue.. avoid being stuck here.
|
|
||||||
sdFsmState = SdStates::MOUNT_UNMOUNT_OTHER;
|
|
||||||
sdInfo.otherState = sd::SdState::ON;
|
sdInfo.otherState = sd::SdState::ON;
|
||||||
currentStateSetter(sdInfo.other, sd::SdState::ON);
|
currentStateSetter(sdInfo.other, sd::SdState::ON);
|
||||||
}
|
}
|
||||||
@ -750,7 +743,8 @@ ReturnValue_t CoreController::sdStateMachine() {
|
|||||||
result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar);
|
result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar);
|
||||||
sdInfo.commandPending = true;
|
sdInfo.commandPending = true;
|
||||||
} else {
|
} else {
|
||||||
if (nonBlockingSdcOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) {
|
if (nonBlockingSdcOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card") <=
|
||||||
|
0) {
|
||||||
sdInfo.otherState = sd::SdState::ON;
|
sdInfo.otherState = sd::SdState::ON;
|
||||||
currentStateSetter(sdInfo.other, sd::SdState::ON);
|
currentStateSetter(sdInfo.other, sd::SdState::ON);
|
||||||
} else {
|
} else {
|
||||||
@ -764,7 +758,8 @@ ReturnValue_t CoreController::sdStateMachine() {
|
|||||||
result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar);
|
result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar);
|
||||||
sdInfo.commandPending = true;
|
sdInfo.commandPending = true;
|
||||||
} else {
|
} else {
|
||||||
if (nonBlockingSdcOpChecking(SdStates::UPDATE_SD_INFO_END, 4, "Mounting other SD card")) {
|
if (nonBlockingSdcOpChecking(SdStates::UPDATE_SD_INFO_END, 4, "Mounting other SD card") <=
|
||||||
|
0) {
|
||||||
sdInfo.otherState = sd::SdState::MOUNTED;
|
sdInfo.otherState = sd::SdState::MOUNTED;
|
||||||
currentStateSetter(sdInfo.other, sd::SdState::MOUNTED);
|
currentStateSetter(sdInfo.other, sd::SdState::MOUNTED);
|
||||||
}
|
}
|
||||||
@ -840,7 +835,7 @@ ReturnValue_t CoreController::sdCardSetup(sd::SdCard sdCard, sd::SdState targetS
|
|||||||
if (state == sd::SdState::MOUNTED) {
|
if (state == sd::SdState::MOUNTED) {
|
||||||
if (targetState == sd::SdState::OFF) {
|
if (targetState == sd::SdState::OFF) {
|
||||||
sif::info << "Switching off SD card " << sdChar << std::endl;
|
sif::info << "Switching off SD card " << sdChar << std::endl;
|
||||||
return sdcMan->switchOffSdCard(sdCard, true, &sdInfo.currentState);
|
return sdcMan->switchOffSdCard(sdCard, sdInfo.currentState, true);
|
||||||
} else if (targetState == sd::SdState::ON) {
|
} else if (targetState == sd::SdState::ON) {
|
||||||
sif::info << "Unmounting SD card " << sdChar << std::endl;
|
sif::info << "Unmounting SD card " << sdChar << std::endl;
|
||||||
return sdcMan->unmountSdCard(sdCard);
|
return sdcMan->unmountSdCard(sdCard);
|
||||||
@ -874,7 +869,7 @@ ReturnValue_t CoreController::sdCardSetup(sd::SdCard sdCard, sd::SdState targetS
|
|||||||
return sdcMan->mountSdCard(sdCard);
|
return sdcMan->mountSdCard(sdCard);
|
||||||
} else if (targetState == sd::SdState::OFF) {
|
} else if (targetState == sd::SdState::OFF) {
|
||||||
sif::info << "Switching off SD card " << sdChar << std::endl;
|
sif::info << "Switching off SD card " << sdChar << std::endl;
|
||||||
return sdcMan->switchOffSdCard(sdCard, false, &sdInfo.currentState);
|
return sdcMan->switchOffSdCard(sdCard, sdInfo.currentState, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sif::warning << "CoreController::sdCardSetup: Invalid state for this call" << std::endl;
|
sif::warning << "CoreController::sdCardSetup: Invalid state for this call" << std::endl;
|
||||||
@ -898,8 +893,7 @@ ReturnValue_t CoreController::sdColdRedundantBlockingInit() {
|
|||||||
sif::info << "Switching off secondary SD card " << sdInfo.otherChar << std::endl;
|
sif::info << "Switching off secondary SD card " << sdInfo.otherChar << std::endl;
|
||||||
// Switch off other SD card in cold redundant mode if setting up preferred one worked
|
// Switch off other SD card in cold redundant mode if setting up preferred one worked
|
||||||
// without issues
|
// without issues
|
||||||
ReturnValue_t result2 =
|
ReturnValue_t result2 = sdcMan->switchOffSdCard(sdInfo.other, sdInfo.currentState, true);
|
||||||
sdcMan->switchOffSdCard(sdInfo.other, sdInfo.otherState, &sdInfo.currentState);
|
|
||||||
if (result2 != returnvalue::OK and result2 != SdCardManager::ALREADY_OFF) {
|
if (result2 != returnvalue::OK and result2 != SdCardManager::ALREADY_OFF) {
|
||||||
sif::warning << "Switching off secondary SD card " << sdInfo.otherChar
|
sif::warning << "Switching off secondary SD card " << sdInfo.otherChar
|
||||||
<< " in cold redundant mode failed" << std::endl;
|
<< " in cold redundant mode failed" << std::endl;
|
||||||
@ -1229,18 +1223,25 @@ ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy co
|
|||||||
// Ensure that all writes/reads do finish.
|
// Ensure that all writes/reads do finish.
|
||||||
sync();
|
sync();
|
||||||
|
|
||||||
// Attempt graceful shutdown by unmounting and switching off SD cards
|
// Unmount and switch off SD cards. This could possibly fix issues with the SD card and is
|
||||||
sdcMan->switchOffSdCard(sd::SdCard::SLOT_0);
|
// the more graceful way to reboot the system. This function takes around 400 ms.
|
||||||
sdcMan->switchOffSdCard(sd::SdCard::SLOT_1);
|
ReturnValue_t result = handleSwitchingSdCardsOffNonBlocking();
|
||||||
// If any boot copies are unprotected.
|
if (result != returnvalue::OK) {
|
||||||
// Actually this function only ensures that reboots to the own image are protected..
|
sif::error
|
||||||
ReturnValue_t result = setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
|
<< "CoreController::gracefulShutdownTasks: Issues unmounting or switching SD cards off"
|
||||||
protOpPerformed, false);
|
<< std::endl;
|
||||||
if (result == returnvalue::OK and protOpPerformed) {
|
}
|
||||||
|
|
||||||
|
// Ensure that the target chip is writeprotected in any case.
|
||||||
|
bool wasProtected = handleBootCopyProt(chip, copy, true);
|
||||||
|
if (wasProtected) {
|
||||||
// TODO: Would be nice to notify operator. But we can't use the filesystem anymore
|
// TODO: Would be nice to notify operator. But we can't use the filesystem anymore
|
||||||
// and a reboot is imminent. Use scratch buffer?
|
// and a reboot is imminent. Use scratch buffer?
|
||||||
sif::info << "Running slot was writeprotected before reboot" << std::endl;
|
sif::info << "Running slot was writeprotected before reboot" << std::endl;
|
||||||
}
|
}
|
||||||
|
sif::info << "Graceful shutdown handling done" << std::endl;
|
||||||
|
// Ensure that all diagnostic prinouts arrive.
|
||||||
|
TaskFactory::delayTask(50);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1274,144 +1275,50 @@ ReturnValue_t CoreController::generateChipStateFile() {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CoreController::setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy,
|
ReturnValue_t CoreController::setBootCopyProtectionAndUpdateFile(xsc::Chip targetChip,
|
||||||
bool protect, bool &protOperationPerformed,
|
xsc::Copy targetCopy,
|
||||||
bool updateProtFile) {
|
bool protect) {
|
||||||
bool allChips = false;
|
if (targetChip == xsc::Chip::ALL_CHIP or targetCopy == xsc::Copy::ALL_COPY) {
|
||||||
bool allCopies = false;
|
return returnvalue::FAILED;
|
||||||
bool selfChip = false;
|
|
||||||
bool selfCopy = false;
|
|
||||||
protOperationPerformed = false;
|
|
||||||
|
|
||||||
switch (targetChip) {
|
|
||||||
case (xsc::Chip::ALL_CHIP): {
|
|
||||||
allChips = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (xsc::Chip::NO_CHIP): {
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
case (xsc::Chip::SELF_CHIP): {
|
|
||||||
selfChip = true;
|
|
||||||
targetChip = CURRENT_CHIP;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (targetCopy) {
|
|
||||||
case (xsc::Copy::ALL_COPY): {
|
|
||||||
allCopies = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (xsc::Copy::NO_COPY): {
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
case (xsc::Copy::SELF_COPY): {
|
|
||||||
selfCopy = true;
|
|
||||||
targetCopy = CURRENT_COPY;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t arrIdx = 0; arrIdx < protArray.size(); arrIdx++) {
|
bool protOperationPerformed = handleBootCopyProt(targetChip, targetCopy, protect);
|
||||||
int result = handleBootCopyProtAtIndex(targetChip, targetCopy, protect, protOperationPerformed,
|
if (protOperationPerformed) {
|
||||||
selfChip, selfCopy, allChips, allCopies, arrIdx);
|
|
||||||
if (result != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (protOperationPerformed and updateProtFile) {
|
|
||||||
updateProtInfo();
|
updateProtInfo();
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CoreController::handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy,
|
bool CoreController::handleBootCopyProt(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect) {
|
||||||
bool protect, bool &protOperationPerformed,
|
|
||||||
bool selfChip, bool selfCopy, bool allChips,
|
|
||||||
bool allCopies, uint8_t arrIdx) {
|
|
||||||
bool currentProt = protArray[arrIdx];
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
bool performOp = false;
|
|
||||||
if (protect == currentProt) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (protOperationPerformed) {
|
|
||||||
if ((selfChip and selfCopy) or (not allCopies and not allChips)) {
|
|
||||||
// No need to continue, only one operation was requested
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xsc::Chip currentChip;
|
|
||||||
xsc::Copy currentCopy;
|
|
||||||
oss << "writeprotect ";
|
oss << "writeprotect ";
|
||||||
if (arrIdx == 0 or arrIdx == 1) {
|
if (targetChip == xsc::Chip::SELF_CHIP) {
|
||||||
oss << "0 ";
|
targetChip = CURRENT_CHIP;
|
||||||
currentChip = xsc::Chip::CHIP_0;
|
|
||||||
} else {
|
|
||||||
oss << "1 ";
|
|
||||||
currentChip = xsc::Chip::CHIP_1;
|
|
||||||
}
|
}
|
||||||
if (arrIdx == 0 or arrIdx == 2) {
|
if (targetCopy == xsc::Copy::SELF_COPY) {
|
||||||
|
targetCopy = CURRENT_COPY;
|
||||||
|
}
|
||||||
|
if (targetChip == xsc::Chip::CHIP_0) {
|
||||||
oss << "0 ";
|
oss << "0 ";
|
||||||
currentCopy = xsc::Copy::COPY_0;
|
} else if (targetChip == xsc::Chip::CHIP_1) {
|
||||||
} else {
|
oss << "1 ";
|
||||||
|
}
|
||||||
|
if (targetCopy == xsc::Copy::COPY_0) {
|
||||||
|
oss << "0 ";
|
||||||
|
} else if (targetCopy == xsc::Copy::COPY_1) {
|
||||||
oss << "1 ";
|
oss << "1 ";
|
||||||
currentCopy = xsc::Copy::COPY_1;
|
|
||||||
}
|
}
|
||||||
if (protect) {
|
if (protect) {
|
||||||
oss << "1";
|
oss << "1";
|
||||||
} else {
|
} else {
|
||||||
oss << "0";
|
oss << "0";
|
||||||
}
|
}
|
||||||
|
sif::info << "Executing command: " << oss.str() << std::endl;
|
||||||
int result = 0;
|
int result = std::system(oss.str().c_str());
|
||||||
if (allChips and allCopies) {
|
if (result == 0) {
|
||||||
performOp = true;
|
return true;
|
||||||
} else if (allChips) {
|
|
||||||
if ((selfCopy and CURRENT_COPY == targetCopy) or (currentCopy == targetCopy)) {
|
|
||||||
performOp = true;
|
|
||||||
}
|
|
||||||
} else if (allCopies) {
|
|
||||||
if ((selfChip and CURRENT_COPY == targetCopy) or (currentChip == targetChip)) {
|
|
||||||
performOp = true;
|
|
||||||
}
|
|
||||||
} else if (selfChip and (currentChip == targetChip)) {
|
|
||||||
if (selfCopy) {
|
|
||||||
if (currentCopy == targetCopy) {
|
|
||||||
performOp = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
performOp = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (selfCopy and (currentCopy == targetCopy)) {
|
|
||||||
if (selfChip) {
|
|
||||||
if (currentChip == targetChip) {
|
|
||||||
performOp = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
performOp = true;
|
|
||||||
}
|
|
||||||
} else if ((targetChip == currentChip) and (targetCopy == currentCopy)) {
|
|
||||||
performOp = true;
|
|
||||||
}
|
}
|
||||||
if (result != 0) {
|
return false;
|
||||||
utility::handleSystemError(result, "CoreController::checkAndSetBootCopyProtection");
|
|
||||||
}
|
|
||||||
if (performOp) {
|
|
||||||
// TODO: Lock operation take a long time. Use command executor? That would require a
|
|
||||||
// new state machine..
|
|
||||||
protOperationPerformed = true;
|
|
||||||
sif::info << "Executing command: " << oss.str() << std::endl;
|
|
||||||
result = std::system(oss.str().c_str());
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CoreController::updateProtInfo(bool regenerateChipStateFile) {
|
ReturnValue_t CoreController::updateProtInfo(bool regenerateChipStateFile) {
|
||||||
@ -1456,7 +1363,6 @@ ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) {
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
string word;
|
string word;
|
||||||
uint8_t wordIdx = 0;
|
uint8_t wordIdx = 0;
|
||||||
uint8_t arrayIdx = 0;
|
|
||||||
istringstream iss(nextLine);
|
istringstream iss(nextLine);
|
||||||
xsc::Chip currentChip = xsc::Chip::CHIP_0;
|
xsc::Chip currentChip = xsc::Chip::CHIP_0;
|
||||||
xsc::Copy currentCopy = xsc::Copy::COPY_0;
|
xsc::Copy currentCopy = xsc::Copy::COPY_0;
|
||||||
@ -1468,28 +1374,11 @@ ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) {
|
|||||||
currentCopy = static_cast<xsc::Copy>(stoi(word));
|
currentCopy = static_cast<xsc::Copy>(stoi(word));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wordIdx == 3) {
|
|
||||||
if (currentChip == xsc::Chip::CHIP_0) {
|
|
||||||
if (currentCopy == xsc::Copy::COPY_0) {
|
|
||||||
arrayIdx = 0;
|
|
||||||
} else if (currentCopy == xsc::Copy::COPY_1) {
|
|
||||||
arrayIdx = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (currentChip == xsc::Chip::CHIP_1) {
|
|
||||||
if (currentCopy == xsc::Copy::COPY_0) {
|
|
||||||
arrayIdx = 2;
|
|
||||||
} else if (currentCopy == xsc::Copy::COPY_1) {
|
|
||||||
arrayIdx = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (wordIdx == 5) {
|
if (wordIdx == 5) {
|
||||||
if (word == "unlocked.") {
|
if (word == "unlocked.") {
|
||||||
protArray[arrayIdx] = false;
|
protArray[currentChip][currentCopy] = false;
|
||||||
} else {
|
} else {
|
||||||
protArray[arrayIdx] = true;
|
protArray[currentChip][currentCopy] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wordIdx++;
|
wordIdx++;
|
||||||
@ -2583,6 +2472,57 @@ void CoreController::announceSdInfo(SdCardManager::SdStatePair sdStates) {
|
|||||||
triggerEvent(core::ACTIVE_SD_INFO, p1, p2);
|
triggerEvent(core::ACTIVE_SD_INFO, p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CoreController::handleSwitchingSdCardsOffNonBlocking() {
|
||||||
|
sdcMan->setBlocking(false);
|
||||||
|
SdCardManager::Operations op;
|
||||||
|
std::pair<sd::SdState, sd::SdState> sdStatus;
|
||||||
|
ReturnValue_t result = sdcMan->getSdCardsStatus(sdStatus);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
Countdown maxWaitTimeCd(10000);
|
||||||
|
// Stopwatch watch;
|
||||||
|
auto waitingForFinish = [&]() {
|
||||||
|
auto currentState = sdcMan->checkCurrentOp(op);
|
||||||
|
if (currentState == SdCardManager::OpStatus::IDLE) {
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
while (currentState == SdCardManager::OpStatus::ONGOING) {
|
||||||
|
if (maxWaitTimeCd.hasTimedOut()) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
TaskFactory::delayTask(50);
|
||||||
|
currentState = sdcMan->checkCurrentOp(op);
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
};
|
||||||
|
if (sdStatus.first != sd::SdState::OFF) {
|
||||||
|
sdcMan->unmountSdCard(sd::SdCard::SLOT_0);
|
||||||
|
result = waitingForFinish();
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
sdcMan->switchOffSdCard(sd::SdCard::SLOT_0, sdStatus, false);
|
||||||
|
result = waitingForFinish();
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sdStatus.second != sd::SdState::OFF) {
|
||||||
|
sdcMan->unmountSdCard(sd::SdCard::SLOT_1);
|
||||||
|
result = waitingForFinish();
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
sdcMan->switchOffSdCard(sd::SdCard::SLOT_1, sdStatus, false);
|
||||||
|
result = waitingForFinish();
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool CoreController::isNumber(const std::string &s) {
|
bool CoreController::isNumber(const std::string &s) {
|
||||||
return !s.empty() && std::find_if(s.begin(), s.end(),
|
return !s.empty() && std::find_if(s.begin(), s.end(),
|
||||||
[](unsigned char c) { return !std::isdigit(c); }) == s.end();
|
[](unsigned char c) { return !std::isdigit(c); }) == s.end();
|
||||||
|
@ -199,8 +199,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
|||||||
* @param updateProtFile Specify whether the protection info file is updated
|
* @param updateProtFile Specify whether the protection info file is updated
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
|
ReturnValue_t setBootCopyProtectionAndUpdateFile(xsc::Chip targetChip, xsc::Copy targetCopy,
|
||||||
bool& protOperationPerformed, bool updateProtFile = true);
|
bool protect);
|
||||||
|
|
||||||
bool sdInitFinished() const;
|
bool sdInitFinished() const;
|
||||||
|
|
||||||
@ -304,12 +304,10 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
|||||||
Countdown sdCardCheckCd = Countdown(INIT_SD_CARD_CHECK_TIMEOUT);
|
Countdown sdCardCheckCd = Countdown(INIT_SD_CARD_CHECK_TIMEOUT);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Index 0: Chip 0 Copy 0
|
* First index: Chip.
|
||||||
* Index 1: Chip 0 Copy 1
|
* Second index: Copy.
|
||||||
* Index 2: Chip 1 Copy 0
|
|
||||||
* Index 3: Chip 1 Copy 1
|
|
||||||
*/
|
*/
|
||||||
std::array<bool, 4> protArray;
|
bool protArray[2][2]{};
|
||||||
PeriodicOperationDivider opDivider5;
|
PeriodicOperationDivider opDivider5;
|
||||||
PeriodicOperationDivider opDivider10;
|
PeriodicOperationDivider opDivider10;
|
||||||
|
|
||||||
@ -374,9 +372,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
|||||||
ReturnValue_t gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy, bool& protOpPerformed);
|
ReturnValue_t gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy, bool& protOpPerformed);
|
||||||
|
|
||||||
ReturnValue_t handleProtInfoUpdateLine(std::string nextLine);
|
ReturnValue_t handleProtInfoUpdateLine(std::string nextLine);
|
||||||
int handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
|
ReturnValue_t handleSwitchingSdCardsOffNonBlocking();
|
||||||
bool& protOperationPerformed, bool selfChip, bool selfCopy,
|
bool handleBootCopyProt(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect);
|
||||||
bool allChips, bool allCopies, uint8_t arrIdx);
|
|
||||||
void rebootWatchdogAlgorithm(RebootWatchdogFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
|
void rebootWatchdogAlgorithm(RebootWatchdogFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
|
||||||
xsc::Copy& tgtCopy);
|
xsc::Copy& tgtCopy);
|
||||||
void resetRebootWatchdogCounters(xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
void resetRebootWatchdogCounters(xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
||||||
|
@ -124,6 +124,8 @@ void ObjectFactory::produce(void* args) {
|
|||||||
if (core::FW_VERSION_MAJOR >= 4) {
|
if (core::FW_VERSION_MAJOR >= 4) {
|
||||||
battAndImtqI2cDev = q7s::I2C_PS_EIVE;
|
battAndImtqI2cDev = q7s::I2C_PS_EIVE;
|
||||||
}
|
}
|
||||||
|
static_cast<void>(battAndImtqI2cDev);
|
||||||
|
|
||||||
#if OBSW_ADD_MGT == 1
|
#if OBSW_ADD_MGT == 1
|
||||||
createImtqComponents(pwrSwitcher, enableHkSets, battAndImtqI2cDev);
|
createImtqComponents(pwrSwitcher, enableHkSets, battAndImtqI2cDev);
|
||||||
#endif
|
#endif
|
||||||
|
@ -125,13 +125,8 @@ ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard, bool doMountSdCar
|
|||||||
return mountSdCard(sdCard);
|
return mountSdCard(sdCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard,
|
ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, SdStatePair& sdStates,
|
||||||
SdStatePair* statusPair) {
|
bool doUnmountSdCard) {
|
||||||
std::pair<sd::SdState, sd::SdState> active;
|
|
||||||
ReturnValue_t result = getSdCardsStatus(active);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (doUnmountSdCard) {
|
if (doUnmountSdCard) {
|
||||||
if (not blocking) {
|
if (not blocking) {
|
||||||
sif::warning << "SdCardManager::switchOffSdCard: Two-step command but manager is"
|
sif::warning << "SdCardManager::switchOffSdCard: Two-step command but manager is"
|
||||||
@ -147,17 +142,17 @@ ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSd
|
|||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
if (sdCard == sd::SdCard::SLOT_0) {
|
if (sdCard == sd::SdCard::SLOT_0) {
|
||||||
if (active.first == sd::SdState::OFF) {
|
if (sdStates.first == sd::SdState::OFF) {
|
||||||
return ALREADY_OFF;
|
return ALREADY_OFF;
|
||||||
}
|
}
|
||||||
} else if (sdCard == sd::SdCard::SLOT_1) {
|
} else if (sdCard == sd::SdCard::SLOT_1) {
|
||||||
if (active.second == sd::SdState::OFF) {
|
if (sdStates.second == sd::SdState::OFF) {
|
||||||
return ALREADY_OFF;
|
return ALREADY_OFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doUnmountSdCard) {
|
if (doUnmountSdCard) {
|
||||||
result = unmountSdCard(sdCard);
|
ReturnValue_t result = unmountSdCard(sdCard);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -189,7 +184,7 @@ ReturnValue_t SdCardManager::setSdCardState(sd::SdCard sdCard, bool on) {
|
|||||||
command << "q7hw sd set " << sdstring << " " << statestring;
|
command << "q7hw sd set " << sdstring << " " << statestring;
|
||||||
cmdExecutor.load(command.str(), blocking, printCmdOutput);
|
cmdExecutor.load(command.str(), blocking, printCmdOutput);
|
||||||
ReturnValue_t result = cmdExecutor.execute();
|
ReturnValue_t result = cmdExecutor.execute();
|
||||||
if (blocking and result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::setSdCardState");
|
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::setSdCardState");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -204,6 +199,7 @@ ReturnValue_t SdCardManager::getSdCardsStatus(SdStatePair& sdStates) {
|
|||||||
ReturnValue_t SdCardManager::mountSdCard(sd::SdCard sdCard) {
|
ReturnValue_t SdCardManager::mountSdCard(sd::SdCard sdCard) {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
||||||
|
sif::warning << "SdCardManager::mountSdCard: Command still pending" << std::endl;
|
||||||
return CommandExecutor::COMMAND_PENDING;
|
return CommandExecutor::COMMAND_PENDING;
|
||||||
}
|
}
|
||||||
if (sdCard == sd::SdCard::BOTH) {
|
if (sdCard == sd::SdCard::BOTH) {
|
||||||
|
@ -114,8 +114,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
|
|||||||
* @return - returnvalue::OK on success, ALREADY_ON if it is already on,
|
* @return - returnvalue::OK on success, ALREADY_ON if it is already on,
|
||||||
* SYSTEM_CALL_ERROR on system error
|
* SYSTEM_CALL_ERROR on system error
|
||||||
*/
|
*/
|
||||||
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true,
|
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, SdStatePair& sdStates, bool doUnmountSdCard);
|
||||||
SdStatePair* statusPair = nullptr);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the state of the SD cards. If the state file does not exist, this function will
|
* Get the state of the SD cards. If the state file does not exist, this function will
|
||||||
|
@ -273,7 +273,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
|||||||
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
|
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
|
||||||
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
|
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
|
||||||
14013;0x36bd;FIRMWARE_INFO;INFO;Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h
|
14013;0x36bd;FIRMWARE_INFO;INFO;Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h
|
||||||
14014;0x36be;ACTIVE_SD_INFO;INFO;Active SD card info. 0: OFF, 1: ON, 2: MOUNTED. P1: SD Card 0, P2: SD Card 1.;mission/sysDefs.h
|
14014;0x36be;ACTIVE_SD_INFO;INFO;Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1;mission/sysDefs.h
|
||||||
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h
|
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||||
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
|
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||||
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||||
|
|
@ -273,7 +273,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
|||||||
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
|
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
|
||||||
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
|
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
|
||||||
14013;0x36bd;FIRMWARE_INFO;INFO;Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h
|
14013;0x36bd;FIRMWARE_INFO;INFO;Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h
|
||||||
14014;0x36be;ACTIVE_SD_INFO;INFO;Active SD card info. 0: OFF, 1: ON, 2: MOUNTED. P1: SD Card 0, P2: SD Card 1.;mission/sysDefs.h
|
14014;0x36be;ACTIVE_SD_INFO;INFO;Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1;mission/sysDefs.h
|
||||||
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h
|
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||||
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
|
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||||
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 301 translations.
|
* @brief Auto-generated event translation file. Contains 301 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-07-21 11:04:23
|
* Generated on: 2023-07-26 12:51:20
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 175 translations.
|
* Contains 175 translations.
|
||||||
* Generated on: 2023-07-21 11:04:23
|
* Generated on: 2023-07-26 12:51:20
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 301 translations.
|
* @brief Auto-generated event translation file. Contains 301 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-07-21 11:04:23
|
* Generated on: 2023-07-26 12:51:20
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 175 translations.
|
* Contains 175 translations.
|
||||||
* Generated on: 2023-07-21 11:04:23
|
* Generated on: 2023-07-26 12:51:20
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
|
@ -26,10 +26,18 @@ enum SafeModeStrategy : uint8_t {
|
|||||||
SAFECTRL_OFF = 0,
|
SAFECTRL_OFF = 0,
|
||||||
SAFECTRL_NO_MAG_FIELD_FOR_CONTROL = 1,
|
SAFECTRL_NO_MAG_FIELD_FOR_CONTROL = 1,
|
||||||
SAFECTRL_NO_SENSORS_FOR_CONTROL = 2,
|
SAFECTRL_NO_SENSORS_FOR_CONTROL = 2,
|
||||||
SAFECTRL_ACTIVE_MEKF = 10,
|
// OBSW version <= v6.1.0
|
||||||
SAFECTRL_WITHOUT_MEKF = 11,
|
LEGACY_SAFECTRL_ACTIVE_MEKF = 10,
|
||||||
SAFECTRL_ECLIPSE_DAMPING = 12,
|
LEGACY_SAFECTRL_WITHOUT_MEKF = 11,
|
||||||
SAFECTRL_ECLIPSE_IDELING = 13,
|
LEGACY_SAFECTRL_ECLIPSE_DAMPING = 12,
|
||||||
|
LEGACY_SAFECTRL_ECLIPSE_IDELING = 13,
|
||||||
|
// Added in v6.2.0
|
||||||
|
SAFECTRL_MEKF = 14,
|
||||||
|
SAFECTRL_GYR = 15,
|
||||||
|
SAFECTRL_SUSMGM = 16,
|
||||||
|
SAFECTRL_ECLIPSE_DAMPING_GYR = 17,
|
||||||
|
SAFECTRL_ECLIPSE_DAMPING_SUSMGM = 18,
|
||||||
|
SAFECTRL_ECLIPSE_IDELING = 19,
|
||||||
SAFECTRL_DETUMBLE_FULL = 20,
|
SAFECTRL_DETUMBLE_FULL = 20,
|
||||||
SAFECTRL_DETUMBLE_DETERIORATED = 21,
|
SAFECTRL_DETUMBLE_DETERIORATED = 21,
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
AcsController::AcsController(object_id_t objectId, bool enableHkSets)
|
AcsController::AcsController(object_id_t objectId, bool enableHkSets)
|
||||||
: ExtendedControllerBase(objectId),
|
: ExtendedControllerBase(objectId),
|
||||||
enableHkSets(enableHkSets),
|
enableHkSets(enableHkSets),
|
||||||
|
fusedRotationEstimation(&acsParameters),
|
||||||
guidance(&acsParameters),
|
guidance(&acsParameters),
|
||||||
safeCtrl(&acsParameters),
|
safeCtrl(&acsParameters),
|
||||||
ptgCtrl(&acsParameters),
|
ptgCtrl(&acsParameters),
|
||||||
@ -20,7 +21,8 @@ AcsController::AcsController(object_id_t objectId, bool enableHkSets)
|
|||||||
gpsDataProcessed(this),
|
gpsDataProcessed(this),
|
||||||
mekfData(this),
|
mekfData(this),
|
||||||
ctrlValData(this),
|
ctrlValData(this),
|
||||||
actuatorCmdData(this) {}
|
actuatorCmdData(this),
|
||||||
|
fusedRotRateData(this) {}
|
||||||
|
|
||||||
ReturnValue_t AcsController::initialize() {
|
ReturnValue_t AcsController::initialize() {
|
||||||
ReturnValue_t result = parameterHelper.initialize();
|
ReturnValue_t result = parameterHelper.initialize();
|
||||||
@ -146,6 +148,8 @@ void AcsController::performSafe() {
|
|||||||
|
|
||||||
sensorProcessing.process(now, &sensorValues, &mgmDataProcessed, &susDataProcessed,
|
sensorProcessing.process(now, &sensorValues, &mgmDataProcessed, &susDataProcessed,
|
||||||
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
||||||
|
fusedRotationEstimation.estimateFusedRotationRateSafe(&susDataProcessed, &mgmDataProcessed,
|
||||||
|
&gyrDataProcessed, &fusedRotRateData);
|
||||||
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||||
&susDataProcessed, &mekfData, &acsParameters);
|
&susDataProcessed, &mekfData, &acsParameters);
|
||||||
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
||||||
@ -172,25 +176,42 @@ void AcsController::performSafe() {
|
|||||||
acs::SafeModeStrategy safeCtrlStrat = safeCtrl.safeCtrlStrategy(
|
acs::SafeModeStrategy safeCtrlStrat = safeCtrl.safeCtrlStrategy(
|
||||||
mgmDataProcessed.mgmVecTot.isValid(), not mekfInvalidFlag,
|
mgmDataProcessed.mgmVecTot.isValid(), not mekfInvalidFlag,
|
||||||
gyrDataProcessed.gyrVecTot.isValid(), susDataProcessed.susVecTot.isValid(),
|
gyrDataProcessed.gyrVecTot.isValid(), susDataProcessed.susVecTot.isValid(),
|
||||||
|
fusedRotRateData.rotRateOrthogonal.isValid(), fusedRotRateData.rotRateTotal.isValid(),
|
||||||
acsParameters.safeModeControllerParameters.useMekf,
|
acsParameters.safeModeControllerParameters.useMekf,
|
||||||
|
acsParameters.safeModeControllerParameters.useGyr,
|
||||||
acsParameters.safeModeControllerParameters.dampingDuringEclipse);
|
acsParameters.safeModeControllerParameters.dampingDuringEclipse);
|
||||||
switch (safeCtrlStrat) {
|
switch (safeCtrlStrat) {
|
||||||
case (acs::SafeModeStrategy::SAFECTRL_ACTIVE_MEKF):
|
case (acs::SafeModeStrategy::SAFECTRL_MEKF):
|
||||||
safeCtrl.safeMekf(mgmDataProcessed.mgmVecTot.value, mekfData.satRotRateMekf.value,
|
safeCtrl.safeMekf(mgmDataProcessed.mgmVecTot.value, mekfData.satRotRateMekf.value,
|
||||||
susDataProcessed.sunIjkModel.value, mekfData.quatMekf.value, sunTargetDir,
|
susDataProcessed.sunIjkModel.value, mekfData.quatMekf.value, sunTargetDir,
|
||||||
magMomMtq, errAng);
|
magMomMtq, errAng);
|
||||||
safeCtrlFailureFlag = false;
|
safeCtrlFailureFlag = false;
|
||||||
safeCtrlFailureCounter = 0;
|
safeCtrlFailureCounter = 0;
|
||||||
break;
|
break;
|
||||||
case (acs::SafeModeStrategy::SAFECTRL_WITHOUT_MEKF):
|
case (acs::SafeModeStrategy::SAFECTRL_GYR):
|
||||||
safeCtrl.safeNonMekf(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
|
safeCtrl.safeGyr(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
|
||||||
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
|
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
|
||||||
safeCtrlFailureFlag = false;
|
safeCtrlFailureFlag = false;
|
||||||
safeCtrlFailureCounter = 0;
|
safeCtrlFailureCounter = 0;
|
||||||
break;
|
break;
|
||||||
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING):
|
case (acs::SafeModeStrategy::SAFECTRL_SUSMGM):
|
||||||
safeCtrl.safeRateDamping(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
|
safeCtrl.safeSusMgm(mgmDataProcessed.mgmVecTot.value, fusedRotRateData.rotRateParallel.value,
|
||||||
sunTargetDir, magMomMtq, errAng);
|
fusedRotRateData.rotRateOrthogonal.value,
|
||||||
|
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
|
||||||
|
safeCtrlFailureFlag = false;
|
||||||
|
safeCtrlFailureCounter = 0;
|
||||||
|
break;
|
||||||
|
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_GYR):
|
||||||
|
safeCtrl.safeRateDampingGyr(mgmDataProcessed.mgmVecTot.value,
|
||||||
|
gyrDataProcessed.gyrVecTot.value, sunTargetDir, magMomMtq,
|
||||||
|
errAng);
|
||||||
|
safeCtrlFailureFlag = false;
|
||||||
|
safeCtrlFailureCounter = 0;
|
||||||
|
break;
|
||||||
|
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_SUSMGM):
|
||||||
|
safeCtrl.safeRateDampingSusMgm(mgmDataProcessed.mgmVecTot.value,
|
||||||
|
fusedRotRateData.rotRateTotal.value, sunTargetDir, magMomMtq,
|
||||||
|
errAng);
|
||||||
safeCtrlFailureFlag = false;
|
safeCtrlFailureFlag = false;
|
||||||
safeCtrlFailureCounter = 0;
|
safeCtrlFailureCounter = 0;
|
||||||
break;
|
break;
|
||||||
@ -214,12 +235,20 @@ void AcsController::performSafe() {
|
|||||||
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
|
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
|
||||||
|
|
||||||
// detumble check and switch
|
// detumble check and switch
|
||||||
if (mekfData.satRotRateMekf.isValid() && acsParameters.safeModeControllerParameters.useMekf &&
|
if (acsParameters.safeModeControllerParameters.useMekf) {
|
||||||
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) >
|
if (mekfData.satRotRateMekf.isValid() and
|
||||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) >
|
||||||
detumbleCounter++;
|
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||||
} else if (gyrDataProcessed.gyrVecTot.isValid() &&
|
detumbleCounter++;
|
||||||
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) >
|
}
|
||||||
|
} else if (acsParameters.safeModeControllerParameters.useGyr) {
|
||||||
|
if (gyrDataProcessed.gyrVecTot.isValid() and
|
||||||
|
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) >
|
||||||
|
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||||
|
detumbleCounter++;
|
||||||
|
}
|
||||||
|
} else if (fusedRotRateData.rotRateTotal.isValid() and
|
||||||
|
VectorOperations<double>::norm(fusedRotRateData.rotRateTotal.value, 3) >
|
||||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||||
detumbleCounter++;
|
detumbleCounter++;
|
||||||
} else if (detumbleCounter > 0) {
|
} else if (detumbleCounter > 0) {
|
||||||
@ -289,17 +318,26 @@ void AcsController::performDetumble() {
|
|||||||
actuatorCmd.cmdDipoleMtq(*acsParameters.magnetorquerParameter.inverseAlignment,
|
actuatorCmd.cmdDipoleMtq(*acsParameters.magnetorquerParameter.inverseAlignment,
|
||||||
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
|
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
|
||||||
|
|
||||||
if (mekfData.satRotRateMekf.isValid() &&
|
if (acsParameters.safeModeControllerParameters.useMekf) {
|
||||||
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) <
|
if (mekfData.satRotRateMekf.isValid() and
|
||||||
acsParameters.detumbleParameter.omegaDetumbleEnd) {
|
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) <
|
||||||
detumbleCounter++;
|
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||||
} else if (gyrDataProcessed.gyrVecTot.isValid() &&
|
detumbleCounter++;
|
||||||
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) <
|
}
|
||||||
acsParameters.detumbleParameter.omegaDetumbleEnd) {
|
} else if (acsParameters.safeModeControllerParameters.useGyr) {
|
||||||
|
if (gyrDataProcessed.gyrVecTot.isValid() and
|
||||||
|
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) <
|
||||||
|
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||||
|
detumbleCounter++;
|
||||||
|
}
|
||||||
|
} else if (fusedRotRateData.rotRateTotal.isValid() and
|
||||||
|
VectorOperations<double>::norm(fusedRotRateData.rotRateTotal.value, 3) <
|
||||||
|
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||||
detumbleCounter++;
|
detumbleCounter++;
|
||||||
} else if (detumbleCounter > 0) {
|
} else if (detumbleCounter > 0) {
|
||||||
detumbleCounter -= 1;
|
detumbleCounter -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detumbleCounter > acsParameters.detumbleParameter.detumblecounter) {
|
if (detumbleCounter > acsParameters.detumbleParameter.detumblecounter) {
|
||||||
detumbleCounter = 0;
|
detumbleCounter = 0;
|
||||||
// Triggers safe mode transition in subsystem
|
// Triggers safe mode transition in subsystem
|
||||||
@ -707,6 +745,11 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
|
|||||||
localDataPoolMap.emplace(acsctrl::PoolIds::RW_TARGET_SPEED, &rwTargetSpeed);
|
localDataPoolMap.emplace(acsctrl::PoolIds::RW_TARGET_SPEED, &rwTargetSpeed);
|
||||||
localDataPoolMap.emplace(acsctrl::PoolIds::MTQ_TARGET_DIPOLE, &mtqTargetDipole);
|
localDataPoolMap.emplace(acsctrl::PoolIds::MTQ_TARGET_DIPOLE, &mtqTargetDipole);
|
||||||
poolManager.subscribeForRegularPeriodicPacket({actuatorCmdData.getSid(), enableHkSets, 10.0});
|
poolManager.subscribeForRegularPeriodicPacket({actuatorCmdData.getSid(), enableHkSets, 10.0});
|
||||||
|
// Fused Rot Rate
|
||||||
|
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_ORTHOGONAL, &rotRateOrthogonal);
|
||||||
|
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_PARALLEL, &rotRateParallel);
|
||||||
|
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_TOTAL, &rotRateTotal);
|
||||||
|
poolManager.subscribeForRegularPeriodicPacket({fusedRotRateData.getSid(), enableHkSets, 10.0});
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,6 +775,8 @@ LocalPoolDataSetBase *AcsController::getDataSetHandle(sid_t sid) {
|
|||||||
return &ctrlValData;
|
return &ctrlValData;
|
||||||
case acsctrl::ACTUATOR_CMD_DATA:
|
case acsctrl::ACTUATOR_CMD_DATA:
|
||||||
return &actuatorCmdData;
|
return &actuatorCmdData;
|
||||||
|
case acsctrl::FUSED_ROTATION_RATE_DATA:
|
||||||
|
return &fusedRotRateData;
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <mission/acs/rwHelpers.h>
|
#include <mission/acs/rwHelpers.h>
|
||||||
#include <mission/acs/susMax1227Helpers.h>
|
#include <mission/acs/susMax1227Helpers.h>
|
||||||
#include <mission/controller/acs/ActuatorCmd.h>
|
#include <mission/controller/acs/ActuatorCmd.h>
|
||||||
|
#include <mission/controller/acs/FusedRotationEstimation.h>
|
||||||
#include <mission/controller/acs/Guidance.h>
|
#include <mission/controller/acs/Guidance.h>
|
||||||
#include <mission/controller/acs/MultiplicativeKalmanFilter.h>
|
#include <mission/controller/acs/MultiplicativeKalmanFilter.h>
|
||||||
#include <mission/controller/acs/Navigation.h>
|
#include <mission/controller/acs/Navigation.h>
|
||||||
@ -49,6 +50,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
|||||||
|
|
||||||
AcsParameters acsParameters;
|
AcsParameters acsParameters;
|
||||||
SensorProcessing sensorProcessing;
|
SensorProcessing sensorProcessing;
|
||||||
|
FusedRotationEstimation fusedRotationEstimation;
|
||||||
Navigation navigation;
|
Navigation navigation;
|
||||||
ActuatorCmd actuatorCmd;
|
ActuatorCmd actuatorCmd;
|
||||||
Guidance guidance;
|
Guidance guidance;
|
||||||
@ -226,6 +228,12 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
|||||||
PoolEntry<int32_t> rwTargetSpeed = PoolEntry<int32_t>(4);
|
PoolEntry<int32_t> rwTargetSpeed = PoolEntry<int32_t>(4);
|
||||||
PoolEntry<int16_t> mtqTargetDipole = PoolEntry<int16_t>(3);
|
PoolEntry<int16_t> mtqTargetDipole = PoolEntry<int16_t>(3);
|
||||||
|
|
||||||
|
// Fused Rot Rate
|
||||||
|
acsctrl::FusedRotRateData fusedRotRateData;
|
||||||
|
PoolEntry<double> rotRateOrthogonal = PoolEntry<double>(3);
|
||||||
|
PoolEntry<double> rotRateParallel = PoolEntry<double>(3);
|
||||||
|
PoolEntry<double> rotRateTotal = PoolEntry<double>(3);
|
||||||
|
|
||||||
// Initial delay to make sure all pool variables have been initialized their owners
|
// Initial delay to make sure all pool variables have been initialized their owners
|
||||||
Countdown initialCountdown = Countdown(INIT_DELAY);
|
Countdown initialCountdown = Countdown(INIT_DELAY);
|
||||||
};
|
};
|
||||||
|
@ -105,6 +105,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
|||||||
parameterWrapper->setVector(mgmHandlingParameters.mgm4variance);
|
parameterWrapper->setVector(mgmHandlingParameters.mgm4variance);
|
||||||
break;
|
break;
|
||||||
case 0x12:
|
case 0x12:
|
||||||
|
parameterWrapper->set(mgmHandlingParameters.mgmVectorFilterWeight);
|
||||||
|
break;
|
||||||
|
case 0x13:
|
||||||
parameterWrapper->set(mgmHandlingParameters.mgmDerivativeFilterWeight);
|
parameterWrapper->set(mgmHandlingParameters.mgmDerivativeFilterWeight);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -224,6 +227,12 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
|||||||
case 0x24:
|
case 0x24:
|
||||||
parameterWrapper->set(susHandlingParameters.susBrightnessThreshold);
|
parameterWrapper->set(susHandlingParameters.susBrightnessThreshold);
|
||||||
break;
|
break;
|
||||||
|
case 0x25:
|
||||||
|
parameterWrapper->set(susHandlingParameters.susVectorFilterWeight);
|
||||||
|
break;
|
||||||
|
case 0x26:
|
||||||
|
parameterWrapper->set(susHandlingParameters.susRateFilterWeight);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return INVALID_IDENTIFIER_ID;
|
return INVALID_IDENTIFIER_ID;
|
||||||
}
|
}
|
||||||
@ -339,26 +348,41 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
|||||||
parameterWrapper->set(safeModeControllerParameters.k_parallelMekf);
|
parameterWrapper->set(safeModeControllerParameters.k_parallelMekf);
|
||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
parameterWrapper->set(safeModeControllerParameters.k_orthoNonMekf);
|
parameterWrapper->set(safeModeControllerParameters.k_orthoGyr);
|
||||||
break;
|
break;
|
||||||
case 0x4:
|
case 0x4:
|
||||||
parameterWrapper->set(safeModeControllerParameters.k_alignNonMekf);
|
parameterWrapper->set(safeModeControllerParameters.k_alignGyr);
|
||||||
break;
|
break;
|
||||||
case 0x5:
|
case 0x5:
|
||||||
parameterWrapper->set(safeModeControllerParameters.k_parallelNonMekf);
|
parameterWrapper->set(safeModeControllerParameters.k_parallelGyr);
|
||||||
break;
|
break;
|
||||||
case 0x6:
|
case 0x6:
|
||||||
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDirLeop);
|
parameterWrapper->set(safeModeControllerParameters.k_orthoSusMgm);
|
||||||
break;
|
break;
|
||||||
case 0x7:
|
case 0x7:
|
||||||
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDir);
|
parameterWrapper->set(safeModeControllerParameters.k_alignSusMgm);
|
||||||
break;
|
break;
|
||||||
case 0x8:
|
case 0x8:
|
||||||
parameterWrapper->set(safeModeControllerParameters.useMekf);
|
parameterWrapper->set(safeModeControllerParameters.k_parallelSusMgm);
|
||||||
break;
|
break;
|
||||||
case 0x9:
|
case 0x9:
|
||||||
|
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDirLeop);
|
||||||
|
break;
|
||||||
|
case 0xA:
|
||||||
|
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDir);
|
||||||
|
break;
|
||||||
|
case 0xB:
|
||||||
|
parameterWrapper->set(safeModeControllerParameters.useMekf);
|
||||||
|
break;
|
||||||
|
case 0xC:
|
||||||
|
parameterWrapper->set(safeModeControllerParameters.useGyr);
|
||||||
|
break;
|
||||||
|
case 0xD:
|
||||||
parameterWrapper->set(safeModeControllerParameters.dampingDuringEclipse);
|
parameterWrapper->set(safeModeControllerParameters.dampingDuringEclipse);
|
||||||
break;
|
break;
|
||||||
|
case 0xE:
|
||||||
|
parameterWrapper->set(safeModeControllerParameters.sineLimitSunRotRate);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return INVALID_IDENTIFIER_ID;
|
return INVALID_IDENTIFIER_ID;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,8 @@ class AcsParameters : public HasParametersIF {
|
|||||||
float mgm02variance[3] = {pow(3.2e-7, 2), pow(3.2e-7, 2), pow(4.1e-7, 2)};
|
float mgm02variance[3] = {pow(3.2e-7, 2), pow(3.2e-7, 2), pow(4.1e-7, 2)};
|
||||||
float mgm13variance[3] = {pow(1.5e-8, 2), pow(1.5e-8, 2), pow(1.5e-8, 2)};
|
float mgm13variance[3] = {pow(1.5e-8, 2), pow(1.5e-8, 2), pow(1.5e-8, 2)};
|
||||||
float mgm4variance[3] = {pow(1.7e-6, 2), pow(1.7e-6, 2), pow(1.7e-6, 2)};
|
float mgm4variance[3] = {pow(1.7e-6, 2), pow(1.7e-6, 2), pow(1.7e-6, 2)};
|
||||||
float mgmDerivativeFilterWeight = 0.5;
|
float mgmVectorFilterWeight = 0.85;
|
||||||
|
float mgmDerivativeFilterWeight = 0.85;
|
||||||
} mgmHandlingParameters;
|
} mgmHandlingParameters;
|
||||||
|
|
||||||
struct SusHandlingParameters {
|
struct SusHandlingParameters {
|
||||||
@ -767,6 +768,8 @@ class AcsParameters : public HasParametersIF {
|
|||||||
0.167666815691513, 0.163137400730063, -0.000609874123906977, -0.00205336098697513,
|
0.167666815691513, 0.163137400730063, -0.000609874123906977, -0.00205336098697513,
|
||||||
-0.000889232196185857, -0.00168429567131815}};
|
-0.000889232196185857, -0.00168429567131815}};
|
||||||
float susBrightnessThreshold = 0.7;
|
float susBrightnessThreshold = 0.7;
|
||||||
|
float susVectorFilterWeight = .85;
|
||||||
|
float susRateFilterWeight = .85;
|
||||||
} susHandlingParameters;
|
} susHandlingParameters;
|
||||||
|
|
||||||
struct GyrHandlingParameters {
|
struct GyrHandlingParameters {
|
||||||
@ -825,15 +828,22 @@ class AcsParameters : public HasParametersIF {
|
|||||||
double k_alignMekf = 4.0e-5;
|
double k_alignMekf = 4.0e-5;
|
||||||
double k_parallelMekf = 3.75e-4;
|
double k_parallelMekf = 3.75e-4;
|
||||||
|
|
||||||
double k_orthoNonMekf = 4.4e-3;
|
double k_orthoGyr = 4.4e-3;
|
||||||
double k_alignNonMekf = 4.0e-5;
|
double k_alignGyr = 4.0e-5;
|
||||||
double k_parallelNonMekf = 3.75e-4;
|
double k_parallelGyr = 3.75e-4;
|
||||||
|
|
||||||
|
double k_orthoSusMgm = 1.1e-2;
|
||||||
|
double k_alignSusMgm = 2.0e-5;
|
||||||
|
double k_parallelSusMgm = 4.4e-4;
|
||||||
|
|
||||||
double sunTargetDirLeop[3] = {0, sqrt(.5), sqrt(.5)};
|
double sunTargetDirLeop[3] = {0, sqrt(.5), sqrt(.5)};
|
||||||
double sunTargetDir[3] = {0, 0, 1};
|
double sunTargetDir[3] = {0, 0, 1};
|
||||||
|
|
||||||
uint8_t useMekf = false;
|
uint8_t useMekf = false;
|
||||||
|
uint8_t useGyr = true;
|
||||||
uint8_t dampingDuringEclipse = true;
|
uint8_t dampingDuringEclipse = true;
|
||||||
|
|
||||||
|
float sineLimitSunRotRate = 0.24;
|
||||||
} safeModeControllerParameters;
|
} safeModeControllerParameters;
|
||||||
|
|
||||||
struct PointingLawParameters {
|
struct PointingLawParameters {
|
||||||
|
@ -2,6 +2,7 @@ target_sources(
|
|||||||
${LIB_EIVE_MISSION}
|
${LIB_EIVE_MISSION}
|
||||||
PRIVATE AcsParameters.cpp
|
PRIVATE AcsParameters.cpp
|
||||||
ActuatorCmd.cpp
|
ActuatorCmd.cpp
|
||||||
|
FusedRotationEstimation.cpp
|
||||||
Guidance.cpp
|
Guidance.cpp
|
||||||
Igrf13Model.cpp
|
Igrf13Model.cpp
|
||||||
MultiplicativeKalmanFilter.cpp
|
MultiplicativeKalmanFilter.cpp
|
||||||
|
103
mission/controller/acs/FusedRotationEstimation.cpp
Normal file
103
mission/controller/acs/FusedRotationEstimation.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include "FusedRotationEstimation.h"
|
||||||
|
|
||||||
|
FusedRotationEstimation::FusedRotationEstimation(AcsParameters *acsParameters_) {
|
||||||
|
acsParameters = acsParameters_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||||
|
acsctrl::SusDataProcessed *susDataProcessed, acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||||
|
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
|
||||||
|
if ((not mgmDataProcessed->mgmVecTot.isValid() and not susDataProcessed->susVecTot.isValid() and
|
||||||
|
not fusedRotRateData->rotRateTotal.isValid()) or
|
||||||
|
(not susDataProcessed->susVecTotDerivative.isValid() and
|
||||||
|
not mgmDataProcessed->mgmVecTotDerivative.isValid())) {
|
||||||
|
{
|
||||||
|
PoolReadGuard pg(fusedRotRateData);
|
||||||
|
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
|
||||||
|
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
|
||||||
|
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
|
||||||
|
fusedRotRateData->setValidity(false, true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (not susDataProcessed->susVecTot.isValid()) {
|
||||||
|
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate rotation around the sun
|
||||||
|
double magSunCross[3] = {0, 0, 0};
|
||||||
|
|
||||||
|
VectorOperations<double>::cross(mgmDataProcessed->mgmVecTot.value,
|
||||||
|
susDataProcessed->susVecTot.value, magSunCross);
|
||||||
|
double magSunCrossNorm = VectorOperations<double>::norm(magSunCross, 3);
|
||||||
|
double magNorm = VectorOperations<double>::norm(mgmDataProcessed->mgmVecTot.value, 3);
|
||||||
|
double fusedRotRateParallel[3] = {0, 0, 0};
|
||||||
|
if (magSunCrossNorm >
|
||||||
|
(acsParameters->safeModeControllerParameters.sineLimitSunRotRate * magNorm)) {
|
||||||
|
double omegaParallel =
|
||||||
|
VectorOperations<double>::dot(mgmDataProcessed->mgmVecTotDerivative.value, magSunCross) *
|
||||||
|
pow(magSunCrossNorm, -2);
|
||||||
|
VectorOperations<double>::mulScalar(susDataProcessed->susVecTot.value, omegaParallel,
|
||||||
|
fusedRotRateParallel, 3);
|
||||||
|
} else {
|
||||||
|
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate rotation orthogonal to the sun
|
||||||
|
double fusedRotRateOrthogonal[3] = {0, 0, 0};
|
||||||
|
VectorOperations<double>::cross(susDataProcessed->susVecTotDerivative.value,
|
||||||
|
susDataProcessed->susVecTot.value, fusedRotRateOrthogonal);
|
||||||
|
VectorOperations<double>::mulScalar(
|
||||||
|
fusedRotRateOrthogonal,
|
||||||
|
pow(VectorOperations<double>::norm(susDataProcessed->susVecTot.value, 3), -2),
|
||||||
|
fusedRotRateOrthogonal, 3);
|
||||||
|
|
||||||
|
// calculate total rotation rate
|
||||||
|
double fusedRotRateTotal[3] = {0, 0, 0};
|
||||||
|
VectorOperations<double>::add(fusedRotRateParallel, fusedRotRateOrthogonal, fusedRotRateTotal);
|
||||||
|
|
||||||
|
// store for calculation of angular acceleration
|
||||||
|
if (gyrDataProcessed->gyrVecTot.isValid()) {
|
||||||
|
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
PoolReadGuard pg(fusedRotRateData);
|
||||||
|
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, fusedRotRateOrthogonal,
|
||||||
|
3 * sizeof(double));
|
||||||
|
std::memcpy(fusedRotRateData->rotRateParallel.value, fusedRotRateParallel, 3 * sizeof(double));
|
||||||
|
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
|
||||||
|
fusedRotRateData->setValidity(true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FusedRotationEstimation::estimateFusedRotationRateEclipse(
|
||||||
|
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
|
||||||
|
if (not gyrDataProcessed->gyrVecTot.isValid() or
|
||||||
|
VectorOperations<double>::norm(fusedRotRateData->rotRateTotal.value, 3) == 0) {
|
||||||
|
{
|
||||||
|
PoolReadGuard pg(fusedRotRateData);
|
||||||
|
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
|
||||||
|
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
|
||||||
|
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
|
||||||
|
fusedRotRateData->setValidity(false, true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
double angAccelB[3] = {0, 0, 0};
|
||||||
|
VectorOperations<double>::subtract(gyrDataProcessed->gyrVecTot.value, rotRateOldB, angAccelB, 3);
|
||||||
|
double fusedRotRateTotal[3] = {0, 0, 0};
|
||||||
|
VectorOperations<double>::add(fusedRotRateData->rotRateTotal.value, angAccelB, fusedRotRateTotal,
|
||||||
|
3);
|
||||||
|
{
|
||||||
|
PoolReadGuard pg(fusedRotRateData);
|
||||||
|
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
|
||||||
|
fusedRotRateData->rotRateOrthogonal.setValid(false);
|
||||||
|
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
|
||||||
|
fusedRotRateData->rotRateParallel.setValid(false);
|
||||||
|
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
|
||||||
|
fusedRotRateData->rotRateTotal.setValid(true);
|
||||||
|
}
|
||||||
|
}
|
29
mission/controller/acs/FusedRotationEstimation.h
Normal file
29
mission/controller/acs/FusedRotationEstimation.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_
|
||||||
|
#define MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_
|
||||||
|
|
||||||
|
#include <fsfw/datapool/PoolReadGuard.h>
|
||||||
|
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||||
|
#include <mission/controller/acs/AcsParameters.h>
|
||||||
|
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||||
|
|
||||||
|
class FusedRotationEstimation {
|
||||||
|
public:
|
||||||
|
FusedRotationEstimation(AcsParameters *acsParameters_);
|
||||||
|
|
||||||
|
void estimateFusedRotationRateSafe(acsctrl::SusDataProcessed *susDataProcessed,
|
||||||
|
acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||||
|
acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||||
|
acsctrl::FusedRotRateData *fusedRotRateData);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
static constexpr double ZERO_VEC[3] = {0, 0, 0};
|
||||||
|
|
||||||
|
AcsParameters *acsParameters;
|
||||||
|
double rotRateOldB[3] = {0, 0, 0};
|
||||||
|
|
||||||
|
void estimateFusedRotationRateEclipse(acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||||
|
acsctrl::FusedRotRateData *fusedRotRateData);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_ */
|
@ -132,6 +132,10 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
|
|||||||
for (uint8_t i = 0; i < 3; i++) {
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
mgmVecTot[i] = sensorFusionNumerator[i] / sensorFusionDenominator[i];
|
mgmVecTot[i] = sensorFusionNumerator[i] / sensorFusionDenominator[i];
|
||||||
}
|
}
|
||||||
|
if (VectorOperations<double>::norm(mgmVecTot, 3) != 0 and mgmDataProcessed->mgmVecTot.isValid()) {
|
||||||
|
lowPassFilter(mgmVecTot, mgmDataProcessed->mgmVecTot.value,
|
||||||
|
mgmParameters->mgmVectorFilterWeight);
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------Mgm Rate Computation ---------------------------------------------------
|
//-----------------------Mgm Rate Computation ---------------------------------------------------
|
||||||
double mgmVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
double mgmVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
||||||
@ -351,6 +355,11 @@ void SensorProcessing::processSus(
|
|||||||
double susVecTot[3] = {0.0, 0.0, 0.0};
|
double susVecTot[3] = {0.0, 0.0, 0.0};
|
||||||
VectorOperations<double>::normalize(susMeanValue, susVecTot, 3);
|
VectorOperations<double>::normalize(susMeanValue, susVecTot, 3);
|
||||||
|
|
||||||
|
if (VectorOperations<double>::norm(susVecTot, 3) != 0 and susDataProcessed->susVecTot.isValid()) {
|
||||||
|
lowPassFilter(susVecTot, susDataProcessed->susVecTot.value,
|
||||||
|
susParameters->susVectorFilterWeight);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------- Sun Derivatiative --------------------- */
|
/* -------- Sun Derivatiative --------------------- */
|
||||||
|
|
||||||
double susVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
double susVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
||||||
@ -363,6 +372,11 @@ void SensorProcessing::processSus(
|
|||||||
susVecTotDerivativeValid = true;
|
susVecTotDerivativeValid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (VectorOperations<double>::norm(susVecTotDerivative, 3) != 0 and
|
||||||
|
susDataProcessed->susVecTotDerivative.isValid()) {
|
||||||
|
lowPassFilter(susVecTotDerivative, susDataProcessed->susVecTotDerivative.value,
|
||||||
|
susParameters->susRateFilterWeight);
|
||||||
|
}
|
||||||
timeOfSavedSusDirEst = timeOfSusMeasurement;
|
timeOfSavedSusDirEst = timeOfSusMeasurement;
|
||||||
{
|
{
|
||||||
PoolReadGuard pg(susDataProcessed);
|
PoolReadGuard pg(susDataProcessed);
|
||||||
|
@ -9,20 +9,36 @@ SafeCtrl::SafeCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameter
|
|||||||
|
|
||||||
SafeCtrl::~SafeCtrl() {}
|
SafeCtrl::~SafeCtrl() {}
|
||||||
|
|
||||||
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(
|
||||||
const bool satRotRateValid, const bool sunDirValid,
|
const bool magFieldValid, const bool mekfValid, const bool satRotRateValid,
|
||||||
const uint8_t mekfEnabled,
|
const bool sunDirValid, const bool fusedRateSplitValid, const bool fusedRateTotalValid,
|
||||||
const uint8_t dampingEnabled) {
|
const uint8_t mekfEnabled, const uint8_t gyrEnabled, const uint8_t dampingEnabled) {
|
||||||
if (not magFieldValid) {
|
if (not magFieldValid) {
|
||||||
return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL;
|
return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL;
|
||||||
} else if (mekfEnabled and mekfValid) {
|
} else if (mekfEnabled and mekfValid) {
|
||||||
return acs::SafeModeStrategy::SAFECTRL_ACTIVE_MEKF;
|
return acs::SafeModeStrategy::SAFECTRL_MEKF;
|
||||||
} else if (satRotRateValid and sunDirValid) {
|
} else if (sunDirValid) {
|
||||||
return acs::SafeModeStrategy::SAFECTRL_WITHOUT_MEKF;
|
if (gyrEnabled and satRotRateValid) {
|
||||||
} else if (dampingEnabled and satRotRateValid and not sunDirValid) {
|
return acs::SafeModeStrategy::SAFECTRL_GYR;
|
||||||
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING;
|
} else if (not gyrEnabled and fusedRateSplitValid) {
|
||||||
} else if (not dampingEnabled and satRotRateValid and not sunDirValid) {
|
return acs::SafeModeStrategy::SAFECTRL_SUSMGM;
|
||||||
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_IDELING;
|
} else {
|
||||||
|
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||||
|
}
|
||||||
|
} else if (not sunDirValid) {
|
||||||
|
if (dampingEnabled) {
|
||||||
|
if (gyrEnabled and satRotRateValid) {
|
||||||
|
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_GYR;
|
||||||
|
} else if (not gyrEnabled and satRotRateValid and fusedRateTotalValid) {
|
||||||
|
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_SUSMGM;
|
||||||
|
} else {
|
||||||
|
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||||
|
}
|
||||||
|
} else if (not dampingEnabled and satRotRateValid) {
|
||||||
|
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_IDELING;
|
||||||
|
} else {
|
||||||
|
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||||
}
|
}
|
||||||
@ -43,8 +59,7 @@ void SafeCtrl::safeMekf(const double *magFieldB, const double *satRotRateB,
|
|||||||
errorAngle = acos(dotSun);
|
errorAngle = acos(dotSun);
|
||||||
|
|
||||||
splitRotationalRate(satRotRateB, sunDirB);
|
splitRotationalRate(satRotRateB, sunDirB);
|
||||||
calculateRotationalRateTorque(sunDirB, sunDirRefB, errorAngle,
|
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelMekf,
|
||||||
acsParameters->safeModeControllerParameters.k_parallelMekf,
|
|
||||||
acsParameters->safeModeControllerParameters.k_orthoMekf);
|
acsParameters->safeModeControllerParameters.k_orthoMekf);
|
||||||
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
||||||
acsParameters->safeModeControllerParameters.k_alignMekf);
|
acsParameters->safeModeControllerParameters.k_alignMekf);
|
||||||
@ -57,9 +72,8 @@ void SafeCtrl::safeMekf(const double *magFieldB, const double *satRotRateB,
|
|||||||
calculateMagneticMoment(magMomB);
|
calculateMagneticMoment(magMomB);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
|
void SafeCtrl::safeGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
|
||||||
const double *sunDirB, const double *sunDirRefB, double *magMomB,
|
const double *sunDirRefB, double *magMomB, double &errorAngle) {
|
||||||
double &errorAngle) {
|
|
||||||
// convert magFieldB from uT to T
|
// convert magFieldB from uT to T
|
||||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||||
|
|
||||||
@ -68,11 +82,10 @@ void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
|
|||||||
errorAngle = acos(dotSun);
|
errorAngle = acos(dotSun);
|
||||||
|
|
||||||
splitRotationalRate(satRotRateB, sunDirB);
|
splitRotationalRate(satRotRateB, sunDirB);
|
||||||
calculateRotationalRateTorque(sunDirB, sunDirRefB, errorAngle,
|
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelGyr,
|
||||||
acsParameters->safeModeControllerParameters.k_parallelNonMekf,
|
acsParameters->safeModeControllerParameters.k_orthoGyr);
|
||||||
acsParameters->safeModeControllerParameters.k_orthoNonMekf);
|
|
||||||
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
||||||
acsParameters->safeModeControllerParameters.k_alignNonMekf);
|
acsParameters->safeModeControllerParameters.k_alignGyr);
|
||||||
|
|
||||||
// sum of all torques
|
// sum of all torques
|
||||||
for (uint8_t i = 0; i < 3; i++) {
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
@ -82,8 +95,33 @@ void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
|
|||||||
calculateMagneticMoment(magMomB);
|
calculateMagneticMoment(magMomB);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SafeCtrl::safeRateDamping(const double *magFieldB, const double *satRotRateB,
|
void SafeCtrl::safeSusMgm(const double *magFieldB, const double *rotRateParallelB,
|
||||||
const double *sunDirRefB, double *magMomB, double &errorAngle) {
|
const double *rotRateOrthogonalB, const double *sunDirB,
|
||||||
|
const double *sunDirRefB, double *magMomB, double &errorAngle) {
|
||||||
|
// convert magFieldB from uT to T
|
||||||
|
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||||
|
|
||||||
|
// calculate error angle between sunDirRef and sunDir
|
||||||
|
double dotSun = VectorOperations<double>::dot(sunDirRefB, sunDirB);
|
||||||
|
errorAngle = acos(dotSun);
|
||||||
|
|
||||||
|
std::memcpy(satRotRateParallelB, rotRateParallelB, sizeof(satRotRateParallelB));
|
||||||
|
std::memcpy(satRotRateOrthogonalB, rotRateOrthogonalB, sizeof(satRotRateOrthogonalB));
|
||||||
|
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelSusMgm,
|
||||||
|
acsParameters->safeModeControllerParameters.k_orthoSusMgm);
|
||||||
|
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
||||||
|
acsParameters->safeModeControllerParameters.k_alignSusMgm);
|
||||||
|
|
||||||
|
// sum of all torques
|
||||||
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
|
cmdTorque[i] = cmdAlign[i] + cmdOrtho[i] + cmdParallel[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateMagneticMoment(magMomB);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SafeCtrl::safeRateDampingGyr(const double *magFieldB, const double *satRotRateB,
|
||||||
|
const double *sunDirRefB, double *magMomB, double &errorAngle) {
|
||||||
// convert magFieldB from uT to T
|
// convert magFieldB from uT to T
|
||||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||||
|
|
||||||
@ -91,9 +129,28 @@ void SafeCtrl::safeRateDamping(const double *magFieldB, const double *satRotRate
|
|||||||
errorAngle = NAN;
|
errorAngle = NAN;
|
||||||
|
|
||||||
splitRotationalRate(satRotRateB, sunDirRefB);
|
splitRotationalRate(satRotRateB, sunDirRefB);
|
||||||
calculateRotationalRateTorque(sunDirRefB, sunDirRefB, errorAngle,
|
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelGyr,
|
||||||
acsParameters->safeModeControllerParameters.k_parallelNonMekf,
|
acsParameters->safeModeControllerParameters.k_orthoGyr);
|
||||||
acsParameters->safeModeControllerParameters.k_orthoNonMekf);
|
|
||||||
|
// sum of all torques
|
||||||
|
VectorOperations<double>::add(cmdParallel, cmdOrtho, cmdTorque, 3);
|
||||||
|
|
||||||
|
// calculate magnetic moment to command
|
||||||
|
calculateMagneticMoment(magMomB);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SafeCtrl::safeRateDampingSusMgm(const double *magFieldB, const double *satRotRateB,
|
||||||
|
const double *sunDirRefB, double *magMomB,
|
||||||
|
double &errorAngle) {
|
||||||
|
// convert magFieldB from uT to T
|
||||||
|
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||||
|
|
||||||
|
// no error angle available for eclipse
|
||||||
|
errorAngle = NAN;
|
||||||
|
|
||||||
|
splitRotationalRate(satRotRateB, sunDirRefB);
|
||||||
|
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelSusMgm,
|
||||||
|
acsParameters->safeModeControllerParameters.k_orthoSusMgm);
|
||||||
|
|
||||||
// sum of all torques
|
// sum of all torques
|
||||||
VectorOperations<double>::add(cmdParallel, cmdOrtho, cmdTorque, 3);
|
VectorOperations<double>::add(cmdParallel, cmdOrtho, cmdTorque, 3);
|
||||||
@ -110,9 +167,7 @@ void SafeCtrl::splitRotationalRate(const double *satRotRateB, const double *sunD
|
|||||||
VectorOperations<double>::subtract(satRotRateB, satRotRateParallelB, satRotRateOrthogonalB, 3);
|
VectorOperations<double>::subtract(satRotRateB, satRotRateParallelB, satRotRateOrthogonalB, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SafeCtrl::calculateRotationalRateTorque(const double *sunDirB, const double *sunDirRefB,
|
void SafeCtrl::calculateRotationalRateTorque(const double gainParallel, const double gainOrtho) {
|
||||||
double &errorAngle, const double gainParallel,
|
|
||||||
const double gainOrtho) {
|
|
||||||
// calculate torque for parallel rotational rate
|
// calculate torque for parallel rotational rate
|
||||||
VectorOperations<double>::mulScalar(satRotRateParallelB, -gainParallel, cmdParallel, 3);
|
VectorOperations<double>::mulScalar(satRotRateParallelB, -gainParallel, cmdParallel, 3);
|
||||||
|
|
||||||
|
@ -14,23 +14,34 @@ class SafeCtrl {
|
|||||||
|
|
||||||
acs::SafeModeStrategy safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
acs::SafeModeStrategy safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||||
const bool satRotRateValid, const bool sunDirValid,
|
const bool satRotRateValid, const bool sunDirValid,
|
||||||
const uint8_t mekfEnabled, const uint8_t dampingEnabled);
|
const bool fusedRateSplitValid,
|
||||||
|
const bool fusedRateTotalValid, const uint8_t mekfEnabled,
|
||||||
|
const uint8_t gyrEnabled, const uint8_t dampingEnabled);
|
||||||
|
|
||||||
void safeMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirModelI,
|
void safeMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirModelI,
|
||||||
const double *quatBI, const double *sunDirRefB, double *magMomB,
|
const double *quatBI, const double *sunDirRefB, double *magMomB,
|
||||||
double &errorAngle);
|
double &errorAngle);
|
||||||
|
|
||||||
void safeNonMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
|
void safeGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
|
||||||
const double *sunDirRefB, double *magMomB, double &errorAngle);
|
const double *sunDirRefB, double *magMomB, double &errorAngle);
|
||||||
|
|
||||||
void safeRateDamping(const double *magFieldB, const double *satRotRateB, const double *sunDirRefB,
|
void safeSusMgm(const double *magFieldB, const double *rotRateParallelB,
|
||||||
double *magMomB, double &errorAngle);
|
const double *rotRateOrthogonalB, const double *sunDirB, const double *sunDirRefB,
|
||||||
|
double *magMomB, double &errorAngle);
|
||||||
|
|
||||||
|
void safeRateDampingGyr(const double *magFieldB, const double *satRotRateB,
|
||||||
|
const double *sunDirRefB, double *magMomB, double &errorAngle);
|
||||||
|
|
||||||
|
void safeRateDampingSusMgm(const double *magFieldB, const double *satRotRateB,
|
||||||
|
const double *sunDirRefB, double *magMomB, double &errorAngle);
|
||||||
|
|
||||||
void splitRotationalRate(const double *satRotRateB, const double *sunDirB);
|
void splitRotationalRate(const double *satRotRateB, const double *sunDirB);
|
||||||
|
|
||||||
void calculateRotationalRateTorque(const double *sunDirB, const double *sunDirRefB,
|
void calculateRotationalRates(const double *magFieldB, const double *magRateB,
|
||||||
double &errorAngle, const double gainParallel,
|
const double *sunDirB, const double *sunRateB,
|
||||||
const double gainOrtho);
|
double *fusedRotRate);
|
||||||
|
|
||||||
|
void calculateRotationalRateTorque(const double gainParallel, const double gainOrtho);
|
||||||
|
|
||||||
void calculateAngleErrorTorque(const double *sunDirB, const double *sunDirRefB,
|
void calculateAngleErrorTorque(const double *sunDirB, const double *sunDirRefB,
|
||||||
const double gainAlign);
|
const double gainAlign);
|
||||||
|
@ -18,7 +18,8 @@ enum SetIds : uint32_t {
|
|||||||
GPS_PROCESSED_DATA,
|
GPS_PROCESSED_DATA,
|
||||||
MEKF_DATA,
|
MEKF_DATA,
|
||||||
CTRL_VAL_DATA,
|
CTRL_VAL_DATA,
|
||||||
ACTUATOR_CMD_DATA
|
ACTUATOR_CMD_DATA,
|
||||||
|
FUSED_ROTATION_RATE_DATA,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PoolIds : lp_id_t {
|
enum PoolIds : lp_id_t {
|
||||||
@ -103,6 +104,10 @@ enum PoolIds : lp_id_t {
|
|||||||
RW_TARGET_TORQUE,
|
RW_TARGET_TORQUE,
|
||||||
RW_TARGET_SPEED,
|
RW_TARGET_SPEED,
|
||||||
MTQ_TARGET_DIPOLE,
|
MTQ_TARGET_DIPOLE,
|
||||||
|
// Fused Rotation Rate
|
||||||
|
ROT_RATE_ORTHOGONAL,
|
||||||
|
ROT_RATE_PARALLEL,
|
||||||
|
ROT_RATE_TOTAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr uint8_t MGM_SET_RAW_ENTRIES = 6;
|
static constexpr uint8_t MGM_SET_RAW_ENTRIES = 6;
|
||||||
@ -115,6 +120,7 @@ static constexpr uint8_t GPS_SET_PROCESSED_ENTRIES = 5;
|
|||||||
static constexpr uint8_t MEKF_SET_ENTRIES = 3;
|
static constexpr uint8_t MEKF_SET_ENTRIES = 3;
|
||||||
static constexpr uint8_t CTRL_VAL_SET_ENTRIES = 5;
|
static constexpr uint8_t CTRL_VAL_SET_ENTRIES = 5;
|
||||||
static constexpr uint8_t ACT_CMD_SET_ENTRIES = 3;
|
static constexpr uint8_t ACT_CMD_SET_ENTRIES = 3;
|
||||||
|
static constexpr uint8_t FUSED_ROT_RATE_SET_ENTRIES = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Raw MGM sensor data. Includes the IMTQ sensor data and actuator status.
|
* @brief Raw MGM sensor data. Includes the IMTQ sensor data and actuator status.
|
||||||
@ -273,6 +279,19 @@ class ActuatorCmdData : public StaticLocalDataSet<ACT_CMD_SET_ENTRIES> {
|
|||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FusedRotRateData : public StaticLocalDataSet<FUSED_ROT_RATE_SET_ENTRIES> {
|
||||||
|
public:
|
||||||
|
FusedRotRateData(HasLocalDataPoolIF* hkOwner)
|
||||||
|
: StaticLocalDataSet(hkOwner, FUSED_ROTATION_RATE_DATA) {}
|
||||||
|
|
||||||
|
lp_vec_t<double, 3> rotRateOrthogonal =
|
||||||
|
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_ORTHOGONAL, this);
|
||||||
|
lp_vec_t<double, 3> rotRateParallel = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_PARALLEL, this);
|
||||||
|
lp_vec_t<double, 3> rotRateTotal = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_TOTAL, this);
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace acsctrl
|
} // namespace acsctrl
|
||||||
|
|
||||||
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_ACSCTRLDEFINITIONS_H_ */
|
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_ACSCTRLDEFINITIONS_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user