6 #ifndef STATE_MACHINE_SM_STATE_H
7 #define STATE_MACHINE_SM_STATE_H
9 #include "sg_monitorbase.h"
10 #include "sg_signalidgroup.h"
11 #include "sm_errorhandlebase.h"
21 #define LOGIC_STATE_ID(x) x::id(mcx::state_machine::id_caller<x>())
23 namespace mcx::state_machine {
25 constexpr
auto EVENT_DEFAULT_TIMEOUT_SEC = std::numeric_limits<double>::max();
30 template <
class SUPER_STATE>
33 template <
class SUPER_STATE>
36 template <
class STATE>
44 std::string defaultName;
50 std::vector<event_name> eventList;
52 inline std::string stateName(
const std::string& prettyFunction) {
53 const std::string stateBeginToken =
"STATE = ";
54 const std::string stateEndTokenGCC =
";";
55 const std::string stateEndTokenClang =
",";
56 size_t begin = prettyFunction.find(stateBeginToken) + stateBeginToken.length();
57 size_t end = prettyFunction.find(stateEndTokenGCC, begin);
58 if (end == std::string::npos) {
59 end = prettyFunction.find(stateEndTokenClang, begin);
61 if (begin == std::string::npos || end == std::string::npos)
64 return prettyFunction.substr(begin, end - begin);
67 struct ErrorMonitorData {
69 ErrorGroup errors[signal_monitor::MonitorAction::NUMBER_OF_ACTIONS];
72 ErrorMonitorData errorMonitor;
75 void addToEventList(
const event_name& event) {
76 for (
auto& e : eventList) {
77 if (event.event->compare(e.event)) {
82 eventList.push_back(event);
86 addToEventList({.event = event.getEvent(), .name = eventName});
90 eventList.push_back({.event = event.getEvent(), .name = eventName});
94 eventList.push_back({.event = event.getEvent(), .name = eventName});
98 eventList.push_back({.event = event.getEvent(), .name = eventName});
102 template <
class STATE,
class MACHINE>
103 void create(MACHINE* newMachine,
const STATE& state,
int id,
ErrorHandleBase* errorHandle) {
104 setMachine(newMachine);
105 Container<STATE>::id = id;
106 idPtr = &Container<STATE>::id;
107 errorMonitor.errorHandle = errorHandle;
108 defaultName = stateName(__PRETTY_FUNCTION__);
109 this->addEventName(&SUPER_STATE::delayEvent,
"delayEvent");
110 this->addEventName(&SUPER_STATE::terminateEvent,
"terminateEvent");
111 this->addEventName(&SUPER_STATE::acknowledgeErrors,
"acknowledgeErrors");
112 this->addEventName(&SUPER_STATE::warning_,
"warning");
113 this->addEventName(&SUPER_STATE::forcedDisengaged_,
"forcedDisengaged");
114 this->addEventName(&SUPER_STATE::shutdown_,
"shutdown");
115 this->addEventName(&SUPER_STATE::emergencyStop_,
"emergencyStop");
116 registerUserEvents();
120 auto groupBegin = stateErrors->begin();
121 for (
auto& error : errorsToAdd) {
122 groupBegin = std::find(groupBegin, stateErrors->end(), error);
123 if (groupBegin == stateErrors->end()) {
124 stateErrors->add(error);
131 for (
auto& error : errorsToAdd) {
132 auto refBegin = refErrors.begin();
135 refBegin = std::find(refBegin, refErrors.end(), error);
136 if (refBegin != refErrors.end()) {
137 auto groupBegin = std::find(stateErrors->begin(), stateErrors->end(), *refBegin);
138 if (groupBegin == stateErrors->end()) {
139 stateErrors->add(*refBegin);
150 auto groupBegin = stateErrors->begin();
151 for (
auto& error : errorsToAdd) {
153 groupBegin = std::find(groupBegin, stateErrors->end(), error);
154 if (groupBegin != stateErrors->end()) {
155 stateErrors->erase(groupBegin);
163 void addErrors(
const ErrorGroup& codes, signal_monitor::MonitorAction newAction) {
164 auto& action = errorMonitor.errors;
165 using namespace signal_monitor;
166 auto& stateErrorsGroup = action[MonitorAction::ADD];
168 case MonitorAction::ADD: {
169 addErrorsHelper(&stateErrorsGroup, codes);
172 case MonitorAction::RESET: {
173 auto& resetGroup = action[MonitorAction::RESET];
174 enableErrorsHelper(&resetGroup, stateErrorsGroup, codes);
177 case MonitorAction::ENABLE: {
178 auto& enableGroup = action[MonitorAction::ENABLE];
179 enableErrorsHelper(&enableGroup, stateErrorsGroup, codes);
180 auto& disableGroup = action[MonitorAction::DISABLE];
181 disableErrorsHelper(&disableGroup, codes);
184 case MonitorAction::DISABLE: {
185 auto& disableGroup = action[MonitorAction::DISABLE];
186 enableErrorsHelper(&disableGroup, stateErrorsGroup, codes);
187 auto& enableGroup = action[MonitorAction::ENABLE];
188 disableErrorsHelper(&enableGroup, codes);
192 log_error(
"Failed to add unknown motion action: {}", newAction);
197 virtual void registerUserEvents() {}
199 template <
class MACHINE>
200 void setMachine(MACHINE* newMachine) {
204 template <
class MACHINE>
205 MACHINE* getMachine() {
209 State() : mach() { idPtr =
nullptr; }
212 for (
auto& e : eventList) {
218 double getDtSec()
const {
return mach->getDtSec(); }
220 template <
class STATE>
222 return Container<STATE>::id;
225 int id() {
return *idPtr; }
227 void clearEventQueue(
bool highPriority =
true,
bool lowPriority =
true) { mach->
clear(highPriority, lowPriority); }
229 SUPER_STATE* setActiveState(
int state_id) {
return mach->
setActiveState(state_id,
true); }
231 template <
class NEWSTATE>
232 NEWSTATE* setActiveState() {
233 return mach->template setActiveState<NEWSTATE>(
true);
236 template <
class NEWSTATE>
237 NEWSTATE* setActiveState(
const NEWSTATE& state) {
238 return mach->template setActiveState<NEWSTATE>(
true);
241 template <
typename... STATES>
242 bool isStateActive() {
243 return mach->template isStateActive<STATES...>();
246 bool isStateActive(
int id) {
return mach->
isStateActive(
id); }
248 void addEvent(
const Event0<SUPER_STATE>& event,
double timeoutSec = EVENT_DEFAULT_TIMEOUT_SEC,
249 EventPriority priority = HIGH_PRIORITY_EVENT) {
250 mach->addEvent(event, timeoutSec, priority);
253 void addEvent(
const Event1<SUPER_STATE>& event,
double timeoutSec = EVENT_DEFAULT_TIMEOUT_SEC,
254 EventPriority priority = HIGH_PRIORITY_EVENT) {
255 mach->addEvent(event, timeoutSec, priority);
258 void addEvent(
const Event2<SUPER_STATE>& event,
double timeoutSec = EVENT_DEFAULT_TIMEOUT_SEC,
259 EventPriority priority = HIGH_PRIORITY_EVENT) {
260 mach->addEvent(event, timeoutSec, priority);
263 void addEvent(
const Event3<SUPER_STATE>& event,
double timeoutSec = EVENT_DEFAULT_TIMEOUT_SEC,
264 EventPriority priority = HIGH_PRIORITY_EVENT) {
265 mach->addEvent(event, timeoutSec, priority);
268 double getActiveTimeoutSec() {
return mach->getActiveTimeoutSec(); }
270 virtual const char* stateName()
const {
return defaultName.c_str(); }
273 for (
unsigned int i = 0; i < eventList.size(); i++) {
274 if (event->compare(eventList[i].event)) {
275 return eventList[i].name.c_str();
279 return "Undefined name";
282 virtual EventStatus acknowledgeErrors() {
return EVENT_NONE; }
284 bool clearErrorMonitor(
bool warnings_only =
false) {
return getErrorMonitor()->acknowledge(warnings_only); }
286 ErrorHandleBase* getErrorMonitor() {
return errorMonitor.errorHandle; }
288 EventStatus warning(
const Error& error) {
289 auto result = mach->executeEvent({&SUPER_STATE::warning_, error},
true);
290 if (result == EventStatus::EVENT_DONE) {
291 if (getErrorMonitor()->warning(error)) {
298 EventStatus forcedDisengaged(
const Error& error) {
299 auto result = mach->executeEvent({&SUPER_STATE::forcedDisengaged_, error});
300 if (result == EventStatus::EVENT_DONE) {
301 if (getErrorMonitor()->forcedDisengaged(error)) {
308 EventStatus shutdown(
const Error& error) {
309 auto result = mach->executeEvent({&SUPER_STATE::shutdown_, error});
310 if (result == EventStatus::EVENT_DONE) {
311 if (getErrorMonitor()->shutdown(error)) {
318 EventStatus emergencyStop(
const Error& error) {
319 auto result = mach->executeEvent({&SUPER_STATE::emergencyStop_, error});
320 if (result == EventStatus::EVENT_DONE) {
321 if (getErrorMonitor()->emergencyStop(error)) {
328 EventStatus delayEvent() {
return EVENT_REPEAT_NO_TERMINATE; }
330 virtual EventStatus terminateEvent() {
return EVENT_DONE; }
332 void errorMonitorAction() {
333 auto monitor = errorMonitor.errorHandle->getSignalMonitor();
334 using namespace signal_monitor;
335 for (
int action = 0; action < MonitorAction::NUMBER_OF_ACTIONS; action++) {
336 auto& errors = errorMonitor.errors[action];
338 case MonitorAction::ENABLE:
339 monitor->enable(errors);
341 case MonitorAction::DISABLE:
342 monitor->disable(errors);
344 case MonitorAction::RESET:
345 monitor->reset(errors);
353 virtual void enter() {}
355 virtual void enter(
int prev_state_id) {}
357 virtual void leave() {}
359 virtual void leave(
int next_state_id) {}
361 virtual void iterate(
double dt_sec) {}
364 virtual EventStatus warning_(
const Error& error) = 0;
366 virtual EventStatus forcedDisengaged_(
const Error& error) = 0;
368 virtual EventStatus shutdown_(
const Error& error) = 0;
370 virtual EventStatus emergencyStop_(
const Error& error) = 0;
375 #endif // STATE_MACHINE_SM_STATE_H