Vanetza
 
Loading...
Searching...
No Matches
fully_meshed_state_machine.cpp
1#include "channel_load.hpp"
2#include "fully_meshed_state_machine.hpp"
3#include <algorithm>
4#include <array>
5#include <cassert>
6#include <cmath>
7#include <limits>
8
9namespace vanetza
10{
11namespace dcc
12{
13
14static constexpr std::size_t N_samples_up = std::chrono::seconds(1) / NDL_minDccSampling;
15static constexpr std::size_t N_samples_down = std::chrono::seconds(5) / NDL_minDccSampling;
16
17static constexpr double NDL_minChannelLoad = 0.19;
18static constexpr double NDL_maxChannelLoad = 0.59;
19
20Clock::duration Relaxed::transmission_interval() const
21{
22 return std::chrono::milliseconds(60);
23}
24
25const char* Relaxed::name() const
26{
27 return "Relaxed";
28}
29
30Clock::duration Restrictive::transmission_interval() const
31{
32 return std::chrono::milliseconds(460);
33}
34
35const char* Restrictive::name() const
36{
37 return "Restrictive";
38}
39
40const std::size_t Active::sc_substates = 5;
41
42Active::Active() : m_substate(0)
43{
44}
45
46void Active::update(double min_cl, double max_cl)
47{
48 assert(min_cl <= max_cl);
49
50 static const std::array<double, sc_substates> channel_loads {{
51 0.27, 0.35, 0.43, 0.51, 0.59
52 }};
53
54 auto state_up_it = std::upper_bound(channel_loads.begin(), channel_loads.end(), min_cl);
55 auto state_up = std::distance(channel_loads.begin(), state_up_it);
56
57 auto state_down_it = std::upper_bound(channel_loads.begin(), channel_loads.end(), max_cl);
58 auto state_down = std::distance(channel_loads.begin(), state_down_it);
59
60 m_substate = std::max(state_up, state_down);
61 m_substate = std::min(sc_substates - 1, m_substate);
62 assert(m_substate < sc_substates);
63}
64
65Clock::duration Active::transmission_interval() const
66{
67 static const std::array<Clock::duration, sc_substates> tx_intervals {{
68 std::chrono::milliseconds(100),
69 std::chrono::milliseconds(180),
70 std::chrono::milliseconds(260),
71 std::chrono::milliseconds(340),
72 std::chrono::milliseconds(420),
73 }};
74
75 const std::size_t index = std::min(tx_intervals.size() - 1, m_substate);
76 return tx_intervals[index];
77}
78
79const char* Active::name() const
80{
81 static const std::array<const char*, sc_substates> names {{
82 "Active 1",
83 "Active 2",
84 "Active 3",
85 "Active 4",
86 "Active 5"
87 }};
88
89 assert(m_substate < sc_substates);
90 return names[m_substate];
91}
92
93FullyMeshedStateMachine::FullyMeshedStateMachine() :
94 m_state(&m_relaxed),
95 m_channel_loads(std::max(N_samples_up, N_samples_down))
96{
97}
98
99FullyMeshedStateMachine::~FullyMeshedStateMachine()
100{
101}
102
103void FullyMeshedStateMachine::update(ChannelLoad cl)
104{
105 m_channel_loads.push_front(cl);
106
107 if (m_state == &m_relaxed) {
108 if (min_channel_load() >= NDL_minChannelLoad) {
109 m_state = &m_active;
110 m_active.update(min_channel_load(), max_channel_load());
111 }
112 } else if (m_state == &m_restrictive) {
113 if (max_channel_load() < NDL_maxChannelLoad) {
114 m_state = &m_active;
115 m_active.update(min_channel_load(), max_channel_load());
116 }
117 } else {
118 if (max_channel_load() < NDL_minChannelLoad) {
119 m_state = &m_relaxed;
120 } else if (min_channel_load() >= NDL_maxChannelLoad) {
121 m_state = &m_restrictive;
122 } else {
123 m_state = &m_active;
124 m_active.update(min_channel_load(), max_channel_load());
125 }
126 }
127}
128
129double FullyMeshedStateMachine::message_rate() const
130{
131 std::chrono::duration<double> one_sec = std::chrono::seconds(1);
132 return one_sec / transmission_interval();
133}
134
135Clock::duration FullyMeshedStateMachine::transmission_interval() const
136{
137 return m_state->transmission_interval();
138}
139
140const State& FullyMeshedStateMachine::state() const
141{
142 assert(m_state != nullptr);
143 return *m_state;
144}
145
146double FullyMeshedStateMachine::min_channel_load() const
147{
148 assert(N_samples_up > 0);
149 double min_cl = std::numeric_limits<double>::infinity();
150 std::size_t sample_cnt = 0;
151 for (auto sample : m_channel_loads) {
152 if (sample_cnt >= N_samples_up) {
153 break;
154 } else if (sample.value() < min_cl) {
155 min_cl = sample.value();
156 }
157 ++sample_cnt;
158 }
159
160 return std::isinf(min_cl) ? 0.0 : min_cl;
161}
162
163double FullyMeshedStateMachine::max_channel_load() const
164{
165 assert(N_samples_down > 0);
166 double max_cl = 0.0;
167 std::size_t sample_cnt = 0;
168 for (auto sample : m_channel_loads) {
169 if (sample_cnt >= N_samples_down) {
170 break;
171 } else if (sample.value() > max_cl) {
172 max_cl = sample.value();
173 }
174 ++sample_cnt;
175 }
176
177 return max_cl;
178}
179
180} // namespace dcc
181} // namespace vanetza
STL namespace.