/** * @file XNModelObject.cpp * @author jinchao * @brief 模型基类源文件 * @version 1.0 * @date 2024-11-07 * * @copyright Copyright (c) 2024 XN * */ #include "XNModelObject.h" #include "XNDDSManager/XNDDSManager.h" #include "XNFramework/XNFramework.h" #include "XNIDL/XNSimStatusPubSubTypes.hpp" #include "XNModelManager/XNModelManager.h" #include "XNModelObject_p.h" #include "XNThreadManager/XNThreadManager.h" namespace XNSim { // 默认构造函数 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 XN_STRING &XNModelObject::GetDescription() { T_D(); return d->_sDescription; } // 设置模型描述 void XNModelObject::SetDescription(const XN_STRING &sDescription) { T_D(); d->_sDescription = sDescription; } // 获取作者 const XN_STRING &XNModelObject::GetAuthor() { T_D(); return d->_sAuthor; } // 设置作者 void XNModelObject::SetAuthor(const XN_STRING &sAuthor) { T_D(); d->_sAuthor = sAuthor; } // 获取模型配置文件路径 const XN_STRING &XNModelObject::GetXmlPath() { T_D(); return d->_sXmlPath; } // 设置模型配置文件路径 void XNModelObject::SetXmlPath(const XN_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 XN_STRING &XNModelObject::GetVersion() { T_D(); return d->_sVersion; } // 设置模型版本号 void XNModelObject::SetVersion(const XN_STRING &sVersion) { T_D(); d->_sVersion = sVersion; } void XNModelObject::SetInitializeType(XN_UINT32 initialType) { T_D(); d->_initialType = initialType; } void XNModelObject::SetThreadID(XN_UINT32 threadID) { T_D(); d->_threadID = threadID; } XN_UINT32 XNModelObject::GetThreadID() const { T_D(); return d->_threadID; } XN_UINT32 XNModelObject::GetRunFreq() const { T_D(); return d->_runFreq; } void XNModelObject::SetRunFreq(XN_UINT32 runFreq) { T_D(); d->_runFreq = runFreq; } XN_UINT32 XNModelObject::GetRunNode() const { T_D(); return d->_runNode; } void XNModelObject::SetRunNode(XN_UINT32 runNode) { T_D(); d->_runNode = runNode; } XN_UINT32 XNModelObject::GetRunPriority() const { T_D(); return d->_runPriority; } void XNModelObject::SetRunPriority(XN_UINT32 runPriority) { T_D(); d->_runPriority = runPriority; } XN_DOUBLE XNModelObject::GetSetFreq() const { T_D(); return d->_setFreq; } void XNModelObject::SetSetFreq(XN_DOUBLE setFreq) { T_D(); d->_setFreq = setFreq; } const XN_STRING &XNModelObject::GetLibPath() { T_D(); return d->_sLibPath; } void XNModelObject::SetLibPath(const XN_STRING &sLibPath) { T_D(); d->_sLibPath = sLibPath; } // 初始化函数 void XNModelObject::Initialize() { T_D(); if (d->_initialType == 0) { ParseXml(); } else { ParseConfig(); } } void XNModelObject::ParseXml() { T_D(); // 读取配置文件,设置循环执行函数 XN_XMLDocument doc; if (LoadXmlFile(GetXmlPath(), doc) != 0) { LOG_WARNING("0x2161 Failed to parse model configuration file: %1!", GetXmlPath()); return; } XN_XMLElement *rootNode = GetRootElement(doc); if (!rootNode) { LOG_WARNING("0x2161 Failed to parse model configuration file: %1!", GetXmlPath()); return; } // 读取配置文件的模型参数 XN_STRING modelName = GetFirstChildElementText(rootNode, "Name"); if (modelName.empty() || 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.empty() ? "null" : modelName); return; } d->_sDescription = GetFirstChildElementText(rootNode, "Description"); d->_sAuthor = GetFirstChildElementText(rootNode, "Author"); d->_sVersion = GetFirstChildElementText(rootNode, "Version"); // 使用标准C++时间处理 XN_STRING createTimeStr = GetFirstChildElementText(rootNode, "CreateTime"); XN_STRING changeTimeStr = GetFirstChildElementText(rootNode, "ChangeTime"); d->_cCreatTime = parseISOTime(createTimeStr); d->_cChangeTime = parseISOTime(changeTimeStr); XN_STRING funcNode = GetFirstChildElementText(rootNode, "Node"); d->_runPriority = XNSafe_stoi(GetFirstChildElementText(rootNode, "Priority")); // 检查运行节点是否是 "x-x" 形式 XN_SIZE 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 = XNSafe_stoi(funcNode.substr(0, tmp)); d->_runNode = XNSafe_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); } } // 加载动态库 XN_STRING mathlib = GetFirstChildElementText(rootNode, "MathLib"); if (!mathlib.empty()) { // 使用标准C++文件路径处理 XN_PATH xmlPath(GetXmlPath()); d->_sLibPath = xmlPath.parent_path().string() + "/" + mathlib; // 使用标准C++动态库加载 d->_dynamicLib = loadLibrary(d->_sLibPath); 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; } } // 处理指令列表 XN_XMLElement *nodeCmds = GetFirstChildElement(rootNode, "CommandList"); if (nodeCmds) { for (XN_XMLElement *nodeCmd = GetFirstChildElement(nodeCmds, "Command"); nodeCmd != nullptr; nodeCmd = GetNextSiblingElement(nodeCmd, "Command")) { XN_STRING cmdName = GetAttribute(nodeCmd, "Name"); XN_STRING cmdDescription = GetAttribute(nodeCmd, "Description"); XN_STRING cmdCall = GetAttribute(nodeCmd, "Call"); // TODO: 处理命令列表 } } } void XNModelObject::ParseConfig() { T_D(); XN_STRINGLIST nameAndVersion = XNSplit(GetXmlPath(), ","); XN_STRING planeName = nameAndVersion[0]; XN_STRING modelName = nameAndVersion[1]; XN_STRING modelVersion = nameAndVersion[2]; // 获取数据库路径 XN_STRING dbPath = getEnv("XNCore"); if (dbPath.empty()) { LOG_ERROR("0x1015 未设置XNCore环境变量, 引擎将退出!"); return; } dbPath += "/database/XNSim.db"; // 打开数据库 XN_DB_PTR db = openDatabase(dbPath); if (db == nullptr) { LOG_ERROR("0x1016 打开数据库失败: %1", sqlite3_errmsg(db)); return; } // 准备SQL语句 XN_STRING sql = "SELECT * FROM XNModelsVersion WHERE PlaneName = ? AND " "ClassName = ? AND Version = ?"; XN_DB_STMT_PTR stmt = prepareSql(db, sql); if (stmt == nullptr) { LOG_ERROR("0x1017 准备SQL语句失败: %1", sqlite3_errmsg(db)); closeDatabase(db); return; } // 绑定参数 if (!bindText(stmt, 1, planeName) || !bindText(stmt, 2, modelName) || !bindText(stmt, 3, modelVersion)) { LOG_ERROR("0x1018 绑定参数失败: %1", sqlite3_errmsg(db)); finalizeSql(stmt); closeDatabase(db); return; } // 执行查询 if (!stepSql(stmt)) { LOG_ERROR("0x1019 未找到机型为%1,模型名称为%2,版本号%3的记录", planeName.c_str(), modelName.c_str(), modelVersion.c_str()); finalizeSql(stmt); closeDatabase(db); return; } d->_sDescription = getStringFromSqlite3(stmt, 7); d->_sAuthor = getStringFromSqlite3(stmt, 6); d->_sVersion = getStringFromSqlite3(stmt, 2); // 解析时间 XN_STRING createTimeStr = getStringFromSqlite3(stmt, 8); XN_STRING changeTimeStr = getStringFromSqlite3(stmt, 9); d->_cCreatTime = parseISOTime(createTimeStr); d->_cChangeTime = parseISOTime(changeTimeStr); d->_runFreq = XNSafe_stoi(getStringFromSqlite3(stmt, 10)); d->_runNode = XNSafe_stoi(getStringFromSqlite3(stmt, 11)); d->_runPriority = XNSafe_stoi(getStringFromSqlite3(stmt, 12)); // 注册周期性函数 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); } } // 加载动态库 XN_STRING mathlib = getStringFromSqlite3(stmt, 13); if (mathlib.length() > 0) { // 使用标准C++文件路径处理 // std::filesystem::path xmlPath(GetXmlPath()); // d->_sLibPath = xmlPath.parent_path().string() + "/" + mathlib; XN_STRING libPath = d->_sLibPath + "/" + mathlib; // 使用标准C++动态库加载 d->_dynamicLib = loadLibrary(libPath); if (d->_dynamicLib) { // 动态库加载成功 LOG_INFO("0x2163 模型 %1 加载数据包模型动态库 %2 成功!", GetObjectName(), libPath); } else { LOG_WARNING( "0x2160 模型 %1 未找到数据包模型动态库 %2, 将不调用数据包模型!", GetObjectName(), libPath); d->_dynamicLib = nullptr; } } // TODO: 读取模型命令列表 // 清理资源 finalizeSql(stmt); closeDatabase(db); } // 单步执行函数 void XNModelObject::StepUpdate() { T_D(); XN_UINT32 setFreq = d->_setFreq < 1.0 ? 1 : (XN_UINT32)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); XN_TIMESPEC now; getCurrentRTTime(&now); double time_diff = calculateRTTime(&now, &d->_lastRunTime); 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(); getCurrentRTTime(&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; } XN_UINT32 MyID = GetUniqueId(); d->_dataWriter = ddsManager ->RegisterPublisher( "XNSim::XNSimStatus::XNModelStatus", MyID); } XN_INT32 XNModelObject::RegisterEventHandler(const XN_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 XN_STRING &eventName, const XN_ANY &eventData, XN_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); } } // namespace XNSim