diff --git a/CHANGELOG.md b/CHANGELOG.md index 009ab806..12e6e1ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,10 +16,20 @@ will consitute of a breaking change warranting a new major release: # [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 wrong dimension of a matrix within the `MEKF`, which would lead to a seg fault, if the star tracker was available. +- Fixed case in which control values within the `AcsController` could become NaN. # [v7.7.0] 2024-02-29 diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index e1b48fd2..1f6fdec6 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -480,6 +480,16 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ successRecipient = commandedBy; 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: { return HasActionsIF::INVALID_ACTION_ID; } @@ -1411,6 +1421,9 @@ void CoreController::performMountedSdCardOperations() { if (not timeFileInitDone) { initClockFromTimeFile(); } + if (not leapSecondsInitDone) { + initLeapSeconds(); + } performRebootWatchdogHandling(false); performRebootCountersHandling(false); } @@ -2066,6 +2079,71 @@ ReturnValue_t CoreController::backupTimeFileHandler() { 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() { using namespace GpsHyperion; using namespace std; diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 79224ed2..1b1f9853 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -150,6 +150,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe std::string(core::LEGACY_REBOOT_WATCHDOG_FILE_NAME); const std::string REBOOT_WATCHDOG_FILE = "/" + 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 = "/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::TIME_FILE_NAME); const std::string REBOOT_COUNTERS_FILE = @@ -296,6 +298,7 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe std::string currMntPrefix; bool timeFileInitDone = false; + bool leapSecondsInitDone = false; bool performOneShotSdCardOpsSwitch = false; uint8_t shortSdCardCdCounter = 0; #if OBSW_THREAD_TRACING == 1 @@ -335,7 +338,11 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe void performMountedSdCardOperations(); ReturnValue_t initVersionFile(); + void initLeapSeconds(); + ReturnValue_t initLeapSecondsFromFile(); ReturnValue_t initClockFromTimeFile(); + ReturnValue_t actionUpdateLeapSeconds(const uint8_t* data); + ReturnValue_t writeLeapSecondsToFile(const uint16_t leapSeconds); ReturnValue_t performSdCardCheck(); ReturnValue_t backupTimeFileHandler(); ReturnValue_t initBootCopyFile(); diff --git a/common/config/eive/definitions.h b/common/config/eive/definitions.h index 0b63a017..4c96c3a5 100644 --- a/common/config/eive/definitions.h +++ b/common/config/eive/definitions.h @@ -20,6 +20,9 @@ static constexpr char OBSW_VERSION_FILE_PATH[] = "/usr/share/eive-obsw/obsw_vers // ISO8601 timestamp. 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_CFDP_APID = 0x66; static constexpr uint16_t EIVE_LOCAL_CFDP_ENTITY_ID = EIVE_CFDP_APID; diff --git a/fsfw b/fsfw index 516357d8..47b21caf 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 516357d855c07786b492e981230988186376d301 +Subproject commit 47b21caf5fa2a27c7ace89f960141b3f24c329ee diff --git a/mission/controller/acs/Guidance.cpp b/mission/controller/acs/Guidance.cpp index f9182cbd..0a70e003 100644 --- a/mission/controller/acs/Guidance.cpp +++ b/mission/controller/acs/Guidance.cpp @@ -273,7 +273,11 @@ void Guidance::limitReferenceRotation(const double xAxisIX[3], double quatIX[4]) QuaternionOperations::multiply(quatIXtilde, quatXI, quatXXtilde); 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)); VectorOperations::normalize(phiResidualVec, phiResidualVec, 3); diff --git a/mission/controller/acs/Igrf13Model.cpp b/mission/controller/acs/Igrf13Model.cpp index 4ae7c93a..b15edada 100644 --- a/mission/controller/acs/Igrf13Model.cpp +++ b/mission/controller/acs/Igrf13Model.cpp @@ -69,7 +69,8 @@ void Igrf13Model::magFieldComp(const double longitude, const double gcLatitude, magFieldModel[1] *= -1; magFieldModel[2] *= (-1 / sin(theta)); - double JD2000 = TimeSystems::convertUnixToJD2000(timeOfMagMeasurement); + double JD2000 = 0; + Clock::convertTimevalToJD2000(timeOfMagMeasurement, &JD2000); double UT1 = JD2000 / 36525.; double gst = @@ -93,7 +94,8 @@ void Igrf13Model::magFieldComp(const double longitude, const double gcLatitude, void Igrf13Model::updateCoeffGH(timeval timeOfMagMeasurement) { 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); for (int i = 0; i <= igrfOrder; i++) { for (int j = 0; j <= (igrfOrder - 1); j++) { diff --git a/mission/controller/acs/Igrf13Model.h b/mission/controller/acs/Igrf13Model.h index 9a7feb34..f0936b7f 100644 --- a/mission/controller/acs/Igrf13Model.h +++ b/mission/controller/acs/Igrf13Model.h @@ -16,11 +16,11 @@ #ifndef IGRF13MODEL_H_ #define IGRF13MODEL_H_ -#include #include #include #include #include +#include #include diff --git a/mission/controller/acs/SensorProcessing.cpp b/mission/controller/acs/SensorProcessing.cpp index ac82e891..46be5db2 100644 --- a/mission/controller/acs/SensorProcessing.cpp +++ b/mission/controller/acs/SensorProcessing.cpp @@ -180,7 +180,8 @@ void SensorProcessing::processSus( const AcsParameters::SunModelParameters *sunModelParameters, acsctrl::SusDataProcessed *susDataProcessed) { /* -------- Sun Model Direction (IJK frame) ------- */ - double JD2000 = TimeSystems::convertUnixToJD2000(timeAbsolute); + double JD2000 = 0; + Clock::convertTimevalToJD2000(timeAbsolute, &JD2000); // Julean Centuries double sunIjkModel[3] = {0.0, 0.0, 0.0}; diff --git a/mission/controller/acs/SensorProcessing.h b/mission/controller/acs/SensorProcessing.h index e5efba71..baa43117 100644 --- a/mission/controller/acs/SensorProcessing.h +++ b/mission/controller/acs/SensorProcessing.h @@ -4,13 +4,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include #include diff --git a/mission/sysDefs.h b/mission/sysDefs.h index 8fade60a..924b1a9e 100644 --- a/mission/sysDefs.h +++ b/mission/sysDefs.h @@ -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 REBOOT_WATCHDOG_FILE_NAME[] = "reboot_watchdog.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 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 MKDIR_HELPER = 55; +static constexpr ActionId_t UPDATE_LEAP_SECONDS = 60; + static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE; static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM); diff --git a/tmtc b/tmtc index 73a4260f..c843356c 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 73a4260f337aa39475baef999466b200c9123e62 +Subproject commit c843356c8af22bf45a04c71c93813716c9d743ec