新版布局

This commit is contained in:
xu
2026-10-16 09:06:03 +08:00
parent e5efdea06e
commit 1ec93e42cb
37 changed files with 1785 additions and 977 deletions
+62 -40
View File
@@ -5,7 +5,6 @@
#include "alarmbanner.h"
#include "datacard.h"
#include "car.h"
#include "confirmdialog.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
//#include <QGridLayout> // 末端按钮原为 2×3 网格,改为竖列后暂不需要
@@ -82,33 +81,32 @@ ArmPage::ArmPage(AppContext* ctx, QWidget* parent)
cardsLay->setSpacing(12);
m_chassisCard = new DataCard("底盘", cardsCol);
m_chassisCard->addField("底盘电量SOC", "85%");
m_chassisCard->addField("底盘电压", "360V");
m_chassisCard->addField("底盘故障", "无");
m_chassisCard->addField("底盘电量SOC", "--");
m_chassisCard->addField("底盘电压", "--");
m_washCard = new DataCard("洗消", cardsCol);
m_washCard->addField("A组分/清水液位", "100L");
m_washCard->addField("泡沫箱液位", "30L");
m_washCard->addField("A组分/清水液位", "--");
m_washCard->addField("泡沫箱液位", "--");
m_gasCard = new DataCard("气体检测仪", cardsCol);
m_gasCard->addField("主机状态", "点火状态");
m_gasCard->addField("有毒物种类", "S级");
m_gasCard->addField("有毒物等级", "二级");
m_gasCard->addField("主机状态", "--");
m_gasCard->addField("有毒物种类", "--");
m_gasCard->addField("有毒物等级", "--");
cardsLay->addWidget(m_chassisCard, 1);
cardsLay->addWidget(m_washCard, 1);
cardsLay->addWidget(m_gasCard, 1);
m_armCard = new DataCard("机械臂参数", center);
m_armCard->addField("末端位置", "XYZ");
m_armCard->addField("末端姿态", "RX/RY/RZ");
m_armCard->addField("末端速度", "0");
m_armCard->addField("Joint1关节角", "30°");
m_armCard->addField("Joint2关节角", "20°");
m_armCard->addField("Joint3关节角", "0°");
m_armCard->addField("Joint4关节角", "90°");
m_armCard->addField("Joint5关节角", "45°");
m_armCard->addField("Joint6关节角", "0°");
m_armCard->addField("末端位置", "--");
m_armCard->addField("末端姿态", "--");
m_armCard->addField("末端速度", "--");
m_armCard->addField("Joint1关节角", "--");
m_armCard->addField("Joint2关节角", "--");
m_armCard->addField("Joint3关节角", "--");
m_armCard->addField("Joint4关节角", "--");
m_armCard->addField("Joint5关节角", "--");
m_armCard->addField("Joint6关节角", "--");
centerLay->addWidget(cardsCol, 1);
centerLay->addWidget(m_armCard, 1);
@@ -151,29 +149,43 @@ ArmPage::ArmPage(AppContext* ctx, QWidget* parent)
connect(ctx->comm(), &CarCommunication::telemetryUpdated, this, &ArmPage::refresh);
connect(ctx, &AppContext::modeChanged, this, [this](Mode) { updateModeGating(); });
connect(ctx, &AppContext::estopChanged, this, [this](bool) { updateModeGating(); });
connect(ctx, &AppContext::rcDrivingChanged, this, [this](bool) { updateModeGating(); });
connect(ctx, &AppContext::rcDrivingChanged, this, [this](bool) {
updateModeGating();
// 同底盘页:让位给遥控器期间按下的轴被忽略,遥控器松手后把按着的键重发一遍。
// 注意写 this->ctx():构造函数形参也叫 ctx,直接写 ctx() 会被它遮住
if (this->ctx()->rcDriving()) return;
for (QPushButton* b : m_moveButtons)
if (b->isDown())
this->ctx()->comm()->sendArmMove(b->property("armAxis").toString(),
b->property("armDir").toInt());
});
updateModeGating();
refresh();
}
void ArmPage::showEvent(QShowEvent* ev)
{
BasePage::showEvent(ev);
// 每次进入机械臂页自动切到机械臂模式:Arm_ControlCmd1 的 Arm_modeCmd/Arm_enable
// 挂在它上面,不切的话车端会忽略这里发出的动作指令。遥控器在线时模式由遥控器报文
// 决定,不抢——和底盘页进页面切行车模式是同一套处理。
if (!ctx()->rc()->linkOk())
ctx()->setMode(Mode::Arm);
}
QPushButton* ArmPage::makeMoveButton(const QString& text, const QString& axis, int dir)
{
QPushButton* b = button(text, "", this);
b->setFixedSize(270, 76);
// 记下这根按钮管哪个轴/往哪边,好让"遥控器松手后重发按住的键"找得到它
b->setProperty("armAxis", axis);
b->setProperty("armDir", dir);
b->setStyleSheet(QString(
"QPushButton{font-size:45px;background-color:%1;color:%2;border:1px solid %3;border-radius:12px;}"
"QPushButton:hover,QPushButton:focus,QPushButton:pressed"
"{background-color:%4;color:#FFFFFF;border:2px solid #8ABFFF;}")
.arg(C::PANEL_HI, C::TEXT, C::BORDER, C::PRIMARY));
connect(b, &QPushButton::pressed, this, [this, axis, dir]() {
if (ctx()->rcDriving()) {
ConfirmDialog::toast(this, "遥控器操作中");
return;
}
if (ctx()->mode != Mode::Arm) {
ConfirmDialog::toast(this, "请切换至机械臂模式");
return;
}
ctx()->comm()->sendArmMove(axis, dir);
});
connect(b, &QPushButton::released, this, [this, axis]() {
@@ -184,10 +196,11 @@ QPushButton* ArmPage::makeMoveButton(const QString& text, const QString& axis, i
void ArmPage::updateModeGating()
{
// 非机械臂模式、急停触发或遥控器正在操作时禁用动作按钮(遥控器优先)
bool arm = (ctx()->mode == Mode::Arm) && !ctx()->estopTriggered && !ctx()->rcDriving();
for (QPushButton* b : m_moveButtons) b->setEnabled(arm);
for (QPushButton* b : m_endButtons) b->setEnabled(arm);
// 和底盘页一样:现在只有**急停**会禁用动作按钮。模式不再限制(进页面即用),
// 遥控器也不再让位——面板和遥控器可以同时操作,两边各发各的。
const bool ok = !ctx()->estopTriggered;
for (QPushButton* b : m_moveButtons) b->setEnabled(ok);
for (QPushButton* b : m_endButtons) b->setEnabled(ok);
}
void ArmPage::onReturnToggled(bool on)
@@ -206,20 +219,29 @@ void ArmPage::refresh()
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(";"));
// 未收到对应报文的数值统一显示 "--"(dashIf)
m_chassisCard->setField(0, dashIf(t.hasBattery, QString("%1%").arg(t.soc)));
m_chassisCard->setField(1, dashIf(t.hasBattery, QString("%1V").arg(t.volt, 0, 'f', 0)));
m_chassisCard->setFaults(t.chassisFaults);
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_washCard->setField(0, dashIf(t.hasWash, QString("%1L").arg(t.levelA, 0, 'f', 0)));
m_washCard->setField(1, dashIf(t.hasWash, QString("%1L").arg(t.levelFoam, 0, 'f', 0)));
m_washCard->setAlarm(0, t.levelALow);
m_washCard->setAlarm(1, t.levelBLow);
m_washCard->setFaults(washCardFaults(t));
m_gasCard->setField(0, gasHostLabel(t));
m_gasCard->setField(1, t.gasType); // 有毒物种类,未收到报文时本身就是 "--"
m_gasCard->setField(2, t.gasLevel); // 有毒物等级
m_gasCard->setAlarm(0, t.gasHost == "fault");
m_gasCard->setFaults(t.detectorFaults);
// 本卡没有故障行:机械臂那四帧只有位置/姿态/关节角,协议里没有机械臂故障信号
m_armCard->setField(0, t.pos);
m_armCard->setField(1, t.pose);
m_armCard->setField(2, QString("%1").arg(t.vel, 0, 'f', 1));
m_armCard->setField(2, dashIf(t.hasArmPose, 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));
m_armCard->setField(3 + i, dashIf(t.hasJoints, QString("%1°").arg(t.js[i], 0, 'f', 0)));
// 回位状态机
if (t.returnState != m_prevReturnState) {