diff --git a/Release/include/XNCore/XNCore_global.h b/Release/include/XNCore/XNCore_global.h index bc921ab..cf4c785 100644 --- a/Release/include/XNCore/XNCore_global.h +++ b/Release/include/XNCore/XNCore_global.h @@ -92,7 +92,7 @@ using XNTimePoint = std::chrono::system_clock::time_point; * @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss) * @return 系统时间点 */ -XNTimePoint parseISOTime(const std::string &timeStr); +extern "C" XNTimePoint XNCORE_EXPORT parseISOTime(const std::string &timeStr); /** * @brief 系统运行状态枚举类 diff --git a/Release/include/XNCore/XNFramework.h b/Release/include/XNCore/XNFramework.h index 8dc40f6..8e09201 100644 --- a/Release/include/XNCore/XNFramework.h +++ b/Release/include/XNCore/XNFramework.h @@ -146,8 +146,10 @@ public: /** * @brief 准备执行 + * @return true: 准备成功 + * @return false: 准备失败 */ - void PrepareForExecute(); + bool PrepareForExecute(); /** * @brief 仿真控制 @@ -158,12 +160,9 @@ public: /** * @brief 初始化 + * @param initialType 初始化类型 + * @return true: 初始化成功 + * @return false: 初始化失败 */ - void Initialize(uint32_t initialType); - - /** - * @brief 仿真控制 - * @param cmd 命令 - */ - void OnSimControl(uint32_t objectId, SimControlCmd cmd); + bool Initialize(uint32_t initialType); }; diff --git a/XNCore/CMakeLists.txt b/XNCore/CMakeLists.txt index 4a127fc..91d8b7e 100755 --- a/XNCore/CMakeLists.txt +++ b/XNCore/CMakeLists.txt @@ -20,6 +20,7 @@ find_package(OpenSSL REQUIRED) add_library(XNCore SHARED XNCore_global.h + XNCore_Function.cpp XNObject.h XNObject.cpp XNObject_p.h diff --git a/XNCore/XNCore_global.h b/XNCore/XNCore_global.h index bc921ab..cf4c785 100755 --- a/XNCore/XNCore_global.h +++ b/XNCore/XNCore_global.h @@ -92,7 +92,7 @@ using XNTimePoint = std::chrono::system_clock::time_point; * @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss) * @return 系统时间点 */ -XNTimePoint parseISOTime(const std::string &timeStr); +extern "C" XNTimePoint XNCORE_EXPORT parseISOTime(const std::string &timeStr); /** * @brief 系统运行状态枚举类 diff --git a/XNCore/XNFramework.cpp b/XNCore/XNFramework.cpp index 0da5c8c..1fd8676 100755 --- a/XNCore/XNFramework.cpp +++ b/XNCore/XNFramework.cpp @@ -86,95 +86,97 @@ void XNFramework::SetCpuAffinity(uint32_t cpuAffinity) d->uCpuAffinity = cpuAffinity; } -void XNFramework::Initialize(uint32_t initialType) +bool XNFramework::Initialize(uint32_t initialType) { T_D(); LOG_INFO("XNFramework Initialize ..."); bool ret = d->eventManager->Initialize(); if (!ret) { LOG_ERROR("XNFramework Initialize Failed!"); - return; + return false; } ret = d->timeManager->Initialize(); if (!ret) { LOG_ERROR("XNFramework Initialize Failed!"); - return; + return false; } ret = d->ddsManager->Initialize(); if (!ret) { LOG_ERROR("XNFramework Initialize Failed!"); - return; + return false; } ret = d->serviceManager->Initialize(); if (!ret) { LOG_ERROR("XNFramework Initialize Failed!"); - return; + return false; } ret = d->threadManager->Initialize(); if (!ret) { LOG_ERROR("XNFramework Initialize Failed!"); - return; + return false; } ret = d->modelManager->Initialize(); if (!ret) { LOG_ERROR("XNFramework Initialize Failed!"); - return; + return false; } ret = d->scenarioManager->Initialize(); if (!ret) { LOG_ERROR("XNFramework Initialize Failed!"); - return; + return false; } LOG_INFO("XNFramework Initialize Success!"); LOG_INFO("XNFramework Analyze Scenario Xml ..."); ret = d->scenarioManager->AnalysisScenarioXml(d->scenarioXml, initialType); if (!ret) { LOG_ERROR("XNFramework Analyze Scenario Xml Failed!"); - return; + return false; } LOG_INFO("XNFramework Analyze Scenario Xml Success!"); + return true; } -void XNFramework::PrepareForExecute() +bool XNFramework::PrepareForExecute() { T_D(); bool ret = d->eventManager->PrepareForExecute(); if (!ret) { LOG_ERROR("XNFramework PrepareForExecute Failed!"); - return; + return false; } ret = d->timeManager->PrepareForExecute(); if (!ret) { LOG_ERROR("XNFramework PrepareForExecute Failed!"); - return; + return false; } ret = d->ddsManager->PrepareForExecute(); if (!ret) { LOG_ERROR("XNFramework PrepareForExecute Failed!"); - return; + return false; } ret = d->serviceManager->PrepareForExecute(); if (!ret) { LOG_ERROR("XNFramework PrepareForExecute Failed!"); - return; + return false; } ret = d->threadManager->PrepareForExecute(); if (!ret) { LOG_ERROR("XNFramework PrepareForExecute Failed!"); - return; + return false; } ret = d->modelManager->PrepareForExecute(); if (!ret) { LOG_ERROR("XNFramework PrepareForExecute Failed!"); - return; + return false; } ret = d->scenarioManager->PrepareForExecute(); if (!ret) { LOG_ERROR("XNFramework PrepareForExecute Failed!"); - return; + return false; } LOG_INFO("XNCore is prepared for execute! Simulation will start soon..."); + return true; } void XNFramework::SetScenarioXml(const std::string &scenarioXml) diff --git a/XNCore/XNFramework.h b/XNCore/XNFramework.h index 8dc40f6..8e09201 100755 --- a/XNCore/XNFramework.h +++ b/XNCore/XNFramework.h @@ -146,8 +146,10 @@ public: /** * @brief 准备执行 + * @return true: 准备成功 + * @return false: 准备失败 */ - void PrepareForExecute(); + bool PrepareForExecute(); /** * @brief 仿真控制 @@ -158,12 +160,9 @@ public: /** * @brief 初始化 + * @param initialType 初始化类型 + * @return true: 初始化成功 + * @return false: 初始化失败 */ - void Initialize(uint32_t initialType); - - /** - * @brief 仿真控制 - * @param cmd 命令 - */ - void OnSimControl(uint32_t objectId, SimControlCmd cmd); + bool Initialize(uint32_t initialType); }; diff --git a/XNCore/XNModelObject.cpp b/XNCore/XNModelObject.cpp index 74831ba..f4277b9 100755 --- a/XNCore/XNModelObject.cpp +++ b/XNCore/XNModelObject.cpp @@ -30,6 +30,18 @@ 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 std::string &XNModelObject::GetDescription() { diff --git a/XNEngine/.vscode/settings.json b/XNEngine/.vscode/settings.json index f3cb2da..3903441 100755 --- a/XNEngine/.vscode/settings.json +++ b/XNEngine/.vscode/settings.json @@ -68,6 +68,11 @@ "sstream": "cpp", "cinttypes": "cpp", "typeindex": "cpp", - "qcoreapplication": "cpp" + "qcoreapplication": "cpp", + "csignal": "cpp", + "any": "cpp", + "codecvt": "cpp", + "unordered_set": "cpp", + "fstream": "cpp" } } \ No newline at end of file diff --git a/XNEngine/CMakeLists.txt b/XNEngine/CMakeLists.txt index 044da4c..272b914 100755 --- a/XNEngine/CMakeLists.txt +++ b/XNEngine/CMakeLists.txt @@ -2,10 +2,6 @@ cmake_minimum_required(VERSION 3.16) project(XNEngine LANGUAGES CXX) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) - set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -17,54 +13,24 @@ if(NOT fastdds_FOUND) find_package(fastdds 3 REQUIRED) endif() -find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Xml) -find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Xml) find_package(Threads REQUIRED) find_package(OpenSSL REQUIRED) -if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) - qt_add_executable(XNEngine - MANUAL_FINALIZATION - main.cpp - XNEngine.h - XNEngine.cpp - ) - - # 获取Qt库的安装路径 - get_target_property(QT_LIB_DIR Qt${QT_VERSION_MAJOR}::Core LOCATION) - get_filename_component(QT_LIB_DIR ${QT_LIB_DIR} DIRECTORY) - - # 设置rpath - set_target_properties(XNEngine PROPERTIES - BUILD_WITH_INSTALL_RPATH TRUE - INSTALL_RPATH "${QT_LIB_DIR}" - ) -else() - add_executable(XNEngine - main.cpp - XNEngine.h - XNEngine.cpp - ) -endif() +add_executable(XNEngine + main.cpp + XNEngine.h + XNEngine.cpp +) -#if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - find_library(XNCORE_LIBRARY NAMES XNCore PATHS ../XNCore/build) - target_link_libraries(XNEngine PRIVATE - Qt${QT_VERSION_MAJOR}::Core - Qt${QT_VERSION_MAJOR}::Xml - ${XNCORE_LIBRARY} - fastcdr - fastdds - pthread - OpenSSL::SSL - OpenSSL::Crypto - ) -#elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") -# target_link_libraries(XNEngine -# Qt${QT_VERSION_MAJOR}::Core -# Qt${QT_VERSION_MAJOR}::Xml -# XNCore) -#endif() +find_library(XNCORE_LIBRARY NAMES XNCore PATHS ../XNCore/build) +target_link_libraries(XNEngine PRIVATE + ${XNCORE_LIBRARY} + fastcdr + fastdds + pthread + OpenSSL::SSL + OpenSSL::Crypto +) # Check if CMAKE_INSTALL_PREFIX is set to its default value if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) @@ -81,8 +47,4 @@ install(TARGETS XNEngine # Add a post-installation command to set the application icon using gio install(CODE " execute_process(COMMAND gio set -t string ${CMAKE_INSTALL_PREFIX}/XNEngine \"metadata::custom-icon\" \"file://${CMAKE_INSTALL_PREFIX}/resource/XNEngine.png\") -") - -if(QT_VERSION_MAJOR EQUAL 6) - qt_finalize_executable(XNEngine) -endif() \ No newline at end of file +") \ No newline at end of file diff --git a/XNEngine/XNEngine.cpp b/XNEngine/XNEngine.cpp index 36b7b4e..1189ff0 100755 --- a/XNEngine/XNEngine.cpp +++ b/XNEngine/XNEngine.cpp @@ -9,8 +9,6 @@ * */ #include "XNEngine.h" -#include -#include #include "../XNCore/XNTimeManager.h" #include "../XNCore/XNThreadManager.h" #include "../XNCore/XNDDSManager.h" @@ -20,27 +18,16 @@ #include "../XNCore/XNScenarioManager.h" // 引擎类构造函数 -XNEngine::XNEngine(QObject *parent) : QObject(parent) +XNEngine::XNEngine() { - // 设置对象名称 - setObjectName("XNEngine"); // 创建框架对象 framework = new XNFramework(); - // 连接初始化信号和槽 - connect(this, &XNEngine::InitializeSignal, framework, &XNFramework::Initialize); - // 连接准备执行信号和槽 - connect(this, &XNEngine::PrepareforExecuteSignal, framework, &XNFramework::OnPrepareForExecute); - // 连接初始化成功信号和槽 - connect(framework, &XNFramework::InitializeSuccess, this, &XNEngine::OnInitializeSuccess); - // 连接准备执行成功信号和槽 - connect(framework, &XNFramework::PrepareForExecuteSuccess, this, - &XNEngine::OnPrepareforExecuteSuccess); - // 连接仿真控制信号和槽 - connect(this, &XNEngine::SimControlSignal, framework, &XNFramework::OnSimControl); // 引擎状态写入器 engineStatusWriter = nullptr; // 测试模式 isTestMode = false; + // 初始化类型 + initializeType = 0; } // 引擎类析构函数 @@ -53,139 +40,189 @@ void XNEngine::SimControlListener(const XNSim::XNSimControl::XNRuntimeControl &c { if (cmd.XNSimCmd() == 1) { // 如果命令是暂停 - emit SimControlSignal(0, SimControlCmd::Suspend); + framework->SimControl(0, SimControlCmd::Suspend); } else if (cmd.XNSimCmd() == 2) { // 如果命令是继续 - emit SimControlSignal(0, SimControlCmd::Continue); + framework->SimControl(0, SimControlCmd::Continue); } else if (cmd.XNSimCmd() == 3) { // 如果命令是终止 - emit SimControlSignal(0, SimControlCmd::Abort); + framework->SimControl(0, SimControlCmd::Abort); //TODO 后续收到结束指令后再结束,还需要最后发一次终止状态 - emit StopTimer(); - // 退出应用程序 - QCoreApplication::quit(); + engineRunning = false; } } // 设置日志级别 -bool XNEngine::SetLogLevel(const QString &XmlPath) +bool XNEngine::SetLogLevel(const std::string &XmlPath) { // 打开配置文件 - QFile file(XmlPath); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qFatal("0x1003 Failed to open the runtime environment configuration file, " - "the engine will exit!"); + std::ifstream file(XmlPath); + if (!file.is_open()) { + std::cerr << "0x1003 Failed to open the runtime environment configuration file, " + "the engine will exit!" + << std::endl; + return false; } // 解析配置文件 - QDomDocument doc; - if (!doc.setContent(&file)) { - qFatal("0x1004 Failed to parse the runtime environment configuration file, " - "the engine will exit!"); + tinyxml2::XMLDocument doc; + if (doc.LoadFile(XmlPath.c_str()) != tinyxml2::XML_SUCCESS) { + std::cerr << "0x1004 Failed to parse the runtime environment configuration file, " + "the engine will exit!" + << std::endl; + return false; } // 获取根元素 - QDomElement root = doc.documentElement(); + tinyxml2::XMLElement *root = doc.FirstChildElement("RuntimeEnvironment"); + if (!root) { + std::cerr << "0x1005 Failed to find RuntimeEnvironment element in configuration file!" + << std::endl; + return false; + } + // 顺便读取一下CPU亲和性 int cpus = sysconf(_SC_NPROCESSORS_ONLN); - qInfo("Current number of CPU cores-> %d", cpus); + std::cout << "Current number of CPU cores-> " << cpus << std::endl; + // 设置CPU亲和性 cpu_set_t mask; CPU_ZERO(&mask); - CPUAffinity = 0; - QDomNode EnvironmentNode = root.firstChildElement("Environment"); - QString tmp = EnvironmentNode.toElement().attribute("CPUAffinity"); - QStringList cpuAffinityList = tmp.split(",", Qt::SkipEmptyParts); - for (const QString &cpuAffinity : cpuAffinityList) { - bool ok; - quint32 cpuIndex = cpuAffinity.toUInt(&ok); - if (ok && cpuIndex < cpus) { - CPUAffinity |= (1 << cpuIndex); - CPU_SET(cpuIndex, &mask); + CPUAffinity = 0; + + // 获取CPU亲和性配置 + tinyxml2::XMLElement *envNode = root->FirstChildElement("Environment"); + if (envNode) { + const char *cpuAffinityStr = envNode->Attribute("CPUAffinity"); + if (cpuAffinityStr) { + std::string affinityStr(cpuAffinityStr); + std::istringstream iss(affinityStr); + std::string cpuIndex; + while (std::getline(iss, cpuIndex, ',')) { + try { + int index = std::stoi(cpuIndex); + if (index >= 0 && index < cpus) { + CPUAffinity |= (1 << index); + CPU_SET(index, &mask); + } + } catch (const std::exception &e) { + std::cerr << "Invalid CPU affinity value: " << cpuIndex << std::endl; + } + } } } + if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { - qFatal("0x1020 Failed to set engine CPU affinity-> %s", strerror(errno)); + std::cerr << "0x1020 Failed to set engine CPU affinity-> " << strerror(errno) << std::endl; + return false; } - qInfo("Successfully set engine CPU affinity-> %u", CPUAffinity); + std::cout << "Successfully set engine CPU affinity-> " << CPUAffinity << std::endl; + // 锁定内存 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { - qFatal("0x1021 Failed to lock engine memory-> %s", strerror(errno)); + std::cerr << "0x1021 Failed to lock engine memory-> " << strerror(errno) << std::endl; + return false; } - qInfo("Successfully locked engine memory!"); + std::cout << "Successfully locked engine memory!" << std::endl; + // 获取配置文件中的控制台输出元素 - QDomNode consoleOutputNode = root.firstChildElement("ConsoleOutput"); - if (consoleOutputNode.isNull()) { - qWarning("The runtime environment configuration file does not contain" - "the ConsoleOutput element, the Console will Output all Log!"); + tinyxml2::XMLElement *consoleOutputNode = root->FirstChildElement("ConsoleOutput"); + if (!consoleOutputNode) { + std::cout << "The runtime environment configuration file does not contain " + "the ConsoleOutput element, the Console will Output all Log!" + << std::endl; } else { // 获取配置文件中的调试日志输出元素 - QString debugConsoleOutput = consoleOutputNode.toElement().attribute("Debug"); - if (debugConsoleOutput == "true" || debugConsoleOutput == "1" - || debugConsoleOutput == "True" || debugConsoleOutput == "TRUE") { + const char *debugConsoleOutput = consoleOutputNode->Attribute("Debug"); + if (debugConsoleOutput + && (strcmp(debugConsoleOutput, "true") == 0 || strcmp(debugConsoleOutput, "1") == 0 + || strcmp(debugConsoleOutput, "True") == 0 + || strcmp(debugConsoleOutput, "TRUE") == 0)) { XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Debug, true); } else { XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Debug, false); } + // 获取配置文件中的信息日志输出元素 - QString infoConsoleOutput = consoleOutputNode.toElement().attribute("Info"); - if (infoConsoleOutput == "true" || infoConsoleOutput == "1" || infoConsoleOutput == "True" - || infoConsoleOutput == "TRUE") { + const char *infoConsoleOutput = consoleOutputNode->Attribute("Info"); + if (infoConsoleOutput + && (strcmp(infoConsoleOutput, "true") == 0 || strcmp(infoConsoleOutput, "1") == 0 + || strcmp(infoConsoleOutput, "True") == 0 + || strcmp(infoConsoleOutput, "TRUE") == 0)) { XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Info, true); } else { XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Info, false); } + // 获取配置文件中的警告日志输出元素 - QString warningConsoleOutput = consoleOutputNode.toElement().attribute("Warning"); - if (warningConsoleOutput == "true" || warningConsoleOutput == "1" - || warningConsoleOutput == "True" || warningConsoleOutput == "TRUE") { + const char *warningConsoleOutput = consoleOutputNode->Attribute("Warning"); + if (warningConsoleOutput + && (strcmp(warningConsoleOutput, "true") == 0 || strcmp(warningConsoleOutput, "1") == 0 + || strcmp(warningConsoleOutput, "True") == 0 + || strcmp(warningConsoleOutput, "TRUE") == 0)) { XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Warning, true); } else { XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Warning, false); } + // 获取配置文件中的错误日志输出元素 - QString errorConsoleOutput = consoleOutputNode.toElement().attribute("Error"); - if (errorConsoleOutput == "true" || errorConsoleOutput == "1" - || errorConsoleOutput == "True" || errorConsoleOutput == "TRUE") { + const char *errorConsoleOutput = consoleOutputNode->Attribute("Error"); + if (errorConsoleOutput + && (strcmp(errorConsoleOutput, "true") == 0 || strcmp(errorConsoleOutput, "1") == 0 + || strcmp(errorConsoleOutput, "True") == 0 + || strcmp(errorConsoleOutput, "TRUE") == 0)) { XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Error, true); } else { XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Error, false); } } + // 获取配置文件中的日志元素 - QDomNode logNode = root.firstChildElement("Log"); - if (logNode.isNull()) { - qWarning("The runtime environment configuration file does not contain" - "the Log element, the Log File will record all Log!"); + tinyxml2::XMLElement *logNode = root->FirstChildElement("Log"); + if (!logNode) { + std::cout << "The runtime environment configuration file does not contain " + "the Log element, the Log File will record all Log!" + << std::endl; } else { // 获取配置文件中的调试日志输出元素 - QString debugLog = logNode.toElement().attribute("Debug"); - if (debugLog == "true" || debugLog == "1" || debugLog == "True" || debugLog == "TRUE") { + const char *debugLog = logNode->Attribute("Debug"); + if (debugLog + && (strcmp(debugLog, "true") == 0 || strcmp(debugLog, "1") == 0 + || strcmp(debugLog, "True") == 0 || strcmp(debugLog, "TRUE") == 0)) { XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Debug, true); } else { XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Debug, false); } + // 获取配置文件中的信息日志输出元素 - QString infoLog = logNode.toElement().attribute("Info"); - if (infoLog == "true" || infoLog == "1" || infoLog == "True" || infoLog == "TRUE") { + const char *infoLog = logNode->Attribute("Info"); + if (infoLog + && (strcmp(infoLog, "true") == 0 || strcmp(infoLog, "1") == 0 + || strcmp(infoLog, "True") == 0 || strcmp(infoLog, "TRUE") == 0)) { XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Info, true); } else { XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Info, false); } + // 获取配置文件中的警告日志输出元素 - QString warningLog = logNode.toElement().attribute("Warning"); - if (warningLog == "true" || warningLog == "1" || warningLog == "True" - || warningLog == "TRUE") { + const char *warningLog = logNode->Attribute("Warning"); + if (warningLog + && (strcmp(warningLog, "true") == 0 || strcmp(warningLog, "1") == 0 + || strcmp(warningLog, "True") == 0 || strcmp(warningLog, "TRUE") == 0)) { XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Warning, true); } else { XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Warning, false); } + // 获取配置文件中的错误日志输出元素 - QString errorLog = logNode.toElement().attribute("Error"); - if (errorLog == "true" || errorLog == "1" || errorLog == "True" || errorLog == "TRUE") { + const char *errorLog = logNode->Attribute("Error"); + if (errorLog + && (strcmp(errorLog, "true") == 0 || strcmp(errorLog, "1") == 0 + || strcmp(errorLog, "True") == 0 || strcmp(errorLog, "TRUE") == 0)) { XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Error, true); } else { XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Error, false); } } + // 关闭配置文件 file.close(); // 返回成功 @@ -202,19 +239,19 @@ void XNEngine::PublishEngineStatus() // 创建内核状态对象 XNSim::XNSimStatus::XNCoreStatus coreStatus; // 设置引擎名称 - engineStatus.XNEngineName(objectName().toStdString()); + engineStatus.XNEngineName("XNEngine"); // 设置引擎ID engineStatus.XNEngineID(getpid()); // 设置引擎亲和性 engineStatus.XNEngineAff(CPUAffinity); // 获取时间管理器 - XNTimeManager *timeManager = framework->findChild(); + XNTimeManagerPtr timeManager = framework->GetTimeManager(); // 如果时间管理器存在 if (timeManager) { // 设置引擎状态 - engineStatus.XNEngineSt((quint32)timeManager->GetStatus()); + engineStatus.XNEngineSt((uint32_t)timeManager->GetStatus()); // 设置内核状态 - coreStatus.XNTMStatus((quint32)timeManager->GetFrameObjectStatus()); + coreStatus.XNTMStatus((uint32_t)timeManager->GetFrameObjectStatus()); } else { // 设置引擎状态 engineStatus.XNEngineSt(4); @@ -222,11 +259,11 @@ void XNEngine::PublishEngineStatus() coreStatus.XNTMStatus(2); } // 获取线程管理器 - XNThreadManager *threadManager = framework->findChild(); + XNThreadManagerPtr threadManager = framework->GetThreadManager(); // 如果线程管理器存在 if (threadManager) { // 设置内核状态 - coreStatus.XNThMStatus((quint32)threadManager->GetFrameObjectStatus()); + coreStatus.XNThMStatus((uint32_t)threadManager->GetFrameObjectStatus()); // 设置引擎状态 engineStatus.XNThCnt(threadManager->GetThreadCount()); } else { @@ -234,57 +271,57 @@ void XNEngine::PublishEngineStatus() coreStatus.XNThMStatus(2); } // 获取DDS管理器 - XNDDSManager *ddsManager = framework->findChild(); + XNDDSManagerPtr ddsManager = framework->GetDDSManager(); // 如果DDS管理器存在 if (ddsManager) { // 设置内核状态 - coreStatus.XNDMStatus((quint32)ddsManager->GetFrameObjectStatus()); + coreStatus.XNDMStatus((uint32_t)ddsManager->GetFrameObjectStatus()); } else { // 设置内核状态 coreStatus.XNDMStatus(2); } // 获取事件管理器 - XNEventManager *eventManager = framework->findChild(); + XNEventManagerPtr eventManager = framework->GetEventManager(); // 如果事件管理器存在 if (eventManager) { // 设置内核状态 - coreStatus.XNEMStatus((quint32)eventManager->GetFrameObjectStatus()); + coreStatus.XNEMStatus((uint32_t)eventManager->GetFrameObjectStatus()); } else { // 设置内核状态 coreStatus.XNEMStatus(2); } // 获取服务管理器 - XNServiceManager *serviceManager = framework->findChild(); + XNServiceManagerPtr serviceManager = framework->GetServiceManager(); // 如果服务管理器存在 if (serviceManager) { // 设置内核状态 - coreStatus.XNSMStatus((quint32)serviceManager->GetFrameObjectStatus()); + coreStatus.XNSMStatus((uint32_t)serviceManager->GetFrameObjectStatus()); } else { // 设置内核状态 coreStatus.XNSMStatus(2); } // 获取模型管理器 - XNModelManager *modelManager = framework->findChild(); + XNModelManagerPtr modelManager = framework->GetModelManager(); // 如果模型管理器存在 if (modelManager) { // 设置内核状态 - coreStatus.XNMMStatus((quint32)modelManager->GetFrameObjectStatus()); + coreStatus.XNMMStatus((uint32_t)modelManager->GetFrameObjectStatus()); } else { // 设置内核状态 coreStatus.XNMMStatus(2); } // 获取场景管理器 - XNScenarioManager *scenarioManager = framework->findChild(); + XNScenarioManagerPtr scenarioManager = framework->GetScenarioManager(); // 如果场景管理器存在 if (scenarioManager) { // 设置内核状态 - coreStatus.XNSDStatus((quint32)scenarioManager->GetFrameObjectStatus()); + coreStatus.XNSDStatus((uint32_t)scenarioManager->GetFrameObjectStatus()); } else { // 设置内核状态 coreStatus.XNSDStatus(2); } // 设置框架状态 - coreStatus.XNFWStatus((quint32)frameworkStatus); + coreStatus.XNFWStatus((uint32_t)frameworkStatus); // 设置引擎状态 engineStatus.XNCoreSt(coreStatus); // 写入引擎状态 @@ -295,7 +332,7 @@ void XNEngine::PublishEngineStatus() } // 运行引擎 -bool XNEngine::Run(const QString &XmlPath) +bool XNEngine::Run(const std::string &XmlPath) { // 设置日志级别 bool isReady = SetLogLevel(XmlPath); @@ -309,92 +346,75 @@ bool XNEngine::Run(const QString &XmlPath) // 设置CPU亲和性 framework->SetCpuAffinity(CPUAffinity); // 单次触发初始化信号 - QTimer::singleShot(50, [this]() { emit InitializeSignal(); }); + bool ret = framework->Initialize(0); + // 如果初始化失败 + if (!ret) { + // 返回失败 + return false; + } + // 如果初始化成功 + // 设置框架状态 + frameworkStatus = XNFrameObjectStatus::Initialized; + // 记录信息日志 + LOG_INFO("XNEngine Initialize Success!"); + // 如果测试模式 + if (isTestMode) { + // 记录信息日志 + LOG_INFO("Verification passed!"); + // 返回成功 + return true; + } + ret = framework->PrepareForExecute(); + // 如果准备执行失败 + if (!ret) { + // 返回失败 + return false; + } + // 设置框架状态 + frameworkStatus = XNFrameObjectStatus::Ready; + // 获取DDS管理器 + XNDDSManagerPtr ddsManager = framework->GetDDSManager(); + // 如果DDS管理器存在 + if (ddsManager) { + // 注册仿真控制订阅者 + auto func = std::bind(&XNEngine::SimControlListener, this, std::placeholders::_1); + ddsManager->RegisterSubscriber( + "XNSim::XNSimControl::XNRuntimeControl", 0, func); + // 触发仿真控制信号 + framework->SimControl(0, SimControlCmd::Start); + // 注册引擎状态发布者 + engineStatusWriter = + ddsManager->RegisterPublisher( + "XNSim::XNSimStatus::XNEngineStatus", 0); + // 如果引擎状态写入器存在 + if (engineStatusWriter) { + // 设置引擎运行标志 + engineRunning = true; + while (engineRunning) { + // 发布一次初始状态 + PublishEngineStatus(); + // 等待1秒 + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + if (!engineRunning) { + // 取消注册引擎状态发布者 + //ddsManager->UnregisterPublisher("XNSim::XNSimStatus::XNEngineStatus"); + //ddsManager->UnregisterSubscriber("XNSim::XNSimControl::XNRuntimeControl"); + } + } + } else { + // 记录错误日志 + LOG_ERROR("0x1007 Failed to prepare for execution, the engine will exit!"); + } + // 返回成功 return true; } -// 初始化成功 -void XNEngine::OnInitializeSuccess(bool isSuccess) +bool XNEngine::Run(const uint32_t &ConfigId) { - if (isSuccess) { // 如果初始化成功 - // 如果不是测试模式 - if (!isTestMode) { - // 设置框架状态 - frameworkStatus = XNFrameObjectStatus::Initialized; - // 记录信息日志 - LOG_INFO("XNEngine Initialize Success!"); - // 触发准备执行信号 - emit PrepareforExecuteSignal(); - } else { - // 记录信息日志 - LOG_INFO("Verification passed!"); - // 退出应用程序 - QCoreApplication::quit(); - } - } else { // 如果初始化失败 - // 如果不是测试模式 - if (!isTestMode) { - // 设置框架状态 - frameworkStatus = XNFrameObjectStatus::Unknown; - // 记录错误日志 - qFatal("0x1006 Failed to initialize the engine, the engine will exit!"); - } else { - // 记录信息日志 - LOG_INFO("Verification failed!"); - // 退出应用程序 - QCoreApplication::quit(); - } - } + return true; } - -// 准备执行成功 -void XNEngine::OnPrepareforExecuteSuccess(bool isSuccess) -{ - // 如果准备执行成功 - if (isSuccess) { - // 设置框架状态 - frameworkStatus = XNFrameObjectStatus::Ready; - // 获取DDS管理器 - XNDDSManager *ddsManager = framework->findChild(); - // 如果DDS管理器存在 - if (ddsManager) { - // 注册引擎状态发布者 - engineStatusWriter = - ddsManager->RegisterPublisher( - "XNSim::XNSimStatus::XNEngineStatus", 0); - // 如果引擎状态写入器存在 - if (engineStatusWriter) { - // 创建定时器 - QTimer *timer = new QTimer(this); - // 设置定时器对象名称 - timer->setObjectName("XNEngineStatusTimer"); - // 连接定时器超时信号和槽 - connect(timer, &QTimer::timeout, this, &XNEngine::PublishEngineStatus); - // 连接停止定时器信号和槽 - connect(this, &XNEngine::StopTimer, timer, &QTimer::stop, Qt::QueuedConnection); - // 启动定时器 - timer->start(1000); // Timer will trigger every second - } - - // 注册仿真控制订阅者 - auto func = std::bind(&XNEngine::SimControlListener, this, std::placeholders::_1); - ddsManager->RegisterSubscriber( - "XNSim::XNSimControl::XNRuntimeControl", 0, func); - // 触发仿真控制信号 - emit SimControlSignal(0, SimControlCmd::Start); - } else { - // 记录错误日志 - qFatal("0x1007 Failed to prepare for execution, the engine will exit!"); - } - } else { - // 设置框架状态 - frameworkStatus = XNFrameObjectStatus::Unknown; - // 记录错误日志 - qFatal("0x1007 Failed to prepare for execution, the engine will exit!"); - } -} - // 设置测试模式 void XNEngine::SetTestMode(bool isTestMode) { diff --git a/XNEngine/XNEngine.h b/XNEngine/XNEngine.h index c916b10..06f32a7 100755 --- a/XNEngine/XNEngine.h +++ b/XNEngine/XNEngine.h @@ -9,22 +9,20 @@ * */ #include "../XNCore/XNFramework.h" -#include #include #include "../XNCore/XNIDL/XNSimStatusPubSubTypes.hpp" /** * @brief 引擎类 */ -class XNEngine : public QObject +class XNEngine { - Q_OBJECT public: /** * @brief 构造函数 * @param parent 父对象 */ - explicit XNEngine(QObject *parent = nullptr); + explicit XNEngine(); /** * @brief 析构函数 */ @@ -35,33 +33,7 @@ public: */ void SimControlListener(const XNSim::XNSimControl::XNRuntimeControl &cmd); -signals: - /** - * @brief 初始化成功信号 - * @param isSuccess 是否成功 - */ - void InitializeSignal(); - /** - * @brief 分析场景XML信号 - * @param XmlPath 场景XML路径 - */ - void AnalysisScenarioXmlSignal(const QString &XmlPath); - /** - * @brief 准备执行信号 - */ - void PrepareforExecuteSignal(); - /** - * @brief 仿真控制信号 - * @param objectID 对象ID - * @param cmd 仿真控制命令 - */ - void SimControlSignal(quint32 objectID, SimControlCmd cmd); - /** - * @brief 停止定时器信号 - */ - void StopTimer(); - -public slots: +public: /** * @brief 初始化成功槽函数 * @param isSuccess 是否成功 @@ -77,7 +49,13 @@ public slots: * @param XmlPath 场景XML路径 * @return 是否成功 */ - bool Run(const QString &XmlPath); + bool Run(const std::string &XmlPath); + /** + * @brief 运行引擎 + * @param ConfigId 构型ID + * @return 是否成功 + */ + bool Run(const uint32_t &ConfigId); /** * @brief 设置测试模式 * @param isTestMode 是否为测试模式 @@ -90,7 +68,7 @@ private: * @param XmlPath 场景XML路径 * @return 是否成功 */ - bool SetLogLevel(const QString &XmlPath); + bool SetLogLevel(const std::string &XmlPath); /** * @brief 发布引擎状态 */ @@ -100,6 +78,11 @@ private: * @brief 是否为测试模式 */ bool isTestMode; + + /** + * @brief 初始化类型 + */ + uint32_t initializeType; /** * @brief 主框架 */ @@ -115,5 +98,9 @@ private: /** * @brief CPU亲和性 */ - quint32 CPUAffinity; + unsigned int CPUAffinity; + /** + * @brief 引擎运行标志 + */ + std::atomic engineRunning{false}; }; diff --git a/XNEngine/main.cpp b/XNEngine/main.cpp index 83f5486..2a3d100 100755 --- a/XNEngine/main.cpp +++ b/XNEngine/main.cpp @@ -8,8 +8,11 @@ * @copyright Copyright (c) 2025 COMAC * */ -#include +#include +#include +#include #include "XNEngine.h" + /** * @brief 主函数 * @param argc 参数个数 @@ -18,59 +21,85 @@ */ int main(int argc, char *argv[]) { - QCoreApplication a(argc, argv); - - //检测输入参数个数 - if (argc <= 1) { - qFatal("0x1000 The input parameters do not contain the path to the runtime environment " - "configuration file, the engine will exit!"); - } - - //第一个参数必须为运行环境配置文件路径 - QString SecPath = argv[1]; - - //检测第一个参数是否是运行环境配置文件 - //限制以下临时变量的生存 - { - int index = SecPath.lastIndexOf('.'); - if (index != -1) { - QString suffix = SecPath.mid(index); - if (suffix != QString(".xml") && suffix != QString(".sce")) { - qFatal("0x1001 The runtime environment configuration file is not a .xml or .sce " - "file, the engine will exit!"); - } - } else { - qFatal("0x1002 The runtime environment configuration file is not a .xml or .sce " - "file, the engine will exit!"); - } - } - XNEngine engine; - quint32 frameworkType = 0; - //依次读取其它附加参数 - for (int i = 2; i < argc;) { - QString arg = argv[i]; - //TODO Error1003 ~ 101f - if ("-fw" == arg) { + //检测输入参数个数 + if (argc <= 2) { + std::cerr << "0x1000 The input parameters is too less!" << std::endl; + return -1; + } + + std::string configPath; + std::string configId; + bool hasConfigPath = false; + bool hasConfigId = false; + + //检查是否包含-f和-id参数 + for (int i = 1; i < argc;) { + std::string arg = argv[i]; + if ("-f" == arg) { if ((i + 1) < argc) { - frameworkType = atoi(argv[i + 1]); + configPath = argv[i + 1]; + hasConfigPath = true; i += 2; } else { - qFatal("0x1003 After the -fw parameter, the framework type is not specified, the " - "engine will exit!"); + std::cerr << "0x1004 After the -f parameter, the configuration file path is not " + "specified, " + "the engine will exit!" + << std::endl; + return -1; + } + } else if ("-id" == arg) { + if ((i + 1) < argc) { + configId = argv[i + 1]; + hasConfigId = true; + i += 2; + } else { + std::cerr + << "0x1005 After the -id parameter, the configuration ID is not specified, " + "the engine will exit!" + << std::endl; + return -1; } } else if ("-test" == arg) { engine.SetTestMode(true); i++; } else { - i++; + std::cerr << "0x1007 The parameter " << arg << " is not valid, the engine will exit!" + << std::endl; + return -1; } - //TODO 其它参数解析 } - // 引擎运行 - bool isReady = engine.Run(SecPath); - if (!isReady) + //检查是否同时包含-f和-id参数 + if (!hasConfigPath || !hasConfigId) { + std::cerr + << "0x1006 Please specify either -f or -id , but not both. " + "The engine will exit!" + << std::endl; return -1; - return a.exec(); + } + + //检测配置文件格式 + if (hasConfigPath) { + size_t index = configPath.find_last_of('.'); + if (index != std::string::npos) { + std::string suffix = configPath.substr(index); + if (suffix != ".xml" && suffix != ".sce") { + std::cerr << "0x1001 The configuration file is not a .xml or .sce " + "file, the engine will exit!" + << std::endl; + return -1; + } + } else { + std::cerr << "0x1002 The configuration file is not a .xml or .sce " + "file, the engine will exit!" + << std::endl; + return -1; + } + return engine.Run(configPath); + } else if (hasConfigId) { + return engine.Run(configId); + } + // 引擎运行 + return engine.Run(configId); }