485 lines
26 KiB
C++
485 lines
26 KiB
C++
#include "VrConfig.h"
|
||
#include <iostream>
|
||
#include <vector>
|
||
#include <string>
|
||
|
||
#include "VrLog.h"
|
||
|
||
using namespace tinyxml2;
|
||
|
||
CVrConfig::CVrConfig() : m_pNotify(nullptr)
|
||
{
|
||
// 构造函数
|
||
}
|
||
|
||
CVrConfig::~CVrConfig()
|
||
{
|
||
// 析构函数
|
||
}
|
||
|
||
int CVrConfig::LoadConfig(const std::string& filePath, ConfigResult& configResult)
|
||
{
|
||
// 使用tinyxml2库加载XML文件
|
||
XMLDocument doc;
|
||
XMLError err = doc.LoadFile(filePath.c_str());
|
||
if (err != XML_SUCCESS)
|
||
{
|
||
LOG_ERR("open config file failed: %s\n", filePath.c_str());
|
||
return LOAD_CONFIG_FILE_NOT_FOUND;
|
||
}
|
||
|
||
// 获取根元素
|
||
XMLElement* root = doc.RootElement();
|
||
if (!root || std::string(root->Name()) != "WorkpieceHoleConfig")
|
||
{
|
||
std::cerr << "config file format error: root element is not WorkpieceHoleConfig" << std::endl;
|
||
return LOAD_CONFIG_INVALID_FORMAT;
|
||
}
|
||
|
||
// 解析摄像头列表
|
||
XMLElement* camerasElement = root->FirstChildElement("Cameras");
|
||
if (camerasElement)
|
||
{
|
||
XMLElement* cameraElement = camerasElement->FirstChildElement("Camera");
|
||
while (cameraElement)
|
||
{
|
||
DeviceInfo camera;
|
||
if (cameraElement->Attribute("name"))
|
||
camera.name = cameraElement->Attribute("name");
|
||
|
||
if (cameraElement->Attribute("ip"))
|
||
camera.ip = cameraElement->Attribute("ip");
|
||
|
||
configResult.cameraList.push_back(camera);
|
||
cameraElement = cameraElement->NextSiblingElement("Camera");
|
||
}
|
||
}
|
||
|
||
// 解析设备列表
|
||
XMLElement* devicesElement = root->FirstChildElement("Devices");
|
||
if (devicesElement)
|
||
{
|
||
XMLElement* deviceElement = devicesElement->FirstChildElement("Device");
|
||
while (deviceElement)
|
||
{
|
||
DeviceInfo device;
|
||
if (deviceElement->Attribute("name"))
|
||
device.name = deviceElement->Attribute("name");
|
||
|
||
if (deviceElement->Attribute("ip"))
|
||
device.ip = deviceElement->Attribute("ip");
|
||
|
||
configResult.deviceList.push_back(device);
|
||
deviceElement = deviceElement->NextSiblingElement("Device");
|
||
}
|
||
}
|
||
|
||
// 解析算法参数
|
||
XMLElement* algoParamsElement = root->FirstChildElement("AlgorithmParams");
|
||
if (algoParamsElement)
|
||
{
|
||
// 解析工件孔参数
|
||
XMLElement* workpieceHoleParamElement = algoParamsElement->FirstChildElement("WorkpieceHoleParam");
|
||
if (workpieceHoleParamElement)
|
||
{
|
||
if (workpieceHoleParamElement->Attribute("workpieceType"))
|
||
configResult.algorithmParams.workpieceHoleParam.workpieceType = workpieceHoleParamElement->IntAttribute("workpieceType");
|
||
if (workpieceHoleParamElement->Attribute("holeDiameter"))
|
||
configResult.algorithmParams.workpieceHoleParam.holeDiameter = workpieceHoleParamElement->DoubleAttribute("holeDiameter");
|
||
if (workpieceHoleParamElement->Attribute("holeDist_L"))
|
||
configResult.algorithmParams.workpieceHoleParam.holeDist_L = workpieceHoleParamElement->DoubleAttribute("holeDist_L");
|
||
if (workpieceHoleParamElement->Attribute("holeDist_W"))
|
||
configResult.algorithmParams.workpieceHoleParam.holeDist_W = workpieceHoleParamElement->DoubleAttribute("holeDist_W");
|
||
}
|
||
|
||
// 解析滤波参数
|
||
XMLElement* filterParamElement = algoParamsElement->FirstChildElement("FilterParam");
|
||
if (filterParamElement)
|
||
{
|
||
if (filterParamElement->Attribute("continuityTh"))
|
||
configResult.algorithmParams.filterParam.continuityTh = filterParamElement->DoubleAttribute("continuityTh");
|
||
if (filterParamElement->Attribute("outlierTh"))
|
||
configResult.algorithmParams.filterParam.outlierTh = filterParamElement->DoubleAttribute("outlierTh");
|
||
}
|
||
|
||
// 解析线段分割参数
|
||
XMLElement* lineSegParamElement = algoParamsElement->FirstChildElement("LineSegParam");
|
||
if (lineSegParamElement)
|
||
{
|
||
if (lineSegParamElement->Attribute("distScale"))
|
||
configResult.algorithmParams.lineSegParam.distScale = lineSegParamElement->DoubleAttribute("distScale");
|
||
if (lineSegParamElement->Attribute("segGapTh_y"))
|
||
configResult.algorithmParams.lineSegParam.segGapTh_y = lineSegParamElement->DoubleAttribute("segGapTh_y");
|
||
if (lineSegParamElement->Attribute("segGapTh_z"))
|
||
configResult.algorithmParams.lineSegParam.segGapTh_z = lineSegParamElement->DoubleAttribute("segGapTh_z");
|
||
}
|
||
|
||
// 解析增长参数
|
||
XMLElement* growParamElement = algoParamsElement->FirstChildElement("GrowParam");
|
||
if (growParamElement)
|
||
{
|
||
if (growParamElement->Attribute("maxLineSkipNum"))
|
||
configResult.algorithmParams.growParam.maxLineSkipNum = growParamElement->IntAttribute("maxLineSkipNum");
|
||
if (growParamElement->Attribute("yDeviation_max"))
|
||
configResult.algorithmParams.growParam.yDeviation_max = growParamElement->DoubleAttribute("yDeviation_max");
|
||
if (growParamElement->Attribute("maxSkipDistance"))
|
||
configResult.algorithmParams.growParam.maxSkipDistance = growParamElement->DoubleAttribute("maxSkipDistance");
|
||
if (growParamElement->Attribute("zDeviation_max"))
|
||
configResult.algorithmParams.growParam.zDeviation_max = growParamElement->DoubleAttribute("zDeviation_max");
|
||
if (growParamElement->Attribute("minLTypeTreeLen"))
|
||
configResult.algorithmParams.growParam.minLTypeTreeLen = growParamElement->DoubleAttribute("minLTypeTreeLen");
|
||
if (growParamElement->Attribute("minVTypeTreeLen"))
|
||
configResult.algorithmParams.growParam.minVTypeTreeLen = growParamElement->DoubleAttribute("minVTypeTreeLen");
|
||
}
|
||
|
||
// 解析多相机平面校准参数
|
||
XMLElement* planeCalibParamsElement = algoParamsElement->FirstChildElement("PlaneCalibParams");
|
||
if (planeCalibParamsElement)
|
||
{
|
||
XMLElement* cameraCalibParamElement = planeCalibParamsElement->FirstChildElement("CameraCalibParam");
|
||
while (cameraCalibParamElement)
|
||
{
|
||
VrCameraPlaneCalibParam cameraParam;
|
||
|
||
// 读取相机基础信息
|
||
if (cameraCalibParamElement->Attribute("cameraIndex"))
|
||
cameraParam.cameraIndex = cameraCalibParamElement->IntAttribute("cameraIndex");
|
||
if (cameraCalibParamElement->Attribute("cameraName"))
|
||
cameraParam.cameraName = cameraCalibParamElement->Attribute("cameraName");
|
||
if (cameraCalibParamElement->Attribute("isCalibrated"))
|
||
cameraParam.isCalibrated = cameraCalibParamElement->BoolAttribute("isCalibrated");
|
||
if (cameraCalibParamElement->Attribute("planeHeight"))
|
||
cameraParam.planeHeight = cameraCalibParamElement->DoubleAttribute("planeHeight");
|
||
|
||
// 读取旋转矩阵planeCalib[9] (3x3矩阵)
|
||
if (cameraCalibParamElement->Attribute("planeCalib_00"))
|
||
cameraParam.planeCalib[0] = cameraCalibParamElement->DoubleAttribute("planeCalib_00");
|
||
if (cameraCalibParamElement->Attribute("planeCalib_01"))
|
||
cameraParam.planeCalib[1] = cameraCalibParamElement->DoubleAttribute("planeCalib_01");
|
||
if (cameraCalibParamElement->Attribute("planeCalib_02"))
|
||
cameraParam.planeCalib[2] = cameraCalibParamElement->DoubleAttribute("planeCalib_02");
|
||
if (cameraCalibParamElement->Attribute("planeCalib_10"))
|
||
cameraParam.planeCalib[3] = cameraCalibParamElement->DoubleAttribute("planeCalib_10");
|
||
if (cameraCalibParamElement->Attribute("planeCalib_11"))
|
||
cameraParam.planeCalib[4] = cameraCalibParamElement->DoubleAttribute("planeCalib_11");
|
||
if (cameraCalibParamElement->Attribute("planeCalib_12"))
|
||
cameraParam.planeCalib[5] = cameraCalibParamElement->DoubleAttribute("planeCalib_12");
|
||
if (cameraCalibParamElement->Attribute("planeCalib_20"))
|
||
cameraParam.planeCalib[6] = cameraCalibParamElement->DoubleAttribute("planeCalib_20");
|
||
if (cameraCalibParamElement->Attribute("planeCalib_21"))
|
||
cameraParam.planeCalib[7] = cameraCalibParamElement->DoubleAttribute("planeCalib_21");
|
||
if (cameraCalibParamElement->Attribute("planeCalib_22"))
|
||
cameraParam.planeCalib[8] = cameraCalibParamElement->DoubleAttribute("planeCalib_22");
|
||
|
||
// 读取逆旋转矩阵invRMatrix[9] (3x3矩阵)
|
||
if (cameraCalibParamElement->Attribute("invRMatrix_00"))
|
||
cameraParam.invRMatrix[0] = cameraCalibParamElement->DoubleAttribute("invRMatrix_00");
|
||
if (cameraCalibParamElement->Attribute("invRMatrix_01"))
|
||
cameraParam.invRMatrix[1] = cameraCalibParamElement->DoubleAttribute("invRMatrix_01");
|
||
if (cameraCalibParamElement->Attribute("invRMatrix_02"))
|
||
cameraParam.invRMatrix[2] = cameraCalibParamElement->DoubleAttribute("invRMatrix_02");
|
||
if (cameraCalibParamElement->Attribute("invRMatrix_10"))
|
||
cameraParam.invRMatrix[3] = cameraCalibParamElement->DoubleAttribute("invRMatrix_10");
|
||
if (cameraCalibParamElement->Attribute("invRMatrix_11"))
|
||
cameraParam.invRMatrix[4] = cameraCalibParamElement->DoubleAttribute("invRMatrix_11");
|
||
if (cameraCalibParamElement->Attribute("invRMatrix_12"))
|
||
cameraParam.invRMatrix[5] = cameraCalibParamElement->DoubleAttribute("invRMatrix_12");
|
||
if (cameraCalibParamElement->Attribute("invRMatrix_20"))
|
||
cameraParam.invRMatrix[6] = cameraCalibParamElement->DoubleAttribute("invRMatrix_20");
|
||
if (cameraCalibParamElement->Attribute("invRMatrix_21"))
|
||
cameraParam.invRMatrix[7] = cameraCalibParamElement->DoubleAttribute("invRMatrix_21");
|
||
if (cameraCalibParamElement->Attribute("invRMatrix_22"))
|
||
cameraParam.invRMatrix[8] = cameraCalibParamElement->DoubleAttribute("invRMatrix_22");
|
||
|
||
// 添加到结果中
|
||
configResult.algorithmParams.planeCalibParam.cameraCalibParams.push_back(cameraParam);
|
||
|
||
// 移动到下一个相机配置
|
||
cameraCalibParamElement = cameraCalibParamElement->NextSiblingElement("CameraCalibParam");
|
||
}
|
||
}
|
||
}
|
||
|
||
// 解析调试参数(在AlgorithmParams外面)
|
||
XMLElement* debugParamElement = root->FirstChildElement("DebugParam");
|
||
if (debugParamElement)
|
||
{
|
||
if (debugParamElement->Attribute("enableDebug"))
|
||
configResult.debugParam.enableDebug = debugParamElement->BoolAttribute("enableDebug");
|
||
if (debugParamElement->Attribute("savePointCloud"))
|
||
configResult.debugParam.savePointCloud = debugParamElement->BoolAttribute("savePointCloud");
|
||
if (debugParamElement->Attribute("saveDebugImage"))
|
||
configResult.debugParam.saveDebugImage = debugParamElement->BoolAttribute("saveDebugImage");
|
||
if (debugParamElement->Attribute("printDetailLog"))
|
||
configResult.debugParam.printDetailLog = debugParamElement->BoolAttribute("printDetailLog");
|
||
if (debugParamElement->Attribute("debugOutputPath"))
|
||
configResult.debugParam.debugOutputPath = debugParamElement->Attribute("debugOutputPath");
|
||
}
|
||
|
||
// 解析串口配置
|
||
XMLElement* serialConfigElement = root->FirstChildElement("SerialConfig");
|
||
if (serialConfigElement)
|
||
{
|
||
if (serialConfigElement->Attribute("portName"))
|
||
configResult.serialConfig.portName = serialConfigElement->Attribute("portName");
|
||
if (serialConfigElement->Attribute("baudRate"))
|
||
configResult.serialConfig.baudRate = serialConfigElement->IntAttribute("baudRate");
|
||
if (serialConfigElement->Attribute("dataBits"))
|
||
configResult.serialConfig.dataBits = serialConfigElement->IntAttribute("dataBits");
|
||
if (serialConfigElement->Attribute("stopBits"))
|
||
configResult.serialConfig.stopBits = serialConfigElement->IntAttribute("stopBits");
|
||
if (serialConfigElement->Attribute("parity"))
|
||
configResult.serialConfig.parity = serialConfigElement->IntAttribute("parity");
|
||
if (serialConfigElement->Attribute("flowControl"))
|
||
configResult.serialConfig.flowControl = serialConfigElement->IntAttribute("flowControl");
|
||
if (serialConfigElement->Attribute("enabled"))
|
||
configResult.serialConfig.enabled = serialConfigElement->BoolAttribute("enabled");
|
||
}
|
||
|
||
// 解析手眼标定矩阵
|
||
XMLElement* handEyeElement = root->FirstChildElement("HandEyeCalibMatrix");
|
||
if (handEyeElement)
|
||
{
|
||
for (int i = 0; i < 16; i++)
|
||
{
|
||
char attrName[32];
|
||
sprintf(attrName, "m%d", i);
|
||
if (handEyeElement->Attribute(attrName))
|
||
configResult.handEyeCalibMatrix.matrix[i] = handEyeElement->DoubleAttribute(attrName);
|
||
}
|
||
// 读取旋转顺序,如果不存在则使用默认值11(外旋ZYX)
|
||
if (handEyeElement->Attribute("eulerOrder"))
|
||
configResult.handEyeCalibMatrix.eulerOrder = handEyeElement->IntAttribute("eulerOrder");
|
||
else
|
||
configResult.handEyeCalibMatrix.eulerOrder = 11; // 默认外旋ZYX
|
||
}
|
||
|
||
// 解析TCP服务端配置(PLC和机械臂)
|
||
XMLElement* tcpServerConfigElement = root->FirstChildElement("TcpServerConfig");
|
||
if (tcpServerConfigElement)
|
||
{
|
||
if (tcpServerConfigElement->Attribute("plcServerIp"))
|
||
configResult.plcRobotServerConfig.plcServerIp = tcpServerConfigElement->Attribute("plcServerIp");
|
||
if (tcpServerConfigElement->Attribute("plcServerPort"))
|
||
configResult.plcRobotServerConfig.plcServerPort = tcpServerConfigElement->IntAttribute("plcServerPort");
|
||
if (tcpServerConfigElement->Attribute("robotServerIp"))
|
||
configResult.plcRobotServerConfig.robotServerIp = tcpServerConfigElement->Attribute("robotServerIp");
|
||
if (tcpServerConfigElement->Attribute("robotServerPort"))
|
||
configResult.plcRobotServerConfig.robotServerPort = tcpServerConfigElement->IntAttribute("robotServerPort");
|
||
|
||
// 解析PLC寄存器地址配置
|
||
if (tcpServerConfigElement->Attribute("addrPhotoRequest"))
|
||
configResult.plcRobotServerConfig.registerConfig.addrPhotoRequest = tcpServerConfigElement->IntAttribute("addrPhotoRequest");
|
||
if (tcpServerConfigElement->Attribute("addrDataComplete"))
|
||
configResult.plcRobotServerConfig.registerConfig.addrDataComplete = tcpServerConfigElement->IntAttribute("addrDataComplete");
|
||
if (tcpServerConfigElement->Attribute("addrCoordDataStart"))
|
||
configResult.plcRobotServerConfig.registerConfig.addrCoordDataStart = tcpServerConfigElement->IntAttribute("addrCoordDataStart");
|
||
|
||
// 解析姿态输出顺序配置
|
||
if (tcpServerConfigElement->Attribute("poseOutputOrder"))
|
||
configResult.plcRobotServerConfig.poseOutputOrder = tcpServerConfigElement->IntAttribute("poseOutputOrder");
|
||
else
|
||
configResult.plcRobotServerConfig.poseOutputOrder = POSE_ORDER_RPY; // 默认RPY
|
||
|
||
// 解析方向向量反向配置
|
||
if (tcpServerConfigElement->Attribute("dirVectorInvert"))
|
||
configResult.plcRobotServerConfig.dirVectorInvert = tcpServerConfigElement->IntAttribute("dirVectorInvert");
|
||
else
|
||
configResult.plcRobotServerConfig.dirVectorInvert = DIR_INVERT_YZ; // 默认YZ反向(兼容原有行为)
|
||
}
|
||
|
||
return LOAD_CONFIG_SUCCESS;
|
||
}
|
||
|
||
bool CVrConfig::SaveConfig(const std::string& filePath, ConfigResult& configResult)
|
||
{
|
||
// 创建XML文档
|
||
XMLDocument doc;
|
||
|
||
// 添加声明
|
||
XMLDeclaration* declaration = doc.NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\"");
|
||
doc.InsertFirstChild(declaration);
|
||
|
||
// 创建根元素
|
||
XMLElement* root = doc.NewElement("WorkpieceHoleConfig");
|
||
doc.InsertEndChild(root);
|
||
|
||
// 添加摄像头列表
|
||
XMLElement* camerasElement = doc.NewElement("Cameras");
|
||
root->InsertEndChild(camerasElement);
|
||
|
||
for (const auto& camera : configResult.cameraList)
|
||
{
|
||
XMLElement* cameraElement = doc.NewElement("Camera");
|
||
cameraElement->SetAttribute("name", camera.name.c_str());
|
||
cameraElement->SetAttribute("ip", camera.ip.c_str());
|
||
camerasElement->InsertEndChild(cameraElement);
|
||
}
|
||
|
||
// 添加设备列表
|
||
XMLElement* devicesElement = doc.NewElement("Devices");
|
||
root->InsertEndChild(devicesElement);
|
||
|
||
for (const auto& device : configResult.deviceList)
|
||
{
|
||
XMLElement* deviceElement = doc.NewElement("Device");
|
||
deviceElement->SetAttribute("name", device.name.c_str());
|
||
deviceElement->SetAttribute("ip", device.ip.c_str());
|
||
devicesElement->InsertEndChild(deviceElement);
|
||
}
|
||
|
||
// 添加算法参数
|
||
XMLElement* algoParamsElement = doc.NewElement("AlgorithmParams");
|
||
root->InsertEndChild(algoParamsElement);
|
||
|
||
// 添加工件孔参数
|
||
XMLElement* workpieceHoleParamElement = doc.NewElement("WorkpieceHoleParam");
|
||
workpieceHoleParamElement->SetAttribute("workpieceType", configResult.algorithmParams.workpieceHoleParam.workpieceType);
|
||
workpieceHoleParamElement->SetAttribute("holeDiameter", configResult.algorithmParams.workpieceHoleParam.holeDiameter);
|
||
workpieceHoleParamElement->SetAttribute("holeDist_L", configResult.algorithmParams.workpieceHoleParam.holeDist_L);
|
||
workpieceHoleParamElement->SetAttribute("holeDist_W", configResult.algorithmParams.workpieceHoleParam.holeDist_W);
|
||
algoParamsElement->InsertEndChild(workpieceHoleParamElement);
|
||
|
||
// 添加滤波参数
|
||
XMLElement* filterParamElement = doc.NewElement("FilterParam");
|
||
filterParamElement->SetAttribute("continuityTh", configResult.algorithmParams.filterParam.continuityTh);
|
||
filterParamElement->SetAttribute("outlierTh", configResult.algorithmParams.filterParam.outlierTh);
|
||
algoParamsElement->InsertEndChild(filterParamElement);
|
||
|
||
// 添加线段分割参数
|
||
XMLElement* lineSegParamElement = doc.NewElement("LineSegParam");
|
||
lineSegParamElement->SetAttribute("distScale", configResult.algorithmParams.lineSegParam.distScale);
|
||
lineSegParamElement->SetAttribute("segGapTh_y", configResult.algorithmParams.lineSegParam.segGapTh_y);
|
||
lineSegParamElement->SetAttribute("segGapTh_z", configResult.algorithmParams.lineSegParam.segGapTh_z);
|
||
algoParamsElement->InsertEndChild(lineSegParamElement);
|
||
|
||
// 添加增长参数
|
||
XMLElement* growParamElement = doc.NewElement("GrowParam");
|
||
growParamElement->SetAttribute("maxLineSkipNum", configResult.algorithmParams.growParam.maxLineSkipNum);
|
||
growParamElement->SetAttribute("yDeviation_max", configResult.algorithmParams.growParam.yDeviation_max);
|
||
growParamElement->SetAttribute("maxSkipDistance", configResult.algorithmParams.growParam.maxSkipDistance);
|
||
growParamElement->SetAttribute("zDeviation_max", configResult.algorithmParams.growParam.zDeviation_max);
|
||
growParamElement->SetAttribute("minLTypeTreeLen", configResult.algorithmParams.growParam.minLTypeTreeLen);
|
||
growParamElement->SetAttribute("minVTypeTreeLen", configResult.algorithmParams.growParam.minVTypeTreeLen);
|
||
algoParamsElement->InsertEndChild(growParamElement);
|
||
|
||
// 添加多相机平面校准参数
|
||
XMLElement* planeCalibParamsElement = doc.NewElement("PlaneCalibParams");
|
||
|
||
for (const auto& cameraParam : configResult.algorithmParams.planeCalibParam.cameraCalibParams)
|
||
{
|
||
XMLElement* cameraCalibParamElement = doc.NewElement("CameraCalibParam");
|
||
cameraCalibParamElement->SetAttribute("cameraIndex", cameraParam.cameraIndex);
|
||
cameraCalibParamElement->SetAttribute("cameraName", cameraParam.cameraName.c_str());
|
||
cameraCalibParamElement->SetAttribute("isCalibrated", cameraParam.isCalibrated);
|
||
cameraCalibParamElement->SetAttribute("planeHeight", cameraParam.planeHeight);
|
||
|
||
// 保存旋转矩阵planeCalib[9] (3x3矩阵)
|
||
cameraCalibParamElement->SetAttribute("planeCalib_00", cameraParam.planeCalib[0]);
|
||
cameraCalibParamElement->SetAttribute("planeCalib_01", cameraParam.planeCalib[1]);
|
||
cameraCalibParamElement->SetAttribute("planeCalib_02", cameraParam.planeCalib[2]);
|
||
cameraCalibParamElement->SetAttribute("planeCalib_10", cameraParam.planeCalib[3]);
|
||
cameraCalibParamElement->SetAttribute("planeCalib_11", cameraParam.planeCalib[4]);
|
||
cameraCalibParamElement->SetAttribute("planeCalib_12", cameraParam.planeCalib[5]);
|
||
cameraCalibParamElement->SetAttribute("planeCalib_20", cameraParam.planeCalib[6]);
|
||
cameraCalibParamElement->SetAttribute("planeCalib_21", cameraParam.planeCalib[7]);
|
||
cameraCalibParamElement->SetAttribute("planeCalib_22", cameraParam.planeCalib[8]);
|
||
|
||
// 保存逆旋转矩阵invRMatrix[9] (3x3矩阵)
|
||
cameraCalibParamElement->SetAttribute("invRMatrix_00", cameraParam.invRMatrix[0]);
|
||
cameraCalibParamElement->SetAttribute("invRMatrix_01", cameraParam.invRMatrix[1]);
|
||
cameraCalibParamElement->SetAttribute("invRMatrix_02", cameraParam.invRMatrix[2]);
|
||
cameraCalibParamElement->SetAttribute("invRMatrix_10", cameraParam.invRMatrix[3]);
|
||
cameraCalibParamElement->SetAttribute("invRMatrix_11", cameraParam.invRMatrix[4]);
|
||
cameraCalibParamElement->SetAttribute("invRMatrix_12", cameraParam.invRMatrix[5]);
|
||
cameraCalibParamElement->SetAttribute("invRMatrix_20", cameraParam.invRMatrix[6]);
|
||
cameraCalibParamElement->SetAttribute("invRMatrix_21", cameraParam.invRMatrix[7]);
|
||
cameraCalibParamElement->SetAttribute("invRMatrix_22", cameraParam.invRMatrix[8]);
|
||
|
||
planeCalibParamsElement->InsertEndChild(cameraCalibParamElement);
|
||
}
|
||
|
||
algoParamsElement->InsertEndChild(planeCalibParamsElement);
|
||
|
||
// 添加调试参数(在AlgorithmParams外面)
|
||
XMLElement* debugParamElement = doc.NewElement("DebugParam");
|
||
debugParamElement->SetAttribute("enableDebug", configResult.debugParam.enableDebug);
|
||
debugParamElement->SetAttribute("savePointCloud", configResult.debugParam.savePointCloud);
|
||
debugParamElement->SetAttribute("saveDebugImage", configResult.debugParam.saveDebugImage);
|
||
debugParamElement->SetAttribute("printDetailLog", configResult.debugParam.printDetailLog);
|
||
debugParamElement->SetAttribute("debugOutputPath", configResult.debugParam.debugOutputPath.c_str());
|
||
root->InsertEndChild(debugParamElement);
|
||
|
||
// 添加串口配置
|
||
XMLElement* serialConfigElement = doc.NewElement("SerialConfig");
|
||
serialConfigElement->SetAttribute("portName", configResult.serialConfig.portName.c_str());
|
||
serialConfigElement->SetAttribute("baudRate", configResult.serialConfig.baudRate);
|
||
serialConfigElement->SetAttribute("dataBits", configResult.serialConfig.dataBits);
|
||
serialConfigElement->SetAttribute("stopBits", configResult.serialConfig.stopBits);
|
||
serialConfigElement->SetAttribute("parity", configResult.serialConfig.parity);
|
||
serialConfigElement->SetAttribute("flowControl", configResult.serialConfig.flowControl);
|
||
serialConfigElement->SetAttribute("enabled", configResult.serialConfig.enabled);
|
||
root->InsertEndChild(serialConfigElement);
|
||
|
||
// 添加手眼标定矩阵
|
||
XMLElement* handEyeElement = doc.NewElement("HandEyeCalibMatrix");
|
||
for (int i = 0; i < 16; i++)
|
||
{
|
||
char attrName[32];
|
||
sprintf(attrName, "m%d", i);
|
||
handEyeElement->SetAttribute(attrName, configResult.handEyeCalibMatrix.matrix[i]);
|
||
}
|
||
// 保存旋转顺序
|
||
handEyeElement->SetAttribute("eulerOrder", configResult.handEyeCalibMatrix.eulerOrder);
|
||
root->InsertEndChild(handEyeElement);
|
||
|
||
// 添加TCP服务端配置(PLC和机械臂)
|
||
XMLElement* tcpServerConfigElement = doc.NewElement("TcpServerConfig");
|
||
tcpServerConfigElement->SetAttribute("plcServerIp", configResult.plcRobotServerConfig.plcServerIp.c_str());
|
||
tcpServerConfigElement->SetAttribute("plcServerPort", configResult.plcRobotServerConfig.plcServerPort);
|
||
tcpServerConfigElement->SetAttribute("robotServerIp", configResult.plcRobotServerConfig.robotServerIp.c_str());
|
||
tcpServerConfigElement->SetAttribute("robotServerPort", configResult.plcRobotServerConfig.robotServerPort);
|
||
// 保存PLC寄存器地址配置
|
||
tcpServerConfigElement->SetAttribute("addrPhotoRequest", configResult.plcRobotServerConfig.registerConfig.addrPhotoRequest);
|
||
tcpServerConfigElement->SetAttribute("addrDataComplete", configResult.plcRobotServerConfig.registerConfig.addrDataComplete);
|
||
tcpServerConfigElement->SetAttribute("addrCoordDataStart", configResult.plcRobotServerConfig.registerConfig.addrCoordDataStart);
|
||
// 保存姿态输出顺序配置
|
||
tcpServerConfigElement->SetAttribute("poseOutputOrder", configResult.plcRobotServerConfig.poseOutputOrder);
|
||
// 保存方向向量反向配置
|
||
tcpServerConfigElement->SetAttribute("dirVectorInvert", configResult.plcRobotServerConfig.dirVectorInvert);
|
||
root->InsertEndChild(tcpServerConfigElement);
|
||
|
||
// 保存到文件
|
||
XMLError err = doc.SaveFile(filePath.c_str());
|
||
if (err != XML_SUCCESS)
|
||
{
|
||
std::cerr << "无法保存配置文件: " << filePath << std::endl;
|
||
return false;
|
||
}
|
||
|
||
// 触发配置改变通知
|
||
if (m_pNotify)
|
||
{
|
||
m_pNotify->OnConfigChanged(configResult);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// 设置配置改变通知回调
|
||
void CVrConfig::SetConfigChangeNotify(IVrConfigChangeNotify* notify)
|
||
{
|
||
m_pNotify = notify;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief 创建实例
|
||
* @return 实例
|
||
*/
|
||
bool IVrConfig::CreateInstance(IVrConfig** ppVrConfig)
|
||
{
|
||
*ppVrConfig = new CVrConfig();
|
||
return *ppVrConfig != nullptr;
|
||
}
|