/** * @file XNEngine.cpp * @author jinchao * @brief 引擎类 * @version 1.0 * @date 2025-02-14 * * @copyright Copyright (c) 2025 COMAC * */ #include "XNEngine.h" #include #include #include "../XNCore/XNTimeManager.h" #include "../XNCore/XNThreadManager.h" #include "../XNCore/XNDDSManager.h" #include "../XNCore/XNEventManager.h" #include "../XNCore/XNServiceManager.h" #include "../XNCore/XNModelManager.h" #include "../XNCore/XNScenarioManager.h" // 引擎类构造函数 XNEngine::XNEngine(QObject *parent) : QObject(parent) { // 设置对象名称 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; } // 引擎类析构函数 XNEngine::~XNEngine() { } // 仿真控制监听器 void XNEngine::SimControlListener(const XNSim::XNSimControl::XNRuntimeControl &cmd) { if (cmd.XNSimCmd() == 1) { // 如果命令是暂停 emit SimControlSignal(0, SimControlCmd::Suspend); } else if (cmd.XNSimCmd() == 2) { // 如果命令是继续 emit SimControlSignal(0, SimControlCmd::Continue); } else if (cmd.XNSimCmd() == 3) { // 如果命令是终止 emit SimControlSignal(0, SimControlCmd::Abort); //TODO 后续收到结束指令后再结束,还需要最后发一次终止状态 emit StopTimer(); // 退出应用程序 QCoreApplication::quit(); } } // 设置日志级别 bool XNEngine::SetLogLevel(const QString &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!"); } // 解析配置文件 QDomDocument doc; if (!doc.setContent(&file)) { qFatal("0x1004 Failed to parse the runtime environment configuration file, " "the engine will exit!"); } // 获取根元素 QDomElement root = doc.documentElement(); // 顺便读取一下CPU亲和性 int cpus = sysconf(_SC_NPROCESSORS_ONLN); qInfo("Current number of CPU cores-> %d", cpus); // 设置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); } } if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { qFatal("0x1020 Failed to set engine CPU affinity-> %s", strerror(errno)); } qInfo("Successfully set engine CPU affinity-> %u", CPUAffinity); // 锁定内存 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { qFatal("0x1021 Failed to lock engine memory-> %s", strerror(errno)); } qInfo("Successfully locked engine memory!"); // 获取配置文件中的控制台输出元素 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!"); } else { // 获取配置文件中的调试日志输出元素 QString debugConsoleOutput = consoleOutputNode.toElement().attribute("Debug"); if (debugConsoleOutput == "true" || debugConsoleOutput == "1" || debugConsoleOutput == "True" || debugConsoleOutput == "TRUE") { 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") { 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") { 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") { 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!"); } else { // 获取配置文件中的调试日志输出元素 QString debugLog = logNode.toElement().attribute("Debug"); if (debugLog == "true" || debugLog == "1" || debugLog == "True" || debugLog == "TRUE") { 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") { 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") { 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") { XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Error, true); } else { XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Error, false); } } // 关闭配置文件 file.close(); // 返回成功 return true; } // 发布引擎状态 void XNEngine::PublishEngineStatus() { // 如果引擎状态写入器存在 if (engineStatusWriter) { // 创建引擎状态对象 XNSim::XNSimStatus::XNEngineStatus engineStatus; // 创建内核状态对象 XNSim::XNSimStatus::XNCoreStatus coreStatus; // 设置引擎名称 engineStatus.XNEngineName(objectName().toStdString()); // 设置引擎ID engineStatus.XNEngineID(getpid()); // 设置引擎亲和性 engineStatus.XNEngineAff(CPUAffinity); // 获取时间管理器 XNTimeManager *timeManager = framework->findChild(); // 如果时间管理器存在 if (timeManager) { // 设置引擎状态 engineStatus.XNEngineSt((quint32)timeManager->GetStatus()); // 设置内核状态 coreStatus.XNTMStatus((quint32)timeManager->GetFrameObjectStatus()); } else { // 设置引擎状态 engineStatus.XNEngineSt(4); // 设置内核状态 coreStatus.XNTMStatus(2); } // 获取线程管理器 XNThreadManager *threadManager = framework->findChild(); // 如果线程管理器存在 if (threadManager) { // 设置内核状态 coreStatus.XNThMStatus((quint32)threadManager->GetFrameObjectStatus()); // 设置引擎状态 engineStatus.XNThCnt(threadManager->GetThreadCount()); } else { // 设置内核状态 coreStatus.XNThMStatus(2); } // 获取DDS管理器 XNDDSManager *ddsManager = framework->findChild(); // 如果DDS管理器存在 if (ddsManager) { // 设置内核状态 coreStatus.XNDMStatus((quint32)ddsManager->GetFrameObjectStatus()); } else { // 设置内核状态 coreStatus.XNDMStatus(2); } // 获取事件管理器 XNEventManager *eventManager = framework->findChild(); // 如果事件管理器存在 if (eventManager) { // 设置内核状态 coreStatus.XNEMStatus((quint32)eventManager->GetFrameObjectStatus()); } else { // 设置内核状态 coreStatus.XNEMStatus(2); } // 获取服务管理器 XNServiceManager *serviceManager = framework->findChild(); // 如果服务管理器存在 if (serviceManager) { // 设置内核状态 coreStatus.XNSMStatus((quint32)serviceManager->GetFrameObjectStatus()); } else { // 设置内核状态 coreStatus.XNSMStatus(2); } // 获取模型管理器 XNModelManager *modelManager = framework->findChild(); // 如果模型管理器存在 if (modelManager) { // 设置内核状态 coreStatus.XNMMStatus((quint32)modelManager->GetFrameObjectStatus()); } else { // 设置内核状态 coreStatus.XNMMStatus(2); } // 获取场景管理器 XNScenarioManager *scenarioManager = framework->findChild(); // 如果场景管理器存在 if (scenarioManager) { // 设置内核状态 coreStatus.XNSDStatus((quint32)scenarioManager->GetFrameObjectStatus()); } else { // 设置内核状态 coreStatus.XNSDStatus(2); } // 设置框架状态 coreStatus.XNFWStatus((quint32)frameworkStatus); // 设置引擎状态 engineStatus.XNCoreSt(coreStatus); // 写入引擎状态 engineStatusWriter->write(&engineStatus); // 记录调试日志 LOG_DEBUG("XNEngine Write DDS!"); } } // 运行引擎 bool XNEngine::Run(const QString &XmlPath) { // 设置日志级别 bool isReady = SetLogLevel(XmlPath); // 如果设置日志级别失败 if (!isReady) { // 返回失败 return false; } // 设置场景XML路径 framework->SetScenarioXml(XmlPath); // 设置CPU亲和性 framework->SetCpuAffinity(CPUAffinity); // 单次触发初始化信号 QTimer::singleShot(50, [this]() { emit InitializeSignal(); }); // 返回成功 return true; } // 初始化成功 void XNEngine::OnInitializeSuccess(bool isSuccess) { 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(); } } } // 准备执行成功 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) { // 设置测试模式 this->isTestMode = isTestMode; }