Merge branch 'develop' into eggert/acs
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit

This commit is contained in:
Marius Eggert 2023-02-08 13:21:49 +01:00
commit 098fcc4f12
24 changed files with 289 additions and 198 deletions

View File

@ -18,34 +18,46 @@ change warranting a new major release:
# [unreleased] # [unreleased]
## Changed ## Changed
- added calculation of satellite velocity vector from GPS position data
- added detumble mode using GYR values - Readded calibration matrices for MGM calibration
- added inertial pointing mode - Added calculation of satellite velocity vector from GPS position data
- added nadir pointing mode - Added detumble mode using GYR values
- added ground station target mode - Added inertial pointing mode
- added antistiction for RWs - Added nadir pointing mode
- added `sunTargetSafe` differentiation for LEOP - Added ground station target mode
- added check for existance of `SD_0_SKEWED_PTG_FILE` and `SD_1_SKEWED_PTG_FILE` to determine - Added antistiction for RWs
- Added `sunTargetSafe` differentiation for LEOP
- Added check for existance of `SD_0_SKEWED_PTG_FILE` and `SD_1_SKEWED_PTG_FILE` to determine
which `sunTargetSafe` to use which `sunTargetSafe` to use
- added `gpsVelocity` and `gpsPosition` to `gpsProcessed` - Added `gpsVelocity` and `gpsPosition` to `gpsProcessed`
- removed deprecated `OutputValues` - Removed deprecated `OutputValues`
- added `HasParametersIF` to `AcsParameters` - Added `HasParametersIF` to `AcsParameters`
- added `ReceivesParameterMessagesIF` and `ParameterHelper` to `AcsController` - Added `ReceivesParameterMessagesIF` and `ParameterHelper` to `AcsController`
- updated `AcsParameters` with actual values and changed structure - Updated `AcsParameters` with actual values and changed structure
- sun vector model and magnetic field vector model calculations are always executed now - Sun vector model and magnetic field vector model calculations are always executed now
- `domainId` is now used as identifier for parameter structs - `domainId` is now used as identifier for parameter structs
- changed onboard GYR value handling from deg/s to rad/s - Changed onboard GYR value handling from deg/s to rad/s
## Fixed ## Fixed
- fixed calculation of model sun vector
- fixed calculation of model magnetic field vector - Single sourcing the version information into `CMakeLists.txt`. The `git describe` functionality
- fixed MEKF algorithm is only used to retrieve the git SHA hash now. Also removed `OBSWVersion.h` accordingly.
- fixed several variable initializations - Build system: Fixed small bug, where the version itself was
- fixed several variable types stored as the git SHA hash in `commonConfig.h`. This will be
- fixed use of `sunMagAngleMin` for safe mode an empty string now for regular versions.
- fixed MEKF not using correct `sampleTime` - Bump FSFW for important fix in PUS mode service.
- fixed assignment of `SUS0` and `SUS6` calibration matrices due to wiring being mixed up - Bugfixes in 'SensofProcessing' where previously MGM values would be calibrated before being
- various smaller bugfixes transformed in body RF. However, the calibration values are in the body RF. Also fixed the
validity flag of 'mgmVecTotDerivative'.
- Fixed calculation of model sun vector
- Fixed calculation of model magnetic field vector
- Fixed MEKF algorithm
- Fixed several variable initializations
- Fixed several variable types
- Fixed use of `sunMagAngleMin` for safe mode
- Fixed MEKF not using correct `sampleTime`
- Fixed assignment of `SUS0` and `SUS6` calibration matrices due to wiring being mixed up
- Various smaller bugfixes
# [v1.25.0] 2023-02-06 # [v1.25.0] 2023-02-06

View File

@ -9,9 +9,9 @@
# ############################################################################## # ##############################################################################
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR_IF_GIT_FAILS 1) set(OBSW_VERSION_MAJOR 1)
set(OBSW_VERSION_MINOR_IF_GIT_FAILS 25) set(OBSW_VERSION_MINOR 25)
set(OBSW_VERSION_REVISION_IF_GIT_FAILS 0) set(OBSW_VERSION_REVISION 0)
# set(CMAKE_VERBOSE TRUE) # set(CMAKE_VERBOSE TRUE)
@ -168,10 +168,13 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
set(GIT_INFO set(GIT_INFO
${GIT_INFO} ${GIT_INFO}
CACHE STRING "Version information retrieved with git describe") CACHE STRING "Version information retrieved with git describe")
list(GET GIT_INFO 1 OBSW_VERSION_MAJOR) # CMakeLists.txt is now single source of information. list(GET GIT_INFO 1
list(GET GIT_INFO 2 OBSW_VERSION_MINOR) # OBSW_VERSION_MAJOR) list(GET GIT_INFO 2 OBSW_VERSION_MINOR) list(GET
list(GET GIT_INFO 3 OBSW_VERSION_REVISION) # GIT_INFO 3 OBSW_VERSION_REVISION)
list(GET GIT_INFO 4 OBSW_VERSION_CST_GIT_SHA1) list(LENGTH GIT_INFO LIST_LEN)
if(LIST_LEN GREATER 4)
list(GET GIT_INFO 4 OBSW_VERSION_CST_GIT_SHA1)
endif()
if(NOT OBSW_VERSION_MAJOR) if(NOT OBSW_VERSION_MAJOR)
set(OBSW_VERSION_MAJOR ${OBSW_VERSION_MAJOR_IF_GIT_FAILS}) set(OBSW_VERSION_MAJOR ${OBSW_VERSION_MAJOR_IF_GIT_FAILS})
endif() endif()

View File

@ -7,7 +7,6 @@
#define FSFWCONFIG_OBSWCONFIG_H_ #define FSFWCONFIG_OBSWCONFIG_H_
#include "commonConfig.h" #include "commonConfig.h"
#include "OBSWVersion.h"
/*******************************************************************/ /*******************************************************************/
/** All of the following flags should be enabled for mission code */ /** All of the following flags should be enabled for mission code */

View File

@ -8,7 +8,6 @@
#include "commonConfig.h" #include "commonConfig.h"
#include "q7sConfig.h" #include "q7sConfig.h"
#include "OBSWVersion.h"
/*******************************************************************/ /*******************************************************************/
/** All of the following flags should be enabled for mission code */ /** All of the following flags should be enabled for mission code */

View File

