XNSim/XNCore/XNModelObject.cpp
2025-04-28 12:25:20 +08:00

287 lines
8.1 KiB
C++
Executable File

/**
* @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 <QMetaMethod>
// 默认构造函数
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<XNModelManager *>(parent());
if (modelManager == nullptr)
return;
XNDDSManager *ddsManager = modelManager->parent()->findChild<XNDDSManager *>();
if (ddsManager == nullptr)
return;
quint32 MyID = getUniqueId();
XN_PUBLISHTOPIC(XNSim::XNSimStatus::XNModelStatus);
}
int XNModelObject::RegisterEventHandler(const QString &eventName,
std::function<void(const QVariant &)> callback, bool async,
XNEvent::Priority priority)
{
// 获取事件管理器
XNModelManager *modelManager = qobject_cast<XNModelManager *>(parent());
if (modelManager == nullptr) {
LOG_WARNING("Failed to get ModelManager!");
return -1;
}
XNEventManager *eventManager = modelManager->parent()->findChild<XNEventManager *>();
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<XNModelManager *>(parent());
if (modelManager == nullptr) {
LOG_WARNING("Failed to get ModelManager!");
return;
}
XNEventManager *eventManager = modelManager->parent()->findChild<XNEventManager *>();
if (eventManager == nullptr) {
LOG_WARNING("Failed to get EventManager!");
return;
}
// 触发事件
eventManager->TriggerEvent(eventName, eventData, forceAsync, priority);
}