Fix NaN for Limiting Rotation Rates #872

Merged
meggert merged 17 commits from limit-rot-rate-fix into main 2024-03-06 11:13:02 +01:00
12 changed files with 116 additions and 8 deletions

View File

@ -16,10 +16,20 @@ will consitute of a breaking change warranting a new major release:
# [unreleased] # [unreleased]
- Bumped `eive-tmtc` to v6.1.1
- Bumped `eive-fsfw`
## Added
- The `CoreController` now sets the leap seconds on initalization. They are stored in a persistent
file. If the file does yet not exist, it will be created. The leap seconds can be updated using an
action command. This will also update the file.
## Fixed ## Fixed
- Fixed wrong dimension of a matrix within the `MEKF`, which would lead to a seg fault, if the - Fixed wrong dimension of a matrix within the `MEKF`, which would lead to a seg fault, if the
star tracker was available. star tracker was available.
- Fixed case in which control values within the `AcsController` could become NaN.
# [v7.7.0] 2024-02-29 # [v7.7.0] 2024-02-29

View File

@ -480,6 +480,16 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
successRecipient = commandedBy; successRecipient = commandedBy;
return returnvalue::OK; return returnvalue::OK;
} }
case (UPDATE_LEAP_SECONDS): {
if (size != sizeof(uint16_t)) {
return HasActionsIF::INVALID_PARAMETERS;
}
ReturnValue_t result = actionUpdateLeapSeconds(data);
if (result != returnvalue::OK) {
return result;
}
return HasActionsIF::EXECUTION_FINISHED;
}
default: { default: {
return HasActionsIF::INVALID_ACTION_ID; return HasActionsIF::INVALID_ACTION_ID;
} }
@ -1411,6 +1421,9 @@ void CoreController::performMountedSdCardOperations() {
if (not timeFileInitDone) { if (not timeFileInitDone) {
initClockFromTimeFile(); initClockFromTimeFile();
} }
if (not leapSecondsInitDone) {
initLeapSeconds();
}
performRebootWatchdogHandling(false); performRebootWatchdogHandling(false);
performRebootCountersHandling(false); performRebootCountersHandling(false);
} }
@ -2066,6 +2079,71 @@ ReturnValue_t CoreController::backupTimeFileHandler() {
return returnvalue::OK; return returnvalue::OK;
} }
void CoreController::initLeapSeconds() {
ReturnValue_t result = initLeapSecondsFromFile();
if (result != returnvalue::OK) {
Clock::setLeapSeconds(config::LEAP_SECONDS);
writeLeapSecondsToFile(config::LEAP_SECONDS);
}
leapSecondsInitDone = true;
}
ReturnValue_t CoreController::initLeapSecondsFromFile() {
std::string fileName = currMntPrefix + LEAP_SECONDS_FILE;
std::error_code e;
if (sdcMan->isSdCardUsable(std::nullopt) and std::filesystem::exists(fileName, e)) {
std::ifstream leapSecondsFile(fileName);
std::string nextWord;
std::getline(leapSecondsFile, nextWord);
std::istringstream iss(nextWord);
iss >> nextWord;
if (iss.bad() or nextWord != "LEAP") {
return returnvalue::FAILED;
}
iss >> nextWord;
if (iss.bad() or nextWord != "SECONDS:") {
return returnvalue::FAILED;
}
iss >> nextWord;
uint16_t leapSeconds = 0;
leapSeconds = std::stoi(nextWord.c_str());
if (iss.bad()) {
return returnvalue::FAILED;
}
Clock::setLeapSeconds(leapSeconds);
return returnvalue::OK;
}
sif::error
<< "CoreController::leapSecondsFileHandler: Initalization of leap seconds from file failed"
<< std::endl;
return returnvalue::FAILED;
};
ReturnValue_t CoreController::writeLeapSecondsToFile(const uint16_t leapSeconds) {
std::string fileName = currMntPrefix + LEAP_SECONDS_FILE;
if (not sdcMan->isSdCardUsable(std::nullopt)) {
return returnvalue::FAILED;
}
std::ofstream leapSecondsFile(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
if (not leapSecondsFile.good()) {
sif::error << "CoreController::leapSecondsFileHandler: Error opening leap seconds file: "
<< strerror(errno) << std::endl;
return returnvalue::FAILED;
}
leapSecondsFile << "LEAP SECONDS: " << leapSeconds << std::endl;
return returnvalue::OK;
};
ReturnValue_t CoreController::actionUpdateLeapSeconds(const uint8_t *data) {
uint16_t leapSeconds = data[1] | (data[0] << 8);
ReturnValue_t result = writeLeapSecondsToFile(leapSeconds);
if (result != returnvalue::OK) {
return result;
}
Clock::setLeapSeconds(leapSeconds);
return returnvalue::OK;
}
ReturnValue_t CoreController::initClockFromTimeFile() { ReturnValue_t CoreController::initClockFromTimeFile() {
using namespace GpsHyperion; using namespace GpsHyperion;
using namespace std; using namespace std;

View File

@ -150,6 +150,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
std::string(core::LEGACY_REBOOT_WATCHDOG_FILE_NAME); std::string(core::LEGACY_REBOOT_WATCHDOG_FILE_NAME);
const std::string REBOOT_WATCHDOG_FILE = const std::string REBOOT_WATCHDOG_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_WATCHDOG_FILE_NAME); "/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_WATCHDOG_FILE_NAME);
const std::string LEAP_SECONDS_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::LEAP_SECONDS_FILE_NAME);
const std::string BACKUP_TIME_FILE = const std::string BACKUP_TIME_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::TIME_FILE_NAME); "/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::TIME_FILE_NAME);
const std::string REBOOT_COUNTERS_FILE = const std::string REBOOT_COUNTERS_FILE =
@ -296,6 +298,7 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
std::string currMntPrefix; std::string currMntPrefix;
bool timeFileInitDone = false; bool timeFileInitDone = false;
bool leapSecondsInitDone = false;
bool performOneShotSdCardOpsSwitch = false; bool performOneShotSdCardOpsSwitch = false;
uint8_t shortSdCardCdCounter = 0; uint8_t shortSdCardCdCounter = 0;
#if OBSW_THREAD_TRACING == 1 #if OBSW_THREAD_TRACING == 1
@ -335,7 +338,11 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
void performMountedSdCardOperations(); void performMountedSdCardOperations();
ReturnValue_t initVersionFile(); ReturnValue_t initVersionFile();
void initLeapSeconds();
ReturnValue_t initLeapSecondsFromFile();
ReturnValue_t initClockFromTimeFile(); ReturnValue_t initClockFromTimeFile();
ReturnValue_t actionUpdateLeapSeconds(const uint8_t* data);
ReturnValue_t writeLeapSecondsToFile(const uint16_t leapSeconds);
ReturnValue_t performSdCardCheck(); ReturnValue_t performSdCardCheck();
ReturnValue_t backupTimeFileHandler(); ReturnValue_t backupTimeFileHandler();
ReturnValue_t initBootCopyFile(); ReturnValue_t initBootCopyFile();

