/** * @file XNModelObject.cpp * @author jinchao * @brief 模型基类源文件 * @version 1.0 * @date 2024-11-07 * * @copyright Copyright (c) 2024 XN * */ #include "XNModelObject.h" #include "XNModelObject_p.h" #include "XNFramework.h" #include "XNThreadManager.h" #include "XNModelManager.h" #include "XNDDSManager.h" #include "XNIDL/XNSimStatusPubSubTypes.hpp" // 默认构造函数 XNModelObject::XNModelObject() : XNObject(new XNModelObjectPrivate()) { } // 默认析构函数 XNModelObject::~XNModelObject() { } XNModelObject::XNModelObject(PrivateType *p) : XNObject(p) { } void XNModelObject::SetFramework(XNFrameworkPtr framework) { T_D(); d->_framework = framework; } XNFrameworkPtr XNModelObject::GetFramework() const { T_D(); return d->_framework; } // 获取模型描述 const std::string &XNModelObject::GetDescription() { T_D(); return d->_sDescription; } // 设置模型描述 void XNModelObject::SetDescription(const std::string &sDescription) { T_D(); d->_sDescription = sDescription; } // 获取作者 const std::string &XNModelObject::GetAuthor() { T_D(); return d->_sAuthor; } // 设置作者 void XNModelObject::SetAuthor(const std::string &sAuthor) { T_D(); d->_sAuthor = sAuthor; } // 获取模型配置文件路径 const std::string &XNModelObject::GetXmlPath() { T_D(); return d->_sXmlPath; } // 设置模型配置文件路径 void XNModelObject::SetXmlPath(const std::string &sXmlPath) { T_D(); d->_sXmlPath = sXmlPath; } // 获取模型创建时间 const XNTimePoint &XNModelObject::GetCreateTime() { T_D(); return d->_cCreatTime; } // 设置模型创建时间 void XNModelObject::SetCreateTime(const XNTimePoint &cTime) { T_D(); d->_cCreatTime = cTime; } // 获取模型修改时间 const XNTimePoint &XNModelObject::GetChangeTime() { T_D(); return d->_cChangeTime; } // 设置模型修改时间 void XNModelObject::SetChangeTime(const XNTimePoint &cTime) { T_D(); d->_cChangeTime = cTime; } // 获取模型版本号 const std::string &XNModelObject::GetVersion() { T_D(); return d->_sVersion; } // 设置模型版本号 void XNModelObject::SetVersion(const std::string &sVersion) { T_D(); 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() { // 先尝试调取动态库 T_D(); if (d->_initialType == 0) { // 读取配置文件,设置循环执行函数 std::ifstream file(GetXmlPath()); if (!file.is_open()) { LOG_WARNING("0x2161 Failed to open the model configuration file: %1!", GetXmlPath()); return; } tinyxml2::XMLDocument doc; doc.LoadFile(GetXmlPath().c_str()); tinyxml2::XMLElement *rootNode = doc.FirstChildElement("Model"); if (!rootNode) { LOG_WARNING("0x2161 Failed to parse model configuration file: %1!", GetXmlPath()); return; } // 读取配置文件的模型参数 const char *modelName = rootNode->FirstChildElement("Name")->GetText(); if (!modelName || std::string(modelName) != GetObjectName()) { LOG_WARNING( "0x2162 The model name in the configuration file of model %1 is not consistent " "with the model name in the configuration file of model %2!", GetObjectName(), modelName ? modelName : "null"); return; } d->_sDescription = rootNode->FirstChildElement("Description")->GetText(); d->_sAuthor = rootNode->FirstChildElement("Author")->GetText(); d->_sVersion = rootNode->FirstChildElement("Version")->GetText(); // 使用标准C++时间处理 std::string createTimeStr = rootNode->FirstChildElement("CreateTime")->GetText(); std::string changeTimeStr = rootNode->FirstChildElement("ChangeTime")->GetText(); d->_cCreatTime = parseISOTime(createTimeStr); d->_cChangeTime = parseISOTime(changeTimeStr); std::string funcNode = rootNode->FirstChildElement("Node")->GetText(); d->_runPriority = std::stoi(rootNode->FirstChildElement("Priority")->GetText()); // 检查运行节点是否是 "x-x" 形式 size_t tmp = funcNode.find('-'); if (tmp == std::string::npos || tmp == 0) { LOG_WARNING( "0x2162 The value of the run node attribute in the configuration file of model " "%1 is not in the x-x format, registration not executed!", GetObjectName()); return; } // 使用标准C++字符串处理 d->_runFreq = std::stoi(funcNode.substr(0, tmp)); d->_runNode = std::stoi(funcNode.substr(tmp + 1)); // 注册周期性函数 auto framework = GetFramework(); if (framework) { auto threadManager = framework->GetThreadManager(); if (threadManager) { threadManager->RegisterFunction( GetUniqueId(), std::bind(&XNModelObject::StepUpdate, this), d->_threadID, d->_runFreq, d->_runNode, d->_runPriority); } } // 加载动态库 const char *mathlib = rootNode->FirstChildElement("MathLib")->GetText(); if (mathlib && strlen(mathlib) > 0) { // 使用标准C++文件路径处理 std::filesystem::path xmlPath(GetXmlPath()); d->_sLibPath = xmlPath.parent_path().string() + "/" + mathlib; // 使用标准C++动态库加载 d->_dynamicLib = dlopen(d->_sLibPath.c_str(), RTLD_LAZY); if (d->_dynamicLib) { // 动态库加载成功 LOG_INFO("0x2163 Model %1 loaded algorithm dynamic library %2 successfully!", GetObjectName(), d->_sLibPath); } else { LOG_WARNING( "0x2160 Model %1 failed to find algorithm dynamic library %2, will not call " "algorithm!", GetObjectName(), d->_sLibPath); d->_dynamicLib = nullptr; } } // 处理指令列表 tinyxml2::XMLElement *nodeCmds = rootNode->FirstChildElement("CommandList"); if (nodeCmds) { for (tinyxml2::XMLElement *nodeCmd = nodeCmds->FirstChildElement("Command"); nodeCmd != nullptr; nodeCmd = nodeCmd->NextSiblingElement("Command")) { const char *cmdName = nodeCmd->Attribute("Name"); const char *cmdDescription = nodeCmd->Attribute("Description"); const char *cmdCall = nodeCmd->Attribute("Call"); // TODO: 处理命令列表 } } } } // 单步执行函数 void XNModelObject::StepUpdate() { T_D(); uint32_t setFreq = d->_setFreq < 1.0 ? 1 : (uint32_t)d->_setFreq; if (d->_dataWriter != nullptr && d->_runCnt > 0 && d->_runCnt % setFreq == 0) { XNSim::XNSimStatus::XNModelStatus modelStatus; modelStatus.XNModelName(GetObjectName()); modelStatus.XNModelID(GetUniqueId()); modelStatus.XNModelSt(1); modelStatus.XNModelThID(d->_threadID); modelStatus.XNModelNode(d->_runNode); modelStatus.XNModelPro(d->_runPriority); modelStatus.XNModelRunCnt(d->_runCnt); timespec now; clock_gettime(CLOCK_MONOTONIC, &now); double time_diff = (now.tv_sec - d->_lastRunTime.tv_sec) + (now.tv_nsec - d->_lastRunTime.tv_nsec) / 1.0E9; modelStatus.XNMdlCurFreq(d->_setFreq / time_diff); modelStatus.XNMdlSetFreq(d->_setFreq); d->_dataWriter->write(&modelStatus); d->_lastRunTime = now; LOG_DEBUG("Model: %1 Write DDS!", GetObjectName()); } d->_runCnt++; } // 运行前最后准备函数 void XNModelObject::PrepareForExecute() { T_D(); d->_runCnt = 0; // 注册DDS RegisterDDSParticipant(); clock_gettime(CLOCK_MONOTONIC, &d->_lastRunTime); } void XNModelObject::RegisterDDSParticipant() { T_D(); auto framework = GetFramework(); if (framework == nullptr) { LOG_WARNING("Failed to get Framework!"); return; } auto ddsManager = framework->GetDDSManager(); if (ddsManager == nullptr) { LOG_WARNING("Failed to get DDSManager!"); return; } uint32_t MyID = GetUniqueId(); d->_dataWriter = ddsManager->RegisterPublisher( "XNSim::XNSimStatus::XNModelStatus", MyID); } int XNModelObject::RegisterEventHandler(const std::string &eventName, XNEventCallback callback, bool async, XNEvent::Priority priority) { // 获取事件管理器 auto framework = GetFramework(); if (framework == nullptr) { LOG_WARNING("Failed to get Framework!"); return -1; } XNEventManagerPtr eventManager = framework->GetEventManager(); if (eventManager == nullptr) { LOG_WARNING("Failed to get EventManager!"); return -1; } // 注册事件处理器 return eventManager->RegisterEventHandler(eventName, callback, GetUniqueId(), async, priority); } void XNModelObject::TriggerEvent(const std::string &eventName, const std::any &eventData, bool forceAsync, XNEvent::Priority priority) { // 获取事件管理器 auto framework = GetFramework(); if (framework == nullptr) { LOG_WARNING("Failed to get Framework!"); return; } XNEventManagerPtr eventManager = framework->GetEventManager(); if (eventManager == nullptr) { LOG_WARNING("Failed to get EventManager!"); return; } // 触发事件 eventManager->TriggerEvent(eventName, eventData, forceAsync, priority); }