diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..952a034 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,7 @@ +target_sources(${TARGET_NAME} + PRIVATE + TestTask.cpp + FsfwReaderTask.cpp + FsfwExampleTask.cpp + MutexExample.cpp +) \ No newline at end of file diff --git a/test/FsfwExampleTask.cpp b/test/FsfwExampleTask.cpp new file mode 100644 index 0000000..7fe35ac --- /dev/null +++ b/test/FsfwExampleTask.cpp @@ -0,0 +1,264 @@ +#include "FsfwExampleTask.h" +#include "OBSWConfig.h" +#include "commonSystemObjects.h" +#include "objects/systemObjectList.h" + +#include +#include +#include +#include +#include + + +FsfwExampleTask::FsfwExampleTask(object_id_t objectId): SystemObject(objectId), + poolManager(this, nullptr), demoSet(this), + monitor(objectId, MONITOR_ID, gp_id_t(objectId, FsfwDemoSet::VARIABLE_LIMIT), 30, 10) +{ + commandQueue = QueueFactory::instance()->createMessageQueue(10, + CommandMessage::MAX_MESSAGE_SIZE); +} + +FsfwExampleTask::~FsfwExampleTask() { +} + +ReturnValue_t FsfwExampleTask::performOperation(uint8_t operationCode) { + if(operationCode == OpCodes::DELAY_SHORT){ + TaskFactory::delayTask(5); + } + + // TODO: Move this to new test controller? + ReturnValue_t result = performMonitoringDemo(); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + if (operationCode == OpCodes::SEND_RAND_NUM) { + result = performSendOperation(); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + + + if (operationCode == OpCodes::RECEIVE_RAND_NUM) { + result = performReceiveOperation(); + + } + + return 0; +} + +object_id_t FsfwExampleTask::getNextRecipient() { + switch(this->getObjectId()) { + case(objects::TEST_DUMMY_1): { + return objects::TEST_DUMMY_2; + } + case(objects::TEST_DUMMY_2): { + return objects::TEST_DUMMY_3; + } + case(objects::TEST_DUMMY_3): { + return objects::TEST_DUMMY_1; + } + default: + return objects::TEST_DUMMY_1; + } +} + +object_id_t FsfwExampleTask::getSender() { + switch(this->getObjectId()) { + case(objects::TEST_DUMMY_1): { + return objects::TEST_DUMMY_3; + } + case(objects::TEST_DUMMY_2): { + return objects::TEST_DUMMY_1; + } + case(objects::TEST_DUMMY_3): { + return objects::TEST_DUMMY_2; + } + default: + return objects::TEST_DUMMY_1; + } +} + + +ReturnValue_t FsfwExampleTask::initialize() { + // Get the dataset of the sender. Will be cached for later checks. + object_id_t sender = getSender(); + HasLocalDataPoolIF* senderIF = ObjectManager::instance()->get(sender); + if(senderIF == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "FsfwDemoTask::initialize: Sender object invalid!" << std::endl; +#else + sif::printError("FsfwDemoTask::initialize: Sender object invalid!\n"); +#endif + return HasReturnvaluesIF::RETURN_FAILED; + } + + // we need a private copy of the previous dataset.. or we use the shared dataset. + senderSet = new FsfwDemoSet(senderIF); + if(senderSet == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "FsfwDemoTask::initialize: Sender dataset invalid!" << std::endl; +#else + sif::printError("FsfwDemoTask::initialize: Sender dataset invalid!\n"); +#endif + return HasReturnvaluesIF::RETURN_FAILED; + } + return poolManager.initialize(commandQueue); +} + +ReturnValue_t FsfwExampleTask::initializeAfterTaskCreation() { + return poolManager.initializeAfterTaskCreation(); +} + +object_id_t FsfwExampleTask::getObjectId() const { + return SystemObject::getObjectId(); +} + +MessageQueueId_t FsfwExampleTask::getMessageQueueId(){ + return commandQueue->getId(); +} + +void FsfwExampleTask::setTaskIF(PeriodicTaskIF* task){ + this->task = task; +} + +LocalPoolDataSetBase* FsfwExampleTask::getDataSetHandle(sid_t sid) { + return &demoSet; +} + +uint32_t FsfwExampleTask::getPeriodicOperationFrequency() const { + return task->getPeriodMs(); +} + +ReturnValue_t FsfwExampleTask::initializeLocalDataPool( + localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE, new PoolEntry({0})); + localDataPoolMap.emplace(FsfwDemoSet::PoolIds::VARIABLE_LIMIT, new PoolEntry({0})); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FsfwExampleTask::performMonitoringDemo() { + ReturnValue_t result = demoSet.variableLimit.read( + MutexIF::TimeoutType::WAITING, 20); + if(result != HasReturnvaluesIF::RETURN_OK) { + /* Configuration error */ +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "DummyObject::performOperation: Could not read variableLimit!" << std::endl; +#else + sif::printError("DummyObject::performOperation: Could not read variableLimit!\n"); +#endif + return result; + } + if(this->getObjectId() == objects::TEST_DUMMY_5){ + if(demoSet.variableLimit.value > 20){ + demoSet.variableLimit.value = 0; + } + demoSet.variableLimit.value++; + demoSet.variableLimit.commit(20); + monitor.check(); + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FsfwExampleTask::performSendOperation() { + object_id_t nextRecipient = getNextRecipient(); + FsfwExampleTask* target = ObjectManager::instance()->get(nextRecipient); + if (target == nullptr) { + /* Configuration error */ +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "DummyObject::performOperation: Next recipient does not exist!" << std::endl; +#else + sif::printError("DummyObject::performOperation: Next recipient does not exist!\n"); +#endif + return HasReturnvaluesIF::RETURN_FAILED; + } + + + uint32_t randomNumber = rand() % 100; + CommandMessage message; + message.setParameter(randomNumber); + message.setParameter2(this->getMessageQueueId()); + + /* Send message using own message queue */ + ReturnValue_t result = commandQueue->sendMessage(target->getMessageQueueId(), &message); + if (result != HasReturnvaluesIF::RETURN_OK + && result != MessageQueueIF::FULL) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << + std::endl; +#else + sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result); +#endif + } + + /* Send message without via MessageQueueSenderIF */ + result = MessageQueueSenderIF::sendMessage(target->getMessageQueueId(), &message, + commandQueue->getId()); + if (result != HasReturnvaluesIF::RETURN_OK + && result != MessageQueueIF::FULL) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "FsfwDemoTask::performSendOperation: Send failed with " << result << std::endl; +#else + sif::printError("FsfwDemoTask::performSendOperation: Send failed with %hu\n", result); +#endif + } + + demoSet.variableWrite.value = randomNumber; + result = demoSet.variableWrite.commit(20); + + return result; +} + +ReturnValue_t FsfwExampleTask::performReceiveOperation() { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + while (result != MessageQueueIF::EMPTY) { + CommandMessage receivedMessage; + result = commandQueue->receiveMessage(&receivedMessage); + if (result != HasReturnvaluesIF::RETURN_OK + && result != MessageQueueIF::EMPTY) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::debug << "Receive failed with " << result << std::endl; +#endif + break; + } + if (result != MessageQueueIF::EMPTY) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 +#if OBSW_VERBOSE_LEVEL >= 2 + sif::debug << "Message Received by " << getObjectId() << " from Queue " << + receivedMessage.getSender() << " ObjectId " << receivedMessage.getParameter() << + " Queue " << receivedMessage.getParameter2() << std::endl; +#endif +#endif + + if(senderSet == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + result = senderSet->variableRead.read(MutexIF::TimeoutType::WAITING, + 20); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + if(senderSet->variableRead.value != receivedMessage.getParameter()) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "FsfwDemoTask::performReceiveOperation: Variable " << std::hex << + "0x" << senderSet->variableRead.getDataPoolId() << std::dec << + " has wrong value." << std::endl; + sif::error << "Value: " << demoSet.variableRead.value << ", expected: " << + receivedMessage.getParameter() << std::endl; +#endif + } + + } + } + return result; +} + +MessageQueueId_t FsfwExampleTask::getCommandQueue() const { + return commandQueue->getId(); +} + +LocalDataPoolManager* FsfwExampleTask::getHkManagerHandle() { + return &poolManager; +} diff --git a/test/FsfwExampleTask.h b/test/FsfwExampleTask.h new file mode 100644 index 0000000..005af8d --- /dev/null +++ b/test/FsfwExampleTask.h @@ -0,0 +1,116 @@ +#ifndef MISSION_DEMO_FSFWDEMOTASK_H_ +#define MISSION_DEMO_FSFWDEMOTASK_H_ + +#include "testdefinitions/demoDefinitions.h" + +#include +#include +#include +#include +#include +#include + +class PeriodicTaskIF; + + +/** + * @brief This demo set shows the local data pool functionality and fixed + * timeslot capabilities of the FSFW. + * + * @details + * There will be multiple demo objects. Each demo object will generate a random + * number and send that number via message queues to the next demo object + * (e.g. DUMMY_1 sends the number to DUMMY_2 etc.). The receiving object + * will check the received value against the sent value by extracting the sent + * value directly from the sender via the local data pool interface. + * If the timing is set up correctly, the values will always be the same. + */ +class FsfwExampleTask: + public ExecutableObjectIF, + public SystemObject, + public HasLocalDataPoolIF { +public: + enum OpCodes { + SEND_RAND_NUM, + RECEIVE_RAND_NUM, + DELAY_SHORT + }; + + static constexpr uint8_t MONITOR_ID = 2; + + /** + * @brief Simple constructor, only expects object ID. + * @param objectId + */ + FsfwExampleTask(object_id_t objectId); + + virtual ~FsfwExampleTask(); + + /** + * @brief The performOperation method is executed in a task. + * @details There are no restrictions for calls within this method, so any + * other member of the class can be used. + * @return Currently, the return value is ignored. + */ + virtual ReturnValue_t performOperation(uint8_t operationCode = 0); + + /** + * @brief This function will be called by the global object manager + * @details + * This function will always be called before any tasks are started. + * It can also be used to return error codes in the software initialization + * process cleanly. + * @return + */ + virtual ReturnValue_t initialize() override; + + /** + * @brief This function will be called by the OSAL task handlers + * @details + * This function will be called before the first #performOperation + * call after the tasks have been started. It can be used if some + * initialization process requires task specific properties like + * periodic intervals (by using the PeriodicTaskIF* handle). + * @return + */ + virtual ReturnValue_t initializeAfterTaskCreation() override; + + /** + * This function will be called by the OSAL task handler. The + * task interface handle can be cached to access task specific properties. + * @param task + */ + void setTaskIF(PeriodicTaskIF* task) override; + + object_id_t getObjectId() const override; + + MessageQueueId_t getMessageQueueId(); + + +private: + LocalDataPoolManager poolManager; + FsfwDemoSet* senderSet = nullptr; + FsfwDemoSet demoSet; + AbsLimitMonitor monitor; + PeriodicTaskIF* task = nullptr; + MessageQueueIF* commandQueue = nullptr; + + /* HasLocalDatapoolIF overrides */ + MessageQueueId_t getCommandQueue() const override; + LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; + uint32_t getPeriodicOperationFrequency() const override; + virtual ReturnValue_t initializeLocalDataPool( + localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + virtual LocalDataPoolManager* getHkManagerHandle() override; + + object_id_t getNextRecipient(); + object_id_t getSender(); + + ReturnValue_t performMonitoringDemo(); + ReturnValue_t performSendOperation(); + ReturnValue_t performReceiveOperation(); + uint8_t execCounter = 0; +}; + +#endif /* MISSION_DEMO_FSFWDEMOTASK_H_ */ diff --git a/test/FsfwReaderTask.cpp b/test/FsfwReaderTask.cpp new file mode 100644 index 0000000..9a19090 --- /dev/null +++ b/test/FsfwReaderTask.cpp @@ -0,0 +1,55 @@ +#include "FsfwReaderTask.h" + +#include +#include +#include +#include + +#include + + +FsfwReaderTask::FsfwReaderTask(object_id_t objectId, bool enablePrintout): + SystemObject(objectId), printoutEnabled(enablePrintout), opDivider(10), + readSet(this->getObjectId(), + gp_id_t(objects::TEST_DUMMY_1, FsfwDemoSet::PoolIds::VARIABLE), + gp_id_t(objects::TEST_DUMMY_2, FsfwDemoSet::PoolIds::VARIABLE), + gp_id_t(objects::TEST_DUMMY_3, FsfwDemoSet::PoolIds::VARIABLE)) { + /* Special protection for set reading because each variable is read from a different pool */ + readSet.setReadCommitProtectionBehaviour(true); +} + +FsfwReaderTask::~FsfwReaderTask() { +} + +ReturnValue_t FsfwReaderTask::initializeAfterTaskCreation() { + /* Give other task some time to set up local data pools. */ + TaskFactory::delayTask(20); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FsfwReaderTask::performOperation(uint8_t operationCode) { + PoolReadGuard readHelper(&readSet); + + uint32_t variable1 = readSet.variable1.value; + uint32_t variable2 = readSet.variable2.value; + uint32_t variable3 = readSet.variable3.value; + +#if OBSW_VERBOSE_LEVEL >= 1 + if(opDivider.checkAndIncrement() and printoutEnabled) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "FsfwPeriodicTask::performOperation: Reading variables." << std::endl; + sif::info << "Variable read from demo object 1: " << variable1 << std::endl; + sif::info << "Variable read from demo object 2: " << variable2 << std::endl; + sif::info << "Variable read from demo object 3: " << variable3 << std::endl; +#else + sif::printInfo("FsfwPeriodicTask::performOperation: Reading variables.\n\r"); + sif::printInfo("Variable read from demo object 1: %d\n\r", variable1); + sif::printInfo("Variable read from demo object 2: %d\n\r", variable2); + sif::printInfo("Variable read from demo object 3: %d\n\r", variable3); +#endif + } +#else + if(variable1 and variable2 and variable3) {}; +#endif + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/test/FsfwReaderTask.h b/test/FsfwReaderTask.h new file mode 100644 index 0000000..7f987da --- /dev/null +++ b/test/FsfwReaderTask.h @@ -0,0 +1,24 @@ +#ifndef MISSION_DEMO_FSFWPERIODICTASK_H_ +#define MISSION_DEMO_FSFWPERIODICTASK_H_ + +#include "testdefinitions/demoDefinitions.h" + +#include +#include +#include + +class FsfwReaderTask: public ExecutableObjectIF, public SystemObject { +public: + FsfwReaderTask(object_id_t objectId, bool enablePrintout); + virtual ~FsfwReaderTask(); + + ReturnValue_t initializeAfterTaskCreation() override; + virtual ReturnValue_t performOperation(uint8_t operationCode = 0); + +private: + bool printoutEnabled = false; + PeriodicOperationDivider opDivider; + CompleteDemoReadSet readSet; +}; + +#endif /* MISSION_DEMO_FSFWPERIODICTASK_H_ */ diff --git a/test/MutexExample.cpp b/test/MutexExample.cpp new file mode 100644 index 0000000..06af15c --- /dev/null +++ b/test/MutexExample.cpp @@ -0,0 +1,47 @@ +#include "MutexExample.h" + +#include +#include + + +void MutexExample::example(){ + MutexIF* mutex = MutexFactory::instance()->createMutex(); + MutexIF* mutex2 = MutexFactory::instance()->createMutex(); + + ReturnValue_t result = mutex->lockMutex(MutexIF::TimeoutType::WAITING, + 2 * 60 * 1000); + if (result != HasReturnvaluesIF::RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "MutexExample::example: Lock Failed with " << result << std::endl; +#else + sif::printError("MutexExample::example: Lock Failed with %hu\n", result); +#endif + } + + result = mutex2->lockMutex(MutexIF::TimeoutType::BLOCKING); + if (result != HasReturnvaluesIF::RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "MutexExample::example: Lock Failed with " << result << std::endl; +#else + sif::printError("MutexExample::example: Lock Failed with %hu\n", result); +#endif + } + + result = mutex->unlockMutex(); + if (result != HasReturnvaluesIF::RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl; +#else + sif::printError("MutexExample::example: Unlock Failed with %hu\n", result); +#endif + } + + result = mutex2->unlockMutex(); + if (result != HasReturnvaluesIF::RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "MutexExample::example: Unlock Failed with " << result << std::endl; +#else + sif::printError("MutexExample::example: Unlock Failed with %hu\n", result); +#endif + } +} diff --git a/test/MutexExample.h b/test/MutexExample.h new file mode 100644 index 0000000..d10ef2f --- /dev/null +++ b/test/MutexExample.h @@ -0,0 +1,8 @@ +#ifndef MISSION_DEMO_MUTEXEXAMPLE_H_ +#define MISSION_DEMO_MUTEXEXAMPLE_H_ + +namespace MutexExample { + void example(); +}; + +#endif /* MISSION_DEMO_MUTEXEXAMPLE_H_ */ diff --git a/test/TestTask.cpp b/test/TestTask.cpp new file mode 100644 index 0000000..cb1a79d --- /dev/null +++ b/test/TestTask.cpp @@ -0,0 +1,77 @@ +#include "TestTask.h" + +#include +#include + +bool TestTask::oneShotAction = true; +MutexIF* TestTask::testLock = nullptr; + +TestTask::TestTask(object_id_t objectId, bool periodicPrintout): + SystemObject(objectId), testMode(testModes::A), + periodicPrinout(periodicPrintout) { + if(testLock == nullptr) { + testLock = MutexFactory::instance()->createMutex(); + } + IPCStore = ObjectManager::instance()->get(objects::IPC_STORE); +} + +TestTask::~TestTask() { +} + +ReturnValue_t TestTask::performOperation(uint8_t operationCode) { + ReturnValue_t result = RETURN_OK; + testLock->lockMutex(MutexIF::TimeoutType::WAITING, 20); + if(oneShotAction) { + // Add code here which should only be run once + performOneShotAction(); + oneShotAction = false; + } + testLock->unlockMutex(); + + // Add code here which should only be run once per performOperation + performPeriodicAction(); + + // Add code here which should only be run on alternating cycles. + if(testMode == testModes::A) { + performActionA(); + testMode = testModes::B; + } + else if(testMode == testModes::B) { + performActionB(); + testMode = testModes::A; + } + return result; +} + +ReturnValue_t TestTask::performOneShotAction() { + /* Everything here will only be performed once. */ + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t TestTask::performPeriodicAction() { + /* This is performed each task cycle */ + ReturnValue_t result = RETURN_OK; + + if(periodicPrinout) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "TestTask::performPeriodicAction: Hello World!" << std::endl; +#else + sif::printInfo("TestTask::performPeriodicAction: Hello World!\n"); +#endif + } + return result; +} + +ReturnValue_t TestTask::performActionA() { + /* This is performed each alternating task cycle */ + ReturnValue_t result = RETURN_OK; + return result; +} + +ReturnValue_t TestTask::performActionB() { + /* This is performed each alternating task cycle */ + ReturnValue_t result = RETURN_OK; + return result; +} + diff --git a/test/TestTask.h b/test/TestTask.h new file mode 100644 index 0000000..375c0d5 --- /dev/null +++ b/test/TestTask.h @@ -0,0 +1,50 @@ +#ifndef MISSION_DEMO_TESTTASK_H_ +#define MISSION_DEMO_TESTTASK_H_ + +#include +#include +#include + + +/** + * @brief Test class for general C++ testing and any other code which will not be part of the + * primary mission software. + * @details + * Should not be used for board specific tests. Instead, a derived board test class should be used. + */ +class TestTask : + public SystemObject, + public ExecutableObjectIF, + public HasReturnvaluesIF { +public: + TestTask(object_id_t objectId, bool periodicPrintout); + virtual ~TestTask(); + virtual ReturnValue_t performOperation(uint8_t operationCode = 0); + +protected: + virtual ReturnValue_t performOneShotAction(); + virtual ReturnValue_t performPeriodicAction(); + virtual ReturnValue_t performActionA(); + virtual ReturnValue_t performActionB(); + + enum testModes: uint8_t { + A, + B + }; + + testModes testMode; + bool periodicPrinout = false; + + bool testFlag = false; + uint8_t counter { 1 }; + uint8_t counterTrigger { 3 }; + + void performPusInjectorTest(); + void examplePacketTest(); +private: + static bool oneShotAction; + static MutexIF* testLock; + StorageManagerIF* IPCStore; +}; + +#endif /* TESTTASK_H_ */ diff --git a/test/testdefinitions/demoDefinitions.h b/test/testdefinitions/demoDefinitions.h new file mode 100644 index 0000000..711168f --- /dev/null +++ b/test/testdefinitions/demoDefinitions.h @@ -0,0 +1,63 @@ +#ifndef MISSION_DEMO_DEMODEFINITIONS_H_ +#define MISSION_DEMO_DEMODEFINITIONS_H_ + +#include +#include + +/** + * @brief This demo set showcases the local data pool functionality of the + * FSFW + * @details + * Each demo object will have an own instance of this set class, which contains + * pool variables (for read and write access respectively). + */ +class FsfwDemoSet: public StaticLocalDataSet<3> { +public: + + static constexpr uint32_t DEMO_SET_ID = 0; + + enum PoolIds { + VARIABLE, + VARIABLE_LIMIT + }; + + FsfwDemoSet(HasLocalDataPoolIF* hkOwner): + StaticLocalDataSet(hkOwner, DEMO_SET_ID) {} + + lp_var_t variableRead = lp_var_t(sid.objectId, + PoolIds::VARIABLE, this, pool_rwm_t::VAR_READ); + lp_var_t variableWrite = lp_var_t(sid.objectId, + PoolIds::VARIABLE, this, pool_rwm_t::VAR_WRITE); + lp_var_t variableLimit = lp_var_t(sid.objectId, + PoolIds::VARIABLE_LIMIT, this); +private: + +}; + +/** + * This set will enable object to read the dummy variables from the dataset + * above. An example application would be a consumer object like a controller + * which reads multiple sensor values at once. + */ +class CompleteDemoReadSet: public StaticLocalDataSet<3> { +public: + static constexpr uint32_t DEMO_SET_ID = 0; + + CompleteDemoReadSet(object_id_t owner, gp_id_t variable1, + gp_id_t variable2, gp_id_t variable3): + StaticLocalDataSet(sid_t(owner, DEMO_SET_ID)), + variable1(variable1, this, pool_rwm_t::VAR_READ), + variable2(variable2, this, pool_rwm_t::VAR_READ), + variable3(variable3, this, pool_rwm_t::VAR_READ) {} + + + lp_var_t variable1; + lp_var_t variable2; + lp_var_t variable3; +private: +}; + + + + +#endif /* MISSION_DEMO_DEMODEFINITIONS_H_ */