View File

@ -20,6 +20,9 @@ static constexpr char OBSW_VERSION_FILE_PATH[] = "/usr/share/eive-obsw/obsw_vers
// ISO8601 timestamp. // ISO8601 timestamp.
static constexpr char FILE_DATE_FORMAT[] = "%FT%H%M%SZ"; static constexpr char FILE_DATE_FORMAT[] = "%FT%H%M%SZ";
// Leap Seconds as of 2024-03-04
static constexpr uint16_t LEAP_SECONDS = 37;
static constexpr uint16_t EIVE_PUS_APID = 0x65; static constexpr uint16_t EIVE_PUS_APID = 0x65;
static constexpr uint16_t EIVE_CFDP_APID = 0x66; static constexpr uint16_t EIVE_CFDP_APID = 0x66;
static constexpr uint16_t EIVE_LOCAL_CFDP_ENTITY_ID = EIVE_CFDP_APID; static constexpr uint16_t EIVE_LOCAL_CFDP_ENTITY_ID = EIVE_CFDP_APID;

2
fsfw

@ -1 +1 @@
Subproject commit 516357d855c07786b492e981230988186376d301 Subproject commit 47b21caf5fa2a27c7ace89f960141b3f24c329ee

View File

@ -273,7 +273,11 @@ void Guidance::limitReferenceRotation(const double xAxisIX[3], double quatIX[4])
QuaternionOperations::multiply(quatIXtilde, quatXI, quatXXtilde); QuaternionOperations::multiply(quatIXtilde, quatXI, quatXXtilde);
double phiResidual = 0, phiResidualVec[3] = {0, 0, 0}; double phiResidual = 0, phiResidualVec[3] = {0, 0, 0};
phiResidual = std::sqrt((phiMax * phiMax) - (phiX * phiX)); if ((phiX * phiX) > (phiMax * phiMax)) {
phiResidual = 0;
} else {
phiResidual = std::sqrt((phiMax * phiMax) - (phiX * phiX));
}
std::memcpy(phiResidualVec, quatXXtilde, sizeof(phiResidualVec)); std::memcpy(phiResidualVec, quatXXtilde, sizeof(phiResidualVec));
VectorOperations<double>::normalize(phiResidualVec, phiResidualVec, 3); VectorOperations<double>::normalize(phiResidualVec, phiResidualVec, 3);

