XNSim/XNEngine/XNEngine.cpp

424 lines
13 KiB
C++
Raw Normal View History

2025-04-28 12:25:20 +08:00
/**
* @file XNEngine.cpp
* @author jinchao
* @brief
* @version 1.0
* @date 2025-02-14
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#include "XNEngine.h"
#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"
// 引擎类构造函数
2025-05-20 16:41:46 +08:00
XNEngine::XNEngine()
2025-04-28 12:25:20 +08:00
{
// 创建框架对象
framework = new XNFramework();
// 引擎状态写入器
engineStatusWriter = nullptr;
// 测试模式
isTestMode = false;
2025-05-20 16:41:46 +08:00
// 初始化类型
initializeType = 0;
2025-04-28 12:25:20 +08:00
}
// 引擎类析构函数
XNEngine::~XNEngine()
{
}
// 仿真控制监听器
void XNEngine::SimControlListener(const XNSim::XNSimControl::XNRuntimeControl &cmd)
{
if (cmd.XNSimCmd() == 1) {
// 如果命令是暂停
2025-05-20 16:41:46 +08:00
framework->SimControl(0, SimControlCmd::Suspend);
2025-04-28 12:25:20 +08:00
} else if (cmd.XNSimCmd() == 2) {
// 如果命令是继续
2025-05-20 16:41:46 +08:00
framework->SimControl(0, SimControlCmd::Continue);
2025-04-28 12:25:20 +08:00
} else if (cmd.XNSimCmd() == 3) {
// 如果命令是终止
2025-05-20 16:41:46 +08:00
framework->SimControl(0, SimControlCmd::Abort);
2025-04-28 12:25:20 +08:00
//TODO 后续收到结束指令后再结束,还需要最后发一次终止状态
2025-05-20 16:41:46 +08:00
engineRunning = false;
2025-04-28 12:25:20 +08:00
}
}
// 设置日志级别
2025-05-20 16:41:46 +08:00
bool XNEngine::SetLogLevel(const std::string &XmlPath)
2025-04-28 12:25:20 +08:00
{
// 打开配置文件
2025-05-20 16:41:46 +08:00
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;
2025-04-28 12:25:20 +08:00
}
// 解析配置文件
2025-05-20 16:41:46 +08:00
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;
2025-04-28 12:25:20 +08:00
}
// 获取根元素
2025-05-20 16:41:46 +08:00
tinyxml2::XMLElement *root = doc.FirstChildElement("RuntimeEnvironment");
if (!root) {
std::cerr << "0x1005 Failed to find RuntimeEnvironment element in configuration file!"
<< std::endl;
return false;
}
2025-04-28 12:25:20 +08:00
// 顺便读取一下CPU亲和性
int cpus = sysconf(_SC_NPROCESSORS_ONLN);
2025-05-20 16:41:46 +08:00
std::cout << "Current number of CPU cores-> " << cpus << std::endl;
2025-04-28 12:25:20 +08:00
// 设置CPU亲和性
cpu_set_t mask;
CPU_ZERO(&mask);
2025-05-20 16:41:46 +08:00
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;
}
}
2025-04-28 12:25:20 +08:00
}
}
2025-05-20 16:41:46 +08:00
2025-04-28 12:25:20 +08:00
if (sched_setaffinity(0, sizeof(mask), &mask) == -1) {
2025-05-20 16:41:46 +08:00
std::cerr << "0x1020 Failed to set engine CPU affinity-> " << strerror(errno) << std::endl;
return false;
2025-04-28 12:25:20 +08:00
}
2025-05-20 16:41:46 +08:00
std::cout << "Successfully set engine CPU affinity-> " << CPUAffinity << std::endl;
2025-04-28 12:25:20 +08:00
// 锁定内存
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
2025-05-20 16:41:46 +08:00
std::cerr << "0x1021 Failed to lock engine memory-> " << strerror(errno) << std::endl;
return false;
2025-04-28 12:25:20 +08:00
}
2025-05-20 16:41:46 +08:00
std::cout << "Successfully locked engine memory!" << std::endl;
2025-04-28 12:25:20 +08:00
// 获取配置文件中的控制台输出元素
2025-05-20 16:41:46 +08:00
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;
2025-04-28 12:25:20 +08:00
} else {
// 获取配置文件中的调试日志输出元素
2025-05-20 16:41:46 +08:00
const char *debugConsoleOutput = consoleOutputNode->Attribute("Debug");
if (debugConsoleOutput
&& (strcmp(debugConsoleOutput, "true") == 0 || strcmp(debugConsoleOutput, "1") == 0
|| strcmp(debugConsoleOutput, "True") == 0
|| strcmp(debugConsoleOutput, "TRUE") == 0)) {
2025-04-28 12:25:20 +08:00
XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Debug, true);
} else {
XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Debug, false);
}
2025-05-20 16:41:46 +08:00
2025-04-28 12:25:20 +08:00
// 获取配置文件中的信息日志输出元素
2025-05-20 16:41:46 +08:00
const char *infoConsoleOutput = consoleOutputNode->Attribute("Info");
if (infoConsoleOutput
&& (strcmp(infoConsoleOutput, "true") == 0 || strcmp(infoConsoleOutput, "1") == 0
|| strcmp(infoConsoleOutput, "True") == 0
|| strcmp(infoConsoleOutput, "TRUE") == 0)) {
2025-04-28 12:25:20 +08:00
XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Info, true);
} else {
XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Info, false);
}
2025-05-20 16:41:46 +08:00
2025-04-28 12:25:20 +08:00
// 获取配置文件中的警告日志输出元素
2025-05-20 16:41:46 +08:00
const char *warningConsoleOutput = consoleOutputNode->Attribute("Warning");
if (warningConsoleOutput
&& (strcmp(warningConsoleOutput, "true") == 0 || strcmp(warningConsoleOutput, "1") == 0
|| strcmp(warningConsoleOutput, "True") == 0
|| strcmp(warningConsoleOutput, "TRUE") == 0)) {
2025-04-28 12:25:20 +08:00
XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Warning, true);
} else {
XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Warning, false);
}
2025-05-20 16:41:46 +08:00
2025-04-28 12:25:20 +08:00
// 获取配置文件中的错误日志输出元素
2025-05-20 16:41:46 +08:00
const char *errorConsoleOutput = consoleOutputNode->Attribute("Error");
if (errorConsoleOutput
&& (strcmp(errorConsoleOutput, "true") == 0 || strcmp(errorConsoleOutput, "1") == 0
|| strcmp(errorConsoleOutput, "True") == 0
|| strcmp(errorConsoleOutput, "TRUE") == 0)) {
2025-04-28 12:25:20 +08:00
XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Error, true);
} else {
XNLogger::instance().enableConsoleOutput(XNLogger::LogLevel::Error, false);
}
}
2025-05-20 16:41:46 +08:00
2025-04-28 12:25:20 +08:00
// 获取配置文件中的日志元素
2025-05-20 16:41:46 +08:00
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;
2025-04-28 12:25:20 +08:00
} else {
// 获取配置文件中的调试日志输出元素
2025-05-20 16:41:46 +08:00
const char *debugLog = logNode->Attribute("Debug");
if (debugLog
&& (strcmp(debugLog, "true") == 0 || strcmp(debugLog, "1") == 0
|| strcmp(debugLog, "True") == 0 || strcmp(debugLog, "TRUE") == 0)) {
2025-04-28 12:25:20 +08:00
XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Debug, true);
} else {
XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Debug, false);
}
2025-05-20 16:41:46 +08:00
2025-04-28 12:25:20 +08:00
// 获取配置文件中的信息日志输出元素
2025-05-20 16:41:46 +08:00
const char *infoLog = logNode->Attribute("Info");
if (infoLog
&& (strcmp(infoLog, "true") == 0 || strcmp(infoLog, "1") == 0
|| strcmp(infoLog, "True") == 0 || strcmp(infoLog, "TRUE") == 0)) {
2025-04-28 12:25:20 +08:00
XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Info, true);
} else {
XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Info, false);
}
2025-05-20 16:41:46 +08:00
2025-04-28 12:25:20 +08:00
// 获取配置文件中的警告日志输出元素
2025-05-20 16:41:46 +08:00
const char *warningLog = logNode->Attribute("Warning");
if (warningLog
&& (strcmp(warningLog, "true") == 0 || strcmp(warningLog, "1") == 0
|| strcmp(warningLog, "True") == 0 || strcmp(warningLog, "TRUE") == 0)) {
2025-04-28 12:25:20 +08:00
XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Warning, true);
} else {
XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Warning, false);
}
2025-05-20 16:41:46 +08:00
2025-04-28 12:25:20 +08:00
// 获取配置文件中的错误日志输出元素
2025-05-20 16:41:46 +08:00
const char *errorLog = logNode->Attribute("Error");
if (errorLog
&& (strcmp(errorLog, "true") == 0 || strcmp(errorLog, "1") == 0
|| strcmp(errorLog, "True") == 0 || strcmp(errorLog, "TRUE") == 0)) {
2025-04-28 12:25:20 +08:00
XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Error, true);
} else {
XNLogger::instance().enableFileOutput(XNLogger::LogLevel::Error, false);
}
}
2025-05-20 16:41:46 +08:00
2025-04-28 12:25:20 +08:00
// 关闭配置文件
file.close();
// 返回成功
return true;
}
// 发布引擎状态
void XNEngine::PublishEngineStatus()
{
// 如果引擎状态写入器存在
if (engineStatusWriter) {
// 创建引擎状态对象
XNSim::XNSimStatus::XNEngineStatus engineStatus;
// 创建内核状态对象
XNSim::XNSimStatus::XNCoreStatus coreStatus;
// 设置引擎名称
2025-05-20 16:41:46 +08:00
engineStatus.XNEngineName("XNEngine");
2025-04-28 12:25:20 +08:00
// 设置引擎ID
engineStatus.XNEngineID(getpid());
// 设置引擎亲和性
engineStatus.XNEngineAff(CPUAffinity);
// 获取时间管理器
2025-05-20 16:41:46 +08:00
XNTimeManagerPtr timeManager = framework->GetTimeManager();
2025-04-28 12:25:20 +08:00
// 如果时间管理器存在
if (timeManager) {
// 设置引擎状态
2025-05-20 16:41:46 +08:00
engineStatus.XNEngineSt((uint32_t)timeManager->GetStatus());
2025-04-28 12:25:20 +08:00
// 设置内核状态
2025-05-20 16:41:46 +08:00
coreStatus.XNTMStatus((uint32_t)timeManager->GetFrameObjectStatus());
2025-04-28 12:25:20 +08:00
} else {
// 设置引擎状态
engineStatus.XNEngineSt(4);
// 设置内核状态
coreStatus.XNTMStatus(2);
}
// 获取线程管理器
2025-05-20 16:41:46 +08:00
XNThreadManagerPtr threadManager = framework->GetThreadManager();
2025-04-28 12:25:20 +08:00
// 如果线程管理器存在
if (threadManager) {
// 设置内核状态
2025-05-20 16:41:46 +08:00
coreStatus.XNThMStatus((uint32_t)threadManager->GetFrameObjectStatus());
2025-04-28 12:25:20 +08:00
// 设置引擎状态
engineStatus.XNThCnt(threadManager->GetThreadCount());
} else {
// 设置内核状态
coreStatus.XNThMStatus(2);
}
// 获取DDS管理器
2025-05-20 16:41:46 +08:00
XNDDSManagerPtr ddsManager = framework->GetDDSManager();
2025-04-28 12:25:20 +08:00
// 如果DDS管理器存在
if (ddsManager) {
// 设置内核状态
2025-05-20 16:41:46 +08:00
coreStatus.XNDMStatus((uint32_t)ddsManager->GetFrameObjectStatus());
2025-04-28 12:25:20 +08:00
} else {
// 设置内核状态
coreStatus.XNDMStatus(2);
}
// 获取事件管理器
2025-05-20 16:41:46 +08:00
XNEventManagerPtr eventManager = framework->GetEventManager();
2025-04-28 12:25:20 +08:00
// 如果事件管理器存在
if (eventManager) {
// 设置内核状态
2025-05-20 16:41:46 +08:00
coreStatus.XNEMStatus((uint32_t)eventManager->GetFrameObjectStatus());
2025-04-28 12:25:20 +08:00
} else {
// 设置内核状态
coreStatus.XNEMStatus(2);
}
// 获取服务管理器
2025-05-20 16:41:46 +08:00
XNServiceManagerPtr serviceManager = framework->GetServiceManager();
2025-04-28 12:25:20 +08:00
// 如果服务管理器存在
if (serviceManager) {
// 设置内核状态
2025-05-20 16:41:46 +08:00
coreStatus.XNSMStatus((uint32_t)serviceManager->GetFrameObjectStatus());
2025-04-28 12:25:20 +08:00
} else {
// 设置内核状态
coreStatus.XNSMStatus(2);
}
// 获取模型管理器
2025-05-20 16:41:46 +08:00
XNModelManagerPtr modelManager = framework->GetModelManager();
2025-04-28 12:25:20 +08:00
// 如果模型管理器存在
if (modelManager) {
// 设置内核状态
2025-05-20 16:41:46 +08:00
coreStatus.XNMMStatus((uint32_t)modelManager->GetFrameObjectStatus());
2025-04-28 12:25:20 +08:00
} else {
// 设置内核状态
coreStatus.XNMMStatus(2);
}
// 获取场景管理器
2025-05-20 16:41:46 +08:00
XNScenarioManagerPtr scenarioManager = framework->GetScenarioManager();
2025-04-28 12:25:20 +08:00
// 如果场景管理器存在
if (scenarioManager) {
// 设置内核状态
2025-05-20 16:41:46 +08:00
coreStatus.XNSDStatus((uint32_t)scenarioManager->GetFrameObjectStatus());
2025-04-28 12:25:20 +08:00
} else {
// 设置内核状态
coreStatus.XNSDStatus(2);
}
// 设置框架状态
2025-05-20 16:41:46 +08:00
coreStatus.XNFWStatus((uint32_t)frameworkStatus);
2025-04-28 12:25:20 +08:00
// 设置引擎状态
engineStatus.XNCoreSt(coreStatus);
// 写入引擎状态
engineStatusWriter->write(&engineStatus);
// 记录调试日志
LOG_DEBUG("XNEngine Write DDS!");
}
}
// 运行引擎
2025-05-20 16:41:46 +08:00
bool XNEngine::Run(const std::string &XmlPath)
2025-04-28 12:25:20 +08:00
{
// 设置日志级别
bool isReady = SetLogLevel(XmlPath);
// 如果设置日志级别失败
if (!isReady) {
// 返回失败
return false;
}
// 设置场景XML路径
framework->SetScenarioXml(XmlPath);
// 设置CPU亲和性
framework->SetCpuAffinity(CPUAffinity);
// 单次触发初始化信号
2025-05-20 16:41:46 +08:00
bool ret = framework->Initialize(0);
// 如果初始化失败
if (!ret) {
// 返回失败
return false;
2025-04-28 12:25:20 +08:00
}
2025-05-20 16:41:46 +08:00
// 如果初始化成功
// 设置框架状态
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::XNRuntimeControlPubSubType>(
"XNSim::XNSimControl::XNRuntimeControl", 0, func);
// 触发仿真控制信号
framework->SimControl(0, SimControlCmd::Start);
// 注册引擎状态发布者
engineStatusWriter =
ddsManager->RegisterPublisher<XNSim::XNSimStatus::XNEngineStatusPubSubType>(
"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");
2025-04-28 12:25:20 +08:00
}
}
} else {
// 记录错误日志
2025-05-20 16:41:46 +08:00
LOG_ERROR("0x1007 Failed to prepare for execution, the engine will exit!");
2025-04-28 12:25:20 +08:00
}
2025-05-20 16:41:46 +08:00
// 返回成功
return true;
2025-04-28 12:25:20 +08:00
}
2025-05-20 16:41:46 +08:00
bool XNEngine::Run(const uint32_t &ConfigId)
{
return true;
}
2025-04-28 12:25:20 +08:00
// 设置测试模式
void XNEngine::SetTestMode(bool isTestMode)
{
// 设置测试模式
this->isTestMode = isTestMode;
}