-
Notifications
You must be signed in to change notification settings - Fork 3
/
motor.cpp
154 lines (137 loc) · 3.76 KB
/
motor.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
#include "msfsm.hpp"
#include <iostream>
using namespace msfsm;
using namespace std;
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 Periodic {};
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 Fsm<Homing> {
friend Fsm<Motor>;
friend Fsm<Homing>;
public:
using Motor::State::State;
private:
void entry() {
Fsm<Homing>::transition(moveLeft);
}
void event(Periodic p) override {
handle(p);
}
void exit() override {
destroy();
}
// Homing base state
class State : public Fsm<Homing>::State, public Named<State> {
friend Fsm;
using Fsm::State::State;
virtual void event(Periodic) = 0;
};
void onTransition(State& nextState) {
cout << nextState.name() << endl;
}
class MoveLeft : public State {
friend Fsm;
using State::State;
void entry() {
fsm.fsm.speed = -1;
}
void event(Periodic) override {
if (fsm.fsm.position == 0)
transition(fsm.moveRight);
}
void exit() override {
fsm.fsm.speed = 0;
}
} moveLeft {this};
class MoveRight : public State {
friend Fsm;
using State::State;
void entry() {
fsm.fsm.speed = +1;
}
void event(Periodic) override {
if (fsm.fsm.position == 7)
return fsm.fsm.transition(fsm.fsm.idle);
}
void exit() override {
fsm.fsm.speed = 0;
}
} moveRight {this};
} 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;
}