View File

@ -69,7 +69,8 @@ void Igrf13Model::magFieldComp(const double longitude, const double gcLatitude,
magFieldModel[1] *= -1; magFieldModel[1] *= -1;
magFieldModel[2] *= (-1 / sin(theta)); magFieldModel[2] *= (-1 / sin(theta));
double JD2000 = TimeSystems::convertUnixToJD2000(timeOfMagMeasurement); double JD2000 = 0;
Clock::convertTimevalToJD2000(timeOfMagMeasurement, &JD2000);
double UT1 = JD2000 / 36525.; double UT1 = JD2000 / 36525.;
double gst = double gst =
@ -93,7 +94,8 @@ void Igrf13Model::magFieldComp(const double longitude, const double gcLatitude,
void Igrf13Model::updateCoeffGH(timeval timeOfMagMeasurement) { void Igrf13Model::updateCoeffGH(timeval timeOfMagMeasurement) {
double JD2000Igrf = (2458850.0 - 2451545); // Begin of IGRF-13 (2020-01-01,00:00:00) in JD2000 double JD2000Igrf = (2458850.0 - 2451545); // Begin of IGRF-13 (2020-01-01,00:00:00) in JD2000
double JD2000 = TimeSystems::convertUnixToJD2000(timeOfMagMeasurement); double JD2000 = 0;
Clock::convertTimevalToJD2000(timeOfMagMeasurement, &JD2000);
double days = ceil(JD2000 - JD2000Igrf); double days = ceil(JD2000 - JD2000Igrf);
for (int i = 0; i <= igrfOrder; i++) { for (int i = 0; i <= igrfOrder; i++) {
for (int j = 0; j <= (igrfOrder - 1); j++) { for (int j = 0; j <= (igrfOrder - 1); j++) {

View File

@ -16,11 +16,11 @@
#ifndef IGRF13MODEL_H_ #ifndef IGRF13MODEL_H_
#define IGRF13MODEL_H_ #define IGRF13MODEL_H_
#include <fsfw/src/fsfw/globalfunctions/TimeSystems.h>
#include <fsfw/src/fsfw/globalfunctions/constants.h> #include <fsfw/src/fsfw/globalfunctions/constants.h>
#include <fsfw/src/fsfw/globalfunctions/math/MatrixOperations.h> #include <fsfw/src/fsfw/globalfunctions/math/MatrixOperations.h>
#include <fsfw/src/fsfw/globalfunctions/math/QuaternionOperations.h> #include <fsfw/src/fsfw/globalfunctions/math/QuaternionOperations.h>
#include <fsfw/src/fsfw/globalfunctions/math/VectorOperations.h> #include <fsfw/src/fsfw/globalfunctions/math/VectorOperations.h>
#include <fsfw/src/fsfw/timemanager/Clock.h>
#include <cmath> #include <cmath>

View File

@ -180,7 +180,8 @@ void SensorProcessing::processSus(
const AcsParameters::SunModelParameters *sunModelParameters, const AcsParameters::SunModelParameters *sunModelParameters,
acsctrl::SusDataProcessed *susDataProcessed) { acsctrl::SusDataProcessed *susDataProcessed) {
/* -------- Sun Model Direction (IJK frame) ------- */ /* -------- Sun Model Direction (IJK frame) ------- */
double JD2000 = TimeSystems::convertUnixToJD2000(timeAbsolute); double JD2000 = 0;
Clock::convertTimevalToJD2000(timeAbsolute, &JD2000);
// Julean Centuries // Julean Centuries
double sunIjkModel[3] = {0.0, 0.0, 0.0}; double sunIjkModel[3] = {0.0, 0.0, 0.0};

View File

@ -4,13 +4,13 @@
#include <common/config/eive/resultClassIds.h> #include <common/config/eive/resultClassIds.h>
#include <fsfw/coordinates/CoordinateTransformations.h> #include <fsfw/coordinates/CoordinateTransformations.h>
#include <fsfw/datapool/PoolReadGuard.h> #include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/globalfunctions/TimeSystems.h>
#include <fsfw/globalfunctions/constants.h> #include <fsfw/globalfunctions/constants.h>
#include <fsfw/globalfunctions/math/MatrixOperations.h> #include <fsfw/globalfunctions/math/MatrixOperations.h>
#include <fsfw/globalfunctions/math/QuaternionOperations.h> #include <fsfw/globalfunctions/math/QuaternionOperations.h>
#include <fsfw/globalfunctions/math/VectorOperations.h> #include <fsfw/globalfunctions/math/VectorOperations.h>
#include <fsfw/globalfunctions/timevalOperations.h> #include <fsfw/globalfunctions/timevalOperations.h>
#include <fsfw/returnvalues/returnvalue.h> #include <fsfw/returnvalues/returnvalue.h>
#include <fsfw/timemanager/Clock.h>
#include <mission/acs/defs.h> #include <mission/acs/defs.h>
#include <mission/controller/acs/AcsParameters.h> #include <mission/controller/acs/AcsParameters.h>
#include <mission/controller/acs/Igrf13Model.h> #include <mission/controller/acs/Igrf13Model.h>

View File

@ -55,6 +55,7 @@ static constexpr char VERSION_FILE_NAME[] = "version.txt";
static constexpr char LEGACY_REBOOT_WATCHDOG_FILE_NAME[] = "reboot.txt"; static constexpr char LEGACY_REBOOT_WATCHDOG_FILE_NAME[] = "reboot.txt";
static constexpr char REBOOT_WATCHDOG_FILE_NAME[] = "reboot_watchdog.txt"; static constexpr char REBOOT_WATCHDOG_FILE_NAME[] = "reboot_watchdog.txt";
static constexpr char REBOOT_COUNTER_FILE_NAME[] = "reboot_counters.txt"; static constexpr char REBOOT_COUNTER_FILE_NAME[] = "reboot_counters.txt";
static constexpr char LEAP_SECONDS_FILE_NAME[] = "leapseconds.txt";
static constexpr char TIME_FILE_NAME[] = "time_backup.txt"; static constexpr char TIME_FILE_NAME[] = "time_backup.txt";
static constexpr uint32_t SYS_ROM_BASE_ADDR = 0x80000000; static constexpr uint32_t SYS_ROM_BASE_ADDR = 0x80000000;
@ -93,6 +94,8 @@ static constexpr ActionId_t MV_HELPER = 53;
static constexpr ActionId_t RM_HELPER = 54; static constexpr ActionId_t RM_HELPER = 54;
static constexpr ActionId_t MKDIR_HELPER = 55; static constexpr ActionId_t MKDIR_HELPER = 55;
static constexpr ActionId_t UPDATE_LEAP_SECONDS = 60;
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE;
static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM); static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM);

2
tmtc

@ -1 +1 @@
Subproject commit 73a4260f337aa39475baef999466b200c9123e62 Subproject commit c843356c8af22bf45a04c71c93813716c9d743ec