XNSim/XNCore/XNDDSInterface.h

401 lines
13 KiB
C
Raw Permalink Normal View History

2025-04-28 12:25:20 +08:00
#pragma once
2025-05-22 08:53:29 +08:00
#include "XNFramework.h"
#include "XNDDSManager.h"
#include "XNByteArray.h"
#include "XNTypeTraits.h"
#include <stdexcept>
2025-05-19 09:49:54 +08:00
// 定义UDP包的最大大小
constexpr size_t MAX_UDP_PACKET_SIZE = 40000;
class XNDDSInterface
2025-04-28 12:25:20 +08:00
{
public:
2025-05-19 09:49:54 +08:00
XNDDSInterface() = default;
virtual ~XNDDSInterface() = default;
2025-04-28 12:25:20 +08:00
public:
/**
* @brief
* @param framework:
*/
virtual void Initialize(XNFrameworkPtr framework, uint32_t modelID, uint32_t DDS_type) = 0;
/**
* @brief UDP包
* @return
*/
XNByteArray getUDPPackage();
/**
* @brief UDP包设置数据
* @param package: UDP包
*/
void setDataByUDPPackage(const XNByteArray &package);
/**
2025-05-22 08:53:29 +08:00
* @brief
* @param varNames:
* @return:
*/
std::unordered_map<std::string, std::string>
getStringData(const std::vector<std::string> &varNames);
2025-05-22 08:53:29 +08:00
/**
* @brief
* @param data:
*/
void setDataByString(const std::unordered_map<std::string, std::string> &data);
2025-05-19 09:49:54 +08:00
protected:
/**
* @brief
* @param data:
* @return
*/
template <typename T>
XNByteArray getByteArray(const eprosima::fastcdr::optional<T> &data)
{
XNByteArray result(getTypeSize<T>());
2025-05-19 09:49:54 +08:00
if constexpr (std::is_arithmetic_v<T>) {
if (data) {
std::memcpy(result.data(), &data.value(), sizeof(T));
2025-05-19 09:49:54 +08:00
} else {
T zero = 0;
std::memcpy(result.data(), &zero, sizeof(T));
2025-05-19 09:49:54 +08:00
}
} else if constexpr (is_std_array_v<T>) {
if (data) {
return getByteArrayFromStdArray(data.value());
} else {
T zero = {};
return getByteArrayFromStdArray(zero);
2025-04-28 12:25:20 +08:00
}
} else {
static_assert(std::is_arithmetic_v<T> || is_std_array_v<T>,
"T 必须是算术类型或std::array类型详见XNDDSInterface.cppline 78");
2025-04-28 12:25:20 +08:00
}
2025-05-19 09:49:54 +08:00
return result;
2025-04-28 12:25:20 +08:00
}
/**
* @brief
* @param data:
* @param byteArray:
*/
2025-05-20 15:39:40 +08:00
template <typename T>
void setByteArray(eprosima::fastcdr::optional<T> &data, const XNByteArray &byteArray,
uint32_t &pos)
2025-05-20 15:39:40 +08:00
{
uint32_t thisSize = getTypeSize<T>();
XNByteArray thisArray(thisSize);
if (pos + thisSize > byteArray.size()) {
2025-05-20 15:39:40 +08:00
return;
}
std::memcpy(thisArray.data(), byteArray.data() + pos, thisSize);
pos += thisSize;
2025-05-20 15:39:40 +08:00
if constexpr (std::is_arithmetic_v<T>) {
T temp;
std::memcpy(&temp, thisArray.data(), sizeof(T));
data = temp;
2025-05-20 15:39:40 +08:00
} else if constexpr (is_std_array_v<T>) {
if (!data) {
data = T{};
}
setByteArrayFromStdArray(data.value(), thisArray);
} else {
static_assert(std::is_arithmetic_v<T> || is_std_array_v<T>,
"T 必须是算术类型或std::array类型详见XNDDSInterface.cppline 112");
}
}
/**
* @brief
* @param data:
* @return
*/
template <typename T, std::size_t N>
XNByteArray getByteArrayFromStdArray(const std::array<T, N> &data)
{
XNByteArray result(getTypeSize<T>() * N);
for (std::size_t i = 0; i < N; ++i) {
if constexpr (std::is_arithmetic_v<T>) {
std::memcpy(result.data() + i * getTypeSize<T>(), &data[i], getTypeSize<T>());
} else if constexpr (is_std_array_v<T>) {
XNByteArray subArray = getByteArrayFromStdArray(data[i]);
std::memcpy(result.data() + i * getTypeSize<T>(), subArray.data(),
getTypeSize<T>());
} else {
static_assert(std::is_arithmetic_v<T> || is_std_array_v<T>,
"T 必须是算术类型或std::array类型详见XNDDSInterface.cppline 135");
2025-05-20 15:39:40 +08:00
}
}
return result;
2025-05-20 15:39:40 +08:00
}
/**
* @brief
* @param data:
* @param byteArray:
*/
2025-05-20 15:39:40 +08:00
template <typename T, std::size_t N>
void setByteArrayFromStdArray(std::array<T, N> &data, const XNByteArray &byteArray)
2025-05-20 15:39:40 +08:00
{
if (byteArray.size() < getTypeSize<T>() * N)
2025-05-20 15:39:40 +08:00
return;
for (std::size_t i = 0; i < N; ++i) {
if constexpr (std::is_arithmetic_v<T>) {
std::memcpy(&data[i], byteArray.data() + i * getTypeSize<T>(), getTypeSize<T>());
} else if constexpr (is_std_array_v<T>) {
XNByteArray subArray(byteArray.data() + i * getTypeSize<T>(), getTypeSize<T>());
setByteArrayFromStdArray(data[i], subArray);
} else {
static_assert(std::is_arithmetic_v<T> || is_std_array_v<T>,
"T 必须是算术类型或std::array类型详见XNDDSInterface.cppline 160");
2025-05-20 15:39:40 +08:00
}
}
}
/**
* @brief JSON前端
* @param data:
* @return:
*/
2025-05-20 15:39:40 +08:00
template <typename T>
std::string getString(const eprosima::fastcdr::optional<T> &data)
2025-05-20 15:39:40 +08:00
{
if constexpr (std::is_arithmetic_v<T>) {
if (data) {
return std::to_string(data.value());
} else {
return "Unknown";
2025-05-20 15:39:40 +08:00
}
2025-05-22 08:53:29 +08:00
} else if constexpr (is_std_array_v<T>) {
2025-05-20 15:39:40 +08:00
if (data) {
return getStringFromStdArray(data.value());
} else {
T zero = {};
return getStringFromStdArray(zero);
}
} else {
static_assert(std::is_arithmetic_v<T> || is_std_array_v<T>,
"T 必须是算术类型或std::array类型详见XNDDSInterface.cppline 188");
2025-05-20 15:39:40 +08:00
}
return std::string();
}
2025-05-22 08:53:29 +08:00
/**
* @brief JSON前端
* @param data:
* @param value:
*/
template <typename T>
void setDataFromString(eprosima::fastcdr::optional<T> &data, const std::string &value)
{
if constexpr (std::is_arithmetic_v<T>) {
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>) {
data = std::stod(value);
} else {
data = std::stoll(value);
}
} else if constexpr (is_std_array_v<T>) {
// 解析输入字符串
std::stringstream ss(value);
std::string item;
std::vector<std::string> items;
while (std::getline(ss, item, ',')) {
items.push_back(item);
}
T temp;
setStdArrayFromString(temp, items, 0);
data = temp;
} else {
static_assert(std::is_arithmetic_v<T> || is_std_array_v<T>,
"T 必须是算术类型或std::array类型详见XNDDSInterface.cppline 220");
2025-05-22 08:53:29 +08:00
}
}
/**
* @brief JSON前端
* @param data:
* @return:
*/
2025-05-20 15:39:40 +08:00
template <typename T, std::size_t N>
std::string getStringFromStdArray(const std::array<T, N> &data)
2025-05-20 15:39:40 +08:00
{
std::stringstream ss;
for (std::size_t i = 0; i < N; ++i) {
if (i > 0)
ss << ",";
if constexpr (std::is_arithmetic_v<T>) {
ss << data[i];
} else if constexpr (is_std_array_v<T>) {
2025-05-20 15:39:40 +08:00
ss << getStringFromStdArray(data[i]);
} else {
static_assert(std::is_arithmetic_v<T> || is_std_array_v<T>,
"T 必须是算术类型或std::array类型详见XNDDSInterface.cppline 243");
2025-05-20 15:39:40 +08:00
}
}
return ss.str();
}
/**
2025-05-22 08:53:29 +08:00
* @brief JSON前端
* @param data:
* @param value: "数字,数字,..."
* @param start_pos:
* @return
* @throw std::runtime_error:
*/
2025-05-22 08:53:29 +08:00
template <typename T, std::size_t N>
size_t setStdArrayFromString(std::array<T, N> &data, const std::vector<std::string> &value,
size_t start_pos = 0)
{
// 递归处理每个元素
for (std::size_t i = 0; i < N; ++i) {
try {
if constexpr (std::is_arithmetic_v<T>) {
// 对于基本类型,直接转换
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>) {
data[i] = static_cast<T>(std::stod(value[start_pos + i]));
} else {
data[i] = static_cast<T>(std::stoll(value[start_pos + i]));
}
} else if constexpr (is_std_array_v<T>) {
// 对于嵌套数组,递归处理
start_pos = setStdArrayFromString(data[i], value, start_pos + i);
} else {
static_assert(
std::is_arithmetic_v<T> || is_std_array_v<T>,
"T 必须是算术类型或std::array类型详见XNDDSInterface.cppline 275");
2025-05-22 08:53:29 +08:00
}
} catch (const std::exception &e) {
throw std::runtime_error("无法解析第 " + std::to_string(i)
+ " 个元素: " + e.what());
2025-05-22 08:53:29 +08:00
}
}
return start_pos + N;
}
template <typename T1, typename T2>
void assign_value_get(const eprosima::fastcdr::optional<T1> &data, T2 &model_data)
2025-05-22 08:53:29 +08:00
{
if (data) {
auto temp = data.value();
if constexpr (std::is_arithmetic_v<T1>) {
static_assert(std::is_arithmetic_v<T2>,
"模板参数T2必须是算术类型详见XNDDSInterface.cppline 293");
static_assert(std::is_convertible_v<T1, T2>,
"模板参数T1必须可以转换为T2类型详见XNDDSInterface.cppline 295");
2025-05-22 08:53:29 +08:00
model_data = temp;
} else if constexpr (is_std_array_v<T1>) {
size_t arraySize = array_size_v<T1>;
for (size_t i = 0; i < arraySize; ++i) {
auto temp2 = temp[i];
using array_type = typename T1::value_type;
if constexpr (std::is_arithmetic_v<array_type>) {
2025-05-22 08:53:29 +08:00
model_data[i] = temp2;
} else if constexpr (is_std_array_v<array_type>) {
size_t arraySize2 = array_size_v<array_type>;
using sub_array_type = typename array_type::value_type;
if constexpr (std::is_arithmetic_v<sub_array_type>) {
for (size_t j = 0; j < arraySize2; ++j) {
model_data[i][j] = temp2[j];
}
} else {
static_assert(std::is_arithmetic_v<sub_array_type>,
"模板参数T1是std::"
"array类型时它的数组嵌套不能超过两层详见XNDDSInterfac"
"e.cppline 313");
2025-05-22 08:53:29 +08:00
}
} else {
static_assert(
std::is_arithmetic_v<array_type> || is_std_array_v<array_type>,
"模板参数T1是std::array类型时它的value_"
"type必须是算术类型或std::array类型详见XNDDSInterface.cppline 320");
2025-05-22 08:53:29 +08:00
}
}
} else {
static_assert(
std::is_arithmetic_v<T1> || is_std_array_v<T1>,
"模板参数T1必须是算术类型或std::array类型详见XNDDSInterface.cppline 326");
2025-05-22 08:53:29 +08:00
}
}
}
2025-05-22 09:42:52 +08:00
template <typename T1, typename T2>
void assign_value_set(eprosima::fastcdr::optional<T1> &data, const T2 &model_data)
2025-05-22 09:42:52 +08:00
{
if constexpr (std::is_arithmetic_v<T1>) {
static_assert(std::is_arithmetic_v<T2>,
"模板参数T2必须是算术类型详见XNDDSInterface.cppline 337");
static_assert(std::is_convertible_v<T2, T1>,
"模板参数T2必须可以转换为T1类型详见XNDDSInterface.cppline 339");
2025-05-22 09:42:52 +08:00
data = model_data;
} else if constexpr (is_std_array_v<T1>) {
T1 temp;
size_t arraySize = array_size_v<T1>;
using array_type = typename T1::value_type;
2025-05-22 09:42:52 +08:00
for (size_t i = 0; i < arraySize; ++i) {
if constexpr (std::is_arithmetic_v<array_type>) {
2025-05-22 09:42:52 +08:00
temp[i] = model_data[i];
} else if constexpr (is_std_array_v<array_type>) {
size_t arraySize2 = array_size_v<array_type>;
using sub_array_type = typename array_type::value_type;
if constexpr (std::is_arithmetic_v<sub_array_type>) {
for (size_t j = 0; j < arraySize2; ++j) {
temp[i][j] = model_data[i][j];
}
} else {
static_assert(std::is_arithmetic_v<sub_array_type>,
"模板参数T1是std::"
"array类型时它的数组嵌套不能超过两层详见XNDDSInterface."
"cppline 357");
2025-05-22 09:42:52 +08:00
}
} else {
static_assert(
std::is_arithmetic_v<array_type> || is_std_array_v<array_type>,
"模板参数T1是std::array类型时它的value_"
"type必须是算术类型或std::array类型详见XNDDSInterface.cppline 364");
2025-05-22 09:42:52 +08:00
}
}
data = temp;
} else {
static_assert(
std::is_arithmetic_v<T1> || is_std_array_v<T1>,
"模板参数T1必须是算术类型或std::array类型详见XNDDSInterface.cppline 371");
2025-05-22 09:42:52 +08:00
}
}
2025-05-22 08:53:29 +08:00
virtual void clearOutData() {}
virtual void sendOutData() {}
2025-04-28 12:25:20 +08:00
protected:
2025-05-19 09:49:54 +08:00
std::unordered_map<std::string, std::function<std::string()>> getDataFunction;
2025-05-22 08:53:29 +08:00
std::unordered_map<std::string, std::function<void(std::string)>> setDataFunction;
std::vector<std::function<XNByteArray(void)>> getByteArrayFunction;
std::vector<std::function<void(XNByteArray, uint32_t &)>> setByteArrayFunction;
std::mutex dataMutex;
std::mutex outDataMutex;
uint8_t header[8]{0}; // 固定大小的头部
size_t headerSize = 8;
2025-05-22 08:53:29 +08:00
FAST_DDS_MACRO::DataWriter *dataWriter;
2025-04-28 12:25:20 +08:00
};
#define MAP_DATA_FUNC(NAME) \
2025-05-19 09:49:54 +08:00
getDataFunction[#NAME] = [this]() { return getString(data.NAME()); }; \
setDataFunction[#NAME] = [this](const std::string &value) { \
2025-05-22 08:53:29 +08:00
setDataFromString(out_data.NAME(), value); \
}; \
getByteArrayFunction.push_back([this]() { return getByteArray(data.NAME()); }); \
setByteArrayFunction.push_back([this](const XNByteArray &byteArray, uint32_t &pos) { \
setByteArray(out_data.NAME(), byteArray, pos); \
});