@ -5,7 +5,7 @@
#include <fsfw/ipc/QueueFactory.h> #include <fsfw/ipc/QueueFactory.h>
#include <fsfw/tasks/TaskFactory.h> #include <fsfw/tasks/TaskFactory.h>
#include "OBSWVersion.h" #include "commonConfig.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/timemanager/Stopwatch.h" #include "fsfw/timemanager/Stopwatch.h"
#include "fsfw/version.h" #include "fsfw/version.h"
@ -179,6 +179,26 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() {
ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) { const uint8_t *data, size_t size) {
switch (actionId) { switch (actionId) {
case (ANNOUNCE_VERSION): {
uint32_t p1 = (common::OBSW_VERSION_MAJOR << 24) | (common::OBSW_VERSION_MINOR << 16) |
(common::OBSW_VERSION_REVISION << 8);
uint32_t p2 = 0;
if (strcmp("", common::OBSW_VERSION_CST_GIT_SHA1) != 0) {
p1 |= 1;
auto shaAsStr = std::string(common::OBSW_VERSION_CST_GIT_SHA1);
size_t posDash = shaAsStr.find("-");
auto gitHash = shaAsStr.substr(posDash + 2, 4);
// Only copy first 4 letters of git hash
memcpy(&p2, gitHash.c_str(), 4);
}
triggerEvent(VERSION_INFO, p1, p2);
return HasActionsIF::EXECUTION_FINISHED;
}
case (ANNOUNCE_CURRENT_IMAGE): {
triggerEvent(CURRENT_IMAGE_INFO, CURRENT_CHIP, CURRENT_COPY);
return HasActionsIF::EXECUTION_FINISHED;
}
case (LIST_DIRECTORY_INTO_FILE): { case (LIST_DIRECTORY_INTO_FILE): {
return actionListDirectoryIntoFile(actionId, commandedBy, data, size); return actionListDirectoryIntoFile(actionId, commandedBy, data, size);
} }
@ -673,9 +693,9 @@ ReturnValue_t CoreController::initVersionFile() {
sif::warning << "CoreController::versionFileInit: Retrieving uname line failed" << std::endl; sif::warning << "CoreController::versionFileInit: Retrieving uname line failed" << std::endl;
} }
std::string fullObswVersionString = "OBSW: v" + std::to_string(SW_VERSION) + "." + std::string fullObswVersionString = "OBSW: v" + std::to_string(common::OBSW_VERSION_MAJOR) + "." +
std::to_string(SW_SUBVERSION) + "." + std::to_string(common::OBSW_VERSION_MINOR) + "." +
std::to_string(SW_REVISION); std::to_string(common::OBSW_VERSION_REVISION);
char versionString[16] = {}; char versionString[16] = {};
fsfw::FSFW_VERSION.getVersion(versionString, sizeof(versionString)); fsfw::FSFW_VERSION.getVersion(versionString, sizeof(versionString));
std::string fullFsfwVersionString = "FSFW: v" + std::string(versionString); std::string fullFsfwVersionString = "FSFW: v" + std::string(versionString);

View File

@ -74,6 +74,8 @@ class CoreController : public ExtendedControllerBase {
static constexpr dur_millis_t DEFAULT_SD_CARD_CHECK_TIMEOUT = 60000; static constexpr dur_millis_t DEFAULT_SD_CARD_CHECK_TIMEOUT = 60000;
static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0;
static constexpr ActionId_t ANNOUNCE_VERSION = 1;
static constexpr ActionId_t ANNOUNCE_CURRENT_IMAGE = 2;
static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5; static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5;
static constexpr ActionId_t RESET_REBOOT_COUNTERS = 6; static constexpr ActionId_t RESET_REBOOT_COUNTERS = 6;
static constexpr ActionId_t SWITCH_IMG_LOCK = 7; static constexpr ActionId_t SWITCH_IMG_LOCK = 7;
@ -109,6 +111,12 @@ class CoreController : public ExtendedControllerBase {
//! [EXPORT] : [COMMENT] No SD card was active. Core controller will attempt to re-initialize //! [EXPORT] : [COMMENT] No SD card was active. Core controller will attempt to re-initialize
//! a SD card. //! a SD card.
static constexpr Event NO_SD_CARD_ACTIVE = event::makeEvent(SUBSYSTEM_ID, 4, severity::HIGH); static constexpr Event NO_SD_CARD_ACTIVE = event::makeEvent(SUBSYSTEM_ID, 4, severity::HIGH);
//! [EXPORT] : [COMMENT]
//! 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.
static constexpr Event VERSION_INFO = event::makeEvent(SUBSYSTEM_ID, 5, severity::INFO);
//! [EXPORT] : [COMMENT] P1: Current Chip, P2: Current Copy
static constexpr Event CURRENT_IMAGE_INFO = event::makeEvent(SUBSYSTEM_ID, 6, severity::INFO);
CoreController(object_id_t objectId); CoreController(object_id_t objectId);
virtual ~CoreController(); virtual ~CoreController();

View File

@ -4,7 +4,7 @@
# 2. Major version # 2. Major version
# 3. Minor version # 3. Minor version
# 4. Revision # 4. Revision
# 5. git SHA hash and commits since tag # 5. (Optional) git SHA hash and commits since tag when applicable
function(determine_version_with_git) function(determine_version_with_git)
include(GetGitRevisionDescription) include(GetGitRevisionDescription)
git_describe(VERSION ${ARGN}) git_describe(VERSION ${ARGN})
@ -22,7 +22,9 @@ function(determine_version_with_git)
list(APPEND GIT_INFO ${_VERSION_MAJOR}) list(APPEND GIT_INFO ${_VERSION_MAJOR})
list(APPEND GIT_INFO ${_VERSION_MINOR}) list(APPEND GIT_INFO ${_VERSION_MINOR})
list(APPEND GIT_INFO ${_VERSION_PATCH}) list(APPEND GIT_INFO ${_VERSION_PATCH})
list(APPEND GIT_INFO ${VERSION_SHA1}) if(NOT VERSION_SHA1 STREQUAL VERSION)
list(APPEND GIT_INFO ${VERSION_SHA1})
endif()
set(GIT_INFO ${GIT_INFO} PARENT_SCOPE) set(GIT_INFO ${GIT_INFO} PARENT_SCOPE)
message(STATUS "eive | Set git version info into GIT_INFO from the git tag ${VERSION}") message(STATUS "eive | Set git version info into GIT_INFO from the git tag ${VERSION}")
endfunction() endfunction()

View File

@ -1,10 +0,0 @@
#ifndef COMMON_CONFIG_OBSWVERSION_H_
#define COMMON_CONFIG_OBSWVERSION_H_
const char* const SW_NAME = "eive";
#define SW_VERSION 1
#define SW_SUBVERSION 12
#define SW_REVISION 1
#endif /* COMMON_CONFIG_OBSWVERSION_H_ */

2
fsfw

@ -1 +1 @@
Subproject commit 38789e053b65cfa14604fc625e7bcc8ca03a3f17 Subproject commit 84bbef016712096147e8cf3f2cec87f317d9e7e7

View File

@ -244,3 +244,5 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14002;0x36b2;REBOOT_MECHANISM_TRIGGERED;MEDIUM;The reboot mechanism was triggered. P1: First 16 bits: Last Chip, Last 16 bits: Last Copy, P2: Each byte is the respective reboot count for the slots;bsp_q7s/core/CoreController.h 14002;0x36b2;REBOOT_MECHANISM_TRIGGERED;MEDIUM;The reboot mechanism was triggered. P1: First 16 bits: Last Chip, Last 16 bits: Last Copy, P2: Each byte is the respective reboot count for the slots;bsp_q7s/core/CoreController.h
14003;0x36b3;REBOOT_HW;MEDIUM;;bsp_q7s/core/CoreController.h 14003;0x36b3;REBOOT_HW;MEDIUM;;bsp_q7s/core/CoreController.h
14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;bsp_q7s/core/CoreController.h 14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;bsp_q7s/core/CoreController.h
14005;0x36b5;VERSION_INFO;INFO;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.;bsp_q7s/core/CoreController.h
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
244 14002 0x36b2 REBOOT_MECHANISM_TRIGGERED MEDIUM The reboot mechanism was triggered. P1: First 16 bits: Last Chip, Last 16 bits: Last Copy, P2: Each byte is the respective reboot count for the slots bsp_q7s/core/CoreController.h
245 14003 0x36b3 REBOOT_HW MEDIUM bsp_q7s/core/CoreController.h
246 14004 0x36b4 NO_SD_CARD_ACTIVE HIGH No SD card was active. Core controller will attempt to re-initialize a SD card. bsp_q7s/core/CoreController.h
247 14005 0x36b5 VERSION_INFO INFO 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. bsp_q7s/core/CoreController.h
248 14006 0x36b6 CURRENT_IMAGE_INFO INFO P1: Current Chip, P2: Current Copy bsp_q7s/core/CoreController.h

View File

@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 245 translations. * @brief Auto-generated event translation file. Contains 247 translations.
* @details * @details
* Generated on: 2023-02-03 10:52:53 * Generated on: 2023-02-08 11:22:40
*/ */
#include "translateEvents.h" #include "translateEvents.h"
@ -245,6 +245,8 @@ const char *REBOOT_SW_STRING = "REBOOT_SW";
const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED"; const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED";
const char *REBOOT_HW_STRING = "REBOOT_HW"; const char *REBOOT_HW_STRING = "REBOOT_HW";
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE"; const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
const char *VERSION_INFO_STRING = "VERSION_INFO";
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
const char *translateEvents(Event event) { const char *translateEvents(Event event) {
switch ((event & 0xFFFF)) { switch ((event & 0xFFFF)) {
@ -728,6 +730,10 @@ const char *translateEvents(Event event) {
return REBOOT_HW_STRING; return REBOOT_HW_STRING;
case (14004): case (14004):
return NO_SD_CARD_ACTIVE_STRING; return NO_SD_CARD_ACTIVE_STRING;
case (14005):
return VERSION_INFO_STRING;
case (14006):
return CURRENT_IMAGE_INFO_STRING;
default: default:
return "UNKNOWN_EVENT"; return "UNKNOWN_EVENT";
} }

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 152 translations. * Contains 152 translations.
* Generated on: 2023-02-03 10:52:53 * Generated on: 2023-02-08 11:22:40
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@ -34,7 +34,6 @@ ReturnValue_t GpsHyperionLinuxController::checkModeCommand(Mode_t mode, Submode_
uint32_t *msToReachTheMode) { uint32_t *msToReachTheMode) {
if (not modeCommanded) { if (not modeCommanded) {
if (mode == MODE_ON or mode == MODE_OFF) { if (mode == MODE_ON or mode == MODE_OFF) {
gpsNotOpenSwitch = true;
// 5h time to reach fix // 5h time to reach fix
*msToReachTheMode = MAX_SECONDS_TO_REACH_FIX; *msToReachTheMode = MAX_SECONDS_TO_REACH_FIX;
maxTimeToReachFix.resetTimer(); maxTimeToReachFix.resetTimer();
@ -44,7 +43,12 @@ ReturnValue_t GpsHyperionLinuxController::checkModeCommand(Mode_t mode, Submode_
} }
} }
if (mode == MODE_OFF) { if (mode == MODE_OFF) {
PoolReadGuard pg(&gpsSet);
gpsSet.setValidity(false, true); gpsSet.setValidity(false, true);
// There can't be a fix with a device that is off.
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, 0);
oneShotSwitches.reset();
modeCommanded = false;
} }
return returnvalue::OK; return returnvalue::OK;
} }
@ -101,6 +105,7 @@ ReturnValue_t GpsHyperionLinuxController::performOperation(uint8_t opCode) {
if (not callAgainImmediately) { if (not callAgainImmediately) {
handleQueue(); handleQueue();
poolManager.performHkOperation(); poolManager.performHkOperation();
TaskFactory::delayTask(250);
} }
} }
// Should never be reached. // Should never be reached.
@ -113,25 +118,24 @@ ReturnValue_t GpsHyperionLinuxController::initialize() {
return result; return result;
} }
auto openError = [&](const char *type, int error) { auto openError = [&](const char *type, int error) {
if (gpsNotOpenSwitch) { // Opening failed
// Opening failed
#if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_VERBOSE_LEVEL >= 1
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Opening GPSMM " << type sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Opening GPSMM " << type
<< " failed | Error " << error << " | " << gps_errstr(error) << std::endl; << " failed | Error " << error << " | " << gps_errstr(error) << std::endl;
#endif #endif
gpsNotOpenSwitch = false;
}
}; };
if (readMode == ReadModes::SOCKET) { if (readMode == ReadModes::SOCKET) {
int retval = gps_open("localhost", DEFAULT_GPSD_PORT, &gps); int retval = gps_open("localhost", DEFAULT_GPSD_PORT, &gps);
if (retval != 0) { if (retval != 0) {
openError("Socket", retval); openError("Socket", retval);
return ObjectManager::CHILD_INIT_FAILED;
} }
gps_stream(&gps, WATCH_ENABLE | WATCH_JSON, nullptr); gps_stream(&gps, WATCH_ENABLE | WATCH_JSON, nullptr);
} else if (readMode == ReadModes::SHM) { } else if (readMode == ReadModes::SHM) {
int retval = gps_open(GPSD_SHARED_MEMORY, "", &gps); int retval = gps_open(GPSD_SHARED_MEMORY, "", &gps);
if (retval != 0) { if (retval != 0) {
openError("SHM", retval); openError("SHM", retval);
return ObjectManager::CHILD_INIT_FAILED;
} }
} }
return result; return result;
@ -145,32 +149,33 @@ void GpsHyperionLinuxController::performControlOperation() {}
bool GpsHyperionLinuxController::readGpsDataFromGpsd() { bool GpsHyperionLinuxController::readGpsDataFromGpsd() {
auto readError = [&]() { auto readError = [&]() {
if (gpsReadFailedSwitch) { if (oneShotSwitches.gpsReadFailedSwitch) {
gpsReadFailedSwitch = false; oneShotSwitches.gpsReadFailedSwitch = false;
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Reading GPS data failed | " sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Reading GPS data failed | "
"Error " "Error "
<< errno << " | " << gps_errstr(errno) << std::endl; << errno << " | " << gps_errstr(errno) << std::endl;
} }
}; };
// GPS is off, no point in reading data from GPSD.
if(mode == MODE_OFF) {
return false;
}
if (readMode == ReadModes::SOCKET) { if (readMode == ReadModes::SOCKET) {
// Perform other necessary handling if not data seen for 0.2 seconds. // Poll the GPS.
if (gps_waiting(&gps, 200000)) { if (gps_waiting(&gps, 0)) {
if (-1 == gps_read(&gps)) { if (-1 == gps_read(&gps)) {
readError(); readError();
return false; return false;
} }
oneShotSwitches.gpsReadFailedSwitch = true;
if (MODE_SET != (MODE_SET & gps.set)) { if (MODE_SET != (MODE_SET & gps.set)) {
if (mode == MODE_ON) { if (mode != MODE_OFF and maxTimeToReachFix.hasTimedOut() and
if (noModeSetCntr >= 0) { oneShotSwitches.cantGetFixSwitch) {
noModeSetCntr++; sif::warning
} << "GPSHyperionHandler::readGpsDataFromGpsd: No mode could be set in allowed "
if (noModeSetCntr == 10) { << maxTimeToReachFix.timeout / 1000 << " seconds" << std::endl;
// TODO: Trigger event here triggerEvent(GpsHyperion::CANT_GET_FIX, maxTimeToReachFix.timeout);
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: No mode could be " oneShotSwitches.cantGetFixSwitch = false;
"read for 10 consecutive reads"
<< std::endl;
noModeSetCntr = -1;
}
// did not event get mode, nothing to see. // did not event get mode, nothing to see.
return false; return false;
} }
@ -198,51 +203,58 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
} }
bool validFix = false; bool validFix = false;
static_cast<void>(validFix);
// 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix // 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix
int newFixMode = gps.fix.mode; if (gps.fix.mode == 2 or gps.fix.mode == 3) {
if (newFixMode == 2 or newFixMode == 3) {
validFix = true; validFix = true;
} }
if (gpsSet.fixMode.value != newFixMode) { if (gpsSet.fixMode.value != gps.fix.mode) {
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, newFixMode); triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, gps.fix.mode);
} }
gpsSet.fixMode.value = newFixMode; gpsSet.fixMode.value = gps.fix.mode;
if (gps.fix.mode == 0 or gps.fix.mode == 1) { if (gps.fix.mode == 0 or gps.fix.mode == 1) {
if (modeCommanded and maxTimeToReachFix.hasTimedOut()) { if (modeCommanded and maxTimeToReachFix.hasTimedOut()) {
// We are supposed to be on and functioning, but not fix was found // We are supposed to be on and functioning, but no fix was found
if (mode == MODE_ON or mode == MODE_NORMAL) { if (mode == MODE_ON or mode == MODE_NORMAL) {
mode = MODE_OFF; mode = MODE_OFF;
} }
modeCommanded = false; modeCommanded = false;
} }
gpsSet.setValidity(false, true); gpsSet.setValidity(false, true);
} else if (gps.satellites_used > 0) { } else if (gps.satellites_used > 0 && validFix && mode != MODE_OFF) {
gpsSet.setValidity(true, true); gpsSet.setValidity(true, true);
} }
gpsSet.satInUse.value = gps.satellites_used; gpsSet.satInUse.value = gps.satellites_used;
gpsSet.satInView.value = gps.satellites_visible; gpsSet.satInView.value = gps.satellites_visible;
bool latValid = false;
if (std::isfinite(gps.fix.latitude)) { if (std::isfinite(gps.fix.latitude)) {
// Negative latitude -> South direction // Negative latitude -> South direction
gpsSet.latitude.value = gps.fix.latitude; gpsSet.latitude.value = gps.fix.latitude;
} else { if (gps.fix.mode >= 2) {
gpsSet.latitude.setValid(false); latValid = true;
}
} }
gpsSet.latitude.setValid(latValid);
bool longValid = false;
if (std::isfinite(gps.fix.longitude)) { if (std::isfinite(gps.fix.longitude)) {
// Negative longitude -> West direction // Negative longitude -> West direction
gpsSet.longitude.value = gps.fix.longitude; gpsSet.longitude.value = gps.fix.longitude;
} else { if (gps.fix.mode >= 2) {
gpsSet.longitude.setValid(false); longValid = true;
}
} }
gpsSet.latitude.setValid(longValid);
bool altitudeValid = false;
if (std::isfinite(gps.fix.altitude)) { if (std::isfinite(gps.fix.altitude)) {
gpsSet.altitude.value = gps.fix.altitude; gpsSet.altitude.value = gps.fix.altitude;
} else { if (gps.fix.mode == 3) {
gpsSet.altitude.setValid(false); altitudeValid = true;
}
} }
gpsSet.altitude.setValid(altitudeValid);
if (std::isfinite(gps.fix.speed)) { if (std::isfinite(gps.fix.speed)) {
gpsSet.speed.value = gps.fix.speed; gpsSet.speed.value = gps.fix.speed;
@ -250,59 +262,44 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
gpsSet.speed.setValid(false); gpsSet.speed.setValid(false);
} }
if (TIME_SET == (TIME_SET & gps.set)) {
timeval time = {};
#if LIBGPS_VERSION_MINOR <= 17 #if LIBGPS_VERSION_MINOR <= 17
gpsSet.unixSeconds.value = gps.fix.time; gpsSet.unixSeconds.value = std::floor(gps.fix.time);
double fractionalPart = gps.fix.time - gpsSet.unixSeconds.value;
time.tv_usec = fractionalPart * 1000.0 * 1000.0;
#else #else
gpsSet.unixSeconds.value = gps.fix.time.tv_sec; gpsSet.unixSeconds.value = gps.fix.time.tv_sec;
time.tv_usec = gps.fix.time.tv_nsec / 1000;
#endif #endif
timeval time = {}; time.tv_sec = gpsSet.unixSeconds.value;
time.tv_sec = gpsSet.unixSeconds.value; // If the time is totally wrong (e.g. year 2000 after system reset because we do not have a RTC
#if LIBGPS_VERSION_MINOR <= 17 // and no time file available) we set it with the roughly valid time from the GPS.
double fractionalPart = gps.fix.time - std::floor(gps.fix.time); // NTP might only work if the time difference between sys time and current time is not too
time.tv_usec = fractionalPart * 1000.0 * 1000.0; // large.
#else overwriteTimeIfNotSane(time, validFix);
time.tv_usec = gps.fix.time.tv_nsec / 1000; Clock::TimeOfDay_t timeOfDay = {};
#endif Clock::convertTimevalToTimeOfDay(&time, &timeOfDay);
std::time_t t = std::time(nullptr); gpsSet.year = timeOfDay.year;
if (time.tv_sec == t) { gpsSet.month = timeOfDay.month;
timeIsConstantCounter++; gpsSet.day = timeOfDay.day;
gpsSet.hours = timeOfDay.hour;
gpsSet.minutes = timeOfDay.minute;
gpsSet.seconds = timeOfDay.second;
} else { } else {
timeIsConstantCounter = 0; gpsSet.unixSeconds.setValid(false);
} gpsSet.year.setValid(false);
if (timeInit and validFix) { gpsSet.month.setValid(false);
if (not utility::timeSanityCheck()) { gpsSet.day.setValid(false);
#if OBSW_VERBOSE_LEVEL >= 1 gpsSet.hours.setValid(false);
time_t timeRaw = time.tv_sec; gpsSet.minutes.setValid(false);
std::tm *timeTm = std::gmtime(&timeRaw); gpsSet.seconds.setValid(false);
sif::info << "Setting invalid system time from GPS data directly: "
<< std::put_time(timeTm, "%c %Z") << std::endl;
#endif
// For some reason, the clock needs to be somewhat correct for NTP to work. Really dumb..
Clock::setClock(&time);
}
timeInit = false;
}
// If the received time does not change anymore for whatever reason, do not set it here
// to avoid stale times. Also, don't do it too often often to avoid jumping times
if (timeIsConstantCounter < 20 and timeUpdateCd.hasTimedOut()) {
// Update the system time here for now. NTP seems to be unable to do so for whatever reason.
// Further tests have shown that the time seems to be set by NTPD after some time..
// Clock::setClock(&time);
timeUpdateCd.resetTimer();
} }
Clock::TimeOfDay_t timeOfDay = {};
Clock::convertTimevalToTimeOfDay(&time, &timeOfDay);
gpsSet.year = timeOfDay.year;
gpsSet.month = timeOfDay.month;
gpsSet.day = timeOfDay.day;
gpsSet.hours = timeOfDay.hour;
gpsSet.minutes = timeOfDay.minute;
gpsSet.seconds = timeOfDay.second;
if (debugHyperionGps) { if (debugHyperionGps) {
sif::info << "-- Hyperion GPS Data --" << std::endl; sif::info << "-- Hyperion GPS Data --" << std::endl;
#if LIBGPS_VERSION_MINOR <= 17 #if LIBGPS_VERSION_MINOR <= 17
time_t timeRaw = gps.fix.time; time_t timeRaw = gpsSet.unixSeconds.value;
#else #else
time_t timeRaw = gps.fix.time.tv_sec; time_t timeRaw = gps.fix.time.tv_sec;
#endif #endif
@ -325,3 +322,19 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
} }
return returnvalue::OK; return returnvalue::OK;
} }
void GpsHyperionLinuxController::overwriteTimeIfNotSane(timeval time, bool validFix) {
if (not timeInit and validFix) {
if (not utility::timeSanityCheck()) {
#if OBSW_VERBOSE_LEVEL >= 1
time_t timeRaw = time.tv_sec;
std::tm *timeTm = std::gmtime(&timeRaw);
sif::info << "Overwriting invalid system time from GPS data directly: "
<< std::put_time(timeTm, "%c %Z") << std::endl;
#endif
// For some reason, the clock needs to be somewhat correct for NTP to work. Really dumb..
Clock::setClock(&time);
}
timeInit = true;
}
}

View File

@ -58,18 +58,30 @@ class GpsHyperionLinuxController : public ExtendedControllerBase {
const char* currentClientBuf = nullptr; const char* currentClientBuf = nullptr;
ReadModes readMode = ReadModes::SOCKET; ReadModes readMode = ReadModes::SOCKET;
Countdown maxTimeToReachFix = Countdown(MAX_SECONDS_TO_REACH_FIX * 1000); Countdown maxTimeToReachFix = Countdown(MAX_SECONDS_TO_REACH_FIX * 1000);
bool modeCommanded = true; bool modeCommanded = false;
bool timeInit = true; bool timeInit = false;
bool gpsNotOpenSwitch = true;
bool gpsReadFailedSwitch = true; struct OneShotSwitches {
void reset() {
gpsReadFailedSwitch = true;
cantGetFixSwitch = true;
}
bool gpsReadFailedSwitch = true;
bool cantGetFixSwitch = true;
} oneShotSwitches;
bool debugHyperionGps = false; bool debugHyperionGps = false;
int32_t noModeSetCntr = 0; int32_t noModeSetCntr = 0;
uint32_t timeIsConstantCounter = 0;
Countdown timeUpdateCd = Countdown(60); Countdown timeUpdateCd = Countdown(60);
// Returns true if the function should be called again or false if other // Returns true if the function should be called again or false if other
// controller handling can be done. // controller handling can be done.
bool readGpsDataFromGpsd(); bool readGpsDataFromGpsd();
// If the time is totally wrong (e.g. year 2000 after system reset because we do not have a RTC)
// we set it with the roughly valid time from the GPS. For some reason, NTP might only work
// if the time difference between sys time and current time is not too large
void overwriteTimeIfNotSane(timeval time, bool validFix);
}; };
#endif /* MISSION_DEVICES_GPSHYPERIONHANDLER_H_ */ #endif /* MISSION_DEVICES_GPSHYPERIONHANDLER_H_ */

View File

@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 245 translations. * @brief Auto-generated event translation file. Contains 247 translations.
* @details * @details
* Generated on: 2023-02-03 10:52:53 * Generated on: 2023-02-08 11:22:40
*/ */
#include "translateEvents.h" #include "translateEvents.h"
@ -245,6 +245,8 @@ const char *REBOOT_SW_STRING = "REBOOT_SW";
const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED"; const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED";
const char *REBOOT_HW_STRING = "REBOOT_HW"; const char *REBOOT_HW_STRING = "REBOOT_HW";
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE"; const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
const char *VERSION_INFO_STRING = "VERSION_INFO";
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
const char *translateEvents(Event event) { const char *translateEvents(Event event) {
switch ((event & 0xFFFF)) { switch ((event & 0xFFFF)) {
@ -728,6 +730,10 @@ const char *translateEvents(Event event) {
return REBOOT_HW_STRING; return REBOOT_HW_STRING;
case (14004): case (14004):
return NO_SD_CARD_ACTIVE_STRING; return NO_SD_CARD_ACTIVE_STRING;
case (14005):
return VERSION_INFO_STRING;
case (14006):
return CURRENT_IMAGE_INFO_STRING;
default: default:
return "UNKNOWN_EVENT"; return "UNKNOWN_EVENT";
} }

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 152 translations. * Contains 152 translations.
* Generated on: 2023-02-03 10:52:53 * Generated on: 2023-02-08 11:22:40
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@ -7,7 +7,7 @@
namespace acs { namespace acs {
enum CtrlSubmode { enum CtrlSubmode {
OFF = HasModesIF::MODE_OFF, OFF = HasModesIF::SUBMODE_NONE,
SAFE = 10, SAFE = 10,
DETUMBLE = 11, DETUMBLE = 11,
PTG_IDLE = 12, PTG_IDLE = 12,

View File

@ -563,7 +563,7 @@ ReturnValue_t AcsController::checkModeCommand(Mode_t mode, Submode_t submode,
return INVALID_SUBMODE; return INVALID_SUBMODE;
} }
} else if ((mode == MODE_ON) || (mode == MODE_NORMAL)) { } else if ((mode == MODE_ON) || (mode == MODE_NORMAL)) {
if ((submode > 8) || (submode < 2)) { if ((submode > acs::PTG_TARGET_INERTIAL) || (submode < acs::SAFE)) {
return INVALID_SUBMODE; return INVALID_SUBMODE;
} else { } else {
return returnvalue::OK; return returnvalue::OK;

View File

@ -51,26 +51,28 @@ class AcsParameters : public HasParametersIF {
float mgm3orientationMatrix[3][3] = {{0, 0, 1}, {0, -1, 0}, {1, 0, 0}}; float mgm3orientationMatrix[3][3] = {{0, 0, 1}, {0, -1, 0}, {1, 0, 0}};
float mgm4orientationMatrix[3][3] = {{0, 0, -1}, {-1, 0, 0}, {0, 1, 0}}; float mgm4orientationMatrix[3][3] = {{0, 0, -1}, {-1, 0, 0}, {0, 1, 0}};
float mgm0hardIronOffset[3] = {0.0, 0.0, 0.0}; //{19.89364, -29.94111, -31.07508}; float mgm0hardIronOffset[3] = {6.116487, 6.796264, -19.188060};
float mgm1hardIronOffset[3] = {0.0, 0.0, 0.0}; //{10.95500, -8.053403, -33.36383}; float mgm1hardIronOffset[3] = {-1.077152, 2.080583, 1.974483};
float mgm2hardIronOffset[3] = {0.0, 0.0, 0.0}; //{15.72181, -26.87090, -62.19010}; float mgm2hardIronOffset[3] = {-19.285857, 5.401821, -16.096297};
float mgm3hardIronOffset[3] = {0.0, 0.0, 0.0}; float mgm3hardIronOffset[3] = {-0.634033, 2.787695, 0.092036};
float mgm4hardIronOffset[3] = {0.0, 0.0, 0.0}; float mgm4hardIronOffset[3] = {2.702743, 5.236043, 0.726229};
float mgm0softIronInverse[3][3] = {{0.910192, -0.188413, -0.161522},
{-0.188413, 1.642303, -0.033184},
{-0.161522, -0.033184, 0.943904}};
float mgm1softIronInverse[3][3] = {{1.053508, -0.170225, -0.041678},
{-0.170225, 1.274465, -0.040231},
{-0.041678, -0.040231, 1.086352}};
float mgm2softIronInverse[3][3] = {{0.931086, 0.172675, -0.043084},
{0.172675, 1.541296, 0.065489},
{-0.043084, 0.065489, 1.001238}};
float mgm3softIronInverse[3][3] = {{1.073353, 0.177266, -0.058832},
{0.177266, 1.262156, 0.010478},
{-0.058832, 0.010478, 1.068345}};
float mgm4softIronInverse[3][3] = {{1.114887, -0.007534, -0.037072},
{-0.007534, 1.253879, 0.006812},
{-0.037072, 0.006812, 1.313158}};
float mgm0softIronInverse[3][3] = {
{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; /*{{1420.727e-3, 9.352825e-3,
-127.1979e-3}, {9.352825e-3, 1031.965e-3, -80.02734e-3},
{-127.1979e-3, -80.02734e-3, 934.8899e-3}};*/
float mgm1softIronInverse[3][3] = {
{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; /*{{126.7325e-2, -4.146410e-2, -18.37963e-2},
{-4.146410e-2, 109.3310e-2, -5.246314e-2},
{-18.37963e-2, -5.246314e-2, 105.7300e-2}};*/
float mgm2softIronInverse[3][3] = {
{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; /*{{143.0438e-2, 7.095763e-2,
15.67482e-2}, {7.095763e-2, 99.65167e-2, -6.958760e-2},
{15.67482e-2, -6.958760e-2, 94.50124e-2}};*/
float mgm3softIronInverse[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
float mgm4softIronInverse[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
float mgm02variance[3] = {1, 1, 1}; float mgm02variance[3] = {1, 1, 1};
float mgm13variance[3] = {1, 1, 1}; float mgm13variance[3] = {1, 1, 1};
float mgm4variance[3] = {1, 1, 1}; float mgm4variance[3] = {1, 1, 1};

View File

@ -69,71 +69,72 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
float mgm0ValueNoBias[3] = {0, 0, 0}, mgm1ValueNoBias[3] = {0, 0, 0}, float mgm0ValueNoBias[3] = {0, 0, 0}, mgm1ValueNoBias[3] = {0, 0, 0},
mgm2ValueNoBias[3] = {0, 0, 0}, mgm3ValueNoBias[3] = {0, 0, 0}, mgm2ValueNoBias[3] = {0, 0, 0}, mgm3ValueNoBias[3] = {0, 0, 0},
mgm4ValueNoBias[3] = {0, 0, 0}; mgm4ValueNoBias[3] = {0, 0, 0};
float mgm0ValueCalib[3] = {0, 0, 0}, mgm1ValueCalib[3] = {0, 0, 0}, mgm2ValueCalib[3] = {0, 0, 0},
mgm3ValueCalib[3] = {0, 0, 0}, mgm4ValueCalib[3] = {0, 0, 0};
float mgm0ValueBody[3] = {0, 0, 0}, mgm1ValueBody[3] = {0, 0, 0}, mgm2ValueBody[3] = {0, 0, 0}, float mgm0ValueBody[3] = {0, 0, 0}, mgm1ValueBody[3] = {0, 0, 0}, mgm2ValueBody[3] = {0, 0, 0},
mgm3ValueBody[3] = {0, 0, 0}, mgm4ValueBody[3] = {0, 0, 0}; mgm3ValueBody[3] = {0, 0, 0}, mgm4ValueBody[3] = {0, 0, 0};
float mgm0ValueCalib[3] = {0, 0, 0}, mgm1ValueCalib[3] = {0, 0, 0}, mgm2ValueCalib[3] = {0, 0, 0},
mgm3ValueCalib[3] = {0, 0, 0}, mgm4ValueCalib[3] = {0, 0, 0};
float sensorFusionNumerator[3] = {0, 0, 0}, sensorFusionDenominator[3] = {0, 0, 0}; float sensorFusionNumerator[3] = {0, 0, 0}, sensorFusionDenominator[3] = {0, 0, 0};
if (mgm0valid) { if (mgm0valid) {
VectorOperations<float>::subtract(mgm0Value, mgmParameters->mgm0hardIronOffset, mgm0ValueNoBias, MatrixOperations<float>::multiply(mgmParameters->mgm0orientationMatrix[0], mgm0Value,
3); mgm0ValueBody, 3, 3, 1);
VectorOperations<float>::subtract(mgm0ValueBody, mgmParameters->mgm0hardIronOffset,
mgm0ValueNoBias, 3);
MatrixOperations<float>::multiply(mgmParameters->mgm0softIronInverse[0], mgm0ValueNoBias, MatrixOperations<float>::multiply(mgmParameters->mgm0softIronInverse[0], mgm0ValueNoBias,
mgm0ValueCalib, 3, 3, 1); mgm0ValueCalib, 3, 3, 1);
MatrixOperations<float>::multiply(mgmParameters->mgm0orientationMatrix[0], mgm0ValueCalib,
mgm0ValueBody, 3, 3, 1);
for (uint8_t i = 0; i < 3; i++) { for (uint8_t i = 0; i < 3; i++) {
sensorFusionNumerator[i] += mgm0ValueBody[i] / mgmParameters->mgm02variance[i]; sensorFusionNumerator[i] += mgm0ValueCalib[i] / mgmParameters->mgm02variance[i];
sensorFusionDenominator[i] += 1 / mgmParameters->mgm02variance[i]; sensorFusionDenominator[i] += 1 / mgmParameters->mgm02variance[i];
} }
} }
if (mgm1valid) { if (mgm1valid) {
VectorOperations<float>::subtract(mgm1Value, mgmParameters->mgm1hardIronOffset, mgm1ValueNoBias, MatrixOperations<float>::multiply(mgmParameters->mgm1orientationMatrix[0], mgm1Value,
3); mgm1ValueBody, 3, 3, 1);
VectorOperations<float>::subtract(mgm1ValueBody, mgmParameters->mgm1hardIronOffset,
mgm1ValueNoBias, 3);
MatrixOperations<float>::multiply(mgmParameters->mgm1softIronInverse[0], mgm1ValueNoBias, MatrixOperations<float>::multiply(mgmParameters->mgm1softIronInverse[0], mgm1ValueNoBias,
mgm1ValueCalib, 3, 3, 1); mgm1ValueCalib, 3, 3, 1);
MatrixOperations<float>::multiply(mgmParameters->mgm1orientationMatrix[0], mgm1ValueCalib,
mgm1ValueBody, 3, 3, 1);
for (uint8_t i = 0; i < 3; i++) { for (uint8_t i = 0; i < 3; i++) {
sensorFusionNumerator[i] += mgm1ValueBody[i] / mgmParameters->mgm13variance[i]; sensorFusionNumerator[i] += mgm1ValueCalib[i] / mgmParameters->mgm13variance[i];
sensorFusionDenominator[i] += 1 / mgmParameters->mgm13variance[i]; sensorFusionDenominator[i] += 1 / mgmParameters->mgm13variance[i];
} }
} }
if (mgm2valid) { if (mgm2valid) {
VectorOperations<float>::subtract(mgm2Value, mgmParameters->mgm2hardIronOffset, mgm2ValueNoBias, MatrixOperations<float>::multiply(mgmParameters->mgm2orientationMatrix[0], mgm2Value,
3); mgm2ValueBody, 3, 3, 1);
VectorOperations<float>::subtract(mgm2ValueBody, mgmParameters->mgm2hardIronOffset,
mgm2ValueNoBias, 3);
MatrixOperations<float>::multiply(mgmParameters->mgm2softIronInverse[0], mgm2ValueNoBias, MatrixOperations<float>::multiply(mgmParameters->mgm2softIronInverse[0], mgm2ValueNoBias,
mgm2ValueCalib, 3, 3, 1); mgm2ValueCalib, 3, 3, 1);
MatrixOperations<float>::multiply(mgmParameters->mgm2orientationMatrix[0], mgm2ValueCalib,
mgm2ValueBody, 3, 3, 1);
for (uint8_t i = 0; i < 3; i++) { for (uint8_t i = 0; i < 3; i++) {
sensorFusionNumerator[i] += mgm2ValueBody[i] / mgmParameters->mgm02variance[i]; sensorFusionNumerator[i] += mgm2ValueCalib[i] / mgmParameters->mgm02variance[i];
sensorFusionDenominator[i] += 1 / mgmParameters->mgm02variance[i]; sensorFusionDenominator[i] += 1 / mgmParameters->mgm02variance[i];
} }
} }
if (mgm3valid) { if (mgm3valid) {
VectorOperations<float>::subtract(mgm3Value, mgmParameters->mgm3hardIronOffset, mgm3ValueNoBias, MatrixOperations<float>::multiply(mgmParameters->mgm3orientationMatrix[0], mgm3Value,
3); mgm3ValueBody, 3, 3, 1);
VectorOperations<float>::subtract(mgm3ValueBody, mgmParameters->mgm3hardIronOffset,
mgm3ValueNoBias, 3);
MatrixOperations<float>::multiply(mgmParameters->mgm3softIronInverse[0], mgm3ValueNoBias, MatrixOperations<float>::multiply(mgmParameters->mgm3softIronInverse[0], mgm3ValueNoBias,
mgm3ValueCalib, 3, 3, 1); mgm3ValueCalib, 3, 3, 1);
MatrixOperations<float>::multiply(mgmParameters->mgm3orientationMatrix[0], mgm3ValueCalib,
mgm3ValueBody, 3, 3, 1);
for (uint8_t i = 0; i < 3; i++) { for (uint8_t i = 0; i < 3; i++) {
sensorFusionNumerator[i] += mgm3ValueBody[i] / mgmParameters->mgm13variance[i]; sensorFusionNumerator[i] += mgm3ValueCalib[i] / mgmParameters->mgm13variance[i];
sensorFusionDenominator[i] += 1 / mgmParameters->mgm13variance[i]; sensorFusionDenominator[i] += 1 / mgmParameters->mgm13variance[i];
} }
} }
if (mgm4valid) { if (mgm4valid) {
float mgm4ValueNT[3]; float mgm4ValueUT[3];
VectorOperations<float>::mulScalar(mgm4Value, 1e-3, mgm4ValueNT, 3); // uT to nT VectorOperations<float>::mulScalar(mgm4Value, 1e-3, mgm4ValueUT, 3); // nT to uT
VectorOperations<float>::subtract(mgm4ValueNT, mgmParameters->mgm4hardIronOffset, MatrixOperations<float>::multiply(mgmParameters->mgm4orientationMatrix[0], mgm4ValueUT,
mgm4ValueBody, 3, 3, 1);
VectorOperations<float>::subtract(mgm4ValueBody, mgmParameters->mgm4hardIronOffset,
mgm4ValueNoBias, 3); mgm4ValueNoBias, 3);
MatrixOperations<float>::multiply(mgmParameters->mgm4softIronInverse[0], mgm4ValueNoBias, MatrixOperations<float>::multiply(mgmParameters->mgm4softIronInverse[0], mgm4ValueNoBias,
mgm4ValueCalib, 3, 3, 1); mgm4ValueCalib, 3, 3, 1);
MatrixOperations<float>::multiply(mgmParameters->mgm4orientationMatrix[0], mgm4ValueCalib,
mgm4ValueBody, 3, 3, 1);
for (uint8_t i = 0; i < 3; i++) { for (uint8_t i = 0; i < 3; i++) {
sensorFusionNumerator[i] += mgm4ValueBody[i] / mgmParameters->mgm4variance[i]; sensorFusionNumerator[i] += mgm4ValueCalib[i] / mgmParameters->mgm4variance[i];
sensorFusionDenominator[i] += 1 / mgmParameters->mgm4variance[i]; sensorFusionDenominator[i] += 1 / mgmParameters->mgm4variance[i];
} }
} }
@ -150,6 +151,7 @@ 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++) {
mgmVecTotDerivative[i] = (mgmVecTot[i] - savedMgmVecTot[i]) / timeDiff; mgmVecTotDerivative[i] = (mgmVecTot[i] - savedMgmVecTot[i]) / timeDiff;
savedMgmVecTot[i] = mgmVecTot[i]; savedMgmVecTot[i] = mgmVecTot[i];
mgmVecTotDerivativeValid = true;
} }
} }
timeOfSavedMagFieldEst = timeOfMgmMeasurement; timeOfSavedMagFieldEst = timeOfMgmMeasurement;
@ -157,15 +159,15 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
{ {
PoolReadGuard pg(mgmDataProcessed); PoolReadGuard pg(mgmDataProcessed);
if (pg.getReadResult() == returnvalue::OK) { if (pg.getReadResult() == returnvalue::OK) {
std::memcpy(mgmDataProcessed->mgm0vec.value, mgm0ValueBody, 3 * sizeof(float)); std::memcpy(mgmDataProcessed->mgm0vec.value, mgm0ValueCalib, 3 * sizeof(float));
mgmDataProcessed->mgm0vec.setValid(mgm0valid); mgmDataProcessed->mgm0vec.setValid(mgm0valid);
std::memcpy(mgmDataProcessed->mgm1vec.value, mgm1ValueBody, 3 * sizeof(float)); std::memcpy(mgmDataProcessed->mgm1vec.value, mgm1ValueCalib, 3 * sizeof(float));
mgmDataProcessed->mgm1vec.setValid(mgm1valid); mgmDataProcessed->mgm1vec.setValid(mgm1valid);
std::memcpy(mgmDataProcessed->mgm2vec.value, mgm2ValueBody, 3 * sizeof(float)); std::memcpy(mgmDataProcessed->mgm2vec.value, mgm2ValueCalib, 3 * sizeof(float));
mgmDataProcessed->mgm2vec.setValid(mgm2valid); mgmDataProcessed->mgm2vec.setValid(mgm2valid);
std::memcpy(mgmDataProcessed->mgm3vec.value, mgm3ValueBody, 3 * sizeof(float)); std::memcpy(mgmDataProcessed->mgm3vec.value, mgm3ValueCalib, 3 * sizeof(float));
mgmDataProcessed->mgm3vec.setValid(mgm3valid); mgmDataProcessed->mgm3vec.setValid(mgm3valid);
std::memcpy(mgmDataProcessed->mgm4vec.value, mgm4ValueBody, 3 * sizeof(float)); std::memcpy(mgmDataProcessed->mgm4vec.value, mgm4ValueCalib, 3 * sizeof(float));
mgmDataProcessed->mgm4vec.setValid(mgm4valid); mgmDataProcessed->mgm4vec.setValid(mgm4valid);
std::memcpy(mgmDataProcessed->mgmVecTot.value, mgmVecTot, 3 * sizeof(double)); std::memcpy(mgmDataProcessed->mgmVecTot.value, mgmVecTot, 3 * sizeof(double));
mgmDataProcessed->mgmVecTot.setValid(true); mgmDataProcessed->mgmVecTot.setValid(true);

View File

@ -13,6 +13,9 @@ static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::GPS_HANDLER;
//! [EXPORT] : [COMMENT] Fix has changed. P1: Old fix. P2: New fix //! [EXPORT] : [COMMENT] Fix has changed. P1: Old fix. P2: New fix
//! 0: Not seen, 1: No Fix, 2: 2D-Fix, 3: 3D-Fix //! 0: Not seen, 1: No Fix, 2: 2D-Fix, 3: 3D-Fix
static constexpr Event GPS_FIX_CHANGE = event::makeEvent(SUBSYSTEM_ID, 0, severity::INFO); static constexpr Event GPS_FIX_CHANGE = event::makeEvent(SUBSYSTEM_ID, 0, severity::INFO);
//! [EXPORT] : [COMMENT] Could not get fix in maximum allowed time. P1: Maximum allowed time
//! to get a fix after the GPS was switched on.
static constexpr Event CANT_GET_FIX = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW);
static constexpr DeviceCommandId_t GPS_REPLY = 0; static constexpr DeviceCommandId_t GPS_REPLY = 0;
static constexpr DeviceCommandId_t TRIGGER_RESET_PIN_GNSS = 5; static constexpr DeviceCommandId_t TRIGGER_RESET_PIN_GNSS = 5;

View File

@ -58,7 +58,7 @@ void AcsSubsystem::handleEventMessages() {
case EventMessage::EVENT_MESSAGE: case EventMessage::EVENT_MESSAGE:
if (event.getEvent() == acs::SAFE_RATE_VIOLATION) { if (event.getEvent() == acs::SAFE_RATE_VIOLATION) {
CommandMessage msg; CommandMessage msg;
ModeMessage::setCmdModeModeMessage(msg, acs::CtrlSubmode::DETUMBLE, 0); ModeMessage::setCmdModeMessage(msg, acs::CtrlSubmode::DETUMBLE, 0);
ReturnValue_t result = commandQueue->sendMessage(commandQueue->getId(), &msg); ReturnValue_t result = commandQueue->sendMessage(commandQueue->getId(), &msg);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
sif::error << "AcsSubsystem: sending DETUMBLE mode cmd to self has failed" << std::endl; sif::error << "AcsSubsystem: sending DETUMBLE mode cmd to self has failed" << std::endl;
@ -66,7 +66,7 @@ void AcsSubsystem::handleEventMessages() {
} }
if (event.getEvent() == acs::SAFE_RATE_RECOVERY) { if (event.getEvent() == acs::SAFE_RATE_RECOVERY) {
CommandMessage msg; CommandMessage msg;
ModeMessage::setCmdModeModeMessage(msg, acs::CtrlSubmode::SAFE, 0); ModeMessage::setCmdModeMessage(msg, acs::CtrlSubmode::SAFE, 0);
ReturnValue_t result = commandQueue->sendMessage(commandQueue->getId(), &msg); ReturnValue_t result = commandQueue->sendMessage(commandQueue->getId(), &msg);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
sif::error << "AcsSubsystem: sending IDLE mode cmd to self has failed" << std::endl; sif::error << "AcsSubsystem: sending IDLE mode cmd to self has failed" << std::endl;

12
release_checklist.md Normal file
View File

@ -0,0 +1,12 @@
OBSW Release Checklist
=========
# Pre-Release
1. Update version in `CMakeLists.txt`
2. Verify that the Q7S, Q7S EM and Host build are working
3. Wait for CI/CD results
# Post-Release
1. Create a new release with tag on `EGit`

2
tmtc

@ -1 +1 @@
Subproject commit d6445d38a8eb644a5e1bd27f0fc56d29e93c030d Subproject commit 4086e7947b4458bcbbd47c78e67c23d3a47885c8