mirror of
https://github.com/BotChain-Robots/firmware.git
synced 2026-07-08 17:47:21 +02:00
Send robot topology to PC
This commit is contained in:
@@ -13,6 +13,8 @@ inline std::unordered_map<int, int> MODULE_TO_NUM_CHANNELS_MAP {{ModuleType_SPLI
|
|||||||
|
|
||||||
#define PC_ADDR 0
|
#define PC_ADDR 0
|
||||||
|
|
||||||
|
#define MAX_WIRED_CONNECTIONS 4
|
||||||
|
|
||||||
#define SERVO_GPIO 1
|
#define SERVO_GPIO 1
|
||||||
|
|
||||||
#define DC_MOTOR_PWM_FWD 1
|
#define DC_MOTOR_PWM_FWD 1
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
idf_component_register(SRCS "MPIMessageBuilder.cpp" "AngleControlMessageBuilder.cpp"
|
idf_component_register(SRCS "MPIMessageBuilder.cpp" "AngleControlMessageBuilder.cpp" "TopologyMessageBuilder.cpp"
|
||||||
INCLUDE_DIRS "include")
|
INCLUDE_DIRS "include")
|
||||||
|
|||||||
37
components/flatbuffers/TopologyMessageBuilder.cpp
Normal file
37
components/flatbuffers/TopologyMessageBuilder.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Created by Johnathon Slightham on 2025-06-30.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TopologyMessageBuilder.h"
|
||||||
|
|
||||||
|
#include "SerializedMessage.h"
|
||||||
|
|
||||||
|
namespace Flatbuffers {
|
||||||
|
SerializedMessage TopologyMessageBuilder::build_topology_message(
|
||||||
|
const uint8_t module_id,
|
||||||
|
const ModuleType module_type,
|
||||||
|
const std::vector<uint8_t>& channel_to_module,
|
||||||
|
const std::vector<int8_t>& orientation_to_module) {
|
||||||
|
builder_.Clear();
|
||||||
|
|
||||||
|
const auto orientation_to_module_vector = builder_.CreateVector(orientation_to_module);
|
||||||
|
const auto channel_to_module_vector = builder_.CreateVector(channel_to_module);
|
||||||
|
|
||||||
|
const auto message = Messaging::CreateTopologyMessage(
|
||||||
|
builder_,
|
||||||
|
module_id,
|
||||||
|
module_type,
|
||||||
|
channel_to_module.size(),
|
||||||
|
channel_to_module_vector,
|
||||||
|
orientation_to_module_vector
|
||||||
|
);
|
||||||
|
|
||||||
|
builder_.Finish(message);
|
||||||
|
|
||||||
|
return {builder_.GetBufferPointer(), builder_.GetSize()};
|
||||||
|
}
|
||||||
|
|
||||||
|
const Messaging::TopologyMessage* TopologyMessageBuilder::parse_topology_message(const uint8_t* buffer) {
|
||||||
|
return flatbuffers::GetRoot<Messaging::TopologyMessage>(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
33
components/flatbuffers/include/TopologyMessageBuilder.h
Normal file
33
components/flatbuffers/include/TopologyMessageBuilder.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// Created by Johnathon Slightham on 2025-06-30.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef TOPOLOGYMESSAGEBUILDER_H
|
||||||
|
#define TOPOLOGYMESSAGEBUILDER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "SerializedMessage.h"
|
||||||
|
#include "flatbuffers_generated/TopologyMessage_generated.h"
|
||||||
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
|
||||||
|
namespace Flatbuffers {
|
||||||
|
class TopologyMessageBuilder {
|
||||||
|
public:
|
||||||
|
TopologyMessageBuilder() : builder_(1024) {}
|
||||||
|
|
||||||
|
SerializedMessage build_topology_message(
|
||||||
|
uint8_t module_id,
|
||||||
|
ModuleType module_type,
|
||||||
|
const std::vector<uint8_t>& channel_to_module,
|
||||||
|
const std::vector<int8_t>& orientation_to_module);
|
||||||
|
|
||||||
|
static const Messaging::TopologyMessage* parse_topology_message(const uint8_t* buffer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
flatbuffers::FlatBufferBuilder builder_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //TOPOLOGYMESSAGEBUILDER_H
|
||||||
4
components/flatbuffers/include/flatbuffers/README.md
Normal file
4
components/flatbuffers/include/flatbuffers/README.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Flatbuffers
|
||||||
|
This folder contains the [Flatbuffer library code](https://github.com/google/flatbuffers/tree/master/include/flatbuffers).
|
||||||
|
It should never be modified, except when we want to bump the version of Flatbuffers we are using.
|
||||||
|
|
||||||
@@ -8,11 +8,14 @@
|
|||||||
|
|
||||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||||
// generated, otherwise it may not be compatible.
|
// generated, otherwise it may not be compatible.
|
||||||
// static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
//static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||||
// FLATBUFFERS_VERSION_MINOR == 2 &&
|
// FLATBUFFERS_VERSION_MINOR == 2 &&
|
||||||
// FLATBUFFERS_VERSION_REVISION == 10,
|
// FLATBUFFERS_VERSION_REVISION == 10,
|
||||||
// "Non-compatible flatbuffers version included");
|
// "Non-compatible flatbuffers version included");
|
||||||
|
|
||||||
|
struct MotorState;
|
||||||
|
struct MotorStateBuilder;
|
||||||
|
|
||||||
struct RobotModule;
|
struct RobotModule;
|
||||||
struct RobotModuleBuilder;
|
struct RobotModuleBuilder;
|
||||||
|
|
||||||
@@ -52,62 +55,178 @@ inline const char *EnumNameModuleType(ModuleType e) {
|
|||||||
return EnumNamesModuleType()[index];
|
return EnumNamesModuleType()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Orientation : int8_t {
|
||||||
|
Orientation_Deg0 = 0,
|
||||||
|
Orientation_Deg90 = 1,
|
||||||
|
Orientation_Deg180 = 2,
|
||||||
|
Orientation_Deg270 = 3,
|
||||||
|
Orientation_MIN = Orientation_Deg0,
|
||||||
|
Orientation_MAX = Orientation_Deg270
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const Orientation (&EnumValuesOrientation())[4] {
|
||||||
|
static const Orientation values[] = {
|
||||||
|
Orientation_Deg0,
|
||||||
|
Orientation_Deg90,
|
||||||
|
Orientation_Deg180,
|
||||||
|
Orientation_Deg270
|
||||||
|
};
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char * const *EnumNamesOrientation() {
|
||||||
|
static const char * const names[5] = {
|
||||||
|
"Deg0",
|
||||||
|
"Deg90",
|
||||||
|
"Deg180",
|
||||||
|
"Deg270",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *EnumNameOrientation(Orientation e) {
|
||||||
|
if (::flatbuffers::IsOutRange(e, Orientation_Deg0, Orientation_Deg270)) return "";
|
||||||
|
const size_t index = static_cast<size_t>(e);
|
||||||
|
return EnumNamesOrientation()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ModuleState : uint8_t {
|
||||||
|
ModuleState_NONE = 0,
|
||||||
|
ModuleState_MotorState = 1,
|
||||||
|
ModuleState_MIN = ModuleState_NONE,
|
||||||
|
ModuleState_MAX = ModuleState_MotorState
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const ModuleState (&EnumValuesModuleState())[2] {
|
||||||
|
static const ModuleState values[] = {
|
||||||
|
ModuleState_NONE,
|
||||||
|
ModuleState_MotorState
|
||||||
|
};
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char * const *EnumNamesModuleState() {
|
||||||
|
static const char * const names[3] = {
|
||||||
|
"NONE",
|
||||||
|
"MotorState",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *EnumNameModuleState(ModuleState e) {
|
||||||
|
if (::flatbuffers::IsOutRange(e, ModuleState_NONE, ModuleState_MotorState)) return "";
|
||||||
|
const size_t index = static_cast<size_t>(e);
|
||||||
|
return EnumNamesModuleState()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> struct ModuleStateTraits {
|
||||||
|
static const ModuleState enum_value = ModuleState_NONE;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct ModuleStateTraits<MotorState> {
|
||||||
|
static const ModuleState enum_value = ModuleState_MotorState;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool VerifyModuleState(::flatbuffers::Verifier &verifier, const void *obj, ModuleState type);
|
||||||
|
bool VerifyModuleStateVector(::flatbuffers::Verifier &verifier, const ::flatbuffers::Vector<::flatbuffers::Offset<void>> *values, const ::flatbuffers::Vector<uint8_t> *types);
|
||||||
|
|
||||||
|
struct MotorState FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||||
|
typedef MotorStateBuilder Builder;
|
||||||
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
|
VT_ANGLE = 4
|
||||||
|
};
|
||||||
|
int32_t angle() const {
|
||||||
|
return GetField<int32_t>(VT_ANGLE, 0);
|
||||||
|
}
|
||||||
|
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||||
|
return VerifyTableStart(verifier) &&
|
||||||
|
VerifyField<int32_t>(verifier, VT_ANGLE, 4) &&
|
||||||
|
verifier.EndTable();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MotorStateBuilder {
|
||||||
|
typedef MotorState Table;
|
||||||
|
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||||
|
::flatbuffers::uoffset_t start_;
|
||||||
|
void add_angle(int32_t angle) {
|
||||||
|
fbb_.AddElement<int32_t>(MotorState::VT_ANGLE, angle, 0);
|
||||||
|
}
|
||||||
|
explicit MotorStateBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
|
: fbb_(_fbb) {
|
||||||
|
start_ = fbb_.StartTable();
|
||||||
|
}
|
||||||
|
::flatbuffers::Offset<MotorState> Finish() {
|
||||||
|
const auto end = fbb_.EndTable(start_);
|
||||||
|
auto o = ::flatbuffers::Offset<MotorState>(end);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ::flatbuffers::Offset<MotorState> CreateMotorState(
|
||||||
|
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
int32_t angle = 0) {
|
||||||
|
MotorStateBuilder builder_(_fbb);
|
||||||
|
builder_.add_angle(angle);
|
||||||
|
return builder_.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
struct RobotModule FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
struct RobotModule FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||||
typedef RobotModuleBuilder Builder;
|
typedef RobotModuleBuilder Builder;
|
||||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_ID = 4,
|
VT_ID = 4,
|
||||||
VT_IP = 6,
|
VT_MODULE_TYPE = 6,
|
||||||
VT_HOSTNAME = 8,
|
VT_CONFIGURATION_TYPE = 8,
|
||||||
VT_MODULE_TYPE = 10,
|
VT_CONFIGURATION = 10
|
||||||
VT_CONNECTED_MODULE_IDS = 12
|
|
||||||
};
|
};
|
||||||
int32_t id() const {
|
uint8_t id() const {
|
||||||
return GetField<int32_t>(VT_ID, 0);
|
return GetField<uint8_t>(VT_ID, 0);
|
||||||
}
|
|
||||||
const ::flatbuffers::String *ip() const {
|
|
||||||
return GetPointer<const ::flatbuffers::String *>(VT_IP);
|
|
||||||
}
|
|
||||||
const ::flatbuffers::String *hostname() const {
|
|
||||||
return GetPointer<const ::flatbuffers::String *>(VT_HOSTNAME);
|
|
||||||
}
|
}
|
||||||
ModuleType module_type() const {
|
ModuleType module_type() const {
|
||||||
return static_cast<ModuleType>(GetField<int8_t>(VT_MODULE_TYPE, 0));
|
return static_cast<ModuleType>(GetField<int8_t>(VT_MODULE_TYPE, 0));
|
||||||
}
|
}
|
||||||
const ::flatbuffers::Vector<int32_t> *connected_module_ids() const {
|
ModuleState configuration_type() const {
|
||||||
return GetPointer<const ::flatbuffers::Vector<int32_t> *>(VT_CONNECTED_MODULE_IDS);
|
return static_cast<ModuleState>(GetField<uint8_t>(VT_CONFIGURATION_TYPE, 0));
|
||||||
|
}
|
||||||
|
const void *configuration() const {
|
||||||
|
return GetPointer<const void *>(VT_CONFIGURATION);
|
||||||
|
}
|
||||||
|
template<typename T> const T *configuration_as() const;
|
||||||
|
const MotorState *configuration_as_MotorState() const {
|
||||||
|
return configuration_type() == ModuleState_MotorState ? static_cast<const MotorState *>(configuration()) : nullptr;
|
||||||
}
|
}
|
||||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyField<int32_t>(verifier, VT_ID, 4) &&
|
VerifyField<uint8_t>(verifier, VT_ID, 1) &&
|
||||||
VerifyOffset(verifier, VT_IP) &&
|
|
||||||
verifier.VerifyString(ip()) &&
|
|
||||||
VerifyOffset(verifier, VT_HOSTNAME) &&
|
|
||||||
verifier.VerifyString(hostname()) &&
|
|
||||||
VerifyField<int8_t>(verifier, VT_MODULE_TYPE, 1) &&
|
VerifyField<int8_t>(verifier, VT_MODULE_TYPE, 1) &&
|
||||||
VerifyOffset(verifier, VT_CONNECTED_MODULE_IDS) &&
|
VerifyField<uint8_t>(verifier, VT_CONFIGURATION_TYPE, 1) &&
|
||||||
verifier.VerifyVector(connected_module_ids()) &&
|
VerifyOffset(verifier, VT_CONFIGURATION) &&
|
||||||
|
VerifyModuleState(verifier, configuration(), configuration_type()) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<> inline const MotorState *RobotModule::configuration_as<MotorState>() const {
|
||||||
|
return configuration_as_MotorState();
|
||||||
|
}
|
||||||
|
|
||||||
struct RobotModuleBuilder {
|
struct RobotModuleBuilder {
|
||||||
typedef RobotModule Table;
|
typedef RobotModule Table;
|
||||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||||
::flatbuffers::uoffset_t start_;
|
::flatbuffers::uoffset_t start_;
|
||||||
void add_id(int32_t id) {
|
void add_id(uint8_t id) {
|
||||||
fbb_.AddElement<int32_t>(RobotModule::VT_ID, id, 0);
|
fbb_.AddElement<uint8_t>(RobotModule::VT_ID, id, 0);
|
||||||
}
|
|
||||||
void add_ip(::flatbuffers::Offset<::flatbuffers::String> ip) {
|
|
||||||
fbb_.AddOffset(RobotModule::VT_IP, ip);
|
|
||||||
}
|
|
||||||
void add_hostname(::flatbuffers::Offset<::flatbuffers::String> hostname) {
|
|
||||||
fbb_.AddOffset(RobotModule::VT_HOSTNAME, hostname);
|
|
||||||
}
|
}
|
||||||
void add_module_type(ModuleType module_type) {
|
void add_module_type(ModuleType module_type) {
|
||||||
fbb_.AddElement<int8_t>(RobotModule::VT_MODULE_TYPE, static_cast<int8_t>(module_type), 0);
|
fbb_.AddElement<int8_t>(RobotModule::VT_MODULE_TYPE, static_cast<int8_t>(module_type), 0);
|
||||||
}
|
}
|
||||||
void add_connected_module_ids(::flatbuffers::Offset<::flatbuffers::Vector<int32_t>> connected_module_ids) {
|
void add_configuration_type(ModuleState configuration_type) {
|
||||||
fbb_.AddOffset(RobotModule::VT_CONNECTED_MODULE_IDS, connected_module_ids);
|
fbb_.AddElement<uint8_t>(RobotModule::VT_CONFIGURATION_TYPE, static_cast<uint8_t>(configuration_type), 0);
|
||||||
|
}
|
||||||
|
void add_configuration(::flatbuffers::Offset<void> configuration) {
|
||||||
|
fbb_.AddOffset(RobotModule::VT_CONFIGURATION, configuration);
|
||||||
}
|
}
|
||||||
explicit RobotModuleBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
explicit RobotModuleBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
@@ -122,37 +241,41 @@ struct RobotModuleBuilder {
|
|||||||
|
|
||||||
inline ::flatbuffers::Offset<RobotModule> CreateRobotModule(
|
inline ::flatbuffers::Offset<RobotModule> CreateRobotModule(
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
int32_t id = 0,
|
uint8_t id = 0,
|
||||||
::flatbuffers::Offset<::flatbuffers::String> ip = 0,
|
|
||||||
::flatbuffers::Offset<::flatbuffers::String> hostname = 0,
|
|
||||||
ModuleType module_type = ModuleType_SPLITTER,
|
ModuleType module_type = ModuleType_SPLITTER,
|
||||||
::flatbuffers::Offset<::flatbuffers::Vector<int32_t>> connected_module_ids = 0) {
|
ModuleState configuration_type = ModuleState_NONE,
|
||||||
|
::flatbuffers::Offset<void> configuration = 0) {
|
||||||
RobotModuleBuilder builder_(_fbb);
|
RobotModuleBuilder builder_(_fbb);
|
||||||
builder_.add_connected_module_ids(connected_module_ids);
|
builder_.add_configuration(configuration);
|
||||||
builder_.add_hostname(hostname);
|
builder_.add_configuration_type(configuration_type);
|
||||||
builder_.add_ip(ip);
|
|
||||||
builder_.add_id(id);
|
|
||||||
builder_.add_module_type(module_type);
|
builder_.add_module_type(module_type);
|
||||||
|
builder_.add_id(id);
|
||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<RobotModule> CreateRobotModuleDirect(
|
inline bool VerifyModuleState(::flatbuffers::Verifier &verifier, const void *obj, ModuleState type) {
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
switch (type) {
|
||||||
int32_t id = 0,
|
case ModuleState_NONE: {
|
||||||
const char *ip = nullptr,
|
return true;
|
||||||
const char *hostname = nullptr,
|
}
|
||||||
ModuleType module_type = ModuleType_SPLITTER,
|
case ModuleState_MotorState: {
|
||||||
const std::vector<int32_t> *connected_module_ids = nullptr) {
|
auto ptr = reinterpret_cast<const MotorState *>(obj);
|
||||||
auto ip__ = ip ? _fbb.CreateString(ip) : 0;
|
return verifier.VerifyTable(ptr);
|
||||||
auto hostname__ = hostname ? _fbb.CreateString(hostname) : 0;
|
}
|
||||||
auto connected_module_ids__ = connected_module_ids ? _fbb.CreateVector<int32_t>(*connected_module_ids) : 0;
|
default: return true;
|
||||||
return CreateRobotModule(
|
}
|
||||||
_fbb,
|
}
|
||||||
id,
|
|
||||||
ip__,
|
inline bool VerifyModuleStateVector(::flatbuffers::Verifier &verifier, const ::flatbuffers::Vector<::flatbuffers::Offset<void>> *values, const ::flatbuffers::Vector<uint8_t> *types) {
|
||||||
hostname__,
|
if (!values || !types) return !values && !types;
|
||||||
module_type,
|
if (values->size() != types->size()) return false;
|
||||||
connected_module_ids__);
|
for (::flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
|
||||||
|
if (!VerifyModuleState(
|
||||||
|
verifier, values->Get(i), types->GetEnum<ModuleState>(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const RobotModule *GetRobotModule(const void *buf) {
|
inline const RobotModule *GetRobotModule(const void *buf) {
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_GENERATED_TOPOLOGYMESSAGE_MESSAGING_H_
|
||||||
|
#define FLATBUFFERS_GENERATED_TOPOLOGYMESSAGE_MESSAGING_H_
|
||||||
|
|
||||||
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
|
||||||
|
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||||
|
// generated, otherwise it may not be compatible.
|
||||||
|
// static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||||
|
// FLATBUFFERS_VERSION_MINOR == 2 &&
|
||||||
|
// FLATBUFFERS_VERSION_REVISION == 10,
|
||||||
|
// "Non-compatible flatbuffers version included");
|
||||||
|
|
||||||
|
#include "RobotModule_generated.h"
|
||||||
|
|
||||||
|
namespace Messaging {
|
||||||
|
|
||||||
|
struct TopologyMessage;
|
||||||
|
struct TopologyMessageBuilder;
|
||||||
|
|
||||||
|
struct TopologyMessage FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||||
|
typedef TopologyMessageBuilder Builder;
|
||||||
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
|
VT_MODULE_ID = 4,
|
||||||
|
VT_MODULE_TYPE = 6,
|
||||||
|
VT_NUM_CHANNELS = 8,
|
||||||
|
VT_CHANNEL_TO_MODULE = 10,
|
||||||
|
VT_CHANNEL_TO_ORIENTATION = 12
|
||||||
|
};
|
||||||
|
uint8_t module_id() const {
|
||||||
|
return GetField<uint8_t>(VT_MODULE_ID, 0);
|
||||||
|
}
|
||||||
|
ModuleType module_type() const {
|
||||||
|
return static_cast<ModuleType>(GetField<int8_t>(VT_MODULE_TYPE, 0));
|
||||||
|
}
|
||||||
|
uint8_t num_channels() const {
|
||||||
|
return GetField<uint8_t>(VT_NUM_CHANNELS, 0);
|
||||||
|
}
|
||||||
|
const ::flatbuffers::Vector<uint8_t> *channel_to_module() const {
|
||||||
|
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_CHANNEL_TO_MODULE);
|
||||||
|
}
|
||||||
|
const ::flatbuffers::Vector<int8_t> *channel_to_orientation() const {
|
||||||
|
return GetPointer<const ::flatbuffers::Vector<int8_t> *>(VT_CHANNEL_TO_ORIENTATION);
|
||||||
|
}
|
||||||
|
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||||
|
return VerifyTableStart(verifier) &&
|
||||||
|
VerifyField<uint8_t>(verifier, VT_MODULE_ID, 1) &&
|
||||||
|
VerifyField<int8_t>(verifier, VT_MODULE_TYPE, 1) &&
|
||||||
|
VerifyField<uint8_t>(verifier, VT_NUM_CHANNELS, 1) &&
|
||||||
|
VerifyOffset(verifier, VT_CHANNEL_TO_MODULE) &&
|
||||||
|
verifier.VerifyVector(channel_to_module()) &&
|
||||||
|
VerifyOffset(verifier, VT_CHANNEL_TO_ORIENTATION) &&
|
||||||
|
verifier.VerifyVector(channel_to_orientation()) &&
|
||||||
|
verifier.EndTable();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TopologyMessageBuilder {
|
||||||
|
typedef TopologyMessage Table;
|
||||||
|
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||||
|
::flatbuffers::uoffset_t start_;
|
||||||
|
void add_module_id(uint8_t module_id) {
|
||||||
|
fbb_.AddElement<uint8_t>(TopologyMessage::VT_MODULE_ID, module_id, 0);
|
||||||
|
}
|
||||||
|
void add_module_type(ModuleType module_type) {
|
||||||
|
fbb_.AddElement<int8_t>(TopologyMessage::VT_MODULE_TYPE, static_cast<int8_t>(module_type), 0);
|
||||||
|
}
|
||||||
|
void add_num_channels(uint8_t num_channels) {
|
||||||
|
fbb_.AddElement<uint8_t>(TopologyMessage::VT_NUM_CHANNELS, num_channels, 0);
|
||||||
|
}
|
||||||
|
void add_channel_to_module(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> channel_to_module) {
|
||||||
|
fbb_.AddOffset(TopologyMessage::VT_CHANNEL_TO_MODULE, channel_to_module);
|
||||||
|
}
|
||||||
|
void add_channel_to_orientation(::flatbuffers::Offset<::flatbuffers::Vector<int8_t>> channel_to_orientation) {
|
||||||
|
fbb_.AddOffset(TopologyMessage::VT_CHANNEL_TO_ORIENTATION, channel_to_orientation);
|
||||||
|
}
|
||||||
|
explicit TopologyMessageBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
|
: fbb_(_fbb) {
|
||||||
|
start_ = fbb_.StartTable();
|
||||||
|
}
|
||||||
|
::flatbuffers::Offset<TopologyMessage> Finish() {
|
||||||
|
const auto end = fbb_.EndTable(start_);
|
||||||
|
auto o = ::flatbuffers::Offset<TopologyMessage>(end);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ::flatbuffers::Offset<TopologyMessage> CreateTopologyMessage(
|
||||||
|
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
uint8_t module_id = 0,
|
||||||
|
ModuleType module_type = ModuleType_SPLITTER,
|
||||||
|
uint8_t num_channels = 0,
|
||||||
|
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> channel_to_module = 0,
|
||||||
|
::flatbuffers::Offset<::flatbuffers::Vector<int8_t>> channel_to_orientation = 0) {
|
||||||
|
TopologyMessageBuilder builder_(_fbb);
|
||||||
|
builder_.add_channel_to_orientation(channel_to_orientation);
|
||||||
|
builder_.add_channel_to_module(channel_to_module);
|
||||||
|
builder_.add_num_channels(num_channels);
|
||||||
|
builder_.add_module_type(module_type);
|
||||||
|
builder_.add_module_id(module_id);
|
||||||
|
return builder_.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ::flatbuffers::Offset<TopologyMessage> CreateTopologyMessageDirect(
|
||||||
|
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
uint8_t module_id = 0,
|
||||||
|
ModuleType module_type = ModuleType_SPLITTER,
|
||||||
|
uint8_t num_channels = 0,
|
||||||
|
const std::vector<uint8_t> *channel_to_module = nullptr,
|
||||||
|
const std::vector<int8_t> *channel_to_orientation = nullptr) {
|
||||||
|
auto channel_to_module__ = channel_to_module ? _fbb.CreateVector<uint8_t>(*channel_to_module) : 0;
|
||||||
|
auto channel_to_orientation__ = channel_to_orientation ? _fbb.CreateVector<int8_t>(*channel_to_orientation) : 0;
|
||||||
|
return Messaging::CreateTopologyMessage(
|
||||||
|
_fbb,
|
||||||
|
module_id,
|
||||||
|
module_type,
|
||||||
|
num_channels,
|
||||||
|
channel_to_module__,
|
||||||
|
channel_to_orientation__);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Messaging::TopologyMessage *GetTopologyMessage(const void *buf) {
|
||||||
|
return ::flatbuffers::GetRoot<Messaging::TopologyMessage>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Messaging::TopologyMessage *GetSizePrefixedTopologyMessage(const void *buf) {
|
||||||
|
return ::flatbuffers::GetSizePrefixedRoot<Messaging::TopologyMessage>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool VerifyTopologyMessageBuffer(
|
||||||
|
::flatbuffers::Verifier &verifier) {
|
||||||
|
return verifier.VerifyBuffer<Messaging::TopologyMessage>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool VerifySizePrefixedTopologyMessageBuffer(
|
||||||
|
::flatbuffers::Verifier &verifier) {
|
||||||
|
return verifier.VerifySizePrefixedBuffer<Messaging::TopologyMessage>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FinishTopologyMessageBuffer(
|
||||||
|
::flatbuffers::FlatBufferBuilder &fbb,
|
||||||
|
::flatbuffers::Offset<Messaging::TopologyMessage> root) {
|
||||||
|
fbb.Finish(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FinishSizePrefixedTopologyMessageBuffer(
|
||||||
|
::flatbuffers::FlatBufferBuilder &fbb,
|
||||||
|
::flatbuffers::Offset<Messaging::TopologyMessage> root) {
|
||||||
|
fbb.FinishSizePrefixed(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Messaging
|
||||||
|
|
||||||
|
#endif // FLATBUFFERS_GENERATED_TOPOLOGYMESSAGE_MESSAGING_H_
|
||||||
@@ -117,3 +117,32 @@ void CommunicationRouter::route(uint8_t* buffer, const size_t length) const {
|
|||||||
this->m_data_link_manager->send(mpi_message->destination(), buffer, length, FrameType::MOTOR_TYPE, 0);
|
this->m_data_link_manager->send(mpi_message->destination(), buffer, length, FrameType::MOTOR_TYPE, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<std::vector<uint8_t>, std::vector<Orientation>> CommunicationRouter::get_physically_connected_modules() const {
|
||||||
|
std::vector<RIPRow_public> table;
|
||||||
|
table.resize(RIP_MAX_ROUTES);
|
||||||
|
size_t table_size = RIP_MAX_ROUTES * sizeof(RIPRow_public);
|
||||||
|
m_data_link_manager->get_routing_table(table.data(), &table_size);
|
||||||
|
|
||||||
|
std::vector<uint8_t> connected_module_ids;
|
||||||
|
std::vector<Orientation> connected_module_orientations;
|
||||||
|
connected_module_ids.resize(MAX_WIRED_CONNECTIONS);
|
||||||
|
connected_module_orientations.resize(MAX_WIRED_CONNECTIONS);
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_WIRED_CONNECTIONS; i++) {
|
||||||
|
connected_module_ids[i] = 0; // this is not the PC ID here, marking as nc.
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < table_size; i++) {
|
||||||
|
if (table[i].info.hops == 1 && table[i].channel < MAX_WIRED_CONNECTIONS) {
|
||||||
|
connected_module_ids[table[i].channel] = table[i].info.board_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: get orientation (temporary)
|
||||||
|
for (int i = 0; i < MAX_WIRED_CONNECTIONS; i++) {
|
||||||
|
connected_module_orientations[i] = Orientation_Deg0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { connected_module_ids, connected_module_orientations };
|
||||||
|
}
|
||||||
|
|||||||
@@ -64,3 +64,7 @@ void MessagingInterface::checkOrInsertTag(const uint8_t tag) {
|
|||||||
}
|
}
|
||||||
xSemaphoreGive(m_map_semaphore);
|
xSemaphoreGive(m_map_semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<std::vector<uint8_t>, std::vector<Orientation>> MessagingInterface::get_physically_connected_modules() const {
|
||||||
|
return m_router->get_physically_connected_modules();
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,7 +18,9 @@
|
|||||||
#include "constants/tcp.h"
|
#include "constants/tcp.h"
|
||||||
#include "constants/module.h"
|
#include "constants/module.h"
|
||||||
|
|
||||||
#include"PtrQueue.h"
|
#include "flatbuffers_generated/TopologyMessage_generated.h"
|
||||||
|
|
||||||
|
#include "PtrQueue.h"
|
||||||
|
|
||||||
class CommunicationRouter {
|
class CommunicationRouter {
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ public:
|
|||||||
|
|
||||||
const auto num_channels = MODULE_TO_NUM_CHANNELS_MAP[ConfigManager::get_module_type()];
|
const auto num_channels = MODULE_TO_NUM_CHANNELS_MAP[ConfigManager::get_module_type()];
|
||||||
this->m_link_layer_threads.resize(num_channels);
|
this->m_link_layer_threads.resize(num_channels);
|
||||||
for (uint8_t i = 0; i < num_channels; i++) {
|
for (int i = 0; i < num_channels; i++) {
|
||||||
auto *params = new link_layer_thread_params(this, i);
|
auto *params = new link_layer_thread_params(this, i);
|
||||||
xTaskCreate(link_layer_thread, "communication_router_rmt", 4096, params, 3, &this->m_link_layer_threads[i]);
|
xTaskCreate(link_layer_thread, "communication_router_rmt", 4096, params, 3, &this->m_link_layer_threads[i]);
|
||||||
}
|
}
|
||||||
@@ -61,13 +63,16 @@ public:
|
|||||||
|
|
||||||
void route(uint8_t *buffer, size_t length) const;
|
void route(uint8_t *buffer, size_t length) const;
|
||||||
|
|
||||||
|
// pair of <module, mount orientation>
|
||||||
|
std::pair<std::vector<uint8_t>, std::vector<Orientation>> get_physically_connected_modules() const;
|
||||||
|
|
||||||
// todo: does this really need to be here (so i can access from thread)?
|
// todo: does this really need to be here (so i can access from thread)?
|
||||||
std::shared_ptr<PtrQueue<std::vector<uint8_t>>> m_tcp_rx_queue;
|
std::shared_ptr<PtrQueue<std::vector<uint8_t>>> m_tcp_rx_queue;
|
||||||
std::function<void(char*, int)> m_rx_callback;
|
std::function<void(char*, int)> m_rx_callback;
|
||||||
private:
|
private:
|
||||||
TaskHandle_t m_router_thread;
|
TaskHandle_t m_router_thread = nullptr;
|
||||||
std::vector<TaskHandle_t> m_link_layer_threads;
|
std::vector<TaskHandle_t> m_link_layer_threads;
|
||||||
std::unique_ptr<TCPServer> m_tcp_server;
|
std::unique_ptr<TCPServer> m_tcp_server; // todo: dependency injection
|
||||||
std::unique_ptr<DataLinkManager> m_data_link_manager;
|
std::unique_ptr<DataLinkManager> m_data_link_manager;
|
||||||
std::unique_ptr<WifiManager> m_pc_connection; // todo: change to dependency inject
|
std::unique_ptr<WifiManager> m_pc_connection; // todo: change to dependency inject
|
||||||
uint8_t m_leader = 0;
|
uint8_t m_leader = 0;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public:
|
|||||||
int broadcast(char* buffer, int size, int root, bool durable);
|
int broadcast(char* buffer, int size, int root, bool durable);
|
||||||
int recv(char* buffer, int size, int source, int tag);
|
int recv(char* buffer, int size, int source, int tag);
|
||||||
int sendrecv(char* send_buffer, int send_size, int dest, int send_tag, char* recv_buffer, int recv_size, int recv_tag);
|
int sendrecv(char* send_buffer, int send_size, int dest, int send_tag, char* recv_buffer, int recv_size, int recv_tag);
|
||||||
|
std::pair<std::vector<uint8_t>, std::vector<Orientation>> get_physically_connected_modules() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleRecv(const char* recv_buffer, int recv_size);
|
void handleRecv(const char* recv_buffer, int recv_size);
|
||||||
|
|||||||
@@ -7,19 +7,39 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <MessagingInterface.h>
|
#include <MessagingInterface.h>
|
||||||
|
#include <TopologyMessageBuilder.h>
|
||||||
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
#define ACTUATOR_CMD_TAG 5
|
#define ACTUATOR_CMD_TAG 5
|
||||||
|
#define TOPOLOGY_CMD_TAG 6
|
||||||
|
|
||||||
[[noreturn]] void LoopManager::control_loop() {
|
#define METADATA_PERIOD_MS 5000
|
||||||
const auto messaging_interface = std::make_unique<MessagingInterface>(std::make_unique<WifiManager>());
|
|
||||||
|
|
||||||
|
[[noreturn]] void LoopManager::control_loop() const {
|
||||||
const auto actuator = ActuatorFactory::create_actuator(ConfigManager::get_module_type());
|
const auto actuator = ActuatorFactory::create_actuator(ConfigManager::get_module_type());
|
||||||
|
|
||||||
uint8_t buffer[512];
|
uint8_t buffer[512];
|
||||||
while (true) {
|
while (true) {
|
||||||
messaging_interface->recv(reinterpret_cast<char *>(buffer), 512, PC_ADDR, ACTUATOR_CMD_TAG);
|
m_messaging_interface->recv(reinterpret_cast<char *>(buffer), 512, PC_ADDR, ACTUATOR_CMD_TAG);
|
||||||
actuator->actuate(buffer);
|
actuator->actuate(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void LoopManager::metadata_tx_loop(char * args) {
|
||||||
|
const auto that = reinterpret_cast<LoopManager *>(args);
|
||||||
|
const auto topology_message_builder = std::make_unique<Flatbuffers::TopologyMessageBuilder>();
|
||||||
|
while (true) {
|
||||||
|
const auto [module_ids, orientations] = that->m_messaging_interface->get_physically_connected_modules();
|
||||||
|
// todo: this is awful, we can't cast from a vector of orientation to int.... :(
|
||||||
|
std::vector<int8_t> casted_orientations{};
|
||||||
|
casted_orientations.reserve(orientations.size());
|
||||||
|
for (const auto orientation : orientations) {
|
||||||
|
casted_orientations.emplace_back(orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto [data, size] = topology_message_builder->build_topology_message(ConfigManager::get_module_id(), ConfigManager::get_module_type(), module_ids, casted_orientations);
|
||||||
|
that->m_messaging_interface->send(static_cast<char *>(data), size, PC_ADDR, TOPOLOGY_CMD_TAG, true);
|
||||||
|
vTaskDelay(METADATA_PERIOD_MS / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,12 +5,21 @@
|
|||||||
#ifndef LOOPMANAGER_H
|
#ifndef LOOPMANAGER_H
|
||||||
#define LOOPMANAGER_H
|
#define LOOPMANAGER_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <MessagingInterface.h>
|
||||||
|
|
||||||
#include "control/IActuator.h"
|
#include "control/IActuator.h"
|
||||||
#include "control/ActuatorFactory.h"
|
#include "control/ActuatorFactory.h"
|
||||||
|
|
||||||
class LoopManager {
|
class LoopManager {
|
||||||
public:
|
public:
|
||||||
[[noreturn]] static void control_loop();
|
LoopManager() : m_messaging_interface(std::make_unique<MessagingInterface>(std::make_unique<WifiManager>())) {}
|
||||||
|
[[noreturn]] void control_loop() const;
|
||||||
|
[[noreturn]] static void metadata_tx_loop(char * args);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<MessagingInterface> m_messaging_interface;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
@@ -17,5 +17,8 @@ extern "C" [[noreturn]] void app_main(void) {
|
|||||||
|
|
||||||
ConfigManager::init_config();
|
ConfigManager::init_config();
|
||||||
|
|
||||||
LoopManager::control_loop();
|
|
||||||
|
const auto loop_manager = std::make_unique<LoopManager>();
|
||||||
|
xTaskCreate(reinterpret_cast<TaskFunction_t>(LoopManager::metadata_tx_loop), "metadata_tx", 3096, loop_manager.get(), 3, nullptr);
|
||||||
|
loop_manager->control_loop();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user