Merge branch 'main' into soc-calculator
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
This commit is contained in:
commit
2195beb045
96
CHANGELOG.md
96
CHANGELOG.md
@ -16,6 +16,102 @@ will consitute of a breaking change warranting a new major release:
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v6.5.1] 2023-09-12
|
||||
|
||||
- Bumped `eive-tmtc` to v5.5.0.
|
||||
|
||||
# [v6.5.0] 2023-09-12
|
||||
|
||||
## Changed
|
||||
|
||||
- Relaxed SUS FDIR. The devices have shown to be glitchy in orbit, but still seem to deliver
|
||||
sensible raw values most of the time. Some further testing is necessary, but some changes in the
|
||||
code should cause the SUS devices to remain healthy for now.
|
||||
- The primary and the secondary temperature sensors for the PLOC mission boards are exchanged.
|
||||
- ACS parameters for the SUSMGM (FLP) safe mode have been adjusted. This safe mode is now the
|
||||
default one.
|
||||
- MGM3100 Startup Configuration: Ignore bit 1 of the CMM reply, which is sometimes set to
|
||||
1 in the reply for some reason.
|
||||
|
||||
# [v6.4.1] 2023-08-21
|
||||
|
||||
## Fixed
|
||||
|
||||
- `PDEC_CONFIG_CORRUPTED` event now actually contains the readback instead of the expected
|
||||
config
|
||||
- Magnetic field vector was not calculated if only MGM4 was available, but still written to
|
||||
the dataset. This would result in a NaN vector. Allowance for usage of MGM4 is now checked
|
||||
before entering calculation.
|
||||
|
||||
# [v6.4.0] 2023-08-16
|
||||
|
||||
- `eive-tmtc`: v5.4.3
|
||||
|
||||
## Fixed
|
||||
|
||||
- The handling function of the GPS data is only called once per GPS read. This should remove
|
||||
the fake fix-has-changed events.
|
||||
- Fix for PLOC SUPV HK set parsing.
|
||||
- The timestamp for the `POSSIBLE_FILE_CORRUPTION` event will be generated properly now.
|
||||
|
||||
## Changed
|
||||
|
||||
- PDEC FDIR rework: A full PDEC reboot will now only be performed after a regular PDEC reset has
|
||||
failed 10 times. The mechanism will reset after no PDEC reset has happended for 2 minutes.
|
||||
The PDEC reset will be performed when counting 4 dirty frame events 10 seconds after the count
|
||||
was incremented initially.
|
||||
- GPS Fix has changed event is no longer triggered for the EM
|
||||
- MGM and SUS rates now will only be calculated, if 2 valid consecutive datapoints are available.
|
||||
The stored value of the last timestep will now be reset, if no actual value is available.
|
||||
|
||||
## Added
|
||||
|
||||
- The PLOC SUPV HK set is requested and downlinked periodically if the SUPV is on now.
|
||||
- SGP4 Propagator is now used for propagating the position of EIVE. It will only work once
|
||||
a TLE has been uploaded with the newly added action command for the ACS Controller. In
|
||||
return the actual GPS data will be ignored once SPG4 is running. However, by setting the
|
||||
according parameter, the ACS Controller can be directed to ignore the SGP4 solution.
|
||||
- Skyview dataset for more GPS TM has been added
|
||||
- `PDEC_CONFIG_CORRUPTED` event which is triggered when the PDEC configuration does not match the
|
||||
expected configuration. P1 will contain the readback of the first word and P2 will contain the
|
||||
readback of the second word.
|
||||
- The MGM and SUS vectors being too close together does not prevent the usage of the safe
|
||||
mode controller anymore.
|
||||
- Parameter to disable usage of MGM4, which is part of the MTQ and therefore cannot be
|
||||
disabled without disabling the MTQ itself.
|
||||
|
||||
# [v6.3.0] 2023-08-03
|
||||
|
||||
## Fixed
|
||||
|
||||
- Small SCEX fix: The temperatur check option was not passed
|
||||
on for commands with a user data size larger than 1.
|
||||
- SCEX: Properly check whether filesystem is usable for filesystem checks.
|
||||
- ACS Controller strategy is now actually written to the dataset for detumbling.
|
||||
- During detumble the fused rotation rate is now calculated.
|
||||
- Detumbling is now exited when its exit value is undercut and not its entry value.
|
||||
- Rotation rate of last cycle is now stored in all cases for the fused rotational rate
|
||||
calculation.
|
||||
- Fused rotation rate estimation during eclipse can be disabled. This will also prevent
|
||||
detumbling during eclipse, as no relevant rotational rate is available for now.
|
||||
- `EiveSystem`: Add a small delay between triggering an event for FDIR reboots and sending the
|
||||
command to the core controller.
|
||||
- PL PDU: Fixed bounds checking logic. Bound checks will only be performed for modules which are
|
||||
enabled.
|
||||
|
||||
## Changed
|
||||
|
||||
- SCEX: Only perform filesystem checks when not in OFF mode.
|
||||
- The `EiveSystem` now only sends reboot commands targetting the same image.
|
||||
- Added 200 ms delay between switching HPA/MPA/TX/X8 and DRO GPIO pin OFF.
|
||||
- PL PCDU ADC set is now automatically enabled for `NORMAL` mode transitions. It is automatically
|
||||
disabled for `OFF` mode transitions.
|
||||
|
||||
## Added
|
||||
|
||||
- PL PCDU for EM build.
|
||||
- SCEX: Add warning event if filesystem is unusable.
|
||||
|
||||
# [v6.2.0] 2023-07-26
|
||||
|
||||
- `eive-tmtc`: v5.3.1
|
||||
|
@ -10,8 +10,8 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(OBSW_VERSION_MAJOR 6)
|
||||
set(OBSW_VERSION_MINOR 2)
|
||||
set(OBSW_VERSION_REVISION 0)
|
||||
set(OBSW_VERSION_MINOR 5)
|
||||
set(OBSW_VERSION_REVISION 1)
|
||||
|
||||
# set(CMAKE_VERBOSE TRUE)
|
||||
|
||||
@ -144,7 +144,7 @@ set(OBSW_ADD_RAD_SENSORS
|
||||
${INIT_VAL}
|
||||
CACHE STRING "Add Rad Sensor module")
|
||||
set(OBSW_ADD_PL_PCDU
|
||||
${INIT_VAL}
|
||||
1
|
||||
CACHE STRING "Add Payload PCDU modukle")
|
||||
set(OBSW_ADD_SYRLINKS
|
||||
1
|
||||
@ -240,6 +240,9 @@ set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF)
|
||||
set(EIVE_ADD_LINUX_FILES OFF)
|
||||
set(FSFW_ADD_TMSTORAGE ON)
|
||||
|
||||
set(FSFW_ADD_COORDINATES ON)
|
||||
set(FSFW_ADD_SGP4_PROPAGATOR ON)
|
||||
|
||||
# Analyse different OS and architecture/target options, determine BSP_PATH,
|
||||
# display information about compiler etc.
|
||||
pre_source_hw_os_config()
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 301 translations.
|
||||
* @brief Auto-generated event translation file. Contains 306 translations.
|
||||
* @details
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
* Generated on: 2023-09-12 10:05:17
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -100,6 +100,7 @@ const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY";
|
||||
const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET";
|
||||
const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION";
|
||||
const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE";
|
||||
const char *TLE_TOO_OLD_STRING = "TLE_TOO_OLD";
|
||||
const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT";
|
||||
const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED";
|
||||
const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED";
|
||||
@ -167,6 +168,7 @@ const char *PDEC_TRYING_RESET_NO_INIT_STRING = "PDEC_TRYING_RESET_NO_INIT";
|
||||
const char *PDEC_RESET_FAILED_STRING = "PDEC_RESET_FAILED";
|
||||
const char *OPEN_IRQ_FILE_FAILED_STRING = "OPEN_IRQ_FILE_FAILED";
|
||||
const char *PDEC_INIT_FAILED_STRING = "PDEC_INIT_FAILED";
|
||||
const char *PDEC_CONFIG_CORRUPTED_STRING = "PDEC_CONFIG_CORRUPTED";
|
||||
const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED";
|
||||
const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED";
|
||||
const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL";
|
||||
@ -261,6 +263,7 @@ const char *TX_OFF_STRING = "TX_OFF";
|
||||
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
|
||||
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
|
||||
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
|
||||
const char *FS_UNUSABLE_STRING = "FS_UNUSABLE";
|
||||
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
|
||||
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
|
||||
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
|
||||
@ -306,6 +309,8 @@ const char *DUMP_NOK_CANCELLED_STRING = "DUMP_NOK_CANCELLED";
|
||||
const char *DUMP_MISC_CANCELLED_STRING = "DUMP_MISC_CANCELLED";
|
||||
const char *DUMP_HK_CANCELLED_STRING = "DUMP_HK_CANCELLED";
|
||||
const char *DUMP_CFDP_CANCELLED_STRING = "DUMP_CFDP_CANCELLED";
|
||||
const char *TEMPERATURE_ALL_ONES_START_STRING = "TEMPERATURE_ALL_ONES_START";
|
||||
const char *TEMPERATURE_ALL_ONES_RECOVERY_STRING = "TEMPERATURE_ALL_ONES_RECOVERY";
|
||||
|
||||
const char *translateEvents(Event event) {
|
||||
switch ((event & 0xFFFF)) {
|
||||
@ -499,6 +504,8 @@ const char *translateEvents(Event event) {
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
case (11207):
|
||||
return SAFE_MODE_CONTROLLER_FAILURE_STRING;
|
||||
case (11208):
|
||||
return TLE_TOO_OLD_STRING;
|
||||
case (11300):
|
||||
return SWITCH_CMD_SENT_STRING;
|
||||
case (11301):
|
||||
@ -633,6 +640,8 @@ const char *translateEvents(Event event) {
|
||||
return OPEN_IRQ_FILE_FAILED_STRING;
|
||||
case (12414):
|
||||
return PDEC_INIT_FAILED_STRING;
|
||||
case (12415):
|
||||
return PDEC_CONFIG_CORRUPTED_STRING;
|
||||
case (12500):
|
||||
return IMAGE_UPLOAD_FAILED_STRING;
|
||||
case (12501):
|
||||
@ -821,6 +830,8 @@ const char *translateEvents(Event event) {
|
||||
return EXPERIMENT_TIMEDOUT_STRING;
|
||||
case (13802):
|
||||
return MULTI_PACKET_COMMAND_DONE_STRING;
|
||||
case (13803):
|
||||
return FS_UNUSABLE_STRING;
|
||||
case (13901):
|
||||
return SET_CONFIGFILEVALUE_FAILED_STRING;
|
||||
case (13902):
|
||||
@ -911,6 +922,10 @@ const char *translateEvents(Event event) {
|
||||
return DUMP_HK_CANCELLED_STRING;
|
||||
case (14314):
|
||||
return DUMP_CFDP_CANCELLED_STRING;
|
||||
case (14500):
|
||||
return TEMPERATURE_ALL_ONES_START_STRING;
|
||||
case (14501):
|
||||
return TEMPERATURE_ALL_ONES_RECOVERY_STRING;
|
||||
default:
|
||||
return "UNKNOWN_EVENT";
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 171 translations.
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
* Generated on: 2023-09-12 10:05:17
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
|
@ -94,6 +94,9 @@ void ObjectFactory::produce(void* args) {
|
||||
#if OBSW_ADD_ACS_BOARD == 1
|
||||
dummyCfg.addAcsBoardDummies = false;
|
||||
#endif
|
||||
#if OBSW_ADD_PL_PCDU == 0
|
||||
dummyCfg.addPlPcduDummy = true;
|
||||
#endif
|
||||
|
||||
PowerSwitchIF* pwrSwitcher = nullptr;
|
||||
#if OBSW_ADD_GOMSPACE_PCDU == 0
|
||||
@ -107,6 +110,9 @@ void ObjectFactory::produce(void* args) {
|
||||
|
||||
new CoreController(objects::CORE_CONTROLLER, enableHkSets);
|
||||
|
||||
auto* stackHandler = new Stack5VHandler(*pwrSwitcher);
|
||||
static_cast<void>(stackHandler);
|
||||
|
||||
// Initialize chip select to avoid SPI bus issues.
|
||||
createRadSensorChipSelect(gpioComIF);
|
||||
|
||||
@ -146,6 +152,9 @@ void ObjectFactory::produce(void* args) {
|
||||
createStrComponents(pwrSwitcher);
|
||||
#endif /* OBSW_ADD_STAR_TRACKER == 1 */
|
||||
|
||||
#if OBSW_ADD_PL_PCDU == 1
|
||||
createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
|
||||
#endif
|
||||
createPayloadComponents(gpioComIF, *pwrSwitcher);
|
||||
|
||||
#if OBSW_ADD_CCSDS_IP_CORES == 1
|
||||
|
@ -81,7 +81,9 @@ void ObjectFactory::produce(void* args) {
|
||||
createTmpComponents(tmpDevsToAdd);
|
||||
#endif
|
||||
createSolarArrayDeploymentComponents(*pwrSwitcher, *gpioComIF);
|
||||
#if OBSW_ADD_PL_PCDU == 1
|
||||
createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
|
||||
#endif
|
||||
#if OBSW_ADD_SYRLINKS == 1
|
||||
createSyrlinksComponents(pwrSwitcher);
|
||||
#endif /* OBSW_ADD_SYRLINKS == 1 */
|
||||
|
@ -902,8 +902,6 @@ void ObjectFactory::createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF*
|
||||
new PayloadPcduHandler(objects::PLPCDU_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie,
|
||||
gpioComIF, SdCardManager::instance(), stackHandler, false);
|
||||
spiCookie->setCallbackMode(PayloadPcduHandler::extConvAsTwoCallback, plPcduHandler);
|
||||
// plPcduHandler->enablePeriodicPrintout(true, 5);
|
||||
// static_cast<void>(plPcduHandler);
|
||||
#if OBSW_TEST_PL_PCDU == 1
|
||||
plPcduHandler->setStartUpImmediately();
|
||||
#endif
|
||||
|
@ -40,6 +40,7 @@ enum : uint8_t {
|
||||
COM_SUBSYSTEM = 142,
|
||||
PERSISTENT_TM_STORE = 143,
|
||||
SYRLINKS_COM = 144,
|
||||
SUS_HANDLER = 145,
|
||||
COMMON_SUBSYSTEM_ID_END
|
||||
|
||||
};
|
||||
|
@ -248,9 +248,11 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
||||
auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
}
|
||||
auto* plPcduDummy =
|
||||
new PlPcduDummy(objects::PLPCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
plPcduDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
if (cfg.addPlPcduDummy) {
|
||||
auto* plPcduDummy =
|
||||
new PlPcduDummy(objects::PLPCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
plPcduDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
}
|
||||
if (cfg.addPlocDummies) {
|
||||
auto* plocMpsocDummy =
|
||||
new PlocMpsocDummy(objects::PLOC_MPSOC_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
|
@ -30,6 +30,7 @@ struct DummyCfg {
|
||||
bool addStrDummy = true;
|
||||
bool addTmpDummies = true;
|
||||
bool addRadSensorDummy = true;
|
||||
bool addPlPcduDummy = false;
|
||||
Tmp1075Cfg tmp1075Cfg;
|
||||
bool addCamSwitcherDummy = false;
|
||||
bool addScexDummy = false;
|
||||
|
2
fsfw
2
fsfw
@ -1 +1 @@
|
||||
Subproject commit d575da85407e029dabecaffa5368f0c9f1034941
|
||||
Subproject commit d246ce34d05ecc5c722fd127e61556374961c899
|
@ -94,6 +94,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
11205;0x2bc5;MEKF_AUTOMATIC_RESET;INFO;MEKF performed an automatic reset after detection of nonfinite values.;mission/acs/defs.h
|
||||
11206;0x2bc6;MEKF_INVALID_MODE_VIOLATION;HIGH;MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.;mission/acs/defs.h
|
||||
11207;0x2bc7;SAFE_MODE_CONTROLLER_FAILURE;HIGH;The ACS safe mode controller was not able to compute a solution and has failed. P1: Missing information about magnetic field, P2: Missing information about rotational rate;mission/acs/defs.h
|
||||
11208;0x2bc8;TLE_TOO_OLD;INFO;The TLE for the SGP4 Propagator has become too old.;mission/acs/defs.h
|
||||
11300;0x2c24;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11301;0x2c25;SWITCH_HAS_CHANGED;INFO;Indicated that a switch state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11302;0x2c26;SWITCHING_Q7S_DENIED;MEDIUM;No description;mission/power/defs.h
|
||||
@ -161,6 +162,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12412;0x307c;PDEC_RESET_FAILED;HIGH;Failed to pull PDEC reset to low;linux/ipcore/pdec.h
|
||||
12413;0x307d;OPEN_IRQ_FILE_FAILED;HIGH;Failed to open the IRQ uio file;linux/ipcore/pdec.h
|
||||
12414;0x307e;PDEC_INIT_FAILED;HIGH;PDEC initialization failed. This might also be due to the persistent confiuration never becoming available, for example due to SD card issues.;linux/ipcore/pdec.h
|
||||
12415;0x307f;PDEC_CONFIG_CORRUPTED;HIGH;The PDEC configuration area has been corrupted P1: The first configuration word P2: The second configuration word;linux/ipcore/pdec.h
|
||||
12500;0x30d4;IMAGE_UPLOAD_FAILED;LOW;Image upload failed;linux/acs/StrComHandler.h
|
||||
12501;0x30d5;IMAGE_DOWNLOAD_FAILED;LOW;Image download failed;linux/acs/StrComHandler.h
|
||||
12502;0x30d6;IMAGE_UPLOAD_SUCCESSFUL;LOW;Uploading image to star tracker was successfulop;linux/acs/StrComHandler.h
|
||||
@ -255,6 +257,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
13800;0x35e8;MISSING_PACKET;LOW;No description;mission/payload/scexHelpers.h
|
||||
13801;0x35e9;EXPERIMENT_TIMEDOUT;LOW;No description;mission/payload/scexHelpers.h
|
||||
13802;0x35ea;MULTI_PACKET_COMMAND_DONE;INFO;No description;mission/payload/scexHelpers.h
|
||||
13803;0x35eb;FS_UNUSABLE;LOW;No description;mission/payload/scexHelpers.h
|
||||
13901;0x364d;SET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
|
||||
13902;0x364e;GET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
|
||||
13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
|
||||
@ -300,3 +303,5 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14312;0x37e8;DUMP_MISC_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14313;0x37e9;DUMP_HK_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14314;0x37ea;DUMP_CFDP_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14500;0x38a4;TEMPERATURE_ALL_ONES_START;MEDIUM;Detected invalid values, starting invalid message counting;mission/acs/SusHandler.h
|
||||
14501;0x38a5;TEMPERATURE_ALL_ONES_RECOVERY;INFO;Detected valid values again, resetting invalid message counter. P1: Invalid message counter.;mission/acs/SusHandler.h
|
||||
|
|
@ -60,3 +60,4 @@
|
||||
142;COM_SUBSYSTEM
|
||||
143;PERSISTENT_TM_STORE
|
||||
144;SYRLINKS_COM
|
||||
145;SUS_HANDLER
|
||||
|
|
@ -94,6 +94,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
11205;0x2bc5;MEKF_AUTOMATIC_RESET;INFO;MEKF performed an automatic reset after detection of nonfinite values.;mission/acs/defs.h
|
||||
11206;0x2bc6;MEKF_INVALID_MODE_VIOLATION;HIGH;MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.;mission/acs/defs.h
|
||||
11207;0x2bc7;SAFE_MODE_CONTROLLER_FAILURE;HIGH;The ACS safe mode controller was not able to compute a solution and has failed. P1: Missing information about magnetic field, P2: Missing information about rotational rate;mission/acs/defs.h
|
||||
11208;0x2bc8;TLE_TOO_OLD;INFO;The TLE for the SGP4 Propagator has become too old.;mission/acs/defs.h
|
||||
11300;0x2c24;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11301;0x2c25;SWITCH_HAS_CHANGED;INFO;Indicated that a switch state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11302;0x2c26;SWITCHING_Q7S_DENIED;MEDIUM;No description;mission/power/defs.h
|
||||
@ -161,6 +162,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12412;0x307c;PDEC_RESET_FAILED;HIGH;Failed to pull PDEC reset to low;linux/ipcore/pdec.h
|
||||
12413;0x307d;OPEN_IRQ_FILE_FAILED;HIGH;Failed to open the IRQ uio file;linux/ipcore/pdec.h
|
||||
12414;0x307e;PDEC_INIT_FAILED;HIGH;PDEC initialization failed. This might also be due to the persistent confiuration never becoming available, for example due to SD card issues.;linux/ipcore/pdec.h
|
||||
12415;0x307f;PDEC_CONFIG_CORRUPTED;HIGH;The PDEC configuration area has been corrupted P1: The first configuration word P2: The second configuration word;linux/ipcore/pdec.h
|
||||
12500;0x30d4;IMAGE_UPLOAD_FAILED;LOW;Image upload failed;linux/acs/StrComHandler.h
|
||||
12501;0x30d5;IMAGE_DOWNLOAD_FAILED;LOW;Image download failed;linux/acs/StrComHandler.h
|
||||
12502;0x30d6;IMAGE_UPLOAD_SUCCESSFUL;LOW;Uploading image to star tracker was successfulop;linux/acs/StrComHandler.h
|
||||
@ -255,6 +257,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
13800;0x35e8;MISSING_PACKET;LOW;No description;mission/payload/scexHelpers.h
|
||||
13801;0x35e9;EXPERIMENT_TIMEDOUT;LOW;No description;mission/payload/scexHelpers.h
|
||||
13802;0x35ea;MULTI_PACKET_COMMAND_DONE;INFO;No description;mission/payload/scexHelpers.h
|
||||
13803;0x35eb;FS_UNUSABLE;LOW;No description;mission/payload/scexHelpers.h
|
||||
13901;0x364d;SET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
|
||||
13902;0x364e;GET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
|
||||
13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
|
||||
@ -300,3 +303,5 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14312;0x37e8;DUMP_MISC_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14313;0x37e9;DUMP_HK_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14314;0x37ea;DUMP_CFDP_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14500;0x38a4;TEMPERATURE_ALL_ONES_START;MEDIUM;Detected invalid values, starting invalid message counting;mission/acs/SusHandler.h
|
||||
14501;0x38a5;TEMPERATURE_ALL_ONES_RECOVERY;INFO;Detected valid values again, resetting invalid message counter. P1: Invalid message counter.;mission/acs/SusHandler.h
|
||||
|
|
@ -60,3 +60,4 @@
|
||||
142;COM_SUBSYSTEM
|
||||
143;PERSISTENT_TM_STORE
|
||||
144;SYRLINKS_COM
|
||||
145;SUS_HANDLER
|
||||
|
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 301 translations.
|
||||
* @brief Auto-generated event translation file. Contains 306 translations.
|
||||
* @details
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
* Generated on: 2023-09-12 10:05:17
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -100,6 +100,7 @@ const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY";
|
||||
const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET";
|
||||
const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION";
|
||||
const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE";
|
||||
const char *TLE_TOO_OLD_STRING = "TLE_TOO_OLD";
|
||||
const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT";
|
||||
const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED";
|
||||
const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED";
|
||||
@ -167,6 +168,7 @@ const char *PDEC_TRYING_RESET_NO_INIT_STRING = "PDEC_TRYING_RESET_NO_INIT";
|
||||
const char *PDEC_RESET_FAILED_STRING = "PDEC_RESET_FAILED";
|
||||
const char *OPEN_IRQ_FILE_FAILED_STRING = "OPEN_IRQ_FILE_FAILED";
|
||||
const char *PDEC_INIT_FAILED_STRING = "PDEC_INIT_FAILED";
|
||||
const char *PDEC_CONFIG_CORRUPTED_STRING = "PDEC_CONFIG_CORRUPTED";
|
||||
const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED";
|
||||
const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED";
|
||||
const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL";
|
||||
@ -261,6 +263,7 @@ const char *TX_OFF_STRING = "TX_OFF";
|
||||
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
|
||||
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
|
||||
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
|
||||
const char *FS_UNUSABLE_STRING = "FS_UNUSABLE";
|
||||
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
|
||||
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
|
||||
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
|
||||
@ -306,6 +309,8 @@ const char *DUMP_NOK_CANCELLED_STRING = "DUMP_NOK_CANCELLED";
|
||||
const char *DUMP_MISC_CANCELLED_STRING = "DUMP_MISC_CANCELLED";
|
||||
const char *DUMP_HK_CANCELLED_STRING = "DUMP_HK_CANCELLED";
|
||||
const char *DUMP_CFDP_CANCELLED_STRING = "DUMP_CFDP_CANCELLED";
|
||||
const char *TEMPERATURE_ALL_ONES_START_STRING = "TEMPERATURE_ALL_ONES_START";
|
||||
const char *TEMPERATURE_ALL_ONES_RECOVERY_STRING = "TEMPERATURE_ALL_ONES_RECOVERY";
|
||||
|
||||
const char *translateEvents(Event event) {
|
||||
switch ((event & 0xFFFF)) {
|
||||
@ -499,6 +504,8 @@ const char *translateEvents(Event event) {
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
case (11207):
|
||||
return SAFE_MODE_CONTROLLER_FAILURE_STRING;
|
||||
case (11208):
|
||||
return TLE_TOO_OLD_STRING;
|
||||
case (11300):
|
||||
return SWITCH_CMD_SENT_STRING;
|
||||
case (11301):
|
||||
@ -633,6 +640,8 @@ const char *translateEvents(Event event) {
|
||||
return OPEN_IRQ_FILE_FAILED_STRING;
|
||||
case (12414):
|
||||
return PDEC_INIT_FAILED_STRING;
|
||||
case (12415):
|
||||
return PDEC_CONFIG_CORRUPTED_STRING;
|
||||
case (12500):
|
||||
return IMAGE_UPLOAD_FAILED_STRING;
|
||||
case (12501):
|
||||
@ -821,6 +830,8 @@ const char *translateEvents(Event event) {
|
||||
return EXPERIMENT_TIMEDOUT_STRING;
|
||||
case (13802):
|
||||
return MULTI_PACKET_COMMAND_DONE_STRING;
|
||||
case (13803):
|
||||
return FS_UNUSABLE_STRING;
|
||||
case (13901):
|
||||
return SET_CONFIGFILEVALUE_FAILED_STRING;
|
||||
case (13902):
|
||||
@ -911,6 +922,10 @@ const char *translateEvents(Event event) {
|
||||
return DUMP_HK_CANCELLED_STRING;
|
||||
case (14314):
|
||||
return DUMP_CFDP_CANCELLED_STRING;
|
||||
case (14500):
|
||||
return TEMPERATURE_ALL_ONES_START_STRING;
|
||||
case (14501):
|
||||
return TEMPERATURE_ALL_ONES_RECOVERY_STRING;
|
||||
default:
|
||||
return "UNKNOWN_EVENT";
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 175 translations.
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
* Generated on: 2023-09-12 10:05:17
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
|
@ -767,6 +767,9 @@ void AcsBoardPolling::mgmRm3100Handler(MgmRm3100& mgm) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
// For some reason, bit 1 is sometimes set on the reply, even if it is not set for the
|
||||
// command.. Ignore it for now by clearing it.
|
||||
rawReply[1] &= ~(1 << 1);
|
||||
if (rawReply[1] != mgmRm3100::CMM_VALUE) {
|
||||
sif::error << "AcsBoardPolling: MGM RM3100 read back CMM invalid" << std::endl;
|
||||
mgm.replyResult = result;
|
||||
|
@ -21,6 +21,7 @@ GpsHyperionLinuxController::GpsHyperionLinuxController(object_id_t objectId, obj
|
||||
bool enableHkSets, bool debugHyperionGps)
|
||||
: ExtendedControllerBase(objectId),
|
||||
gpsSet(this),
|
||||
skyviewSet(this),
|
||||
enableHkSets(enableHkSets),
|
||||
debugHyperionGps(debugHyperionGps) {}
|
||||
|
||||
@ -29,7 +30,17 @@ GpsHyperionLinuxController::~GpsHyperionLinuxController() {
|
||||
gps_close(&gps);
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *GpsHyperionLinuxController::getDataSetHandle(sid_t sid) { return &gpsSet; }
|
||||
LocalPoolDataSetBase *GpsHyperionLinuxController::getDataSetHandle(sid_t sid) {
|
||||
switch (sid.ownerSetId) {
|
||||
case GpsHyperion::CORE_DATASET:
|
||||
return &gpsSet;
|
||||
case GpsHyperion::SKYVIEW_DATASET:
|
||||
return &skyviewSet;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) {
|
||||
@ -90,6 +101,13 @@ ReturnValue_t GpsHyperionLinuxController::initializeLocalDataPool(
|
||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
|
||||
poolManager.subscribeForRegularPeriodicPacket({gpsSet.getSid(), enableHkSets, 30.0});
|
||||
localDataPoolMap.emplace(GpsHyperion::SKYVIEW_UNIX_SECONDS, new PoolEntry<double>());
|
||||
localDataPoolMap.emplace(GpsHyperion::PRN_ID, new PoolEntry<int16_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::AZIMUTH, new PoolEntry<int16_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::ELEVATION, new PoolEntry<int16_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::SIGNAL2NOISE, new PoolEntry<double>());
|
||||
localDataPoolMap.emplace(GpsHyperion::USED, new PoolEntry<uint8_t>());
|
||||
poolManager.subscribeForRegularPeriodicPacket({skyviewSet.getSid(), false, 120.0});
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -166,30 +184,32 @@ bool GpsHyperionLinuxController::readGpsDataFromGpsd() {
|
||||
if (mode == MODE_OFF) {
|
||||
return false;
|
||||
}
|
||||
unsigned int readIdx = 0;
|
||||
if (readMode == ReadModes::SOCKET) {
|
||||
// Poll the GPS.
|
||||
if (gps_waiting(&gps, 0)) {
|
||||
if (-1 == gps_read(&gps)) {
|
||||
while (gps_waiting(&gps, 0)) {
|
||||
int retval = gps_read(&gps);
|
||||
if (retval < 0) {
|
||||
readError();
|
||||
return false;
|
||||
}
|
||||
oneShotSwitches.gpsReadFailedSwitch = true;
|
||||
ReturnValue_t result = handleGpsReadData();
|
||||
if (result == returnvalue::OK) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
readIdx++;
|
||||
if (readIdx >= 40) {
|
||||
sif::warning << "GpsHyperionLinuxController: Received " << readIdx
|
||||
<< " GPSD message consecutively" << std::endl;
|
||||
break;
|
||||
}
|
||||
noModeSetCntr = 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (readIdx > 0) {
|
||||
oneShotSwitches.gpsReadFailedSwitch = true;
|
||||
handleGpsReadData();
|
||||
}
|
||||
} else if (readMode == ReadModes::SHM) {
|
||||
sif::error << "GpsHyperionLinuxController::readGpsDataFromGpsdPermanentLoop: "
|
||||
"SHM read not implemented"
|
||||
<< std::endl;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
||||
@ -208,7 +228,15 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
ReturnValue_t result = handleCoreTelemetry(modeIsSet);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleSkyviewTelemetry();
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::handleCoreTelemetry(bool modeIsSet) {
|
||||
PoolReadGuard pg(&gpsSet);
|
||||
if (pg.getReadResult() != returnvalue::OK) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
@ -236,7 +264,9 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
||||
}
|
||||
}
|
||||
if (gpsSet.fixMode.value != newFix) {
|
||||
#if OBSW_Q7S_EM != 1
|
||||
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, newFix);
|
||||
#endif
|
||||
}
|
||||
gpsSet.fixMode = newFix;
|
||||
gpsSet.fixMode.setValid(modeIsSet);
|
||||
@ -369,6 +399,22 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::handleSkyviewTelemetry() {
|
||||
PoolReadGuard pg(&skyviewSet);
|
||||
if (pg.getReadResult() != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
skyviewSet.unixSeconds.value = gps.skyview_time;
|
||||
for (int sat = 0; sat < GpsHyperion::MAX_SATELLITES; sat++) {
|
||||
skyviewSet.prn_id.value[sat] = gps.skyview[sat].PRN;
|
||||
skyviewSet.azimuth.value[sat] = gps.skyview[sat].azimuth;
|
||||
skyviewSet.elevation.value[sat] = gps.skyview[sat].elevation;
|
||||
skyviewSet.signal2noise.value[sat] = gps.skyview[sat].ss;
|
||||
skyviewSet.used.value[sat] = gps.skyview[sat].used;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void GpsHyperionLinuxController::overwriteTimeIfNotSane(timeval time, bool validFix) {
|
||||
if (not timeInit and validFix) {
|
||||
if (not utility::timeSanityCheck()) {
|
||||
|
@ -54,9 +54,12 @@ class GpsHyperionLinuxController : public ExtendedControllerBase {
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
|
||||
ReturnValue_t handleGpsReadData();
|
||||
ReturnValue_t handleCoreTelemetry(bool modeIsSet);
|
||||
ReturnValue_t handleSkyviewTelemetry();
|
||||
|
||||
private:
|
||||
GpsPrimaryDataset gpsSet;
|
||||
SkyviewDataset skyviewSet;
|
||||
gps_data_t gps = {};
|
||||
bool enableHkSets = false;
|
||||
const char* currentClientBuf = nullptr;
|
||||
@ -81,7 +84,6 @@ class GpsHyperionLinuxController : public ExtendedControllerBase {
|
||||
} oneShotSwitches;
|
||||
|
||||
bool debugHyperionGps = false;
|
||||
int32_t noModeSetCntr = 0;
|
||||
|
||||
// Returns true if the function should be called again or false if other
|
||||
// controller handling can be done.
|
||||
|
@ -170,18 +170,12 @@ ReturnValue_t SusPolling::handleSusPolling() {
|
||||
}
|
||||
MutexGuard mg(ipcLock);
|
||||
susDevs[idx].ownReply.tempRaw = ((rawReply[0] & 0x0f) << 8) | rawReply[1];
|
||||
// Reply is all ones. Sensor is probably off or faulty when
|
||||
// it should not be.
|
||||
if (susDevs[idx].ownReply.tempRaw == 0x0fff) {
|
||||
susDevs[idx].replyResult = returnvalue::FAILED;
|
||||
} else {
|
||||
susDevs[idx].replyResult = returnvalue::OK;
|
||||
for (unsigned chIdx = 0; chIdx < 6; chIdx++) {
|
||||
susDevs[idx].ownReply.channelsRaw[chIdx] =
|
||||
(rawReply[chIdx * 2 + 2] << 8) | rawReply[chIdx * 2 + 3];
|
||||
}
|
||||
susDevs[idx].ownReply.dataWasSet = true;
|
||||
susDevs[idx].replyResult = returnvalue::OK;
|
||||
for (unsigned chIdx = 0; chIdx < 6; chIdx++) {
|
||||
susDevs[idx].ownReply.channelsRaw[chIdx] =
|
||||
(rawReply[chIdx * 2 + 2] << 8) | rawReply[chIdx * 2 + 3];
|
||||
}
|
||||
susDevs[idx].ownReply.dataWasSet = true;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
//#include "lwgps/lwgps.h"
|
||||
// #include "lwgps/lwgps.h"
|
||||
#include "test/TestTask.h"
|
||||
|
||||
class ScexUartReader;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 301 translations.
|
||||
* @brief Auto-generated event translation file. Contains 306 translations.
|
||||
* @details
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
* Generated on: 2023-09-12 10:05:17
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -100,6 +100,7 @@ const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY";
|
||||
const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET";
|
||||
const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION";
|
||||
const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE";
|
||||
const char *TLE_TOO_OLD_STRING = "TLE_TOO_OLD";
|
||||
const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT";
|
||||
const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED";
|
||||
const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED";
|
||||
@ -167,6 +168,7 @@ const char *PDEC_TRYING_RESET_NO_INIT_STRING = "PDEC_TRYING_RESET_NO_INIT";
|
||||
const char *PDEC_RESET_FAILED_STRING = "PDEC_RESET_FAILED";
|
||||
const char *OPEN_IRQ_FILE_FAILED_STRING = "OPEN_IRQ_FILE_FAILED";
|
||||
const char *PDEC_INIT_FAILED_STRING = "PDEC_INIT_FAILED";
|
||||
const char *PDEC_CONFIG_CORRUPTED_STRING = "PDEC_CONFIG_CORRUPTED";
|
||||
const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED";
|
||||
const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED";
|
||||
const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL";
|
||||
@ -261,6 +263,7 @@ const char *TX_OFF_STRING = "TX_OFF";
|
||||
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
|
||||
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
|
||||
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
|
||||
const char *FS_UNUSABLE_STRING = "FS_UNUSABLE";
|
||||
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
|
||||
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
|
||||
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
|
||||
@ -306,6 +309,8 @@ const char *DUMP_NOK_CANCELLED_STRING = "DUMP_NOK_CANCELLED";
|
||||
const char *DUMP_MISC_CANCELLED_STRING = "DUMP_MISC_CANCELLED";
|
||||
const char *DUMP_HK_CANCELLED_STRING = "DUMP_HK_CANCELLED";
|
||||
const char *DUMP_CFDP_CANCELLED_STRING = "DUMP_CFDP_CANCELLED";
|
||||
const char *TEMPERATURE_ALL_ONES_START_STRING = "TEMPERATURE_ALL_ONES_START";
|
||||
const char *TEMPERATURE_ALL_ONES_RECOVERY_STRING = "TEMPERATURE_ALL_ONES_RECOVERY";
|
||||
|
||||
const char *translateEvents(Event event) {
|
||||
switch ((event & 0xFFFF)) {
|
||||
@ -499,6 +504,8 @@ const char *translateEvents(Event event) {
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
case (11207):
|
||||
return SAFE_MODE_CONTROLLER_FAILURE_STRING;
|
||||
case (11208):
|
||||
return TLE_TOO_OLD_STRING;
|
||||
case (11300):
|
||||
return SWITCH_CMD_SENT_STRING;
|
||||
case (11301):
|
||||
@ -633,6 +640,8 @@ const char *translateEvents(Event event) {
|
||||
return OPEN_IRQ_FILE_FAILED_STRING;
|
||||
case (12414):
|
||||
return PDEC_INIT_FAILED_STRING;
|
||||
case (12415):
|
||||
return PDEC_CONFIG_CORRUPTED_STRING;
|
||||
case (12500):
|
||||
return IMAGE_UPLOAD_FAILED_STRING;
|
||||
case (12501):
|
||||
@ -821,6 +830,8 @@ const char *translateEvents(Event event) {
|
||||
return EXPERIMENT_TIMEDOUT_STRING;
|
||||
case (13802):
|
||||
return MULTI_PACKET_COMMAND_DONE_STRING;
|
||||
case (13803):
|
||||
return FS_UNUSABLE_STRING;
|
||||
case (13901):
|
||||
return SET_CONFIGFILEVALUE_FAILED_STRING;
|
||||
case (13902):
|
||||
@ -911,6 +922,10 @@ const char *translateEvents(Event event) {
|
||||
return DUMP_HK_CANCELLED_STRING;
|
||||
case (14314):
|
||||
return DUMP_CFDP_CANCELLED_STRING;
|
||||
case (14500):
|
||||
return TEMPERATURE_ALL_ONES_START_STRING;
|
||||
case (14501):
|
||||
return TEMPERATURE_ALL_ONES_RECOVERY_STRING;
|
||||
default:
|
||||
return "UNKNOWN_EVENT";
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 175 translations.
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
* Generated on: 2023-09-12 10:05:17
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
|
@ -22,11 +22,11 @@ ReturnValue_t PdecConfig::write() {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = writeFrameHeaderFirstOctet();
|
||||
result = writeFrameHeaderFirstWord();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = writeFrameHeaderSecondOctet();
|
||||
result = writeFrameHeaderSecondWord();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@ -77,7 +77,7 @@ ReturnValue_t PdecConfig::setPositiveWindow(uint8_t pw) {
|
||||
return result;
|
||||
}
|
||||
// Rewrite second config word which contains the positive window parameter
|
||||
writeFrameHeaderSecondOctet();
|
||||
writeFrameHeaderSecondWord();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ ReturnValue_t PdecConfig::setNegativeWindow(uint8_t nw) {
|
||||
return result;
|
||||
}
|
||||
// Rewrite second config word which contains the negative window parameter
|
||||
writeFrameHeaderSecondOctet();
|
||||
writeFrameHeaderSecondWord();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -114,43 +114,23 @@ ReturnValue_t PdecConfig::getNegativeWindow(uint8_t& negativeWindow) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::writeFrameHeaderFirstOctet() {
|
||||
ReturnValue_t PdecConfig::writeFrameHeaderFirstWord() {
|
||||
uint32_t word = 0;
|
||||
word |= (VERSION_ID << 30);
|
||||
|
||||
// Setting the bypass flag and the control command flag should not have any
|
||||
// implication on the operation of the PDEC IP Core
|
||||
word |= (BYPASS_FLAG << 29);
|
||||
word |= (CONTROL_COMMAND_FLAG << 28);
|
||||
|
||||
word |= (RESERVED_FIELD_A << 26);
|
||||
word |= (SPACECRAFT_ID << 16);
|
||||
word |= (VIRTUAL_CHANNEL << 10);
|
||||
word |= (DUMMY_BITS << 8);
|
||||
uint8_t positiveWindow = 0;
|
||||
ReturnValue_t result =
|
||||
localParameterHandler.getValue(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, positiveWindow);
|
||||
ReturnValue_t result = createFirstWord(&word);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
word |= static_cast<uint32_t>(positiveWindow);
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET) = word;
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET + OFFSET_FIRST_CONFIG_WORD) = word;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::writeFrameHeaderSecondOctet() {
|
||||
uint8_t negativeWindow = 0;
|
||||
ReturnValue_t result =
|
||||
localParameterHandler.getValue(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, negativeWindow);
|
||||
ReturnValue_t PdecConfig::writeFrameHeaderSecondWord() {
|
||||
uint32_t word = 0;
|
||||
ReturnValue_t result = createSecondWord(&word);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint32_t word = 0;
|
||||
word = 0;
|
||||
word |= (static_cast<uint32_t>(negativeWindow) << 24);
|
||||
word |= (HIGH_AU_MAP_ID << 16);
|
||||
word |= (ENABLE_DERANDOMIZER << 8);
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = word;
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET + OFFSET_SECOND_CONFIG_WORD) = word;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -189,3 +169,49 @@ uint8_t PdecConfig::getOddParity(uint8_t number) {
|
||||
parityBit = ~(countBits & 0x1) & 0x1;
|
||||
return parityBit;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::createFirstWord(uint32_t* word) {
|
||||
*word = 0;
|
||||
*word |= (VERSION_ID << 30);
|
||||
|
||||
// Setting the bypass flag and the control command flag should not have any
|
||||
// implication on the operation of the PDEC IP Core
|
||||
*word |= (BYPASS_FLAG << 29);
|
||||
*word |= (CONTROL_COMMAND_FLAG << 28);
|
||||
|
||||
*word |= (RESERVED_FIELD_A << 26);
|
||||
*word |= (SPACECRAFT_ID << 16);
|
||||
*word |= (VIRTUAL_CHANNEL << 10);
|
||||
*word |= (DUMMY_BITS << 8);
|
||||
uint8_t positiveWindow = 0;
|
||||
ReturnValue_t result =
|
||||
localParameterHandler.getValue(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, positiveWindow);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
*word |= static_cast<uint32_t>(positiveWindow);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::createSecondWord(uint32_t* word) {
|
||||
uint8_t negativeWindow = 0;
|
||||
ReturnValue_t result =
|
||||
localParameterHandler.getValue(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, negativeWindow);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
*word = 0;
|
||||
*word = 0;
|
||||
*word |= (static_cast<uint32_t>(negativeWindow) << 24);
|
||||
*word |= (HIGH_AU_MAP_ID << 16);
|
||||
*word |= (ENABLE_DERANDOMIZER << 8);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
uint32_t PdecConfig::readbackFirstWord() {
|
||||
return *(memoryBaseAddress + FRAME_HEADER_OFFSET + OFFSET_FIRST_CONFIG_WORD);
|
||||
}
|
||||
|
||||
uint32_t PdecConfig::readbackSecondWord() {
|
||||
return *(memoryBaseAddress + FRAME_HEADER_OFFSET + OFFSET_SECOND_CONFIG_WORD);
|
||||
}
|
||||
|
@ -48,6 +48,39 @@ class PdecConfig {
|
||||
ReturnValue_t getPositiveWindow(uint8_t& positiveWindow);
|
||||
ReturnValue_t getNegativeWindow(uint8_t& negativeWindow);
|
||||
|
||||
/**
|
||||
* @brief Creates the first word of the PDEC configuration
|
||||
*
|
||||
* @param word The created word will be written to this pointer
|
||||
*
|
||||
* @return OK if successful, otherwise error return value
|
||||
*
|
||||
*/
|
||||
ReturnValue_t createFirstWord(uint32_t* word);
|
||||
|
||||
/**
|
||||
* @brief Creates the second word of the PDEC configuration
|
||||
*
|
||||
* @param word The created word will be written to this pointer
|
||||
*
|
||||
* @return OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t createSecondWord(uint32_t* word);
|
||||
|
||||
/**
|
||||
* @brief Reads first config word from the config memory
|
||||
*
|
||||
* @return The config word
|
||||
*/
|
||||
uint32_t readbackFirstWord();
|
||||
|
||||
/**
|
||||
* @brief Reads the second config word from the config memory
|
||||
*
|
||||
* @return The config word
|
||||
*/
|
||||
uint32_t readbackSecondWord();
|
||||
|
||||
private:
|
||||
// TC transfer frame configuration parameters
|
||||
static const uint8_t VERSION_ID = 0;
|
||||
@ -66,6 +99,8 @@ class PdecConfig {
|
||||
|
||||
// 0x200 / 4 = 0x80
|
||||
static const uint32_t FRAME_HEADER_OFFSET = 0x80;
|
||||
static const uint32_t OFFSET_FIRST_CONFIG_WORD = 0;
|
||||
static const uint32_t OFFSET_SECOND_CONFIG_WORD = 1;
|
||||
|
||||
static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0;
|
||||
static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90;
|
||||
@ -102,8 +137,8 @@ class PdecConfig {
|
||||
*/
|
||||
ReturnValue_t createPersistentConfig();
|
||||
|
||||
ReturnValue_t writeFrameHeaderFirstOctet();
|
||||
ReturnValue_t writeFrameHeaderSecondOctet();
|
||||
ReturnValue_t writeFrameHeaderFirstWord();
|
||||
ReturnValue_t writeFrameHeaderSecondWord();
|
||||
void writeMapConfig();
|
||||
|
||||
/**
|
||||
|
@ -478,6 +478,7 @@ bool PdecHandler::checkFrameAna(uint32_t pdecFar) {
|
||||
}
|
||||
case (FrameAna_t::FRAME_DIRTY): {
|
||||
triggerEvent(INVALID_TC_FRAME, FRAME_DIRTY_RETVAL);
|
||||
checkConfig();
|
||||
sif::warning << "PdecHandler::checkFrameAna: Frame dirty" << std::endl;
|
||||
break;
|
||||
}
|
||||
@ -577,6 +578,30 @@ void PdecHandler::handleIReason(uint32_t pdecFar, ReturnValue_t parameter1) {
|
||||
}
|
||||
}
|
||||
|
||||
void PdecHandler::checkConfig() {
|
||||
uint32_t firstWord = 0;
|
||||
ReturnValue_t result = pdecConfig.createFirstWord(&firstWord);
|
||||
if (result != returnvalue::OK) {
|
||||
// This should normally never happen during runtime. So here is just
|
||||
// output a warning
|
||||
sif::warning << "PdecHandler::checkConfig: Failed to create first word" << std::endl;
|
||||
return;
|
||||
}
|
||||
uint32_t secondWord = 0;
|
||||
result = pdecConfig.createSecondWord(&secondWord);
|
||||
if (result != returnvalue::OK) {
|
||||
// This should normally never happen during runtime. So here is just
|
||||
// output a warning
|
||||
sif::warning << "PdecHandler::checkConfig: Failed to create second word" << std::endl;
|
||||
return;
|
||||
}
|
||||
uint32_t readbackFirstWord = pdecConfig.readbackFirstWord();
|
||||
uint32_t readbackSecondWord = pdecConfig.readbackSecondWord();
|
||||
if (firstWord != readbackFirstWord or secondWord != readbackSecondWord) {
|
||||
triggerEvent(PDEC_CONFIG_CORRUPTED, readbackFirstWord, readbackSecondWord);
|
||||
}
|
||||
}
|
||||
|
||||
void PdecHandler::handleNewTc() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
|
@ -282,6 +282,11 @@ class PdecHandler : public SystemObject,
|
||||
*/
|
||||
void handleIReason(uint32_t pdecFar, ReturnValue_t parameter1);
|
||||
|
||||
/**
|
||||
* @brief Checks if PDEC configuration is still correct
|
||||
*/
|
||||
void checkConfig();
|
||||
|
||||
/**
|
||||
* @brief Handles the reception of new TCs. Reads the pointer to the storage location of the
|
||||
* new TC segment, extracts the PUS packet and forwards the data to the object
|
||||
|
@ -71,6 +71,10 @@ static constexpr Event OPEN_IRQ_FILE_FAILED = event::makeEvent(SUBSYSTEM_ID, 13,
|
||||
//! [EXPORT] : [COMMENT] PDEC initialization failed. This might also be due to the persistent
|
||||
//! confiuration never becoming available, for example due to SD card issues.
|
||||
static constexpr Event PDEC_INIT_FAILED = event::makeEvent(SUBSYSTEM_ID, 14, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] The PDEC configuration area has been corrupted
|
||||
//! P1: The first configuration word
|
||||
//! P2: The second configuration word
|
||||
static constexpr Event PDEC_CONFIG_CORRUPTED = event::makeEvent(SUBSYSTEM_ID, 15, severity::HIGH);
|
||||
|
||||
// Action IDs
|
||||
static constexpr ActionId_t PRINT_CLCW = 0;
|
||||
|
@ -155,12 +155,15 @@ void PlocSupervisorHandler::doStartUp() {
|
||||
startupState = StartupState::ON;
|
||||
}
|
||||
if (startupState == StartupState::ON) {
|
||||
hkset.setReportingEnabled(true);
|
||||
setMode(_MODE_TO_ON);
|
||||
}
|
||||
}
|
||||
|
||||
void PlocSupervisorHandler::doShutDown() {
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
hkset.setReportingEnabled(false);
|
||||
hkset.setValidity(false, true);
|
||||
shutdownCmdSent = false;
|
||||
packetInBuffer = false;
|
||||
nextReplyId = supv::NONE;
|
||||
@ -170,6 +173,10 @@ void PlocSupervisorHandler::doShutDown() {
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupervisorHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
||||
if (not commandIsExecuting(GET_HK_REPORT)) {
|
||||
*id = GET_HK_REPORT;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
|
||||
@ -430,7 +437,7 @@ void PlocSupervisorHandler::fillCommandAndReplyMap() {
|
||||
insertInReplyMap(MEMORY_CHECK, 5, nullptr, 0, false);
|
||||
|
||||
// TM replies
|
||||
insertInReplyMap(HK_REPORT, 3, &hkset, SIZE_HK_REPORT);
|
||||
insertInReplyMap(HK_REPORT, 3, &hkset);
|
||||
insertInReplyMap(BOOT_STATUS_REPORT, 3, &bootStatusReport, SIZE_BOOT_STATUS_REPORT);
|
||||
insertInReplyMap(LATCHUP_REPORT, 3, &latchupStatusReport, SIZE_LATCHUP_STATUS_REPORT);
|
||||
insertInReplyMap(LOGGING_REPORT, 3, &loggingReport, SIZE_LOGGING_REPORT);
|
||||
@ -790,6 +797,8 @@ ReturnValue_t PlocSupervisorHandler::initializeLocalDataPool(localpool::DataPool
|
||||
localDataPoolMap.emplace(supv::ADC_ENG_14, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(supv::ADC_ENG_15, new PoolEntry<uint16_t>({0}));
|
||||
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(hkset.getSid(), false, 10.0));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -918,7 +927,7 @@ ReturnValue_t PlocSupervisorHandler::handleExecutionReport(const uint8_t* data)
|
||||
ReturnValue_t PlocSupervisorHandler::handleHkReport(const uint8_t* data) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
result = verifyPacket(data, supv::SIZE_HK_REPORT);
|
||||
result = verifyPacket(data, tmReader.getFullPacketLen());
|
||||
|
||||
if (result == result::CRC_FAILURE) {
|
||||
sif::error << "PlocSupervisorHandler::handleHkReport: Hk report has invalid crc" << std::endl;
|
||||
@ -2096,9 +2105,9 @@ uint32_t PlocSupervisorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t mod
|
||||
// if (result != returnvalue::OK) {
|
||||
// return result;
|
||||
// }
|
||||
//#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1
|
||||
// #if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_PLOC_SUPERVISOR == 1
|
||||
// loggingReport.printSet();
|
||||
//#endif
|
||||
// #endif
|
||||
// nextReplyId = supv::EXE_REPORT;
|
||||
// return result;
|
||||
// }
|
||||
|
@ -274,12 +274,12 @@ ReturnValue_t PlocSupvUartManager::initiateUpdateContinuation() {
|
||||
}
|
||||
|
||||
// ReturnValue_t PlocSupvHelper::startEventBufferRequest(std::string path) {
|
||||
//#ifdef XIPHOS_Q7S
|
||||
// #ifdef XIPHOS_Q7S
|
||||
// ReturnValue_t result = FilesystemHelper::checkPath(path);
|
||||
// if (result != returnvalue::OK) {
|
||||
// return result;
|
||||
// }
|
||||
//#endif
|
||||
// #endif
|
||||
// if (not std::filesystem::exists(path)) {
|
||||
// return PATH_NOT_EXISTS;
|
||||
// }
|
||||
@ -836,11 +836,11 @@ uint32_t PlocSupvUartManager::getFileSize(std::string filename) {
|
||||
ReturnValue_t PlocSupvUartManager::handleEventBufferReception(ploc::SpTmReader& reader) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
// TODO: Fix
|
||||
//#ifdef XIPHOS_Q7S
|
||||
// #ifdef XIPHOS_Q7S
|
||||
// if (not sdcMan->getActiveSdCard()) {
|
||||
// return HasFileSystemIF::FILESYSTEM_INACTIVE;
|
||||
// }
|
||||
//#endif
|
||||
// #endif
|
||||
// std::string filename = Filenaming::generateAbsoluteFilename(
|
||||
// eventBufferReq.path, eventBufferReq.filename, timestamping);
|
||||
// std::ofstream file(filename, std::ios_base::app | std::ios_base::out);
|
||||
|
@ -139,7 +139,6 @@ enum ReplyId : DeviceCommandId_t {
|
||||
// Size of complete space packet (6 byte header + size of data + 2 byte CRC)
|
||||
static const uint16_t SIZE_ACK_REPORT = 14;
|
||||
static const uint16_t SIZE_EXE_REPORT = 14;
|
||||
static const uint16_t SIZE_HK_REPORT = 52;
|
||||
static const uint16_t SIZE_BOOT_STATUS_REPORT = 24;
|
||||
static const uint16_t SIZE_LATCHUP_STATUS_REPORT = 31;
|
||||
static const uint16_t SIZE_LOGGING_REPORT = 73;
|
||||
|
@ -20,6 +20,9 @@ void SusHandler::doStartUp() {
|
||||
}
|
||||
if (internalState == InternalState::STARTUP) {
|
||||
if (commandExecuted) {
|
||||
if (waitingForRecovery) {
|
||||
waitingForRecovery = false;
|
||||
}
|
||||
setMode(MODE_ON);
|
||||
internalState = InternalState::NONE;
|
||||
commandExecuted = false;
|
||||
@ -83,15 +86,36 @@ ReturnValue_t SusHandler::scanForReply(const uint8_t *start, size_t len, DeviceC
|
||||
}
|
||||
ReturnValue_t SusHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
|
||||
const auto *reply = reinterpret_cast<const acs::SusReply *>(packet);
|
||||
if (reply->dataWasSet) {
|
||||
if (internalState == InternalState::STARTUP) {
|
||||
commandExecuted = true;
|
||||
}
|
||||
PoolReadGuard pg(&dataset);
|
||||
dataset.setValidity(true, true);
|
||||
dataset.tempC = max1227::getTemperature(reply->tempRaw);
|
||||
std::memcpy(dataset.channels.value, reply->channelsRaw, sizeof(reply->channelsRaw));
|
||||
if (!reply->dataWasSet) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
if (internalState == InternalState::STARTUP) {
|
||||
commandExecuted = true;
|
||||
}
|
||||
PoolReadGuard pg(&dataset);
|
||||
// Simple FDIR variant to make the handler more robust to invalid messages which
|
||||
// appear sometimes for the SUS device: Allow invalid message up to a certain threshold
|
||||
// before triggering FDIR reactions.
|
||||
if (reply->tempRaw == 0xfff and not waitingForRecovery) {
|
||||
if (invalidMsgCounter == 0) {
|
||||
triggerEvent(TEMPERATURE_ALL_ONES_START);
|
||||
} else if (invalidMsgCounter == susMax1227::MAX_INVALID_MSG_COUNT) {
|
||||
triggerEvent(DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT);
|
||||
waitingForRecovery = true;
|
||||
}
|
||||
invalidMsgCounter++;
|
||||
dataset.setValidity(false, true);
|
||||
dataset.tempC = thermal::INVALID_TEMPERATURE;
|
||||
std::memset(dataset.channels.value, 0, sizeof(dataset.channels.value));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
if (invalidMsgCounter > 0) {
|
||||
triggerEvent(TEMPERATURE_ALL_ONES_RECOVERY, invalidMsgCounter);
|
||||
invalidMsgCounter = 0;
|
||||
}
|
||||
dataset.setValidity(true, true);
|
||||
dataset.tempC = max1227::getTemperature(reply->tempRaw);
|
||||
std::memcpy(dataset.channels.value, reply->channelsRaw, sizeof(reply->channelsRaw));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,15 @@ class SusHandler : public DeviceHandlerBase {
|
||||
static constexpr DeviceCommandId_t REPLY = 0x77;
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::SUS_HANDLER;
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SUS_BOARD_ASS;
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SUS_HANDLER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Detected invalid values, starting invalid message counting
|
||||
static constexpr Event TEMPERATURE_ALL_ONES_START =
|
||||
event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM);
|
||||
//! [EXPORT] : [COMMENT] Detected valid values again, resetting invalid message counter.
|
||||
//! P1: Invalid message counter.
|
||||
static constexpr Event TEMPERATURE_ALL_ONES_RECOVERY =
|
||||
event::makeEvent(SUBSYSTEM_ID, 1, severity::INFO);
|
||||
|
||||
SusHandler(uint32_t objectId, uint8_t susIdx, object_id_t deviceCommunication,
|
||||
CookieIF *comCookie);
|
||||
@ -46,6 +54,8 @@ class SusHandler : public DeviceHandlerBase {
|
||||
susMax1227::SusDataset dataset;
|
||||
acs::SusRequest request{};
|
||||
uint8_t susIdx;
|
||||
bool waitingForRecovery = true;
|
||||
uint32_t invalidMsgCounter = 0;
|
||||
|
||||
uint32_t transitionDelay = 1000;
|
||||
bool goToNormalMode = false;
|
||||
|
@ -20,32 +20,47 @@ static constexpr Event CANT_GET_FIX = event::makeEvent(SUBSYSTEM_ID, 1, severity
|
||||
static constexpr DeviceCommandId_t GPS_REPLY = 0;
|
||||
static constexpr DeviceCommandId_t TRIGGER_RESET_PIN_GNSS = 5;
|
||||
|
||||
static constexpr uint32_t DATASET_ID = 0;
|
||||
enum SetIds : uint32_t {
|
||||
CORE_DATASET,
|
||||
SKYVIEW_DATASET,
|
||||
};
|
||||
|
||||
enum GpsPoolIds : lp_id_t {
|
||||
LATITUDE = 0,
|
||||
LONGITUDE = 1,
|
||||
ALTITUDE = 2,
|
||||
SPEED = 3,
|
||||
FIX_MODE = 4,
|
||||
SATS_IN_USE = 5,
|
||||
SATS_IN_VIEW = 6,
|
||||
UNIX_SECONDS = 7,
|
||||
YEAR = 8,
|
||||
MONTH = 9,
|
||||
DAY = 10,
|
||||
HOURS = 11,
|
||||
MINUTES = 12,
|
||||
SECONDS = 13
|
||||
LATITUDE,
|
||||
LONGITUDE,
|
||||
ALTITUDE,
|
||||
SPEED,
|
||||
FIX_MODE,
|
||||
SATS_IN_USE,
|
||||
SATS_IN_VIEW,
|
||||
UNIX_SECONDS,
|
||||
YEAR,
|
||||
MONTH,
|
||||
DAY,
|
||||
HOURS,
|
||||
MINUTES,
|
||||
SECONDS,
|
||||
SKYVIEW_UNIX_SECONDS,
|
||||
PRN_ID,
|
||||
AZIMUTH,
|
||||
ELEVATION,
|
||||
SIGNAL2NOISE,
|
||||
USED,
|
||||
};
|
||||
|
||||
static constexpr uint8_t CORE_DATASET_ENTRIES = 14;
|
||||
static constexpr uint8_t SKYVIEW_ENTRIES = 6;
|
||||
|
||||
static constexpr uint8_t MAX_SATELLITES = 30;
|
||||
|
||||
enum GpsFixModes : uint8_t { INVALID = 0, NO_FIX = 1, FIX_2D = 2, FIX_3D = 3 };
|
||||
|
||||
} // namespace GpsHyperion
|
||||
|
||||
class GpsPrimaryDataset : public StaticLocalDataSet<18> {
|
||||
class GpsPrimaryDataset : public StaticLocalDataSet<GpsHyperion::CORE_DATASET_ENTRIES> {
|
||||
public:
|
||||
GpsPrimaryDataset(object_id_t gpsId) : StaticLocalDataSet(sid_t(gpsId, GpsHyperion::DATASET_ID)) {
|
||||
GpsPrimaryDataset(object_id_t gpsId)
|
||||
: StaticLocalDataSet(sid_t(gpsId, GpsHyperion::CORE_DATASET)) {
|
||||
setAllVariablesReadOnly();
|
||||
}
|
||||
|
||||
@ -69,7 +84,34 @@ class GpsPrimaryDataset : public StaticLocalDataSet<18> {
|
||||
friend class GpsHyperionLinuxController;
|
||||
friend class GpsCtrlDummy;
|
||||
GpsPrimaryDataset(HasLocalDataPoolIF* hkOwner)
|
||||
: StaticLocalDataSet(hkOwner, GpsHyperion::DATASET_ID) {}
|
||||
: StaticLocalDataSet(hkOwner, GpsHyperion::CORE_DATASET) {}
|
||||
};
|
||||
|
||||
class SkyviewDataset : public StaticLocalDataSet<GpsHyperion::SKYVIEW_ENTRIES> {
|
||||
public:
|
||||
SkyviewDataset(object_id_t gpsId)
|
||||
: StaticLocalDataSet(sid_t(gpsId, GpsHyperion::SKYVIEW_DATASET)) {
|
||||
setAllVariablesReadOnly();
|
||||
}
|
||||
|
||||
lp_var_t<double> unixSeconds =
|
||||
lp_var_t<double>(sid.objectId, GpsHyperion::SKYVIEW_UNIX_SECONDS, this);
|
||||
lp_vec_t<int16_t, GpsHyperion::MAX_SATELLITES> prn_id =
|
||||
lp_vec_t<int16_t, GpsHyperion::MAX_SATELLITES>(sid.objectId, GpsHyperion::PRN_ID, this);
|
||||
lp_vec_t<int16_t, GpsHyperion::MAX_SATELLITES> azimuth =
|
||||
lp_vec_t<int16_t, GpsHyperion::MAX_SATELLITES>(sid.objectId, GpsHyperion::AZIMUTH, this);
|
||||
lp_vec_t<int16_t, GpsHyperion::MAX_SATELLITES> elevation =
|
||||
lp_vec_t<int16_t, GpsHyperion::MAX_SATELLITES>(sid.objectId, GpsHyperion::ELEVATION, this);
|
||||
lp_vec_t<double, GpsHyperion::MAX_SATELLITES> signal2noise =
|
||||
lp_vec_t<double, GpsHyperion::MAX_SATELLITES>(sid.objectId, GpsHyperion::SIGNAL2NOISE, this);
|
||||
lp_vec_t<uint8_t, GpsHyperion::MAX_SATELLITES> used =
|
||||
lp_vec_t<uint8_t, GpsHyperion::MAX_SATELLITES>(sid.objectId, GpsHyperion::USED, this);
|
||||
|
||||
private:
|
||||
friend class GpsHyperionLinuxController;
|
||||
friend class GpsCtrlDummy;
|
||||
SkyviewDataset(HasLocalDataPoolIF* hkOwner)
|
||||
: StaticLocalDataSet(hkOwner, GpsHyperion::SKYVIEW_DATASET) {}
|
||||
};
|
||||
|
||||
#endif /* MISSION_ACS_ARCHIVE_GPSDEFINITIONS_H_ */
|
||||
|
@ -42,6 +42,13 @@ enum SafeModeStrategy : uint8_t {
|
||||
SAFECTRL_DETUMBLE_DETERIORATED = 21,
|
||||
};
|
||||
|
||||
enum GpsSource : uint8_t {
|
||||
NONE,
|
||||
GPS,
|
||||
GPS_EXTRAPOLATED,
|
||||
SPG4,
|
||||
};
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::ACS_SUBSYSTEM;
|
||||
//! [EXPORT] : [COMMENT] The limits for the rotation in safe mode were violated.
|
||||
static constexpr Event SAFE_RATE_VIOLATION = MAKE_EVENT(0, severity::MEDIUM);
|
||||
@ -64,6 +71,8 @@ static constexpr Event MEKF_INVALID_MODE_VIOLATION = MAKE_EVENT(6, severity::HIG
|
||||
//! failed.
|
||||
//! P1: Missing information about magnetic field, P2: Missing information about rotational rate
|
||||
static constexpr Event SAFE_MODE_CONTROLLER_FAILURE = MAKE_EVENT(7, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] The TLE for the SGP4 Propagator has become too old.
|
||||
static constexpr Event TLE_TOO_OLD = MAKE_EVENT(8, severity::INFO);
|
||||
|
||||
extern const char* getModeStr(AcsMode mode);
|
||||
|
||||
|
@ -8,6 +8,14 @@
|
||||
|
||||
namespace susMax1227 {
|
||||
|
||||
// This is 16 seconds for a polling frequency of 0.4 seconds.
|
||||
static constexpr uint32_t MAX_INVALID_MSG_COUNT = 40;
|
||||
// Using a decrement time of 32 seconds should cause faulty device incrementation to best faster
|
||||
// the decrementation, so that FDIR reactions will eventuall be triggered.
|
||||
// NOTE: Not used currently, we perform the strange reply check logic in the handler and trigger
|
||||
// a reboot directly using the appropriate event.
|
||||
static constexpr uint32_t FAULTY_COM_DECREMENT_TIME_MS = 32000;
|
||||
|
||||
static const DeviceCommandId_t NONE = 0x0; // Set when no command is pending
|
||||
|
||||
static const DeviceCommandId_t WRITE_SETUP = 1;
|
||||
|
@ -22,7 +22,8 @@ AcsController::AcsController(object_id_t objectId, bool enableHkSets)
|
||||
mekfData(this),
|
||||
ctrlValData(this),
|
||||
actuatorCmdData(this),
|
||||
fusedRotRateData(this) {}
|
||||
fusedRotRateData(this),
|
||||
tleData(this) {}
|
||||
|
||||
ReturnValue_t AcsController::initialize() {
|
||||
ReturnValue_t result = parameterHelper.initialize();
|
||||
@ -62,6 +63,26 @@ ReturnValue_t AcsController::executeAction(ActionId_t actionId, MessageQueueId_t
|
||||
mekfLost = false;
|
||||
return HasActionsIF::EXECUTION_FINISHED;
|
||||
}
|
||||
case UPDATE_TLE: {
|
||||
if (size != 69 * 2) {
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
ReturnValue_t result = navigation.updateTle(data, data + 69);
|
||||
if (result != returnvalue::OK) {
|
||||
PoolReadGuard pg(&tleData);
|
||||
navigation.updateTle(tleData.line1.value, tleData.line2.value);
|
||||
return result;
|
||||
}
|
||||
{
|
||||
PoolReadGuard pg(&tleData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(tleData.line1.value, data, 69);
|
||||
std::memcpy(tleData.line2.value, data + 69, 69);
|
||||
tleData.setValidity(true, true);
|
||||
}
|
||||
}
|
||||
return HasActionsIF::EXECUTION_FINISHED;
|
||||
}
|
||||
default: {
|
||||
return HasActionsIF::INVALID_ACTION_ID;
|
||||
}
|
||||
@ -146,12 +167,19 @@ void AcsController::performSafe() {
|
||||
timeval now;
|
||||
Clock::getClock_timeval(&now);
|
||||
|
||||
ReturnValue_t result = navigation.useSpg4(now, &gpsDataProcessed);
|
||||
if (result == Sgp4Propagator::TLE_TOO_OLD and not tleTooOldFlag) {
|
||||
triggerEvent(acs::TLE_TOO_OLD);
|
||||
tleTooOldFlag = true;
|
||||
} else if (result != Sgp4Propagator::TLE_TOO_OLD) {
|
||||
tleTooOldFlag = false;
|
||||
}
|
||||
sensorProcessing.process(now, &sensorValues, &mgmDataProcessed, &susDataProcessed,
|
||||
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
||||
fusedRotationEstimation.estimateFusedRotationRateSafe(&susDataProcessed, &mgmDataProcessed,
|
||||
&gyrDataProcessed, &fusedRotRateData);
|
||||
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||
&susDataProcessed, &mekfData, &acsParameters);
|
||||
result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||
&susDataProcessed, &mekfData, &acsParameters);
|
||||
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
||||
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
|
||||
if (not mekfInvalidFlag) {
|
||||
@ -176,8 +204,7 @@ void AcsController::performSafe() {
|
||||
acs::SafeModeStrategy safeCtrlStrat = safeCtrl.safeCtrlStrategy(
|
||||
mgmDataProcessed.mgmVecTot.isValid(), not mekfInvalidFlag,
|
||||
gyrDataProcessed.gyrVecTot.isValid(), susDataProcessed.susVecTot.isValid(),
|
||||
fusedRotRateData.rotRateOrthogonal.isValid(), fusedRotRateData.rotRateTotal.isValid(),
|
||||
acsParameters.safeModeControllerParameters.useMekf,
|
||||
fusedRotRateData.rotRateTotal.isValid(), acsParameters.safeModeControllerParameters.useMekf,
|
||||
acsParameters.safeModeControllerParameters.useGyr,
|
||||
acsParameters.safeModeControllerParameters.dampingDuringEclipse);
|
||||
switch (safeCtrlStrat) {
|
||||
@ -195,7 +222,8 @@ void AcsController::performSafe() {
|
||||
safeCtrlFailureCounter = 0;
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_SUSMGM):
|
||||
safeCtrl.safeSusMgm(mgmDataProcessed.mgmVecTot.value, fusedRotRateData.rotRateParallel.value,
|
||||
safeCtrl.safeSusMgm(mgmDataProcessed.mgmVecTot.value, fusedRotRateData.rotRateTotal.value,
|
||||
fusedRotRateData.rotRateParallel.value,
|
||||
fusedRotRateData.rotRateOrthogonal.value,
|
||||
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
|
||||
safeCtrlFailureFlag = false;
|
||||
@ -271,10 +299,19 @@ void AcsController::performDetumble() {
|
||||
timeval now;
|
||||
Clock::getClock_timeval(&now);
|
||||
|
||||
ReturnValue_t result = navigation.useSpg4(now, &gpsDataProcessed);
|
||||
if (result == Sgp4Propagator::TLE_TOO_OLD and not tleTooOldFlag) {
|
||||
triggerEvent(acs::TLE_TOO_OLD);
|
||||
tleTooOldFlag = true;
|
||||
} else {
|
||||
tleTooOldFlag = false;
|
||||
}
|
||||
sensorProcessing.process(now, &sensorValues, &mgmDataProcessed, &susDataProcessed,
|
||||
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
||||
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||
&susDataProcessed, &mekfData, &acsParameters);
|
||||
fusedRotationEstimation.estimateFusedRotationRateSafe(&susDataProcessed, &mgmDataProcessed,
|
||||
&gyrDataProcessed, &fusedRotRateData);
|
||||
result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||
&susDataProcessed, &mekfData, &acsParameters);
|
||||
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
||||
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
|
||||
if (not mekfInvalidFlag) {
|
||||
@ -321,18 +358,18 @@ void AcsController::performDetumble() {
|
||||
if (acsParameters.safeModeControllerParameters.useMekf) {
|
||||
if (mekfData.satRotRateMekf.isValid() and
|
||||
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) <
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
acsParameters.detumbleParameter.omegaDetumbleEnd) {
|
||||
detumbleCounter++;
|
||||
}
|
||||
} else if (acsParameters.safeModeControllerParameters.useGyr) {
|
||||
if (gyrDataProcessed.gyrVecTot.isValid() and
|
||||
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) <
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
acsParameters.detumbleParameter.omegaDetumbleEnd) {
|
||||
detumbleCounter++;
|
||||
}
|
||||
} else if (fusedRotRateData.rotRateTotal.isValid() and
|
||||
VectorOperations<double>::norm(fusedRotRateData.rotRateTotal.value, 3) <
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
acsParameters.detumbleParameter.omegaDetumbleEnd) {
|
||||
detumbleCounter++;
|
||||
} else if (detumbleCounter > 0) {
|
||||
detumbleCounter -= 1;
|
||||
@ -345,7 +382,7 @@ void AcsController::performDetumble() {
|
||||
startTransition(mode, acs::SafeSubmode::DEFAULT);
|
||||
}
|
||||
|
||||
disableCtrlValData();
|
||||
updateCtrlValData(safeCtrlStrat);
|
||||
updateActuatorCmdData(cmdDipoleMtqs);
|
||||
commandActuators(cmdDipoleMtqs[0], cmdDipoleMtqs[1], cmdDipoleMtqs[2],
|
||||
acsParameters.magnetorquerParameter.torqueDuration);
|
||||
@ -355,10 +392,17 @@ void AcsController::performPointingCtrl() {
|
||||
timeval now;
|
||||
Clock::getClock_timeval(&now);
|
||||
|
||||
ReturnValue_t result = navigation.useSpg4(now, &gpsDataProcessed);
|
||||
if (result == Sgp4Propagator::TLE_TOO_OLD and not tleTooOldFlag) {
|
||||
triggerEvent(acs::TLE_TOO_OLD);
|
||||
tleTooOldFlag = true;
|
||||
} else {
|
||||
tleTooOldFlag = false;
|
||||
}
|
||||
sensorProcessing.process(now, &sensorValues, &mgmDataProcessed, &susDataProcessed,
|
||||
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
||||
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||
&susDataProcessed, &mekfData, &acsParameters);
|
||||
result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||
&susDataProcessed, &mekfData, &acsParameters);
|
||||
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
||||
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
|
||||
mekfInvalidCounter++;
|
||||
@ -616,6 +660,23 @@ void AcsController::updateActuatorCmdData(const double *rwTargetTorque,
|
||||
}
|
||||
}
|
||||
|
||||
void AcsController::updateCtrlValData(uint8_t safeModeStrat) {
|
||||
PoolReadGuard pg(&ctrlValData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(ctrlValData.tgtQuat.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
ctrlValData.tgtQuat.setValid(false);
|
||||
std::memcpy(ctrlValData.errQuat.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
ctrlValData.errQuat.setValid(false);
|
||||
ctrlValData.errAng.value = 0;
|
||||
ctrlValData.errAng.setValid(false);
|
||||
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC3, 3 * sizeof(double));
|
||||
ctrlValData.tgtRotRate.setValid(false);
|
||||
ctrlValData.safeStrat.value = safeModeStrat;
|
||||
ctrlValData.safeStrat.setValid(true);
|
||||
ctrlValData.setValidity(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
void AcsController::updateCtrlValData(double errAng, uint8_t safeModeStrat) {
|
||||
PoolReadGuard pg(&ctrlValData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
@ -646,17 +707,6 @@ void AcsController::updateCtrlValData(const double *tgtQuat, const double *errQu
|
||||
}
|
||||
}
|
||||
|
||||
void AcsController::disableCtrlValData() {
|
||||
PoolReadGuard pg(&ctrlValData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(ctrlValData.tgtQuat.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
std::memcpy(ctrlValData.errQuat.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
ctrlValData.errAng.value = 0;
|
||||
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC3, 3 * sizeof(double));
|
||||
ctrlValData.setValidity(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
// MGM Raw
|
||||
@ -727,6 +777,7 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ALTITUDE, &altitude);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GPS_POSITION, &gpsPosition);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GPS_VELOCITY, &gpsVelocity);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SOURCE, &gpsSource);
|
||||
poolManager.subscribeForRegularPeriodicPacket({gpsDataProcessed.getSid(), enableHkSets, 30.0});
|
||||
// MEKF
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::QUAT_MEKF, &quatMekf);
|
||||
@ -750,6 +801,9 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_PARALLEL, &rotRateParallel);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_TOTAL, &rotRateTotal);
|
||||
poolManager.subscribeForRegularPeriodicPacket({fusedRotRateData.getSid(), enableHkSets, 10.0});
|
||||
// TLE Data
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::TLE_LINE_1, &line1);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::TLE_LINE_2, &line2);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <eive/objects.h>
|
||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||
#include <fsfw/coordinates/Sgp4Propagator.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <fsfw/health/HealthTable.h>
|
||||
#include <fsfw/parameters/ParameterHelper.h>
|
||||
@ -61,6 +62,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
|
||||
ParameterHelper parameterHelper;
|
||||
|
||||
bool tleTooOldFlag = false;
|
||||
uint8_t detumbleCounter = 0;
|
||||
uint8_t multipleRwUnavailableCounter = 0;
|
||||
bool mekfInvalidFlag = false;
|
||||
@ -84,6 +86,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
static const DeviceCommandId_t SOLAR_ARRAY_DEPLOYMENT_SUCCESSFUL = 0x0;
|
||||
static const DeviceCommandId_t RESET_MEKF = 0x1;
|
||||
static const DeviceCommandId_t RESTORE_MEKF_NONFINITE_RECOVERY = 0x2;
|
||||
static const DeviceCommandId_t UPDATE_TLE = 0x3;
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ACS_CTRL;
|
||||
//! [EXPORT] : [COMMENT] File deletion failed and at least one file is still existent.
|
||||
@ -117,10 +120,10 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
void updateActuatorCmdData(const int16_t* mtqTargetDipole);
|
||||
void updateActuatorCmdData(const double* rwTargetTorque, const int32_t* rwTargetSpeed,
|
||||
const int16_t* mtqTargetDipole);
|
||||
void updateCtrlValData(uint8_t safeModeStrat);
|
||||
void updateCtrlValData(double errAng, uint8_t safeModeStrat);
|
||||
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng,
|
||||
const double* tgtRotRate);
|
||||
void disableCtrlValData();
|
||||
|
||||
/* ACS Sensor Values */
|
||||
ACS::SensorValues sensorValues;
|
||||
@ -207,6 +210,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
PoolEntry<double> altitude = PoolEntry<double>();
|
||||
PoolEntry<double> gpsPosition = PoolEntry<double>(3);
|
||||
PoolEntry<double> gpsVelocity = PoolEntry<double>(3);
|
||||
PoolEntry<uint8_t> gpsSource = PoolEntry<uint8_t>();
|
||||
|
||||
// MEKF
|
||||
acsctrl::MekfData mekfData;
|
||||
@ -234,6 +238,11 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
PoolEntry<double> rotRateParallel = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateTotal = PoolEntry<double>(3);
|
||||
|
||||
// TLE Dataset
|
||||
acsctrl::TleData tleData;
|
||||
PoolEntry<uint8_t> line1 = PoolEntry<uint8_t>(69);
|
||||
PoolEntry<uint8_t> line2 = PoolEntry<uint8_t>(69);
|
||||
|
||||
// Initial delay to make sure all pool variables have been initialized their owners
|
||||
Countdown initialCountdown = Countdown(INIT_DELAY);
|
||||
};
|
||||
|
@ -1372,12 +1372,13 @@ void ThermalController::ctrlPlPcduBoard() {
|
||||
tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
|
||||
}
|
||||
|
||||
// ToDo: remove one of the following 2
|
||||
void ThermalController::ctrlPlocMissionBoard() {
|
||||
ctrlCtx.thermalComponent = tcsCtrl::PLOCMISSION_BOARD;
|
||||
sensors[0].first = sensorTemperatures.plocHeatspreader.isValid();
|
||||
sensors[0].second = sensorTemperatures.plocHeatspreader.value;
|
||||
sensors[1].first = sensorTemperatures.plocMissionboard.isValid();
|
||||
sensors[1].second = sensorTemperatures.plocMissionboard.value;
|
||||
sensors[0].first = sensorTemperatures.plocMissionboard.isValid();
|
||||
sensors[0].second = sensorTemperatures.plocMissionboard.value;
|
||||
sensors[1].first = sensorTemperatures.plocHeatspreader.isValid();
|
||||
sensors[1].second = sensorTemperatures.plocHeatspreader.value;
|
||||
sensors[2].first = sensorTemperatures.dacHeatspreader.isValid();
|
||||
sensors[2].second = sensorTemperatures.dacHeatspreader.value;
|
||||
numSensors = 3;
|
||||
|
@ -26,6 +26,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case 0x1:
|
||||
parameterWrapper->set(onBoardParams.mekfViolationTimer);
|
||||
break;
|
||||
case 0x2:
|
||||
parameterWrapper->set(onBoardParams.fusedRateSafeDuringEclipse);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
@ -110,6 +113,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case 0x13:
|
||||
parameterWrapper->set(mgmHandlingParameters.mgmDerivativeFilterWeight);
|
||||
break;
|
||||
case 0x14:
|
||||
parameterWrapper->set(mgmHandlingParameters.useMgm4);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
@ -662,6 +668,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case 0x3:
|
||||
parameterWrapper->set(gpsParameters.fdirAltitude);
|
||||
break;
|
||||
case 0x4:
|
||||
parameterWrapper->set(gpsParameters.useSpg4);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ class AcsParameters : public HasParametersIF {
|
||||
struct OnBoardParams {
|
||||
double sampleTime = 0.4; // [s]
|
||||
uint16_t mekfViolationTimer = 750;
|
||||
uint8_t fusedRateSafeDuringEclipse = true;
|
||||
} onBoardParams;
|
||||
|
||||
struct InertiaEIVE {
|
||||
@ -78,7 +79,8 @@ class AcsParameters : public HasParametersIF {
|
||||
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 mgmVectorFilterWeight = 0.85;
|
||||
float mgmDerivativeFilterWeight = 0.85;
|
||||
float mgmDerivativeFilterWeight = 0.99;
|
||||
uint8_t useMgm4 = false;
|
||||
} mgmHandlingParameters;
|
||||
|
||||
struct SusHandlingParameters {
|
||||
@ -769,7 +771,7 @@ class AcsParameters : public HasParametersIF {
|
||||
-0.000889232196185857, -0.00168429567131815}};
|
||||
float susBrightnessThreshold = 0.7;
|
||||
float susVectorFilterWeight = .85;
|
||||
float susRateFilterWeight = .85;
|
||||
float susRateFilterWeight = .99;
|
||||
} susHandlingParameters;
|
||||
|
||||
struct GyrHandlingParameters {
|
||||
@ -832,15 +834,15 @@ class AcsParameters : public HasParametersIF {
|
||||
double k_alignGyr = 4.0e-5;
|
||||
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 k_orthoSusMgm = 4.4e-3;
|
||||
double k_alignSusMgm = 4.0e-5;
|
||||
double k_parallelSusMgm = 3.75e-4;
|
||||
|
||||
double sunTargetDirLeop[3] = {0, sqrt(.5), sqrt(.5)};
|
||||
double sunTargetDir[3] = {0, 0, 1};
|
||||
|
||||
uint8_t useMekf = false;
|
||||
uint8_t useGyr = true;
|
||||
uint8_t useGyr = false;
|
||||
uint8_t dampingDuringEclipse = true;
|
||||
|
||||
float sineLimitSunRotRate = 0.24;
|
||||
@ -915,6 +917,7 @@ class AcsParameters : public HasParametersIF {
|
||||
double minimumFdirAltitude = 475 * 1e3; // [m]
|
||||
double maximumFdirAltitude = 575 * 1e3; // [m]
|
||||
double fdirAltitude = 525 * 1e3; // [m]
|
||||
uint8_t useSpg4 = true;
|
||||
} gpsParameters;
|
||||
|
||||
struct SunModelParameters {
|
||||
|
@ -18,10 +18,18 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
fusedRotRateData->setValidity(false, true);
|
||||
}
|
||||
// store for calculation of angular acceleration
|
||||
if (gyrDataProcessed->gyrVecTot.isValid()) {
|
||||
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (not susDataProcessed->susVecTot.isValid()) {
|
||||
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
|
||||
// store for calculation of angular acceleration
|
||||
if (gyrDataProcessed->gyrVecTot.isValid()) {
|
||||
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -42,6 +50,10 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||
fusedRotRateParallel, 3);
|
||||
} else {
|
||||
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
|
||||
// store for calculation of angular acceleration
|
||||
if (gyrDataProcessed->gyrVecTot.isValid()) {
|
||||
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -58,11 +70,6 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||
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,
|
||||
@ -71,11 +78,17 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
|
||||
fusedRotRateData->setValidity(true, true);
|
||||
}
|
||||
|
||||
// store for calculation of angular acceleration
|
||||
if (gyrDataProcessed->gyrVecTot.isValid()) {
|
||||
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
|
||||
}
|
||||
}
|
||||
|
||||
void FusedRotationEstimation::estimateFusedRotationRateEclipse(
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
|
||||
if (not gyrDataProcessed->gyrVecTot.isValid() or
|
||||
if (not acsParameters->onBoardParams.fusedRateSafeDuringEclipse or
|
||||
not gyrDataProcessed->gyrVecTot.isValid() or
|
||||
VectorOperations<double>::norm(fusedRotRateData->rotRateTotal.value, 3) == 0) {
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
|
@ -44,3 +44,40 @@ ReturnValue_t Navigation::useMekf(ACS::SensorValues *sensorValues,
|
||||
void Navigation::resetMekf(acsctrl::MekfData *mekfData) {
|
||||
mekfStatus = multiplicativeKalmanFilter.reset(mekfData);
|
||||
}
|
||||
|
||||
ReturnValue_t Navigation::useSpg4(timeval now, acsctrl::GpsDataProcessed *gpsDataProcessed) {
|
||||
double position[3] = {0, 0, 0};
|
||||
double velocity[3] = {0, 0, 0};
|
||||
ReturnValue_t result = sgp4Propagator.propagate(position, velocity, now, 0);
|
||||
|
||||
if (result == returnvalue::OK) {
|
||||
{
|
||||
PoolReadGuard pg(gpsDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
gpsDataProcessed->source = acs::GpsSource::SPG4;
|
||||
gpsDataProcessed->source.setValid(true);
|
||||
std::memcpy(gpsDataProcessed->gpsPosition.value, position, 3 * sizeof(double));
|
||||
gpsDataProcessed->gpsPosition.setValid(true);
|
||||
std::memcpy(gpsDataProcessed->gpsVelocity.value, velocity, 3 * sizeof(double));
|
||||
gpsDataProcessed->gpsVelocity.setValid(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
{
|
||||
PoolReadGuard pg(gpsDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
gpsDataProcessed->source = acs::GpsSource::NONE;
|
||||
gpsDataProcessed->source.setValid(true);
|
||||
std::memcpy(gpsDataProcessed->gpsPosition.value, position, 3 * sizeof(double));
|
||||
gpsDataProcessed->gpsPosition.setValid(false);
|
||||
std::memcpy(gpsDataProcessed->gpsVelocity.value, velocity, 3 * sizeof(double));
|
||||
gpsDataProcessed->gpsVelocity.setValid(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t Navigation::updateTle(const uint8_t *line1, const uint8_t *line2) {
|
||||
return sgp4Propagator.initialize(line1, line2);
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
#ifndef NAVIGATION_H_
|
||||
#define NAVIGATION_H_
|
||||
|
||||
#include "../controllerdefinitions/AcsCtrlDefinitions.h"
|
||||
#include "AcsParameters.h"
|
||||
#include "MultiplicativeKalmanFilter.h"
|
||||
#include "SensorProcessing.h"
|
||||
#include "SensorValues.h"
|
||||
#include <fsfw/coordinates/Sgp4Propagator.h>
|
||||
#include <mission/acs/defs.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/controller/acs/MultiplicativeKalmanFilter.h>
|
||||
#include <mission/controller/acs/SensorProcessing.h>
|
||||
#include <mission/controller/acs/SensorValues.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
|
||||
class Navigation {
|
||||
public:
|
||||
@ -19,10 +21,14 @@ class Navigation {
|
||||
AcsParameters *acsParameters);
|
||||
void resetMekf(acsctrl::MekfData *mekfData);
|
||||
|
||||
ReturnValue_t useSpg4(timeval now, acsctrl::GpsDataProcessed *gpsDataProcessed);
|
||||
ReturnValue_t updateTle(const uint8_t *line1, const uint8_t *line2);
|
||||
|
||||
protected:
|
||||
private:
|
||||
MultiplicativeKalmanFilter multiplicativeKalmanFilter;
|
||||
ReturnValue_t mekfStatus = MultiplicativeKalmanFilter::MEKF_UNINITIALIZED;
|
||||
Sgp4Propagator sgp4Propagator;
|
||||
};
|
||||
|
||||
#endif /* ACS_NAVIGATION_H_ */
|
||||
|
@ -1,19 +1,5 @@
|
||||
#include "SensorProcessing.h"
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/constants.h>
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <fsfw/globalfunctions/timevalOperations.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "../controllerdefinitions/AcsCtrlDefinitions.h"
|
||||
#include "Igrf13Model.h"
|
||||
#include "util/MathOperations.h"
|
||||
|
||||
using namespace Math;
|
||||
|
||||
SensorProcessing::SensorProcessing() {}
|
||||
|
||||
SensorProcessing::~SensorProcessing() {}
|
||||
@ -24,21 +10,23 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
|
||||
bool mgm4valid, timeval timeOfMgmMeasurement,
|
||||
const AcsParameters::MgmHandlingParameters *mgmParameters,
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed,
|
||||
const double gpsAltitude, bool gpsValid,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed) {
|
||||
// ---------------- IGRF- 13 Implementation here
|
||||
// ------------------------------------------------
|
||||
double magIgrfModel[3] = {0.0, 0.0, 0.0};
|
||||
if (gpsValid) {
|
||||
bool gpsValid = false;
|
||||
if (gpsDataProcessed->source.value != acs::GpsSource::NONE) {
|
||||
Igrf13Model igrf13;
|
||||
igrf13.schmidtNormalization();
|
||||
igrf13.updateCoeffGH(timeOfMgmMeasurement);
|
||||
// maybe put a condition here, to only update after a full day, this
|
||||
// class function has around 700 steps to perform
|
||||
igrf13.magFieldComp(gpsDataProcessed->gdLongitude.value, gpsDataProcessed->gcLatitude.value,
|
||||
gpsAltitude, timeOfMgmMeasurement, magIgrfModel);
|
||||
gpsDataProcessed->altitude.value, timeOfMgmMeasurement, magIgrfModel);
|
||||
gpsValid = true;
|
||||
}
|
||||
if (!mgm0valid && !mgm1valid && !mgm2valid && !mgm3valid && !mgm4valid) {
|
||||
if (not mgm0valid and not mgm1valid and not mgm2valid and not mgm3valid and
|
||||
(not mgm4valid or not mgmParameters->useMgm4)) {
|
||||
{
|
||||
PoolReadGuard pg(mgmDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
@ -54,6 +42,7 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
|
||||
mgmDataProcessed->magIgrfModel.setValid(gpsValid);
|
||||
}
|
||||
}
|
||||
std::memcpy(savedMgmVecTot, ZERO_VEC_D, sizeof(savedMgmVecTot));
|
||||
return;
|
||||
}
|
||||
float mgm0ValueNoBias[3] = {0, 0, 0}, mgm1ValueNoBias[3] = {0, 0, 0},
|
||||
@ -113,7 +102,7 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
|
||||
sensorFusionDenominator[i] += 1 / mgmParameters->mgm13variance[i];
|
||||
}
|
||||
}
|
||||
if (mgm4valid) {
|
||||
if (mgm4valid and mgmParameters->useMgm4) {
|
||||
float mgm4ValueUT[3];
|
||||
VectorOperations<float>::mulScalar(mgm4Value, 1e-3, mgm4ValueUT, 3); // nT to uT
|
||||
MatrixOperations<float>::multiply(mgmParameters->mgm4orientationMatrix[0], mgm4ValueUT,
|
||||
@ -141,14 +130,14 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
|
||||
double mgmVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
||||
bool mgmVecTotDerivativeValid = false;
|
||||
double timeDiff = timevalOperations::toDouble(timeOfMgmMeasurement - timeOfSavedMagFieldEst);
|
||||
if (timeOfSavedMagFieldEst.tv_sec != 0 and timeDiff > 0) {
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
mgmVecTotDerivative[i] = (mgmVecTot[i] - savedMgmVecTot[i]) / timeDiff;
|
||||
savedMgmVecTot[i] = mgmVecTot[i];
|
||||
mgmVecTotDerivativeValid = true;
|
||||
}
|
||||
if (timeOfSavedMagFieldEst.tv_sec != 0 and timeDiff > 0 and
|
||||
VectorOperations<double>::norm(savedMgmVecTot, 3) != 0) {
|
||||
VectorOperations<double>::subtract(mgmVecTot, savedMgmVecTot, mgmVecTotDerivative, 3);
|
||||
VectorOperations<double>::mulScalar(mgmVecTotDerivative, 1. / timeDiff, mgmVecTotDerivative, 3);
|
||||
mgmVecTotDerivativeValid = true;
|
||||
}
|
||||
timeOfSavedMagFieldEst = timeOfMgmMeasurement;
|
||||
std::memcpy(savedMgmVecTot, mgmVecTot, sizeof(savedMgmVecTot));
|
||||
|
||||
if (VectorOperations<double>::norm(mgmVecTotDerivative, 3) != 0 and
|
||||
mgmDataProcessed->mgmVecTotDerivative.isValid()) {
|
||||
@ -199,8 +188,8 @@ void SensorProcessing::processSus(
|
||||
double JC2000 = JD2000 / 36525.;
|
||||
|
||||
double meanLongitude =
|
||||
sunModelParameters->omega_0 + (sunModelParameters->domega * JC2000) * PI / 180.;
|
||||
double meanAnomaly = (sunModelParameters->m_0 + sunModelParameters->dm * JC2000) * PI / 180.;
|
||||
sunModelParameters->omega_0 + (sunModelParameters->domega * JC2000) * M_PI / 180.;
|
||||
double meanAnomaly = (sunModelParameters->m_0 + sunModelParameters->dm * JC2000) * M_PI / 180.;
|
||||
|
||||
double eclipticLongitude = meanLongitude + sunModelParameters->p1 * sin(meanAnomaly) +
|
||||
sunModelParameters->p2 * sin(2 * meanAnomaly);
|
||||
@ -277,6 +266,7 @@ void SensorProcessing::processSus(
|
||||
susDataProcessed->sunIjkModel.setValid(true);
|
||||
}
|
||||
}
|
||||
std::memcpy(savedSusVecTot, ZERO_VEC_D, sizeof(savedSusVecTot));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -365,13 +355,13 @@ void SensorProcessing::processSus(
|
||||
double susVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
||||
bool susVecTotDerivativeValid = false;
|
||||
double timeDiff = timevalOperations::toDouble(timeOfSusMeasurement - timeOfSavedSusDirEst);
|
||||
if (timeOfSavedSusDirEst.tv_sec != 0 and timeDiff > 0) {
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
susVecTotDerivative[i] = (susVecTot[i] - savedSusVecTot[i]) / timeDiff;
|
||||
savedSusVecTot[i] = susVecTot[i];
|
||||
susVecTotDerivativeValid = true;
|
||||
}
|
||||
if (timeOfSavedSusDirEst.tv_sec != 0 and timeDiff > 0 and
|
||||
VectorOperations<double>::norm(savedSusVecTot, 3) != 0) {
|
||||
VectorOperations<double>::subtract(susVecTot, savedSusVecTot, susVecTotDerivative, 3);
|
||||
VectorOperations<double>::mulScalar(susVecTotDerivative, 1. / timeDiff, susVecTotDerivative, 3);
|
||||
susVecTotDerivativeValid = true;
|
||||
}
|
||||
std::memcpy(savedSusVecTot, susVecTot, sizeof(savedSusVecTot));
|
||||
if (VectorOperations<double>::norm(susVecTotDerivative, 3) != 0 and
|
||||
susDataProcessed->susVecTotDerivative.isValid()) {
|
||||
lowPassFilter(susVecTotDerivative, susDataProcessed->susVecTotDerivative.value,
|
||||
@ -535,14 +525,31 @@ void SensorProcessing::processGps(const double gpsLatitude, const double gpsLong
|
||||
const bool validGps,
|
||||
const AcsParameters::GpsParameters *gpsParameters,
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed) {
|
||||
double gdLongitude = 0, gcLatitude = 0, altitude = 0, posSatE[3] = {0, 0, 0},
|
||||
// init variables
|
||||
double gdLongitude = 0, gdLatitude = 0, gcLatitude = 0, altitude = 0, posSatE[3] = {0, 0, 0},
|
||||
gpsVelocityE[3] = {0, 0, 0};
|
||||
if (validGps) {
|
||||
// Transforming from Degree to Radians and calculation geocentric lattitude from geodetic
|
||||
gdLongitude = gpsLongitude * PI / 180.;
|
||||
double latitudeRad = gpsLatitude * PI / 180.;
|
||||
double eccentricityWgs84 = 0.0818195;
|
||||
double factor = 1 - pow(eccentricityWgs84, 2);
|
||||
uint8_t gpsSource = acs::GpsSource::NONE;
|
||||
// We do not trust the GPS and therefore it shall die here if SPG4 is running
|
||||
if (gpsDataProcessed->source.value == acs::GpsSource::SPG4 and gpsParameters->useSpg4) {
|
||||
MathOperations<double>::latLongAltFromCartesian(gpsDataProcessed->gpsPosition.value, gdLatitude,
|
||||
gdLongitude, altitude);
|
||||
double factor = 1 - pow(ECCENTRICITY_WGS84, 2);
|
||||
gcLatitude = atan(factor * tan(gdLatitude));
|
||||
{
|
||||
PoolReadGuard pg(gpsDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
gpsDataProcessed->gdLongitude.value = gdLongitude;
|
||||
gpsDataProcessed->gcLatitude.value = gcLatitude;
|
||||
gpsDataProcessed->altitude.value = altitude;
|
||||
gpsDataProcessed->setValidity(true, true);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (validGps) {
|
||||
// Transforming from Degree to Radians and calculation geocentric latitude from geodetic
|
||||
gdLongitude = gpsLongitude * M_PI / 180.;
|
||||
double latitudeRad = gpsLatitude * M_PI / 180.;
|
||||
double factor = 1 - pow(ECCENTRICITY_WGS84, 2);
|
||||
gcLatitude = atan(factor * tan(latitudeRad));
|
||||
|
||||
// Altitude FDIR
|
||||
@ -569,6 +576,8 @@ void SensorProcessing::processGps(const double gpsLatitude, const double gpsLong
|
||||
|
||||
timeOfSavedPosSatE = gpsUnixSeconds;
|
||||
validSavedPosSatE = true;
|
||||
|
||||
gpsSource = acs::GpsSource::GPS;
|
||||
}
|
||||
{
|
||||
PoolReadGuard pg(gpsDataProcessed);
|
||||
@ -579,6 +588,8 @@ void SensorProcessing::processGps(const double gpsLatitude, const double gpsLong
|
||||
std::memcpy(gpsDataProcessed->gpsPosition.value, posSatE, 3 * sizeof(double));
|
||||
std::memcpy(gpsDataProcessed->gpsVelocity.value, gpsVelocityE, 3 * sizeof(double));
|
||||
gpsDataProcessed->setValidity(validGps, true);
|
||||
gpsDataProcessed->source.value = gpsSource;
|
||||
gpsDataProcessed->source.setValid(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -606,11 +617,7 @@ void SensorProcessing::process(timeval now, ACS::SensorValues *sensorValues,
|
||||
sensorValues->mgm3Rm3100Set.fieldStrengths.value,
|
||||
sensorValues->mgm3Rm3100Set.fieldStrengths.isValid(),
|
||||
sensorValues->imtqMgmSet.mtmRawNt.value, sensorValues->imtqMgmSet.mtmRawNt.isValid(),
|
||||
now, &acsParameters->mgmHandlingParameters, gpsDataProcessed,
|
||||
sensorValues->gpsSet.altitude.value,
|
||||
(sensorValues->gpsSet.latitude.isValid() && sensorValues->gpsSet.longitude.isValid() &&
|
||||
sensorValues->gpsSet.altitude.isValid()),
|
||||
mgmDataProcessed);
|
||||
now, &acsParameters->mgmHandlingParameters, gpsDataProcessed, mgmDataProcessed);
|
||||
|
||||
processSus(sensorValues->susSets[0].channels.value, sensorValues->susSets[0].channels.isValid(),
|
||||
sensorValues->susSets[1].channels.value, sensorValues->susSets[1].channels.isValid(),
|
||||
|
@ -1,15 +1,23 @@
|
||||
#ifndef SENSORPROCESSING_H_
|
||||
#define SENSORPROCESSING_H_
|
||||
|
||||
#include <common/config/eive/resultClassIds.h>
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/constants.h>
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <fsfw/globalfunctions/timevalOperations.h>
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <stdint.h> //uint8_t
|
||||
#include <time.h> /*purpose, timeval ?*/
|
||||
#include <mission/acs/defs.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/controller/acs/Igrf13Model.h>
|
||||
#include <mission/controller/acs/SensorValues.h>
|
||||
#include <mission/controller/acs/SusConverter.h>
|
||||
#include <mission/controller/acs/util/MathOperations.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
|
||||
#include "../controllerdefinitions/AcsCtrlDefinitions.h"
|
||||
#include "AcsParameters.h"
|
||||
#include "SensorValues.h"
|
||||
#include "SusConverter.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
#include <cmath>
|
||||
|
||||
class SensorProcessing {
|
||||
public:
|
||||
@ -25,6 +33,7 @@ class SensorProcessing {
|
||||
private:
|
||||
static constexpr float ZERO_VEC_F[3] = {0, 0, 0};
|
||||
static constexpr double ZERO_VEC_D[3] = {0, 0, 0};
|
||||
static constexpr double ECCENTRICITY_WGS84 = 0.0818195;
|
||||
|
||||
protected:
|
||||
// short description needed for every function
|
||||
@ -32,8 +41,8 @@ class SensorProcessing {
|
||||
const float *mgm2Value, bool mgm2valid, const float *mgm3Value, bool mgm3valid,
|
||||
const float *mgm4Value, bool mgm4valid, timeval timeOfMgmMeasurement,
|
||||
const AcsParameters::MgmHandlingParameters *mgmParameters,
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed, const double gpsAltitude,
|
||||
bool gpsValid, acsctrl::MgmDataProcessed *mgmDataProcessed);
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed);
|
||||
|
||||
void processSus(const uint16_t *sus0Value, bool sus0valid, const uint16_t *sus1Value,
|
||||
bool sus1valid, const uint16_t *sus2Value, bool sus2valid,
|
||||
|
@ -9,10 +9,12 @@ SafeCtrl::SafeCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameter
|
||||
|
||||
SafeCtrl::~SafeCtrl() {}
|
||||
|
||||
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(
|
||||
const bool magFieldValid, const bool mekfValid, const bool satRotRateValid,
|
||||
const bool sunDirValid, const bool fusedRateSplitValid, const bool fusedRateTotalValid,
|
||||
const uint8_t mekfEnabled, const uint8_t gyrEnabled, const uint8_t dampingEnabled) {
|
||||
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||
const bool satRotRateValid, const bool sunDirValid,
|
||||
const bool fusedRateTotalValid,
|
||||
const uint8_t mekfEnabled,
|
||||
const uint8_t gyrEnabled,
|
||||
const uint8_t dampingEnabled) {
|
||||
if (not magFieldValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL;
|
||||
} else if (mekfEnabled and mekfValid) {
|
||||
@ -20,7 +22,7 @@ acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(
|
||||
} else if (sunDirValid) {
|
||||
if (gyrEnabled and satRotRateValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_GYR;
|
||||
} else if (not gyrEnabled and fusedRateSplitValid) {
|
||||
} else if (not gyrEnabled and fusedRateTotalValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_SUSMGM;
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
@ -95,9 +97,10 @@ void SafeCtrl::safeGyr(const double *magFieldB, const double *satRotRateB, const
|
||||
calculateMagneticMoment(magMomB);
|
||||
}
|
||||
|
||||
void SafeCtrl::safeSusMgm(const double *magFieldB, const double *rotRateParallelB,
|
||||
const double *rotRateOrthogonalB, const double *sunDirB,
|
||||
const double *sunDirRefB, double *magMomB, double &errorAngle) {
|
||||
void SafeCtrl::safeSusMgm(const double *magFieldB, const double *rotRateTotalB,
|
||||
const double *rotRateParallelB, 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);
|
||||
|
||||
@ -105,8 +108,14 @@ void SafeCtrl::safeSusMgm(const double *magFieldB, const double *rotRateParallel
|
||||
double dotSun = VectorOperations<double>::dot(sunDirRefB, sunDirB);
|
||||
errorAngle = acos(dotSun);
|
||||
|
||||
std::memcpy(satRotRateParallelB, rotRateParallelB, sizeof(satRotRateParallelB));
|
||||
std::memcpy(satRotRateOrthogonalB, rotRateOrthogonalB, sizeof(satRotRateOrthogonalB));
|
||||
if (VectorOperations<double>::norm(rotRateParallelB, 3) != 0 and
|
||||
VectorOperations<double>::norm(rotRateOrthogonalB, 3) != 0) {
|
||||
std::memcpy(satRotRateParallelB, rotRateParallelB, sizeof(satRotRateParallelB));
|
||||
std::memcpy(satRotRateOrthogonalB, rotRateOrthogonalB, sizeof(satRotRateOrthogonalB));
|
||||
} else {
|
||||
splitRotationalRate(rotRateTotalB, sunDirB);
|
||||
}
|
||||
|
||||
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelSusMgm,
|
||||
acsParameters->safeModeControllerParameters.k_orthoSusMgm);
|
||||
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
||||
|
@ -14,7 +14,6 @@ class SafeCtrl {
|
||||
|
||||
acs::SafeModeStrategy safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||
const bool satRotRateValid, const bool sunDirValid,
|
||||
const bool fusedRateSplitValid,
|
||||
const bool fusedRateTotalValid, const uint8_t mekfEnabled,
|
||||
const uint8_t gyrEnabled, const uint8_t dampingEnabled);
|
||||
|
||||
@ -25,9 +24,10 @@ class SafeCtrl {
|
||||
void safeGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
|
||||
const double *sunDirRefB, double *magMomB, double &errorAngle);
|
||||
|
||||
void safeSusMgm(const double *magFieldB, const double *rotRateParallelB,
|
||||
const double *rotRateOrthogonalB, const double *sunDirB, const double *sunDirRefB,
|
||||
double *magMomB, double &errorAngle);
|
||||
void safeSusMgm(const double *magFieldB, const double *rotRateTotalB,
|
||||
const double *rotRateParallelB, 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);
|
||||
|
@ -3,14 +3,15 @@
|
||||
|
||||
#include <fsfw/src/fsfw/globalfunctions/constants.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <math.h>
|
||||
#include <fsfw/src/fsfw/globalfunctions/sign.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Math;
|
||||
#include "fsfw/serviceinterface.h"
|
||||
|
||||
template <typename T1, typename T2 = T1>
|
||||
class MathOperations {
|
||||
@ -114,6 +115,44 @@ class MathOperations {
|
||||
cartesianOutput[1] = (auxRadius + alt) * cos(lat) * sin(longi);
|
||||
cartesianOutput[2] = ((1 - pow(eccentricity, 2)) * auxRadius + alt) * sin(lat);
|
||||
}
|
||||
|
||||
static void latLongAltFromCartesian(const T1 *vector, T1 &latitude, T1 &longitude, T1 &altitude) {
|
||||
/* @brief: latLongAltFromCartesian() - calculates latitude, longitude and altitude from
|
||||
* cartesian coordinates in ECEF
|
||||
* @param: x x-value of position vector [m]
|
||||
* y y-value of position vector [m]
|
||||
* z z-value of position vector [m]
|
||||
* latitude geodetic latitude [rad]
|
||||
* longitude longitude [rad]
|
||||
* altitude altitude [m]
|
||||
* @source: Fundamentals of Spacecraft Attitude Determination and Control, P.35 f
|
||||
* Landis Markley and John L. Crassidis*/
|
||||
// From World Geodetic System the Earth Radii
|
||||
double a = 6378137.0; // semimajor axis [m]
|
||||
double b = 6356752.3142; // semiminor axis [m]
|
||||
|
||||
// Calculation
|
||||
double e2 = 1 - pow(b, 2) / pow(a, 2);
|
||||
double epsilon2 = pow(a, 2) / pow(b, 2) - 1;
|
||||
double rho = sqrt(pow(vector[0], 2) + pow(vector[1], 2));
|
||||
double p = std::abs(vector[2]) / epsilon2;
|
||||
double s = pow(rho, 2) / (e2 * epsilon2);
|
||||
double q = pow(p, 2) - pow(b, 2) + s;
|
||||
double u = p / sqrt(q);
|
||||
double v = pow(b, 2) * pow(u, 2) / q;
|
||||
double P = 27 * v * s / q;
|
||||
double Q = pow(sqrt(P + 1) + sqrt(P), 2. / 3.);
|
||||
double t = (1 + Q + 1 / Q) / 6;
|
||||
double c = sqrt(pow(u, 2) - 1 + 2 * t);
|
||||
double w = (c - u) / 2;
|
||||
double d =
|
||||
sign(vector[2]) * sqrt(q) * (w + sqrt(sqrt(pow(t, 2) + v) - u * w - t / 2 - 1. / 4.));
|
||||
double N = a * sqrt(1 + epsilon2 * pow(d, 2) / pow(b, 2));
|
||||
latitude = asin((epsilon2 + 1) * d / N);
|
||||
altitude = rho * cos(latitude) + vector[2] * sin(latitude) - pow(a, 2) / N;
|
||||
longitude = atan2(vector[1], vector[0]);
|
||||
}
|
||||
|
||||
static void dcmEJ(timeval time, T1 *outputDcmEJ, T1 *outputDotDcmEJ) {
|
||||
/* @brief: dcmEJ() - calculates the transformation matrix between ECEF and ECI frame
|
||||
* @param: time Current time
|
||||
@ -140,7 +179,7 @@ class MathOperations {
|
||||
double FloorRest = floor(rest);
|
||||
double secOfDay = rest - FloorRest;
|
||||
secOfDay *= 86400;
|
||||
gmst = secOfDay / 240 * PI / 180;
|
||||
gmst = secOfDay / 240 * M_PI / 180;
|
||||
|
||||
outputDcmEJ[0] = cos(gmst);
|
||||
outputDcmEJ[1] = sin(gmst);
|
||||
@ -191,11 +230,11 @@ class MathOperations {
|
||||
double theta[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
// Earth Rotation angle
|
||||
double era = 0;
|
||||
era = 2 * PI * (0.779057273264 + 1.00273781191135448 * JD2000UTC1);
|
||||
era = 2 * M_PI * (0.779057273264 + 1.00273781191135448 * JD2000UTC1);
|
||||
// Greenwich Mean Sidereal Time
|
||||
double gmst2000 = 0.014506 + 4612.15739966 * JC2000TT + 1.39667721 * pow(JC2000TT, 2) -
|
||||
0.00009344 * pow(JC2000TT, 3) + 0.00001882 * pow(JC2000TT, 4);
|
||||
double arcsecFactor = 1 * PI / (180 * 3600);
|
||||
double arcsecFactor = 1 * M_PI / (180 * 3600);
|
||||
gmst2000 *= arcsecFactor;
|
||||
gmst2000 += era;
|
||||
|
||||
@ -247,7 +286,7 @@ class MathOperations {
|
||||
double de = 9.203 * arcsecFactor * cos(Om);
|
||||
|
||||
// % true obliquity of the ecliptic eps p.71 (simplified)
|
||||
double e = 23.43929111 * PI / 180 - 46.8150 / 3600 * JC2000TT * PI / 180;
|
||||
double e = 23.43929111 * M_PI / 180 - 46.8150 / 3600 * JC2000TT * M_PI / 180;
|
||||
|
||||
nutation[0][0] = cos(dp);
|
||||
nutation[1][0] = cos(e + de) * sin(dp);
|
||||
|
@ -20,6 +20,7 @@ enum SetIds : uint32_t {
|
||||
CTRL_VAL_DATA,
|
||||
ACTUATOR_CMD_DATA,
|
||||
FUSED_ROTATION_RATE_DATA,
|
||||
TLE_SET,
|
||||
};
|
||||
|
||||
enum PoolIds : lp_id_t {
|
||||
@ -85,6 +86,7 @@ enum PoolIds : lp_id_t {
|
||||
GYR_3_VEC,
|
||||
GYR_VEC_TOT,
|
||||
// GPS Processed
|
||||
SOURCE,
|
||||
GC_LATITUDE,
|
||||
GD_LONGITUDE,
|
||||
ALTITUDE,
|
||||
@ -108,6 +110,9 @@ enum PoolIds : lp_id_t {
|
||||
ROT_RATE_ORTHOGONAL,
|
||||
ROT_RATE_PARALLEL,
|
||||
ROT_RATE_TOTAL,
|
||||
// TLE
|
||||
TLE_LINE_1,
|
||||
TLE_LINE_2,
|
||||
};
|
||||
|
||||
static constexpr uint8_t MGM_SET_RAW_ENTRIES = 6;
|
||||
@ -116,11 +121,12 @@ static constexpr uint8_t SUS_SET_RAW_ENTRIES = 12;
|
||||
static constexpr uint8_t SUS_SET_PROCESSED_ENTRIES = 15;
|
||||
static constexpr uint8_t GYR_SET_RAW_ENTRIES = 4;
|
||||
static constexpr uint8_t GYR_SET_PROCESSED_ENTRIES = 5;
|
||||
static constexpr uint8_t GPS_SET_PROCESSED_ENTRIES = 5;
|
||||
static constexpr uint8_t GPS_SET_PROCESSED_ENTRIES = 6;
|
||||
static constexpr uint8_t MEKF_SET_ENTRIES = 3;
|
||||
static constexpr uint8_t CTRL_VAL_SET_ENTRIES = 5;
|
||||
static constexpr uint8_t ACT_CMD_SET_ENTRIES = 3;
|
||||
static constexpr uint8_t FUSED_ROT_RATE_SET_ENTRIES = 3;
|
||||
static constexpr uint8_t TLE_SET_ENTRIES = 2;
|
||||
|
||||
/**
|
||||
* @brief Raw MGM sensor data. Includes the IMTQ sensor data and actuator status.
|
||||
@ -239,6 +245,7 @@ class GpsDataProcessed : public StaticLocalDataSet<GPS_SET_PROCESSED_ENTRIES> {
|
||||
lp_var_t<double> altitude = lp_var_t<double>(sid.objectId, ALTITUDE, this);
|
||||
lp_vec_t<double, 3> gpsPosition = lp_vec_t<double, 3>(sid.objectId, GPS_POSITION, this);
|
||||
lp_vec_t<double, 3> gpsVelocity = lp_vec_t<double, 3>(sid.objectId, GPS_VELOCITY, this);
|
||||
lp_var_t<uint8_t> source = lp_var_t<uint8_t>(sid.objectId, SOURCE, this);
|
||||
|
||||
private:
|
||||
};
|
||||
@ -292,6 +299,16 @@ class FusedRotRateData : public StaticLocalDataSet<FUSED_ROT_RATE_SET_ENTRIES> {
|
||||
private:
|
||||
};
|
||||
|
||||
class TleData : public StaticLocalDataSet<TLE_SET_ENTRIES> {
|
||||
public:
|
||||
TleData(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, TLE_SET) {}
|
||||
|
||||
lp_vec_t<uint8_t, 69> line1 = lp_vec_t<uint8_t, 69>(sid.objectId, TLE_LINE_1, this);
|
||||
lp_vec_t<uint8_t, 69> line2 = lp_vec_t<uint8_t, 69>(sid.objectId, TLE_LINE_1, this);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace acsctrl
|
||||
|
||||
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_ACSCTRLDEFINITIONS_H_ */
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include <fsfw/src/fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <mission/payload/PayloadPcduHandler.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/thermal/tcsDefinitions.h"
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include <fsfw_hal/linux/UnixFileGuard.h>
|
||||
@ -64,6 +66,16 @@ void PayloadPcduHandler::doShutDown() {
|
||||
return;
|
||||
}
|
||||
state = States::PL_PCDU_OFF;
|
||||
quickTransitionAlreadyCalled = false;
|
||||
{
|
||||
PoolReadGuard pg(&adcSet);
|
||||
adcSet.setReportingEnabled(false);
|
||||
adcSet.tempC = thermal::INVALID_TEMPERATURE;
|
||||
|
||||
std::memset(adcSet.channels.value, 0, sizeof(adcSet.channels.value));
|
||||
std::memset(adcSet.processed.value, 0, sizeof(adcSet.processed.value));
|
||||
adcSet.setValidity(false, true);
|
||||
}
|
||||
// No need to set mode _MODE_POWER_DOWN, power switching was already handled
|
||||
setMode(MODE_OFF);
|
||||
}
|
||||
@ -73,14 +85,7 @@ void PayloadPcduHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||
stateMachineToNormal(modeFrom, subModeFrom);
|
||||
return;
|
||||
} else if (getMode() == _MODE_TO_ON and modeFrom == MODE_NORMAL) {
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_HPA);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_MPA);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_X8);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_DRO);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT0);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT1);
|
||||
pullAllGpiosLow(200);
|
||||
state = States::STACK_5V_CORRECT;
|
||||
}
|
||||
DeviceHandlerBase::doTransition(modeFrom, subModeFrom);
|
||||
@ -89,6 +94,11 @@ void PayloadPcduHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||
ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||
using namespace plpcdu;
|
||||
bool doFinish = true;
|
||||
if (toNormalOneShot) {
|
||||
PoolReadGuard pg(&adcSet);
|
||||
adcSet.setReportingEnabled(true);
|
||||
toNormalOneShot = false;
|
||||
}
|
||||
if (((getSubmode() >> SOLID_STATE_RELAYS_ADC_ON) & 0b1) == 1) {
|
||||
if (state == States::PL_PCDU_OFF) {
|
||||
sif::error << "PayloadPcduHandler::stateMachineToNormal: Unexpected state PL_PCDU_OFF"
|
||||
@ -114,23 +124,23 @@ ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_
|
||||
state = States::ON_TRANS_ADC_CLOSE_ZERO;
|
||||
adcCountdown.setTimeout(50);
|
||||
adcCountdown.resetTimer();
|
||||
adcState = AdcStates::BOOT_DELAY;
|
||||
adcState = AdcState::BOOT_DELAY;
|
||||
doFinish = false;
|
||||
// If the values are not close to zero, we should not allow transition
|
||||
monMode = MonitoringMode::CLOSE_TO_ZERO;
|
||||
}
|
||||
}
|
||||
if (state == States::ON_TRANS_ADC_CLOSE_ZERO) {
|
||||
if (adcState == AdcStates::BOOT_DELAY) {
|
||||
if (adcState == AdcState::BOOT_DELAY) {
|
||||
doFinish = false;
|
||||
if (adcCountdown.hasTimedOut()) {
|
||||
adcState = AdcStates::SEND_SETUP;
|
||||
adcState = AdcState::SEND_SETUP;
|
||||
adcCmdExecuted = false;
|
||||
}
|
||||
}
|
||||
if (adcState == AdcStates::SEND_SETUP) {
|
||||
if (adcState == AdcState::SEND_SETUP) {
|
||||
if (adcCmdExecuted) {
|
||||
adcState = AdcStates::NORMAL;
|
||||
adcState = AdcState::NORMAL;
|
||||
doFinish = true;
|
||||
adcCountdown.setTimeout(100);
|
||||
adcCountdown.resetTimer();
|
||||
@ -167,6 +177,7 @@ ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_
|
||||
switchHandler(MPA_ON, gpioIds::PLPCDU_ENB_MPA, "MPA");
|
||||
switchHandler(HPA_ON, gpioIds::PLPCDU_ENB_HPA, "HPA");
|
||||
if (doFinish) {
|
||||
toNormalOneShot = true;
|
||||
setMode(MODE_NORMAL);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
@ -174,11 +185,11 @@ ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_
|
||||
|
||||
ReturnValue_t PayloadPcduHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
||||
switch (adcState) {
|
||||
case (AdcStates::SEND_SETUP): {
|
||||
case (AdcState::SEND_SETUP): {
|
||||
*id = plpcdu::SETUP_CMD;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case (AdcStates::NORMAL): {
|
||||
case (AdcState::NORMAL): {
|
||||
*id = plpcdu::READ_WITH_TEMP_EXT;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
@ -190,7 +201,7 @@ ReturnValue_t PayloadPcduHandler::buildNormalDeviceCommand(DeviceCommandId_t* id
|
||||
}
|
||||
|
||||
ReturnValue_t PayloadPcduHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
|
||||
if (adcState == AdcStates::SEND_SETUP) {
|
||||
if (adcState == AdcState::SEND_SETUP) {
|
||||
*id = plpcdu::SETUP_CMD;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
@ -211,9 +222,9 @@ void PayloadPcduHandler::updateSwitchGpio(gpioId_t id, gpio::Levels level) {
|
||||
}
|
||||
|
||||
void PayloadPcduHandler::fillCommandAndReplyMap() {
|
||||
insertInCommandAndReplyMap(plpcdu::READ_CMD, 2, &adcSet);
|
||||
insertInCommandAndReplyMap(plpcdu::READ_TEMP_EXT, 1, &adcSet);
|
||||
insertInCommandAndReplyMap(plpcdu::READ_WITH_TEMP_EXT, 1, &adcSet);
|
||||
insertInCommandAndReplyMap(plpcdu::READ_CMD, 2);
|
||||
insertInCommandAndReplyMap(plpcdu::READ_TEMP_EXT, 1);
|
||||
insertInCommandAndReplyMap(plpcdu::READ_WITH_TEMP_EXT, 1);
|
||||
insertInCommandAndReplyMap(plpcdu::SETUP_CMD, 1);
|
||||
}
|
||||
|
||||
@ -277,27 +288,31 @@ ReturnValue_t PayloadPcduHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
break;
|
||||
}
|
||||
case (READ_CMD): {
|
||||
PoolReadGuard pg(&adcSet);
|
||||
if (pg.getReadResult() != returnvalue::OK) {
|
||||
return pg.getReadResult();
|
||||
{
|
||||
PoolReadGuard pg(&adcSet);
|
||||
if (pg.getReadResult() != returnvalue::OK) {
|
||||
return pg.getReadResult();
|
||||
}
|
||||
handleExtConvRead(packet);
|
||||
checkAdcValues();
|
||||
adcSet.setValidity(true, true);
|
||||
}
|
||||
handleExtConvRead(packet);
|
||||
checkAdcValues();
|
||||
adcSet.setValidity(true, true);
|
||||
handlePrintout();
|
||||
break;
|
||||
}
|
||||
case (READ_WITH_TEMP_EXT): {
|
||||
PoolReadGuard pg(&adcSet);
|
||||
if (pg.getReadResult() != returnvalue::OK) {
|
||||
return pg.getReadResult();
|
||||
{
|
||||
PoolReadGuard pg(&adcSet);
|
||||
if (pg.getReadResult() != returnvalue::OK) {
|
||||
return pg.getReadResult();
|
||||
}
|
||||
handleExtConvRead(packet);
|
||||
uint8_t tempStartIdx = ADC_REPLY_SIZE + TEMP_REPLY_SIZE - 2;
|
||||
adcSet.tempC.value =
|
||||
max1227::getTemperature(packet[tempStartIdx] << 8 | packet[tempStartIdx + 1]);
|
||||
checkAdcValues();
|
||||
adcSet.setValidity(true, true);
|
||||
}
|
||||
handleExtConvRead(packet);
|
||||
uint8_t tempStartIdx = ADC_REPLY_SIZE + TEMP_REPLY_SIZE - 2;
|
||||
adcSet.tempC.value =
|
||||
max1227::getTemperature(packet[tempStartIdx] << 8 | packet[tempStartIdx + 1]);
|
||||
checkAdcValues();
|
||||
adcSet.setValidity(true, true);
|
||||
handlePrintout();
|
||||
break;
|
||||
}
|
||||
@ -367,16 +382,9 @@ void PayloadPcduHandler::enablePeriodicPrintout(bool enable, uint8_t divider) {
|
||||
|
||||
void PayloadPcduHandler::quickTransitionBackToOff(bool startTransitionToOff, bool notifyFdir) {
|
||||
States currentState = state;
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_HPA);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_MPA);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_X8);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_DRO);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT0);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT1);
|
||||
pullAllGpiosLow(200);
|
||||
state = States::STACK_5V_SWITCHING;
|
||||
adcState = AdcStates::OFF;
|
||||
adcState = AdcState::OFF;
|
||||
if (startTransitionToOff) {
|
||||
startTransition(MODE_OFF, 0);
|
||||
}
|
||||
@ -405,10 +413,13 @@ void PayloadPcduHandler::checkAdcValues() {
|
||||
adcSet.processed[U_DRO_DIV_6] = static_cast<float>(adcSet.channels[11]) * SCALE_VOLTAGE;
|
||||
float lowerBound = 0.0;
|
||||
float upperBound = 0.0;
|
||||
bool adcTransition = false;
|
||||
adcTransition = state == States::ON_TRANS_DRO and adcCountdown.isBusy();
|
||||
// Now check against voltage and current limits, depending on state
|
||||
if (state >= States::ON_TRANS_DRO and not adcTransition) {
|
||||
bool adcTransition = adcState == AdcState::NORMAL and adcCountdown.isBusy();
|
||||
if (NO_ADC_CHECKS or adcTransition) {
|
||||
return;
|
||||
}
|
||||
// Now check against voltage and current limits.
|
||||
uint8_t submode = getSubmode();
|
||||
if (((submode >> NormalSubmodeBits::DRO_ON) & 0b1) == 0b1) {
|
||||
if (ssrToDroInjectionRequested) {
|
||||
handleFailureInjection("SSR to DRO", NEG_V_OUT_OF_BOUNDS);
|
||||
ssrToDroInjectionRequested = false;
|
||||
@ -435,8 +446,7 @@ void PayloadPcduHandler::checkAdcValues() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
adcTransition = state == States::ON_TRANS_X8 and adcCountdown.isBusy();
|
||||
if (state >= States::ON_TRANS_X8 and not adcTransition) {
|
||||
if (((submode >> NormalSubmodeBits::X8_ON) & 0b1) == 0b1) {
|
||||
if (droToX8InjectionRequested) {
|
||||
handleFailureInjection("X8 to TX", U_X8_OUT_OF_BOUNDS);
|
||||
droToX8InjectionRequested = false;
|
||||
@ -453,8 +463,7 @@ void PayloadPcduHandler::checkAdcValues() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
adcTransition = state == States::ON_TRANS_TX and adcCountdown.isBusy();
|
||||
if (state >= States::ON_TRANS_TX and not adcTransition) {
|
||||
if (((submode >> NormalSubmodeBits::TX_ON) & 0b1) == 0b1) {
|
||||
if (txToMpaInjectionRequested) {
|
||||
handleFailureInjection("TX to MPA", U_TX_OUT_OF_BOUNDS);
|
||||
txToMpaInjectionRequested = false;
|
||||
@ -471,8 +480,7 @@ void PayloadPcduHandler::checkAdcValues() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
adcTransition = state == States::ON_TRANS_MPA and adcCountdown.isBusy();
|
||||
if (state >= States::ON_TRANS_MPA and not adcTransition) {
|
||||
if (((submode >> NormalSubmodeBits::MPA_ON) & 0b1) == 0b1) {
|
||||
if (mpaToHpaInjectionRequested) {
|
||||
handleFailureInjection("MPA to HPA", U_HPA_OUT_OF_BOUNDS);
|
||||
mpaToHpaInjectionRequested = false;
|
||||
@ -489,8 +497,7 @@ void PayloadPcduHandler::checkAdcValues() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
adcTransition = state == States::ON_TRANS_HPA and adcCountdown.isBusy();
|
||||
if (state >= States::ON_TRANS_HPA and not adcTransition) {
|
||||
if (((submode >> NormalSubmodeBits::HPA_ON) & 0b1) == 0b1) {
|
||||
if (allOnInjectRequested) {
|
||||
handleFailureInjection("All On", U_HPA_OUT_OF_BOUNDS);
|
||||
allOnInjectRequested = false;
|
||||
@ -677,6 +684,18 @@ void PayloadPcduHandler::handleFailureInjection(std::string output, Event event)
|
||||
droToX8InjectionRequested = false;
|
||||
}
|
||||
|
||||
void PayloadPcduHandler::pullAllGpiosLow(uint32_t delayBeforeSwitchingOffDro) {
|
||||
sif::info << "Pulling all PL PCDU GPIOs to low" << std::endl;
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_HPA);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_MPA);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_X8);
|
||||
TaskFactory::delayTask(delayBeforeSwitchingOffDro);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_DRO);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT0);
|
||||
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT1);
|
||||
}
|
||||
|
||||
ReturnValue_t PayloadPcduHandler::handleDoubleParamUpdate(std::string key,
|
||||
ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues) {
|
||||
@ -692,6 +711,8 @@ ReturnValue_t PayloadPcduHandler::handleDoubleParamUpdate(std::string key,
|
||||
return params.writeJsonFile();
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase* PayloadPcduHandler::getDataSetHandle(sid_t sid) { return &adcSet; }
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
ReturnValue_t PayloadPcduHandler::extConvAsTwoCallback(SpiComIF* comIf, SpiCookie* cookie,
|
||||
const uint8_t* sendData, size_t sendLen,
|
||||
|
@ -76,6 +76,8 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
||||
#endif
|
||||
|
||||
private:
|
||||
static constexpr bool NO_ADC_CHECKS = false;
|
||||
|
||||
enum class States : uint8_t {
|
||||
PL_PCDU_OFF,
|
||||
STACK_5V_SWITCHING,
|
||||
@ -84,20 +86,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
||||
// Solid State Relay, enable battery voltages VBAT0 and VBAT1. This will also switch on
|
||||
// the ADC
|
||||
ON_TRANS_SSR,
|
||||
ON_TRANS_ADC_CLOSE_ZERO,
|
||||
// Enable Dielectric Resonant Oscillator and start monitoring voltages as
|
||||
// soon as DRO voltage reaches 6V
|
||||
ON_TRANS_DRO,
|
||||
// Switch on X8 compoennt and monitor voltages for 5 seconds
|
||||
ON_TRANS_X8,
|
||||
// Switch on TX component and monitor voltages for 5 seconds
|
||||
ON_TRANS_TX,
|
||||
// Switch on MPA component and monitor voltages for 5 seconds
|
||||
ON_TRANS_MPA,
|
||||
// Switch on HPA component and monitor voltages for 5 seconds
|
||||
ON_TRANS_HPA,
|
||||
// All components of the experiment are on
|
||||
PL_PCDU_ON,
|
||||
ON_TRANS_ADC_CLOSE_ZERO
|
||||
} state = States::PL_PCDU_OFF;
|
||||
|
||||
duallane::Submodes pwrSubmode = duallane::Submodes::A_SIDE;
|
||||
@ -106,7 +95,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
||||
|
||||
enum class MonitoringMode { NONE, CLOSE_TO_ZERO, NEGATIVE } monMode = MonitoringMode::NONE;
|
||||
|
||||
enum class AdcStates { OFF, BOOT_DELAY, SEND_SETUP, NORMAL } adcState = AdcStates::OFF;
|
||||
enum class AdcState { OFF, BOOT_DELAY, SEND_SETUP, NORMAL } adcState = AdcState::OFF;
|
||||
|
||||
bool goToNormalMode = false;
|
||||
plpcdu::PlPcduAdcSet adcSet;
|
||||
@ -128,6 +117,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
||||
bool mpaToHpaInjectionRequested = false;
|
||||
bool allOnInjectRequested = false;
|
||||
bool clearSetOnOffFlag = true;
|
||||
bool toNormalOneShot = true;
|
||||
|
||||
PeriodicOperationDivider opDivider = PeriodicOperationDivider(5);
|
||||
uint8_t tempReadDivisor = 1;
|
||||
@ -168,6 +158,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
||||
|
||||
void handleExtConvRead(const uint8_t* bufStart);
|
||||
void handlePrintout();
|
||||
void pullAllGpiosLow(uint32_t delayBeforeSwitchingOffDro);
|
||||
void checkAdcValues();
|
||||
void handleOutOfBoundsPrintout();
|
||||
void checkJsonFileInit();
|
||||
@ -178,6 +169,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
||||
ReturnValue_t serializeFloat(uint32_t& param, float val);
|
||||
ReturnValue_t handleDoubleParamUpdate(std::string key, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues);
|
||||
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
};
|
||||
|
||||
#endif /* LINUX_DEVICES_PLPCDUHANDLER_H_ */
|
||||
|
@ -19,11 +19,16 @@ using namespace returnvalue;
|
||||
|
||||
ScexDeviceHandler::ScexDeviceHandler(object_id_t objectId, ScexUartReader& reader, CookieIF* cookie,
|
||||
SdCardMountedIF& sdcMan)
|
||||
: DeviceHandlerBase(objectId, reader.getObjectId(), cookie), sdcMan(sdcMan), reader(reader) {}
|
||||
: DeviceHandlerBase(objectId, reader.getObjectId(), cookie), sdcMan(sdcMan), reader(reader) {
|
||||
fsUnusableEventCd.timeOut();
|
||||
}
|
||||
|
||||
ScexDeviceHandler::~ScexDeviceHandler() {}
|
||||
|
||||
void ScexDeviceHandler::doStartUp() { setMode(MODE_ON); }
|
||||
void ScexDeviceHandler::doStartUp() {
|
||||
filesystemChecks();
|
||||
setMode(MODE_ON);
|
||||
}
|
||||
|
||||
void ScexDeviceHandler::doShutDown() {
|
||||
reader.reset();
|
||||
@ -47,7 +52,7 @@ ReturnValue_t ScexDeviceHandler::buildCommandFromCommand(DeviceCommandId_t devic
|
||||
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
|
||||
}
|
||||
bool tempCheck = false;
|
||||
if (commandDataLen == 1) {
|
||||
if (commandDataLen >= 1) {
|
||||
tempCheck = commandData[0];
|
||||
}
|
||||
if (commandActive) {
|
||||
@ -215,8 +220,12 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
||||
}
|
||||
fileNameSet = true;
|
||||
} else {
|
||||
ofstream out(fileName,
|
||||
ofstream::binary | ofstream::app); // append
|
||||
if (!sdcMan.isSdCardUsable(std::nullopt)) {
|
||||
fsUnsableEvent();
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
// Append to existing file.
|
||||
ofstream out(fileName, ofstream::binary | ofstream::app);
|
||||
if (out.bad()) {
|
||||
sif::error << "ScexDeviceHandler::handleValidReply: Could not open file " << fileName
|
||||
<< std::endl;
|
||||
@ -280,18 +289,8 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
||||
}
|
||||
|
||||
void ScexDeviceHandler::performOperationHook() {
|
||||
auto mntPrefix = sdcMan.getCurrentMountPrefix();
|
||||
if (mntPrefix != nullptr) {
|
||||
std::filesystem::path fullFilePath = mntPrefix;
|
||||
std::error_code e;
|
||||
fullFilePath /= "scex";
|
||||
bool fileExists = std::filesystem::exists(fullFilePath, e);
|
||||
if (not fileExists) {
|
||||
bool created = std::filesystem::create_directory(fullFilePath, e);
|
||||
if (not created) {
|
||||
sif::error << "Could not create SCEX directory: " << e << std::endl;
|
||||
}
|
||||
}
|
||||
if (getMode() != MODE_OFF) {
|
||||
filesystemChecks();
|
||||
}
|
||||
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
|
||||
if (commandActive and finishCountdown.hasTimedOut()) {
|
||||
@ -319,6 +318,33 @@ ReturnValue_t ScexDeviceHandler::initializeLocalDataPool(localpool::DataPool& lo
|
||||
return OK;
|
||||
}
|
||||
|
||||
void ScexDeviceHandler::filesystemChecks() {
|
||||
auto mntPrefix = sdcMan.getCurrentMountPrefix();
|
||||
if (mntPrefix == nullptr or !sdcMan.isSdCardUsable(std::nullopt)) {
|
||||
sif::warning << "SCEX: Filesystem currently unavailable" << std::endl;
|
||||
fsUnsableEvent();
|
||||
} else {
|
||||
std::filesystem::path fullFilePath = mntPrefix;
|
||||
std::error_code e;
|
||||
fullFilePath /= "scex";
|
||||
bool fileExists = std::filesystem::exists(fullFilePath, e);
|
||||
if (not fileExists) {
|
||||
bool created = std::filesystem::create_directory(fullFilePath, e);
|
||||
if (not created) {
|
||||
sif::error << "Could not create SCEX directory: " << e << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScexDeviceHandler::fsUnsableEvent() {
|
||||
if (fsUnusableEventCd.isBusy()) {
|
||||
return;
|
||||
}
|
||||
triggerEvent(scex::FS_UNUSABLE);
|
||||
fsUnusableEventCd.resetTimer();
|
||||
}
|
||||
|
||||
ReturnValue_t ScexDeviceHandler::generateNewScexFile(const char* cmdName) {
|
||||
char timeString[64]{};
|
||||
auto activeSd = sdcMan.getActiveSdCard();
|
||||
@ -328,7 +354,8 @@ ReturnValue_t ScexDeviceHandler::generateNewScexFile(const char* cmdName) {
|
||||
|
||||
std::ostringstream oss;
|
||||
auto prefix = sdcMan.getCurrentMountPrefix();
|
||||
if (prefix == nullptr) {
|
||||
if (prefix == nullptr or !sdcMan.isSdCardUsable(std::nullopt)) {
|
||||
fsUnsableEvent();
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
timeval tv;
|
||||
|
@ -42,6 +42,7 @@ class ScexDeviceHandler : public DeviceHandlerBase {
|
||||
scex::Cmds currCmd = scex::Cmds::PING;
|
||||
SdCardMountedIF &sdcMan;
|
||||
Countdown finishCountdown = Countdown(LONG_CD);
|
||||
Countdown fsUnusableEventCd = Countdown(10000);
|
||||
|
||||
// DeviceHandlerBase private function implementation
|
||||
void doStartUp() override;
|
||||
@ -49,12 +50,15 @@ class ScexDeviceHandler : public DeviceHandlerBase {
|
||||
ScexHelper helper;
|
||||
ScexUartReader &reader;
|
||||
|
||||
void fsUnsableEvent();
|
||||
|
||||
void performOperationHook() override;
|
||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
|
||||
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
|
||||
size_t commandDataLen) override;
|
||||
void fillCommandAndReplyMap() override;
|
||||
void filesystemChecks();
|
||||
ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize, DeviceCommandId_t *foundId,
|
||||
size_t *foundLen) override;
|
||||
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
|
||||
|
@ -20,6 +20,7 @@ static constexpr Event EXPERIMENT_TIMEDOUT = event::makeEvent(SUBSYSTEM_ID, 1, s
|
||||
//! FRAM, One Cell or All cells command finished. P1: Command ID
|
||||
static constexpr Event MULTI_PACKET_COMMAND_DONE =
|
||||
event::makeEvent(SUBSYSTEM_ID, 2, severity::INFO);
|
||||
static constexpr Event FS_UNUSABLE = event::makeEvent(SUBSYSTEM_ID, 3, severity::LOW);
|
||||
|
||||
enum Cmds : DeviceCommandId_t {
|
||||
PING = 0b00111,
|
||||
|
@ -8,12 +8,12 @@
|
||||
// I really don't want to pull in all of those GomSpace headers just for 6 constants..
|
||||
// Those are the headers which contain the defines which were just hardcoded below.
|
||||
|
||||
//#include "p60acu_hk.h"
|
||||
//#include "p60acu_param.h"
|
||||
//#include "p60dock_hk.h"
|
||||
//#include "p60dock_param.h"
|
||||
//#include "p60pdu_hk.h"
|
||||
//#include "p60pdu_param.h"
|
||||
// #include "p60acu_hk.h"
|
||||
// #include "p60acu_param.h"
|
||||
// #include "p60dock_hk.h"
|
||||
// #include "p60dock_param.h"
|
||||
// #include "p60pdu_hk.h"
|
||||
// #include "p60pdu_param.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -133,6 +133,10 @@ void EiveSystem::handleEventMessages() {
|
||||
case pdec::INVALID_TC_FRAME: {
|
||||
if (event.getParameter1() == pdec::FRAME_DIRTY_RETVAL) {
|
||||
frameDirtyErrorCounter++;
|
||||
// Check whether threshold was reached after 10 seconds.
|
||||
if (frameDirtyErrorCounter == 1) {
|
||||
frameDirtyCheckCd.resetTimer();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -195,10 +199,21 @@ void EiveSystem::i2cRecoveryLogic() {
|
||||
// Try recovery.
|
||||
executeAction(EXECUTE_I2C_REBOOT, MessageQueueIF::NO_QUEUE, nullptr, 0);
|
||||
} else {
|
||||
if (waitingForI2cReboot) {
|
||||
return;
|
||||
}
|
||||
triggerEvent(core::I2C_REBOOT);
|
||||
// Some delay to ensure that the event is stored in the persistent TM store as well.
|
||||
TaskFactory::delayTask(500);
|
||||
// We already tried an I2C recovery but the bus is still broken.
|
||||
// Send full reboot request to core controller.
|
||||
sendFullRebootCommand();
|
||||
// Send reboot request to core controller.
|
||||
result = sendSelfRebootCommand();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "Sending a reboot command has failed" << std::endl;
|
||||
// If the previous operation failed, it should be re-attempted the next task cycle.
|
||||
return;
|
||||
}
|
||||
waitingForI2cReboot = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -285,29 +300,39 @@ ReturnValue_t EiveSystem::sendFullRebootCommand() {
|
||||
}
|
||||
|
||||
void EiveSystem::pdecRecoveryLogic() {
|
||||
if (ptmeResetWasAttempted and ptmeResetWasAttemptedCd.hasTimedOut()) {
|
||||
ptmeResetWasAttempted = false;
|
||||
// PDEC reset has happened too often in the last time. Perform reboot to same image.
|
||||
if (pdecResetCounter >= PDEC_RESET_MAX_COUNT_BEFORE_REBOOT) {
|
||||
if (waitingForPdecReboot) {
|
||||
return;
|
||||
}
|
||||
triggerEvent(core::PDEC_REBOOT);
|
||||
// Some delay to ensure that the event is stored in the persistent TM store as well.
|
||||
TaskFactory::delayTask(500);
|
||||
// Send reboot command.
|
||||
ReturnValue_t result = sendSelfRebootCommand();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "Sending a reboot command has failed" << std::endl;
|
||||
// If the previous operation failed, it should be re-attempted the next task cycle.
|
||||
pdecResetCounterResetCd.resetTimer();
|
||||
return;
|
||||
}
|
||||
waitingForPdecReboot = true;
|
||||
return;
|
||||
}
|
||||
if (frameDirtyCheckCd.hasTimedOut()) {
|
||||
if (pdecResetCounterResetCd.hasTimedOut()) {
|
||||
pdecResetCounter = 0;
|
||||
}
|
||||
if (frameDirtyCheckCd.hasTimedOut() and frameDirtyErrorCounter > 0) {
|
||||
if (frameDirtyErrorCounter >= FRAME_DIRTY_COM_REBOOT_LIMIT) {
|
||||
// If a PTME reset was already attempted and there is still an issue receiving TC frames,
|
||||
// reboot the system.
|
||||
if (ptmeResetWasAttempted) {
|
||||
triggerEvent(core::PDEC_REBOOT);
|
||||
// Send reboot command.
|
||||
sendFullRebootCommand();
|
||||
} else {
|
||||
// Try one full PDEC reset.
|
||||
CommandMessage msg;
|
||||
store_address_t dummy{};
|
||||
ActionMessage::setCommand(&msg, pdec::RESET_PDEC_WITH_REINIITALIZATION, dummy);
|
||||
commandQueue->sendMessage(pdecHandlerQueueId, &msg);
|
||||
ptmeResetWasAttemptedCd.resetTimer();
|
||||
ptmeResetWasAttempted = true;
|
||||
}
|
||||
// Try one full PDEC reset.
|
||||
CommandMessage msg;
|
||||
store_address_t dummy{};
|
||||
ActionMessage::setCommand(&msg, pdec::RESET_PDEC_WITH_REINIITALIZATION, dummy);
|
||||
commandQueue->sendMessage(pdecHandlerQueueId, &msg);
|
||||
pdecResetCounterResetCd.resetTimer();
|
||||
pdecResetCounter++;
|
||||
}
|
||||
frameDirtyErrorCounter = 0;
|
||||
frameDirtyCheckCd.resetTimer();
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,3 +354,17 @@ ReturnValue_t EiveSystem::handleCommandMessage(CommandMessage* message) {
|
||||
}
|
||||
return Subsystem::handleCommandMessage(message);
|
||||
}
|
||||
|
||||
ReturnValue_t EiveSystem::sendSelfRebootCommand() {
|
||||
CommandMessage msg;
|
||||
uint8_t data[1];
|
||||
// This option is used to target the same image.
|
||||
data[0] = true;
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = IPCStore->addData(&storeId, data, sizeof(data));
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
ActionMessage::setCommand(&msg, core::XSC_REBOOT_OBC, storeId);
|
||||
return commandQueue->sendMessage(coreCtrlQueueId, &msg);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
class EiveSystem : public Subsystem, public HasActionsIF {
|
||||
public:
|
||||
static constexpr uint8_t FRAME_DIRTY_COM_REBOOT_LIMIT = 4;
|
||||
static constexpr uint32_t PDEC_RESET_MAX_COUNT_BEFORE_REBOOT = 10;
|
||||
|
||||
static constexpr ActionId_t EXECUTE_I2C_REBOOT = 10;
|
||||
|
||||
@ -39,9 +40,11 @@ class EiveSystem : public Subsystem, public HasActionsIF {
|
||||
Countdown frameDirtyCheckCd = Countdown(10000);
|
||||
// If the PDEC reset was already attempted in the last 2 minutes, there is a high chance that
|
||||
// only a full reboot will fix the issue.
|
||||
Countdown ptmeResetWasAttemptedCd = Countdown(120000);
|
||||
bool ptmeResetWasAttempted = false;
|
||||
Countdown pdecResetCounterResetCd = Countdown(120000);
|
||||
bool waitingForI2cReboot = false;
|
||||
bool waitingForPdecReboot = false;
|
||||
|
||||
uint32_t pdecResetCounter = 0;
|
||||
ActionHelper actionHelper;
|
||||
PowerSwitchIF* powerSwitcher = nullptr;
|
||||
std::atomic_uint16_t& i2cErrors;
|
||||
@ -63,6 +66,7 @@ class EiveSystem : public Subsystem, public HasActionsIF {
|
||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
||||
|
||||
ReturnValue_t sendFullRebootCommand();
|
||||
ReturnValue_t sendSelfRebootCommand();
|
||||
|
||||
void pdecRecoveryLogic();
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "SusFdir.h"
|
||||
|
||||
#include "eive/objects.h"
|
||||
#include "mission/acs/susMax1227Helpers.h"
|
||||
|
||||
SusFdir::SusFdir(object_id_t sensorId)
|
||||
: DeviceHandlerFailureIsolation(sensorId, objects::SUS_BOARD_ASS) {}
|
||||
|
@ -320,6 +320,7 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() {
|
||||
}
|
||||
// File will change, reset this field for correct state-keeping.
|
||||
dumpParams.currentSameFileIdx = std::nullopt;
|
||||
dumpParams.currentFileUnixStamp = dumpParams.dumpIter->epoch;
|
||||
// Increment iterator for next cycle.
|
||||
dumpParams.dumpIter++;
|
||||
};
|
||||
|
2
tmtc
2
tmtc
@ -1 +1 @@
|
||||
Subproject commit cbcc06ede704d36e1558aae922092470fee5ff66
|
||||
Subproject commit d23cc6834ad0895c230d2378b0c8d9ba4f374f8d
|
Loading…
Reference in New Issue
Block a user