YARP
Yet Another Robot Platform
fsm.h
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #ifndef YARP_MANAGER_FSM
7 #define YARP_MANAGER_FSM
8 
9 #include <iostream>
10 #include <string>
11 #include <typeinfo>
12 #include <exception>
13 #include <map>
14 
15 #include <yarp/os/Semaphore.h>
16 
17 namespace FSM {
18  class Event;
19  class IEventSink;
20  class StateBase;
21  class StateMachineBase;
22 }
23 
29 {
30 public:
31  Event(const char* szName) {
32  if(szName) { strName = szName; }
33  timeStamp = 0;
34  }
35  virtual ~Event() = default;
36 
37  void setTimeStamp(double t) { timeStamp = t; }
38  double getTimeStamp() { return timeStamp; }
39  const char* getName() { return strName.c_str(); }
40 
41  inline bool operator==(const Event& alt) const {
42  return ((strName == alt.strName)); }
43 
44 private:
45  std::string strName;
46  double timeStamp;
47 };
48 
49 
50 
56 {
57 public:
58 
59  IEventSink() = default;
60  virtual ~IEventSink() = default;
61 
65  virtual void castEvent (Event* event) = 0;
66 
67 private:
68 
69 
70 };
71 
72 
77 {
78 public:
79  StateBase(IEventSink* pEventSink, const char* szName = nullptr) {
80  eventSink = pEventSink;
81  if(szName) { strName = szName; }
82  }
83 
84  virtual ~StateBase() = default;
85 
86  const char* getName() {
87  return strName.c_str(); }
88 
89 protected:
90  void castEvent(Event* event) {
91  eventSink->castEvent(event);
92  }
93 
94 private:
95  IEventSink* eventSink;
96  std::string strName;
97 };
98 
99 typedef std::map<FSM::StateBase*, std::map<FSM::Event*, FSM::StateBase*> > MyStateMap;
100 typedef std::map<FSM::StateBase*, std::map<FSM::Event*, FSM::StateBase*> >::iterator MyStateItr;
101 
102 
107 {
108 public:
110  state = nullptr;
111  currentTimeStamp = 0.0;
112  }
113  ~StateMachineBase() override = default;
114 
116  try
117  {
118  // typeid(*state);
119  return state;
120  }
121  catch (std::exception& )
122  {
123  std::cerr<<"Exception in currentState(): Initial state is not set!"<<std::endl;
124  std::terminate();
125  }
126  }
127 
128  void setInitState(StateBase* pState) {
129  if(!state) { state = pState; }
130  }
131 
132  void addTransition(StateBase* source, Event* event, StateBase* target) {
133  try
134  {
135 // typeid(*target);
136  transitions[source][event] = target;
137  }
138  catch (std::exception& typevar)
139  {
140  std::cerr<<"Exception in addTransition(): "<<typevar.what()<<std::endl;
141  std::terminate();
142  }
143  }
144 
145 protected:
146 
150  virtual void onTransition(StateBase* previous, Event* event, StateBase* current) {}
151  virtual void onEventMissed(StateBase* state, Event* event) {}
152 
153 public: // implementing IEventSink::castEvent()
154 
155  void castEvent(Event* event) override
156  {
157  semEvent.wait();
158  if(!state)
159  {
160  std::cerr<<"Initial state is not set!"<<std::endl;
161  semEvent.post();
162  return;
163  }
164 
165  if(event->getTimeStamp() < currentTimeStamp )
166  {
167  onEventMissed(state, event);
168  semEvent.post();
169  return;
170  }
171 
172  currentTimeStamp = event->getTimeStamp();
173 
174  MyStateItr it;
175  it = transitions.find(state);
176  if(it==transitions.end())
177  {
178  std::cerr<<"No transition is registered from state "<<state->getName()<<std::endl;
179  semEvent.post();
180  return;
181  }
182 
183  std::map<Event*, StateBase*> row = transitions[state];
184  std::map<Event*, StateBase*>::iterator itr2 = row.find(event);
185  if(itr2 == row.end())
186  {
187  std::cerr<<"No transition is registered for event ";
188  std::cerr<<event->getName()<<" ("<<event->getTimeStamp()<<")";
189  std::cerr<<" from state "<<state->getName()<<std::endl;
190  semEvent.post();
191  return;
192  }
193 
194  StateBase* previous = state;
195  state = row[event];
196 
197  // calling callback
198  onTransition(previous, event, state);
199  semEvent.post();
200  }
201 
202 private:
203  StateBase* state;
204  MyStateMap transitions;
205  yarp::os::Semaphore semEvent;
206  double currentTimeStamp;
207 
208 };
209 
210 
211 #endif // __YARP_MANAGER_FSM__
float t
class IEventSink
Definition: fsm.h:29
Event(const char *szName)
Definition: fsm.h:31
virtual ~Event()=default
bool operator==(const Event &alt) const
Definition: fsm.h:41
void setTimeStamp(double t)
Definition: fsm.h:37
double getTimeStamp()
Definition: fsm.h:38
const char * getName()
Definition: fsm.h:39
class IEventSink
Definition: fsm.h:56
IEventSink()=default
virtual void castEvent(Event *event)=0
virtual ~IEventSink()=default
Class StateBase.
Definition: fsm.h:77
StateBase(IEventSink *pEventSink, const char *szName=nullptr)
Definition: fsm.h:79
void castEvent(Event *event)
Definition: fsm.h:90
const char * getName()
Definition: fsm.h:86
virtual ~StateBase()=default
Class StateMachineBase.
Definition: fsm.h:107
virtual void onTransition(StateBase *previous, Event *event, StateBase *current)
Callback onTransition represents the change in the states.
Definition: fsm.h:150
StateBase * currentState()
Definition: fsm.h:115
~StateMachineBase() override=default
virtual void onEventMissed(StateBase *state, Event *event)
Definition: fsm.h:151
void setInitState(StateBase *pState)
Definition: fsm.h:128
void castEvent(Event *event) override
Definition: fsm.h:155
void addTransition(StateBase *source, Event *event, StateBase *target)
Definition: fsm.h:132
A class for thread synchronization and mutual exclusion.
Definition: Semaphore.h:26
void wait()
Decrement the counter, even if we must wait to do that.
Definition: Semaphore.cpp:96
void post()
Increment the counter.
Definition: Semaphore.cpp:111
std::map< FSM::StateBase *, std::map< FSM::Event *, FSM::StateBase * > > MyStateMap
Definition: fsm.h:99
std::map< FSM::StateBase *, std::map< FSM::Event *, FSM::StateBase * > >::iterator MyStateItr
Definition: fsm.h:100
Definition: fsm.h:17