-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdetector_fsm.hpp
80 lines (61 loc) · 1.96 KB
/
detector_fsm.hpp
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
#ifndef DETECTOR_FSM_HPP
#define DETECTOR_FSM_HPP
#include <chrono>
#include "boost/sml.hpp"
struct CalibrationInfo {
int readings{0};
double mean{0.0};
};
namespace FSM {
constexpr auto calibration_readings = 250;
// events
struct reading {
double stdev;
};
struct cal_done {
};
// states
auto Calibrating = boost::sml::state<class Calibrating>;
auto NoDip = boost::sml::state<class NoDip>;
auto Dip = boost::sml::state<class Dip>;
// guards
auto IsBelowLowerThreshold = [](const reading& e, CalibrationInfo& cal) -> bool {
// Below 75% mean stdev
return e.stdev < cal.mean * .75;
};
auto IsAboveUpperThreshold = [](const reading& e, CalibrationInfo& cal) -> bool {
// Above 75% mean stdev
return e.stdev > cal.mean * .75;
};
// actions
auto AccumulateMean = [](const auto& e, auto& sm, CalibrationInfo& cal) -> void {
cal.readings++;
cal.mean += (e.stdev - cal.mean) / cal.readings;
if (cal.readings == calibration_readings) {
sm.process_event(cal_done{});
}
};
auto NotifyDip = [](std::function<void(void)>& callback) {
callback();
};
struct Detector_ {
auto operator()() noexcept {
using namespace boost::sml;
return make_transition_table(
*Calibrating + event<reading> / AccumulateMean,
Calibrating + event<cal_done> = NoDip,
NoDip + event<reading>[IsBelowLowerThreshold] / NotifyDip = Dip,
Dip + event<reading>[IsAboveUpperThreshold] = NoDip
);
}
};
}
struct DetectorFSM {
explicit DetectorFSM(std::function<void(void)> dip_callback) :
callback_(dip_callback),
sm(cal_, callback_) {}
CalibrationInfo cal_{};
std::function<void(void)> callback_{[] {}};
boost::sml::sm<FSM::Detector_> sm;
};
#endif // DETECTOR_FSM_HPP