-
Notifications
You must be signed in to change notification settings - Fork 3
/
motor-separate.cpp
187 lines (162 loc) · 4.58 KB
/
motor-separate.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// This example shows how to define nested FSMs independently of their
// nesting class. This allows to reuse sub-FSMs at multiple places.
// Here, we nest Homing FSM into the Motor FSM but only at one place.
#include "msfsm.hpp"
#include <iostream>
using namespace msfsm;
using namespace std;
// Event commont to all FSMs below
struct Periodic {};
// Homing FSM that is nested into Motor::Homing state (see below)
class FsmHoming : public Fsm<FsmHoming> {
public:
virtual ~FsmHoming() {}
private:
friend Fsm<FsmHoming>;
// Homing base state
class State : public Fsm::State, public Named<State> {
friend Fsm;
using Fsm::State::State;
virtual void event(Periodic) = 0;
};
void onTransition(State& nextState) {
cout << nextState.name() << endl;
}
// Extra interface for the higher FSM (Motor)
//
// Methods to be called by Motor
public:
void start() { transition(moveLeft); }
// Methods to be implemented by Motor
private:
virtual void stop() = 0;
virtual void setSpeed(int speed) = 0;
virtual int getPosition() = 0;
class MoveLeft : public State {
friend Fsm;
using State::State;
void entry() {
fsm.setSpeed(-1);
}
void event(Periodic) override {
if (fsm.getPosition() == 0)
transition(fsm.moveRight);
}
void exit() override {
fsm.setSpeed(0);
}
} moveLeft {this};
class MoveRight : public State {
friend Fsm;
using State::State;
void entry() {
fsm.setSpeed(+1);
}
void event(Periodic) override {
if (fsm.getPosition() == 7)
return fsm.stop();
}
void exit() override {
fsm.setSpeed(0);
}
} moveRight {this};
};
class Motor : protected msfsm::Fsm<Motor>
{
public:
Motor() {
transition(homing);
}
void home() { handle(Home()); }
void moveTo(int t) { handle(Goto(t)); }
void periodic() {
handle(Periodic());
position += speed;
cout << position << endl;
}
bool isMoving() const { return state() != &idle; }
private:
friend Fsm;
// Events
struct Home {};
struct Goto {
const int position;
Goto(int pos) : position(pos) {}
};
int position = 3;
int speed = 0;
class State : public Fsm::State, public Named<State> {
friend Fsm;
using Fsm::State::State;
virtual void event(Periodic) = 0;
virtual void event(Goto g) { /* ignore when not explicitly handled */ };
virtual void event(Home) { /* ignore when not explicitly handled */ };
};
void onTransition(State& nextState) {
cout << nextState.name() << endl;
}
class Homing : public State, public FsmHoming {
public:
Homing(Motor *fsm) : Motor::State(fsm) {}
~Homing() = default;
private:
friend Fsm<Motor>;
void entry() {
start();
}
void event(Periodic p) override {
handle(p); // Send the event to sub-FSM
}
void exit() override {
destroy(); // Destroy sub-FSM
}
// Called when sub-FSM finishes
void stop() override { Motor::State::transition(fsm.idle); }
void setSpeed(int speed) override { fsm.speed = speed; }
int getPosition() override { return fsm.position; }
} homing {this};
class Idle : public State {
friend Fsm;
using State::State;
void entry() {}
void event(Goto g) override {
return transition(fsm.moving, g);
}
void event(Home) override {
return transition(fsm.homing);
}
void event(Periodic) override {}
} idle {this};
class Moving : public State {
friend Fsm;
using State::State;
int target;
void entry(Goto g) {
target = g.position;
if (target < fsm.position)
fsm.speed = -1;
if (target > fsm.position)
fsm.speed = +1;
}
void event(Goto g) override {
return transition(fsm.moving, g);
}
void event(Periodic) override {
if (fsm.position == target)
return transition(fsm.idle);
}
void exit() override {
fsm.speed = 0;
}
} moving {this};
};
int main(int argc, char *argv[])
{
Motor m;
while (m.isMoving())
m.periodic();
m.moveTo(4);
while (m.isMoving())
m.periodic();
return 0;
}