XNSim/XNCore/XNModelObject.cpp

390 lines
9.4 KiB
C++
Raw Permalink Normal View History

2025-04-28 12:25:20 +08:00
/**
* @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"
// 默认构造函数
2025-05-20 15:39:40 +08:00
XNModelObject::XNModelObject() : XNObject(new XNModelObjectPrivate())
2025-04-28 12:25:20 +08:00
{
}
// 默认析构函数
XNModelObject::~XNModelObject()
{
}
2025-05-20 15:39:40 +08:00
XNModelObject::XNModelObject(PrivateType *p) : XNObject(p)
2025-04-28 12:25:20 +08:00
{
}
2025-05-20 16:41:46 +08:00
void XNModelObject::SetFramework(XNFrameworkPtr framework)
{
T_D();
d->_framework = framework;
}
XNFrameworkPtr XNModelObject::GetFramework() const
{
T_D();
return d->_framework;
}
2025-04-28 12:25:20 +08:00
// 获取模型描述
2025-05-20 15:39:40 +08:00
const std::string &XNModelObject::GetDescription()
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
return d->_sDescription;
}
// 设置模型描述
2025-05-20 15:39:40 +08:00
void XNModelObject::SetDescription(const std::string &sDescription)
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
d->_sDescription = sDescription;
}
// 获取作者
2025-05-20 15:39:40 +08:00
const std::string &XNModelObject::GetAuthor()
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
return d->_sAuthor;
}
// 设置作者
2025-05-20 15:39:40 +08:00
void XNModelObject::SetAuthor(const std::string &sAuthor)
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
d->_sAuthor = sAuthor;
}
// 获取模型配置文件路径
2025-05-20 15:39:40 +08:00
const std::string &XNModelObject::GetXmlPath()
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
return d->_sXmlPath;
}
// 设置模型配置文件路径
2025-05-20 15:39:40 +08:00
void XNModelObject::SetXmlPath(const std::string &sXmlPath)
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
d->_sXmlPath = sXmlPath;
}
// 获取模型创建时间
2025-05-20 15:39:40 +08:00
const XNTimePoint &XNModelObject::GetCreateTime()
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
return d->_cCreatTime;
}
// 设置模型创建时间
2025-05-20 15:39:40 +08:00
void XNModelObject::SetCreateTime(const XNTimePoint &cTime)
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
d->_cCreatTime = cTime;
}
// 获取模型修改时间
2025-05-20 15:39:40 +08:00
const XNTimePoint &XNModelObject::GetChangeTime()
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
return d->_cChangeTime;
}
// 设置模型修改时间
2025-05-20 15:39:40 +08:00
void XNModelObject::SetChangeTime(const XNTimePoint &cTime)
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
d->_cChangeTime = cTime;
}
// 获取模型版本号
2025-05-20 15:39:40 +08:00
const std::string &XNModelObject::GetVersion()
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
return d->_sVersion;
}
// 设置模型版本号
2025-05-20 15:39:40 +08:00
void XNModelObject::SetVersion(const std::string &sVersion)
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
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;
}
2025-04-28 12:25:20 +08:00
// 初始化函数
void XNModelObject::Initialize()
2025-04-28 12:25:20 +08:00
{
// 先尝试调取动态库
2025-05-20 15:39:40 +08:00
T_D();
if (d->_initialType == 0) {
2025-05-20 15:39:40 +08:00
// 读取配置文件,设置循环执行函数
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()) {
2025-04-28 12:25:20 +08:00
LOG_WARNING(
2025-05-20 15:39:40 +08:00
"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,
2025-05-20 15:39:40 +08:00
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: 处理命令列表
}
2025-04-28 12:25:20 +08:00
}
}
}
// 单步执行函数
void XNModelObject::StepUpdate()
{
2025-05-20 15:39:40 +08:00
T_D();
uint32_t setFreq = d->_setFreq < 1.0 ? 1 : (uint32_t)d->_setFreq;
2025-05-22 16:22:48 +08:00
if (d->_dataWriter != nullptr && d->_runCnt > 0 && d->_runCnt % setFreq == 0) {
2025-04-28 12:25:20 +08:00
XNSim::XNSimStatus::XNModelStatus modelStatus;
2025-05-20 15:39:40 +08:00
modelStatus.XNModelName(GetObjectName());
modelStatus.XNModelID(GetUniqueId());
2025-04-28 12:25:20 +08:00
modelStatus.XNModelSt(1);
2025-05-20 15:39:40 +08:00
modelStatus.XNModelThID(d->_threadID);
2025-04-28 12:25:20 +08:00
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);
2025-05-22 16:22:48 +08:00
d->_dataWriter->write(&modelStatus);
2025-04-28 12:25:20 +08:00
d->_lastRunTime = now;
2025-05-20 15:39:40 +08:00
LOG_DEBUG("Model: %1 Write DDS!", GetObjectName());
2025-04-28 12:25:20 +08:00
}
d->_runCnt++;
}
// 运行前最后准备函数
2025-05-20 15:39:40 +08:00
void XNModelObject::PrepareForExecute()
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
T_D();
2025-04-28 12:25:20 +08:00
d->_runCnt = 0;
// 注册DDS
RegisterDDSParticipant();
clock_gettime(CLOCK_MONOTONIC, &d->_lastRunTime);
}
void XNModelObject::RegisterDDSParticipant()
{
2025-05-20 15:39:40 +08:00
T_D();
auto framework = GetFramework();
if (framework == nullptr) {
LOG_WARNING("Failed to get Framework!");
2025-04-28 12:25:20 +08:00
return;
2025-05-20 15:39:40 +08:00
}
auto ddsManager = framework->GetDDSManager();
if (ddsManager == nullptr) {
LOG_WARNING("Failed to get DDSManager!");
2025-04-28 12:25:20 +08:00
return;
2025-05-20 15:39:40 +08:00
}
2025-05-22 16:22:48 +08:00
uint32_t MyID = GetUniqueId();
d->_dataWriter = ddsManager->RegisterPublisher<XNSim::XNSimStatus::XNModelStatusPubSubType>(
"XNSim::XNSimStatus::XNModelStatus", MyID);
2025-04-28 12:25:20 +08:00
}
int XNModelObject::RegisterEventHandler(const std::string &eventName, XNEventCallback callback,
bool async, XNEvent::Priority priority)
2025-04-28 12:25:20 +08:00
{
// 获取事件管理器
2025-05-20 15:39:40 +08:00
auto framework = GetFramework();
if (framework == nullptr) {
LOG_WARNING("Failed to get Framework!");
2025-04-28 12:25:20 +08:00
return -1;
}
2025-05-20 15:39:40 +08:00
XNEventManagerPtr eventManager = framework->GetEventManager();
2025-04-28 12:25:20 +08:00
if (eventManager == nullptr) {
LOG_WARNING("Failed to get EventManager!");
return -1;
}
// 注册事件处理器
2025-05-20 15:39:40 +08:00
return eventManager->RegisterEventHandler(eventName, callback, GetUniqueId(), async, priority);
2025-04-28 12:25:20 +08:00
}
2025-05-20 15:39:40 +08:00
void XNModelObject::TriggerEvent(const std::string &eventName, const std::any &eventData,
2025-04-28 12:25:20 +08:00
bool forceAsync, XNEvent::Priority priority)
{
// 获取事件管理器
2025-05-20 15:39:40 +08:00
auto framework = GetFramework();
if (framework == nullptr) {
LOG_WARNING("Failed to get Framework!");
2025-04-28 12:25:20 +08:00
return;
}
2025-05-20 15:39:40 +08:00
XNEventManagerPtr eventManager = framework->GetEventManager();
2025-04-28 12:25:20 +08:00
if (eventManager == nullptr) {
LOG_WARNING("Failed to get EventManager!");
return;
}
// 触发事件
eventManager->TriggerEvent(eventName, eventData, forceAsync, priority);
}