GrabBag/App/ScrewPosition/ScrewPositionApp/Presenter/Src/ScrewPositionPresenter.cpp

700 lines
25 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ScrewPositionPresenter.h"
#include "DetectPresenter.h"
#include "PathManager.h"
#include "ScrewPositionTCPProtocol.h"
#include "Version.h"
#include "VrConvert.h"
#include "VrError.h"
#include "VrLog.h"
#include "VrTimeUtils.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDateTime>
#include <QtCore/QString>
#include <algorithm>
#include <cstdio>
#include <cstring>
ScrewPositionPresenter::ScrewPositionPresenter(QObject *parent)
: BasePresenter(parent)
{
}
ScrewPositionPresenter::~ScrewPositionPresenter()
{
if (m_pConfigManager) {
delete m_pConfigManager;
m_pConfigManager = nullptr;
}
if (m_pTCPServer) {
m_pTCPServer->Deinitialize();
delete m_pTCPServer;
m_pTCPServer = nullptr;
}
if (m_pDetectPresenter) {
delete m_pDetectPresenter;
m_pDetectPresenter = nullptr;
}
}
int ScrewPositionPresenter::InitApp()
{
LOG_DEBUG("Start APP Version: %s\n", SCREWPOSITION_FULL_VERSION_STRING);
SetWorkStatus(WorkStatus::InitIng);
m_pDetectPresenter = new DetectPresenter();
m_pConfigManager = new ConfigManager();
if (!m_pConfigManager) {
LOG_ERROR("Failed to create ConfigManager instance\n");
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate("配置管理器创建失败");
}
return ERR_CODE(DEV_CONFIG_ERR);
}
if (!m_pConfigManager->Initialize()) {
LOG_ERROR("Failed to initialize ConfigManager\n");
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate("配置管理器初始化失败");
}
return ERR_CODE(DEV_CONFIG_ERR);
}
const ConfigResult configResult = m_pConfigManager->GetConfigResult();
SetDebugParam(configResult.debugParam);
m_modbusRegistersInitialized = false;
m_modbusWorkStatus = 0;
std::vector<DeviceInfo> cameraList = configResult.cameraList;
InitCamera(cameraList, false, true);
LOG_INFO("Camera initialization completed. Connected cameras: %zu, default camera index: %d\n",
m_vrEyeDeviceList.size(), m_currentCameraIndex);
int nRet = InitTCPServer();
if (nRet != SUCCESS) {
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate("TCP服务器初始化失败");
}
m_bTCPConnected = false;
} else {
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate("TCP服务器初始化成功");
}
}
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate("设备初始化完成");
}
CheckAndUpdateWorkStatus();
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate("配置初始化成功");
}
return SUCCESS;
}
int ScrewPositionPresenter::InitAlgoParams()
{
LOG_DEBUG("initializing algorithm parameters\n");
const ConfigResult configResult = m_pConfigManager->GetConfigResult();
SetDebugParam(configResult.debugParam);
LOG_INFO("Loaded %zu detection config sets from config.xml\n",
configResult.detectionConfigList.size());
for (const auto& item : configResult.detectionConfigList) {
const char* typeStr = (item.detectionType == DETECTION_TYPE_TOOL_DISK) ? "toolDisk" : "screw";
LOG_INFO(" - camera %d / %s : rodDiameter=%.1f isHorizonScan=%s\n",
item.cameraIndex, typeStr,
item.algorithmParams.screwParam.rodDiameter,
item.algorithmParams.screwParam.isHorizonScan ? "true" : "false");
}
LOG_INFO("Algorithm parameters initialized successfully\n");
return SUCCESS;
}
CalibMatrix ScrewPositionPresenter::GetClibMatrix(int cameraIndex, DetectionType type) const
{
CalibMatrix clibMatrix;
const double identity[16] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
};
std::memcpy(clibMatrix.clibMatrix, identity, sizeof(identity));
if (!m_pConfigManager) {
LOG_WARNING("ConfigManager not initialized while requesting clib matrix\n");
return clibMatrix;
}
const ConfigResult configResult = m_pConfigManager->GetConfigResult();
if (const auto* item = configResult.FindDetectionConfig(cameraIndex, type)) {
std::memcpy(clibMatrix.clibMatrix, item->handEyeMatrix.matrix, sizeof(identity));
} else {
LOG_WARNING("No clib matrix configured for camera=%d type=%d, using identity\n",
cameraIndex, static_cast<int>(type));
}
return clibMatrix;
}
CalibMatrix ScrewPositionPresenter::GetClibMatrix(int index) const
{
return GetClibMatrix(index + 1, DETECTION_TYPE_SCREW);
}
void ScrewPositionPresenter::CheckAndUpdateWorkStatus()
{
SetWorkStatus(m_bCameraConnected ? WorkStatus::Ready : WorkStatus::Error);
}
int ScrewPositionPresenter::ProcessAlgoDetection(std::vector<std::pair<EVzResultDataType, SVzLaserLineData>>& detectionDataCache)
{
LOG_INFO("[Algo Thread] Start real detection task using algorithm\n");
const unsigned int lineNum = detectionDataCache.size();
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate(QString("扫描线数:%1正在算法检测...").arg(lineNum).toStdString());
}
if (!m_pDetectPresenter) {
LOG_ERROR("DetectPresenter is null, cannot proceed with detection\n");
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate("检测处理器未初始化");
}
return ERR_CODE(DEV_NOT_FIND);
}
CVrTimeUtils oTimeUtils;
const CalibMatrix currentClibMatrix = GetClibMatrix(m_currentCameraIndex, m_currentDetectionType);
const ConfigResult configResult = m_pConfigManager->GetConfigResult();
const VrDebugParam debugParam = configResult.debugParam;
const int poseOutputOrder = configResult.poseOutputOrder;
// 选中 (camera, detectionType) 对应的 4 套之一;找不到时使用默认值(已在加载时补齐,
// 此处保留兜底是为了应对运行期相机数量变化的极端场景)。
VrAlgorithmParams algorithmParams;
HandEyeExtrinsic extrinsic;
if (const auto* item = configResult.FindDetectionConfig(m_currentCameraIndex, m_currentDetectionType)) {
algorithmParams = item->algorithmParams;
// planeCalibParam 是相机级共享配置,永远从顶层取
algorithmParams.planeCalibParam = configResult.algorithmParams.planeCalibParam;
extrinsic.eulerOrder = item->handEyeMatrix.eulerOrder;
extrinsic.rotX = item->handEyeMatrix.rotX;
extrinsic.rotY = item->handEyeMatrix.rotY;
extrinsic.rotZ = item->handEyeMatrix.rotZ;
extrinsic.approachOffset = item->handEyeMatrix.approachOffset;
extrinsic.offsetX = item->handEyeMatrix.offsetX;
extrinsic.offsetY = item->handEyeMatrix.offsetY;
extrinsic.offsetZ = item->handEyeMatrix.offsetZ;
extrinsic.outRotX = item->handEyeMatrix.outRotX;
extrinsic.outRotY = item->handEyeMatrix.outRotY;
extrinsic.outRotZ = item->handEyeMatrix.outRotZ;
} else {
LOG_WARNING("No detection config set found for camera=%d type=%d, using defaults\n",
m_currentCameraIndex, static_cast<int>(m_currentDetectionType));
algorithmParams.planeCalibParam = configResult.algorithmParams.planeCalibParam;
}
LOG_INFO("[Algo Thread] camera=%d type=%d eulerOrder=%d poseOutputOrder=%d rot=(%.3f, %.3f, %.3f) outRot=(%.3f, %.3f, %.3f) approachOffset=%.3f offset=(%.3f, %.3f, %.3f)\n",
m_currentCameraIndex, static_cast<int>(m_currentDetectionType),
extrinsic.eulerOrder, poseOutputOrder,
extrinsic.rotX, extrinsic.rotY, extrinsic.rotZ,
extrinsic.outRotX, extrinsic.outRotY, extrinsic.outRotZ,
extrinsic.approachOffset,
extrinsic.offsetX, extrinsic.offsetY, extrinsic.offsetZ);
DetectionResult detectionResult;
detectionResult.cameraIndex = m_currentCameraIndex;
int nRet = SUCCESS;
if (m_currentDetectionType == DETECTION_TYPE_TOOL_DISK) {
nRet = m_pDetectPresenter->DetectToolDisk(
m_currentCameraIndex,
detectionDataCache,
algorithmParams,
debugParam,
m_dataLoader,
currentClibMatrix.clibMatrix,
m_currentRobotPose,
extrinsic,
poseOutputOrder,
detectionResult);
} else {
nRet = m_pDetectPresenter->DetectScrew(
m_currentCameraIndex,
detectionDataCache,
algorithmParams,
debugParam,
m_dataLoader,
currentClibMatrix.clibMatrix,
m_currentRobotPose,
extrinsic,
poseOutputOrder,
detectionResult);
}
if (nRet != SUCCESS) {
detectionResult.success = false;
if (detectionResult.errorCode == 0) {
detectionResult.errorCode = nRet;
}
if (detectionResult.message.isEmpty() || detectionResult.message == QStringLiteral("检测成功")) {
detectionResult.message = QString("检测失败:%1").arg(nRet);
}
}
LOG_INFO("[Algo Thread] detection type=%d objects=%zu time : %.2f ms\n",
static_cast<int>(m_currentDetectionType),
detectionResult.positions.size(),
oTimeUtils.GetElapsedTimeInMilliSec());
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnDetectionResult(detectionResult);
}
QString statusMsg;
if (!detectionResult.success) {
statusMsg = detectionResult.message;
} else if (m_currentDetectionType == DETECTION_TYPE_TOOL_DISK) {
statusMsg = QString("工具盘检测完成,定位点数:%1").arg(detectionResult.positions.size());
} else {
statusMsg = QString("检测完成,发现%1个螺杆").arg(detectionResult.positions.size());
}
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate(statusMsg.toStdString());
}
_SendDetectionResultToTCP(detectionResult, m_currentCameraIndex);
_PublishDetectionResultToModbus(detectionResult);
return nRet;
}
void ScrewPositionPresenter::OnConfigChanged(const ConfigResult& configResult)
{
LOG_INFO("Configuration changed notification received, reloading algorithm parameters\n");
SetDebugParam(configResult.debugParam);
int result = InitAlgoParams();
stopServer();
const int tcpResult = InitTCPServer();
if (result == SUCCESS) {
LOG_INFO("Algorithm parameters reloaded successfully after config change\n");
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate("配置已更新,算法参数重新加载成功");
}
} else {
LOG_ERROR("Failed to reload algorithm parameters after config change, error: %d\n", result);
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate("配置更新后算法参数重新加载失败");
}
}
if (tcpResult != SUCCESS) {
LOG_ERROR("Failed to restart TCP server after config change, error: %d\n", tcpResult);
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate("TCP server restart failed");
}
}
}
SSG_planeCalibPara ScrewPositionPresenter::_GetCameraCalibParam(int cameraIndex)
{
SSG_planeCalibPara calibParam;
const double identityMatrix[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
for (int i = 0; i < 9; ++i) {
calibParam.planeCalib[i] = identityMatrix[i];
calibParam.invRMatrix[i] = identityMatrix[i];
}
calibParam.planeHeight = -1.0;
const VrAlgorithmParams algorithmParams = m_pConfigManager->GetAlgorithmParams();
for (const auto& cameraParam : algorithmParams.planeCalibParam.cameraCalibParams) {
if (cameraParam.cameraIndex == cameraIndex && cameraParam.isCalibrated) {
for (int i = 0; i < 9; ++i) {
calibParam.planeCalib[i] = cameraParam.planeCalib[i];
calibParam.invRMatrix[i] = cameraParam.invRMatrix[i];
}
calibParam.planeHeight = cameraParam.planeHeight;
}
}
return calibParam;
}
void ScrewPositionPresenter::OnCameraStatusChanged(int cameraIndex, bool isConnected)
{
LOG_INFO("Camera %d status changed: %s\n", cameraIndex, isConnected ? "connected" : "disconnected");
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
if (cameraIndex == 1) {
pStatus->OnCamera1StatusChanged(isConnected);
} else if (cameraIndex == 2) {
pStatus->OnCamera2StatusChanged(isConnected);
}
QString cameraName;
const int arrayIndex = cameraIndex - 1;
if (arrayIndex >= 0 && arrayIndex < static_cast<int>(m_vrEyeDeviceList.size())) {
cameraName = QString::fromStdString(m_vrEyeDeviceList[arrayIndex].first);
} else {
cameraName = QString("相机%1").arg(cameraIndex);
}
const QString statusMsg = QString("%1%2").arg(cameraName).arg(isConnected ? "已连接" : "已断开");
pStatus->OnStatusUpdate(statusMsg.toStdString());
}
CheckAndUpdateWorkStatus();
}
void ScrewPositionPresenter::OnWorkStatusChanged(WorkStatus status)
{
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnWorkStatusChanged(status);
}
if (!m_modbusRegistersInitialized && status == WorkStatus::Ready) {
_InitializeModbusRegisters();
}
if (status == WorkStatus::Working) {
_UpdateModbusWorkStatus(1);
} else if (status == WorkStatus::Error) {
_UpdateModbusWorkStatus(3);
}
}
void ScrewPositionPresenter::OnCameraCountChanged(int count)
{
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnCameraCountChanged(count);
}
}
void ScrewPositionPresenter::OnStatusUpdate(const std::string& statusMessage)
{
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate(statusMessage);
}
}
void ScrewPositionPresenter::OnModbusServerStatusChanged(bool isConnected)
{
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnRobotConnectionChanged(isConnected);
}
}
void ScrewPositionPresenter::OnModbusWriteCallback(uint16_t startAddress, const uint16_t* data, uint16_t count)
{
if (!data || count == 0) {
return;
}
constexpr uint16_t kTriggerAddress = 0;
constexpr uint16_t kRobotPoseAddress = 2;
constexpr uint16_t kRobotPoseRegCount = 12;
// 缓存机械臂位姿写入地址2~136个float32
for (uint16_t i = 0; i < count; ++i) {
uint16_t addr = startAddress + i;
if (addr >= kRobotPoseAddress && addr < kRobotPoseAddress + kRobotPoseRegCount) {
m_modbusRobotPoseRegs[addr - kRobotPoseAddress] = data[i];
}
}
// 检查触发
uint16_t triggerValue = 0;
bool hasTrigger = false;
for (uint16_t i = 0; i < count; ++i) {
if (startAddress + i == kTriggerAddress) {
triggerValue = data[i];
hasTrigger = true;
break;
}
}
if (!hasTrigger) {
return;
}
const uint16_t resetValue = 0;
WriteModbusRegisters(kTriggerAddress, &resetValue, 1);
if (triggerValue == static_cast<uint16_t>(DETECTION_TYPE_SCREW) ||
triggerValue == static_cast<uint16_t>(DETECTION_TYPE_TOOL_DISK)) {
// 从缓存的寄存器中解析机械臂位姿
RobotPose6D robotPose;
auto regToFloat = [this](int offset) -> float {
uint32_t raw = (static_cast<uint32_t>(m_modbusRobotPoseRegs[offset]) << 16) | static_cast<uint32_t>(m_modbusRobotPoseRegs[offset + 1]);
float val = 0;
std::memcpy(&val, &raw, sizeof(val));
return val;
};
robotPose.x = regToFloat(0);
robotPose.y = regToFloat(2);
robotPose.z = regToFloat(4);
robotPose.a = regToFloat(6);
robotPose.b = regToFloat(8);
robotPose.c = regToFloat(10);
LOG_INFO("Modbus trigger: type=%u, robotPose=(%.3f, %.3f, %.3f, %.3f, %.3f, %.3f)\n",
triggerValue, robotPose.x, robotPose.y, robotPose.z, robotPose.a, robotPose.b, robotPose.c);
TriggerDetection(-1, static_cast<DetectionType>(triggerValue), robotPose);
return;
}
LOG_WARNING("Unsupported Modbus trigger value: %u\n", triggerValue);
_UpdateModbusWorkStatus(3);
if (auto pStatus = GetStatusCallback<IYScrewPositionStatus>()) {
pStatus->OnStatusUpdate(QString("Modbus触发值无效:%1").arg(triggerValue).toStdString());
}
}
bool ScrewPositionPresenter::CalculatePlaneCalibration(
const std::vector<std::pair<EVzResultDataType, SVzLaserLineData>>& scanData,
double planeCalib[9],
double& planeHeight,
double invRMatrix[9])
{
try {
if (scanData.empty()) {
LOG_ERROR("No scan data available for plane calibration\n");
return false;
}
LaserDataLoader dataLoader;
std::vector<std::vector<SVzNL3DPosition>> xyzData;
int convertResult = dataLoader.ConvertToSVzNL3DPosition(scanData, xyzData);
if (convertResult != SUCCESS || xyzData.empty()) {
LOG_WARNING("Failed to convert data to XYZ format or no XYZ data available\n");
return false;
}
const double identity[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
std::memcpy(planeCalib, identity, sizeof(double) * 9);
std::memcpy(invRMatrix, identity, sizeof(double) * 9);
planeHeight = -1.0;
LOG_INFO("Plane calibration calculated successfully: height=%.3f\n", planeHeight);
return true;
} catch (const std::exception& e) {
LOG_ERROR("Exception in CalculatePlaneCalibration: %s\n", e.what());
return false;
} catch (...) {
LOG_ERROR("Unknown exception in CalculatePlaneCalibration\n");
return false;
}
}
bool ScrewPositionPresenter::SaveLevelingResults(double planeCalib[9], double planeHeight, double invRMatrix[9],
int cameraIndex, const QString& cameraName)
{
try {
if (!m_pConfigManager) {
LOG_ERROR("ConfigManager is null, cannot save leveling results\n");
return false;
}
if (cameraIndex <= 0 || cameraName.isEmpty()) {
LOG_ERROR("Invalid camera info when saving leveling results\n");
return false;
}
const QString configPath = PathManager::GetInstance().GetConfigFilePath();
SystemConfig systemConfig = m_pConfigManager->GetConfig();
VrCameraPlaneCalibParam cameraParam;
cameraParam.cameraIndex = cameraIndex;
cameraParam.cameraName = cameraName.toStdString();
cameraParam.planeHeight = planeHeight;
cameraParam.isCalibrated = true;
for (int i = 0; i < 9; ++i) {
cameraParam.planeCalib[i] = planeCalib[i];
cameraParam.invRMatrix[i] = invRMatrix[i];
}
systemConfig.configResult.algorithmParams.planeCalibParam.SetCameraCalibParam(cameraParam);
if (!m_pConfigManager->UpdateFullConfig(systemConfig)) {
LOG_ERROR("Failed to update config with leveling results\n");
return false;
}
if (!m_pConfigManager->SaveConfigToFile(configPath.toStdString())) {
LOG_ERROR("Failed to save config file with leveling results\n");
return false;
}
LOG_INFO("Leveling results saved successfully for camera %d (%s)\n",
cameraIndex, cameraName.toUtf8().constData());
return true;
} catch (const std::exception& e) {
LOG_ERROR("Exception in SaveLevelingResults: %s\n", e.what());
return false;
}
}
bool ScrewPositionPresenter::LoadLevelingResults(int cameraIndex, const QString& cameraName,
double planeCalib[9], double& planeHeight, double invRMatrix[9])
{
try {
if (!m_pConfigManager) {
LOG_ERROR("ConfigManager is null, cannot load calibration data\n");
return false;
}
const ConfigResult configResult = m_pConfigManager->GetConfigResult();
VrCameraPlaneCalibParam cameraParamValue;
if (!configResult.algorithmParams.planeCalibParam.GetCameraCalibParam(cameraIndex, cameraParamValue) ||
!cameraParamValue.isCalibrated) {
LOG_INFO("No calibration data found for camera %d (%s)\n",
cameraIndex, cameraName.toUtf8().constData());
return false;
}
for (int i = 0; i < 9; ++i) {
planeCalib[i] = cameraParamValue.planeCalib[i];
invRMatrix[i] = cameraParamValue.invRMatrix[i];
}
planeHeight = cameraParamValue.planeHeight;
return true;
} catch (const std::exception& e) {
LOG_ERROR("Exception in LoadLevelingResults: %s\n", e.what());
return false;
}
}
void ScrewPositionPresenter::DeinitApp()
{
LOG_DEBUG("Deinitializing ScrewPositionPresenter\n");
StopDetection();
if (m_pTCPServer) {
m_pTCPServer->Deinitialize();
delete m_pTCPServer;
m_pTCPServer = nullptr;
}
if (m_pConfigManager) {
delete m_pConfigManager;
m_pConfigManager = nullptr;
}
if (m_pDetectPresenter) {
delete m_pDetectPresenter;
m_pDetectPresenter = nullptr;
}
}
bool ScrewPositionPresenter::TriggerDetection(int cameraIndex, DetectionType detectionType, const RobotPose6D& robotPose)
{
if (cameraIndex > 0) {
SetDefaultCameraIndex(cameraIndex);
}
m_currentDetectionType = detectionType;
m_currentRobotPose = robotPose;
m_requestTimestamp = QDateTime::currentMSecsSinceEpoch();
if (!m_bCameraConnected) {
LOG_WARNING("Camera not connected, cannot trigger detection\n");
_UpdateModbusWorkStatus(3);
return false;
}
if (GetCurrentWorkStatus() == WorkStatus::Working) {
LOG_WARNING("Detection is already running, skip duplicated trigger\n");
_UpdateModbusWorkStatus(1);
return false;
}
_InitializeModbusRegisters();
_ResetModbusResultRegisters();
_UpdateModbusWorkStatus(1);
int ret = StartDetection(cameraIndex, false);
if (ret != SUCCESS) {
LOG_ERROR("Failed to trigger detection, error: %d\n", ret);
_UpdateModbusWorkStatus(3);
return false;
}
return true;
}
int ScrewPositionPresenter::LoadAndDetect(const QString& fileName, DetectionType detectionType)
{
LOG_INFO("Loading data from file: %s, detectionType: %d\n",
fileName.toStdString().c_str(), static_cast<int>(detectionType));
m_currentDetectionType = detectionType;
return LoadDebugDataAndDetect(fileName.toStdString());
}
void ScrewPositionPresenter::ReconnectCamera()
{
LOG_INFO("Attempting to reconnect cameras\n");
TryReconnectCameras();
}
ScrewPositionPresenter::AlgoParams ScrewPositionPresenter::GetAlgoParams() const
{
AlgoParams params;
if (m_pConfigManager) {
// 以 (Camera 1, Screw) 作为「公共默认」展示值。
// 这条 set 在加载时已被 EnsureDetectionConfig 兜底填充,肯定存在。
const ConfigResult configResult = m_pConfigManager->GetConfigResult();
const VrDetectionConfigSet* defaultSet =
configResult.FindDetectionConfig(1, DETECTION_TYPE_SCREW);
if (defaultSet) {
params.screwParam = defaultSet->algorithmParams.screwParam;
params.cornerParam = defaultSet->algorithmParams.cornerParam;
params.filterParam = defaultSet->algorithmParams.filterParam;
params.growParam = defaultSet->algorithmParams.growParam;
return params;
}
}
params.screwParam.rodDiameter = 10.0;
params.screwParam.isHorizonScan = true;
return params;
}
QString ScrewPositionPresenter::GetAlgoVersion() const
{
return DetectPresenter::GetAlgoVersion();
}
void ScrewPositionPresenter::SetAlgoParams(const AlgoParams& params)
{
if (!m_pConfigManager) {
LOG_WARNING("ConfigManager not initialized, cannot set algorithm params\n");
return;
}
// 旧对话框只关心「公共默认」概念,因此把它写到全部 4 套 (camera, type) 上,
// 想要差异化的用户通过新对话框单独覆盖。
SystemConfig systemConfig = m_pConfigManager->GetConfig();
for (auto& item : systemConfig.configResult.detectionConfigList) {
item.algorithmParams.screwParam = params.screwParam;
item.algorithmParams.cornerParam = params.cornerParam;
item.algorithmParams.filterParam = params.filterParam;
item.algorithmParams.growParam = params.growParam;
}
m_pConfigManager->UpdateFullConfig(systemConfig);
LOG_INFO("Algorithm parameters updated for all (camera, type) sets\n");
}