6 #ifndef STATE_MACHINE_SM_STATEMACHINE_H_
7 #define STATE_MACHINE_SM_STATEMACHINE_H_
9 #include "sg_monitor.h"
10 #include "sm_errorhandle.h"
15 #include <initializer_list>
18 namespace mcx::state_machine {
20 constexpr
auto MAX_NUMBER_OF_STATES = 100;
21 constexpr
auto DEFAULT_TERMINATE_EVENT =
nullptr;
33 template <
class SUPER_STATE>
35 friend class ErrorHandle<SUPER_STATE>;
37 SUPER_STATE* activeState;
39 SUPER_STATE* stateArray[MAX_NUMBER_OF_STATES];
40 std::string machineName;
41 unsigned int eventStackOffset{0};
44 bool setActiveStateRoutine(
int id) {
45 log_assert(
id > -1,
"State is not initialized!");
47 SUPER_STATE* newState = stateArray[id];
49 activeState = newState;
57 std::deque<Event<SUPER_STATE>*> highPriorityEvents;
58 std::deque<Event<SUPER_STATE>*> lowPriorityEvents;
62 EventStatus executeEvent(Event<SUPER_STATE>* event,
bool silently) {
63 EventStatus status = EVENT_NONE;
65 auto prevState = activeState;
66 status =
event->dispatchEvent(activeState);
67 if ((!event->getExecutedOnceFlag() || (status != EVENT_REPEAT && status != EVENT_REPEAT_NO_TERMINATE)) &&
68 !silently && status != EVENT_NONE) {
69 log_sm(
"{}: State: {} Event: {} {}",
getName(), prevState->stateName(), prevState->eventName(event),
70 status == EVENT_REPEAT || status == EVENT_REPEAT_NO_TERMINATE ?
"[repeat]"
71 : status == EVENT_DONE ?
"[done]"
72 : status == EVENT_TERMINATE ?
"[terminate]"
76 log_sm(
"{}: Active state is not set, can not execute event!",
getName());
82 SUPER_STATE* getStatePtr(uint32_t index) {
83 if (
static_cast<int>(index) < numberOfStates) {
84 return stateArray[index];
89 template <
typename... STATES>
90 void action_variadic(signal_monitor::SignalMonitorBase* monitor,
const ErrorGroup& error_group,
91 signal_monitor::MonitorAction action, id_caller<STATES>... states) {
92 auto id_list = {(STATES::id(id_caller<STATES>()))...};
93 for (
auto&
id : id_list) {
94 stateArray[id]->addErrors(monitor, error_group, action);
100 void action_variadic(signal_monitor::SignalMonitorBase* monitor,
const ErrorGroup& error_group,
101 signal_monitor::MonitorAction action) {}
103 state_machine::ErrorHandle<SUPER_STATE> errorHandle;
105 void addEvent(Event<SUPER_STATE>* event,
double timeoutSec, EventPriority priority,
106 EventStatus(SUPER_STATE::*terminateEvent)) {
107 event->setTimeoutSec(timeoutSec);
108 if (!terminateEvent) {
109 event->setTerminateFunc(&State<SUPER_STATE>::terminateEvent);
111 if (priority == HIGH_PRIORITY_EVENT) {
112 highPriorityEvents.insert(highPriorityEvents.begin() + eventStackOffset, event);
116 lowPriorityEvents.push_back(event);
121 StateMachine() : stateArray(), errorHandle(this) {
122 activeState =
nullptr;
125 eventStackOffset = 0;
135 for (
auto& i : stateArray) {
142 for (
auto& e : highPriorityEvents) {
146 for (
auto& e : lowPriorityEvents) {
150 highPriorityEvents.clear();
151 lowPriorityEvents.clear();
159 machineName = new_name;
160 errorHandle.setName(new_name);
167 const std::string&
getName()
const {
return machineName; }
181 template <
class STATE>
185 id = numberOfStates++;
187 numberOfStates = numberOfStates < (
id + 1) ?
id + 1 : numberOfStates;
190 if (!stateArray[
id]) {
191 stateArray[id] =
new STATE();
193 stateArray[id]->create(
this, STATE(),
id, &errorHandle);
194 log_sm(
"{}: Initialized state: {}",
getName(), stateArray[
id]->stateName());
217 template <
class STATE>
221 id = numberOfStates++;
223 numberOfStates = numberOfStates < (
id + 1) ?
id + 1 : numberOfStates;
226 log_assert(
id <= MAX_NUMBER_OF_STATES,
"Number of states exceeded maximum value: {}!", MAX_NUMBER_OF_STATES);
228 if (!stateArray[
id]) {
229 stateArray[id] =
new STATE(new_state);
232 stateArray[id]->create(
this, new_state,
id, &errorHandle);
233 log_sm(
"{}: Initialized state: {}",
getName(), stateArray[
id]->stateName());
245 template <
class STATE>
271 auto prevStateId = activeStateId;
273 activeState->leave();
274 activeState->leave(state_id);
276 if (setActiveStateRoutine(state_id)) {
278 log_sm(
"{}: Enter state: {}",
getName(), activeState->stateName());
280 activeState->errorMonitorAction();
281 activeState->enter();
282 activeState->enter(prevStateId);
285 log_sm(
"{}: Can not enter state, it is not initialized!",
getName());
296 template <
typename STATE>
306 template <
typename... STATES>
308 if (activeStateId > -1) {
310 for (
auto&
id : id_list) {
311 if (
id == activeStateId) {
326 if (activeStateId > -1) {
327 return activeStateId == id;
338 if (activeStateId > -1) {
339 for (
auto&
id : id_list) {
340 if (
id == activeStateId) {
371 EventStatus status = executeEvent(event.getEvent(), silently);
372 delete event.getEvent();
399 EventStatus status = executeEvent(event.getEvent(), silently);
400 delete event.getEvent();
428 EventStatus status = executeEvent(event.getEvent(), silently);
429 delete event.getEvent();
455 EventStatus status = executeEvent(event.getEvent(), silently);
456 delete event.getEvent();
489 EventPriority priority = LOW_PRIORITY_EVENT,
490 EventStatus(SUPER_STATE::*terminateEvent) = DEFAULT_TERMINATE_EVENT) {
491 addEvent(event.getEvent(), timeoutSec, priority, terminateEvent);
523 EventPriority priority = LOW_PRIORITY_EVENT,
524 EventStatus(SUPER_STATE::*terminateEvent) = DEFAULT_TERMINATE_EVENT) {
525 addEvent(event.getEvent(), timeoutSec, priority, terminateEvent);
562 EventPriority priority = LOW_PRIORITY_EVENT,
563 EventStatus(SUPER_STATE::*terminateEvent) = DEFAULT_TERMINATE_EVENT) {
564 addEvent(event.getEvent(), timeoutSec, priority, terminateEvent);
599 EventPriority priority = LOW_PRIORITY_EVENT,
600 EventStatus(SUPER_STATE::*terminateEvent) = DEFAULT_TERMINATE_EVENT) {
601 addEvent(event.getEvent(), timeoutSec, priority, terminateEvent);
604 double getDtSec()
const {
return dtSec; }
613 dtSec = cycleTimeSec;
615 EventStatus status = EVENT_NONE;
617 errorHandle.iterate(cycleTimeSec);
620 activeState->iterate(cycleTimeSec);
623 if (highPriorityEvents.empty() && !lowPriorityEvents.empty()) {
624 highPriorityEvents.push_back(lowPriorityEvents.front());
625 lowPriorityEvents.pop_front();
628 if (!highPriorityEvents.empty()) {
630 eventStackOffset = 0;
631 status = executeEvent(event,
false);
632 event->setExecutedOnceFlag(
true);
633 if (status == EVENT_REPEAT || status == EVENT_REPEAT_NO_TERMINATE) {
634 double timeout =
event->getTimeoutSec() - cycleTimeSec;
635 event->setTimeoutSec(timeout);
636 if (timeout <= 0.0f) {
637 highPriorityEvents.erase(highPriorityEvents.begin() + eventStackOffset);
641 status = EVENT_TERMINATE;
644 highPriorityEvents.push_front(termFuncPtr);
648 case EVENT_REPEAT_NO_TERMINATE: {
658 highPriorityEvents.erase(highPriorityEvents.begin() + eventStackOffset);
672 void clear(
bool highPriority =
true,
bool lowPriority =
true) {
674 eventStackOffset = 0;
675 highPriorityEvents.clear();
678 lowPriorityEvents.clear();
688 size_t length(EventPriority priority = LOW_PRIORITY_EVENT) {
690 case LOW_PRIORITY_EVENT: {
691 return lowPriorityEvents.size();
693 case HIGH_PRIORITY_EVENT: {
694 return highPriorityEvents.size();
724 return activeState->warning(error) == EventStatus::EVENT_DONE;
740 return activeState->forcedDisengaged(error) == EventStatus::EVENT_DONE;
756 return activeState->shutdown(error) == EventStatus::EVENT_DONE;
772 return activeState->emergencyStop(error) == EventStatus::EVENT_DONE;
778 template <
class BaseState>
779 template <
class STATE>
786 #endif // STATE_MACHINE_SM_STATEMACHINE_H_