From a6818f35bcd9f90e72f1f009c70077a45e96ff5d Mon Sep 17 00:00:00 2001 From: jinchao <383321154@qq.com> Date: Wed, 21 May 2025 12:17:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9DDSInterface=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=EF=BC=8C=E4=BF=AE=E5=A4=8DModelObject=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Release/include/XNCore/XNByteArray.h | 99 +++++++ Release/include/XNCore/XNCore_global.h | 4 + Release/include/XNCore/XNDDSInterface.h | 272 ++++++++---------- Release/include/XNCore/XNModelObject.h | 56 +++- Release/include/XNCore/XNModelObject_p.h | 5 + Release/include/XNCore/XNThreadManager.h | 16 ++ Release/include/XNCore/XNTypeTraits.h | 28 ++ XNCore/.vscode/settings.json | 4 +- XNCore/CMakeLists.txt | 2 + XNCore/XNByteArray.h | 99 +++++++ XNCore/XNCore_global.h | 4 + XNCore/XNDDSInterface.cpp | 107 +++++++ XNCore/XNDDSInterface.h | 272 ++++++++---------- XNCore/XNModelManager.cpp | 15 +- XNCore/XNModelObject.cpp | 78 ++++- XNCore/XNModelObject.h | 56 +++- XNCore/XNModelObject_p.h | 5 + XNCore/XNServiceManager.cpp | 3 + XNCore/XNThread.cpp | 3 +- XNCore/XNThreadManager.cpp | 12 + XNCore/XNThreadManager.h | 16 ++ XNCore/XNTypeTraits.h | 28 ++ XNModels/XNAerodynamics/.vscode/settings.json | 69 ++++- .../XNAerodynamics/XNAerodynamics.h | 2 +- .../XNGroundHandling/XNGroundHandling.h | 13 +- .../XNGroundHandling/XNGroundHandling_p.h | 13 +- 26 files changed, 951 insertions(+), 330 deletions(-) create mode 100644 Release/include/XNCore/XNByteArray.h create mode 100644 Release/include/XNCore/XNTypeTraits.h create mode 100644 XNCore/XNByteArray.h create mode 100644 XNCore/XNDDSInterface.cpp create mode 100644 XNCore/XNTypeTraits.h diff --git a/Release/include/XNCore/XNByteArray.h b/Release/include/XNCore/XNByteArray.h new file mode 100644 index 0000000..b6ba387 --- /dev/null +++ b/Release/include/XNCore/XNByteArray.h @@ -0,0 +1,99 @@ +#pragma once + +#include +#include +#include + +/** + * @brief 自定义字节数组容器类 + * @details 提供类似QByteArray的功能,用于处理二进制数据 + */ +class XNByteArray +{ +public: + XNByteArray() = default; + explicit XNByteArray(size_t size) : data_(size) {} + + /** + * @brief 从原始数据构造 + * @param buffer 原始数据缓冲区 + * @param size 数据大小 + */ + XNByteArray(const uint8_t *buffer, size_t size) : data_(buffer, buffer + size) {} + + /** + * @brief 获取数据指针 + * @return 数据指针 + */ + uint8_t *data() { return data_.data(); } + + /** + * @brief 获取常量数据指针 + * @return 常量数据指针 + */ + const uint8_t *data() const { return data_.data(); } + + /** + * @brief 获取数据大小 + * @return 数据大小 + */ + size_t size() const { return data_.size(); } + + /** + * @brief 调整大小 + * @param size 新大小 + */ + void resize(size_t size) { data_.resize(size); } + + /** + * @brief 清空数据 + */ + void clear() { data_.clear(); } + + /** + * @brief 追加数据 + * @param buffer 要追加的数据 + * @param size 数据大小 + */ + void append(const uint8_t *buffer, size_t size) + { + size_t oldSize = data_.size(); + data_.resize(oldSize + size); + std::memcpy(data_.data() + oldSize, buffer, size); + } + + /** + * @brief 追加另一个XNByteArray + * @param other 要追加的XNByteArray + */ + void append(const XNByteArray &other) { append(other.data(), other.size()); } + + /** + * @brief 获取指定位置的字节 + * @param index 索引 + * @return 字节值 + */ + uint8_t &operator[](size_t index) { return data_[index]; } + + /** + * @brief 获取指定位置的字节(常量版本) + * @param index 索引 + * @return 字节值 + */ + const uint8_t &operator[](size_t index) const { return data_[index]; } + + /** + * @brief 检查是否为空 + * @return 是否为空 + */ + bool isEmpty() const { return data_.empty(); } + + /** + * @brief 预分配空间 + * @param size 要预分配的大小 + */ + void reserve(size_t size) { data_.reserve(size); } + +private: + std::vector data_; +}; \ No newline at end of file diff --git a/Release/include/XNCore/XNCore_global.h b/Release/include/XNCore/XNCore_global.h index cf4c785..b4ce4bb 100644 --- a/Release/include/XNCore/XNCore_global.h +++ b/Release/include/XNCore/XNCore_global.h @@ -37,6 +37,9 @@ # include # include # include +# include +# include +# include #endif #include @@ -47,6 +50,7 @@ #include #include #include +#include #define FAST_DDS_MACRO eprosima::fastdds::dds /** diff --git a/Release/include/XNCore/XNDDSInterface.h b/Release/include/XNCore/XNDDSInterface.h index b884b45..21ba78c 100644 --- a/Release/include/XNCore/XNDDSInterface.h +++ b/Release/include/XNCore/XNDDSInterface.h @@ -1,191 +1,149 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "XNObject.h" +#include "XNByteArray.h" +#include "XNTypeTraits.h" +#include // 定义UDP包的最大大小 constexpr size_t MAX_UDP_PACKET_SIZE = 40000; -template -struct is_std_array : std::false_type { -}; - -template -struct is_std_array> : std::true_type { -}; - -// 变量模板简化使用 -template -inline constexpr bool is_std_array_v = is_std_array::value; - -// 获取类型大小的辅助函数 -template -constexpr size_t getTypeSize() -{ - if constexpr (is_std_array_v) { - // 对于std::array,计算所有元素的总大小 - return getTypeSize() * std::tuple_size::value; - } else { - return sizeof(T); - } -} - class XNDDSInterface { public: XNDDSInterface() = default; virtual ~XNDDSInterface() = default; - void getUDPPackage(uint8_t *buffer, size_t bufferSize) - { - if (bufferSize < MAX_UDP_PACKET_SIZE) - return; +public: + /** + * @brief 初始化 + * @param framework: 框架 + */ + virtual void Initialize(XNFrameworkPtr framework) = 0; - size_t currentPos = 0; + /** + * @brief 获取该接口的UDP包 + * @return 字节数组 + */ + XNByteArray getUDPPackage(); - // 复制头部 - if (headerSize >= 5) { - std::memcpy(buffer, header, 5); - currentPos = 5; - } - - // 复制数据 - for (auto func : getByteArrayFunction) { - if (currentPos + func.size <= MAX_UDP_PACKET_SIZE) { - func.func(buffer + currentPos, func.size); - currentPos += func.size; - } else { - break; // 超出最大包大小 - } - } - - // 更新包大小 - if (currentPos >= 5) { - buffer[4] = static_cast(currentPos); - } - } - - std::string getData(const std::string &varName) - { - int index1 = -1; - int index2 = -1; - std::string trueVarName = varName; - - size_t startPos = varName.find('['); - if (startPos != std::string::npos) { - size_t midPos = varName.find("][", startPos); - size_t endPos = varName.find_last_of(']'); - - if (midPos != std::string::npos) { - try { - index1 = std::stoi(varName.substr(startPos + 1, midPos - startPos - 1)); - index2 = std::stoi(varName.substr(midPos + 2, endPos - midPos - 2)); - } catch (...) { - std::cerr << "无法解析数组索引: " << varName << std::endl; - index1 = 0; - index2 = 0; - } - } else if (endPos != std::string::npos) { - try { - index1 = std::stoi(varName.substr(startPos + 1, endPos - startPos - 1)); - } catch (...) { - std::cerr << "无法解析数组索引: " << varName << std::endl; - index1 = 0; - } - } - trueVarName = varName.substr(0, startPos); - } - - auto it = getDataFunction.find(trueVarName); - if (it == getDataFunction.end()) { - return std::string(); - } - - std::lock_guard lock(mutex); - std::string result = it->second(); - - if (index1 < 0) { - return result; - } - - std::vector list; - std::stringstream ss(result); - std::string item; - while (std::getline(ss, item, ',')) { - list.push_back(item); - } - - if (index1 >= static_cast(list.size())) { - std::cerr << "数组索引超出范围: " << varName << std::endl; - return std::string(); - } - - if (index2 < 0) { - return list[index1]; - } - - std::vector list2; - std::stringstream ss2(list[index1]); - while (std::getline(ss2, item, ' ')) { - list2.push_back(item); - } - - if (index2 >= static_cast(list2.size())) { - std::cerr << "数组索引超出范围: " << varName << std::endl; - return std::string(); - } - - return list2[index2]; - } + /** + * @brief JSON前端获取指定变量的数据 + * @param varName: 变量名 + * @param nameSize: 变量名大小 + * @param varData: 数据 + * @param dataSize: 数据大小 + */ + void getData(const char *varName, const size_t nameSize, char *varData, size_t dataSize); protected: + /** + * @brief 获取指定变量的字节数据,用于网络通信 + * @param data: 数据 + * @return 字节数组 + */ template - void getByteArray(eprosima::fastcdr::optional data, uint8_t *buffer, size_t bufferSize) + XNByteArray getByteArray(eprosima::fastcdr::optional data) { - if (bufferSize < getTypeSize()) - return; + XNByteArray result(getTypeSize()); if constexpr (std::is_arithmetic_v) { if (data) { - std::memcpy(buffer, &data.value(), sizeof(T)); + std::memcpy(result.data(), &data.value(), sizeof(T)); } else { T zero = 0; - std::memcpy(buffer, &zero, sizeof(T)); + std::memcpy(result.data(), &zero, sizeof(T)); } } else if constexpr (is_std_array_v) { if (data) { - getByteArrayFromStdArray(data.value(), buffer, bufferSize); + return getByteArrayFromStdArray(data.value()); } else { T zero = {}; - getByteArrayFromStdArray(zero, buffer, bufferSize); + return getByteArrayFromStdArray(zero); } + } else { + static_assert(std::is_arithmetic_v || is_std_array_v, + "Type must be arithmetic or std::array"); + } + + return result; + } + + /** + * @brief 设置指定变量的字节数据,用于网络通信 + * @param data: 数据 + * @param byteArray: 字节数组 + */ + template + void setByteArray(eprosima::fastcdr::optional &data, const XNByteArray &byteArray) + { + if (byteArray.size() < getTypeSize()) + return; + + if constexpr (std::is_arithmetic_v) { + T temp; + std::memcpy(&temp, byteArray.data(), sizeof(T)); + data = temp; + } else if constexpr (is_std_array_v) { + if (!data) { + data = T{}; + } + setByteArrayFromStdArray(data.value(), byteArray); + } else { + static_assert(std::is_arithmetic_v || is_std_array_v, + "Type must be arithmetic or std::array"); } } + /** + * @brief 获取指定数组变量的字节数据,用于网络通信 + * @param data: 数据 + * @return 字节数组 + */ template - void getByteArrayFromStdArray(std::array data, uint8_t *buffer, size_t bufferSize) + XNByteArray getByteArrayFromStdArray(const std::array &data) { - if (bufferSize < getTypeSize() * N) + XNByteArray result(getTypeSize() * N); + + for (std::size_t i = 0; i < N; ++i) { + if constexpr (std::is_arithmetic_v) { + std::memcpy(result.data() + i * getTypeSize(), &data[i], getTypeSize()); + } else { + XNByteArray subArray = getByteArrayFromStdArray(data[i]); + std::memcpy(result.data() + i * getTypeSize(), subArray.data(), + getTypeSize()); + } + } + + return result; + } + + /** + * @brief 设置指定数组变量的字节数据,用于网络通信 + * @param data: 数据 + * @param byteArray: 字节数组 + */ + template + void setByteArrayFromStdArray(std::array &data, const XNByteArray &byteArray) + { + if (byteArray.size() < getTypeSize() * N) return; for (std::size_t i = 0; i < N; ++i) { if constexpr (std::is_arithmetic_v) { - std::memcpy(buffer + i * getTypeSize(), &data[i], getTypeSize()); + std::memcpy(&data[i], byteArray.data() + i * getTypeSize(), getTypeSize()); } else { - getByteArrayFromStdArray(data[i], buffer + i * getTypeSize(), getTypeSize()); + XNByteArray subArray(byteArray.data() + i * getTypeSize(), getTypeSize()); + setByteArrayFromStdArray(data[i], subArray); } } } + /** + * @brief 获取指定变量的字符串数据,用于JSON前端 + * @param data: 数据 + * @return: 数据(字符串格式) + */ template std::string getString(eprosima::fastcdr::optional data) { @@ -206,6 +164,11 @@ protected: return std::string(); } + /** + * @brief 获取指定数组变量的字符串数据,用于JSON前端 + * @param data: 数据 + * @return: 数据(字符串格式) + */ template std::string getStringFromStdArray(std::array data) { @@ -222,24 +185,35 @@ protected: return ss.str(); } +private: + /** + * @brief 通过变量名获取指定的数据 + * @param varName: 变量名 + * @return: 数据(字符串格式) + */ + std::string getData(const std::string &varName); + protected: struct ByteArrayFunc { - std::function func; + std::function func; size_t size; }; std::unordered_map> getDataFunction; std::vector getByteArrayFunction; + std::unordered_map> setByteArrayFunction; std::mutex mutex; uint8_t header[5]{}; // 固定大小的头部 size_t headerSize = 0; }; -#define MAP_GET_DATA_FUNC(NAME) \ +#define MAP_DATA_FUNC(NAME) \ getDataFunction[#NAME] = [this]() { return getString(data.NAME()); }; \ getByteArrayFunction.push_back( \ - {[this](uint8_t *buffer, size_t size) { getByteArray(data.NAME(), buffer, size); }, \ - getTypeSize()}) + {[this]() { return getByteArray(data.NAME()); }, getTypeSize()}); \ + setByteArrayFunction[#NAME] = [this](XNByteArray byteArray) { \ + setByteArray(data.NAME(), byteArray); \ + } #define ASSIGN_VALUE_GET(NAME) \ if (data.NAME()) { \ diff --git a/Release/include/XNCore/XNModelObject.h b/Release/include/XNCore/XNModelObject.h index f6b6467..91dc622 100644 --- a/Release/include/XNCore/XNModelObject.h +++ b/Release/include/XNCore/XNModelObject.h @@ -121,6 +121,54 @@ public: */ void SetVersion(const std::string &sVersion); + /** + * @brief 获取模型运行频率组 + * @return uint32_t: 模型运行频率组 + */ + uint32_t GetRunFreq() const; + + /** + * @brief 设置模型运行频率组 + * @param runFreq: uint32_t类型,模型运行频率组 + */ + void SetRunFreq(uint32_t runFreq); + + /** + * @brief 获取模型运行节点 + * @return uint32_t: 模型运行节点 + */ + uint32_t GetRunNode() const; + + /** + * @brief 设置模型运行节点 + * @param runNode: uint32_t类型,模型运行节点 + */ + void SetRunNode(uint32_t runNode); + + /** + * @brief 获取模型运行优先级 + * @return uint32_t: 模型运行优先级 + */ + uint32_t GetRunPriority() const; + + /** + * @brief 设置模型运行优先级 + * @param runPriority: uint32_t类型,模型运行优先级 + */ + void SetRunPriority(uint32_t runPriority); + + /** + * @brief 获取模型设置频率 + * @return double: 模型设置频率 + */ + double GetSetFreq() const; + + /** + * @brief 设置模型设置频率 + * @param setFreq: double类型,模型设置频率 + */ + void SetSetFreq(double setFreq); + /** * @brief 单步执行函数 * @details 模型默认的周期性执行函数 @@ -169,12 +217,18 @@ public: TriggerEvent(eventName, eventData, true, XNEvent::Priority::RealTime); } + void SetInitializeType(uint32_t initialType); + + void SetThreadID(uint32_t threadID); + + uint32_t GetThreadID() const; + /** * @brief 初始化函数 * @details * 模型的初始化函数接口,子类继承时要调用父类初始化接口,或在此函数中使用AddMyFunction方法注册需要被线程调用的函数 */ - virtual void Initialize(uint32_t initialType, uint32_t threadID); + virtual void Initialize(); /** * @brief 仿真系统运行前做最后处理 diff --git a/Release/include/XNCore/XNModelObject_p.h b/Release/include/XNCore/XNModelObject_p.h index 6374413..6b3703c 100644 --- a/Release/include/XNCore/XNModelObject_p.h +++ b/Release/include/XNCore/XNModelObject_p.h @@ -84,6 +84,11 @@ struct XNModelObjectPrivate : public XNObjectPrivate { */ double _setFreq; + /** + * @brief 模型初始化类型 + */ + uint32_t _initialType; + /** * @brief 模型线程ID */ diff --git a/Release/include/XNCore/XNThreadManager.h b/Release/include/XNCore/XNThreadManager.h index 968a90d..9c3ad77 100644 --- a/Release/include/XNCore/XNThreadManager.h +++ b/Release/include/XNCore/XNThreadManager.h @@ -81,6 +81,22 @@ public: */ virtual bool PrepareForExecute() override; + /** + * @brief 设置线程频率 + * @param threadID: UINT32类型,线程ID + * @param freq: double类型,线程频率 + * @details 设置线程频率接口 + */ + void SetThreadFreqByID(uint32_t threadID, double freq); + + /** + * @brief 获取线程频率 + * @param threadID: UINT32类型,线程ID + * @return double: 线程频率 + * @details 获取线程频率接口 + */ + double GetThreadFreqByID(uint32_t threadID); + /** * @brief 仿真控制 * @param objectId: 对象ID diff --git a/Release/include/XNCore/XNTypeTraits.h b/Release/include/XNCore/XNTypeTraits.h new file mode 100644 index 0000000..2be257d --- /dev/null +++ b/Release/include/XNCore/XNTypeTraits.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include +#include + +template +struct is_std_array : std::false_type { +}; + +template +struct is_std_array> : std::true_type { +}; + +// 变量模板简化使用 +template +inline constexpr bool is_std_array_v = is_std_array::value; + +// 获取类型大小的辅助函数 +template +constexpr size_t getTypeSize() +{ + if constexpr (is_std_array_v) { + // 对于std::array,计算所有元素的总大小 + return getTypeSize() * std::tuple_size::value; + } else { + return sizeof(T); + } +} \ No newline at end of file diff --git a/XNCore/.vscode/settings.json b/XNCore/.vscode/settings.json index 3cea849..47ef93c 100755 --- a/XNCore/.vscode/settings.json +++ b/XNCore/.vscode/settings.json @@ -79,6 +79,8 @@ "csignal": "cpp", "any": "cpp", "unordered_set": "cpp", - "fstream": "cpp" + "fstream": "cpp", + "forward_list": "cpp", + "valarray": "cpp" } } \ No newline at end of file diff --git a/XNCore/CMakeLists.txt b/XNCore/CMakeLists.txt index 91d8b7e..8404cf9 100755 --- a/XNCore/CMakeLists.txt +++ b/XNCore/CMakeLists.txt @@ -21,6 +21,8 @@ find_package(OpenSSL REQUIRED) add_library(XNCore SHARED XNCore_global.h XNCore_Function.cpp + XNTypeTraits.h + XNByteArray.h XNObject.h XNObject.cpp XNObject_p.h diff --git a/XNCore/XNByteArray.h b/XNCore/XNByteArray.h new file mode 100644 index 0000000..b6ba387 --- /dev/null +++ b/XNCore/XNByteArray.h @@ -0,0 +1,99 @@ +#pragma once + +#include +#include +#include + +/** + * @brief 自定义字节数组容器类 + * @details 提供类似QByteArray的功能,用于处理二进制数据 + */ +class XNByteArray +{ +public: + XNByteArray() = default; + explicit XNByteArray(size_t size) : data_(size) {} + + /** + * @brief 从原始数据构造 + * @param buffer 原始数据缓冲区 + * @param size 数据大小 + */ + XNByteArray(const uint8_t *buffer, size_t size) : data_(buffer, buffer + size) {} + + /** + * @brief 获取数据指针 + * @return 数据指针 + */ + uint8_t *data() { return data_.data(); } + + /** + * @brief 获取常量数据指针 + * @return 常量数据指针 + */ + const uint8_t *data() const { return data_.data(); } + + /** + * @brief 获取数据大小 + * @return 数据大小 + */ + size_t size() const { return data_.size(); } + + /** + * @brief 调整大小 + * @param size 新大小 + */ + void resize(size_t size) { data_.resize(size); } + + /** + * @brief 清空数据 + */ + void clear() { data_.clear(); } + + /** + * @brief 追加数据 + * @param buffer 要追加的数据 + * @param size 数据大小 + */ + void append(const uint8_t *buffer, size_t size) + { + size_t oldSize = data_.size(); + data_.resize(oldSize + size); + std::memcpy(data_.data() + oldSize, buffer, size); + } + + /** + * @brief 追加另一个XNByteArray + * @param other 要追加的XNByteArray + */ + void append(const XNByteArray &other) { append(other.data(), other.size()); } + + /** + * @brief 获取指定位置的字节 + * @param index 索引 + * @return 字节值 + */ + uint8_t &operator[](size_t index) { return data_[index]; } + + /** + * @brief 获取指定位置的字节(常量版本) + * @param index 索引 + * @return 字节值 + */ + const uint8_t &operator[](size_t index) const { return data_[index]; } + + /** + * @brief 检查是否为空 + * @return 是否为空 + */ + bool isEmpty() const { return data_.empty(); } + + /** + * @brief 预分配空间 + * @param size 要预分配的大小 + */ + void reserve(size_t size) { data_.reserve(size); } + +private: + std::vector data_; +}; \ No newline at end of file diff --git a/XNCore/XNCore_global.h b/XNCore/XNCore_global.h index cf4c785..b4ce4bb 100755 --- a/XNCore/XNCore_global.h +++ b/XNCore/XNCore_global.h @@ -37,6 +37,9 @@ # include # include # include +# include +# include +# include #endif #include @@ -47,6 +50,7 @@ #include #include #include +#include #define FAST_DDS_MACRO eprosima::fastdds::dds /** diff --git a/XNCore/XNDDSInterface.cpp b/XNCore/XNDDSInterface.cpp new file mode 100644 index 0000000..839d46d --- /dev/null +++ b/XNCore/XNDDSInterface.cpp @@ -0,0 +1,107 @@ +#include "XNDDSInterface.h" +#include "XNObject_p.h" +#include + +using json = nlohmann::json; + +void XNDDSInterface::getUDPPackage(uint8_t *buffer, size_t bufferSize) +{ + if (bufferSize < MAX_UDP_PACKET_SIZE) + return; + + size_t currentPos = 0; + + // 复制头部 + if (headerSize >= 5) { + std::memcpy(buffer, header, 5); + currentPos = 5; + } + + // 复制数据 + for (auto func : getByteArrayFunction) { + if (currentPos + func.size <= MAX_UDP_PACKET_SIZE) { + func.func(buffer + currentPos, func.size); + currentPos += func.size; + } else { + break; // 超出最大包大小 + } + } + + // 更新包大小 + if (currentPos >= 5) { + buffer[4] = static_cast(currentPos); + } +} + +std::string XNDDSInterface::getData(const std::string &varName) +{ + int index1 = -1; + int index2 = -1; + std::string trueVarName = varName; + + size_t startPos = varName.find('['); + if (startPos != std::string::npos) { + size_t midPos = varName.find("][", startPos); + size_t endPos = varName.find_last_of(']'); + + if (midPos != std::string::npos) { + try { + index1 = std::stoi(varName.substr(startPos + 1, midPos - startPos - 1)); + index2 = std::stoi(varName.substr(midPos + 2, endPos - midPos - 2)); + } catch (...) { + std::cerr << "无法解析数组索引: " << varName << std::endl; + index1 = 0; + index2 = 0; + } + } else if (endPos != std::string::npos) { + try { + index1 = std::stoi(varName.substr(startPos + 1, endPos - startPos - 1)); + } catch (...) { + std::cerr << "无法解析数组索引: " << varName << std::endl; + index1 = 0; + } + } + trueVarName = varName.substr(0, startPos); + } + + auto it = getDataFunction.find(trueVarName); + if (it == getDataFunction.end()) { + return std::string(); + } + + std::lock_guard lock(mutex); + std::string result = it->second(); + + if (index1 < 0) { + return result; + } + + std::vector list; + std::stringstream ss(result); + std::string item; + while (std::getline(ss, item, ',')) { + list.push_back(item); + } + + if (index1 >= static_cast(list.size())) { + std::cerr << "数组索引超出范围: " << varName << std::endl; + return std::string(); + } + + if (index2 < 0) { + return list[index1]; + } + + std::vector list2; + std::stringstream ss2(list[index1]); + while (std::getline(ss2, item, ' ')) { + list2.push_back(item); + } + + if (index2 >= static_cast(list2.size())) { + std::cerr << "数组索引超出范围: " << varName << std::endl; + return std::string(); + } + + return list2[index2]; +} \ No newline at end of file diff --git a/XNCore/XNDDSInterface.h b/XNCore/XNDDSInterface.h index b884b45..21ba78c 100644 --- a/XNCore/XNDDSInterface.h +++ b/XNCore/XNDDSInterface.h @@ -1,191 +1,149 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "XNObject.h" +#include "XNByteArray.h" +#include "XNTypeTraits.h" +#include // 定义UDP包的最大大小 constexpr size_t MAX_UDP_PACKET_SIZE = 40000; -template -struct is_std_array : std::false_type { -}; - -template -struct is_std_array> : std::true_type { -}; - -// 变量模板简化使用 -template -inline constexpr bool is_std_array_v = is_std_array::value; - -// 获取类型大小的辅助函数 -template -constexpr size_t getTypeSize() -{ - if constexpr (is_std_array_v) { - // 对于std::array,计算所有元素的总大小 - return getTypeSize() * std::tuple_size::value; - } else { - return sizeof(T); - } -} - class XNDDSInterface { public: XNDDSInterface() = default; virtual ~XNDDSInterface() = default; - void getUDPPackage(uint8_t *buffer, size_t bufferSize) - { - if (bufferSize < MAX_UDP_PACKET_SIZE) - return; +public: + /** + * @brief 初始化 + * @param framework: 框架 + */ + virtual void Initialize(XNFrameworkPtr framework) = 0; - size_t currentPos = 0; + /** + * @brief 获取该接口的UDP包 + * @return 字节数组 + */ + XNByteArray getUDPPackage(); - // 复制头部 - if (headerSize >= 5) { - std::memcpy(buffer, header, 5); - currentPos = 5; - } - - // 复制数据 - for (auto func : getByteArrayFunction) { - if (currentPos + func.size <= MAX_UDP_PACKET_SIZE) { - func.func(buffer + currentPos, func.size); - currentPos += func.size; - } else { - break; // 超出最大包大小 - } - } - - // 更新包大小 - if (currentPos >= 5) { - buffer[4] = static_cast(currentPos); - } - } - - std::string getData(const std::string &varName) - { - int index1 = -1; - int index2 = -1; - std::string trueVarName = varName; - - size_t startPos = varName.find('['); - if (startPos != std::string::npos) { - size_t midPos = varName.find("][", startPos); - size_t endPos = varName.find_last_of(']'); - - if (midPos != std::string::npos) { - try { - index1 = std::stoi(varName.substr(startPos + 1, midPos - startPos - 1)); - index2 = std::stoi(varName.substr(midPos + 2, endPos - midPos - 2)); - } catch (...) { - std::cerr << "无法解析数组索引: " << varName << std::endl; - index1 = 0; - index2 = 0; - } - } else if (endPos != std::string::npos) { - try { - index1 = std::stoi(varName.substr(startPos + 1, endPos - startPos - 1)); - } catch (...) { - std::cerr << "无法解析数组索引: " << varName << std::endl; - index1 = 0; - } - } - trueVarName = varName.substr(0, startPos); - } - - auto it = getDataFunction.find(trueVarName); - if (it == getDataFunction.end()) { - return std::string(); - } - - std::lock_guard lock(mutex); - std::string result = it->second(); - - if (index1 < 0) { - return result; - } - - std::vector list; - std::stringstream ss(result); - std::string item; - while (std::getline(ss, item, ',')) { - list.push_back(item); - } - - if (index1 >= static_cast(list.size())) { - std::cerr << "数组索引超出范围: " << varName << std::endl; - return std::string(); - } - - if (index2 < 0) { - return list[index1]; - } - - std::vector list2; - std::stringstream ss2(list[index1]); - while (std::getline(ss2, item, ' ')) { - list2.push_back(item); - } - - if (index2 >= static_cast(list2.size())) { - std::cerr << "数组索引超出范围: " << varName << std::endl; - return std::string(); - } - - return list2[index2]; - } + /** + * @brief JSON前端获取指定变量的数据 + * @param varName: 变量名 + * @param nameSize: 变量名大小 + * @param varData: 数据 + * @param dataSize: 数据大小 + */ + void getData(const char *varName, const size_t nameSize, char *varData, size_t dataSize); protected: + /** + * @brief 获取指定变量的字节数据,用于网络通信 + * @param data: 数据 + * @return 字节数组 + */ template - void getByteArray(eprosima::fastcdr::optional data, uint8_t *buffer, size_t bufferSize) + XNByteArray getByteArray(eprosima::fastcdr::optional data) { - if (bufferSize < getTypeSize()) - return; + XNByteArray result(getTypeSize()); if constexpr (std::is_arithmetic_v) { if (data) { - std::memcpy(buffer, &data.value(), sizeof(T)); + std::memcpy(result.data(), &data.value(), sizeof(T)); } else { T zero = 0; - std::memcpy(buffer, &zero, sizeof(T)); + std::memcpy(result.data(), &zero, sizeof(T)); } } else if constexpr (is_std_array_v) { if (data) { - getByteArrayFromStdArray(data.value(), buffer, bufferSize); + return getByteArrayFromStdArray(data.value()); } else { T zero = {}; - getByteArrayFromStdArray(zero, buffer, bufferSize); + return getByteArrayFromStdArray(zero); } + } else { + static_assert(std::is_arithmetic_v || is_std_array_v, + "Type must be arithmetic or std::array"); + } + + return result; + } + + /** + * @brief 设置指定变量的字节数据,用于网络通信 + * @param data: 数据 + * @param byteArray: 字节数组 + */ + template + void setByteArray(eprosima::fastcdr::optional &data, const XNByteArray &byteArray) + { + if (byteArray.size() < getTypeSize()) + return; + + if constexpr (std::is_arithmetic_v) { + T temp; + std::memcpy(&temp, byteArray.data(), sizeof(T)); + data = temp; + } else if constexpr (is_std_array_v) { + if (!data) { + data = T{}; + } + setByteArrayFromStdArray(data.value(), byteArray); + } else { + static_assert(std::is_arithmetic_v || is_std_array_v, + "Type must be arithmetic or std::array"); } } + /** + * @brief 获取指定数组变量的字节数据,用于网络通信 + * @param data: 数据 + * @return 字节数组 + */ template - void getByteArrayFromStdArray(std::array data, uint8_t *buffer, size_t bufferSize) + XNByteArray getByteArrayFromStdArray(const std::array &data) { - if (bufferSize < getTypeSize() * N) + XNByteArray result(getTypeSize() * N); + + for (std::size_t i = 0; i < N; ++i) { + if constexpr (std::is_arithmetic_v) { + std::memcpy(result.data() + i * getTypeSize(), &data[i], getTypeSize()); + } else { + XNByteArray subArray = getByteArrayFromStdArray(data[i]); + std::memcpy(result.data() + i * getTypeSize(), subArray.data(), + getTypeSize()); + } + } + + return result; + } + + /** + * @brief 设置指定数组变量的字节数据,用于网络通信 + * @param data: 数据 + * @param byteArray: 字节数组 + */ + template + void setByteArrayFromStdArray(std::array &data, const XNByteArray &byteArray) + { + if (byteArray.size() < getTypeSize() * N) return; for (std::size_t i = 0; i < N; ++i) { if constexpr (std::is_arithmetic_v) { - std::memcpy(buffer + i * getTypeSize(), &data[i], getTypeSize()); + std::memcpy(&data[i], byteArray.data() + i * getTypeSize(), getTypeSize()); } else { - getByteArrayFromStdArray(data[i], buffer + i * getTypeSize(), getTypeSize()); + XNByteArray subArray(byteArray.data() + i * getTypeSize(), getTypeSize()); + setByteArrayFromStdArray(data[i], subArray); } } } + /** + * @brief 获取指定变量的字符串数据,用于JSON前端 + * @param data: 数据 + * @return: 数据(字符串格式) + */ template std::string getString(eprosima::fastcdr::optional data) { @@ -206,6 +164,11 @@ protected: return std::string(); } + /** + * @brief 获取指定数组变量的字符串数据,用于JSON前端 + * @param data: 数据 + * @return: 数据(字符串格式) + */ template std::string getStringFromStdArray(std::array data) { @@ -222,24 +185,35 @@ protected: return ss.str(); } +private: + /** + * @brief 通过变量名获取指定的数据 + * @param varName: 变量名 + * @return: 数据(字符串格式) + */ + std::string getData(const std::string &varName); + protected: struct ByteArrayFunc { - std::function func; + std::function func; size_t size; }; std::unordered_map> getDataFunction; std::vector getByteArrayFunction; + std::unordered_map> setByteArrayFunction; std::mutex mutex; uint8_t header[5]{}; // 固定大小的头部 size_t headerSize = 0; }; -#define MAP_GET_DATA_FUNC(NAME) \ +#define MAP_DATA_FUNC(NAME) \ getDataFunction[#NAME] = [this]() { return getString(data.NAME()); }; \ getByteArrayFunction.push_back( \ - {[this](uint8_t *buffer, size_t size) { getByteArray(data.NAME(), buffer, size); }, \ - getTypeSize()}) + {[this]() { return getByteArray(data.NAME()); }, getTypeSize()}); \ + setByteArrayFunction[#NAME] = [this](XNByteArray byteArray) { \ + setByteArray(data.NAME(), byteArray); \ + } #define ASSIGN_VALUE_GET(NAME) \ if (data.NAME()) { \ diff --git a/XNCore/XNModelManager.cpp b/XNCore/XNModelManager.cpp index 9596991..5d3c2ff 100755 --- a/XNCore/XNModelManager.cpp +++ b/XNCore/XNModelManager.cpp @@ -38,6 +38,9 @@ XNModelManager::XNModelManager(PrivateType *p) : XNBaseFrameObject(p) bool XNModelManager::PrepareForExecute() { T_D(); + for (auto &model : d->ModelMap) { + model.second->PrepareForExecute(); + } d->_status = XNFrameObjectStatus::Ready; LOG_INFO("XNModelManager is prepared!"); return true; @@ -72,7 +75,8 @@ void XNModelManager::LoadModel(const std::string &modelPath, const std::string & model->SetUniqueId(modelID); model->SetObjectName(className); model->SetFramework(GetFramework()); - + model->SetInitializeType(initialType); + model->SetThreadID(threadID); // 使用std::filesystem处理路径 std::filesystem::path configPath = std::filesystem::path(modelPath).parent_path() / (className + ".mcfg"); @@ -82,7 +86,7 @@ void XNModelManager::LoadModel(const std::string &modelPath, const std::string & d->ModelMap[modelID] = model; // 初始化模型 - model->Initialize(initialType, threadID); + model->Initialize(); // 注册到线程管理器 if (threadID != 0) { @@ -90,7 +94,12 @@ void XNModelManager::LoadModel(const std::string &modelPath, const std::string & if (framework) { framework->GetThreadManager()->RegisterFunction( modelID, std::bind(&XNModelObject::StepUpdate, model.get()), threadID, - 0, 0, 0); + model->GetRunFreq(), model->GetRunNode(), model->GetRunPriority()); + // 设置模型设置频率 + double threadFreq = + framework->GetThreadManager()->GetThreadFreqByID(threadID); + double modelSetFreq = threadFreq / (double)(1 << model->GetRunFreq()); + model->SetSetFreq(modelSetFreq); } } } else { diff --git a/XNCore/XNModelObject.cpp b/XNCore/XNModelObject.cpp index f4277b9..2c9c483 100755 --- a/XNCore/XNModelObject.cpp +++ b/XNCore/XNModelObject.cpp @@ -126,12 +126,78 @@ void XNModelObject::SetVersion(const std::string &sVersion) d->_sVersion = sVersion; } +void XNModelObject::SetInitializeType(uint32_t initialType) +{ + T_D(); + d->_initialType = initialType; +} + +void XNModelObject::SetThreadID(uint32_t threadID) +{ + T_D(); + d->_threadID = threadID; +} + +uint32_t XNModelObject::GetThreadID() const +{ + T_D(); + return d->_threadID; +} + +uint32_t XNModelObject::GetRunFreq() const +{ + T_D(); + return d->_runFreq; +} + +void XNModelObject::SetRunFreq(uint32_t runFreq) +{ + T_D(); + d->_runFreq = runFreq; +} + +uint32_t XNModelObject::GetRunNode() const +{ + T_D(); + return d->_runNode; +} + +void XNModelObject::SetRunNode(uint32_t runNode) +{ + T_D(); + d->_runNode = runNode; +} + +uint32_t XNModelObject::GetRunPriority() const +{ + T_D(); + return d->_runPriority; +} + +void XNModelObject::SetRunPriority(uint32_t runPriority) +{ + T_D(); + d->_runPriority = runPriority; +} + +double XNModelObject::GetSetFreq() const +{ + T_D(); + return d->_setFreq; +} + +void XNModelObject::SetSetFreq(double setFreq) +{ + T_D(); + d->_setFreq = setFreq; +} + // 初始化函数 -void XNModelObject::Initialize(uint32_t initialType, uint32_t threadID) +void XNModelObject::Initialize() { // 先尝试调取动态库 T_D(); - if (initialType == 0) { + if (d->_initialType == 0) { // 读取配置文件,设置循环执行函数 std::ifstream file(GetXmlPath()); if (!file.is_open()) { @@ -179,7 +245,6 @@ void XNModelObject::Initialize(uint32_t initialType, uint32_t threadID) // 使用标准C++字符串处理 d->_runFreq = std::stoi(funcNode.substr(0, tmp)); - d->_setFreq = d->_setFreq / std::pow(2.0, d->_runFreq); d->_runNode = std::stoi(funcNode.substr(tmp + 1)); // 注册周期性函数 @@ -188,7 +253,7 @@ void XNModelObject::Initialize(uint32_t initialType, uint32_t threadID) auto threadManager = framework->GetThreadManager(); if (threadManager) { threadManager->RegisterFunction( - GetUniqueId(), std::bind(&XNModelObject::StepUpdate, this), threadID, + GetUniqueId(), std::bind(&XNModelObject::StepUpdate, this), d->_threadID, d->_runFreq, d->_runNode, d->_runPriority); } } @@ -284,9 +349,8 @@ void XNModelObject::RegisterDDSParticipant() XN_PUBLISHTOPIC(XNSim::XNSimStatus::XNModelStatus); } -int XNModelObject::RegisterEventHandler(const std::string &eventName, - std::function callback, bool async, - XNEvent::Priority priority) +int XNModelObject::RegisterEventHandler(const std::string &eventName, XNEventCallback callback, + bool async, XNEvent::Priority priority) { // 获取事件管理器 auto framework = GetFramework(); diff --git a/XNCore/XNModelObject.h b/XNCore/XNModelObject.h index f6b6467..91dc622 100755 --- a/XNCore/XNModelObject.h +++ b/XNCore/XNModelObject.h @@ -121,6 +121,54 @@ public: */ void SetVersion(const std::string &sVersion); + /** + * @brief 获取模型运行频率组 + * @return uint32_t: 模型运行频率组 + */ + uint32_t GetRunFreq() const; + + /** + * @brief 设置模型运行频率组 + * @param runFreq: uint32_t类型,模型运行频率组 + */ + void SetRunFreq(uint32_t runFreq); + + /** + * @brief 获取模型运行节点 + * @return uint32_t: 模型运行节点 + */ + uint32_t GetRunNode() const; + + /** + * @brief 设置模型运行节点 + * @param runNode: uint32_t类型,模型运行节点 + */ + void SetRunNode(uint32_t runNode); + + /** + * @brief 获取模型运行优先级 + * @return uint32_t: 模型运行优先级 + */ + uint32_t GetRunPriority() const; + + /** + * @brief 设置模型运行优先级 + * @param runPriority: uint32_t类型,模型运行优先级 + */ + void SetRunPriority(uint32_t runPriority); + + /** + * @brief 获取模型设置频率 + * @return double: 模型设置频率 + */ + double GetSetFreq() const; + + /** + * @brief 设置模型设置频率 + * @param setFreq: double类型,模型设置频率 + */ + void SetSetFreq(double setFreq); + /** * @brief 单步执行函数 * @details 模型默认的周期性执行函数 @@ -169,12 +217,18 @@ public: TriggerEvent(eventName, eventData, true, XNEvent::Priority::RealTime); } + void SetInitializeType(uint32_t initialType); + + void SetThreadID(uint32_t threadID); + + uint32_t GetThreadID() const; + /** * @brief 初始化函数 * @details * 模型的初始化函数接口,子类继承时要调用父类初始化接口,或在此函数中使用AddMyFunction方法注册需要被线程调用的函数 */ - virtual void Initialize(uint32_t initialType, uint32_t threadID); + virtual void Initialize(); /** * @brief 仿真系统运行前做最后处理 diff --git a/XNCore/XNModelObject_p.h b/XNCore/XNModelObject_p.h index 6374413..6b3703c 100755 --- a/XNCore/XNModelObject_p.h +++ b/XNCore/XNModelObject_p.h @@ -84,6 +84,11 @@ struct XNModelObjectPrivate : public XNObjectPrivate { */ double _setFreq; + /** + * @brief 模型初始化类型 + */ + uint32_t _initialType; + /** * @brief 模型线程ID */ diff --git a/XNCore/XNServiceManager.cpp b/XNCore/XNServiceManager.cpp index b7ead8b..4ee77fc 100755 --- a/XNCore/XNServiceManager.cpp +++ b/XNCore/XNServiceManager.cpp @@ -29,6 +29,9 @@ bool XNServiceManager::Initialize() bool XNServiceManager::PrepareForExecute() { T_D(); + for (auto &service : d->ServiceList) { + service.second->PrepareForExecute(); + } d->_status = XNFrameObjectStatus::Ready; LOG_INFO("XNServiceManager is prepared!"); return true; diff --git a/XNCore/XNThread.cpp b/XNCore/XNThread.cpp index e12b3ab..85faacc 100755 --- a/XNCore/XNThread.cpp +++ b/XNCore/XNThread.cpp @@ -271,7 +271,8 @@ const double &XNThread::GetRunFrequecy() void XNThread::SetRunFrequecy(const double &dRunFrequecy) { T_D(); - d->_setFreq = dRunFrequecy; + d->_setFreq = dRunFrequecy; + d->pinfo.period_ns = 1.0E9 / dRunFrequecy; } // 获取线程运行优先级 diff --git a/XNCore/XNThreadManager.cpp b/XNCore/XNThreadManager.cpp index a3637ad..f06d093 100755 --- a/XNCore/XNThreadManager.cpp +++ b/XNCore/XNThreadManager.cpp @@ -225,3 +225,15 @@ uint32_t XNThreadManager::AllocateThreadID() d->threadList[threadID] = nullptr; return threadID; } + +void XNThreadManager::SetThreadFreqByID(uint32_t threadID, double freq) +{ + T_D(); + d->threadList[threadID]->SetRunFrequecy(freq); +} + +double XNThreadManager::GetThreadFreqByID(uint32_t threadID) +{ + T_D(); + return d->threadList[threadID]->GetRunFrequecy(); +} diff --git a/XNCore/XNThreadManager.h b/XNCore/XNThreadManager.h index 968a90d..9c3ad77 100755 --- a/XNCore/XNThreadManager.h +++ b/XNCore/XNThreadManager.h @@ -81,6 +81,22 @@ public: */ virtual bool PrepareForExecute() override; + /** + * @brief 设置线程频率 + * @param threadID: UINT32类型,线程ID + * @param freq: double类型,线程频率 + * @details 设置线程频率接口 + */ + void SetThreadFreqByID(uint32_t threadID, double freq); + + /** + * @brief 获取线程频率 + * @param threadID: UINT32类型,线程ID + * @return double: 线程频率 + * @details 获取线程频率接口 + */ + double GetThreadFreqByID(uint32_t threadID); + /** * @brief 仿真控制 * @param objectId: 对象ID diff --git a/XNCore/XNTypeTraits.h b/XNCore/XNTypeTraits.h new file mode 100644 index 0000000..2be257d --- /dev/null +++ b/XNCore/XNTypeTraits.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include +#include + +template +struct is_std_array : std::false_type { +}; + +template +struct is_std_array> : std::true_type { +}; + +// 变量模板简化使用 +template +inline constexpr bool is_std_array_v = is_std_array::value; + +// 获取类型大小的辅助函数 +template +constexpr size_t getTypeSize() +{ + if constexpr (is_std_array_v) { + // 对于std::array,计算所有元素的总大小 + return getTypeSize() * std::tuple_size::value; + } else { + return sizeof(T); + } +} \ No newline at end of file diff --git a/XNModels/XNAerodynamics/.vscode/settings.json b/XNModels/XNAerodynamics/.vscode/settings.json index 69ee91c..b417e52 100755 --- a/XNModels/XNAerodynamics/.vscode/settings.json +++ b/XNModels/XNAerodynamics/.vscode/settings.json @@ -7,6 +7,73 @@ "*.ipp": "cpp", "*.tcc": "cpp", "optional": "cpp", - "type_traits": "cpp" + "type_traits": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "ranges": "cpp", + "span": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "variant": "cpp" } } \ No newline at end of file diff --git a/XNModels/XNAerodynamics/XNAerodynamics/XNAerodynamics.h b/XNModels/XNAerodynamics/XNAerodynamics/XNAerodynamics.h index f60f62a..8c1012e 100755 --- a/XNModels/XNAerodynamics/XNAerodynamics/XNAerodynamics.h +++ b/XNModels/XNAerodynamics/XNAerodynamics/XNAerodynamics.h @@ -18,7 +18,7 @@ protected: XNAerodynamics(PrivateType *p); public: - virtual void Initialize(uint32_t initialType, uint32_t threadID) override; + virtual void Initialize() override; virtual void PrepareForExecute() override; public: diff --git a/XNModels/XNGroundHandling/XNGroundHandling/XNGroundHandling.h b/XNModels/XNGroundHandling/XNGroundHandling/XNGroundHandling.h index 67f8563..84dc86d 100755 --- a/XNModels/XNGroundHandling/XNGroundHandling/XNGroundHandling.h +++ b/XNModels/XNGroundHandling/XNGroundHandling/XNGroundHandling.h @@ -3,13 +3,12 @@ #include #include "../XNGroundHandlingInterface/XNGroundHandlingInterface.hpp" -class XNGroundHandlingPrivate; +struct XNGroundHandlingPrivate; class XNGROUNDHANDLING_EXPORT XNGroundHandling : public XNModelObject { - Q_OBJECT - Q_DISABLE_COPY(XNGroundHandling) - Q_DECLARE_PRIVATE(XNGroundHandling) + XN_METATYPE(XNGroundHandling, XNModelObject) + XN_DECLARE_PRIVATE(XNGroundHandling) XN_DECLARE_DDS() public: explicit XNGroundHandling(QObject *parent = nullptr); @@ -18,9 +17,9 @@ public: protected: XNGroundHandling(XNGroundHandlingPrivate &dd, QObject *parent = nullptr); -public slots: - virtual void OnInitialize() override; - virtual void OnPrepareForExecute() override; +public: + virtual void Initialize() override; + virtual void PrepareForExecute() override; public: virtual void StepUpdate() override; diff --git a/XNModels/XNGroundHandling/XNGroundHandling/XNGroundHandling_p.h b/XNModels/XNGroundHandling/XNGroundHandling/XNGroundHandling_p.h index bdf9d17..df69b8d 100755 --- a/XNModels/XNGroundHandling/XNGroundHandling/XNGroundHandling_p.h +++ b/XNModels/XNGroundHandling/XNGroundHandling/XNGroundHandling_p.h @@ -1,20 +1,15 @@ #pragma once #include #include -#include typedef void (*FunctionType)(ComacDataStructure_S *); -class XNGroundHandlingPrivate : public XNModelObjectPrivate -{ -public: - Q_DECLARE_PUBLIC(XNGroundHandling) - - XNGroundHandlingPrivate(XNGroundHandling *q) : XNModelObjectPrivate(q) {} - +struct XNGroundHandlingPrivate : public XNModelObjectPrivate { FunctionType _fun = nullptr; ComacDataStructure_S _data; - QMutex _mutex; + std::string _entryPointName = "_Z29SACSCGroundHandlingEntryPointP20ComacDataStructure_S"; + + std::mutex _mutex; };