SimpleStatemachine.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package ARCHES::ArmarXObjects::ARCHESArmar6GraspCandidateExecutor
17  * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18  * @date 2019
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #pragma once
24 
25 #include <type_traits>
26 #include <functional>
27 
31 
32 namespace armarx
33 {
34  template<class EnumT>
36 
37  template<class EnumT>
38  class state_t
39  {
40  static_assert(std::is_enum_v<EnumT>);
41  public:
42  using enum_t = EnumT;
43 
44  // *INDENT-OFF*
45  auto previous_state () const { return _previous_state ; }
46  auto current_state () const { return _current_state ; }
47  auto is_initial_state () const { return _is_initial_state ; }
48 
49  void quit()
50  {
51  _quit = true;
52  }
53  // *INDENT-ON*
54  private:
56  enum_t _previous_state;
57  enum_t _current_state;
58  bool _quit{false};
59  bool _is_initial_state{true};
60  };
61 
62  template<class EnumT>
63  class simple_state_machine
64  {
65  static_assert(std::is_enum_v<EnumT>);
66  public:
67  using enum_t = EnumT;
70 
71  using state_function_t = std::function<enum_t(state_t&)>;
72  using transition_function_t = std::function<void(const state_t&)>;
73  using hook_function_t = std::function<void(const state_t&)>;
74 
75 
76  public:
77  static void noop_transition(const state_t&) {}
78 
79  template<enum_t state>
81  {
82  ARMARX_CHECK_EXPRESSION(!_states.count(state));
83  _states[state] = std::move(f);
84  }
85 
86  template<enum_t state0, enum_t state1>
88  {
89  ARMARX_CHECK_EXPRESSION(!_transitions.count({state0, state1}));
90  _transitions[ {state0, state1}] = std::move(f);
91  }
92 
94  {
95  _post_transition_callback = std::move(f);
96  }
97 
99  {
100  _pre_transition_callback = std::move(f);
101  }
102 
104  {
105  _post_state_exit_callback = std::move(f);
106  }
107 
109  {
110  _pre_state_enter_callback = std::move(f);
111  }
112  template<enum_t state0>
114  {
115  ARMARX_TRACE;
116  for (const auto& [edge, _] : _transitions)
117  {
118  ARMARX_TRACE;
119  const auto [f, t] = edge;
120  ARMARX_CHECK_EXPRESSION(_states.count(f)) << "No state " << f;
121  ARMARX_CHECK_EXPRESSION(_states.count(t)) << "No state " << t;
122  }
123  state_t state;
124  state._previous_state = state0;
125  state._current_state = state0;
126  state._is_initial_state = true;
127  state._quit = false;
128 
129  while (true)
130  {
131  ARMARX_TRACE;
132  _pre_state_enter_callback(state);
133  ARMARX_IMPORTANT << "Executing state '" << state._current_state << "'";
134  const auto next = _states.at(state._current_state)(state);
135  state._previous_state = state._current_state;
136  state._current_state = next;
137  state._is_initial_state = false;
138  _post_state_exit_callback(state);
139  if (state._quit)
140  {
141  break;
142  }
143  const std::pair<enum_t, enum_t> t{state._previous_state, state._current_state};
144  ARMARX_CHECK_EXPRESSION(_transitions.count(t))
145  << "No transition from " << state._previous_state << " to " << state._current_state;
146  _pre_transition_callback(state);
147  ARMARX_IMPORTANT << "Taking transition '" << state._previous_state << "' -> '" << state._current_state << "'";
148  _transitions.at(t)(state);
149  _post_transition_callback(state);
150  }
151  ARMARX_IMPORTANT << "Exiting while in state '" << state._current_state << "'";
152  return state;
153  }
154 
155  private:
156  std::unordered_map<enum_t, state_function_t> _states;
157  std::unordered_map<std::pair<enum_t, enum_t>, transition_function_t> _transitions;
158 
159  hook_function_t _pre_transition_callback = noop_transition;
160  hook_function_t _post_transition_callback = noop_transition;
161 
162  hook_function_t _pre_state_enter_callback = noop_transition;
163  hook_function_t _post_state_exit_callback = noop_transition;
164  };
165 }
armarx::simple_state_machine::enum_t
EnumT enum_t
Definition: SimpleStatemachine.h:67
armarx::state_t::quit
void quit()
Definition: SimpleStatemachine.h:49
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::simple_state_machine::transition_function_t
std::function< void(const state_t &)> transition_function_t
Definition: SimpleStatemachine.h:72
armarx::simple_state_machine::set_post_transition_callback
void set_post_transition_callback(hook_function_t f)
Definition: SimpleStatemachine.h:93
armarx::simple_state_machine::run
state_t run()
Definition: SimpleStatemachine.h:113
armarx::simple_state_machine::hook_function_t
std::function< void(const state_t &)> hook_function_t
Definition: SimpleStatemachine.h:73
armarx::simple_state_machine
Definition: SimpleStatemachine.h:35
trace.h
armarx::state_t::current_state
auto current_state() const
Definition: SimpleStatemachine.h:46
armarx::state_t::is_initial_state
auto is_initial_state() const
Definition: SimpleStatemachine.h:47
armarx::state_t
Definition: SimpleStatemachine.h:38
armarx::simple_state_machine::state_function_t
std::function< enum_t(state_t &)> state_function_t
Definition: SimpleStatemachine.h:71
armarx::simple_state_machine::configure_transition
void configure_transition(transition_function_t f=noop_transition)
Definition: SimpleStatemachine.h:87
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
armarx::simple_state_machine::set_pre_state_enter_callback
void set_pre_state_enter_callback(hook_function_t f)
Definition: SimpleStatemachine.h:108
armarx::simple_state_machine::noop_transition
static void noop_transition(const state_t &)
Definition: SimpleStatemachine.h:77
ExpressionException.h
armarx::simple_state_machine::set_pre_transition_callback
void set_pre_transition_callback(hook_function_t f)
Definition: SimpleStatemachine.h:98
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
hash.h
armarx::simple_state_machine::set_post_state_exit_callback
void set_post_state_exit_callback(hook_function_t f)
Definition: SimpleStatemachine.h:103
armarx::state_t::enum_t
EnumT enum_t
Definition: SimpleStatemachine.h:42
armarx::state_t::previous_state
auto previous_state() const
Definition: SimpleStatemachine.h:45
armarx::simple_state_machine::configure_state
void configure_state(state_function_t f)
Definition: SimpleStatemachine.h:80
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28