XNSim/XNCore_Win/XNModelObject/XNModelObject.cpp

479 lines
13 KiB
C++

/**
* @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::XNModelStatusPubSubType>(
"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