简短文件名
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
#include "chassis.h"
|
||||
#include "titlebar.h"
|
||||
#include "statusstrip.h"
|
||||
#include "alarmbanner.h"
|
||||
#include "datacard.h"
|
||||
#include "paramcontrol.h"
|
||||
#include "udpcommunication.h"
|
||||
#include "confirmdialog.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
#include "global.h"
|
||||
|
||||
ChassisPage::ChassisPage(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);
|
||||
|
||||
// 左控制列(垂直居中 + 平均分布)
|
||||
QWidget* left = new QWidget(this);
|
||||
QVBoxLayout* leftLay = new QVBoxLayout(left);
|
||||
leftLay->setContentsMargins(0, 0, 0, 0);
|
||||
leftLay->setSpacing(8);
|
||||
|
||||
QPushButton* fwd = makeDirButton("前进", "fwd");
|
||||
QPushButton* back = makeDirButton("后退", "back");
|
||||
QPushButton* leftT = makeDirButton("左转向", "left");
|
||||
QPushButton* rightT = makeDirButton("右转向", "right");
|
||||
m_dirButtons << fwd << back << leftT << rightT;
|
||||
|
||||
leftLay->addStretch(1);
|
||||
leftLay->addWidget(fwd);
|
||||
leftLay->addStretch(1);
|
||||
leftLay->addWidget(back);
|
||||
leftLay->addStretch(1);
|
||||
leftLay->addWidget(leftT);
|
||||
leftLay->addStretch(1);
|
||||
leftLay->addWidget(rightT);
|
||||
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_washCard = new DataCard("洗消", center);
|
||||
m_washCard->addField("A液位", "100L");
|
||||
m_washCard->addField("泡沫液位", "30L");
|
||||
|
||||
m_armCard = new DataCard("机械臂", center);
|
||||
m_armCard->addField("末端位置", "XYZ");
|
||||
m_armCard->addField("姿态", "RX/RY/RZ");
|
||||
|
||||
m_gasCard = new DataCard("气体检测仪", center);
|
||||
m_gasCard->addField("主机状态", "待机");
|
||||
m_gasCard->addField("浓度", "0 ppb");
|
||||
|
||||
centerLay->addWidget(m_washCard, 1);
|
||||
centerLay->addWidget(m_armCard, 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_chassisCard = new DataCard("底盘状态", right);
|
||||
m_chassisCard->addField("电量SOC", "85%");
|
||||
m_chassisCard->addField("电压U", "360V");
|
||||
m_chassisCard->addField("车速V", "3.45 km/h");
|
||||
m_chassisCard->addField("手刹", "有效");
|
||||
m_chassisFieldFault = m_chassisCard->addField("故障", "无");
|
||||
rightLay->addWidget(m_chassisCard, 1);
|
||||
|
||||
// 车速设置
|
||||
double speed = ctx->getDouble(ctx->keySpeed(), 4.5);
|
||||
m_speed = new ParamControl("车速设置", "km/h", 0.5, 0.0, 10.0, false, false, right);
|
||||
m_speed->setValue(speed);
|
||||
m_speed->setStyleSheet("background:transparent;");
|
||||
connect(m_speed, &ParamControl::valueChanged, this, &ChassisPage::onSpeedChanged);
|
||||
rightLay->addWidget(m_speed);
|
||||
|
||||
right->setFixedWidth(380);
|
||||
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);
|
||||
|
||||
// 车速自动保存(1s 防抖)
|
||||
m_saveTimer = new QTimer(this);
|
||||
m_saveTimer->setSingleShot(true);
|
||||
m_saveTimer->setInterval(1000);
|
||||
connect(m_saveTimer, &QTimer::timeout, this, &ChassisPage::onSpeedSaved);
|
||||
|
||||
connect(ctx->comm(), &UdpCommunication::telemetryUpdated, this, &ChassisPage::refresh);
|
||||
connect(ctx, &AppContext::modeChanged, this, [this](Mode) { updateModeGating(); });
|
||||
connect(ctx, &AppContext::estopChanged, this, [this](bool) { updateModeGating(); });
|
||||
updateModeGating();
|
||||
refresh();
|
||||
}
|
||||
|
||||
QPushButton* ChassisPage::makeDirButton(const QString& text, const QString& dir)
|
||||
{
|
||||
QPushButton* b = button(text, "", this);
|
||||
b->setFixedSize(180, 150);
|
||||
b->setStyleSheet(QString("font-size:26px;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, dir]() {
|
||||
if (ctx()->mode != Mode::Drive) {
|
||||
ConfirmDialog::toast(this, "请切换至行车模式");
|
||||
return;
|
||||
}
|
||||
ctx()->comm()->sendChassisMove(dir, ctx()->getDouble(ctx()->keySpeed(), 4.5));
|
||||
});
|
||||
connect(b, &QPushButton::released, this, [this]() {
|
||||
ctx()->comm()->sendChassisMove("stop", 0);
|
||||
});
|
||||
return b;
|
||||
}
|
||||
|
||||
void ChassisPage::updateModeGating()
|
||||
{
|
||||
// 非行车模式或急停触发时禁用方向按钮
|
||||
bool drive = (ctx()->mode == Mode::Drive) && !ctx()->estopTriggered;
|
||||
for (QPushButton* b : m_dirButtons)
|
||||
b->setEnabled(drive);
|
||||
}
|
||||
|
||||
void ChassisPage::refresh()
|
||||
{
|
||||
const Telemetry& t = ctx()->telemetry;
|
||||
|
||||
// 机械臂未回位 / 通信异常告警
|
||||
if (!t.commOk) {
|
||||
m_banner->showAlarm("通信异常");
|
||||
} else if (!t.armHomed && t.returnState != "idle") {
|
||||
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, QString("%1 km/h").arg(t.speed, 0, 'f', 2));
|
||||
m_chassisCard->setField(3, t.handbrake ? "有效" : "无效");
|
||||
m_chassisCard->setField(m_chassisFieldFault, t.chassisFaults.isEmpty() ? "无" : t.chassisFaults.join(";"));
|
||||
m_chassisCard->setAlarm(m_chassisFieldFault, !t.chassisFaults.isEmpty());
|
||||
|
||||
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_armCard->setField(0, t.pos);
|
||||
m_armCard->setField(1, t.pose);
|
||||
m_gasCard->setField(0, t.gasHost == "detecting" ? "检测中" : (t.gasHost == "fault" ? "故障" : "待机"));
|
||||
m_gasCard->setField(1, QString("%1 ppb").arg(t.gasConc, 0, 'f', 0));
|
||||
}
|
||||
|
||||
void ChassisPage::onSpeedChanged(double v)
|
||||
{
|
||||
// 1s 防抖后自动保存
|
||||
m_saveTimer->start();
|
||||
ctx()->comm()->sendSetParam(ctx()->keySpeed(), v);
|
||||
}
|
||||
|
||||
void ChassisPage::onSpeedSaved()
|
||||
{
|
||||
ctx()->setDouble(ctx()->keySpeed(), m_speed->value());
|
||||
ConfirmDialog::toast(this, "车速已保存");
|
||||
}
|
||||
Reference in New Issue
Block a user