新版布局
This commit is contained in:
+92
-47
@@ -12,6 +12,12 @@
|
||||
#include <QTimer>
|
||||
#include "global.h"
|
||||
|
||||
namespace {
|
||||
// 收起姿态取全零:任一关节角绝对值超过这个角度即认为机械臂已展开。
|
||||
// 单位与 CAN 下发的关节角一致(car.cpp 直接写入 t.js,未经缩放)。
|
||||
const double kArmStowedTolDeg = 5.0;
|
||||
}
|
||||
|
||||
ChassisPage::ChassisPage(AppContext* ctx, QWidget* parent)
|
||||
: BasePage(ctx, parent)
|
||||
{
|
||||
@@ -63,16 +69,17 @@ ChassisPage::ChassisPage(AppContext* ctx, QWidget* parent)
|
||||
centerLay->setSpacing(12);
|
||||
|
||||
m_washCard = new DataCard("洗消", center);
|
||||
m_washCard->addField("A液位", "100L");
|
||||
m_washCard->addField("泡沫液位", "30L");
|
||||
m_washCard->addField("A组分/清水液位", "--");
|
||||
m_washCard->addField("泡沫箱液位", "--");
|
||||
|
||||
m_armCard = new DataCard("机械臂", center);
|
||||
m_armCard->addField("末端位置", "XYZ");
|
||||
m_armCard->addField("姿态", "RX/RY/RZ");
|
||||
m_armCard->addField("末端位置", "--");
|
||||
m_armCard->addField("末端姿态", "--");
|
||||
|
||||
m_gasCard = new DataCard("气体检测仪", center);
|
||||
m_gasCard->addField("主机状态", "待机");
|
||||
m_gasCard->addField("浓度", "0 ppb");
|
||||
m_gasCard->addField("主机状态", "--");
|
||||
m_gasCard->addField("有毒物种类", "--");
|
||||
m_gasCard->addField("有毒物等级", "--");
|
||||
|
||||
centerLay->addWidget(m_washCard, 1);
|
||||
centerLay->addWidget(m_armCard, 1);
|
||||
@@ -88,11 +95,15 @@ ChassisPage::ChassisPage(AppContext* ctx, QWidget* parent)
|
||||
chassisLay->setSpacing(12);
|
||||
|
||||
m_chassisCard = new DataCard("底盘状态", chassisCol);
|
||||
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("故障", "无");
|
||||
m_chassisCard->addField("底盘电量SOC", "--");
|
||||
m_chassisCard->addField("底盘电压U", "--");
|
||||
m_chassisCard->addField("底盘车速V", "--");
|
||||
m_chassisCard->addField("档位状态", "--");
|
||||
m_chassisCard->addField("驻车状态", "--");
|
||||
m_chassisCard->addField("四驱模式", "--");
|
||||
m_chassisCard->addField("底盘Ready状态", "--");
|
||||
m_chassisCard->addField("方向盘角度", "--");
|
||||
m_chassisCard->addField("角度对中状态", "--");
|
||||
chassisLay->addWidget(m_chassisCard, 1);
|
||||
main->addWidget(chassisCol, 1); // 与中间卡片列平均分配中间区域
|
||||
main->addSpacing(17); // 底盘列 ↔ 车速设置列:由 32 减小到 17(底盘列整体右移 15px)
|
||||
@@ -119,7 +130,6 @@ ChassisPage::ChassisPage(AppContext* ctx, QWidget* parent)
|
||||
root->addLayout(main, 1);
|
||||
|
||||
m_statusStrip = new StatusStrip(ctx, this);
|
||||
m_statusStrip->setModeVisible(false); // 本页固定行车模式,底部不显示模式徽标
|
||||
connect(m_statusStrip, &StatusStrip::backClicked, this, [this]() { emit navigate(PageJob); });
|
||||
root->addWidget(m_statusStrip);
|
||||
|
||||
@@ -132,7 +142,14 @@ ChassisPage::ChassisPage(AppContext* ctx, QWidget* parent)
|
||||
connect(ctx->comm(), &CarCommunication::telemetryUpdated, this, &ChassisPage::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() && !m_heldDirs.isEmpty())
|
||||
sendDirCommand();
|
||||
});
|
||||
updateModeGating();
|
||||
refresh();
|
||||
}
|
||||
@@ -155,20 +172,14 @@ QPushButton* ChassisPage::makeDirButton(const QString& text, const QString& dir)
|
||||
"{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, dir]() {
|
||||
if (ctx()->rcDriving()) {
|
||||
ConfirmDialog::toast(this, "遥控器操作中");
|
||||
return;
|
||||
}
|
||||
if (ctx()->mode != Mode::Drive) {
|
||||
ConfirmDialog::toast(this, "请切换至行车模式");
|
||||
return;
|
||||
}
|
||||
m_heldDirs.insert(dir);
|
||||
sendDirCommand();
|
||||
updateAlarm();
|
||||
});
|
||||
connect(b, &QPushButton::released, this, [this, dir]() {
|
||||
m_heldDirs.remove(dir);
|
||||
sendDirCommand();
|
||||
updateAlarm();
|
||||
});
|
||||
return b;
|
||||
}
|
||||
@@ -192,46 +203,80 @@ void ChassisPage::sendDirCommand()
|
||||
|
||||
void ChassisPage::updateModeGating()
|
||||
{
|
||||
// 非行车模式、急停触发或遥控器正在操作时禁用方向按钮(遥控器优先)
|
||||
const bool drive = (ctx()->mode == Mode::Drive) && !ctx()->estopTriggered && !ctx()->rcDriving();
|
||||
// 现在只有**急停**会禁用方向按钮:模式不再限制(进页面即用),遥控器也不再让位——
|
||||
// 面板和遥控器可以同时操作,两边各发各的,由车端处理。
|
||||
const bool ok = !ctx()->estopTriggered;
|
||||
for (QPushButton* b : m_dirButtons)
|
||||
b->setEnabled(drive);
|
||||
b->setEnabled(ok);
|
||||
|
||||
// 让位时清掉本地按住状态:按钮被禁用后不会再收到 released,否则方向会被一直挂住。
|
||||
// 让位给遥控器时不补发 stop,否则会覆盖遥控器刚下发的那条指令。
|
||||
if (!drive && !m_heldDirs.isEmpty()) {
|
||||
// 急停把按钮禁掉时清掉按住状态并补一条 stop。(Qt 禁用时会补发 released,
|
||||
// 各按钮自己那一遍已经发过了,这里只是兜底。)
|
||||
if (!ok && !m_heldDirs.isEmpty()) {
|
||||
m_heldDirs.clear();
|
||||
if (!ctx()->rcDriving())
|
||||
ctx()->comm()->sendChassisMove("stop", 0);
|
||||
ctx()->comm()->sendChassisMove("stop", 0);
|
||||
}
|
||||
|
||||
updateAlarm();
|
||||
}
|
||||
|
||||
// 任一关节角偏离收起姿态(全零)即认为机械臂已展开
|
||||
bool ChassisPage::armNotStowed() const
|
||||
{
|
||||
const QVector<double>& js = ctx()->telemetry.js;
|
||||
for (double a : js)
|
||||
if (a > kArmStowedTolDeg || a < -kArmStowedTolDeg)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 面板方向键按住,或遥控器正在推杆,都算正在驱动底盘
|
||||
bool ChassisPage::chassisDriving() const
|
||||
{
|
||||
return !m_heldDirs.isEmpty() || ctx()->rcDriving();
|
||||
}
|
||||
|
||||
// 通信异常优先;其次是“机械臂已展开且正在驱动底盘”
|
||||
void ChassisPage::updateAlarm()
|
||||
{
|
||||
if (!ctx()->telemetry.commOk)
|
||||
m_banner->showAlarm("通信异常");
|
||||
else if (armNotStowed() && chassisDriving())
|
||||
m_banner->showAlarm("机械臂未回位,请谨慎操作");
|
||||
else
|
||||
m_banner->clear();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
updateAlarm();
|
||||
|
||||
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());
|
||||
// 未收到对应报文的数值统一显示 "--"(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->setField(2, dashIf(t.hasSpeed, QString("%1 km/h").arg(t.speed, 0, 'f', 2)));
|
||||
m_chassisCard->setField(3, dashIf(t.hasChassis4, gearLabel(t.gearPos)));
|
||||
m_chassisCard->setField(4, dashIf(t.hasChassis4, parkingLabel(t.parking)));
|
||||
m_chassisCard->setField(5, dashIf(t.hasChassis4, awdLabel(t.awdMode)));
|
||||
m_chassisCard->setField(6, dashIf(t.hasSpeed, rdyLabel(t.rdyStatus)));
|
||||
m_chassisCard->setField(7, dashIf(t.hasChassis4, QString("%1°").arg(t.steerAngle, 0, 'f', 0)));
|
||||
m_chassisCard->setField(8, dashIf(t.hasChassis4, alignLabel(t.alignStatus)));
|
||||
m_chassisCard->setFaults(t.chassisFaults);
|
||||
|
||||
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_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));
|
||||
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);
|
||||
}
|
||||
|
||||
void ChassisPage::onSpeedChanged(double v)
|
||||
|
||||
Reference in New Issue
Block a user