#include "ConfigCmdParser.h" #include "VrError.h" #include #include #include #include #include ConfigCmdParser::ConfigCmdParser() : m_pShareMem(nullptr) { } ConfigCmdParser::~ConfigCmdParser() { CleanupSharedMemory(); } bool ConfigCmdParser::ParseCommandLine(int argc, char* argv[], ConfigCmdData& configData) { if (argc < 2) { ShowHelp(); return false; } for (int i = 1; i < argc; ++i) { std::string arg = argv[i]; if (arg == "-h" || arg == "--help") { ShowHelp(); return false; } if (arg == "-v" || arg == "--version") { ShowVersion(); return false; } if (arg == "-c" || arg == "--config") { if (i + 1 >= argc) { std::cerr << "错误: -c 参数需要指定配置项" << std::endl; return false; } std::string configType = argv[i + 1]; // 收集剩余的参数 std::vector configParams; for (int j = i + 2; j < argc; ++j) { configParams.push_back(argv[j]); } // 根据参数类型进行解析 if (configType == "expose") { return ParseCameraExpose(configParams, configData); } else if (configType == "gain") { return ParseCameraGain(configParams, configData); } else if (configType == "framerate") { return ParseCameraFrameRate(configParams, configData); } else if (configType == "swing") { return ParseCameraSwing(configParams, configData); } else if (configType == "roi") { return ParseROISetting(configParams, configData); } else if (configType == "algo") { return ParseAlgoParam(configParams, configData); } else if (configType == "calib") { return ParseCalibParam(configParams, configData); } else { std::cerr << "错误: 未知的配置参数类型: " << configType << std::endl; return false; } } } std::cerr << "错误: 未找到有效的配置参数" << std::endl; return false; } bool ConfigCmdParser::SendConfigCommand(const ConfigCmdData& configData) { if (!InitializeSharedMemory()) { std::cerr << "错误: 初始化共享内存失败" << std::endl; return false; } // 准备共享数据 ConfigCmdSharedData sharedData; sharedData.data = configData; sharedData.header.checksum = sharedData.CalculateChecksum(); sharedData.header.hasNewData = true; // 写入共享内存 int ret = m_pShareMem->Lock(5000); // 5秒超时 if (ret != SUCCESS) { std::cerr << "错误: 锁定共享内存失败, 错误码: " << ret << std::endl; return false; } ret = m_pShareMem->WriteData(0, &sharedData, sizeof(ConfigCmdSharedData)); m_pShareMem->Unlock(); if (ret < 0) { std::cerr << "错误: 写入共享内存失败, 错误码: " << ret << std::endl; return false; } std::cout << "配置命令发送成功" << std::endl; return true; } bool ConfigCmdParser::ParseCameraExpose(const std::vector& params, ConfigCmdData& configData) { // 支持格式: // expose 100 - 设置所有相机曝光时间为100微秒 // expose 1 100 - 设置相机1曝光时间为100微秒 if (params.empty()) { std::cerr << "错误: expose 命令需要指定曝光时间" << std::endl; std::cerr << "用法: expose <曝光时间> 或 expose <相机索引> <曝光时间>" << std::endl; return false; } configData.cmdType = CONFIG_CMD_CAMERA_EXPOSE; configData.cameraParam.cameraIndex = -1; // 默认所有相机 if (params.size() == 1) { // 格式: expose 100 if (!IsNumber(params[0])) { std::cerr << "错误: 曝光时间必须是数字: " << params[0] << std::endl; return false; } configData.cameraParam.exposeTime = std::stod(params[0]); } else if (params.size() == 2) { // 格式: expose 1 100 if (!IsNumber(params[0]) || !IsNumber(params[1])) { std::cerr << "错误: 相机索引和曝光时间都必须是数字" << std::endl; return false; } configData.cameraParam.cameraIndex = std::stoi(params[0]); configData.cameraParam.exposeTime = std::stod(params[1]); } else { std::cerr << "错误: expose 命令参数过多" << std::endl; std::cerr << "用法: expose <曝光时间> 或 expose <相机索引> <曝光时间>" << std::endl; return false; } // 参数验证 if (configData.cameraParam.exposeTime <= 0) { std::cerr << "错误: 曝光时间必须大于0" << std::endl; return false; } // 设置时间戳 std::string timestamp = GetCurrentTimestamp(); strncpy(configData.timestamp, timestamp.c_str(), sizeof(configData.timestamp) - 1); std::cout << "解析相机曝光参数: 相机" << configData.cameraParam.cameraIndex << ", 曝光时间: " << configData.cameraParam.exposeTime << "微秒" << std::endl; return true; } bool ConfigCmdParser::ParseCameraGain(const std::vector& params, ConfigCmdData& configData) { // 支持格式: // gain 2.5 - 设置所有相机增益为2.5 // gain 1 2.5 - 设置相机1增益为2.5 if (params.empty()) { std::cerr << "错误: gain 命令需要指定增益值" << std::endl; std::cerr << "用法: gain <增益值> 或 gain <相机索引> <增益值>" << std::endl; return false; } configData.cmdType = CONFIG_CMD_CAMERA_GAIN; configData.cameraParam.cameraIndex = -1; // 默认所有相机 if (params.size() == 1) { // 格式: gain 2.5 if (!IsNumber(params[0])) { std::cerr << "错误: 增益值必须是数字: " << params[0] << std::endl; return false; } configData.cameraParam.gain = std::stod(params[0]); } else if (params.size() == 2) { // 格式: gain 1 2.5 if (!IsNumber(params[0]) || !IsNumber(params[1])) { std::cerr << "错误: 相机索引和增益值都必须是数字" << std::endl; return false; } configData.cameraParam.cameraIndex = std::stoi(params[0]); configData.cameraParam.gain = std::stod(params[1]); } else { std::cerr << "错误: gain 命令参数过多" << std::endl; std::cerr << "用法: gain <增益值> 或 gain <相机索引> <增益值>" << std::endl; return false; } // 参数验证 if (configData.cameraParam.gain <= 0) { std::cerr << "错误: 增益值必须大于0" << std::endl; return false; } std::string timestamp = GetCurrentTimestamp(); strncpy(configData.timestamp, timestamp.c_str(), sizeof(configData.timestamp) - 1); std::cout << "解析相机增益参数: 相机" << configData.cameraParam.cameraIndex << ", 增益: " << configData.cameraParam.gain << std::endl; return true; } bool ConfigCmdParser::ParseAlgoParam(const std::vector& params, ConfigCmdData& configData) { // 支持格式: // algo threshold 0.5 - 设置算法参数threshold为0.5 if (params.size() != 2) { std::cerr << "错误: algo 命令需要2个参数" << std::endl; std::cerr << "用法: algo <参数名> <参数值>" << std::endl; return false; } if (!IsNumber(params[1])) { std::cerr << "错误: 算法参数值必须是数字: " << params[1] << std::endl; return false; } configData.cmdType = CONFIG_CMD_ALGO_PARAM; strncpy(configData.algoParam.paramName, params[0].c_str(), sizeof(configData.algoParam.paramName) - 1); configData.algoParam.paramValue = std::stod(params[1]); std::string timestamp = GetCurrentTimestamp(); strncpy(configData.timestamp, timestamp.c_str(), sizeof(configData.timestamp) - 1); std::cout << "解析算法参数: " << configData.algoParam.paramName << " = " << configData.algoParam.paramValue << std::endl; return true; } bool ConfigCmdParser::ParseCalibParam(const std::vector& params, ConfigCmdData& configData) { // 简化实现,这里可以根据实际需求扩展 // 支持格式: // calib <相机索引> - 触发指定相机的标定过程 if (params.size() != 1) { std::cerr << "错误: calib 命令需要1个参数" << std::endl; std::cerr << "用法: calib <相机索引>" << std::endl; return false; } if (!IsNumber(params[0])) { std::cerr << "错误: 相机索引必须是数字: " << params[0] << std::endl; return false; } configData.cmdType = CONFIG_CMD_CALIB_PARAM; configData.calibParam.cameraIndex = std::stoi(params[0]); std::string timestamp = GetCurrentTimestamp(); strncpy(configData.timestamp, timestamp.c_str(), sizeof(configData.timestamp) - 1); std::cout << "解析标定参数: 相机" << configData.calibParam.cameraIndex << std::endl; std::cerr << "警告: 标定参数配置功能尚未完全实现" << std::endl; return true; } bool ConfigCmdParser::ParseCameraFrameRate(const std::vector& params, ConfigCmdData& configData) { // 支持格式: // framerate 30 - 设置所有相机帧率为30fps // framerate 1 30 - 设置相机1帧率为30fps if (params.empty()) { std::cerr << "错误: framerate 命令需要指定帧率值" << std::endl; std::cerr << "用法: framerate <帧率> 或 framerate <相机索引> <帧率>" << std::endl; return false; } configData.cmdType = CONFIG_CMD_CAMERA_FRAMERATE; configData.cameraParam.cameraIndex = -1; // 默认所有相机 if (params.size() == 1) { // 格式: framerate 30 if (!IsNumber(params[0])) { std::cerr << "错误: 帧率值必须是数字: " << params[0] << std::endl; return false; } configData.cameraParam.frameRate = std::stod(params[0]); } else if (params.size() == 2) { // 格式: framerate 1 30 if (!IsNumber(params[0]) || !IsNumber(params[1])) { std::cerr << "错误: 相机索引和帧率值都必须是数字" << std::endl; return false; } configData.cameraParam.cameraIndex = std::stoi(params[0]); configData.cameraParam.frameRate = std::stod(params[1]); } else { std::cerr << "错误: framerate 命令参数过多" << std::endl; std::cerr << "用法: framerate <帧率> 或 framerate <相机索引> <帧率>" << std::endl; return false; } // 参数验证 if (configData.cameraParam.frameRate <= 0) { std::cerr << "错误: 帧率值必须大于0" << std::endl; return false; } // 设置时间戳 std::string timestamp = GetCurrentTimestamp(); strncpy(configData.timestamp, timestamp.c_str(), sizeof(configData.timestamp) - 1); std::cout << "解析相机帧率参数: 相机" << configData.cameraParam.cameraIndex << ", 帧率: " << configData.cameraParam.frameRate << "fps" << std::endl; return true; } bool ConfigCmdParser::ParseCameraSwing(const std::vector& params, ConfigCmdData& configData) { // 支持格式: // swing 10 0 180 - 设置所有相机摆动:速度10,角度0-180度 // swing 1 10 0 180 - 设置相机1摆动:速度10,角度0-180度 if (params.size() != 3 && params.size() != 4) { std::cerr << "错误: swing 命令需要3个或4个参数" << std::endl; std::cerr << "用法: swing <速度> <开始角度> <结束角度> 或 swing <相机索引> <速度> <开始角度> <结束角度>" << std::endl; return false; } configData.cmdType = CONFIG_CMD_CAMERA_SWING; configData.swingParam.cameraIndex = -1; // 默认所有相机 std::vector swingValues; if (params.size() == 3) { // 格式: swing 10 0 180 swingValues = params; } else if (params.size() == 4) { // 格式: swing 1 10 0 180 if (!IsNumber(params[0])) { std::cerr << "错误: 相机索引必须是数字: " << params[0] << std::endl; return false; } configData.swingParam.cameraIndex = std::stoi(params[0]); swingValues = std::vector(params.begin() + 1, params.end()); } // 验证所有摆动参数都是数字 for (size_t i = 0; i < swingValues.size(); ++i) { if (!IsNumber(swingValues[i])) { std::cerr << "错误: 摆动参数必须是数字: " << swingValues[i] << std::endl; return false; } } // 解析摆动参数 configData.swingParam.swingSpeed = std::stod(swingValues[0]); configData.swingParam.startAngle = std::stod(swingValues[1]); configData.swingParam.stopAngle = std::stod(swingValues[2]); // 参数验证 if (configData.swingParam.swingSpeed <= 0) { std::cerr << "错误: 摆动速度必须大于0" << std::endl; return false; } if (configData.swingParam.startAngle >= configData.swingParam.stopAngle) { std::cerr << "错误: 开始角度必须小于结束角度" << std::endl; return false; } // 设置时间戳 std::string timestamp = GetCurrentTimestamp(); strncpy(configData.timestamp, timestamp.c_str(), sizeof(configData.timestamp) - 1); std::cout << "解析相机摆动参数: 相机" << configData.swingParam.cameraIndex << ", 速度: " << configData.swingParam.swingSpeed << ", 角度: " << configData.swingParam.startAngle << "-" << configData.swingParam.stopAngle << std::endl; return true; } void ConfigCmdParser::ShowHelp() { std::cout << "GrabBag 配置命令行工具" << std::endl; std::cout << "用法: grabbag [选项] -c <配置类型> <参数...>" << std::endl; std::cout << std::endl; std::cout << "选项:" << std::endl; std::cout << " -h, --help 显示帮助信息" << std::endl; std::cout << " -v, --version 显示版本信息" << std::endl; std::cout << " -c, --config 设置配置参数" << std::endl; std::cout << std::endl; std::cout << "配置参数格式:" << std::endl; std::cout << " 相机曝光:" << std::endl; std::cout << " grabbag -c expose <曝光时间> - 设置所有相机曝光时间(微秒)" << std::endl; std::cout << " grabbag -c expose <相机索引> <曝光时间> - 设置指定相机曝光时间" << std::endl; std::cout << " 示例: grabbag -c expose 100" << std::endl; std::cout << " grabbag -c expose 1 150" << std::endl; std::cout << std::endl; std::cout << " 相机增益:" << std::endl; std::cout << " grabbag -c gain <增益值> - 设置所有相机增益" << std::endl; std::cout << " grabbag -c gain <相机索引> <增益值> - 设置指定相机增益" << std::endl; std::cout << " 示例: grabbag -c gain 2.5" << std::endl; std::cout << " grabbag -c gain 1 3.0" << std::endl; std::cout << std::endl; std::cout << " 相机帧率:" << std::endl; std::cout << " grabbag -c framerate <帧率> - 设置所有相机帧率(fps)" << std::endl; std::cout << " grabbag -c framerate <相机索引> <帧率> - 设置指定相机帧率" << std::endl; std::cout << " 示例: grabbag -c framerate 30" << std::endl; std::cout << " grabbag -c framerate 1 25" << std::endl; std::cout << std::endl; std::cout << " 摆动参数:" << std::endl; std::cout << " grabbag -c swing <速度> <开始角度> <结束角度> - 设置所有相机摆动参数" << std::endl; std::cout << " grabbag -c swing <相机索引> <速度> <开始角度> <结束角度> - 设置指定相机摆动参数" << std::endl; std::cout << " 示例: grabbag -c swing 10 0 180" << std::endl; std::cout << " grabbag -c swing 1 15 -45 45" << std::endl; std::cout << std::endl; std::cout << " 算法参数:" << std::endl; std::cout << " grabbag -c algo <参数名> <值> - 设置算法参数" << std::endl; std::cout << " 示例: grabbag -c algo threshold 0.5" << std::endl; std::cout << " grabbag -c algo windowSize 10" << std::endl; std::cout << std::endl; std::cout << " 标定参数:" << std::endl; std::cout << " grabbag -c calib <相机索引> - 触发指定相机标定" << std::endl; std::cout << " 示例: grabbag -c calib 1" << std::endl; std::cout << std::endl; } void ConfigCmdParser::ShowVersion() { std::cout << "GrabBag 配置命令行工具 v1.0.0" << std::endl; std::cout << "版权所有 (C) 2024" << std::endl; } bool ConfigCmdParser::InitializeSharedMemory() { if (m_pShareMem) { return true; // 已经初始化 } m_pShareMem = CreateShareMemInstance(); if (!m_pShareMem) { return false; } // 尝试打开已存在的共享内存,如果不存在则创建 int ret = m_pShareMem->CreateOrOpen(CONFIG_CMD_SHARED_MEM_NAME, CONFIG_CMD_SHARED_MEM_SIZE, false); if (ret != SUCCESS) { // 如果打开失败,尝试创建新的 ret = m_pShareMem->CreateOrOpen(CONFIG_CMD_SHARED_MEM_NAME, CONFIG_CMD_SHARED_MEM_SIZE, true); if (ret != SUCCESS) { CleanupSharedMemory(); return false; } } // 映射内存 void* mappedAddr = m_pShareMem->MapView(); if (!mappedAddr) { CleanupSharedMemory(); return false; } return true; } void ConfigCmdParser::CleanupSharedMemory() { if (m_pShareMem) { m_pShareMem->UnmapView(); m_pShareMem->Close(); DestroyShareMemInstance(m_pShareMem); m_pShareMem = nullptr; } } std::vector ConfigCmdParser::SplitString(const std::string& str, char delimiter) { std::vector result; std::stringstream ss(str); std::string item; while (std::getline(ss, item, delimiter)) { result.push_back(item); } return result; } bool ConfigCmdParser::IsNumber(const std::string& str) { if (str.empty()) return false; std::string::const_iterator it = str.begin(); // 允许负号 if (*it == '-') ++it; bool hasDigit = false; bool hasDot = false; while (it != str.end()) { if (std::isdigit(*it)) { hasDigit = true; } else if (*it == '.' && !hasDot) { hasDot = true; } else { return false; } ++it; } return hasDigit; } std::string ConfigCmdParser::GetCurrentTimestamp() { auto now = std::chrono::system_clock::now(); auto time_t = std::chrono::system_clock::to_time_t(now); std::stringstream ss; ss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S"); return ss.str(); }