This is an old revision of the document!
Create a safety system
The safety system is implemented as a singleton. Its constructors are private, and you can get an instance by calling
SafetySystem& safetySys = SafetySystem::instance();
The central attribute of the safety system is its currentLevel. Of course, this level can be queried by everyone but only set by the safety system itself.
The most important function is its run method. This method is called periodically by a high priority thread. Here's how it works:
void SafetySystem::run() { // 1) Make local copy of currentLevel SafetyLevel* level = currentLevel; // 2) Read inputs for(auto ia : level->inputAction) { if(ia != nullptr) ia->check(&privateContext); } // 3) Execute level action if(level->action != nullptr) level->action(&privateContext); // 4) Set outputs for(auto oa : level->outputAction) { if(oa != nullptr) oa->set(); } }
Changing the Safety Level
The only possibility to change the safety level is through the method triggerEvent.
Safety System Usage
Since the safety system and the HAL (hardware abstraction layer or hardware access layer) are strongly coupled it makes sense to show the usage of both systems on this page.
Sometimes you need to fire an event e.g. swInitDone:
safetySys.triggerEvent(swInitDone, privateContext);
The C-style definition in class SafetySystem:
void triggerEvent(uint32_t event);
Watchdog Output
The last thing to do, is to set an watchdog output, which will be toggled on every execution of run(). This can easily be done with:
SystemOutput<bool>* watchdog = hal.getLogicSystemOutput("watchdog"); safetySys.setWatchdogOutput(watchdog);
Setting Up The System
Before the safety system can be started, you have to define the entry level:
safetySys.setEntryLevel(off);
Finally add the safety system to an executor, so the run() method will be called periodically (every second, for example). Start the thread by calling the start() method of the executor.
Executor e(1); e.addRunnable(safetySys); e.start();