Files
QT_wuhan_YT/pages/armpage.cpp
T
2026-09-09 17:00:37 +08:00

228 lines
8.1 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 "armpage.h"
#include "titlebar.h"
#include "statusstrip.h"
#include "alarmbanner.h"
#include "datacard.h"
#include "udpcommunication.h"
#include "confirmdialog.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QLabel>
#include <QTimer>
#include "global.h"
ArmPage::ArmPage(AppContext* ctx, QWidget* parent)
: BasePage(ctx, parent)
{
QVBoxLayout* root = new QVBoxLayout(this);
root->setContentsMargins(0, 0, 0, 0);
root->setSpacing(0);
m_titleBar = new TitleBar(ctx, this);
m_titleBar->setTitle("机械臂");
root->addWidget(m_titleBar);
m_banner = new AlarmBanner(this);
root->addWidget(m_banner);
QHBoxLayout* main = new QHBoxLayout();
main->setContentsMargins(36, 16, 36, 16);
main->setSpacing(32);
// 左控制列(6 运动按钮 + 系统回位/暂停)
QWidget* left = new QWidget(this);
QVBoxLayout* leftLay = new QVBoxLayout(left);
leftLay->setContentsMargins(0, 0, 0, 0);
leftLay->setSpacing(8);
auto addMove = [&](const QString& t, const QString& axis, int dir) {
QPushButton* b = makeMoveButton(t, axis, dir);
m_moveButtons << b;
leftLay->addWidget(b);
};
addMove("左平移", "x", -1);
addMove("右平移", "x", +1);
addMove("上升", "z", +1);
addMove("下降", "z", -1);
addMove("前平移", "y", +1);
addMove("后平移", "y", -1);
m_returnBtn = button("系统回位/暂停", "", left);
m_returnBtn->setCheckable(true);
m_returnBtn->setFixedSize(180, 90);
m_returnBtn->setStyleSheet(QString("font-size:22px;background-color:%1;color:%2;border:1px solid %3;border-radius:12px;")
.arg(C::PANEL_HI, C::TEXT, C::BORDER));
connect(m_returnBtn, &QPushButton::toggled, this, &ArmPage::onReturnToggled);
leftLay->addWidget(m_returnBtn);
m_returnStatus = label("", 18, C::TEXT_SUB, false, left);
m_returnStatus->setAlignment(Qt::AlignCenter);
m_returnStatus->setWordWrap(true);
leftLay->addWidget(m_returnStatus);
leftLay->addStretch(1);
left->setFixedWidth(180);
main->addWidget(left);
// 中央卡片区(底盘/洗消/气体检测仪)
QWidget* center = new QWidget(this);
QVBoxLayout* centerLay = new QVBoxLayout(center);
centerLay->setContentsMargins(0, 0, 0, 0);
centerLay->setSpacing(12);
m_chassisCard = new DataCard("底盘", center);
m_chassisCard->addField("电量", "85%");
m_chassisCard->addField("电压", "360V");
m_chassisCard->addField("故障", "无");
m_washCard = new DataCard("洗消", center);
m_washCard->addField("A液位", "100L");
m_washCard->addField("泡沫液位", "30L");
m_gasCard = new DataCard("气体检测仪", center);
m_gasCard->addField("主机状态", "待机");
m_gasCard->addField("浓度", "0 ppb");
centerLay->addWidget(m_chassisCard, 1);
centerLay->addWidget(m_washCard, 1);
centerLay->addWidget(m_gasCard, 1);
main->addWidget(center, 1);
// 右参数区(机械臂参数卡 + 末端按钮列)
QWidget* right = new QWidget(this);
QVBoxLayout* rightLay = new QVBoxLayout(right);
rightLay->setContentsMargins(0, 0, 0, 0);
rightLay->setSpacing(12);
m_armCard = new DataCard("机械臂参数", right);
m_armCard->addField("末端位置", "XYZ");
m_armCard->addField("姿态", "RX/RY/RZ");
m_armCard->addField("速度", "0");
m_armCard->addField("J1", "30°");
m_armCard->addField("J2", "20°");
m_armCard->addField("J3", "0°");
m_armCard->addField("J4", "90°");
m_armCard->addField("J5", "45°");
m_armCard->addField("J6", "0°");
rightLay->addWidget(m_armCard, 1);
// 末端 6 姿态按钮(2 列 × 3 行)
QGridLayout* endGrid = new QGridLayout();
endGrid->setSpacing(8);
auto addEnd = [&](const QString& t, const QString& axis, int dir, int r, int c) {
QPushButton* b = makeMoveButton(t, axis, dir);
b->setFixedHeight(80);
m_endButtons << b;
endGrid->addWidget(b, r, c);
};
addEnd("末端仰", "pitch", +1, 0, 0);
addEnd("末端俯", "pitch", -1, 0, 1);
addEnd("末端正偏航", "yaw", +1, 1, 0);
addEnd("末端负偏航", "yaw", -1, 1, 1);
addEnd("末端左横滚", "roll", -1, 2, 0);
addEnd("末端右横滚", "roll", +1, 2, 1);
rightLay->addLayout(endGrid);
right->setFixedWidth(430);
main->addWidget(right);
root->addLayout(main, 1);
m_statusStrip = new StatusStrip(ctx, this);
connect(m_statusStrip, &StatusStrip::backClicked, this, [this]() { emit navigate(PageJob); });
root->addWidget(m_statusStrip);
m_statusTimer = new QTimer(this);
m_statusTimer->setSingleShot(true);
m_statusTimer->setInterval(3000);
connect(m_statusTimer, &QTimer::timeout, this, [this]() {
m_returnStatus->setText("");
});
connect(ctx->comm(), &UdpCommunication::telemetryUpdated, this, &ArmPage::refresh);
connect(ctx, &AppContext::modeChanged, this, [this](Mode) { updateModeGating(); });
connect(ctx, &AppContext::estopChanged, this, [this](bool) { updateModeGating(); });
updateModeGating();
refresh();
}
QPushButton* ArmPage::makeMoveButton(const QString& text, const QString& axis, int dir)
{
QPushButton* b = button(text, "", this);
b->setFixedSize(180, 90);
b->setStyleSheet(QString("font-size:24px;background-color:%1;color:%2;border:1px solid %3;border-radius:12px;")
.arg(C::PANEL_HI, C::TEXT, C::BORDER));
connect(b, &QPushButton::pressed, this, [this, axis, dir]() {
if (ctx()->mode != Mode::Arm) {
ConfirmDialog::toast(this, "请切换至机械臂模式");
return;
}
ctx()->comm()->sendArmMove(axis, dir);
});
connect(b, &QPushButton::released, this, [this, axis]() {
ctx()->comm()->sendArmMove(axis, 0);
});
return b;
}
void ArmPage::updateModeGating()
{
bool arm = (ctx()->mode == Mode::Arm) && !ctx()->estopTriggered;
for (QPushButton* b : m_moveButtons) b->setEnabled(arm);
for (QPushButton* b : m_endButtons) b->setEnabled(arm);
}
void ArmPage::onReturnToggled(bool on)
{
if (on) ctx()->comm()->sendArmReturn();
else ctx()->comm()->sendArmPause();
}
void ArmPage::refresh()
{
const Telemetry& t = ctx()->telemetry;
if (!t.commOk) {
m_banner->showAlarm("通信异常");
} else {
m_banner->clear();
}
m_chassisCard->setField(0, QString("%1%").arg(t.soc));
m_chassisCard->setField(1, QString("%1V").arg(t.volt, 0, 'f', 0));
m_chassisCard->setField(2, t.chassisFaults.isEmpty() ? "无" : t.chassisFaults.join(";"));
m_washCard->setField(0, QString("%1L").arg(t.levelA, 0, 'f', 0));
m_washCard->setField(1, QString("%1L").arg(t.levelFoam, 0, 'f', 0));
m_gasCard->setField(0, t.gasHost == "detecting" ? "检测中" : (t.gasHost == "fault" ? "故障" : "待机"));
m_gasCard->setField(1, QString("%1 ppb").arg(t.gasConc, 0, 'f', 0));
m_armCard->setField(0, t.pos);
m_armCard->setField(1, t.pose);
m_armCard->setField(2, QString("%1").arg(t.vel, 0, 'f', 1));
for (int i = 0; i < 6 && i < t.js.size(); ++i)
m_armCard->setField(3 + i, QString("%1°").arg(t.js[i], 0, 'f', 0));
// 回位状态机
if (t.returnState != m_prevReturnState) {
m_prevReturnState = t.returnState;
if (t.returnState == "done") {
m_returnBtn->setChecked(false);
m_returnStatus->setText("机械臂系统完成回位");
m_returnStatus->setStyleSheet(QString("color:%1;font-size:22px;font-weight:700;").arg(C::SUCCESS));
m_statusTimer->start();
} else if (t.returnState == "fault") {
m_returnBtn->setChecked(false);
m_returnStatus->setText("机械臂系统回位异常");
m_returnStatus->setStyleSheet(QString("color:%1;font-size:22px;font-weight:700;").arg(C::DANGER));
} else if (t.returnState == "returning") {
m_returnStatus->setText("回位中…");
m_returnStatus->setStyleSheet(QString("color:%1;font-size:22px;font-weight:700;").arg(C::WARNING));
} else {
m_returnStatus->setText("");
}
}
}