增加通讯协议

This commit is contained in:
xu
2026-10-14 09:59:42 +08:00
parent 32878a9a80
commit 950e9e6c9e
102 changed files with 5538 additions and 2679 deletions
+81 -24
View File
@@ -4,7 +4,7 @@
#include "alarmbanner.h"
#include "datacard.h"
#include "paramcontrol.h"
#include "udpcommunication.h"
#include "car.h"
#include "confirmdialog.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
@@ -29,13 +29,13 @@ ChassisPage::ChassisPage(AppContext* ctx, QWidget* parent)
QHBoxLayout* main = new QHBoxLayout();
main->setContentsMargins(36, 16, 36, 16);
main->setSpacing(32);
main->setSpacing(0); // 各段间距改用显式 addSpacing,便于单独调整(底盘列位置见各段注释)
// 左控制列(垂直居中 + 平均分布)
QWidget* left = new QWidget(this);
QVBoxLayout* leftLay = new QVBoxLayout(left);
leftLay->setContentsMargins(0, 0, 0, 0);
leftLay->setSpacing(8);
leftLay->setContentsMargins(20, 20, 0, 0);
leftLay->setSpacing(30);
QPushButton* fwd = makeDirButton("前进", "fwd");
QPushButton* back = makeDirButton("后退", "back");
@@ -54,6 +54,7 @@ ChassisPage::ChassisPage(AppContext* ctx, QWidget* parent)
leftLay->addStretch(1);
left->setFixedWidth(180);
main->addWidget(left);
main->addSpacing(32);
// 中央卡片区(洗消/机械臂/气体检测仪)
QWidget* center = new QWidget(this);
@@ -76,36 +77,49 @@ ChassisPage::ChassisPage(AppContext* ctx, QWidget* parent)
centerLay->addWidget(m_washCard, 1);
centerLay->addWidget(m_armCard, 1);
centerLay->addWidget(m_gasCard, 1);
// 中间区域由「卡片列」与「底盘状态列」平均分配(两列拉伸因子都为 1)
main->addWidget(center, 1);
main->addSpacing(47); // 中间卡片列 ↔ 底盘列:由 32 加大到 47
// 右参数区
QWidget* right = new QWidget(this);
QVBoxLayout* rightLay = new QVBoxLayout(right);
rightLay->setContentsMargins(0, 0, 0, 0);
rightLay->setSpacing(12);
// 底盘状态列
QWidget* chassisCol = new QWidget(this);
QVBoxLayout* chassisLay = new QVBoxLayout(chassisCol);
chassisLay->setContentsMargins(0, 0, 0, 0);
chassisLay->setSpacing(12);
m_chassisCard = new DataCard("底盘状态", right);
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("故障", "无");
rightLay->addWidget(m_chassisCard, 1);
chassisLay->addWidget(m_chassisCard, 1);
main->addWidget(chassisCol, 1); // 与中间卡片列平均分配中间区域
main->addSpacing(17); // 底盘列 ↔ 车速设置列:由 32 减小到 17(底盘列整体右移 15px)
// 车速设置列(垂直居中)
QWidget* right = new QWidget(this);
QVBoxLayout* rightLay = new QVBoxLayout(right);
rightLay->setContentsMargins(0, 0, 0, 0);
rightLay->setSpacing(12);
// 车速设置
double speed = ctx->getDouble(ctx->keySpeed(), 4.5);
m_speed = new ParamControl("车速设置", "km/h", 0.5, 0.0, 10.0, false, false, right);
// 协议 Vehi_TargetSpd:精度 0.01、0~500 → 物理范围 0~5.00 km/h
// 每档 = 显示精度的最小单位(1 位小数 → 0.1),比协议的 0.01 粗,够用
m_speed = new ParamControl("车速设置", "km/h", 0.1, 0.0, 5.0, false, false, right);
m_speed->setValue(speed);
m_speed->setStyleSheet("background:transparent;");
m_speed->setStyleSheet("ParamControl{background:transparent;}"); // 只作用于本控件,避免影响子控件
connect(m_speed, &ParamControl::valueChanged, this, &ChassisPage::onSpeedChanged);
rightLay->addStretch(1);
rightLay->addWidget(m_speed);
rightLay->addStretch(1);
right->setFixedWidth(380);
main->addWidget(right);
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);
@@ -115,38 +129,81 @@ ChassisPage::ChassisPage(AppContext* ctx, QWidget* parent)
m_saveTimer->setInterval(1000);
connect(m_saveTimer, &QTimer::timeout, this, &ChassisPage::onSpeedSaved);
connect(ctx->comm(), &UdpCommunication::telemetryUpdated, this, &ChassisPage::refresh);
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(); });
updateModeGating();
refresh();
}
void ChassisPage::showEvent(QShowEvent* ev)
{
BasePage::showEvent(ev);
// 每次进入底盘页自动切换到行车模式;遥控器在线时模式由遥控器报文决定,不抢
if (!ctx()->rc()->linkOk())
ctx()->setMode(Mode::Drive);
}
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));
b->setFixedSize(140, 100);
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, dir]() {
if (ctx()->rcDriving()) {
ConfirmDialog::toast(this, "遥控器操作中");
return;
}
if (ctx()->mode != Mode::Drive) {
ConfirmDialog::toast(this, "请切换至行车模式");
return;
}
ctx()->comm()->sendChassisMove(dir, ctx()->getDouble(ctx()->keySpeed(), 4.5));
m_heldDirs.insert(dir);
sendDirCommand();
});
connect(b, &QPushButton::released, this, [this]() {
ctx()->comm()->sendChassisMove("stop", 0);
connect(b, &QPushButton::released, this, [this, dir]() {
m_heldDirs.remove(dir);
sendDirCommand();
});
return b;
}
// 同时按住前进/后退与左/右转向时一并下发;两者都松开才停车
void ChassisPage::sendDirCommand()
{
const QString dir = m_heldDirs.contains("fwd") ? "fwd"
: m_heldDirs.contains("back") ? "back" : QString("stop");
const QString turn = m_heldDirs.contains("right") ? "right"
: m_heldDirs.contains("left") ? "left" : QString();
if (dir == "stop" && turn.isEmpty()) {
ctx()->comm()->sendChassisMove("stop", 0);
return;
}
// 仅转向(档位回中)时发 stop + turn,由车载端决定是否原地转向
const double spd = (dir == "stop") ? 0.0 : ctx()->getDouble(ctx()->keySpeed(), 4.5);
ctx()->comm()->sendChassisMove(dir, spd, turn);
}
void ChassisPage::updateModeGating()
{
// 非行车模式或急停触发时禁用方向按钮
bool drive = (ctx()->mode == Mode::Drive) && !ctx()->estopTriggered;
// 非行车模式、急停触发或遥控器正在操作时禁用方向按钮(遥控器优先)
const bool drive = (ctx()->mode == Mode::Drive) && !ctx()->estopTriggered && !ctx()->rcDriving();
for (QPushButton* b : m_dirButtons)
b->setEnabled(drive);
// 让位时清掉本地按住状态:按钮被禁用后不会再收到 released,否则方向会被一直挂住。
// 让位给遥控器时不补发 stop,否则会覆盖遥控器刚下发的那条指令。
if (!drive && !m_heldDirs.isEmpty()) {
m_heldDirs.clear();
if (!ctx()->rcDriving())
ctx()->comm()->sendChassisMove("stop", 0);
}
}
void ChassisPage::refresh()