/** * @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" #include // 默认构造函数 XNModelObject::XNModelObject(QObject *parent) : XNObject(*new XNModelObjectPrivate(this), parent) { } // 默认析构函数 XNModelObject::~XNModelObject() { } XNModelObject::XNModelObject(XNModelObjectPrivate &dd, QObject *parent) : XNObject(dd, parent) { } // 获取模型描述 const QString &XNModelObject::GetDescription() { Q_D(XNModelObject); return d->_sDescription; } // 设置模型描述 void XNModelObject::SetDescription(const QString &sDescription) { Q_D(XNModelObject); d->_sDescription = sDescription; } // 获取作者 const QString &XNModelObject::GetAuthor() { Q_D(XNModelObject); return d->_sAuthor; } // 设置作者 void XNModelObject::SetAuthor(const QString &sAuthor) { Q_D(XNModelObject); d->_sAuthor = sAuthor; } // 获取模型配置文件路径 const QString &XNModelObject::GetXmlPath() { Q_D(XNModelObject); return d->_sXmlPath; } // 设置模型配置文件路径 void XNModelObject::SetXmlPath(const QString &sXmlPath) { Q_D(XNModelObject); d->_sXmlPath = sXmlPath; } // 获取模型创建时间 const QDateTime &XNModelObject::GetCreateTime() { Q_D(XNModelObject); return d->_cCreatTime; } // 设置模型创建时间 void XNModelObject::SetCreateTime(const QDateTime &cTime) { Q_D(XNModelObject); d->_cCreatTime = cTime; } // 获取模型修改时间 const QDateTime &XNModelObject::GetChangeTime() { Q_D(XNModelObject); return d->_cChangeTime; } // 设置模型修改时间 void XNModelObject::SetChangeTime(const QDateTime &cTime) { Q_D(XNModelObject); d->_cChangeTime = cTime; } // 获取模型版本号 const QString &XNModelObject::GetVersion() { Q_D(XNModelObject); return d->_sVersion; } // 设置模型版本号 void XNModelObject::SetVersion(const QString &sVersion) { Q_D(XNModelObject); d->_sVersion = sVersion; } void XNModelObject::SetBaseFreq(const double &dBaseFreq) { Q_D(XNModelObject); d->_setFreq = dBaseFreq; } // 初始化函数 void XNModelObject::OnInitialize() { // 先尝试调取动态库 Q_D(XNModelObject); // 读取配置文件,设置循环执行函数 QFile file(GetXmlPath()); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { LOG_WARNING("0x2161 Failed to open the model configuration file: %1!", GetXmlPath()); return; } QDomDocument doc; doc.setContent(&file); QDomElement rootNode = doc.documentElement(); // 读取配置文件的模型参数 QString modelName = rootNode.firstChildElement("Name").text(); if (modelName != objectName()) { 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!", objectName(), modelName); return; } d->_sDescription = rootNode.firstChildElement("Description").text(); d->_sAuthor = rootNode.firstChildElement("Author").text(); d->_sVersion = rootNode.firstChildElement("Version").text(); d->_cCreatTime = QDateTime::fromString(rootNode.firstChildElement("CreateTime").text(), Qt::ISODate); d->_cChangeTime = QDateTime::fromString(rootNode.firstChildElement("ChangeTime").text(), Qt::ISODate); QString funcNode = rootNode.firstChildElement("Node").text(); d->_runPriority = rootNode.firstChildElement("Priority").text().toInt(); // 检查运行节点是否是 "x-x" 形式 quint32 tmp = funcNode.indexOf('-'); if (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!", objectName()); } d->_runFreq = funcNode.left(tmp).toInt(); d->_setFreq = d->_setFreq / pow(2.0, d->_runFreq); d->_runNode = funcNode.right(funcNode.length() - tmp - 1).toInt(); // 注册周期性函数 emit RegisterFunction(getUniqueId(), std::bind(&XNModelObject::StepUpdate, this), d->_runFreq, d->_runNode, d->_runPriority); // 加载动态库 QString mathlib = rootNode.firstChildElement("MathLib").text(); if (mathlib.size() != 0) { d->_sLibPath = QFileInfo(GetXmlPath()).absolutePath() + "/" + mathlib; d->_dynamicLib = new QLibrary(d->_sLibPath); if (d->_dynamicLib->load()) { // 动态库加载成功 LOG_INFO("0x2163 Model %1 loaded algorithm dynamic library %2 successfully!", objectName(), d->_sLibPath); } else { LOG_WARNING( "0x2160 Model %1 failed to find algorithm dynamic library %2, will not call " "algorithm!", objectName(), d->_sLibPath); delete d->_dynamicLib; d->_dynamicLib = nullptr; } } // TODO 指令列表 QDomElement nodeCmds = rootNode.firstChildElement("CommandList"); for (QDomElement nodeCmd = nodeCmds.firstChildElement("Command"); !nodeCmd.isNull(); nodeCmd = nodeCmd.nextSiblingElement("Command")) { QString cmdName = nodeCmd.attribute("Name"); QString cmdDescription = nodeCmd.attribute("Description"); QString cmdCall = nodeCmd.attribute("Call"); } } // 单步执行函数 void XNModelObject::StepUpdate() { Q_D(XNModelObject); quint32 setFreq = d->_setFreq < 1.0 ? 1 : (quint32)d->_setFreq; if (d->_dataWriters.contains("XNSim::XNSimStatus::XNModelStatus") && d->_dataWriters["XNSim::XNSimStatus::XNModelStatus"] != nullptr && d->_runCnt > 0 && d->_runCnt % setFreq == 0) { XNSim::XNSimStatus::XNModelStatus modelStatus; modelStatus.XNModelName(objectName().toStdString()); modelStatus.XNModelID(getUniqueId()); modelStatus.XNModelSt(1); modelStatus.XNModelThID(pthread_self()); 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->_dataWriters["XNSim::XNSimStatus::XNModelStatus"]->write(&modelStatus); d->_lastRunTime = now; LOG_DEBUG("Model: %1 Write DDS!", objectName()); } d->_runCnt++; } // 运行前最后准备函数 void XNModelObject::OnPrepareForExecute() { Q_D(XNModelObject); d->_runCnt = 0; // 注册DDS RegisterDDSParticipant(); clock_gettime(CLOCK_MONOTONIC, &d->_lastRunTime); } void XNModelObject::RegisterDDSParticipant() { Q_D(XNModelObject); XNModelManager *modelManager = qobject_cast(parent()); if (modelManager == nullptr) return; XNDDSManager *ddsManager = modelManager->parent()->findChild(); if (ddsManager == nullptr) return; quint32 MyID = getUniqueId(); XN_PUBLISHTOPIC(XNSim::XNSimStatus::XNModelStatus); } int XNModelObject::RegisterEventHandler(const QString &eventName, std::function callback, bool async, XNEvent::Priority priority) { // 获取事件管理器 XNModelManager *modelManager = qobject_cast(parent()); if (modelManager == nullptr) { LOG_WARNING("Failed to get ModelManager!"); return -1; } XNEventManager *eventManager = modelManager->parent()->findChild(); if (eventManager == nullptr) { LOG_WARNING("Failed to get EventManager!"); return -1; } // 注册事件处理器 return eventManager->RegisterEventHandler(eventName, callback, getUniqueId(), async, priority); } void XNModelObject::TriggerEvent(const QString &eventName, const QVariant &eventData, bool forceAsync, XNEvent::Priority priority) { // 获取事件管理器 XNModelManager *modelManager = qobject_cast(parent()); if (modelManager == nullptr) { LOG_WARNING("Failed to get ModelManager!"); return; } XNEventManager *eventManager = modelManager->parent()->findChild(); if (eventManager == nullptr) { LOG_WARNING("Failed to get EventManager!"); return; } // 触发事件 eventManager->TriggerEvent(eventName, eventData, forceAsync, priority); }