blob: 6de14ceb50395e20f9c2f41cc4c479b7923edfae (
plain)
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
|
Elevator Project
================
Example implementation of a simplified elevator logic, using [TinyFSM].
[TinyFSM]: https://digint.ch/tinyfsm/
Overview
--------
Imagine a elevator having:
- "Call" button on each floor,
- "Floor Sensor" on each floor, triggering an event as soon as the
elevator arrives there,
- "Alarm" button.
Implementation
--------------
The elevator example implements two state machines interacting with
each other:
1. Elevator
- State: Idle
- State: Moving
- State: Panic
2. Motor
- State: Stopped
- State: Up
- State: Down
A good state machine design avoids circular dependencies at all
cost: While the elevator sends events to the motor, the motor NEVER
sends events to the elevator (top-down only).
FAQ
---
Did you notice the motor starting twice? This is by design, let's
have a look at the call stack of fsm_list::start() in main.cpp:
FsmList<Motor, Elevator>::start()
Motor::set_initial_state()
Motor::current_state = Stopped
Elevator::set_initial_state()
Elevator::current_state = Idle
Motor::enter()
Motor:Stopped->entry()
cout << "Motor: stopped" <-- HERE
Motor::direction = 0
Elevator::enter()
Elevator:Idle->entry()
send_event(MotorStop)
Motor::react(MotorStop)
Motor:Stopped->transit<Stopped>
Motor:Stopped->exit()
Motor::current_state = Stopped
Motor:Stopped->entry()
cout << "Motor: stopped" <-- HERE
Motor::direction = 0
Elevator::react(MotorStop)
If we really had to work around this, we could either:
1. Change the initialization (bad design practice!) in main.cpp:
- fsm_list::start();
+ fsm_list::set_initial_state();
+ Elevator::enter();
2. Modify the Motor:Stopped->entry() function in motor.cpp:
class Stopped : public Motor {
void entry() override {
+ if(direction == 0)
+ return;
cout << "Motor: stopped" << endl;
direction = 0;
};
|