v3.1.1 reduced to minimum #687
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -16,12 +16,23 @@ will consitute of a breaking change warranting a new major release:
|
|||
|
||||
# [unreleased]
|
||||
|
||||
- Fix sun vector calculation
|
||||
|
||||
# [v2.0.5] to be released
|
||||
|
||||
- The dual lane assembly transition failed handler started new transitions towards the current mode
|
||||
instead of the target mode. This means that if the dual lane assembly never reached the initial
|
||||
submode (e.g. mode normal and submode dual side), it will transition back to the current mode,
|
||||
which miht be `MODE_OFF`. Furthermore, this can lead to invalid internal states, so the subsequent
|
||||
recovery handling becomes stuck in the custom recovery sequence when swichting power back on.
|
||||
- The dual lane custom recovery handling was adapted to always perform proper power switch handling
|
||||
irrespective of current or target modes.
|
||||
|
||||
# [v2.0.4] 2023-04-19
|
||||
|
||||
## Fixed
|
||||
|
||||
- The dual lane assembly device handlers did not properly set their datasets
|
||||
to invalid on off transitions
|
||||
- The dual lane assembly datasets were not marked invalid properly on OFF transitions.
|
||||
|
||||
# [v2.0.3] 2023-04-17
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ cmake_minimum_required(VERSION 3.13)
|
|||
|
||||
set(OBSW_VERSION_MAJOR 2)
|
||||
set(OBSW_VERSION_MINOR 0)
|
||||
set(OBSW_VERSION_REVISION 4)
|
||||
set(OBSW_VERSION_REVISION 5)
|
||||
|
||||
# set(CMAKE_VERBOSE TRUE)
|
||||
|
||||
|
@ -146,8 +146,11 @@ set(OBSW_ADD_TMP_DEVICES
|
|||
${INIT_VAL}
|
||||
CACHE STRING "Add TMP devices")
|
||||
set(OBSW_ADD_GOMSPACE_PCDU
|
||||
${INIT_VAL}
|
||||
1
|
||||
CACHE STRING "Add GomSpace PCDU modules")
|
||||
set(OBSW_ADD_GOMSPACE_ACU
|
||||
${INIT_VAL}
|
||||
CACHE STRING "Add GomSpace ACU submodule")
|
||||
set(OBSW_ADD_RW
|
||||
${INIT_VAL}
|
||||
CACHE STRING "Add RW modules")
|
||||
|
|
18
README.md
18
README.md
|
@ -99,11 +99,21 @@ When using Windows, run theses steps in MSYS2.
|
|||
git submodule update --init
|
||||
```
|
||||
|
||||
3. Ensure that the cross-compiler is working with `arm-linux-gnueabihf-gcc --version` and that
|
||||
3. Create two system variables to pass the system root path and the cross-compiler path to the
|
||||
build system. You only need to do this once when setting up the build system.
|
||||
Example for Unix:
|
||||
|
||||
```sh
|
||||
export CROSS_COMPILE_BIN_PATH=<absolutePathToCrossCompilerBinPath>
|
||||
export ZYNQ_7020_SYSROOT=<absolutePathToSysroot>
|
||||
```
|
||||
|
||||
4. Ensure that the cross-compiler is working with
|
||||
`${CROSS_COMPILE_BIN_PATH}/arm-linux-gnueabihf-gcc --version` and that
|
||||
the sysroot environmental variables have been set like specified in the
|
||||
[root filesystem chapter](#sysroot).
|
||||
|
||||
4. Run the CMake configuration to create the build system in a `build-Debug-Q7S` folder.
|
||||
5. Run the CMake configuration to create the build system in a `build-Debug-Q7S` folder.
|
||||
Add `-G "MinGW Makefiles` in MinGW64 on Windows.
|
||||
|
||||
```sh
|
||||
|
@ -112,7 +122,7 @@ When using Windows, run theses steps in MSYS2.
|
|||
cmake --build . -j
|
||||
```
|
||||
|
||||
You can also use provided shell scripts to perform these commands.
|
||||
Please note that you can also use provided shell scripts to perform these commands.
|
||||
```sh
|
||||
cp scripts/q7s-env.sh ..
|
||||
cp scripts/q7s-env-em.sh ..
|
||||
|
@ -144,7 +154,7 @@ When using Windows, run theses steps in MSYS2.
|
|||
There are also different values for `-DTGT_BSP` to build for the Raspberry Pi
|
||||
or the Beagle Bone Black: `arm/raspberrypi` and `arm/beagleboneblack`.
|
||||
|
||||
5. Build the software with
|
||||
6. Build the software with
|
||||
|
||||
```sh
|
||||
cd cmake-build-debug-q7s
|
||||
|
|
|
@ -62,6 +62,10 @@ void ObjectFactory::produce(void* args) {
|
|||
StorageManagerIF* tmStore;
|
||||
StorageManagerIF* ipcStore;
|
||||
PersistentTmStores persistentStores;
|
||||
bool enableHkSets = false;
|
||||
#if OBSW_ENABLE_PERIODIC_HK == 1
|
||||
enableHkSets = true;
|
||||
#endif
|
||||
auto sdcMan = new DummySdCardManager("/tmp");
|
||||
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan, &ipcStore,
|
||||
&tmStore, persistentStores);
|
||||
|
@ -100,7 +104,7 @@ void ObjectFactory::produce(void* args) {
|
|||
#endif
|
||||
|
||||
dummy::DummyCfg cfg;
|
||||
dummy::createDummies(cfg, *dummySwitcher, dummyGpioIF);
|
||||
dummy::createDummies(cfg, *dummySwitcher, dummyGpioIF, enableHkSets);
|
||||
|
||||
HeaterHandler* heaterHandler = nullptr;
|
||||
// new ThermalController(objects::THERMAL_CONTROLLER);
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#define OBSW_COMMAND_SAFE_MODE_AT_STARTUP 1
|
||||
|
||||
#define OBSW_ADD_GOMSPACE_PCDU @OBSW_ADD_GOMSPACE_PCDU@
|
||||
// This define is necessary because the EM setup has the P60 dock module, but no ACU on the P60
|
||||
// module because it broke.
|
||||
#define OBSW_ADD_GOMSPACE_ACU @OBSW_ADD_GOMSPACE_ACU@
|
||||
#define OBSW_ADD_MGT @OBSW_ADD_MGT@
|
||||
#define OBSW_ADD_BPX_BATTERY_HANDLER @OBSW_ADD_BPX_BATTERY_HANDLER@
|
||||
#define OBSW_ADD_STAR_TRACKER @OBSW_ADD_STAR_TRACKER@
|
||||
|
|
|
@ -197,7 +197,6 @@ void ObjectFactory::createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchI
|
|||
CspCookie* p60DockCspCookie = new CspCookie(P60Dock::MAX_REPLY_SIZE, addresses::P60DOCK, 500);
|
||||
CspCookie* pdu1CspCookie = new CspCookie(PDU::MAX_REPLY_SIZE, addresses::PDU1, 500);
|
||||
CspCookie* pdu2CspCookie = new CspCookie(PDU::MAX_REPLY_SIZE, addresses::PDU2, 500);
|
||||
CspCookie* acuCspCookie = new CspCookie(ACU::MAX_REPLY_SIZE, addresses::ACU, 500);
|
||||
|
||||
auto p60Fdir = new GomspacePowerFdir(objects::P60DOCK_HANDLER);
|
||||
P60DockHandler* p60dockhandler = new P60DockHandler(objects::P60DOCK_HANDLER, objects::CSP_COM_IF,
|
||||
|
@ -210,10 +209,12 @@ void ObjectFactory::createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchI
|
|||
auto pdu2Fdir = new GomspacePowerFdir(objects::PDU2_HANDLER);
|
||||
Pdu2Handler* pdu2handler = new Pdu2Handler(objects::PDU2_HANDLER, objects::CSP_COM_IF,
|
||||
pdu2CspCookie, pdu2Fdir, enableHkSets);
|
||||
|
||||
#if OBSW_ADD_GOMSPACE_ACU == 1
|
||||
CspCookie* acuCspCookie = new CspCookie(ACU::MAX_REPLY_SIZE, addresses::ACU, 500);
|
||||
auto acuFdir = new GomspacePowerFdir(objects::ACU_HANDLER);
|
||||
ACUHandler* acuhandler = new ACUHandler(objects::ACU_HANDLER, objects::CSP_COM_IF, acuCspCookie,
|
||||
acuFdir, enableHkSets);
|
||||
#endif
|
||||
auto pcduHandler = new PcduHandler(objects::PCDU_HANDLER, 50);
|
||||
|
||||
/**
|
||||
|
@ -223,7 +224,9 @@ void ObjectFactory::createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchI
|
|||
p60dockhandler->setModeNormal();
|
||||
pdu1handler->setModeNormal();
|
||||
pdu2handler->setModeNormal();
|
||||
#if OBSW_ADD_GOMSPACE_ACU == 1
|
||||
acuhandler->setModeNormal();
|
||||
#endif
|
||||
if (pwrSwitcher != nullptr) {
|
||||
*pwrSwitcher = pcduHandler;
|
||||
}
|
||||
|
@ -816,7 +819,7 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
|
|||
// Core task which handles the HK store and takes care of dumping it as TM using a VC directly
|
||||
auto* hkStore = new PersistentSingleTmStoreTask(
|
||||
objects::HK_STORE_AND_TM_TASK, args.ipcStore, *args.stores.hkStore, *vc,
|
||||
persTmStore::DUMP_HK_STORE_DONE, persTmStore::DUMP_HK_STORE_DONE, *SdCardManager::instance(),
|
||||
persTmStore::DUMP_HK_STORE_DONE, persTmStore::DUMP_HK_CANCELLED, *SdCardManager::instance(),
|
||||
PTME_LOCKED);
|
||||
hkStore->connectModeTreeParent(satsystem::com::SUBSYSTEM);
|
||||
|
||||
|
|
|
@ -51,15 +51,21 @@ void ObjectFactory::produce(void* args) {
|
|||
// level components.
|
||||
dummy::DummyCfg dummyCfg;
|
||||
dummyCfg.addCoreCtrlCfg = false;
|
||||
dummyCfg.addCamSwitcherDummy = false;
|
||||
#if OBSW_ADD_SYRLINKS == 1
|
||||
dummyCfg.addSyrlinksDummies = false;
|
||||
#endif
|
||||
#if OBSW_ADD_GOMSPACE_PCDU == 1
|
||||
dummyCfg.addPowerDummies = false;
|
||||
// The ACU broke.
|
||||
dummyCfg.addOnlyAcuDummy = true;
|
||||
#endif
|
||||
#if OBSW_ADD_ACS_BOARD == 1
|
||||
dummyCfg.addAcsBoardDummies = false;
|
||||
#endif
|
||||
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
|
||||
dummyCfg.addBpxBattDummy = false;
|
||||
#endif
|
||||
|
||||
PowerSwitchIF* pwrSwitcher = nullptr;
|
||||
#if OBSW_ADD_GOMSPACE_PCDU == 0
|
||||
|
@ -69,7 +75,7 @@ void ObjectFactory::produce(void* args) {
|
|||
#endif
|
||||
satsystem::EIVE_SYSTEM.setI2cRecoveryParams(pwrSwitcher);
|
||||
|
||||
dummy::createDummies(dummyCfg, *pwrSwitcher, gpioComIF);
|
||||
dummy::createDummies(dummyCfg, *pwrSwitcher, gpioComIF, enableHkSets);
|
||||
|
||||
new CoreController(objects::CORE_CONTROLLER, enableHkSets);
|
||||
|
||||
|
@ -117,6 +123,8 @@ void ObjectFactory::produce(void* args) {
|
|||
createStrComponents(pwrSwitcher);
|
||||
#endif /* OBSW_ADD_STAR_TRACKER == 1 */
|
||||
|
||||
createPayloadComponents(gpioComIF, *pwrSwitcher);
|
||||
|
||||
#if OBSW_ADD_CCSDS_IP_CORES == 1
|
||||
CcsdsIpCoreHandler* ipCoreHandler = nullptr;
|
||||
CcsdsComponentArgs ccsdsArgs(*gpioComIF, *ipcStore, *tmStore, stores, *pusFunnel, *cfdpFunnel,
|
||||
|
|
|
@ -40,8 +40,8 @@ set(CROSS_COMPILE_OBJCOPY "${CROSS_COMPILE}-objcopy")
|
|||
set(CROSS_COMPILE_SIZE "${CROSS_COMPILE}-size")
|
||||
|
||||
# At the very least, cross compile gcc and g++ have to be set!
|
||||
find_program (CMAKE_C_COMPILER ${CROSS_COMPILE_CC} REQUIRED)
|
||||
find_program (CMAKE_CXX_COMPILER ${CROSS_COMPILE_CXX} REQUIRED)
|
||||
find_program (CMAKE_C_COMPILER ${CROSS_COMPILE_CC} HINTS $ENV{CROSS_COMPILE_BIN_PATH} REQUIRED)
|
||||
find_program (CMAKE_CXX_COMPILER ${CROSS_COMPILE_CXX} HINTS $ENV{CROSS_COMPILE_BIN_PATH} REQUIRED)
|
||||
# Useful utilities, not strictly necessary
|
||||
find_program(CMAKE_SIZE ${CROSS_COMPILE_SIZE})
|
||||
find_program(CMAKE_OBJCOPY ${CROSS_COMPILE_OBJCOPY})
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
#include <mission/power/gsDefs.h>
|
||||
|
||||
AcuDummy::AcuDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie) {}
|
||||
AcuDummy::AcuDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie, bool enableHkSets)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie),
|
||||
coreHk(this),
|
||||
auxHk(this),
|
||||
enableHkSets(enableHkSets) {}
|
||||
|
||||
AcuDummy::~AcuDummy() {}
|
||||
|
||||
|
@ -37,7 +40,49 @@ uint32_t AcuDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return
|
|||
|
||||
ReturnValue_t AcuDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
using namespace ACU;
|
||||
localDataPoolMap.emplace(pool::ACU_CURRENT_IN_CHANNELS, new PoolEntry<int16_t>(6));
|
||||
localDataPoolMap.emplace(pool::ACU_VOLTAGE_IN_CHANNELS, new PoolEntry<uint16_t>(6));
|
||||
|
||||
localDataPoolMap.emplace(pool::ACU_VCC, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(pool::ACU_VBAT, new PoolEntry<uint16_t>({0}));
|
||||
|
||||
localDataPoolMap.emplace(ACU::pool::ACU_TEMPERATURES,
|
||||
new PoolEntry<float>({10.0, 10.0, 10.0}, true));
|
||||
|
||||
localDataPoolMap.emplace(pool::ACU_MPPT_MODE, new PoolEntry<uint8_t>({0}));
|
||||
|
||||
localDataPoolMap.emplace(pool::ACU_VBOOST_IN_CHANNELS, new PoolEntry<uint16_t>(6));
|
||||
localDataPoolMap.emplace(pool::ACU_POWER_IN_CHANNELS, new PoolEntry<uint16_t>(6));
|
||||
|
||||
localDataPoolMap.emplace(pool::ACU_DAC_ENABLES, new PoolEntry<uint8_t>(3));
|
||||
localDataPoolMap.emplace(pool::ACU_DAC_RAW_CHANNELS, new PoolEntry<uint16_t>(6));
|
||||
|
||||
localDataPoolMap.emplace(pool::ACU_BOOTCAUSE, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(pool::ACU_BOOTCNT, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(pool::ACU_UPTIME, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(pool::ACU_RESET_CAUSE, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(pool::ACU_MPPT_TIME, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(pool::ACU_MPPT_PERIOD, new PoolEntry<uint16_t>({0}));
|
||||
|
||||
localDataPoolMap.emplace(pool::ACU_DEVICES, new PoolEntry<uint8_t>(8));
|
||||
localDataPoolMap.emplace(pool::ACU_DEVICES_STATUS, new PoolEntry<uint8_t>(8));
|
||||
|
||||
localDataPoolMap.emplace(pool::ACU_WDT_CNT_GND, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(pool::ACU_WDT_GND_LEFT, new PoolEntry<uint32_t>({0}));
|
||||
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(coreHk.getSid(), enableHkSets, 30.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(auxHk.getSid(), enableHkSets, 6000.0));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *AcuDummy::getDataSetHandle(sid_t sid) {
|
||||
if (sid == coreHk.getSid()) {
|
||||
return &coreHk;
|
||||
} else if (sid == auxHk.getSid()) {
|
||||
return &auxHk;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define DUMMIES_ACUDUMMY_H_
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
#include <mission/power/gsDefs.h>
|
||||
|
||||
class AcuDummy : public DeviceHandlerBase {
|
||||
public:
|
||||
|
@ -11,10 +12,14 @@ class AcuDummy : public DeviceHandlerBase {
|
|||
static const uint8_t SIMPLE_COMMAND_DATA = 1;
|
||||
static const uint8_t PERIODIC_REPLY_DATA = 2;
|
||||
|
||||
AcuDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie);
|
||||
AcuDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie, bool enableHkSets);
|
||||
virtual ~AcuDummy();
|
||||
|
||||
protected:
|
||||
ACU::CoreHk coreHk;
|
||||
ACU::AuxHk auxHk;
|
||||
bool enableHkSets;
|
||||
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||
|
@ -28,6 +33,7 @@ class AcuDummy : public DeviceHandlerBase {
|
|||
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
|
||||
};
|
||||
|
||||
#endif /* DUMMIES_ACUDUMMY_H_ */
|
||||
|
|
|
@ -2,8 +2,13 @@
|
|||
|
||||
#include <mission/acs/imtqHelpers.h>
|
||||
|
||||
ImtqDummy::ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie) {}
|
||||
ImtqDummy::ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie,
|
||||
power::Switch_t pwrSwitcher, bool enableHkSets)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie),
|
||||
setNoTorque(this),
|
||||
setWithTorque(this),
|
||||
enableHkSets(enableHkSets),
|
||||
switcher(pwrSwitcher) {}
|
||||
|
||||
ImtqDummy::~ImtqDummy() = default;
|
||||
|
||||
|
@ -11,6 +16,15 @@ void ImtqDummy::doStartUp() { setMode(MODE_NORMAL); }
|
|||
|
||||
void ImtqDummy::doShutDown() { setMode(_MODE_POWER_DOWN); }
|
||||
|
||||
ReturnValue_t ImtqDummy::getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) {
|
||||
if (switcher != power::NO_SWITCH) {
|
||||
*numberOfSwitches = 1;
|
||||
*switches = &switcher;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return DeviceHandlerBase::NO_SWITCH;
|
||||
}
|
||||
|
||||
ReturnValue_t ImtqDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) { return NOTHING_TO_SEND; }
|
||||
|
||||
ReturnValue_t ImtqDummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
|
||||
|
@ -45,5 +59,37 @@ ReturnValue_t ImtqDummy::initializeLocalDataPool(localpool::DataPool &localDataP
|
|||
localDataPoolMap.emplace(imtq::ACTUATION_RAW_STATUS, new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(imtq::DIPOLES_ID, new PoolEntry<int16_t>({0, 0, 0}));
|
||||
localDataPoolMap.emplace(imtq::CURRENT_TORQUE_DURATION, new PoolEntry<uint16_t>({0}));
|
||||
|
||||
// ENG HK No Torque
|
||||
localDataPoolMap.emplace(imtq::DIGITAL_VOLTAGE_MV, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(imtq::ANALOG_VOLTAGE_MV, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(imtq::DIGITAL_CURRENT, new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(imtq::ANALOG_CURRENT, new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(imtq::COIL_CURRENTS, &coilCurrentsMilliampsNoTorque);
|
||||
localDataPoolMap.emplace(imtq::COIL_TEMPERATURES, &coilTempsNoTorque);
|
||||
localDataPoolMap.emplace(imtq::MCU_TEMPERATURE, new PoolEntry<int16_t>({0}));
|
||||
|
||||
// ENG HK With Torque
|
||||
localDataPoolMap.emplace(imtq::DIGITAL_VOLTAGE_MV_WT, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(imtq::ANALOG_VOLTAGE_MV_WT, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(imtq::DIGITAL_CURRENT_WT, new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(imtq::ANALOG_CURRENT_WT, new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(imtq::COIL_CURRENTS_WT, &coilCurrentsMilliampsWithTorque);
|
||||
localDataPoolMap.emplace(imtq::COIL_TEMPERATURES_WT, &coilTempsWithTorque);
|
||||
localDataPoolMap.emplace(imtq::MCU_TEMPERATURE_WT, new PoolEntry<int16_t>({0}));
|
||||
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(setNoTorque.getSid(), enableHkSets, 30.0));
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(setWithTorque.getSid(), enableHkSets, 30.0));
|
||||
return DeviceHandlerBase::initializeLocalDataPool(localDataPoolMap, poolManager);
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *ImtqDummy::getDataSetHandle(sid_t sid) {
|
||||
if (sid == setNoTorque.getSid()) {
|
||||
return &setNoTorque;
|
||||
} else if (sid == setWithTorque.getSid()) {
|
||||
return &setWithTorque;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
|
||||
#include "mission/acs/imtqHelpers.h"
|
||||
|
||||
class ImtqDummy : public DeviceHandlerBase {
|
||||
public:
|
||||
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
|
||||
|
@ -11,10 +13,35 @@ class ImtqDummy : public DeviceHandlerBase {
|
|||
static const uint8_t SIMPLE_COMMAND_DATA = 1;
|
||||
static const uint8_t PERIODIC_REPLY_DATA = 2;
|
||||
|
||||
ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie);
|
||||
ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie,
|
||||
power::Switch_t pwrSwitcher, bool enableHkSets);
|
||||
~ImtqDummy() override;
|
||||
|
||||
protected:
|
||||
ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;
|
||||
imtq::HkDatasetNoTorque setNoTorque;
|
||||
imtq::HkDatasetWithTorque setWithTorque;
|
||||
bool enableHkSets;
|
||||
|
||||
PoolEntry<uint8_t> statusMode = PoolEntry<uint8_t>({0});
|
||||
PoolEntry<uint8_t> statusError = PoolEntry<uint8_t>({0});
|
||||
PoolEntry<uint8_t> statusConfig = PoolEntry<uint8_t>({0});
|
||||
PoolEntry<uint32_t> statusUptime = PoolEntry<uint32_t>({0});
|
||||
|
||||
PoolEntry<int32_t> mgmCalEntry = PoolEntry<int32_t>(3);
|
||||
PoolEntry<int16_t> dipolesPoolEntry = PoolEntry<int16_t>({0, 0, 0}, false);
|
||||
PoolEntry<uint16_t> torqueDurationEntry = PoolEntry<uint16_t>({0}, false);
|
||||
PoolEntry<float> coilCurrentsMilliampsNoTorque = PoolEntry<float>(3);
|
||||
PoolEntry<float> coilCurrentsMilliampsWithTorque = PoolEntry<float>(3);
|
||||
PoolEntry<int16_t> coilTempsNoTorque = PoolEntry<int16_t>(3);
|
||||
PoolEntry<int16_t> coilTempsWithTorque = PoolEntry<int16_t>(3);
|
||||
PoolEntry<float> mtmRawNoTorque = PoolEntry<float>(3);
|
||||
PoolEntry<uint8_t> actStatusNoTorque = PoolEntry<uint8_t>(1);
|
||||
PoolEntry<float> mtmRawWithTorque = PoolEntry<float>(3);
|
||||
PoolEntry<uint8_t> actStatusWithTorque = PoolEntry<uint8_t>(1);
|
||||
|
||||
power::Switch_t switcher = power::NO_SWITCH;
|
||||
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||
|
@ -28,6 +55,7 @@ class ImtqDummy : public DeviceHandlerBase {
|
|||
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
|
||||
};
|
||||
|
||||
#endif /* DUMMIES_IMTQDUMMY_H_ */
|
||||
|
|
|
@ -42,10 +42,13 @@
|
|||
#include "mission/system/tree/payloadModeTree.h"
|
||||
#include "mission/tcs/defs.h"
|
||||
|
||||
void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpioIF) {
|
||||
void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpioIF,
|
||||
bool enableHkSets) {
|
||||
new ComIFDummy(objects::DUMMY_COM_IF);
|
||||
auto* comCookieDummy = new ComCookieDummy();
|
||||
new BpxDummy(objects::BPX_BATT_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
if (cfg.addBpxBattDummy) {
|
||||
new BpxDummy(objects::BPX_BATT_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
}
|
||||
if (cfg.addCoreCtrlCfg) {
|
||||
new CoreControllerDummy(objects::CORE_CONTROLLER);
|
||||
}
|
||||
|
@ -72,11 +75,15 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
|||
}
|
||||
auto* imtqAssy = new ImtqAssembly(objects::IMTQ_ASSY);
|
||||
imtqAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
|
||||
auto* imtqDummy = new ImtqDummy(objects::IMTQ_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
auto* imtqDummy = new ImtqDummy(objects::IMTQ_HANDLER, objects::DUMMY_COM_IF, comCookieDummy,
|
||||
power::Switches::PDU1_CH3_MGT_5V, enableHkSets);
|
||||
imtqDummy->enableThermalModule(ThermalStateCfg());
|
||||
imtqDummy->setPowerSwitcher(&pwrSwitcher);
|
||||
imtqDummy->connectModeTreeParent(*imtqAssy);
|
||||
if (cfg.addPowerDummies) {
|
||||
new AcuDummy(objects::ACU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
if (cfg.addOnlyAcuDummy) {
|
||||
new AcuDummy(objects::ACU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy, enableHkSets);
|
||||
} else if (cfg.addPowerDummies) {
|
||||
new AcuDummy(objects::ACU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy, enableHkSets);
|
||||
new PduDummy(objects::PDU1_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
new PduDummy(objects::PDU2_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
new P60DockDummy(objects::P60DOCK_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
|
@ -195,10 +202,10 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
|||
objects::TMP1075_HANDLER_PLPCDU_0,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_0, objects::DUMMY_COM_IF, comCookieDummy));
|
||||
// damaged.
|
||||
// tmpSensorDummies.emplace(
|
||||
// objects::TMP1075_HANDLER_PLPCDU_1,
|
||||
// new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1, objects::DUMMY_COM_IF,
|
||||
// comCookieDummy));
|
||||
// tmpSensorDummies.emplace(
|
||||
// objects::TMP1075_HANDLER_PLPCDU_1,
|
||||
// new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1, objects::DUMMY_COM_IF,
|
||||
// comCookieDummy));
|
||||
tmpSensorDummies.emplace(
|
||||
objects::TMP1075_HANDLER_IF_BOARD,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_IF_BOARD, objects::DUMMY_COM_IF, comCookieDummy));
|
||||
|
@ -214,9 +221,11 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
|||
tmp.second->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
||||
}
|
||||
}
|
||||
auto* camSwitcher =
|
||||
new CamSwitcher(objects::CAM_SWITCHER, pwrSwitcher, power::Switches::PDU2_CH8_PAYLOAD_CAMERA);
|
||||
camSwitcher->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
if (cfg.addCamSwitcherDummy) {
|
||||
auto* camSwitcher = new CamSwitcher(objects::CAM_SWITCHER, pwrSwitcher,
|
||||
power::Switches::PDU2_CH8_PAYLOAD_CAMERA);
|
||||
camSwitcher->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
}
|
||||
auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
auto* plPcduDummy =
|
||||
|
|
|
@ -6,17 +6,22 @@ class GpioIF;
|
|||
|
||||
namespace dummy {
|
||||
|
||||
// Default values targeted towards EM.
|
||||
struct DummyCfg {
|
||||
bool addCoreCtrlCfg = true;
|
||||
// Special variant because the ACU broke. Overrides addPowerDummies, only ACU dummy will be added.
|
||||
bool addOnlyAcuDummy = false;
|
||||
bool addPowerDummies = true;
|
||||
bool addBpxBattDummy = true;
|
||||
bool addSyrlinksDummies = true;
|
||||
bool addAcsBoardDummies = true;
|
||||
bool addSusDummies = true;
|
||||
bool addTempSensorDummies = true;
|
||||
bool addRtdComIFDummy = true;
|
||||
bool addPlocDummies = true;
|
||||
bool addCamSwitcherDummy = false;
|
||||
};
|
||||
|
||||
void createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitch, GpioIF* gpioIF);
|
||||
void createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitch, GpioIF* gpioIF, bool enableHkSets);
|
||||
|
||||
} // namespace dummy
|
||||
|
|
2
fsfw
2
fsfw
|
@ -1 +1 @@
|
|||
Subproject commit 5eb9ee8bc1e6f8640cbea46febd11e4b92241881
|
||||
Subproject commit f80c5980ea5bf84828a22dc6b4985a8747f85df4
|
|
@ -99,6 +99,19 @@ void StarTrackerHandler::doShutDown() {
|
|||
startupState = StartupState::IDLE;
|
||||
bootState = FwBootState::NONE;
|
||||
solutionSet.setReportingEnabled(false);
|
||||
{
|
||||
PoolReadGuard pg(&solutionSet);
|
||||
solutionSet.caliQw.value = 0.0;
|
||||
solutionSet.caliQx.value = 0.0;
|
||||
solutionSet.caliQy.value = 0.0;
|
||||
solutionSet.caliQz.value = 0.0;
|
||||
solutionSet.isTrustWorthy.value = 0;
|
||||
solutionSet.setValidity(false, true);
|
||||
}
|
||||
{
|
||||
PoolReadGuard pg(&temperatureSet);
|
||||
temperatureSet.setValidity(false, true);
|
||||
}
|
||||
reinitNextSetParam = false;
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
}
|
||||
|
|
|
@ -175,7 +175,7 @@ void ThermalController::performControlOperation() {
|
|||
heaterHandler.getAllSwitchStates(heaterSwitchStateArray);
|
||||
{
|
||||
PoolReadGuard pg(&heaterInfo);
|
||||
std::memcpy(heaterInfo.heaterSwitchState.value, heaterStates.data(), 8);
|
||||
std::memcpy(heaterInfo.heaterSwitchState.value, heaterSwitchStateArray.data(), 8);
|
||||
{
|
||||
PoolReadGuard pg2(¤tVecPdu2);
|
||||
if (pg.getReadResult() == returnvalue::OK and pg2.getReadResult() == returnvalue::OK) {
|
||||
|
@ -1002,7 +1002,7 @@ void ThermalController::copyDevices() {
|
|||
|
||||
void ThermalController::ctrlAcsBoard() {
|
||||
heater::Switch switchNr = heater::HEATER_2_ACS_BRD;
|
||||
heater::Switch redSwitchNr = heater::HEATER_0_OBC_BRD;
|
||||
heater::Switch redSwitchNr = heater::HEATER_3_OBC_BRD;
|
||||
|
||||
// A side
|
||||
thermalComponent = ACS_BOARD;
|
||||
|
@ -1067,7 +1067,7 @@ void ThermalController::ctrlMgt() {
|
|||
sensors[2].first = sensorTemperatures.plpcduHeatspreader.isValid();
|
||||
sensors[2].second = sensorTemperatures.plpcduHeatspreader.value;
|
||||
numSensors = 3;
|
||||
HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_3_PCDU_PDU, mgtLimits);
|
||||
HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_1_PCDU_PDU, mgtLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
if (componentAboveUpperLimit and not mgtTooHotFlag) {
|
||||
triggerEvent(tcsCtrl::MGT_OVERHEATING, tempFloatToU32());
|
||||
|
@ -1206,7 +1206,7 @@ void ThermalController::ctrlIfBoard() {
|
|||
sensors[2].first = deviceTemperatures.mgm2SideB.isValid();
|
||||
sensors[2].second = deviceTemperatures.mgm2SideB.value;
|
||||
numSensors = 3;
|
||||
HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_3_PCDU_PDU, ifBoardLimits);
|
||||
HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_1_PCDU_PDU, ifBoardLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
// TODO: special event overheating + could go back to safe mode
|
||||
}
|
||||
|
@ -1220,7 +1220,7 @@ void ThermalController::ctrlTcsBoard() {
|
|||
sensors[2].first = sensorTemperatures.tmp1075Tcs1.isValid();
|
||||
sensors[2].second = sensorTemperatures.tmp1075Tcs1.value;
|
||||
numSensors = 3;
|
||||
HeaterContext htrCtx(heater::HEATER_0_OBC_BRD, heater::HEATER_2_ACS_BRD, tcsBoardLimits);
|
||||
HeaterContext htrCtx(heater::HEATER_3_OBC_BRD, heater::HEATER_2_ACS_BRD, tcsBoardLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
// TODO: special event overheating + could go back to safe mode
|
||||
}
|
||||
|
@ -1234,7 +1234,7 @@ void ThermalController::ctrlObc() {
|
|||
sensors[2].first = sensorTemperatures.tmp1075Tcs0.isValid();
|
||||
sensors[2].second = sensorTemperatures.tmp1075Tcs0.value;
|
||||
numSensors = 3;
|
||||
HeaterContext htrCtx(heater::HEATER_0_OBC_BRD, heater::HEATER_2_ACS_BRD, obcLimits);
|
||||
HeaterContext htrCtx(heater::HEATER_3_OBC_BRD, heater::HEATER_2_ACS_BRD, obcLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
if (componentAboveUpperLimit and not obcTooHotFlag) {
|
||||
triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32());
|
||||
|
@ -1253,7 +1253,7 @@ void ThermalController::ctrlObcIfBoard() {
|
|||
sensors[2].first = sensorTemperatures.tmp1075Tcs1.isValid();
|
||||
sensors[2].second = sensorTemperatures.tmp1075Tcs1.value;
|
||||
numSensors = 3;
|
||||
HeaterContext htrCtx(heater::HEATER_0_OBC_BRD, heater::HEATER_2_ACS_BRD, obcIfBoardLimits);
|
||||
HeaterContext htrCtx(heater::HEATER_3_OBC_BRD, heater::HEATER_2_ACS_BRD, obcIfBoardLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
if (componentAboveUpperLimit and not obcTooHotFlag) {
|
||||
triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32());
|
||||
|
@ -1288,7 +1288,7 @@ void ThermalController::ctrlPcduP60Board() {
|
|||
sensors[1].first = deviceTemperatures.temp2P60dock.isValid();
|
||||
sensors[1].second = deviceTemperatures.temp2P60dock.value;
|
||||
numSensors = 2;
|
||||
HeaterContext htrCtx(heater::HEATER_3_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduP60BoardLimits);
|
||||
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduP60BoardLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
if (componentAboveUpperLimit and not pcduSystemTooHotFlag) {
|
||||
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
|
||||
|
@ -1300,7 +1300,7 @@ void ThermalController::ctrlPcduP60Board() {
|
|||
|
||||
void ThermalController::ctrlPcduAcu() {
|
||||
thermalComponent = PCDUACU;
|
||||
heater::Switch switchNr = heater::HEATER_3_PCDU_PDU;
|
||||
heater::Switch switchNr = heater::HEATER_1_PCDU_PDU;
|
||||
heater::Switch redSwitchNr = heater::HEATER_2_ACS_BRD;
|
||||
|
||||
if (chooseHeater(switchNr, redSwitchNr)) {
|
||||
|
@ -1340,7 +1340,7 @@ void ThermalController::ctrlPcduPdu() {
|
|||
sensors[2].first = sensorTemperatures.tmp1075Tcs0.isValid();
|
||||
sensors[2].second = sensorTemperatures.tmp1075Tcs0.value;
|
||||
numSensors = 3;
|
||||
HeaterContext htrCtx(heater::HEATER_3_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduPduLimits);
|
||||
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduPduLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
if (componentAboveUpperLimit and not pcduSystemTooHotFlag) {
|
||||
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
|
||||
|
@ -1361,7 +1361,7 @@ void ThermalController::ctrlPlPcduBoard() {
|
|||
sensors[3].first = sensorTemperatures.plpcduHeatspreader.isValid();
|
||||
sensors[3].second = sensorTemperatures.plpcduHeatspreader.value;
|
||||
numSensors = 4;
|
||||
HeaterContext htrCtx(heater::HEATER_3_PCDU_PDU, heater::HEATER_2_ACS_BRD, plPcduBoardLimits);
|
||||
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, plPcduBoardLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag);
|
||||
}
|
||||
|
@ -1375,7 +1375,7 @@ void ThermalController::ctrlPlocMissionBoard() {
|
|||
sensors[2].first = sensorTemperatures.dacHeatspreader.isValid();
|
||||
sensors[2].second = sensorTemperatures.dacHeatspreader.value;
|
||||
numSensors = 3;
|
||||
HeaterContext htrCtx(heater::HEATER_1_PLOC_PROC_BRD, heater::HEATER_0_OBC_BRD,
|
||||
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD,
|
||||
plocMissionBoardLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, plocTooHotFlag);
|
||||
|
@ -1390,7 +1390,7 @@ void ThermalController::ctrlPlocProcessingBoard() {
|
|||
sensors[2].first = sensorTemperatures.dacHeatspreader.isValid();
|
||||
sensors[2].second = sensorTemperatures.dacHeatspreader.value;
|
||||
numSensors = 3;
|
||||
HeaterContext htrCtx(heater::HEATER_1_PLOC_PROC_BRD, heater::HEATER_0_OBC_BRD,
|
||||
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD,
|
||||
plocProcessingBoardLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, plocTooHotFlag);
|
||||
|
@ -1405,7 +1405,7 @@ void ThermalController::ctrlDac() {
|
|||
sensors[2].first = sensorTemperatures.plocHeatspreader.isValid();
|
||||
sensors[2].second = sensorTemperatures.plocHeatspreader.value;
|
||||
numSensors = 3;
|
||||
HeaterContext htrCtx(heater::HEATER_1_PLOC_PROC_BRD, heater::HEATER_0_OBC_BRD, dacLimits);
|
||||
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD, dacLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag);
|
||||
}
|
||||
|
@ -1631,13 +1631,18 @@ bool ThermalController::selectAndReadSensorTemp(HeaterContext& htrCtx) {
|
|||
bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch redSwitchNr) {
|
||||
bool heaterAvailable = true;
|
||||
|
||||
if (heaterHandler.getHealth(switchNr) != HasHealthIF::HEALTHY) {
|
||||
if (heaterHandler.getHealth(redSwitchNr) == HasHealthIF::HEALTHY) {
|
||||
HasHealthIF::HealthState mainHealth = heaterHandler.getHealth(switchNr);
|
||||
HasHealthIF::HealthState redHealth = heaterHandler.getHealth(redSwitchNr);
|
||||
if (mainHealth != HasHealthIF::HEALTHY) {
|
||||
if (redHealth == HasHealthIF::HEALTHY) {
|
||||
switchNr = redSwitchNr;
|
||||
redSwitchNrInUse = true;
|
||||
} else {
|
||||
heaterAvailable = false;
|
||||
triggerEvent(tcsCtrl::NO_HEALTHY_HEATER_AVAILABLE, switchNr, redSwitchNr);
|
||||
// Special case: Ground might command/do something with the heaters, so prevent spam.
|
||||
if (not(mainHealth == EXTERNAL_CONTROL and redHealth == EXTERNAL_CONTROL)) {
|
||||
triggerEvent(tcsCtrl::NO_HEALTHY_HEATER_AVAILABLE, switchNr, redSwitchNr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
redSwitchNrInUse = false;
|
||||
|
|
|
@ -221,6 +221,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
|||
case 0x23:
|
||||
parameterWrapper->setMatrix(susHandlingParameters.sus11coeffBeta);
|
||||
break;
|
||||
case 0x24:
|
||||
parameterWrapper->set(susHandlingParameters.susBrightnessThreshold);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
|
|
|
@ -766,6 +766,7 @@ class AcsParameters : public HasParametersIF {
|
|||
{116.975421945286, -5.53022680362263, -5.61081660666997, 0.109754904982136,
|
||||
0.167666815691513, 0.163137400730063, -0.000609874123906977, -0.00205336098697513,
|
||||
-0.000889232196185857, -0.00168429567131815}};
|
||||
float susBrightnessThreshold = 0.7;
|
||||
} susHandlingParameters;
|
||||
|
||||
struct GyrHandlingParameters {
|
||||
|
|
|
@ -210,49 +210,56 @@ void SensorProcessing::processSus(
|
|||
sunIjkModel[0] = cos(eclipticLongitude);
|
||||
sunIjkModel[1] = sin(eclipticLongitude) * cos(epsilon);
|
||||
sunIjkModel[2] = sin(eclipticLongitude) * sin(epsilon);
|
||||
|
||||
uint64_t susBrightness[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
if (sus0valid) {
|
||||
sus0valid = susConverter.checkSunSensorData(sus0Value);
|
||||
susBrightness[0] = susConverter.checkSunSensorData(sus0Value);
|
||||
}
|
||||
if (sus1valid) {
|
||||
sus1valid = susConverter.checkSunSensorData(sus1Value);
|
||||
susBrightness[1] = susConverter.checkSunSensorData(sus1Value);
|
||||
}
|
||||
if (sus2valid) {
|
||||
sus2valid = susConverter.checkSunSensorData(sus2Value);
|
||||
susBrightness[2] = susConverter.checkSunSensorData(sus2Value);
|
||||
}
|
||||
if (sus3valid) {
|
||||
sus3valid = susConverter.checkSunSensorData(sus3Value);
|
||||
susBrightness[3] = susConverter.checkSunSensorData(sus3Value);
|
||||
}
|
||||
if (sus4valid) {
|
||||
sus4valid = susConverter.checkSunSensorData(sus4Value);
|
||||
susBrightness[4] = susConverter.checkSunSensorData(sus4Value);
|
||||
}
|
||||
if (sus5valid) {
|
||||
sus5valid = susConverter.checkSunSensorData(sus5Value);
|
||||
susBrightness[5] = susConverter.checkSunSensorData(sus5Value);
|
||||
}
|
||||
if (sus6valid) {
|
||||
sus6valid = susConverter.checkSunSensorData(sus6Value);
|
||||
susBrightness[6] = susConverter.checkSunSensorData(sus6Value);
|
||||
}
|
||||
if (sus7valid) {
|
||||
sus7valid = susConverter.checkSunSensorData(sus7Value);
|
||||
susBrightness[7] = susConverter.checkSunSensorData(sus7Value);
|
||||
}
|
||||
if (sus8valid) {
|
||||
sus8valid = susConverter.checkSunSensorData(sus8Value);
|
||||
susBrightness[8] = susConverter.checkSunSensorData(sus8Value);
|
||||
}
|
||||
if (sus9valid) {
|
||||
sus9valid = susConverter.checkSunSensorData(sus9Value);
|
||||
susBrightness[9] = susConverter.checkSunSensorData(sus9Value);
|
||||
}
|
||||
if (sus10valid) {
|
||||
sus10valid = susConverter.checkSunSensorData(sus10Value);
|
||||
susBrightness[10] = susConverter.checkSunSensorData(sus10Value);
|
||||
}
|
||||
if (sus11valid) {
|
||||
sus11valid = susConverter.checkSunSensorData(sus11Value);
|
||||
susBrightness[11] = susConverter.checkSunSensorData(sus11Value);
|
||||
}
|
||||
|
||||
if (!sus0valid && !sus1valid && !sus2valid && !sus3valid && !sus4valid && !sus5valid &&
|
||||
!sus6valid && !sus7valid && !sus8valid && !sus9valid && !sus10valid && !sus11valid) {
|
||||
bool susValid[12] = {sus0valid, sus1valid, sus2valid, sus3valid, sus4valid, sus5valid,
|
||||
sus6valid, sus7valid, sus8valid, sus9valid, sus10valid, sus11valid};
|
||||
bool allInvalid =
|
||||
susConverter.checkValidity(susValid, susBrightness, susParameters->susBrightnessThreshold);
|
||||
|
||||
if (allInvalid) {
|
||||
{
|
||||
PoolReadGuard pg(susDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
float zeroVec[3] = {0.0, 0.0, 0.0};
|
||||
double zeroVecD[3] = {0, 0, 0};
|
||||
std::memcpy(susDataProcessed->sus0vec.value, zeroVec, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus1vec.value, zeroVec, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus2vec.value, zeroVec, 3 * sizeof(float));
|
||||
|
@ -265,8 +272,8 @@ void SensorProcessing::processSus(
|
|||
std::memcpy(susDataProcessed->sus9vec.value, zeroVec, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus10vec.value, zeroVec, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus11vec.value, zeroVec, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->susVecTot.value, zeroVec, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->susVecTotDerivative.value, zeroVec, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->susVecTot.value, zeroVecD, 3 * sizeof(double));
|
||||
std::memcpy(susDataProcessed->susVecTotDerivative.value, zeroVecD, 3 * sizeof(double));
|
||||
susDataProcessed->setValidity(false, true);
|
||||
std::memcpy(susDataProcessed->sunIjkModel.value, sunIjkModel, 3 * sizeof(double));
|
||||
susDataProcessed->sunIjkModel.setValid(true);
|
||||
|
@ -274,118 +281,78 @@ void SensorProcessing::processSus(
|
|||
}
|
||||
return;
|
||||
}
|
||||
// WARNING: NOT TRANSFORMED IN BODY FRAME YET
|
||||
// Transformation into Geomtry Frame
|
||||
float sus0VecBody[3] = {0, 0, 0}, sus1VecBody[3] = {0, 0, 0}, sus2VecBody[3] = {0, 0, 0},
|
||||
sus3VecBody[3] = {0, 0, 0}, sus4VecBody[3] = {0, 0, 0}, sus5VecBody[3] = {0, 0, 0},
|
||||
sus6VecBody[3] = {0, 0, 0}, sus7VecBody[3] = {0, 0, 0}, sus8VecBody[3] = {0, 0, 0},
|
||||
sus9VecBody[3] = {0, 0, 0}, sus10VecBody[3] = {0, 0, 0}, sus11VecBody[3] = {0, 0, 0};
|
||||
|
||||
if (sus0valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus0orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus0Value, susParameters->sus0coeffAlpha,
|
||||
susParameters->sus0coeffBeta),
|
||||
sus0VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus1valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus1orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus1Value, susParameters->sus1coeffAlpha,
|
||||
susParameters->sus1coeffBeta),
|
||||
sus1VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus2valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus2orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus2Value, susParameters->sus2coeffAlpha,
|
||||
susParameters->sus2coeffBeta),
|
||||
sus2VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus3valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus3orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus3Value, susParameters->sus3coeffAlpha,
|
||||
susParameters->sus3coeffBeta),
|
||||
sus3VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus4valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus4orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus4Value, susParameters->sus4coeffAlpha,
|
||||
susParameters->sus4coeffBeta),
|
||||
sus4VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus5valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus5orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus5Value, susParameters->sus5coeffAlpha,
|
||||
susParameters->sus5coeffBeta),
|
||||
sus5VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus6valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus6orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus6Value, susParameters->sus6coeffAlpha,
|
||||
susParameters->sus6coeffBeta),
|
||||
sus6VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus7valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus7orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus7Value, susParameters->sus7coeffAlpha,
|
||||
susParameters->sus7coeffBeta),
|
||||
sus7VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus8valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus8orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus8Value, susParameters->sus8coeffAlpha,
|
||||
susParameters->sus8coeffBeta),
|
||||
sus8VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus9valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus9orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus9Value, susParameters->sus9coeffAlpha,
|
||||
susParameters->sus9coeffBeta),
|
||||
sus9VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus10valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus10orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus10Value, susParameters->sus10coeffAlpha,
|
||||
susParameters->sus10coeffBeta),
|
||||
sus10VecBody, 3, 3, 1);
|
||||
}
|
||||
if (sus11valid) {
|
||||
MatrixOperations<float>::multiply(
|
||||
susParameters->sus11orientationMatrix[0],
|
||||
susConverter.getSunVectorSensorFrame(sus11Value, susParameters->sus11coeffAlpha,
|
||||
susParameters->sus11coeffBeta),
|
||||
sus11VecBody, 3, 3, 1);
|
||||
}
|
||||
float susVecSensor[12][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
|
||||
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
float susVecBody[12][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
|
||||
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
|
||||
/* ------ Mean Value: susDirEst ------ */
|
||||
bool validIds[12] = {sus0valid, sus1valid, sus2valid, sus3valid, sus4valid, sus5valid,
|
||||
sus6valid, sus7valid, sus8valid, sus9valid, sus10valid, sus11valid};
|
||||
float susVecBody[3][12] = {{sus0VecBody[0], sus1VecBody[0], sus2VecBody[0], sus3VecBody[0],
|
||||
sus4VecBody[0], sus5VecBody[0], sus6VecBody[0], sus7VecBody[0],
|
||||
sus8VecBody[0], sus9VecBody[0], sus10VecBody[0], sus11VecBody[0]},
|
||||
{sus0VecBody[1], sus1VecBody[1], sus2VecBody[1], sus3VecBody[1],
|
||||
sus4VecBody[1], sus5VecBody[1], sus6VecBody[1], sus7VecBody[1],
|
||||
sus8VecBody[1], sus9VecBody[1], sus10VecBody[1], sus11VecBody[1]},
|
||||
{sus0VecBody[2], sus1VecBody[2], sus2VecBody[2], sus3VecBody[2],
|
||||
sus4VecBody[2], sus5VecBody[2], sus6VecBody[2], sus7VecBody[2],
|
||||
sus8VecBody[2], sus9VecBody[2], sus10VecBody[2], sus11VecBody[2]}};
|
||||
if (susValid[0]) {
|
||||
susConverter.calculateSunVector(susVecSensor[0], sus0Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus0orientationMatrix[0], susVecSensor[0],
|
||||
susVecBody[0], 3, 3, 1);
|
||||
}
|
||||
if (susValid[1]) {
|
||||
susConverter.calculateSunVector(susVecSensor[1], sus1Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus1orientationMatrix[0], susVecSensor[1],
|
||||
susVecBody[1], 3, 3, 1);
|
||||
}
|
||||
if (susValid[2]) {
|
||||
susConverter.calculateSunVector(susVecSensor[2], sus2Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus2orientationMatrix[0], susVecSensor[2],
|
||||
susVecBody[2], 3, 3, 1);
|
||||
}
|
||||
if (susValid[3]) {
|
||||
susConverter.calculateSunVector(susVecSensor[3], sus3Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus3orientationMatrix[0], susVecSensor[3],
|
||||
susVecBody[3], 3, 3, 1);
|
||||
}
|
||||
if (susValid[4]) {
|
||||
susConverter.calculateSunVector(susVecSensor[4], sus4Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus4orientationMatrix[0], susVecSensor[4],
|
||||
susVecBody[4], 3, 3, 1);
|
||||
}
|
||||
if (susValid[5]) {
|
||||
susConverter.calculateSunVector(susVecSensor[5], sus5Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus5orientationMatrix[0], susVecSensor[5],
|
||||
susVecBody[5], 3, 3, 1);
|
||||
}
|
||||
if (susValid[6]) {
|
||||
susConverter.calculateSunVector(susVecSensor[6], sus6Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus6orientationMatrix[0], susVecSensor[6],
|
||||
susVecBody[6], 3, 3, 1);
|
||||
}
|
||||
if (susValid[7]) {
|
||||
susConverter.calculateSunVector(susVecSensor[7], sus7Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus7orientationMatrix[0], susVecSensor[7],
|
||||
susVecBody[7], 3, 3, 1);
|
||||
}
|
||||
if (susValid[8]) {
|
||||
susConverter.calculateSunVector(susVecSensor[8], sus8Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus8orientationMatrix[0], susVecSensor[8],
|
||||
susVecBody[8], 3, 3, 1);
|
||||
}
|
||||
if (susValid[9]) {
|
||||
susConverter.calculateSunVector(susVecSensor[9], sus9Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus9orientationMatrix[0], susVecSensor[9],
|
||||
susVecBody[9], 3, 3, 1);
|
||||
}
|
||||
if (susValid[10]) {
|
||||
susConverter.calculateSunVector(susVecSensor[10], sus10Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus10orientationMatrix[0], susVecSensor[10],
|
||||
susVecBody[10], 3, 3, 1);
|
||||
}
|
||||
if (susValid[11]) {
|
||||
susConverter.calculateSunVector(susVecSensor[11], sus11Value);
|
||||
MatrixOperations<float>::multiply(susParameters->sus11orientationMatrix[0], susVecSensor[11],
|
||||
susVecBody[11], 3, 3, 1);
|
||||
}
|
||||
|
||||
double susMeanValue[3] = {0, 0, 0};
|
||||
for (uint8_t i = 0; i < 12; i++) {
|
||||
if (validIds[i]) {
|
||||
susMeanValue[0] += susVecBody[0][i];
|
||||
susMeanValue[1] += susVecBody[1][i];
|
||||
susMeanValue[2] += susVecBody[2][i];
|
||||
}
|
||||
susMeanValue[0] += susVecBody[i][0];
|
||||
susMeanValue[1] += susVecBody[i][1];
|
||||
susMeanValue[2] += susVecBody[i][2];
|
||||
}
|
||||
double susVecTot[3] = {0.0, 0.0, 0.0};
|
||||
VectorOperations<double>::normalize(susMeanValue, susVecTot, 3);
|
||||
|
@ -406,29 +373,29 @@ void SensorProcessing::processSus(
|
|||
{
|
||||
PoolReadGuard pg(susDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(susDataProcessed->sus0vec.value, sus0VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus0vec.value, susVecBody[0], 3 * sizeof(float));
|
||||
susDataProcessed->sus0vec.setValid(sus0valid);
|
||||
std::memcpy(susDataProcessed->sus1vec.value, sus1VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus1vec.value, susVecBody[1], 3 * sizeof(float));
|
||||
susDataProcessed->sus1vec.setValid(sus1valid);
|
||||
std::memcpy(susDataProcessed->sus2vec.value, sus2VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus2vec.value, susVecBody[2], 3 * sizeof(float));
|
||||
susDataProcessed->sus2vec.setValid(sus2valid);
|
||||
std::memcpy(susDataProcessed->sus3vec.value, sus3VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus3vec.value, susVecBody[3], 3 * sizeof(float));
|
||||
susDataProcessed->sus3vec.setValid(sus3valid);
|
||||
std::memcpy(susDataProcessed->sus4vec.value, sus4VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus4vec.value, susVecBody[4], 3 * sizeof(float));
|
||||
susDataProcessed->sus4vec.setValid(sus4valid);
|
||||
std::memcpy(susDataProcessed->sus5vec.value, sus5VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus5vec.value, susVecBody[5], 3 * sizeof(float));
|
||||
susDataProcessed->sus5vec.setValid(sus5valid);
|
||||
std::memcpy(susDataProcessed->sus6vec.value, sus6VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus6vec.value, susVecBody[6], 3 * sizeof(float));
|
||||
susDataProcessed->sus6vec.setValid(sus6valid);
|
||||
std::memcpy(susDataProcessed->sus7vec.value, sus7VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus7vec.value, susVecBody[7], 3 * sizeof(float));
|
||||
susDataProcessed->sus7vec.setValid(sus7valid);
|
||||
std::memcpy(susDataProcessed->sus8vec.value, sus8VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus8vec.value, susVecBody[8], 3 * sizeof(float));
|
||||
susDataProcessed->sus8vec.setValid(sus8valid);
|
||||
std::memcpy(susDataProcessed->sus9vec.value, sus9VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus9vec.value, susVecBody[9], 3 * sizeof(float));
|
||||
susDataProcessed->sus9vec.setValid(sus9valid);
|
||||
std::memcpy(susDataProcessed->sus10vec.value, sus10VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus10vec.value, susVecBody[10], 3 * sizeof(float));
|
||||
susDataProcessed->sus10vec.setValid(sus10valid);
|
||||
std::memcpy(susDataProcessed->sus11vec.value, sus11VecBody, 3 * sizeof(float));
|
||||
std::memcpy(susDataProcessed->sus11vec.value, susVecBody[11], 3 * sizeof(float));
|
||||
susDataProcessed->sus11vec.setValid(sus11valid);
|
||||
std::memcpy(susDataProcessed->susVecTot.value, susVecTot, 3 * sizeof(double));
|
||||
susDataProcessed->susVecTot.setValid(true);
|
||||
|
|
|
@ -1,121 +1,64 @@
|
|||
#include "SusConverter.h"
|
||||
|
||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||
#include <fsfw/datapoollocal/LocalPoolVector.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool SusConverter::checkSunSensorData(const uint16_t susChannel[6]) {
|
||||
if (susChannel[0] <= susChannelValueCheckLow || susChannel[0] > susChannelValueCheckHigh ||
|
||||
uint64_t SusConverter::checkSunSensorData(const uint16_t susChannel[6]) {
|
||||
if (susChannel[0] <= SUS_CHANNEL_VALUE_LOW || susChannel[0] > SUS_CHANNEL_VALUE_HIGH ||
|
||||
susChannel[0] > susChannel[GNDREF]) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if (susChannel[1] <= susChannelValueCheckLow || susChannel[1] > susChannelValueCheckHigh ||
|
||||
if (susChannel[1] <= SUS_CHANNEL_VALUE_LOW || susChannel[1] > SUS_CHANNEL_VALUE_HIGH ||
|
||||
susChannel[1] > susChannel[GNDREF]) {
|
||||
return false;
|
||||
return 0;
|
||||
};
|
||||
if (susChannel[2] <= susChannelValueCheckLow || susChannel[2] > susChannelValueCheckHigh ||
|
||||
if (susChannel[2] <= SUS_CHANNEL_VALUE_LOW || susChannel[2] > SUS_CHANNEL_VALUE_HIGH ||
|
||||
susChannel[2] > susChannel[GNDREF]) {
|
||||
return false;
|
||||
return 0;
|
||||
};
|
||||
if (susChannel[3] <= susChannelValueCheckLow || susChannel[3] > susChannelValueCheckHigh ||
|
||||
if (susChannel[3] <= SUS_CHANNEL_VALUE_LOW || susChannel[3] > SUS_CHANNEL_VALUE_HIGH ||
|
||||
susChannel[3] > susChannel[GNDREF]) {
|
||||
return false;
|
||||
return 0;
|
||||
};
|
||||
|
||||
susChannelValueSum =
|
||||
uint64_t susChannelValueSum =
|
||||
4 * susChannel[GNDREF] - (susChannel[0] + susChannel[1] + susChannel[2] + susChannel[3]);
|
||||
if ((susChannelValueSum < susChannelValueSumHigh) &&
|
||||
(susChannelValueSum > susChannelValueSumLow)) {
|
||||
return false;
|
||||
if (susChannelValueSum < SUS_ALBEDO_CHECK) {
|
||||
return 0;
|
||||
};
|
||||
return true;
|
||||
return susChannelValueSum;
|
||||
}
|
||||
|
||||
void SusConverter::calcAngle(const uint16_t susChannel[6]) {
|
||||
float xout, yout;
|
||||
float s = 0.03; // s=[mm] gap between diodes
|
||||
uint8_t d = 5; // d=[mm] edge length of the quadratic aperture
|
||||
uint8_t h = 1; // h=[mm] distance between diodes and aperture
|
||||
int ch0, ch1, ch2, ch3;
|
||||
bool SusConverter::checkValidity(bool* susValid, const uint64_t brightness[12],
|
||||
const float threshold) {
|
||||
uint8_t maxBrightness = 0;
|
||||
VectorOperations<uint64_t>::maxValue(brightness, 12, &maxBrightness);
|
||||
if (brightness[maxBrightness] == 0) {
|
||||
return true;
|
||||
}
|
||||
for (uint8_t idx = 0; idx < 12; idx++) {
|
||||
if ((idx != maxBrightness) and (brightness[idx] < threshold * brightness[maxBrightness])) {
|
||||
susValid[idx] = false;
|
||||
continue;
|
||||
}
|
||||
susValid[idx] = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SusConverter::calculateSunVector(float* sunVectorSensorFrame, const uint16_t susChannel[6]) {
|
||||
// Substract measurement values from GNDREF zero current threshold
|
||||
ch0 = susChannel[GNDREF] - susChannel[0];
|
||||
ch1 = susChannel[GNDREF] - susChannel[1];
|
||||
ch2 = susChannel[GNDREF] - susChannel[2];
|
||||
ch3 = susChannel[GNDREF] - susChannel[3];
|
||||
float ch0 = susChannel[GNDREF] - susChannel[0];
|
||||
float ch1 = susChannel[GNDREF] - susChannel[1];
|
||||
float ch2 = susChannel[GNDREF] - susChannel[2];
|
||||
float ch3 = susChannel[GNDREF] - susChannel[3];
|
||||
|
||||
// Calculation of x and y
|
||||
xout = ((d - s) / 2) * (ch2 - ch3 - ch0 + ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
|
||||
yout = ((d - s) / 2) * (ch2 + ch3 - ch0 - ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
|
||||
float xout = ((D - S) / 2) * (ch2 - ch3 - ch0 + ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
|
||||
float yout = ((D - S) / 2) * (ch2 + ch3 - ch0 - ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
|
||||
|
||||
// Calculation of the angles
|
||||
alphaBetaRaw[0] = atan2(xout, h) * (180 / M_PI); //[°]
|
||||
alphaBetaRaw[1] = atan2(yout, h) * (180 / M_PI); //[°]
|
||||
}
|
||||
|
||||
void SusConverter::calibration(const float coeffAlpha[9][10], const float coeffBeta[9][10]) {
|
||||
uint8_t index, k, l;
|
||||
|
||||
// while loop iterates above all calibration cells to use the different calibration functions in
|
||||
// each cell
|
||||
k = 0;
|
||||
while (k < 3) {
|
||||
k++;
|
||||
l = 0;
|
||||
while (l < 3) {
|
||||
l++;
|
||||
// if-condition to check in which cell the data point has to be
|
||||
if ((alphaBetaRaw[0] > ((completeCellWidth * ((k - 1) / 3.)) - halfCellWidth) &&
|
||||
alphaBetaRaw[0] < ((completeCellWidth * (k / 3.)) - halfCellWidth)) &&
|
||||
(alphaBetaRaw[1] > ((completeCellWidth * ((l - 1) / 3.)) - halfCellWidth) &&
|
||||
alphaBetaRaw[1] < ((completeCellWidth * (l / 3.)) - halfCellWidth))) {
|
||||
index = (3 * (k - 1) + l) - 1; // calculate the index of the datapoint for the right cell
|
||||
alphaBetaCalibrated[0] =
|
||||
coeffAlpha[index][0] + coeffAlpha[index][1] * alphaBetaRaw[0] +
|
||||
coeffAlpha[index][2] * alphaBetaRaw[1] +
|
||||
coeffAlpha[index][3] * alphaBetaRaw[0] * alphaBetaRaw[0] +
|
||||
coeffAlpha[index][4] * alphaBetaRaw[0] * alphaBetaRaw[1] +
|
||||
coeffAlpha[index][5] * alphaBetaRaw[1] * alphaBetaRaw[1] +
|
||||
coeffAlpha[index][6] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[0] +
|
||||
coeffAlpha[index][7] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[1] +
|
||||
coeffAlpha[index][8] * alphaBetaRaw[0] * alphaBetaRaw[1] * alphaBetaRaw[1] +
|
||||
coeffAlpha[index][9] * alphaBetaRaw[1] * alphaBetaRaw[1] * alphaBetaRaw[1]; //[°]
|
||||
alphaBetaCalibrated[1] =
|
||||
coeffBeta[index][0] + coeffBeta[index][1] * alphaBetaRaw[0] +
|
||||
coeffBeta[index][2] * alphaBetaRaw[1] +
|
||||
coeffBeta[index][3] * alphaBetaRaw[0] * alphaBetaRaw[0] +
|
||||
coeffBeta[index][4] * alphaBetaRaw[0] * alphaBetaRaw[1] +
|
||||
coeffBeta[index][5] * alphaBetaRaw[1] * alphaBetaRaw[1] +
|
||||
coeffBeta[index][6] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[0] +
|
||||
coeffBeta[index][7] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[1] +
|
||||
coeffBeta[index][8] * alphaBetaRaw[0] * alphaBetaRaw[1] * alphaBetaRaw[1] +
|
||||
coeffBeta[index][9] * alphaBetaRaw[1] * alphaBetaRaw[1] * alphaBetaRaw[1]; //[°]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float* SusConverter::calculateSunVector() {
|
||||
// Calculate the normalized Sun Vector
|
||||
sunVectorSensorFrame[0] = -(tan(alphaBetaCalibrated[0] * (M_PI / 180)) /
|
||||
(sqrt((powf(tan(alphaBetaCalibrated[0] * (M_PI / 180)), 2)) +
|
||||
powf(tan((alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1))));
|
||||
sunVectorSensorFrame[1] = -(tan(alphaBetaCalibrated[1] * (M_PI / 180)) /
|
||||
(sqrt(powf((tan(alphaBetaCalibrated[0] * (M_PI / 180))), 2) +
|
||||
powf(tan((alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1))));
|
||||
sunVectorSensorFrame[2] =
|
||||
-(-1 / (sqrt(powf((tan(alphaBetaCalibrated[0] * (M_PI / 180))), 2) +
|
||||
powf((tan(alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1))));
|
||||
|
||||
return sunVectorSensorFrame;
|
||||
}
|
||||
|
||||
float* SusConverter::getSunVectorSensorFrame(const uint16_t susChannel[6],
|
||||
const float coeffAlpha[9][10],
|
||||
const float coeffBeta[9][10]) {
|
||||
calcAngle(susChannel);
|
||||
calibration(coeffAlpha, coeffBeta);
|
||||
return calculateSunVector();
|
||||
sunVectorSensorFrame[0] = -xout;
|
||||
sunVectorSensorFrame[1] = -yout;
|
||||
sunVectorSensorFrame[2] = H;
|
||||
VectorOperations<float>::normalize(sunVectorSensorFrame, sunVectorSensorFrame, 3);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
#ifndef MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
|
||||
#define MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
|
||||
|
||||
#include <fsfw/datapoollocal/LocalPoolVector.h>
|
||||
#include <stdint.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
|
||||
#include "AcsParameters.h"
|
||||
|
||||
|
@ -10,41 +6,26 @@ class SusConverter {
|
|||
public:
|
||||
SusConverter() {}
|
||||
|
||||
bool checkSunSensorData(const uint16_t susChannel[6]);
|
||||
|
||||
void calcAngle(const uint16_t susChannel[6]);
|
||||
void calibration(const float coeffAlpha[9][10], const float coeffBeta[9][10]);
|
||||
float* calculateSunVector();
|
||||
|
||||
float* getSunVectorSensorFrame(const uint16_t susChannel[6], const float coeffAlpha[9][10],
|
||||
const float coeffBeta[9][10]);
|
||||
uint64_t checkSunSensorData(const uint16_t susChannel[6]);
|
||||
bool checkValidity(bool* susValid, const uint64_t brightness[12], const float threshold);
|
||||
void calculateSunVector(float* sunVectorSensorFrame, const uint16_t susChannel[6]);
|
||||
|
||||
private:
|
||||
float alphaBetaRaw[2]; //[°]
|
||||
float alphaBetaCalibrated[2]; //[°]
|
||||
float sunVectorSensorFrame[3]; //[-]
|
||||
|
||||
bool validFlag[12] = {returnvalue::OK, returnvalue::OK, returnvalue::OK, returnvalue::OK,
|
||||
returnvalue::OK, returnvalue::OK, returnvalue::OK, returnvalue::OK,
|
||||
returnvalue::OK, returnvalue::OK, returnvalue::OK, returnvalue::OK};
|
||||
|
||||
static const uint8_t GNDREF = 4;
|
||||
uint16_t susChannelValueCheckHigh =
|
||||
4096; //=2^12[Bit]high borderline for the channel values of one sun sensor for validity Check
|
||||
uint8_t susChannelValueCheckLow =
|
||||
0; //[Bit]low borderline for the channel values of one sun sensor for validity Check
|
||||
uint16_t susChannelValueSumHigh =
|
||||
100; // 4096[Bit]high borderline for check if the sun sensor is illuminated by the sun or by
|
||||
// the reflection of sunlight from the moon/earth
|
||||
uint8_t susChannelValueSumLow =
|
||||
0; //[Bit]low borderline for check if the sun sensor is illuminated
|
||||
// by the sun or by the reflection of sunlight from the moon/earth
|
||||
uint8_t completeCellWidth = 140,
|
||||
halfCellWidth = 70; //[°] Width of the calibration cells --> necessary for checking in
|
||||
// which cell a data point should be
|
||||
uint16_t susChannelValueSum = 0;
|
||||
// =2^12[Bit]high borderline for the channel values of one sun sensor for validity Check
|
||||
static constexpr uint16_t SUS_CHANNEL_VALUE_HIGH = 4096;
|
||||
// [Bit]low borderline for the channel values of one sun sensor for validity Check
|
||||
static constexpr uint8_t SUS_CHANNEL_VALUE_LOW = 0;
|
||||
// 4096[Bit]high borderline for check if the sun sensor is illuminated by the sun or by the
|
||||
// reflection of sunlight from the moon/earth
|
||||
static constexpr uint16_t SUS_ALBEDO_CHECK = 1000;
|
||||
// [Bit]low borderline for check if the sun sensor is illuminated by the sun or by the reflection
|
||||
// of sunlight from the moon/earth
|
||||
static constexpr uint8_t SUS_CHANNEL_SUM_LOW = 0;
|
||||
|
||||
static constexpr float S = 0.03; // S=[mm] gap between diodes
|
||||
static constexpr float D = 5; // D=[mm] edge length of the quadratic aperture
|
||||
static constexpr float H = 1; // H=[mm] distance between diodes and aperture
|
||||
|
||||
AcsParameters acsParameters;
|
||||
};
|
||||
|
||||
#endif /* MISSION_CONTROLLER_ACS_SUSCONVERTER_H_ */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/arrayprinter.h>
|
||||
#include <mission/power/BpxBatteryHandler.h>
|
||||
|
||||
BpxBatteryHandler::BpxBatteryHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
|
||||
|
@ -51,6 +52,9 @@ void BpxBatteryHandler::fillCommandAndReplyMap() {
|
|||
insertInCommandAndReplyMap(bpxBat::RESET_COUNTERS, 1, nullptr, EMPTY_REPLY_LEN);
|
||||
insertInCommandAndReplyMap(bpxBat::CONFIG_CMD, 1, nullptr, EMPTY_REPLY_LEN);
|
||||
insertInCommandAndReplyMap(bpxBat::CONFIG_GET, 1, &cfgSet, CONFIG_GET_REPLY_LEN);
|
||||
insertInCommandAndReplyMap(bpxBat::CONFIG_SET, 1, nullptr, EMPTY_REPLY_LEN);
|
||||
insertInCommandAndReplyMap(bpxBat::MAN_HEAT_ON, 1, nullptr, MAN_HEAT_REPLY_LEN);
|
||||
insertInCommandAndReplyMap(bpxBat::MAN_HEAT_OFF, 1, nullptr, MAN_HEAT_REPLY_LEN);
|
||||
}
|
||||
|
||||
ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||
|
@ -155,7 +159,7 @@ ReturnValue_t BpxBatteryHandler::scanForReply(const uint8_t* start, size_t remai
|
|||
case (bpxBat::PING):
|
||||
case (bpxBat::MAN_HEAT_ON):
|
||||
case (bpxBat::MAN_HEAT_OFF): {
|
||||
if (remainingSize != PING_REPLY_LEN) {
|
||||
if (remainingSize != MAN_HEAT_REPLY_LEN) {
|
||||
return DeviceHandlerIF::LENGTH_MISSMATCH;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -48,6 +48,7 @@ static constexpr uint32_t CFG_SET_ID = CONFIG_GET;
|
|||
static constexpr size_t GET_HK_REPLY_LEN = 23;
|
||||
static constexpr size_t PING_REPLY_LEN = 3;
|
||||
static constexpr size_t EMPTY_REPLY_LEN = 2;
|
||||
static constexpr size_t MAN_HEAT_REPLY_LEN = 3;
|
||||
static constexpr size_t CONFIG_GET_REPLY_LEN = 5;
|
||||
|
||||
static constexpr uint8_t PORT_PING = 1;
|
||||
|
@ -219,6 +220,7 @@ class BpxBatteryCfg : public StaticLocalDataSet<bpxBat::CFG_ENTRIES> {
|
|||
if (size < 3) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
|
||||
battheatermode.value = data[0];
|
||||
battheaterLow.value = data[1];
|
||||
battheaterHigh.value = data[2];
|
||||
|
|
|
@ -183,11 +183,11 @@ void DualLaneAssemblyBase::handleModeTransitionFailed(ReturnValue_t result) {
|
|||
// transition to dual mode.
|
||||
if (not tryingOtherSide) {
|
||||
triggerEvent(CANT_KEEP_MODE, mode, submode);
|
||||
startTransition(mode, nextSubmode);
|
||||
startTransition(targetMode, nextSubmode);
|
||||
tryingOtherSide = true;
|
||||
} else {
|
||||
triggerEvent(transitionOtherSideFailedEvent, mode, targetSubmode);
|
||||
startTransition(mode, Submodes::DUAL_MODE);
|
||||
triggerEvent(transitionOtherSideFailedEvent, targetMode, targetSubmode);
|
||||
startTransition(targetMode, Submodes::DUAL_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,8 @@ bool DualLaneAssemblyBase::checkAndHandleRecovery() {
|
|||
opCode = pwrStateMachine.fsm();
|
||||
if (opCode == OpCodes::TO_OFF_DONE or opCode == OpCodes::TIMEOUT_OCCURED) {
|
||||
customRecoveryStates = RecoveryCustomStates::POWER_SWITCHING_ON;
|
||||
pwrStateMachine.start(targetMode, targetSubmode);
|
||||
// Command power back on in any case.
|
||||
pwrStateMachine.start(HasModesIF::MODE_ON, targetSubmode);
|
||||
}
|
||||
}
|
||||
if (customRecoveryStates == POWER_SWITCHING_ON) {
|
||||
|
|
|
@ -268,6 +268,8 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
|
|||
triggerEvent(GPIO_PULL_HIGH_FAILED, result);
|
||||
} else {
|
||||
triggerEvent(HEATER_WENT_ON, heaterIdx, 0);
|
||||
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
||||
MODE_ON, 0);
|
||||
{
|
||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
heater.switchState = ON;
|
||||
|
@ -324,6 +326,8 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
|
|||
heater.switchState = OFF;
|
||||
}
|
||||
triggerEvent(HEATER_WENT_OFF, heaterIdx, 0);
|
||||
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
||||
MODE_OFF, 0);
|
||||
// When all switches are off, also main line switch will be turned off
|
||||
if (allSwitchesOff()) {
|
||||
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
|
||||
|
|
|
@ -86,8 +86,11 @@ ReturnValue_t Tmp1075Handler::scanForReply(const uint8_t *start, size_t remainin
|
|||
ReturnValue_t Tmp1075Handler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
|
||||
switch (id) {
|
||||
case TMP1075::GET_TEMP: {
|
||||
int16_t tempValueRaw = 0;
|
||||
tempValueRaw = packet[0] << 4 | packet[1] >> 4;
|
||||
// Convert 12 bit MSB first raw temperature to 16 bit first.
|
||||
int16_t tempValueRaw = static_cast<uint16_t>((packet[0] << 8) | packet[1]) >> 4;
|
||||
// Sign extension to 16 bits: If the sign bit is set, fill up with ones on the left.
|
||||
tempValueRaw = (packet[0] & 0x80) ? (tempValueRaw | 0xF000) : tempValueRaw;
|
||||
// 0.0625 is the sensor sensitivity.
|
||||
float tempValue = ((static_cast<float>(tempValueRaw)) * 0.0625);
|
||||
#if OBSW_DEBUG_TMP1075 == 1
|
||||
sif::info << "Tmp1075 with object id: 0x" << std::hex << getObjectId()
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
|
||||
namespace heater {
|
||||
enum Switch : uint8_t {
|
||||
HEATER_0_OBC_BRD,
|
||||
HEATER_1_PLOC_PROC_BRD,
|
||||
HEATER_0_PLOC_PROC_BRD,
|
||||
HEATER_1_PCDU_PDU,
|
||||
HEATER_2_ACS_BRD,
|
||||
HEATER_3_PCDU_PDU,
|
||||
HEATER_3_OBC_BRD,
|
||||
HEATER_4_CAMERA,
|
||||
HEATER_5_STR,
|
||||
HEATER_6_DRO,
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
# custom cross-compiler and sysroot path setups
|
||||
|
||||
# Adapt the following two entries to your need
|
||||
CROSS_COMPILE_BIN_PATH="/opt/q7s-gcc/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin"
|
||||
export CROSS_COMPILE_BIN_PATH="/opt/q7s-gcc/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin"
|
||||
export ZYNQ_7020_SYSROOT="/opt/xiphos/sdk/ark/sysroots/cortexa9hf-neon-xiphos-linux-gnueabi"
|
||||
|
||||
export PATH=$PATH:${CROSS_COMPILE_BIN_PATH}
|
||||
export PATH=${CROSS_COMPILE_BIN_PATH}:$PATH
|
||||
export CROSS_COMPILE="arm-linux-gnueabihf"
|
||||
export EIVE_Q7S_EM=1
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
# custom cross-compiler and sysroot path setups
|
||||
|
||||
# Adapt the following two entries to your need
|
||||
CROSS_COMPILE_BIN_PATH="/opt/q7s-gcc/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin"
|
||||
export CROSS_COMPILE_BIN_PATH="/opt/q7s-gcc/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin"
|
||||
export ZYNQ_7020_SYSROOT="/opt/xiphos/sdk/ark/sysroots/cortexa9hf-neon-xiphos-linux-gnueabi"
|
||||
|
||||
export PATH=$PATH:${CROSS_COMPILE_BIN_PATH}
|
||||
export PATH=${CROSS_COMPILE_BIN_PATH}:$PATH
|
||||
export CROSS_COMPILE="arm-linux-gnueabihf"
|
||||
# export EIVE_Q7S_EM=1
|
||||
|
||||
|
|
|
@ -7,7 +7,9 @@ OBSW Release Checklist
|
|||
2. Re-run the generators with `generators/gen.py all`
|
||||
3. Re-run the auto-formatters with the `scripts/auto-formatter.sh` script
|
||||
4. Verify that the Q7S, Q7S EM and Host build are working
|
||||
5. Wait for CI/CD results
|
||||
5. Update `CHANGELOG.md`: Add new `unreleased` section, convert old unreleased section to
|
||||
header containing version number and release date.
|
||||
6. Wait for CI/CD results
|
||||
|
||||
# Post-Release
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user