716 lines
37 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 "dialogalgoarg.h"
#include "ui_dialogalgoarg.h"
#include <QCheckBox>
#include <QDoubleValidator>
#include <QFormLayout>
#include <QFont>
#include <QIntValidator>
#include <QLineEdit>
#include <QList>
#include <QScrollArea>
#include <QTabWidget>
#include <cmath>
#include "ParkingSpaceGuidePresenter.h"
#include "PathManager.h"
#include "StyledMessageBox.h"
DialogAlgoArg::DialogAlgoArg(QWidget* parent)
: QDialog(parent)
, ui(new Ui::DialogAlgoArg)
{
ui->setupUi(this);
setWindowTitle(QStringLiteral("停机引导参数设置"));
if (ui->label_title) {
ui->label_title->setText(QStringLiteral("停机引导参数设置"));
}
BuildUi();
connect(ui->tabWidget, &QTabWidget::currentChanged, this, [this](int index) {
if (index >= 0 && index < m_visiblePages.size()) {
UpdateTitle(m_visiblePages[index]);
}
});
ApplyUiFont();
}
DialogAlgoArg::~DialogAlgoArg()
{
delete ui;
}
void DialogAlgoArg::SetPresenter(ParkingSpaceGuidePresenter* presenter)
{
m_presenter = presenter;
LoadParams();
}
void DialogAlgoArg::SetCurrentPage(ConfigPage page)
{
if (ui && ui->tabWidget) {
ShowTabGroup(page);
}
}
void DialogAlgoArg::ShowTabGroup(ConfigPage page)
{
if (!ui || !ui->tabWidget) {
return;
}
const bool oldBlocked = ui->tabWidget->blockSignals(true);
ui->tabWidget->clear();
HideDetachedTabs();
m_visiblePages.clear();
auto addTab = [this](QWidget* tab, const QString& title, ConfigPage tabPage) {
if (tab) {
ui->tabWidget->addTab(tab, title);
m_visiblePages.push_back(tabPage);
}
};
int selectedIndex = 0;
if (page == ConfigPage::Camera || page == ConfigPage::Lidar) {
addTab(m_cameraTab, QStringLiteral("相机参数"), ConfigPage::Camera);
addTab(m_lidarTab, QStringLiteral("雷达参数"), ConfigPage::Lidar);
selectedIndex = page == ConfigPage::Lidar ? 1 : 0;
} else if (page == ConfigPage::Calibration) {
addTab(m_groundCalibrationTab, QStringLiteral("地面调平"), ConfigPage::Calibration);
} else if (page == ConfigPage::Multicast) {
addTab(m_multicastTab, QStringLiteral("组播参数"), ConfigPage::Multicast);
} else {
addTab(m_planeParkingTab, QStringLiteral("停机几何"), ConfigPage::Detection);
addTab(m_groundCalibrationTab, QStringLiteral("地面调平"), ConfigPage::Detection);
addTab(m_treeGrowTab, QStringLiteral("聚类生长"), ConfigPage::Detection);
addTab(m_guideDecisionTab, QStringLiteral("引导判定"), ConfigPage::Detection);
addTab(m_processTab, QStringLiteral("流程判定"), ConfigPage::Detection);
addTab(m_modelRecognitionTab, QStringLiteral("机型识别"), ConfigPage::Detection);
addTab(m_personDetectionTab, QStringLiteral("人员检测"), ConfigPage::Detection);
}
if (selectedIndex >= 0 && selectedIndex < ui->tabWidget->count()) {
ui->tabWidget->setCurrentIndex(selectedIndex);
}
if (ui->tabWidget->currentWidget()) {
ui->tabWidget->currentWidget()->show();
}
ui->tabWidget->blockSignals(oldBlocked);
UpdateTitle(page);
}
void DialogAlgoArg::UpdateTitle(ConfigPage page)
{
QString title = QStringLiteral("停机引导参数设置");
switch (page) {
case ConfigPage::Detection:
title = QStringLiteral("检测参数设置");
break;
case ConfigPage::Camera:
title = QStringLiteral("相机参数设置");
break;
case ConfigPage::Lidar:
title = QStringLiteral("雷达参数设置");
break;
case ConfigPage::Multicast:
title = QStringLiteral("组播参数设置");
break;
case ConfigPage::Calibration:
title = QStringLiteral("雷达地面调平参数");
break;
}
setWindowTitle(title);
if (ui && ui->label_title) {
ui->label_title->setText(title);
}
}
void DialogAlgoArg::HideDetachedTabs()
{
const QList<QWidget*> tabs = {
m_planeParkingTab,
m_groundCalibrationTab,
m_treeGrowTab,
m_guideDecisionTab,
m_processTab,
m_modelRecognitionTab,
m_personDetectionTab,
m_cameraTab,
m_lidarTab,
m_multicastTab
};
for (QWidget* tab : tabs) {
if (tab) {
tab->hide();
}
}
}
void DialogAlgoArg::BuildUi()
{
ui->tabWidget->clear();
auto makeTab = [this](QWidget** tabWidget, const QString& title) -> QWidget* {
auto* scroll = new QScrollArea(ui->tabWidget);
scroll->setWidgetResizable(true);
auto* page = new QWidget(scroll);
page->setObjectName(title);
auto* layout = new QFormLayout(page);
layout->setContentsMargins(24, 24, 24, 24);
layout->setSpacing(14);
scroll->setWidget(page);
*tabWidget = scroll;
scroll->hide();
return page;
};
QWidget* planeParking = makeTab(&m_planeParkingTab, QStringLiteral("停机几何"));
m_parkingPointX = AddDoubleEditor(planeParking, QStringLiteral("停机点X(毫米)"), 0, -1000000.0, 1000000.0);
m_parkingPointY = AddDoubleEditor(planeParking, QStringLiteral("停机点Y(毫米)"), 1, -1000000.0, 1000000.0);
m_parkingPointZ = AddDoubleEditor(planeParking, QStringLiteral("停机点Z(毫米)"), 2, -1000000.0, 1000000.0);
m_guideLinePointX = AddDoubleEditor(planeParking, QStringLiteral("引导线远点X(毫米)"), 3, -1000000.0, 1000000.0);
m_guideLinePointY = AddDoubleEditor(planeParking, QStringLiteral("引导线远点Y(毫米)"), 4, -1000000.0, 1000000.0);
m_guideLinePointZ = AddDoubleEditor(planeParking, QStringLiteral("引导线远点Z(毫米)"), 5, -1000000.0, 1000000.0);
m_guidingRange = AddDoubleEditor(planeParking, QStringLiteral("飞机引导范围(毫米)"), 6, 0.0, 10000000.0);
m_parkingRange = AddDoubleEditor(planeParking, QStringLiteral("引导线过滤范围(毫米)"), 7, 0.0, 10000000.0);
m_distFromNoseToWheel = AddDoubleEditor(planeParking, QStringLiteral("机鼻到前轮距离(毫米)"), 8, 0.0, 100000.0);
QWidget* ground = makeTab(&m_groundCalibrationTab, QStringLiteral("地面调平"));
for (int i = 0; i < 9; ++i) {
m_planeCalib[i] = AddDoubleEditor(ground,
QStringLiteral("调平矩阵 R%1%2").arg(i / 3).arg(i % 3), i, -1000.0, 1000.0);
}
m_planeHeight = AddDoubleEditor(ground, QStringLiteral("地面高度(毫米)"), 9, -1000000.0, 1000000.0);
for (int i = 0; i < 9; ++i) {
m_invRMatrix[i] = AddDoubleEditor(ground,
QStringLiteral("逆矩阵 R%1%2").arg(i / 3).arg(i % 3), 10 + i, -1000.0, 1000.0);
}
QWidget* treeGrow = makeTab(&m_treeGrowTab, QStringLiteral("聚类生长"));
m_yDeviationMax = AddDoubleEditor(treeGrow, QStringLiteral("Y方向最大偏差(毫米)"), 0, 0.0, 1000000.0);
m_zDeviationMax = AddDoubleEditor(treeGrow, QStringLiteral("Z方向最大偏差(毫米)"), 1, 0.0, 1000000.0);
m_maxLineSkipNum = AddIntEditor(treeGrow, QStringLiteral("最大跳线数(-1按距离)"), 2, -1, 1000000);
m_maxSkipDistance = AddDoubleEditor(treeGrow, QStringLiteral("最大跳过距离(毫米,-1禁用)"), 3, -1.0, 1000000.0);
m_minLTypeTreeLen = AddDoubleEditor(treeGrow, QStringLiteral("L型树最小长度(毫米)"), 4, 0.0, 1000000.0);
m_minVTypeTreeLen = AddDoubleEditor(treeGrow, QStringLiteral("V型树最小长度(毫米)"), 5, 0.0, 1000000.0);
QWidget* guideDecision = makeTab(&m_guideDecisionTab, QStringLiteral("引导判定"));
m_lateralTolerance = AddDoubleEditor(guideDecision, QStringLiteral("横向对中容差(毫米)"), 0, 0.0, 100000.0);
m_angleTolerance = AddDoubleEditor(guideDecision, QStringLiteral("航向角容差(度)"), 1, 0.0, 180.0);
QWidget* process = makeTab(&m_processTab, QStringLiteral("流程判定"));
m_dockingStartDistance = AddDoubleEditor(process, QStringLiteral("引导启动距离(毫米)"), 0, 0.0, 1000000.0);
m_captureStartDistance = AddDoubleEditor(process, QStringLiteral("目标捕获距离(毫米)"), 1, 0.0, 1000000.0);
m_approachStartDistance = AddDoubleEditor(process, QStringLiteral("对中/方位引导距离(毫米)"), 2, 0.0, 1000000.0);
m_slowDistance = AddDoubleEditor(process, QStringLiteral("减速触发距离(毫米)"), 3, 0.0, 1000000.0);
m_stopDistanceTolerance = AddDoubleEditor(process, QStringLiteral("到位距离容差(毫米)"), 4, 0.0, 100000.0);
m_overshootDistance = AddDoubleEditor(process, QStringLiteral("越过停止线距离(毫米)"), 5, 0.0, 1000000.0);
m_stoppedShortMinDistance = AddDoubleEditor(process, QStringLiteral("提前停止最小距离(毫米)"), 6, 0.0, 1000000.0);
m_maxApproachSpeed = AddDoubleEditor(process, QStringLiteral("最大接近速度(毫米/秒)"), 7, 0.0, 100000.0);
m_stoppedSpeedThreshold = AddDoubleEditor(process, QStringLiteral("静止速度阈值(毫米/秒)"), 8, 0.0, 100000.0);
m_speedFilterAlpha = AddDoubleEditor(process, QStringLiteral("速度滤波系数"), 9, 0.0, 1.0);
m_distanceChangeThreshold = AddDoubleEditor(process, QStringLiteral("距离变化阈值(毫米)"), 10, 0.0, 1000000.0);
m_lateralOffsetChangeThreshold = AddDoubleEditor(process, QStringLiteral("横向偏移变化阈值(毫米)"), 11, 0.0, 1000000.0);
m_stopStableFrames = AddIntEditor(process, QStringLiteral("到位稳定帧数"), 12, 1, 1000000);
m_stoppedShortStableFrames = AddIntEditor(process, QStringLiteral("提前停止稳定帧数"), 13, 1, 1000000);
m_errorFrameThreshold = AddIntEditor(process, QStringLiteral("连续错误帧阈值"), 14, 1, 1000000);
m_lostFrameThreshold = AddIntEditor(process, QStringLiteral("目标丢失帧阈值"), 15, 1, 1000000);
m_completedHoldFrames = AddIntEditor(process, QStringLiteral("完成状态保持帧数"), 16, 1, 1000000);
QWidget* model = makeTab(&m_modelRecognitionTab, QStringLiteral("机型识别"));
m_modelVerifyDistance = AddDoubleEditor(model, QStringLiteral("机型验证距离(毫米)"), 0, -1000000.0, 1000000.0);
m_modelRoiX = AddDoubleEditor(model, QStringLiteral("飞机检测区域 X (0~1)"), 1, 0.0, 1.0);
m_modelRoiY = AddDoubleEditor(model, QStringLiteral("飞机检测区域 Y (0~1)"), 2, 0.0, 1.0);
m_modelRoiWidth = AddDoubleEditor(model, QStringLiteral("飞机检测区域宽度 (0~1)"), 3, 0.000001, 1.0);
m_modelRoiHeight = AddDoubleEditor(model, QStringLiteral("飞机检测区域高度 (0~1)"), 4, 0.000001, 1.0);
m_confidenceThreshold = AddDoubleEditor(model, QStringLiteral("识别置信度阈值"), 5, 0.0, 1.0);
m_maxRecognitionAttempts = AddIntEditor(model, QStringLiteral("最大识别次数"), 6, 1, 1000);
QWidget* person = makeTab(&m_personDetectionTab, QStringLiteral("人员检测"));
m_personDetectionEnabled = AddCheckBox(person, QStringLiteral("启用停稳后人员检测"), 0);
m_personRoiX = AddDoubleEditor(person, QStringLiteral("轮挡区域 X (0~1)"), 1, 0.0, 1.0);
m_personRoiY = AddDoubleEditor(person, QStringLiteral("轮挡区域 Y (0~1)"), 2, 0.0, 1.0);
m_personRoiWidth = AddDoubleEditor(person, QStringLiteral("轮挡区域宽度 (0~1)"), 3, 0.000001, 1.0);
m_personRoiHeight = AddDoubleEditor(person, QStringLiteral("轮挡区域高度 (0~1)"), 4, 0.000001, 1.0);
m_personConfidenceThreshold = AddDoubleEditor(person, QStringLiteral("人员置信度阈值"), 5, 0.0, 1.0);
m_personStableFrames = AddIntEditor(person, QStringLiteral("连续有效检测次数"), 6, 1, 1000);
m_personDetectionIntervalMs = AddIntEditor(person, QStringLiteral("检测周期(毫秒)"), 7, 10, 60000);
QWidget* camera = makeTab(&m_cameraTab, QStringLiteral("相机参数"));
m_mvsSerialNumber = AddTextEditor(camera, QStringLiteral("设备序列号"), 0);
m_mvsDeviceIndex = AddIntEditor(camera, QStringLiteral("设备序号"), 1, 0, 64);
m_mvsEnabled = AddCheckBox(camera, QStringLiteral("启用"), 2);
QWidget* lidar = makeTab(&m_lidarTab, QStringLiteral("雷达参数"));
m_lidarType = AddTextEditor(lidar, QStringLiteral("雷达型号"), 0);
m_lidarHost = AddTextEditor(lidar, QStringLiteral("监听地址"), 1);
m_lidarMsopPort = AddIntEditor(lidar, QStringLiteral("数据端口"), 2, 1, 65535);
m_lidarDifopPort = AddIntEditor(lidar, QStringLiteral("设备端口"), 3, 1, 65535);
m_lidarMinDistance = AddDoubleEditor(lidar, QStringLiteral("最小距离(米)"), 4, 0.0, 1000.0);
m_lidarMaxDistance = AddDoubleEditor(lidar, QStringLiteral("最大距离(米)"), 5, 0.0, 1000.0);
m_lidarStartAngle = AddDoubleEditor(lidar, QStringLiteral("起始角度(度)"), 6, 0.0, 360.0);
m_lidarEndAngle = AddDoubleEditor(lidar, QStringLiteral("结束角度(度)"), 7, 0.0, 360.0);
QWidget* udp = makeTab(&m_multicastTab, QStringLiteral("组播参数"));
m_udpAddress = AddTextEditor(udp, QStringLiteral("组播地址"), 0);
m_udpPort = AddIntEditor(udp, QStringLiteral("组播端口"), 1, 1, 65535);
m_udpTargetId = AddTextEditor(udp, QStringLiteral("目标编号"), 2);
m_udpParkId = AddTextEditor(udp, QStringLiteral("车位编号"), 3);
m_udpEnabled = AddCheckBox(udp, QStringLiteral("启用"), 4);
ShowTabGroup(ConfigPage::Detection);
}
void DialogAlgoArg::ApplyUiFont()
{
QFont font;
font.setPointSize(16);
setFont(font);
const QList<QWidget*> widgets = findChildren<QWidget*>();
for (QWidget* widget : widgets) {
widget->setFont(font);
}
}
QLineEdit* DialogAlgoArg::AddDoubleEditor(QWidget* parent, const QString& label, int row, double min, double max)
{
Q_UNUSED(row);
auto* edit = new QLineEdit(parent);
auto* validator = new QDoubleValidator(min, max, 12, edit);
validator->setNotation(QDoubleValidator::ScientificNotation);
edit->setValidator(validator);
static_cast<QFormLayout*>(parent->layout())->addRow(label, edit);
return edit;
}
QLineEdit* DialogAlgoArg::AddIntEditor(QWidget* parent, const QString& label, int row, int min, int max)
{
Q_UNUSED(row);
auto* edit = new QLineEdit(parent);
edit->setValidator(new QIntValidator(min, max, edit));
static_cast<QFormLayout*>(parent->layout())->addRow(label, edit);
return edit;
}
QLineEdit* DialogAlgoArg::AddTextEditor(QWidget* parent, const QString& label, int row, bool password)
{
Q_UNUSED(row);
auto* edit = new QLineEdit(parent);
if (password) {
edit->setEchoMode(QLineEdit::Password);
}
static_cast<QFormLayout*>(parent->layout())->addRow(label, edit);
return edit;
}
QCheckBox* DialogAlgoArg::AddCheckBox(QWidget* parent, const QString& label, int row)
{
Q_UNUSED(row);
auto* check = new QCheckBox(parent);
static_cast<QFormLayout*>(parent->layout())->addRow(label, check);
return check;
}
void DialogAlgoArg::LoadParams()
{
if (!m_presenter || !m_presenter->GetConfigManager()) {
return;
}
const ConfigResult config = m_presenter->GetConfigManager()->GetConfigResult();
const VrAlgorithmParams& params = config.algorithmParams;
const VrPlaneParkingParam& parking = params.planeParkingParam;
SetDouble(m_parkingPointX, parking.parkingPointX);
SetDouble(m_parkingPointY, parking.parkingPointY);
SetDouble(m_parkingPointZ, parking.parkingPointZ);
SetDouble(m_guideLinePointX, parking.guideLinePointX);
SetDouble(m_guideLinePointY, parking.guideLinePointY);
SetDouble(m_guideLinePointZ, parking.guideLinePointZ);
SetDouble(m_guidingRange, parking.guidingRange);
SetDouble(m_parkingRange, parking.parkingRange);
SetDouble(m_distFromNoseToWheel, parking.distFromNoseToWheel);
const VrPlaneGroundCalibrationParam& ground = params.groundCalibrationParam;
SetMatrix(m_planeCalib, ground.planeCalib);
SetDouble(m_planeHeight, ground.planeHeight);
SetMatrix(m_invRMatrix, ground.invRMatrix);
const VrPlaneTreeGrowParam& tree = params.treeGrowParam;
SetDouble(m_yDeviationMax, tree.yDeviationMax);
SetDouble(m_zDeviationMax, tree.zDeviationMax);
SetInt(m_maxLineSkipNum, tree.maxLineSkipNum);
SetDouble(m_maxSkipDistance, tree.maxSkipDistance);
SetDouble(m_minLTypeTreeLen, tree.minLTypeTreeLen);
SetDouble(m_minVTypeTreeLen, tree.minVTypeTreeLen);
const VrGuideDecisionParam& guide = params.guideDecisionParam;
SetDouble(m_lateralTolerance, guide.lateralTolerance);
SetDouble(m_angleTolerance, guide.angleTolerance);
const VrParkingProcessParam& process = params.processParam;
SetDouble(m_dockingStartDistance, process.dockingStartDistance);
SetDouble(m_captureStartDistance, process.captureStartDistance);
SetDouble(m_approachStartDistance, process.approachStartDistance);
SetDouble(m_slowDistance, process.slowDistance);
SetDouble(m_stopDistanceTolerance, process.stopDistanceTolerance);
SetDouble(m_overshootDistance, process.overshootDistance);
SetDouble(m_stoppedShortMinDistance, process.stoppedShortMinDistance);
SetDouble(m_maxApproachSpeed, process.maxApproachSpeed);
SetDouble(m_stoppedSpeedThreshold, process.stoppedSpeedThreshold);
SetDouble(m_speedFilterAlpha, process.speedFilterAlpha);
SetDouble(m_distanceChangeThreshold, process.distanceChangeThreshold);
SetDouble(m_lateralOffsetChangeThreshold, process.lateralOffsetChangeThreshold);
SetInt(m_stopStableFrames, process.stopStableFrames);
SetInt(m_stoppedShortStableFrames, process.stoppedShortStableFrames);
SetInt(m_errorFrameThreshold, process.errorFrameThreshold);
SetInt(m_lostFrameThreshold, process.lostFrameThreshold);
SetInt(m_completedHoldFrames, process.completedHoldFrames);
const VrModelRecognitionParam& model = params.modelRecognitionParam;
SetDouble(m_modelVerifyDistance, model.modelVerifyDistance);
SetDouble(m_modelRoiX, model.roiX);
SetDouble(m_modelRoiY, model.roiY);
SetDouble(m_modelRoiWidth, model.roiWidth);
SetDouble(m_modelRoiHeight, model.roiHeight);
SetDouble(m_confidenceThreshold, model.confidenceThreshold);
SetInt(m_maxRecognitionAttempts, model.maxRecognitionAttempts);
const VrPersonDetectionParam& person = params.personDetectionParam;
m_personDetectionEnabled->setChecked(person.enabled);
SetDouble(m_personRoiX, person.roiX);
SetDouble(m_personRoiY, person.roiY);
SetDouble(m_personRoiWidth, person.roiWidth);
SetDouble(m_personRoiHeight, person.roiHeight);
SetDouble(m_personConfidenceThreshold, person.confidenceThreshold);
SetInt(m_personStableFrames, person.stableFrames);
SetInt(m_personDetectionIntervalMs, person.detectionIntervalMs);
m_mvsSerialNumber->setText(QString::fromStdString(config.mvsCamera.serialNumber));
SetInt(m_mvsDeviceIndex, config.mvsCamera.deviceIndex);
m_mvsEnabled->setChecked(config.mvsCamera.enabled);
m_lidarType->setText(QString::fromStdString(config.lidarConfig.lidarType));
m_lidarHost->setText(QString::fromStdString(config.lidarConfig.hostAddress));
SetInt(m_lidarMsopPort, config.lidarConfig.msopPort);
SetInt(m_lidarDifopPort, config.lidarConfig.difopPort);
SetDouble(m_lidarMinDistance, config.lidarConfig.minDistance);
SetDouble(m_lidarMaxDistance, config.lidarConfig.maxDistance);
SetDouble(m_lidarStartAngle, config.lidarConfig.startAngle);
SetDouble(m_lidarEndAngle, config.lidarConfig.endAngle);
m_udpAddress->setText(QString::fromStdString(config.udpBroadcastConfig.address));
SetInt(m_udpPort, config.udpBroadcastConfig.port);
m_udpTargetId->setText(QString::fromStdString(config.udpBroadcastConfig.targetId));
m_udpParkId->setText(QString::fromStdString(config.udpBroadcastConfig.parkId));
m_udpEnabled->setChecked(config.udpBroadcastConfig.enabled);
}
bool DialogAlgoArg::SaveParams()
{
if (!m_presenter || !m_presenter->GetConfigManager()) {
return false;
}
SystemConfig systemConfig = m_presenter->GetConfigManager()->GetConfig();
ConfigResult& config = systemConfig.configResult;
VrAlgorithmParams& params = config.algorithmParams;
VrPlaneParkingParam& parking = params.planeParkingParam;
if (!GetDouble(m_parkingPointX, QStringLiteral("停机点X"), parking.parkingPointX)) return false;
if (!GetDouble(m_parkingPointY, QStringLiteral("停机点Y"), parking.parkingPointY)) return false;
if (!GetDouble(m_parkingPointZ, QStringLiteral("停机点Z"), parking.parkingPointZ)) return false;
if (!GetDouble(m_guideLinePointX, QStringLiteral("引导线远点X"), parking.guideLinePointX)) return false;
if (!GetDouble(m_guideLinePointY, QStringLiteral("引导线远点Y"), parking.guideLinePointY)) return false;
if (!GetDouble(m_guideLinePointZ, QStringLiteral("引导线远点Z"), parking.guideLinePointZ)) return false;
if (!GetDouble(m_guidingRange, QStringLiteral("飞机引导范围"), parking.guidingRange)) return false;
if (!GetDouble(m_parkingRange, QStringLiteral("引导线过滤范围"), parking.parkingRange)) return false;
if (!GetDouble(m_distFromNoseToWheel, QStringLiteral("机鼻到前轮距离"), parking.distFromNoseToWheel)) return false;
const double dx = parking.guideLinePointX - parking.parkingPointX;
const double dy = parking.guideLinePointY - parking.parkingPointY;
const double dz = parking.guideLinePointZ - parking.parkingPointZ;
if (parking.guidingRange <= 0.0 || parking.parkingRange <= 0.0 ||
std::sqrt(dx * dx + dy * dy + dz * dz) < 20000.0) {
StyledMessageBox::warning(this, QStringLiteral("参数错误"),
QStringLiteral("引导范围必须大于0且引导线远点距离停机点至少20米"));
return false;
}
VrPlaneGroundCalibrationParam& ground = params.groundCalibrationParam;
if (!GetMatrix(m_planeCalib, QStringLiteral("调平矩阵"), ground.planeCalib)) return false;
if (!GetDouble(m_planeHeight, QStringLiteral("地面高度"), ground.planeHeight)) return false;
if (!GetMatrix(m_invRMatrix, QStringLiteral("逆矩阵"), ground.invRMatrix)) return false;
VrPlaneTreeGrowParam& tree = params.treeGrowParam;
if (!GetDouble(m_yDeviationMax, QStringLiteral("Y方向最大偏差"), tree.yDeviationMax)) return false;
if (!GetDouble(m_zDeviationMax, QStringLiteral("Z方向最大偏差"), tree.zDeviationMax)) return false;
if (!GetInt(m_maxLineSkipNum, QStringLiteral("最大跳线数"), tree.maxLineSkipNum)) return false;
if (!GetDouble(m_maxSkipDistance, QStringLiteral("最大跳过距离"), tree.maxSkipDistance)) return false;
if (!GetDouble(m_minLTypeTreeLen, QStringLiteral("L型树最小长度"), tree.minLTypeTreeLen)) return false;
if (!GetDouble(m_minVTypeTreeLen, QStringLiteral("V型树最小长度"), tree.minVTypeTreeLen)) return false;
if (tree.yDeviationMax <= 0.0 || tree.zDeviationMax <= 0.0 ||
(tree.maxLineSkipNum == -1 && tree.maxSkipDistance < 0.0)) {
StyledMessageBox::warning(this, QStringLiteral("参数错误"), QStringLiteral("聚类生长参数组合无效"));
return false;
}
VrGuideDecisionParam& guide = params.guideDecisionParam;
if (!GetDouble(m_lateralTolerance, QStringLiteral("横向对中容差"), guide.lateralTolerance)) return false;
if (!GetDouble(m_angleTolerance, QStringLiteral("航向角容差"), guide.angleTolerance)) return false;
VrParkingProcessParam& process = params.processParam;
if (!GetDouble(m_dockingStartDistance, QStringLiteral("引导启动距离"), process.dockingStartDistance)) return false;
if (!GetDouble(m_captureStartDistance, QStringLiteral("目标捕获距离"), process.captureStartDistance)) return false;
if (!GetDouble(m_approachStartDistance, QStringLiteral("对中/方位引导距离"), process.approachStartDistance)) return false;
if (!GetDouble(m_slowDistance, QStringLiteral("减速触发距离"), process.slowDistance)) return false;
if (!GetDouble(m_stopDistanceTolerance, QStringLiteral("到位距离容差"), process.stopDistanceTolerance)) return false;
if (!GetDouble(m_overshootDistance, QStringLiteral("越过停止线距离"), process.overshootDistance)) return false;
if (!GetDouble(m_stoppedShortMinDistance, QStringLiteral("提前停止最小距离"), process.stoppedShortMinDistance)) return false;
if (!GetDouble(m_maxApproachSpeed, QStringLiteral("最大接近速度"), process.maxApproachSpeed)) return false;
if (!GetDouble(m_stoppedSpeedThreshold, QStringLiteral("静止速度阈值"), process.stoppedSpeedThreshold)) return false;
if (!GetDouble(m_speedFilterAlpha, QStringLiteral("速度滤波系数"), process.speedFilterAlpha)) return false;
if (!GetDouble(m_distanceChangeThreshold, QStringLiteral("距离变化阈值"), process.distanceChangeThreshold)) return false;
if (!GetDouble(m_lateralOffsetChangeThreshold, QStringLiteral("横向偏移变化阈值"), process.lateralOffsetChangeThreshold)) return false;
if (!GetInt(m_stopStableFrames, QStringLiteral("到位稳定帧数"), process.stopStableFrames)) return false;
if (!GetInt(m_stoppedShortStableFrames, QStringLiteral("提前停止稳定帧数"), process.stoppedShortStableFrames)) return false;
if (!GetInt(m_errorFrameThreshold, QStringLiteral("连续错误帧阈值"), process.errorFrameThreshold)) return false;
if (!GetInt(m_lostFrameThreshold, QStringLiteral("目标丢失帧阈值"), process.lostFrameThreshold)) return false;
if (!GetInt(m_completedHoldFrames, QStringLiteral("完成状态保持帧数"), process.completedHoldFrames)) return false;
if (process.dockingStartDistance <= process.captureStartDistance ||
process.captureStartDistance <= process.approachStartDistance ||
process.approachStartDistance <= process.slowDistance ||
process.slowDistance <= process.stopDistanceTolerance ||
process.overshootDistance < process.stopDistanceTolerance ||
process.stoppedShortMinDistance < process.stopDistanceTolerance ||
process.maxApproachSpeed <= process.stoppedSpeedThreshold) {
StyledMessageBox::warning(this, QStringLiteral("参数错误"),
QStringLiteral("流程距离应满足启动>捕获>对中/方位>减速>到位容差,越线和提前停止距离不得小于到位容差,最大接近速度必须大于静止速度阈值"));
return false;
}
VrModelRecognitionParam& model = params.modelRecognitionParam;
if (!GetDouble(m_modelVerifyDistance, QStringLiteral("机型验证距离"), model.modelVerifyDistance)) return false;
if (!GetDouble(m_modelRoiX, QStringLiteral("飞机检测区域 X"), model.roiX)) return false;
if (!GetDouble(m_modelRoiY, QStringLiteral("飞机检测区域 Y"), model.roiY)) return false;
if (!GetDouble(m_modelRoiWidth, QStringLiteral("飞机检测区域宽度"), model.roiWidth)) return false;
if (!GetDouble(m_modelRoiHeight, QStringLiteral("飞机检测区域高度"), model.roiHeight)) return false;
if (!GetDouble(m_confidenceThreshold, QStringLiteral("识别置信度阈值"), model.confidenceThreshold)) return false;
if (!GetInt(m_maxRecognitionAttempts, QStringLiteral("最大识别次数"), model.maxRecognitionAttempts)) return false;
if (model.roiX + model.roiWidth > 1.0 ||
model.roiY + model.roiHeight > 1.0) {
StyledMessageBox::warning(this,
QStringLiteral("参数错误"),
QStringLiteral("飞机检测区域必须完整位于归一化图像范围 0~1 内"));
return false;
}
VrPersonDetectionParam& person = params.personDetectionParam;
person.enabled = m_personDetectionEnabled->isChecked();
if (!GetDouble(m_personRoiX, QStringLiteral("轮挡区域 X"), person.roiX)) return false;
if (!GetDouble(m_personRoiY, QStringLiteral("轮挡区域 Y"), person.roiY)) return false;
if (!GetDouble(m_personRoiWidth, QStringLiteral("轮挡区域宽度"), person.roiWidth)) return false;
if (!GetDouble(m_personRoiHeight, QStringLiteral("轮挡区域高度"), person.roiHeight)) return false;
if (!GetDouble(m_personConfidenceThreshold, QStringLiteral("人员置信度阈值"), person.confidenceThreshold)) return false;
if (!GetInt(m_personStableFrames, QStringLiteral("连续有效检测次数"), person.stableFrames)) return false;
if (!GetInt(m_personDetectionIntervalMs, QStringLiteral("人员检测周期"), person.detectionIntervalMs)) return false;
if (person.roiX + person.roiWidth > 1.0 ||
person.roiY + person.roiHeight > 1.0) {
StyledMessageBox::warning(this,
QStringLiteral("参数错误"),
QStringLiteral("轮挡区域必须完整位于归一化图像范围 0~1 内"));
return false;
}
config.mvsCamera.serialNumber = m_mvsSerialNumber->text().trimmed().toStdString();
if (!GetInt(m_mvsDeviceIndex, QStringLiteral("相机设备序号"), config.mvsCamera.deviceIndex)) return false;
config.mvsCamera.enabled = m_mvsEnabled->isChecked();
config.lidarConfig.lidarType = m_lidarType->text().trimmed().toStdString();
config.lidarConfig.hostAddress = m_lidarHost->text().trimmed().toStdString();
int intValue = 0;
if (!GetInt(m_lidarMsopPort, QStringLiteral("雷达数据端口"), intValue)) return false;
config.lidarConfig.msopPort = static_cast<unsigned short>(intValue);
if (!GetInt(m_lidarDifopPort, QStringLiteral("雷达设备端口"), intValue)) return false;
config.lidarConfig.difopPort = static_cast<unsigned short>(intValue);
if (!GetFloat(m_lidarMinDistance, QStringLiteral("雷达最小距离"), config.lidarConfig.minDistance)) return false;
if (!GetFloat(m_lidarMaxDistance, QStringLiteral("雷达最大距离"), config.lidarConfig.maxDistance)) return false;
if (!GetFloat(m_lidarStartAngle, QStringLiteral("雷达起始角度"), config.lidarConfig.startAngle)) return false;
if (!GetFloat(m_lidarEndAngle, QStringLiteral("雷达结束角度"), config.lidarConfig.endAngle)) return false;
config.udpBroadcastConfig.address = m_udpAddress->text().trimmed().toStdString();
if (!GetInt(m_udpPort, QStringLiteral("组播端口"), config.udpBroadcastConfig.port)) return false;
config.udpBroadcastConfig.targetId = m_udpTargetId->text().trimmed().toStdString();
config.udpBroadcastConfig.parkId = m_udpParkId->text().trimmed().toStdString();
config.udpBroadcastConfig.enabled = m_udpEnabled->isChecked();
config.Normalize();
if (!m_presenter->GetConfigManager()->UpdateFullConfig(systemConfig)) {
StyledMessageBox::warning(this, QStringLiteral("失败"), QStringLiteral("更新配置缓存失败"));
return false;
}
const QString configPath = PathManager::GetInstance().GetConfigFilePath();
if (!m_presenter->GetConfigManager()->SaveConfigToFile(configPath.toStdString())) {
StyledMessageBox::warning(this, QStringLiteral("失败"), QStringLiteral("保存配置文件失败"));
return false;
}
m_presenter->OnConfigChanged(config);
return true;
}
void DialogAlgoArg::ResetParams()
{
ConfigResult config;
config.Normalize();
const VrAlgorithmParams& params = config.algorithmParams;
const VrPlaneParkingParam& parking = params.planeParkingParam;
SetDouble(m_parkingPointX, parking.parkingPointX);
SetDouble(m_parkingPointY, parking.parkingPointY);
SetDouble(m_parkingPointZ, parking.parkingPointZ);
SetDouble(m_guideLinePointX, parking.guideLinePointX);
SetDouble(m_guideLinePointY, parking.guideLinePointY);
SetDouble(m_guideLinePointZ, parking.guideLinePointZ);
SetDouble(m_guidingRange, parking.guidingRange);
SetDouble(m_parkingRange, parking.parkingRange);
SetDouble(m_distFromNoseToWheel, parking.distFromNoseToWheel);
const VrPlaneGroundCalibrationParam& ground = params.groundCalibrationParam;
SetMatrix(m_planeCalib, ground.planeCalib);
SetDouble(m_planeHeight, ground.planeHeight);
SetMatrix(m_invRMatrix, ground.invRMatrix);
const VrPlaneTreeGrowParam& tree = params.treeGrowParam;
SetDouble(m_yDeviationMax, tree.yDeviationMax);
SetDouble(m_zDeviationMax, tree.zDeviationMax);
SetInt(m_maxLineSkipNum, tree.maxLineSkipNum);
SetDouble(m_maxSkipDistance, tree.maxSkipDistance);
SetDouble(m_minLTypeTreeLen, tree.minLTypeTreeLen);
SetDouble(m_minVTypeTreeLen, tree.minVTypeTreeLen);
const VrGuideDecisionParam& guide = params.guideDecisionParam;
SetDouble(m_lateralTolerance, guide.lateralTolerance);
SetDouble(m_angleTolerance, guide.angleTolerance);
const VrParkingProcessParam& process = params.processParam;
SetDouble(m_dockingStartDistance, process.dockingStartDistance);
SetDouble(m_captureStartDistance, process.captureStartDistance);
SetDouble(m_approachStartDistance, process.approachStartDistance);
SetDouble(m_slowDistance, process.slowDistance);
SetDouble(m_stopDistanceTolerance, process.stopDistanceTolerance);
SetDouble(m_overshootDistance, process.overshootDistance);
SetDouble(m_stoppedShortMinDistance, process.stoppedShortMinDistance);
SetDouble(m_maxApproachSpeed, process.maxApproachSpeed);
SetDouble(m_stoppedSpeedThreshold, process.stoppedSpeedThreshold);
SetDouble(m_speedFilterAlpha, process.speedFilterAlpha);
SetDouble(m_distanceChangeThreshold, process.distanceChangeThreshold);
SetDouble(m_lateralOffsetChangeThreshold, process.lateralOffsetChangeThreshold);
SetInt(m_stopStableFrames, process.stopStableFrames);
SetInt(m_stoppedShortStableFrames, process.stoppedShortStableFrames);
SetInt(m_errorFrameThreshold, process.errorFrameThreshold);
SetInt(m_lostFrameThreshold, process.lostFrameThreshold);
SetInt(m_completedHoldFrames, process.completedHoldFrames);
const VrModelRecognitionParam& model = params.modelRecognitionParam;
SetDouble(m_modelVerifyDistance, model.modelVerifyDistance);
SetDouble(m_modelRoiX, model.roiX);
SetDouble(m_modelRoiY, model.roiY);
SetDouble(m_modelRoiWidth, model.roiWidth);
SetDouble(m_modelRoiHeight, model.roiHeight);
SetDouble(m_confidenceThreshold, model.confidenceThreshold);
SetInt(m_maxRecognitionAttempts, model.maxRecognitionAttempts);
const VrPersonDetectionParam& person = params.personDetectionParam;
m_personDetectionEnabled->setChecked(person.enabled);
SetDouble(m_personRoiX, person.roiX);
SetDouble(m_personRoiY, person.roiY);
SetDouble(m_personRoiWidth, person.roiWidth);
SetDouble(m_personRoiHeight, person.roiHeight);
SetDouble(m_personConfidenceThreshold, person.confidenceThreshold);
SetInt(m_personStableFrames, person.stableFrames);
SetInt(m_personDetectionIntervalMs, person.detectionIntervalMs);
m_mvsSerialNumber->setText(QString::fromStdString(config.mvsCamera.serialNumber));
SetInt(m_mvsDeviceIndex, config.mvsCamera.deviceIndex);
m_mvsEnabled->setChecked(config.mvsCamera.enabled);
m_lidarType->setText(QString::fromStdString(config.lidarConfig.lidarType));
m_lidarHost->setText(QString::fromStdString(config.lidarConfig.hostAddress));
SetInt(m_lidarMsopPort, config.lidarConfig.msopPort);
SetInt(m_lidarDifopPort, config.lidarConfig.difopPort);
SetDouble(m_lidarMinDistance, config.lidarConfig.minDistance);
SetDouble(m_lidarMaxDistance, config.lidarConfig.maxDistance);
SetDouble(m_lidarStartAngle, config.lidarConfig.startAngle);
SetDouble(m_lidarEndAngle, config.lidarConfig.endAngle);
m_udpAddress->setText(QString::fromStdString(config.udpBroadcastConfig.address));
SetInt(m_udpPort, config.udpBroadcastConfig.port);
m_udpTargetId->setText(QString::fromStdString(config.udpBroadcastConfig.targetId));
m_udpParkId->setText(QString::fromStdString(config.udpBroadcastConfig.parkId));
m_udpEnabled->setChecked(config.udpBroadcastConfig.enabled);
}
void DialogAlgoArg::SetDouble(QLineEdit* edit, double value)
{
if (edit) edit->setText(QString::number(value, 'g', 12));
}
void DialogAlgoArg::SetInt(QLineEdit* edit, int value)
{
if (edit) edit->setText(QString::number(value));
}
bool DialogAlgoArg::GetDouble(QLineEdit* edit, const QString& label, double& value)
{
bool ok = false;
value = edit ? edit->text().trimmed().toDouble(&ok) : 0.0;
if (!edit || !edit->hasAcceptableInput() || !ok || !std::isfinite(value)) {
StyledMessageBox::warning(this, QStringLiteral("参数错误"), QStringLiteral("%1无效").arg(label));
if (edit) edit->setFocus();
return false;
}
return true;
}
bool DialogAlgoArg::GetFloat(QLineEdit* edit, const QString& label, float& value)
{
double doubleValue = 0.0;
if (!GetDouble(edit, label, doubleValue)) return false;
value = static_cast<float>(doubleValue);
return true;
}
bool DialogAlgoArg::GetInt(QLineEdit* edit, const QString& label, int& value)
{
bool ok = false;
value = edit ? edit->text().trimmed().toInt(&ok) : 0;
if (!edit || !edit->hasAcceptableInput() || !ok) {
StyledMessageBox::warning(this, QStringLiteral("参数错误"), QStringLiteral("%1无效").arg(label));
if (edit) edit->setFocus();
return false;
}
return true;
}
void DialogAlgoArg::SetMatrix(QLineEdit* const edits[9], const double values[9])
{
for (int i = 0; i < 9; ++i) SetDouble(edits[i], values[i]);
}
bool DialogAlgoArg::GetMatrix(QLineEdit* const edits[9], const QString& label, double values[9])
{
for (int i = 0; i < 9; ++i) {
if (!GetDouble(edits[i], QStringLiteral("%1 R%2%3").arg(label).arg(i / 3).arg(i % 3), values[i])) {
return false;
}
}
return true;
}
void DialogAlgoArg::on_btnOK_clicked()
{
if (SaveParams()) accept();
}
void DialogAlgoArg::on_btnCancel_clicked()
{
reject();
}
void DialogAlgoArg::on_btnApply_clicked()
{
if (SaveParams()) {
StyledMessageBox::information(this, QStringLiteral("提示"), QStringLiteral("参数已应用"));
}
}
void DialogAlgoArg::on_btnReset_clicked()
{
ResetParams();
}