Keep the colleague's microbu-esp32c5 tree in this repository
obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but that tree was gitignored, so a clone of this repository could not build the firmware it ships. It is now committed here as ordinary files in its own folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP bridge's signature verification (--trust) used on the bench. Nothing is fetched from or pushed to the colleague's repository; this repository and its remotes carry everything. The folder's own .gitignore keeps build output, downloaded components and private key material out, as it did there; the committed file set is identical to that repository's tracked files. The ESP32-C5 is still flashed from obu-firmware/, which only takes vanetza-idf from microbu-esp32c5/, so the two stay separate folders. FLASHING.md says how to take a newer version of the colleague's tree (copy it over the folder, rebuild, test, commit).
This commit is contained in:
+181
@@ -0,0 +1,181 @@
|
||||
#include "channel_load.hpp"
|
||||
#include "fully_meshed_state_machine.hpp"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace dcc
|
||||
{
|
||||
|
||||
static constexpr std::size_t N_samples_up = std::chrono::seconds(1) / NDL_minDccSampling;
|
||||
static constexpr std::size_t N_samples_down = std::chrono::seconds(5) / NDL_minDccSampling;
|
||||
|
||||
static constexpr double NDL_minChannelLoad = 0.19;
|
||||
static constexpr double NDL_maxChannelLoad = 0.59;
|
||||
|
||||
Clock::duration Relaxed::transmission_interval() const
|
||||
{
|
||||
return std::chrono::milliseconds(60);
|
||||
}
|
||||
|
||||
const char* Relaxed::name() const
|
||||
{
|
||||
return "Relaxed";
|
||||
}
|
||||
|
||||
Clock::duration Restrictive::transmission_interval() const
|
||||
{
|
||||
return std::chrono::milliseconds(460);
|
||||
}
|
||||
|
||||
const char* Restrictive::name() const
|
||||
{
|
||||
return "Restrictive";
|
||||
}
|
||||
|
||||
const std::size_t Active::sc_substates = 5;
|
||||
|
||||
Active::Active() : m_substate(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Active::update(double min_cl, double max_cl)
|
||||
{
|
||||
assert(min_cl <= max_cl);
|
||||
|
||||
static const std::array<double, sc_substates> channel_loads {{
|
||||
0.27, 0.35, 0.43, 0.51, 0.59
|
||||
}};
|
||||
|
||||
auto state_up_it = std::upper_bound(channel_loads.begin(), channel_loads.end(), min_cl);
|
||||
auto state_up = std::distance(channel_loads.begin(), state_up_it);
|
||||
|
||||
auto state_down_it = std::upper_bound(channel_loads.begin(), channel_loads.end(), max_cl);
|
||||
auto state_down = std::distance(channel_loads.begin(), state_down_it);
|
||||
|
||||
m_substate = std::max(state_up, state_down);
|
||||
m_substate = std::min(sc_substates - 1, m_substate);
|
||||
assert(m_substate < sc_substates);
|
||||
}
|
||||
|
||||
Clock::duration Active::transmission_interval() const
|
||||
{
|
||||
static const std::array<Clock::duration, sc_substates> tx_intervals {{
|
||||
std::chrono::milliseconds(100),
|
||||
std::chrono::milliseconds(180),
|
||||
std::chrono::milliseconds(260),
|
||||
std::chrono::milliseconds(340),
|
||||
std::chrono::milliseconds(420),
|
||||
}};
|
||||
|
||||
const std::size_t index = std::min(tx_intervals.size() - 1, m_substate);
|
||||
return tx_intervals[index];
|
||||
}
|
||||
|
||||
const char* Active::name() const
|
||||
{
|
||||
static const std::array<const char*, sc_substates> names {{
|
||||
"Active 1",
|
||||
"Active 2",
|
||||
"Active 3",
|
||||
"Active 4",
|
||||
"Active 5"
|
||||
}};
|
||||
|
||||
assert(m_substate < sc_substates);
|
||||
return names[m_substate];
|
||||
}
|
||||
|
||||
FullyMeshedStateMachine::FullyMeshedStateMachine() :
|
||||
m_state(&m_relaxed),
|
||||
m_channel_loads(std::max(N_samples_up, N_samples_down))
|
||||
{
|
||||
}
|
||||
|
||||
FullyMeshedStateMachine::~FullyMeshedStateMachine()
|
||||
{
|
||||
}
|
||||
|
||||
void FullyMeshedStateMachine::update(ChannelLoad cl)
|
||||
{
|
||||
m_channel_loads.push_front(cl);
|
||||
|
||||
if (m_state == &m_relaxed) {
|
||||
if (min_channel_load() >= NDL_minChannelLoad) {
|
||||
m_state = &m_active;
|
||||
m_active.update(min_channel_load(), max_channel_load());
|
||||
}
|
||||
} else if (m_state == &m_restrictive) {
|
||||
if (max_channel_load() < NDL_maxChannelLoad) {
|
||||
m_state = &m_active;
|
||||
m_active.update(min_channel_load(), max_channel_load());
|
||||
}
|
||||
} else {
|
||||
if (max_channel_load() < NDL_minChannelLoad) {
|
||||
m_state = &m_relaxed;
|
||||
} else if (min_channel_load() >= NDL_maxChannelLoad) {
|
||||
m_state = &m_restrictive;
|
||||
} else {
|
||||
m_state = &m_active;
|
||||
m_active.update(min_channel_load(), max_channel_load());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double FullyMeshedStateMachine::message_rate() const
|
||||
{
|
||||
std::chrono::duration<double> one_sec = std::chrono::seconds(1);
|
||||
return one_sec / transmission_interval();
|
||||
}
|
||||
|
||||
Clock::duration FullyMeshedStateMachine::transmission_interval() const
|
||||
{
|
||||
return m_state->transmission_interval();
|
||||
}
|
||||
|
||||
const State& FullyMeshedStateMachine::state() const
|
||||
{
|
||||
assert(m_state != nullptr);
|
||||
return *m_state;
|
||||
}
|
||||
|
||||
double FullyMeshedStateMachine::min_channel_load() const
|
||||
{
|
||||
assert(N_samples_up > 0);
|
||||
double min_cl = std::numeric_limits<double>::infinity();
|
||||
std::size_t sample_cnt = 0;
|
||||
for (auto sample : m_channel_loads) {
|
||||
if (sample_cnt >= N_samples_up) {
|
||||
break;
|
||||
} else if (sample.value() < min_cl) {
|
||||
min_cl = sample.value();
|
||||
}
|
||||
++sample_cnt;
|
||||
}
|
||||
|
||||
return std::isinf(min_cl) ? 0.0 : min_cl;
|
||||
}
|
||||
|
||||
double FullyMeshedStateMachine::max_channel_load() const
|
||||
{
|
||||
assert(N_samples_down > 0);
|
||||
double max_cl = 0.0;
|
||||
std::size_t sample_cnt = 0;
|
||||
for (auto sample : m_channel_loads) {
|
||||
if (sample_cnt >= N_samples_down) {
|
||||
break;
|
||||
} else if (sample.value() > max_cl) {
|
||||
max_cl = sample.value();
|
||||
}
|
||||
++sample_cnt;
|
||||
}
|
||||
|
||||
return max_cl;
|
||||
}
|
||||
|
||||
} // namespace dcc
|
||||
} // namespace vanetza
|
||||
Reference in New Issue
Block a user