Files
QT_wuhan_YT/app/global.h
T
2026-10-16 09:06:03 +08:00

322 lines
14 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.
#ifndef GLOBAL_H
#define GLOBAL_H
#include <QString>
#include <QStringList>
#include <QVector>
#include <QWidget>
#include <QTimer>
#include <QVariant>
#include <QColor>
class QApplication;
// ===================== 画布与全局常量 =====================
// 屏幕分辨率(1920×1200);窗口按此固定尺寸,页面布局靠 layout 自适应,
// 富余的垂直空间由各页的 addStretch 分配(控件像素尺寸与字号不随屏幕缩放)
static const int SCREEN_W = 1920;
static const int SCREEN_H = 1200;
// ===================== 工业风格配色体系(QSS 十六进制) =====================
namespace C {
const QString BG = "#161C23"; // 主背景:窗口画布底色
const QString PANEL = "#242E3A"; // 面板背景:卡片/弹窗/顶条/底条
const QString PANEL_HI = "#2D3947"; // 面板亮色:按钮常态、表头、进度条底
const QString BORDER = "#3D4A59"; // 分割线:边框、表格线
const QString TEXT = "#E6EDF3"; // 主文字:标题、正文、数值
const QString TEXT_SUB = "#9AA7B4"; // 次文字:说明、单位、标签
const QString PRIMARY = "#3D8BFD"; // 强调主色:主按钮、选中、焦点、进度条
const QString SUCCESS = "#36C75A"; // 成功/运行:运行、开启、到位
const QString WARNING = "#F5A623"; // 警告:提醒、待确认
const QString DANGER = "#E5484D"; // 危险/故障:急停、故障、警示
const QString DISABLED = "#56636F"; // 禁用:不可操作控件底色
const QString DISABLED_T = "#6B7A88"; // 禁用文字
}
// ===================== 操作模式 =====================
// 面板机械旋钮切换:行车模式 / 机械臂模式
enum class Mode { Drive = 0, Arm = 1 };
// ===================== 页面枚举(QStackedWidget 索引) =====================
enum PageId {
PageBoot = 0, // ③ 开机密码
PageWarning, // 密码警告
PageMgmtLogin, // 密码管理登录
PageMgmt, // 密码管理
PageReset, // 密码重置
PageSelfCheck, // ④ 自检
PageHome, // ⑤ 系统首页面(自检完成后进入)
PageJob, // ⑥ 作业选择
PageChassis, // ⑦ 机器人底盘
PageArm, // ⑧ 机械臂
PageGas, // ⑨ 气体检测仪
PageClean, // ⑩ 消除作业
PageDisinfect, // ⑪ 消毒作业
PageDebug, // ⑫ 调试维护
PageFault, // ⑬ 故障查询
PageCount
};
// ===================== 遥测数据(车载端 → UI) =====================
// 由通信层解析车端反馈报文后填充,页面刷新时读取。
// 这里不留任何演示初值:数值字段只由报文写入,配套的 has* 标志在收到对应报文时置位,
// 页面按 dashIf() 判断“还没有值”,未收到时显示 "--"。
struct Telemetry {
// 底盘
int soc = 0; // 电量 %
double volt = 0.0; // 电压 V
double speed = 0.0; // 车速 km/h
bool handbrake = false; // 手刹
int driveMode = 0; // 行车/机械臂模式:0=行车 1=机械臂(遥控器拨钮→串口→底盘报文 mode)
int rdyStatus = 0; // 底盘 ready:0=初始 1=高压上电完成 2=准备就绪
int gearPos = 0; // 挡位:0=N 1=D 2=R
int parking = 0; // 驻车:0=未驻车 1=左电机 2=右电机 3=完全驻车
int awdMode = 0; // 四驱模式:0=二驱 1=四驱 2=四驱锁定
double steerAngle = 0.0; // 方向盘角度
int alignStatus = 0; // 角度对中状态:0x11=对中失败、0xEE/0x55=成功、其它=未对中
QStringList chassisFaults; // 底盘故障(多条 2s 轮换)
// 机械臂
QVector<double> js{0, 0, 0, 0, 0, 0}; // 关节角 J1~J6(°)
QString pos = "--"; // 末端位置 XYZ
QString pose = "--"; // 姿态 RX/RY/RZ
double vel = 0.0; // 末端速度
QString returnState = "idle";// 回位状态 idle/returning/done/fault
bool armHomed = false; // 是否已回位(用于底盘“机械臂未回位”告警)
// 洗消
QString washMode = "--"; // 手动消除 / 手动消毒
bool washStart = false; // 洗消启停反馈
double flowA = 0.0; // A 药剂流量 L/min
double flowB = 0.0; // B 药剂流量 L/min
double gasFlow = 0.0; // 气体流量 L/min
double press = 0.0; // 管路压力 MPa
double airPress = 0.0; // 空压机压力 MPa
double foam = 0.0; // 发泡倍数
double flowPlungerFb = 0.0; // 柱塞泵流量反馈 L/min
double flowAirFb = 0.0; // 空压机流量反馈 L/min
double flowVaneFb = 0.0; // 叶片泵流量反馈 L/min
QStringList washFaults; // 洗消故障代码
// 液位
double levelA = 0.0; // 清水/药剂液位 L
double levelFoam = 0.0; // 泡沫液位 L
bool levelALow = false; // A组分/清水液位低(A_LiquidLevel_Low)
bool levelBLow = false; // B组分/泡沫液位低(B_LiquidLevel_Low)
// 气体检测仪
QString gasHost; // 主机状态 standby/detecting/fault,空=未收到
QString gasType = "--"; // 有毒物种类
QString gasLevel = "--"; // 有毒物等级
double gasConc = 0.0; // 有毒物浓度 ppb
// 球阀 D1/D2
bool d1open = false; // D1 开启到位
bool d1close = true; // D1 关闭到位
bool d2open = false; // D2 开启到位
bool d2close = true; // D2 关闭到位
// 泵
bool plunger = false; // 柱塞泵上电
bool air = false; // 空压机上电
bool leaf = false; // 叶片泵上电
QStringList pumpFaults; // 泵故障代码
// 气体检测仪故障。单列一份、不并进 washFaults:洗消页底栏的“系统故障”灯
// 只看洗消系统与泵,气体检测仪的告警要归到它自己的卡片上。
QStringList detectorFaults;
// 遥控器(24 字节二进制帧,见 comm/uart.h)
bool rcLinkOk = false; // 遥控器链路是否在线
int rcBattery = 0; // 遥控器电量 %
bool rcDriveMode = false; // bit0 行车模式
bool rcArmMode = false; // bit1 机械臂模式
bool rcArmEnabled = false; // bit2 机械臂使能
bool rcChassisEnabled = false;// bit3 底盘使能
bool rcEstop = false; // bit4 急停
int rcGear = 2048; // 整车档位(底盘 Y)0~4096,中位 2048
int rcSteer = 2048; // 整车转向(底盘 X)
int rcPosZ = 2048; // 末端位置上下
int rcPosX = 2048; // 末端位置左右
int rcPosY = 2048; // 末端位置前后
int rcRoll = 2048; // 末端姿态横滚
int rcPitch = 2048; // 末端姿态俯仰
int rcYaw = 2048; // 末端姿态偏航
// 全局
bool commOk = true; // 通信状态
bool estop = false; // 急停触发
// 顶部左区固定显示的一行通信状态,由 CarCommunication 渲染:
// 链路正常且 All_Comm_FaultCode=0 → “系统通信正常”;有码 → 该码的文案
// (“机械臂通信异常”…);链路断开、没有码 → “通信异常”。
// 各项子系统故障明细不在这里,而是各自进对应卡片的“故障”行。
QString commText = QString::fromUtf8("系统通信正常");
int commCode = 0; // All_Comm_FaultCode 原值,0 = 通信正常
// ---- 各报文是否已收到 ----
// CarCommunication 每解析到一条报文就置位对应的 has*,页面按它决定“还没有值”时显示 "--"。
// 按“一条报文覆盖哪些显示项”分组,而不是每个字段一个标志。
bool hasBattery = false; // 0x18308180 底盘状态1:电量 / 电压
bool hasSpeed = false; // 0x18318180 底盘状态2:车速 / 手刹 / Ready状态
bool hasChassis4 = false; // 0x183B8180 底盘状态4:挡位 / 驻车 / 四驱 / 方向盘角度
bool hasArmPose = false; // 0x18338180 机械臂状态2:末端速度
bool hasJoints = false; // 0x18348180 / 0x18358180:关节角 J1~J6
bool hasWash = false; // 0x18368180 洗消状态1:液位 / 流量 / 发泡倍数
bool hasWashPress= false; // 0x18378180 洗消状态2:管路压力 / 空压机压力
bool hasGasHost = false; // 0x18388180 检测仪状态1:主机状态
bool hasGasConc = false; // 0x18398180 检测仪状态2:有毒物浓度
};
// 遥测未收到(has* 为 false)时统一显示 "--"
inline QString dashIf(bool has, const QString& text)
{
return has ? text : QStringLiteral("--");
}
// 气体检测仪主机状态 → 显示文案
inline QString gasHostLabel(const Telemetry& t)
{
if (!t.hasGasHost) return QStringLiteral("--");
return t.gasHost == "detecting" ? QString::fromUtf8("检测中")
: t.gasHost == "fault" ? QString::fromUtf8("故障")
: QString::fromUtf8("待机");
}
// 洗消卡片“故障”行的内容:洗消系统与泵都算它,气体检测仪另走一份 detectorFaults。
inline QStringList washCardFaults(const Telemetry& t)
{
return t.washFaults + t.pumpFaults;
}
// ---- 底盘的几个枚举信号 → 显示文案(取值见协议「信号值描述」列) ----
inline QString gearLabel(int v)
{
return v == 1 ? QString::fromUtf8("D挡")
: v == 2 ? QString::fromUtf8("R挡")
: QString::fromUtf8("N挡");
}
inline QString parkingLabel(int v)
{
switch (v) {
case 1: return QString::fromUtf8("左电机驻车");
case 2: return QString::fromUtf8("右电机驻车");
case 3: return QString::fromUtf8("完全驻车");
default: return QString::fromUtf8("未驻车");
}
}
inline QString awdLabel(int v)
{
return v == 1 ? QString::fromUtf8("四驱")
: v == 2 ? QString::fromUtf8("四驱锁定")
: QString::fromUtf8("二驱");
}
inline QString rdyLabel(int v)
{
return v == 1 ? QString::fromUtf8("高压上电完成")
: v == 2 ? QString::fromUtf8("准备就绪")
: QString::fromUtf8("初始状态");
}
// Angle_alignment_status:0 是"还没做过",与失败要分清楚。
// 文案比协议描述短一点("未进行过角度对中"→"未进行过对中"):标签已经写了"角度对中状态",
// 值里再重复一遍就溢出行宽了(底盘卡正文区 548px)。
inline QString alignLabel(int v)
{
switch (v) {
case 0x11: return QString::fromUtf8("角度对中失败");
case 0xEE: return QString::fromUtf8("角度对中成功");
case 0x55: return QString::fromUtf8("已对中成功");
default: return QString::fromUtf8("未进行过对中");
}
}
// ===================== 全局闪烁节拍 =====================
// 界面上有好几处在“异常闪烁”:顶部通信状态、卡片故障行、告警横幅、底栏指示灯、
// 自检结果……各自起定时器的话相位互不相同,同一屏上会各闪各的。
// 这里做成**一个**公共节拍,所有闪烁都挂在它上面:整屏同时亮、同时灭。
// 要改闪烁快慢只改这一处的 interval(500ms)。
class BlinkBeat : public QObject
{
Q_OBJECT
public:
static BlinkBeat* instance();
bool on() const { return m_on; } // 当前是“亮”还是“灭”,供刚订阅上来的对齐相位
signals:
void toggled(bool on);
private:
explicit BlinkBeat(QObject* parent = nullptr);
QTimer* m_timer = nullptr;
bool m_on = true;
};
// ===================== 工具函数 =====================
// 启动闪烁:挂到全局节拍上,每拍翻转一次动态属性(40% ↔ 100% 透明度由 QSS 规则体现)
void startBlink(QWidget* w, const char* prop = "blink");
// 退订全局节拍并复位属性
void stopBlink(QWidget* w, const char* prop = "blink");
// 退出/取消按钮预设样式:被选中(悬停/按下/焦点)时红底白字
QString cancelButtonStyle(int fontPx = 60);
// ===================== 本机按键 =====================
// 面板只提供 5 个键:Tab、Shift+Tab、空格、方向上、方向下。
// 新增按键或调整键位只改这一处。
namespace Keys {
inline bool tab(int k) { return k == Qt::Key_Tab; }
inline bool backtab(int k) { return k == Qt::Key_Backtab; } // Shift+Tab
inline bool shifted(int mods) { return (mods & Qt::ShiftModifier) != 0; }
inline bool space(int k) { return k == Qt::Key_Space; }
inline bool up(int k) { return k == Qt::Key_Up; }
inline bool down(int k) { return k == Qt::Key_Down; }
}
// ===================== 按钮焦点(选中)光圈 =====================
// 全局事件过滤器:任意 QPushButton 获得焦点时,在其四周加一圈发光;
// 同时把"触摸/点击"与"Tab"归一到同一个焦点,并清除触摸残留在按钮上的悬停态,
// 保证任意时刻只有一个按钮呈选中样式(新的操作覆盖原来的)。
class ButtonFocusGlow : public QObject
{
Q_OBJECT
public:
explicit ButtonFocusGlow(const QColor& glow = QColor("#3D8BFD"), QObject* parent = nullptr);
protected:
bool eventFilter(QObject* obj, QEvent* ev) override;
private:
QColor m_glow;
};
// 为整个应用安装按钮焦点光圈
void installButtonFocusGlow(QApplication* app);
// ===================== 方向键(旋钮)隔离 =====================
// 上/下方向键在本机是"旋钮"键位,只由 ParamControl 用来调值。
// 这个全局过滤器把"焦点在按钮上时"的方向键吞掉,方向键只做调值、换焦只走 Tab。
class ArrowKeyGuard : public QObject
{
Q_OBJECT
public:
explicit ArrowKeyGuard(QObject* parent = nullptr);
protected:
bool eventFilter(QObject* obj, QEvent* ev) override;
};
// 为整个应用安装方向键隔离
void installArrowKeyGuard(QApplication* app);
// 全局 QSS 样式表
QString appStyleSheet();
#endif // GLOBAL_H