#include #include #include #include #include "BinocularMarkPresenter.h" #include "BinocularMarkTcpProtocol.h" #include "PathManager.h" #include "Version.h" #include "VrLog.h" #include "IVrUtils.h" #include "binocularMarkCam_Export.h" int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); // 设置应用程序信息 app.setApplicationName(BINOCULAR_MARK_PRODUCT_NAME); app.setApplicationVersion(BINOCULAR_MARK_VERSION_STRING); app.setOrganizationName(BINOCULAR_MARK_COMPANY_NAME); // 初始化日志 VrLogUtils::InitLog(); VrLogUtils::EnableTime(false); // 打印启动横幅 LOG_DEBUG("===========================================\n"); LOG_INFO(" %s\n", BINOCULAR_MARK_PRODUCT_NAME); LOG_INFO(" %s\n", BINOCULAR_MARK_VERSION_STRING); LOG_INFO(" %s\n", BINOCULAR_MARK_VERSION_BUILD); LOG_DEBUG("===========================================\n"); // 打印算法版本 const char* algoVersion = wd_charuco3DMarkVersion(); LOG_INFO("Algorithm Version: %s\n", algoVersion); // 注册自定义类型用于信号槽 qRegisterMetaType>("std::vector"); qRegisterMetaType("cv::Mat"); // 创建Presenter和TCP协议处理对象 BinocularMarkPresenter presenter; BinocularMarkTcpProtocol tcpProtocol; // 连接信号槽 QObject::connect(&presenter, &BinocularMarkPresenter::detectionResult, &tcpProtocol, &BinocularMarkTcpProtocol::sendMarkResult); QObject::connect(&presenter, &BinocularMarkPresenter::singleDetectionResult, &tcpProtocol, &BinocularMarkTcpProtocol::sendSingleDetectionResult); QObject::connect(&presenter, &BinocularMarkPresenter::singleImageResult, &tcpProtocol, &BinocularMarkTcpProtocol::sendImageData); QObject::connect(&presenter, &BinocularMarkPresenter::cameraInfoResult, &tcpProtocol, &BinocularMarkTcpProtocol::sendCameraInfoResponse); QObject::connect(&presenter, &BinocularMarkPresenter::calibrationMatrixResult, &tcpProtocol, &BinocularMarkTcpProtocol::sendCalibrationMatrixResponse); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::singleDetectionRequested, &presenter, &BinocularMarkPresenter::handleSingleDetection); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::singleImageRequested, &presenter, &BinocularMarkPresenter::handleSingleImage); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::startWorkRequested, &presenter, &BinocularMarkPresenter::handleStartWork); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::stopWorkRequested, &presenter, &BinocularMarkPresenter::handleStopWork); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::startContinuousImageRequested, &presenter, &BinocularMarkPresenter::handleStartContinuousImage); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::stopContinuousImageRequested, &presenter, &BinocularMarkPresenter::handleStopContinuousImage); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::setExposureTimeRequested, &presenter, &BinocularMarkPresenter::handleSetExposureTime); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::setGainRequested, &presenter, &BinocularMarkPresenter::handleSetGain); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::setLeftExposureTimeRequested, &presenter, &BinocularMarkPresenter::handleSetLeftExposureTime); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::setRightExposureTimeRequested, &presenter, &BinocularMarkPresenter::handleSetRightExposureTime); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::setLeftGainRequested, &presenter, &BinocularMarkPresenter::handleSetLeftGain); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::setRightGainRequested, &presenter, &BinocularMarkPresenter::handleSetRightGain); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::getCameraInfoRequested, &presenter, &BinocularMarkPresenter::handleGetCameraInfo); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::getCalibrationRequested, &presenter, &BinocularMarkPresenter::handleGetCalibration); QObject::connect(&tcpProtocol, &BinocularMarkTcpProtocol::setCalibrationRequested, &presenter, &BinocularMarkPresenter::handleSetCalibration); // 获取配置文件路径(通过 PathManager 自动判断加密或明文) QString configFilePath = PathManager::GetInstance().GetConfigFilePath(); // 加载配置文件 if (!presenter.loadConfiguration(configFilePath)) { LOG_WARN("Warning: Failed to load configuration file. Using default settings.\n"); LOG_INFO("Config file location: %s\n", configFilePath.toStdString().c_str()); } // 启动TCP服务器 quint16 serverPort = presenter.getServerPort(); if (serverPort == 0) { serverPort = 5901; // 默认端口 } if (!tcpProtocol.startServer(serverPort)) { LOG_ERROR("Failed to start TCP server on port %d\n", serverPort); return -1; } // 不需要向外的心跳,客户端会发送心跳 // tcpProtocol.startHeartbeat(30); // 初始化双目相机(不启动采集线程,等待cmd_start_work命令) int cameraResult = presenter.initCameras(); if (cameraResult != 0) { LOG_WARN("Failed to initialize cameras, will retry on client request\n"); } // 设置版本信息文本:版本号 + 编译时间 QString versionText = QString("%1_%2_%3") .arg(BINOCULAR_MARK_VERSION_STRING) .arg(BINOCULAR_MARK_VERSION_BUILD) .arg(BUILD_TIME.c_str()); // 输出系统信息 LOG_INFO("=== BinocularMark Server Started %s ===\n", versionText.toStdString().c_str()); LOG_INFO("Server is running on port %d\n", serverPort); LOG_INFO("Press Ctrl+C to exit.\n"); #if 0 // 将 0 改为 1 可启用模拟线程 #ifdef _WIN32 LOG_INFO("Simulation thread started - sending test data every 5 seconds\n"); // 模拟线程:定期发送模拟的 Mark 检测结果 std::thread testThread([&presenter]() { QThread::sleep(5); // 等待5秒,确保系统启动完成 int frameCounter = 0; while (true) { // 生成模拟的 Mark 数据 std::vector simulatedMarks; // 模拟检测到 4 个 Mark for (int i = 0; i < 4; i++) { SWD_charuco3DMark mark; mark.mark3D.markID = i; // 模拟位置:在 (100, 200, 300) 附近随机分布 mark.mark3D.x = 100.0 + (rand() % 100 - 50) / 10.0; // 95.0 ~ 105.0 mark.mark3D.y = 200.0 + (rand() % 100 - 50) / 10.0; // 195.0 ~ 205.0 mark.mark3D.z = 300.0 + (rand() % 100 - 50) / 10.0; // 295.0 ~ 305.0 simulatedMarks.push_back(mark); } // 生成模拟图像(640x480 灰度图) cv::Mat simulatedLeftImage(480, 640, CV_8UC1, cv::Scalar(128)); cv::Mat simulatedRightImage(480, 640, CV_8UC1, cv::Scalar(120)); // 在图像上绘制一些标记 for (size_t i = 0; i < simulatedMarks.size(); i++) { cv::Point center(100 + i * 150, 240); cv::circle(simulatedLeftImage, center, 20, cv::Scalar(255), 2); cv::putText(simulatedLeftImage, std::to_string(i), cv::Point(center.x - 10, center.y + 5), cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar(255), 2); } // 发送模拟数据(通过信号) emit presenter.detectionResult(simulatedMarks, simulatedLeftImage, simulatedRightImage, SUCCESS); frameCounter++; LOG_DEBUG("Simulation: Sent frame #%d with %zu marks\n", frameCounter, simulatedMarks.size()); // 等待5秒 QThread::sleep(5); } }); testThread.detach(); #endif #endif return app.exec(); }