parent
c064453fdb
commit
6a0e91b955
Binary file not shown.
@ -0,0 +1,545 @@
|
|||||||
|
/**
|
||||||
|
* @file DroneControlDialog.cpp
|
||||||
|
* @brief 无人机控制对话框实现
|
||||||
|
* @author Qt UI Optimizer
|
||||||
|
* @date 2024-07-04
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ui/dialogs/DroneControlDialog.h"
|
||||||
|
#include "styles/ModernStyleManager.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDesktopWidget>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
DroneControlDialog::DroneControlDialog(QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, m_mainLayout(nullptr)
|
||||||
|
, m_contentLayout(nullptr)
|
||||||
|
, m_isMappingActive(false)
|
||||||
|
, m_isNavigationActive(false)
|
||||||
|
, m_isPhotoTransmissionActive(false)
|
||||||
|
, m_isPersonRecognitionActive(false)
|
||||||
|
, m_isFlying(false)
|
||||||
|
, m_statusUpdateTimer(new QTimer(this))
|
||||||
|
{
|
||||||
|
setupUI();
|
||||||
|
applyStyles();
|
||||||
|
connectSignals();
|
||||||
|
|
||||||
|
// 启动状态更新定时器
|
||||||
|
m_statusUpdateTimer->start(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
DroneControlDialog::~DroneControlDialog()
|
||||||
|
{
|
||||||
|
if (m_statusUpdateTimer) {
|
||||||
|
m_statusUpdateTimer->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::setupUI()
|
||||||
|
{
|
||||||
|
setWindowTitle("🚁 无人机控制中心");
|
||||||
|
setModal(false);
|
||||||
|
setMinimumSize(900, 700);
|
||||||
|
resize(1000, 750);
|
||||||
|
|
||||||
|
// 窗口居中显示
|
||||||
|
QRect screenGeometry = QApplication::desktop()->screenGeometry();
|
||||||
|
int x = (screenGeometry.width() - this->width()) / 2;
|
||||||
|
int y = (screenGeometry.height() - this->height()) / 2;
|
||||||
|
move(x, y);
|
||||||
|
|
||||||
|
m_mainLayout = new QVBoxLayout(this);
|
||||||
|
m_mainLayout->setSpacing(20);
|
||||||
|
m_mainLayout->setContentsMargins(20, 20, 20, 20);
|
||||||
|
|
||||||
|
// 标题
|
||||||
|
QLabel *titleLabel = new QLabel("🚁 无人机控制中心");
|
||||||
|
titleLabel->setObjectName("DialogTitle");
|
||||||
|
titleLabel->setAlignment(Qt::AlignCenter);
|
||||||
|
titleLabel->setStyleSheet(
|
||||||
|
"font-size: 24px; "
|
||||||
|
"font-weight: bold; "
|
||||||
|
"color: #0078d4; "
|
||||||
|
"padding: 10px; "
|
||||||
|
"border-bottom: 2px solid #0078d4; "
|
||||||
|
"margin-bottom: 10px;"
|
||||||
|
);
|
||||||
|
m_mainLayout->addWidget(titleLabel);
|
||||||
|
|
||||||
|
// 主内容区域
|
||||||
|
m_contentLayout = new QHBoxLayout();
|
||||||
|
m_contentLayout->setSpacing(20);
|
||||||
|
|
||||||
|
setupFlightControlModule();
|
||||||
|
setupMissionControlModule();
|
||||||
|
setupStatusMonitorModule();
|
||||||
|
|
||||||
|
m_mainLayout->addLayout(m_contentLayout);
|
||||||
|
|
||||||
|
// 底部按钮
|
||||||
|
QHBoxLayout *buttonLayout = new QHBoxLayout();
|
||||||
|
buttonLayout->addStretch();
|
||||||
|
|
||||||
|
QPushButton *closeBtn = new QPushButton("关闭");
|
||||||
|
closeBtn->setObjectName("CloseBtn");
|
||||||
|
closeBtn->setMinimumSize(100, 40);
|
||||||
|
connect(closeBtn, &QPushButton::clicked, this, &QDialog::close);
|
||||||
|
|
||||||
|
buttonLayout->addWidget(closeBtn);
|
||||||
|
m_mainLayout->addLayout(buttonLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::setupFlightControlModule()
|
||||||
|
{
|
||||||
|
m_flightControlGroup = new QGroupBox("✈️ 飞行控制");
|
||||||
|
m_flightControlGroup->setObjectName("ControlGroup");
|
||||||
|
m_flightControlGroup->setMinimumWidth(280);
|
||||||
|
|
||||||
|
QVBoxLayout *flightLayout = new QVBoxLayout(m_flightControlGroup);
|
||||||
|
flightLayout->setSpacing(15);
|
||||||
|
|
||||||
|
// 基础飞行控制按钮
|
||||||
|
QGridLayout *basicControlLayout = new QGridLayout();
|
||||||
|
basicControlLayout->setSpacing(10);
|
||||||
|
|
||||||
|
m_takeoffBtn = new QPushButton("🚀 起飞");
|
||||||
|
m_takeoffBtn->setObjectName("PrimaryBtn");
|
||||||
|
m_takeoffBtn->setMinimumHeight(50);
|
||||||
|
|
||||||
|
m_landBtn = new QPushButton("🛬 降落");
|
||||||
|
m_landBtn->setObjectName("WarningBtn");
|
||||||
|
m_landBtn->setMinimumHeight(50);
|
||||||
|
m_landBtn->setEnabled(false);
|
||||||
|
|
||||||
|
m_hoverBtn = new QPushButton("⏸️ 悬停");
|
||||||
|
m_hoverBtn->setObjectName("InfoBtn");
|
||||||
|
m_hoverBtn->setMinimumHeight(50);
|
||||||
|
m_hoverBtn->setEnabled(false);
|
||||||
|
|
||||||
|
m_returnHomeBtn = new QPushButton("🏠 返航");
|
||||||
|
m_returnHomeBtn->setObjectName("SuccessBtn");
|
||||||
|
m_returnHomeBtn->setMinimumHeight(50);
|
||||||
|
m_returnHomeBtn->setEnabled(false);
|
||||||
|
|
||||||
|
basicControlLayout->addWidget(m_takeoffBtn, 0, 0);
|
||||||
|
basicControlLayout->addWidget(m_landBtn, 0, 1);
|
||||||
|
basicControlLayout->addWidget(m_hoverBtn, 1, 0);
|
||||||
|
basicControlLayout->addWidget(m_returnHomeBtn, 1, 1);
|
||||||
|
|
||||||
|
flightLayout->addLayout(basicControlLayout);
|
||||||
|
|
||||||
|
// 高度和速度控制
|
||||||
|
QLabel *altitudeLabel = new QLabel("飞行高度 (m):");
|
||||||
|
m_altitudeSlider = new QSlider(Qt::Horizontal);
|
||||||
|
m_altitudeSlider->setRange(1, 100);
|
||||||
|
m_altitudeSlider->setValue(10);
|
||||||
|
m_altitudeSlider->setEnabled(false);
|
||||||
|
|
||||||
|
QLabel *speedLabel = new QLabel("飞行速度 (m/s):");
|
||||||
|
m_speedSlider = new QSlider(Qt::Horizontal);
|
||||||
|
m_speedSlider->setRange(1, 20);
|
||||||
|
m_speedSlider->setValue(5);
|
||||||
|
m_speedSlider->setEnabled(false);
|
||||||
|
|
||||||
|
flightLayout->addWidget(altitudeLabel);
|
||||||
|
flightLayout->addWidget(m_altitudeSlider);
|
||||||
|
flightLayout->addWidget(speedLabel);
|
||||||
|
flightLayout->addWidget(m_speedSlider);
|
||||||
|
|
||||||
|
// 紧急停止按钮
|
||||||
|
m_emergencyStopBtn = new QPushButton("🚨 紧急停止");
|
||||||
|
m_emergencyStopBtn->setObjectName("DangerBtn");
|
||||||
|
m_emergencyStopBtn->setMinimumHeight(60);
|
||||||
|
m_emergencyStopBtn->setStyleSheet(
|
||||||
|
"QPushButton {"
|
||||||
|
" background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
|
||||||
|
" stop:0 #e74c3c, stop:1 #c0392b);"
|
||||||
|
" color: white;"
|
||||||
|
" font-size: 16px;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
" border: 2px solid #e74c3c;"
|
||||||
|
" border-radius: 8px;"
|
||||||
|
"}"
|
||||||
|
"QPushButton:hover {"
|
||||||
|
" background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
|
||||||
|
" stop:0 #c0392b, stop:1 #a93226);"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
flightLayout->addWidget(m_emergencyStopBtn);
|
||||||
|
flightLayout->addStretch();
|
||||||
|
|
||||||
|
m_contentLayout->addWidget(m_flightControlGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::setupMissionControlModule()
|
||||||
|
{
|
||||||
|
m_missionControlGroup = new QGroupBox("🎯 任务控制");
|
||||||
|
m_missionControlGroup->setObjectName("ControlGroup");
|
||||||
|
m_missionControlGroup->setMinimumWidth(280);
|
||||||
|
|
||||||
|
QVBoxLayout *missionLayout = new QVBoxLayout(m_missionControlGroup);
|
||||||
|
missionLayout->setSpacing(15);
|
||||||
|
|
||||||
|
// 任务模式选择
|
||||||
|
QLabel *modeLabel = new QLabel("任务模式:");
|
||||||
|
m_missionModeCombo = new QComboBox();
|
||||||
|
m_missionModeCombo->addItems({"手动控制", "自主巡航", "目标跟踪", "区域扫描"});
|
||||||
|
m_missionModeCombo->setMinimumHeight(35);
|
||||||
|
|
||||||
|
missionLayout->addWidget(modeLabel);
|
||||||
|
missionLayout->addWidget(m_missionModeCombo);
|
||||||
|
|
||||||
|
// 功能控制按钮
|
||||||
|
m_mappingBtn = new QPushButton("🗺️ 开始建图");
|
||||||
|
m_mappingBtn->setObjectName("FunctionBtn");
|
||||||
|
m_mappingBtn->setMinimumHeight(50);
|
||||||
|
m_mappingBtn->setCheckable(true);
|
||||||
|
|
||||||
|
m_navigationBtn = new QPushButton("🧭 导航避障");
|
||||||
|
m_navigationBtn->setObjectName("FunctionBtn");
|
||||||
|
m_navigationBtn->setMinimumHeight(50);
|
||||||
|
m_navigationBtn->setCheckable(true);
|
||||||
|
|
||||||
|
m_photoBtn = new QPushButton("📸 照片传输");
|
||||||
|
m_photoBtn->setObjectName("FunctionBtn");
|
||||||
|
m_photoBtn->setMinimumHeight(50);
|
||||||
|
m_photoBtn->setCheckable(true);
|
||||||
|
|
||||||
|
m_recognitionBtn = new QPushButton("👁️ 人物识别");
|
||||||
|
m_recognitionBtn->setObjectName("FunctionBtn");
|
||||||
|
m_recognitionBtn->setMinimumHeight(50);
|
||||||
|
m_recognitionBtn->setCheckable(true);
|
||||||
|
|
||||||
|
missionLayout->addWidget(m_mappingBtn);
|
||||||
|
missionLayout->addWidget(m_navigationBtn);
|
||||||
|
missionLayout->addWidget(m_photoBtn);
|
||||||
|
missionLayout->addWidget(m_recognitionBtn);
|
||||||
|
missionLayout->addStretch();
|
||||||
|
|
||||||
|
m_contentLayout->addWidget(m_missionControlGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::setupStatusMonitorModule()
|
||||||
|
{
|
||||||
|
m_statusGroup = new QGroupBox("📊 状态监控");
|
||||||
|
m_statusGroup->setObjectName("ControlGroup");
|
||||||
|
m_statusGroup->setMinimumWidth(320);
|
||||||
|
|
||||||
|
QVBoxLayout *statusLayout = new QVBoxLayout(m_statusGroup);
|
||||||
|
statusLayout->setSpacing(15);
|
||||||
|
|
||||||
|
// 电池状态
|
||||||
|
QHBoxLayout *batteryLayout = new QHBoxLayout();
|
||||||
|
m_batteryLabel = new QLabel("电池电量:");
|
||||||
|
m_batteryProgress = new QProgressBar();
|
||||||
|
m_batteryProgress->setRange(0, 100);
|
||||||
|
m_batteryProgress->setValue(85);
|
||||||
|
m_batteryProgress->setTextVisible(true);
|
||||||
|
m_batteryProgress->setFormat("%p%");
|
||||||
|
|
||||||
|
batteryLayout->addWidget(m_batteryLabel);
|
||||||
|
batteryLayout->addWidget(m_batteryProgress);
|
||||||
|
statusLayout->addLayout(batteryLayout);
|
||||||
|
|
||||||
|
// 飞行参数
|
||||||
|
QGridLayout *paramLayout = new QGridLayout();
|
||||||
|
paramLayout->addWidget(new QLabel("飞行高度:"), 0, 0);
|
||||||
|
m_altitudeLabel = new QLabel("0.0 m");
|
||||||
|
m_altitudeLabel->setStyleSheet("font-weight: bold; color: #0078d4;");
|
||||||
|
paramLayout->addWidget(m_altitudeLabel, 0, 1);
|
||||||
|
|
||||||
|
paramLayout->addWidget(new QLabel("飞行速度:"), 1, 0);
|
||||||
|
m_speedLabel = new QLabel("0.0 m/s");
|
||||||
|
m_speedLabel->setStyleSheet("font-weight: bold; color: #0078d4;");
|
||||||
|
paramLayout->addWidget(m_speedLabel, 1, 1);
|
||||||
|
|
||||||
|
paramLayout->addWidget(new QLabel("GPS状态:"), 2, 0);
|
||||||
|
m_gpsLabel = new QLabel("🔴 未连接");
|
||||||
|
paramLayout->addWidget(m_gpsLabel, 2, 1);
|
||||||
|
|
||||||
|
paramLayout->addWidget(new QLabel("连接状态:"), 3, 0);
|
||||||
|
m_connectionLabel = new QLabel("🟢 已连接");
|
||||||
|
paramLayout->addWidget(m_connectionLabel, 3, 1);
|
||||||
|
|
||||||
|
statusLayout->addLayout(paramLayout);
|
||||||
|
|
||||||
|
// 日志显示
|
||||||
|
QLabel *logLabel = new QLabel("系统日志:");
|
||||||
|
m_logTextEdit = new QTextEdit();
|
||||||
|
m_logTextEdit->setMaximumHeight(200);
|
||||||
|
m_logTextEdit->setReadOnly(true);
|
||||||
|
m_logTextEdit->append(QString("[%1] 无人机控制系统启动").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
m_logTextEdit->append(QString("[%1] 等待连接无人机...").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
|
||||||
|
statusLayout->addWidget(logLabel);
|
||||||
|
statusLayout->addWidget(m_logTextEdit);
|
||||||
|
|
||||||
|
m_contentLayout->addWidget(m_statusGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::applyStyles()
|
||||||
|
{
|
||||||
|
// 应用现代样式管理器
|
||||||
|
ModernStyleManager* styleManager = ModernStyleManager::getInstance();
|
||||||
|
|
||||||
|
// 应用按钮样式
|
||||||
|
styleManager->applyButtonStyle(m_takeoffBtn, ModernStyleManager::ButtonStyle::Primary);
|
||||||
|
styleManager->applyButtonStyle(m_landBtn, ModernStyleManager::ButtonStyle::Warning);
|
||||||
|
styleManager->applyButtonStyle(m_hoverBtn, ModernStyleManager::ButtonStyle::Info);
|
||||||
|
styleManager->applyButtonStyle(m_returnHomeBtn, ModernStyleManager::ButtonStyle::Success);
|
||||||
|
styleManager->applyButtonStyle(m_emergencyStopBtn, ModernStyleManager::ButtonStyle::Danger);
|
||||||
|
|
||||||
|
// 设置对话框样式
|
||||||
|
setStyleSheet(
|
||||||
|
"QDialog {"
|
||||||
|
" background-color: #f8f9fa;"
|
||||||
|
" border: 1px solid #dee2e6;"
|
||||||
|
"}"
|
||||||
|
"QGroupBox {"
|
||||||
|
" font-size: 16px;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
" color: #495057;"
|
||||||
|
" border: 2px solid #dee2e6;"
|
||||||
|
" border-radius: 8px;"
|
||||||
|
" margin-top: 10px;"
|
||||||
|
" padding-top: 10px;"
|
||||||
|
"}"
|
||||||
|
"QGroupBox::title {"
|
||||||
|
" subcontrol-origin: margin;"
|
||||||
|
" left: 10px;"
|
||||||
|
" padding: 0 8px 0 8px;"
|
||||||
|
" background-color: #f8f9fa;"
|
||||||
|
"}"
|
||||||
|
"QSlider::groove:horizontal {"
|
||||||
|
" border: 1px solid #bbb;"
|
||||||
|
" background: white;"
|
||||||
|
" height: 10px;"
|
||||||
|
" border-radius: 4px;"
|
||||||
|
"}"
|
||||||
|
"QSlider::handle:horizontal {"
|
||||||
|
" background: #0078d4;"
|
||||||
|
" border: 1px solid #5c5c5c;"
|
||||||
|
" width: 18px;"
|
||||||
|
" margin: -2px 0;"
|
||||||
|
" border-radius: 3px;"
|
||||||
|
"}"
|
||||||
|
"QProgressBar {"
|
||||||
|
" border: 2px solid #dee2e6;"
|
||||||
|
" border-radius: 5px;"
|
||||||
|
" text-align: center;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
"}"
|
||||||
|
"QProgressBar::chunk {"
|
||||||
|
" background-color: #28a745;"
|
||||||
|
" border-radius: 3px;"
|
||||||
|
"}"
|
||||||
|
"QTextEdit {"
|
||||||
|
" border: 1px solid #dee2e6;"
|
||||||
|
" border-radius: 4px;"
|
||||||
|
" background-color: white;"
|
||||||
|
" font-family: 'Consolas', monospace;"
|
||||||
|
" font-size: 12px;"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::connectSignals()
|
||||||
|
{
|
||||||
|
// 飞行控制信号连接
|
||||||
|
connect(m_takeoffBtn, &QPushButton::clicked, this, &DroneControlDialog::onTakeoffClicked);
|
||||||
|
connect(m_landBtn, &QPushButton::clicked, this, &DroneControlDialog::onLandClicked);
|
||||||
|
connect(m_hoverBtn, &QPushButton::clicked, this, &DroneControlDialog::onHoverClicked);
|
||||||
|
connect(m_returnHomeBtn, &QPushButton::clicked, this, &DroneControlDialog::onReturnHomeClicked);
|
||||||
|
connect(m_emergencyStopBtn, &QPushButton::clicked, this, &DroneControlDialog::onEmergencyStop);
|
||||||
|
|
||||||
|
// 任务控制信号连接
|
||||||
|
connect(m_mappingBtn, &QPushButton::clicked, this, &DroneControlDialog::onMappingToggle);
|
||||||
|
connect(m_navigationBtn, &QPushButton::clicked, this, &DroneControlDialog::onNavigationToggle);
|
||||||
|
connect(m_photoBtn, &QPushButton::clicked, this, &DroneControlDialog::onPhotoTransmissionToggle);
|
||||||
|
connect(m_recognitionBtn, &QPushButton::clicked, this, &DroneControlDialog::onPersonRecognitionToggle);
|
||||||
|
|
||||||
|
// 状态更新定时器
|
||||||
|
connect(m_statusUpdateTimer, &QTimer::timeout, [this]() {
|
||||||
|
// 模拟状态更新
|
||||||
|
static int counter = 0;
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
if (m_isFlying) {
|
||||||
|
// 模拟电池消耗
|
||||||
|
int currentBattery = m_batteryProgress->value();
|
||||||
|
if (currentBattery > 0 && counter % 10 == 0) {
|
||||||
|
m_batteryProgress->setValue(currentBattery - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新电池颜色
|
||||||
|
if (currentBattery > 50) {
|
||||||
|
m_batteryProgress->setStyleSheet("QProgressBar::chunk { background-color: #28a745; }");
|
||||||
|
} else if (currentBattery > 20) {
|
||||||
|
m_batteryProgress->setStyleSheet("QProgressBar::chunk { background-color: #ffc107; }");
|
||||||
|
} else {
|
||||||
|
m_batteryProgress->setStyleSheet("QProgressBar::chunk { background-color: #dc3545; }");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 槽函数实现
|
||||||
|
void DroneControlDialog::onTakeoffClicked()
|
||||||
|
{
|
||||||
|
m_isFlying = true;
|
||||||
|
m_takeoffBtn->setEnabled(false);
|
||||||
|
m_landBtn->setEnabled(true);
|
||||||
|
m_hoverBtn->setEnabled(true);
|
||||||
|
m_returnHomeBtn->setEnabled(true);
|
||||||
|
m_altitudeSlider->setEnabled(true);
|
||||||
|
m_speedSlider->setEnabled(true);
|
||||||
|
|
||||||
|
m_logTextEdit->append(QString("[%1] 无人机起飞中...").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
m_gpsLabel->setText("🟢 GPS已锁定");
|
||||||
|
|
||||||
|
// 模拟起飞过程
|
||||||
|
QTimer::singleShot(2000, [this]() {
|
||||||
|
m_logTextEdit->append(QString("[%1] 无人机起飞成功,当前高度: %2m").arg(
|
||||||
|
QDateTime::currentDateTime().toString("hh:mm:ss")).arg(m_altitudeSlider->value()));
|
||||||
|
updateDroneStatus(m_batteryProgress->value(), m_altitudeSlider->value(), m_speedSlider->value());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::onLandClicked()
|
||||||
|
{
|
||||||
|
m_isFlying = false;
|
||||||
|
m_takeoffBtn->setEnabled(true);
|
||||||
|
m_landBtn->setEnabled(false);
|
||||||
|
m_hoverBtn->setEnabled(false);
|
||||||
|
m_returnHomeBtn->setEnabled(false);
|
||||||
|
m_altitudeSlider->setEnabled(false);
|
||||||
|
m_speedSlider->setEnabled(false);
|
||||||
|
|
||||||
|
// 停止所有任务
|
||||||
|
if (m_isMappingActive) onMappingToggle();
|
||||||
|
if (m_isNavigationActive) onNavigationToggle();
|
||||||
|
if (m_isPhotoTransmissionActive) onPhotoTransmissionToggle();
|
||||||
|
if (m_isPersonRecognitionActive) onPersonRecognitionToggle();
|
||||||
|
|
||||||
|
m_logTextEdit->append(QString("[%1] 无人机降落中...").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
|
||||||
|
QTimer::singleShot(3000, [this]() {
|
||||||
|
m_logTextEdit->append(QString("[%1] 无人机安全降落").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
updateDroneStatus(m_batteryProgress->value(), 0.0, 0.0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::onHoverClicked()
|
||||||
|
{
|
||||||
|
m_logTextEdit->append(QString("[%1] 无人机进入悬停模式").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
updateDroneStatus(m_batteryProgress->value(), m_altitudeSlider->value(), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::onReturnHomeClicked()
|
||||||
|
{
|
||||||
|
m_logTextEdit->append(QString("[%1] 无人机开始返航").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
|
||||||
|
// 停止所有任务
|
||||||
|
if (m_isMappingActive) onMappingToggle();
|
||||||
|
if (m_isNavigationActive) onNavigationToggle();
|
||||||
|
if (m_isPhotoTransmissionActive) onPhotoTransmissionToggle();
|
||||||
|
if (m_isPersonRecognitionActive) onPersonRecognitionToggle();
|
||||||
|
|
||||||
|
QTimer::singleShot(5000, [this]() {
|
||||||
|
m_logTextEdit->append(QString("[%1] 无人机返航完成").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
onLandClicked();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::onEmergencyStop()
|
||||||
|
{
|
||||||
|
QMessageBox::StandardButton reply = QMessageBox::warning(this, "紧急停止",
|
||||||
|
"确定要执行紧急停止吗?这将立即停止所有操作!",
|
||||||
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
|
if (reply == QMessageBox::Yes) {
|
||||||
|
m_logTextEdit->append(QString("[%1] 🚨 执行紧急停止!").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
onLandClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::onMappingToggle()
|
||||||
|
{
|
||||||
|
m_isMappingActive = !m_isMappingActive;
|
||||||
|
|
||||||
|
if (m_isMappingActive) {
|
||||||
|
m_mappingBtn->setText("🗺️ 停止建图");
|
||||||
|
m_mappingBtn->setStyleSheet("background-color: #dc3545; color: white;");
|
||||||
|
m_logTextEdit->append(QString("[%1] 开始自主建图").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit startMapping();
|
||||||
|
} else {
|
||||||
|
m_mappingBtn->setText("🗺️ 开始建图");
|
||||||
|
m_mappingBtn->setStyleSheet("");
|
||||||
|
m_logTextEdit->append(QString("[%1] 停止自主建图").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit stopMapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::onNavigationToggle()
|
||||||
|
{
|
||||||
|
m_isNavigationActive = !m_isNavigationActive;
|
||||||
|
|
||||||
|
if (m_isNavigationActive) {
|
||||||
|
m_navigationBtn->setText("🧭 停止导航");
|
||||||
|
m_navigationBtn->setStyleSheet("background-color: #dc3545; color: white;");
|
||||||
|
m_logTextEdit->append(QString("[%1] 开始导航避障").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit startNavigation();
|
||||||
|
} else {
|
||||||
|
m_navigationBtn->setText("🧭 导航避障");
|
||||||
|
m_navigationBtn->setStyleSheet("");
|
||||||
|
m_logTextEdit->append(QString("[%1] 停止导航避障").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit stopNavigation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::onPhotoTransmissionToggle()
|
||||||
|
{
|
||||||
|
m_isPhotoTransmissionActive = !m_isPhotoTransmissionActive;
|
||||||
|
|
||||||
|
if (m_isPhotoTransmissionActive) {
|
||||||
|
m_photoBtn->setText("📸 停止传输");
|
||||||
|
m_photoBtn->setStyleSheet("background-color: #dc3545; color: white;");
|
||||||
|
m_logTextEdit->append(QString("[%1] 开始照片传输").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit startPhotoTransmission();
|
||||||
|
} else {
|
||||||
|
m_photoBtn->setText("📸 照片传输");
|
||||||
|
m_photoBtn->setStyleSheet("");
|
||||||
|
m_logTextEdit->append(QString("[%1] 停止照片传输").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit stopPhotoTransmission();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::onPersonRecognitionToggle()
|
||||||
|
{
|
||||||
|
m_isPersonRecognitionActive = !m_isPersonRecognitionActive;
|
||||||
|
|
||||||
|
if (m_isPersonRecognitionActive) {
|
||||||
|
m_recognitionBtn->setText("👁️ 停止识别");
|
||||||
|
m_recognitionBtn->setStyleSheet("background-color: #dc3545; color: white;");
|
||||||
|
m_logTextEdit->append(QString("[%1] 开始人物识别").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit startPersonRecognition();
|
||||||
|
} else {
|
||||||
|
m_recognitionBtn->setText("👁️ 人物识别");
|
||||||
|
m_recognitionBtn->setStyleSheet("");
|
||||||
|
m_logTextEdit->append(QString("[%1] 停止人物识别").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit stopPersonRecognition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DroneControlDialog::updateDroneStatus(int battery, double altitude, double speed)
|
||||||
|
{
|
||||||
|
m_batteryProgress->setValue(battery);
|
||||||
|
m_altitudeLabel->setText(QString("%1 m").arg(altitude, 0, 'f', 1));
|
||||||
|
m_speedLabel->setText(QString("%1 m/s").arg(speed, 0, 'f', 1));
|
||||||
|
}
|
@ -0,0 +1,630 @@
|
|||||||
|
/**
|
||||||
|
* @file RobotDogControlDialog.cpp
|
||||||
|
* @brief 机器狗控制对话框实现
|
||||||
|
* @author Qt UI Optimizer
|
||||||
|
* @date 2024-07-04
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ui/dialogs/RobotDogControlDialog.h"
|
||||||
|
#include "styles/ModernStyleManager.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDesktopWidget>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
RobotDogControlDialog::RobotDogControlDialog(QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, m_mainLayout(nullptr)
|
||||||
|
, m_contentLayout(nullptr)
|
||||||
|
, m_isMappingActive(false)
|
||||||
|
, m_isNavigationActive(false)
|
||||||
|
, m_isPhotoTransmissionActive(false)
|
||||||
|
, m_isPersonRecognitionActive(false)
|
||||||
|
, m_isMoving(false)
|
||||||
|
, m_currentPosture("站立")
|
||||||
|
, m_statusUpdateTimer(new QTimer(this))
|
||||||
|
{
|
||||||
|
setupUI();
|
||||||
|
applyStyles();
|
||||||
|
connectSignals();
|
||||||
|
|
||||||
|
// 启动状态更新定时器
|
||||||
|
m_statusUpdateTimer->start(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
RobotDogControlDialog::~RobotDogControlDialog()
|
||||||
|
{
|
||||||
|
if (m_statusUpdateTimer) {
|
||||||
|
m_statusUpdateTimer->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::setupUI()
|
||||||
|
{
|
||||||
|
setWindowTitle("🐕 机器狗控制中心");
|
||||||
|
setModal(false);
|
||||||
|
setMinimumSize(900, 700);
|
||||||
|
resize(1000, 750);
|
||||||
|
|
||||||
|
// 窗口居中显示
|
||||||
|
QRect screenGeometry = QApplication::desktop()->screenGeometry();
|
||||||
|
int x = (screenGeometry.width() - this->width()) / 2;
|
||||||
|
int y = (screenGeometry.height() - this->height()) / 2;
|
||||||
|
move(x, y);
|
||||||
|
|
||||||
|
m_mainLayout = new QVBoxLayout(this);
|
||||||
|
m_mainLayout->setSpacing(20);
|
||||||
|
m_mainLayout->setContentsMargins(20, 20, 20, 20);
|
||||||
|
|
||||||
|
// 标题
|
||||||
|
QLabel *titleLabel = new QLabel("🐕 机器狗控制中心");
|
||||||
|
titleLabel->setObjectName("DialogTitle");
|
||||||
|
titleLabel->setAlignment(Qt::AlignCenter);
|
||||||
|
titleLabel->setStyleSheet(
|
||||||
|
"font-size: 24px; "
|
||||||
|
"font-weight: bold; "
|
||||||
|
"color: #16a085; "
|
||||||
|
"padding: 10px; "
|
||||||
|
"border-bottom: 2px solid #16a085; "
|
||||||
|
"margin-bottom: 10px;"
|
||||||
|
);
|
||||||
|
m_mainLayout->addWidget(titleLabel);
|
||||||
|
|
||||||
|
// 主内容区域
|
||||||
|
m_contentLayout = new QHBoxLayout();
|
||||||
|
m_contentLayout->setSpacing(20);
|
||||||
|
|
||||||
|
setupMovementControlModule();
|
||||||
|
setupMissionControlModule();
|
||||||
|
setupStatusMonitorModule();
|
||||||
|
|
||||||
|
m_mainLayout->addLayout(m_contentLayout);
|
||||||
|
|
||||||
|
// 底部按钮
|
||||||
|
QHBoxLayout *buttonLayout = new QHBoxLayout();
|
||||||
|
buttonLayout->addStretch();
|
||||||
|
|
||||||
|
QPushButton *closeBtn = new QPushButton("关闭");
|
||||||
|
closeBtn->setObjectName("CloseBtn");
|
||||||
|
closeBtn->setMinimumSize(100, 40);
|
||||||
|
connect(closeBtn, &QPushButton::clicked, this, &QDialog::close);
|
||||||
|
|
||||||
|
buttonLayout->addWidget(closeBtn);
|
||||||
|
m_mainLayout->addLayout(buttonLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::setupMovementControlModule()
|
||||||
|
{
|
||||||
|
m_movementControlGroup = new QGroupBox("🎮 运动控制");
|
||||||
|
m_movementControlGroup->setObjectName("ControlGroup");
|
||||||
|
m_movementControlGroup->setMinimumWidth(280);
|
||||||
|
|
||||||
|
QVBoxLayout *movementLayout = new QVBoxLayout(m_movementControlGroup);
|
||||||
|
movementLayout->setSpacing(15);
|
||||||
|
|
||||||
|
// 方向控制按钮 - 十字布局
|
||||||
|
QGridLayout *directionLayout = new QGridLayout();
|
||||||
|
directionLayout->setSpacing(10);
|
||||||
|
|
||||||
|
m_forwardBtn = new QPushButton("⬆️ 前进");
|
||||||
|
m_forwardBtn->setObjectName("DirectionBtn");
|
||||||
|
m_forwardBtn->setMinimumHeight(50);
|
||||||
|
|
||||||
|
m_backwardBtn = new QPushButton("⬇️ 后退");
|
||||||
|
m_backwardBtn->setObjectName("DirectionBtn");
|
||||||
|
m_backwardBtn->setMinimumHeight(50);
|
||||||
|
|
||||||
|
m_leftBtn = new QPushButton("⬅️ 左转");
|
||||||
|
m_leftBtn->setObjectName("DirectionBtn");
|
||||||
|
m_leftBtn->setMinimumHeight(50);
|
||||||
|
|
||||||
|
m_rightBtn = new QPushButton("➡️ 右转");
|
||||||
|
m_rightBtn->setObjectName("DirectionBtn");
|
||||||
|
m_rightBtn->setMinimumHeight(50);
|
||||||
|
|
||||||
|
m_stopBtn = new QPushButton("⏹️ 停止");
|
||||||
|
m_stopBtn->setObjectName("StopBtn");
|
||||||
|
m_stopBtn->setMinimumHeight(50);
|
||||||
|
|
||||||
|
// 十字布局
|
||||||
|
directionLayout->addWidget(m_forwardBtn, 0, 1);
|
||||||
|
directionLayout->addWidget(m_leftBtn, 1, 0);
|
||||||
|
directionLayout->addWidget(m_stopBtn, 1, 1);
|
||||||
|
directionLayout->addWidget(m_rightBtn, 1, 2);
|
||||||
|
directionLayout->addWidget(m_backwardBtn, 2, 1);
|
||||||
|
|
||||||
|
movementLayout->addLayout(directionLayout);
|
||||||
|
|
||||||
|
// 姿态控制按钮
|
||||||
|
QLabel *postureLabel = new QLabel("姿态控制:");
|
||||||
|
movementLayout->addWidget(postureLabel);
|
||||||
|
|
||||||
|
QHBoxLayout *postureLayout = new QHBoxLayout();
|
||||||
|
postureLayout->setSpacing(10);
|
||||||
|
|
||||||
|
m_standBtn = new QPushButton("🧍 站立");
|
||||||
|
m_standBtn->setObjectName("PostureBtn");
|
||||||
|
m_standBtn->setMinimumHeight(45);
|
||||||
|
|
||||||
|
m_lieDownBtn = new QPushButton("🛌 趴下");
|
||||||
|
m_lieDownBtn->setObjectName("PostureBtn");
|
||||||
|
m_lieDownBtn->setMinimumHeight(45);
|
||||||
|
|
||||||
|
m_jumpBtn = new QPushButton("🦘 跳跃");
|
||||||
|
m_jumpBtn->setObjectName("PostureBtn");
|
||||||
|
m_jumpBtn->setMinimumHeight(45);
|
||||||
|
|
||||||
|
postureLayout->addWidget(m_standBtn);
|
||||||
|
postureLayout->addWidget(m_lieDownBtn);
|
||||||
|
postureLayout->addWidget(m_jumpBtn);
|
||||||
|
movementLayout->addLayout(postureLayout);
|
||||||
|
|
||||||
|
// 速度控制
|
||||||
|
QLabel *speedLabel = new QLabel("移动速度:");
|
||||||
|
m_speedSlider = new QSlider(Qt::Horizontal);
|
||||||
|
m_speedSlider->setRange(1, 10);
|
||||||
|
m_speedSlider->setValue(5);
|
||||||
|
|
||||||
|
movementLayout->addWidget(speedLabel);
|
||||||
|
movementLayout->addWidget(m_speedSlider);
|
||||||
|
|
||||||
|
// 紧急停止按钮
|
||||||
|
m_emergencyStopBtn = new QPushButton("🚨 紧急停止");
|
||||||
|
m_emergencyStopBtn->setObjectName("DangerBtn");
|
||||||
|
m_emergencyStopBtn->setMinimumHeight(60);
|
||||||
|
m_emergencyStopBtn->setStyleSheet(
|
||||||
|
"QPushButton {"
|
||||||
|
" background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
|
||||||
|
" stop:0 #e74c3c, stop:1 #c0392b);"
|
||||||
|
" color: white;"
|
||||||
|
" font-size: 16px;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
" border: 2px solid #e74c3c;"
|
||||||
|
" border-radius: 8px;"
|
||||||
|
"}"
|
||||||
|
"QPushButton:hover {"
|
||||||
|
" background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
|
||||||
|
" stop:0 #c0392b, stop:1 #a93226);"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
movementLayout->addWidget(m_emergencyStopBtn);
|
||||||
|
movementLayout->addStretch();
|
||||||
|
|
||||||
|
m_contentLayout->addWidget(m_movementControlGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::setupMissionControlModule()
|
||||||
|
{
|
||||||
|
m_missionControlGroup = new QGroupBox("🎯 任务控制");
|
||||||
|
m_missionControlGroup->setObjectName("ControlGroup");
|
||||||
|
m_missionControlGroup->setMinimumWidth(280);
|
||||||
|
|
||||||
|
QVBoxLayout *missionLayout = new QVBoxLayout(m_missionControlGroup);
|
||||||
|
missionLayout->setSpacing(15);
|
||||||
|
|
||||||
|
// 任务模式选择
|
||||||
|
QLabel *modeLabel = new QLabel("任务模式:");
|
||||||
|
m_missionModeCombo = new QComboBox();
|
||||||
|
m_missionModeCombo->addItems({"手动控制", "自主巡逻", "目标跟踪", "区域探索", "护卫模式"});
|
||||||
|
m_missionModeCombo->setMinimumHeight(35);
|
||||||
|
|
||||||
|
missionLayout->addWidget(modeLabel);
|
||||||
|
missionLayout->addWidget(m_missionModeCombo);
|
||||||
|
|
||||||
|
// 功能控制按钮
|
||||||
|
m_mappingBtn = new QPushButton("🗺️ 开始建图");
|
||||||
|
m_mappingBtn->setObjectName("FunctionBtn");
|
||||||
|
m_mappingBtn->setMinimumHeight(50);
|
||||||
|
m_mappingBtn->setCheckable(true);
|
||||||
|
|
||||||
|
m_navigationBtn = new QPushButton("🧭 导航避障");
|
||||||
|
m_navigationBtn->setObjectName("FunctionBtn");
|
||||||
|
m_navigationBtn->setMinimumHeight(50);
|
||||||
|
m_navigationBtn->setCheckable(true);
|
||||||
|
|
||||||
|
m_photoBtn = new QPushButton("📸 照片传输");
|
||||||
|
m_photoBtn->setObjectName("FunctionBtn");
|
||||||
|
m_photoBtn->setMinimumHeight(50);
|
||||||
|
m_photoBtn->setCheckable(true);
|
||||||
|
|
||||||
|
m_recognitionBtn = new QPushButton("👁️ 人物识别");
|
||||||
|
m_recognitionBtn->setObjectName("FunctionBtn");
|
||||||
|
m_recognitionBtn->setMinimumHeight(50);
|
||||||
|
m_recognitionBtn->setCheckable(true);
|
||||||
|
|
||||||
|
missionLayout->addWidget(m_mappingBtn);
|
||||||
|
missionLayout->addWidget(m_navigationBtn);
|
||||||
|
missionLayout->addWidget(m_photoBtn);
|
||||||
|
missionLayout->addWidget(m_recognitionBtn);
|
||||||
|
missionLayout->addStretch();
|
||||||
|
|
||||||
|
m_contentLayout->addWidget(m_missionControlGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::setupStatusMonitorModule()
|
||||||
|
{
|
||||||
|
m_statusGroup = new QGroupBox("📊 状态监控");
|
||||||
|
m_statusGroup->setObjectName("ControlGroup");
|
||||||
|
m_statusGroup->setMinimumWidth(320);
|
||||||
|
|
||||||
|
QVBoxLayout *statusLayout = new QVBoxLayout(m_statusGroup);
|
||||||
|
statusLayout->setSpacing(15);
|
||||||
|
|
||||||
|
// 电池状态
|
||||||
|
QHBoxLayout *batteryLayout = new QHBoxLayout();
|
||||||
|
m_batteryLabel = new QLabel("电池电量:");
|
||||||
|
m_batteryProgress = new QProgressBar();
|
||||||
|
m_batteryProgress->setRange(0, 100);
|
||||||
|
m_batteryProgress->setValue(90);
|
||||||
|
m_batteryProgress->setTextVisible(true);
|
||||||
|
m_batteryProgress->setFormat("%p%");
|
||||||
|
|
||||||
|
batteryLayout->addWidget(m_batteryLabel);
|
||||||
|
batteryLayout->addWidget(m_batteryProgress);
|
||||||
|
statusLayout->addLayout(batteryLayout);
|
||||||
|
|
||||||
|
// 运行参数
|
||||||
|
QGridLayout *paramLayout = new QGridLayout();
|
||||||
|
paramLayout->addWidget(new QLabel("移动速度:"), 0, 0);
|
||||||
|
m_speedLabel = new QLabel("0.0 m/s");
|
||||||
|
m_speedLabel->setStyleSheet("font-weight: bold; color: #16a085;");
|
||||||
|
paramLayout->addWidget(m_speedLabel, 0, 1);
|
||||||
|
|
||||||
|
paramLayout->addWidget(new QLabel("设备温度:"), 1, 0);
|
||||||
|
m_temperatureLabel = new QLabel("35.2°C");
|
||||||
|
m_temperatureLabel->setStyleSheet("font-weight: bold; color: #16a085;");
|
||||||
|
paramLayout->addWidget(m_temperatureLabel, 1, 1);
|
||||||
|
|
||||||
|
paramLayout->addWidget(new QLabel("当前姿态:"), 2, 0);
|
||||||
|
m_postureLabel = new QLabel("🧍 站立");
|
||||||
|
paramLayout->addWidget(m_postureLabel, 2, 1);
|
||||||
|
|
||||||
|
paramLayout->addWidget(new QLabel("连接状态:"), 3, 0);
|
||||||
|
m_connectionLabel = new QLabel("🟢 已连接");
|
||||||
|
paramLayout->addWidget(m_connectionLabel, 3, 1);
|
||||||
|
|
||||||
|
statusLayout->addLayout(paramLayout);
|
||||||
|
|
||||||
|
// 日志显示
|
||||||
|
QLabel *logLabel = new QLabel("系统日志:");
|
||||||
|
m_logTextEdit = new QTextEdit();
|
||||||
|
m_logTextEdit->setMaximumHeight(200);
|
||||||
|
m_logTextEdit->setReadOnly(true);
|
||||||
|
m_logTextEdit->append(QString("[%1] 机器狗控制系统启动").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
m_logTextEdit->append(QString("[%1] 机器狗已连接,当前状态:待命").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
|
||||||
|
statusLayout->addWidget(logLabel);
|
||||||
|
statusLayout->addWidget(m_logTextEdit);
|
||||||
|
|
||||||
|
m_contentLayout->addWidget(m_statusGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::applyStyles()
|
||||||
|
{
|
||||||
|
// 应用现代样式管理器
|
||||||
|
ModernStyleManager* styleManager = ModernStyleManager::getInstance();
|
||||||
|
|
||||||
|
// 设置对话框样式
|
||||||
|
setStyleSheet(
|
||||||
|
"QDialog {"
|
||||||
|
" background-color: #f8f9fa;"
|
||||||
|
" border: 1px solid #dee2e6;"
|
||||||
|
"}"
|
||||||
|
"QGroupBox {"
|
||||||
|
" font-size: 16px;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
" color: #495057;"
|
||||||
|
" border: 2px solid #dee2e6;"
|
||||||
|
" border-radius: 8px;"
|
||||||
|
" margin-top: 10px;"
|
||||||
|
" padding-top: 10px;"
|
||||||
|
"}"
|
||||||
|
"QGroupBox::title {"
|
||||||
|
" subcontrol-origin: margin;"
|
||||||
|
" left: 10px;"
|
||||||
|
" padding: 0 8px 0 8px;"
|
||||||
|
" background-color: #f8f9fa;"
|
||||||
|
"}"
|
||||||
|
"QPushButton#DirectionBtn {"
|
||||||
|
" background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
|
||||||
|
" stop:0 #16a085, stop:1 #138d75);"
|
||||||
|
" color: white;"
|
||||||
|
" font-size: 14px;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
" border: 2px solid #16a085;"
|
||||||
|
" border-radius: 8px;"
|
||||||
|
" padding: 8px;"
|
||||||
|
"}"
|
||||||
|
"QPushButton#DirectionBtn:hover {"
|
||||||
|
" background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
|
||||||
|
" stop:0 #138d75, stop:1 #117a65);"
|
||||||
|
"}"
|
||||||
|
"QPushButton#DirectionBtn:pressed {"
|
||||||
|
" background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
|
||||||
|
" stop:0 #117a65, stop:1 #0e6b5d);"
|
||||||
|
"}"
|
||||||
|
"QPushButton#StopBtn {"
|
||||||
|
" background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
|
||||||
|
" stop:0 #e67e22, stop:1 #d35400);"
|
||||||
|
" color: white;"
|
||||||
|
" font-size: 14px;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
" border: 2px solid #e67e22;"
|
||||||
|
" border-radius: 8px;"
|
||||||
|
" padding: 8px;"
|
||||||
|
"}"
|
||||||
|
"QPushButton#PostureBtn {"
|
||||||
|
" background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
|
||||||
|
" stop:0 #3498db, stop:1 #2980b9);"
|
||||||
|
" color: white;"
|
||||||
|
" font-size: 13px;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
" border: 2px solid #3498db;"
|
||||||
|
" border-radius: 6px;"
|
||||||
|
" padding: 6px;"
|
||||||
|
"}"
|
||||||
|
"QSlider::groove:horizontal {"
|
||||||
|
" border: 1px solid #bbb;"
|
||||||
|
" background: white;"
|
||||||
|
" height: 10px;"
|
||||||
|
" border-radius: 4px;"
|
||||||
|
"}"
|
||||||
|
"QSlider::handle:horizontal {"
|
||||||
|
" background: #16a085;"
|
||||||
|
" border: 1px solid #5c5c5c;"
|
||||||
|
" width: 18px;"
|
||||||
|
" margin: -2px 0;"
|
||||||
|
" border-radius: 3px;"
|
||||||
|
"}"
|
||||||
|
"QProgressBar {"
|
||||||
|
" border: 2px solid #dee2e6;"
|
||||||
|
" border-radius: 5px;"
|
||||||
|
" text-align: center;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
"}"
|
||||||
|
"QProgressBar::chunk {"
|
||||||
|
" background-color: #28a745;"
|
||||||
|
" border-radius: 3px;"
|
||||||
|
"}"
|
||||||
|
"QTextEdit {"
|
||||||
|
" border: 1px solid #dee2e6;"
|
||||||
|
" border-radius: 4px;"
|
||||||
|
" background-color: white;"
|
||||||
|
" font-family: 'Consolas', monospace;"
|
||||||
|
" font-size: 12px;"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::connectSignals()
|
||||||
|
{
|
||||||
|
// 运动控制信号连接
|
||||||
|
connect(m_forwardBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onMoveForwardClicked);
|
||||||
|
connect(m_backwardBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onMoveBackwardClicked);
|
||||||
|
connect(m_leftBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onTurnLeftClicked);
|
||||||
|
connect(m_rightBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onTurnRightClicked);
|
||||||
|
connect(m_stopBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onStopClicked);
|
||||||
|
|
||||||
|
// 姿态控制信号连接
|
||||||
|
connect(m_standBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onStandClicked);
|
||||||
|
connect(m_lieDownBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onLieDownClicked);
|
||||||
|
connect(m_jumpBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onJumpClicked);
|
||||||
|
|
||||||
|
// 紧急停止
|
||||||
|
connect(m_emergencyStopBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onEmergencyStop);
|
||||||
|
|
||||||
|
// 任务控制信号连接
|
||||||
|
connect(m_mappingBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onMappingToggle);
|
||||||
|
connect(m_navigationBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onNavigationToggle);
|
||||||
|
connect(m_photoBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onPhotoTransmissionToggle);
|
||||||
|
connect(m_recognitionBtn, &QPushButton::clicked, this, &RobotDogControlDialog::onPersonRecognitionToggle);
|
||||||
|
|
||||||
|
// 速度滑块
|
||||||
|
connect(m_speedSlider, &QSlider::valueChanged, [this](int value) {
|
||||||
|
m_logTextEdit->append(QString("[%1] 速度设置为: %2").arg(
|
||||||
|
QDateTime::currentDateTime().toString("hh:mm:ss")).arg(value));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 状态更新定时器
|
||||||
|
connect(m_statusUpdateTimer, &QTimer::timeout, [this]() {
|
||||||
|
// 模拟状态更新
|
||||||
|
static int counter = 0;
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
if (m_isMoving) {
|
||||||
|
// 模拟电池消耗
|
||||||
|
int currentBattery = m_batteryProgress->value();
|
||||||
|
if (currentBattery > 0 && counter % 15 == 0) {
|
||||||
|
m_batteryProgress->setValue(currentBattery - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新电池颜色
|
||||||
|
if (currentBattery > 50) {
|
||||||
|
m_batteryProgress->setStyleSheet("QProgressBar::chunk { background-color: #28a745; }");
|
||||||
|
} else if (currentBattery > 20) {
|
||||||
|
m_batteryProgress->setStyleSheet("QProgressBar::chunk { background-color: #ffc107; }");
|
||||||
|
} else {
|
||||||
|
m_batteryProgress->setStyleSheet("QProgressBar::chunk { background-color: #dc3545; }");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟温度变化
|
||||||
|
static double temperature = 35.2;
|
||||||
|
temperature += (qrand() % 21 - 10) * 0.1; // ±1度随机变化
|
||||||
|
if (temperature < 30.0) temperature = 30.0;
|
||||||
|
if (temperature > 45.0) temperature = 45.0;
|
||||||
|
m_temperatureLabel->setText(QString("%1°C").arg(temperature, 0, 'f', 1));
|
||||||
|
|
||||||
|
// 温度颜色警告
|
||||||
|
if (temperature > 40.0) {
|
||||||
|
m_temperatureLabel->setStyleSheet("font-weight: bold; color: #dc3545;");
|
||||||
|
} else if (temperature > 38.0) {
|
||||||
|
m_temperatureLabel->setStyleSheet("font-weight: bold; color: #ffc107;");
|
||||||
|
} else {
|
||||||
|
m_temperatureLabel->setStyleSheet("font-weight: bold; color: #16a085;");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 运动控制槽函数实现
|
||||||
|
void RobotDogControlDialog::onMoveForwardClicked()
|
||||||
|
{
|
||||||
|
m_isMoving = true;
|
||||||
|
m_logTextEdit->append(QString("[%1] 机器狗开始前进").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
updateRobotStatus(m_batteryProgress->value(), m_speedSlider->value() * 0.5, 35.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onMoveBackwardClicked()
|
||||||
|
{
|
||||||
|
m_isMoving = true;
|
||||||
|
m_logTextEdit->append(QString("[%1] 机器狗开始后退").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
updateRobotStatus(m_batteryProgress->value(), m_speedSlider->value() * 0.3, 35.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onTurnLeftClicked()
|
||||||
|
{
|
||||||
|
m_isMoving = true;
|
||||||
|
m_logTextEdit->append(QString("[%1] 机器狗开始左转").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
updateRobotStatus(m_batteryProgress->value(), m_speedSlider->value() * 0.2, 35.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onTurnRightClicked()
|
||||||
|
{
|
||||||
|
m_isMoving = true;
|
||||||
|
m_logTextEdit->append(QString("[%1] 机器狗开始右转").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
updateRobotStatus(m_batteryProgress->value(), m_speedSlider->value() * 0.2, 35.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onStopClicked()
|
||||||
|
{
|
||||||
|
m_isMoving = false;
|
||||||
|
m_logTextEdit->append(QString("[%1] 机器狗停止移动").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
updateRobotStatus(m_batteryProgress->value(), 0.0, 34.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onStandClicked()
|
||||||
|
{
|
||||||
|
m_currentPosture = "站立";
|
||||||
|
m_postureLabel->setText("🧍 站立");
|
||||||
|
m_logTextEdit->append(QString("[%1] 机器狗切换到站立姿态").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onLieDownClicked()
|
||||||
|
{
|
||||||
|
m_currentPosture = "趴下";
|
||||||
|
m_postureLabel->setText("🛌 趴下");
|
||||||
|
m_logTextEdit->append(QString("[%1] 机器狗切换到趴下姿态").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
|
||||||
|
// 趴下时停止移动
|
||||||
|
if (m_isMoving) {
|
||||||
|
onStopClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onJumpClicked()
|
||||||
|
{
|
||||||
|
m_logTextEdit->append(QString("[%1] 机器狗执行跳跃动作").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
|
||||||
|
// 跳跃后恢复站立姿态
|
||||||
|
QTimer::singleShot(1000, [this]() {
|
||||||
|
onStandClicked();
|
||||||
|
m_logTextEdit->append(QString("[%1] 跳跃动作完成").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onEmergencyStop()
|
||||||
|
{
|
||||||
|
QMessageBox::StandardButton reply = QMessageBox::warning(this, "紧急停止",
|
||||||
|
"确定要执行紧急停止吗?这将立即停止所有操作!",
|
||||||
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
|
if (reply == QMessageBox::Yes) {
|
||||||
|
m_logTextEdit->append(QString("[%1] 🚨 执行紧急停止!").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
onStopClicked();
|
||||||
|
|
||||||
|
// 停止所有任务
|
||||||
|
if (m_isMappingActive) onMappingToggle();
|
||||||
|
if (m_isNavigationActive) onNavigationToggle();
|
||||||
|
if (m_isPhotoTransmissionActive) onPhotoTransmissionToggle();
|
||||||
|
if (m_isPersonRecognitionActive) onPersonRecognitionToggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 任务控制槽函数实现
|
||||||
|
void RobotDogControlDialog::onMappingToggle()
|
||||||
|
{
|
||||||
|
m_isMappingActive = !m_isMappingActive;
|
||||||
|
|
||||||
|
if (m_isMappingActive) {
|
||||||
|
m_mappingBtn->setText("🗺️ 停止建图");
|
||||||
|
m_mappingBtn->setStyleSheet("background-color: #dc3545; color: white;");
|
||||||
|
m_logTextEdit->append(QString("[%1] 开始自主建图").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit startMapping();
|
||||||
|
} else {
|
||||||
|
m_mappingBtn->setText("🗺️ 开始建图");
|
||||||
|
m_mappingBtn->setStyleSheet("");
|
||||||
|
m_logTextEdit->append(QString("[%1] 停止自主建图").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit stopMapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onNavigationToggle()
|
||||||
|
{
|
||||||
|
m_isNavigationActive = !m_isNavigationActive;
|
||||||
|
|
||||||
|
if (m_isNavigationActive) {
|
||||||
|
m_navigationBtn->setText("🧭 停止导航");
|
||||||
|
m_navigationBtn->setStyleSheet("background-color: #dc3545; color: white;");
|
||||||
|
m_logTextEdit->append(QString("[%1] 开始导航避障").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit startNavigation();
|
||||||
|
} else {
|
||||||
|
m_navigationBtn->setText("🧭 导航避障");
|
||||||
|
m_navigationBtn->setStyleSheet("");
|
||||||
|
m_logTextEdit->append(QString("[%1] 停止导航避障").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit stopNavigation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onPhotoTransmissionToggle()
|
||||||
|
{
|
||||||
|
m_isPhotoTransmissionActive = !m_isPhotoTransmissionActive;
|
||||||
|
|
||||||
|
if (m_isPhotoTransmissionActive) {
|
||||||
|
m_photoBtn->setText("📸 停止传输");
|
||||||
|
m_photoBtn->setStyleSheet("background-color: #dc3545; color: white;");
|
||||||
|
m_logTextEdit->append(QString("[%1] 开始照片传输").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit startPhotoTransmission();
|
||||||
|
} else {
|
||||||
|
m_photoBtn->setText("📸 照片传输");
|
||||||
|
m_photoBtn->setStyleSheet("");
|
||||||
|
m_logTextEdit->append(QString("[%1] 停止照片传输").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit stopPhotoTransmission();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::onPersonRecognitionToggle()
|
||||||
|
{
|
||||||
|
m_isPersonRecognitionActive = !m_isPersonRecognitionActive;
|
||||||
|
|
||||||
|
if (m_isPersonRecognitionActive) {
|
||||||
|
m_recognitionBtn->setText("👁️ 停止识别");
|
||||||
|
m_recognitionBtn->setStyleSheet("background-color: #dc3545; color: white;");
|
||||||
|
m_logTextEdit->append(QString("[%1] 开始人物识别").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit startPersonRecognition();
|
||||||
|
} else {
|
||||||
|
m_recognitionBtn->setText("👁️ 人物识别");
|
||||||
|
m_recognitionBtn->setStyleSheet("");
|
||||||
|
m_logTextEdit->append(QString("[%1] 停止人物识别").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
|
||||||
|
emit stopPersonRecognition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RobotDogControlDialog::updateRobotStatus(int battery, double speed, double temperature)
|
||||||
|
{
|
||||||
|
m_batteryProgress->setValue(battery);
|
||||||
|
m_speedLabel->setText(QString("%1 m/s").arg(speed, 0, 'f', 1));
|
||||||
|
m_temperatureLabel->setText(QString("%1°C").arg(temperature, 0, 'f', 1));
|
||||||
|
}
|
Loading…
Reference in new issue