Files
QT_wuhan_YT/comm/car.h
T
2026-10-14 10:33:58 +08:00

150 lines
6.8 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 CAR_H
#define CAR_H
#include <QByteArray>
#include <QObject>
#include <QSet>
#include <QString>
#include <QTimer>
#include <QVector>
#include "global.h"
class QUdpSocket;
// 摇杆量协议范围 0~4096,中位 2048(分类一各轴、Vehi_gear/Vehi_turning 通用)
static const int kRcAxisMid = 2048;
// CAN 反馈只给故障码,这里带上系统与中文描述:
// system 取界面故障历史既有的四个分组名,desc 供页面直接显示,code 供故障查询追溯。
struct CanFault {
QString system;
QString code;
QString desc;
};
// ===================== 车端通信层(CAN 报文经 /dev/ttyS7 串口收发) =====================
// 依据《洗消机器人遥控器通信协议20260810》sheet RC 实现的 19 条报文:
// 上行 分类一 7 条(遥控器 → 车端):Chassis_ControlCmd / Arm_ControlCmd1 / Arm_ControlCmd2 /
// Decontam_ControlCmd / Decontam_DebugCmd / Detector_ControlCmd / Emergency_Cmd,
// 按协议「报文周期时间」列分 50 / 100 / 1000ms 三组重发;
// 下行 分类二/三 12 条(车端 → 遥控器):底盘 4 条、机械臂 4 条、洗消 2 条、气体检测仪 2 条,
// 按 canId 分流转 handleFrame() 写入 Telemetry。
// 全部为 29 位扩展帧、信号一律 Intel(小端)位序。
// 传输走 UDP:bind 本机 9000 端口收下行反馈,上行命令发往 127.0.0.1:9001。
// UDP 载荷统一为 18 字节:帧头 0x5AA5FF00 + canId + DLC + 8 字节数据 + 校验和。
// 通信超时判定:连续 2s 未收到任何合法帧则判为通信异常(最慢的下行周期 1000ms)。
class CarCommunication : public QObject
{
Q_OBJECT
public:
explicit CarCommunication(Telemetry* tel, QObject* parent = nullptr);
~CarCommunication() override;
bool start();
void stop();
// 行车/机械臂模式(面板旋钮或遥控器报文)→ Arm_ControlCmd1 的 Arm_modeCmd / Arm_enable
void setArmMode(bool arm) { m_armMode = arm; }
// ---------- 上行命令(分类一)----------
// 命令只更新本端控制状态,实际报文由周期定时器编码发送(CAN 控制帧本就是周期报文)。
// turn 非空("left"/"right")时与 dir 同时下发,支持边前进/后退边转向
void sendChassisMove(const QString& dir, double speed, const QString& turn = QString());
void sendArmMove(const QString& axis, int dir); // dir: +1 / -1 / 0(停止)
void sendArmReturn();
void sendArmPause();
void sendGasStart();
void sendGasStop();
void sendWashStart(const QString& mode); // "clean" / "disinfect"
void sendWashStop();
void sendBallValve(int valve, bool open); // valve: 1=D1, 2=D2
void sendPumpPower(const QString& pump, bool on); // "plunger"/"air"/"leaf"
void sendPumpRpm(const QString& pump, int rpm);
void sendSetParam(const QString& key, double value);
void sendSelfCheckStart(); // 启动本端自检序列(不发 CAN)
void sendEstop();
void sendEstopReset();
signals:
void telemetryUpdated(); // 任意遥测包到达(页面据此刷新)
void commOkChanged(bool ok); // 通信状态变化
void selfCheckItem(int index, bool ok); // 自检单项结果(0~9)
void selfCheckDone(bool allOk); // 自检完成
void faultAppended(const QString& system, const QString& code, const QString& desc);
private slots:
void onDatagram();
void onSendFast(); // 50ms 组:底盘 / 机械臂 / 急停
void onSendMid(); // 100ms 组:洗消指令 / 洗消调试
void onSendSlow(); // 1000ms 组:气体检测仪
void onHeartbeatTimeout();
void onSelfCheckTick();
private:
// 收包:按 canId 分流;发包:18 字节封帧后写串口
void handleFrame(quint32 canId, const quint8* d);
void sendFrame(quint32 canId, const quint8* data);
void cacheFaults();
void setCommOk(bool ok);
Telemetry* m_tel = nullptr;
QUdpSocket* m_sock = nullptr;
QTimer* m_hbTimer = nullptr;
QTimer* m_fastTimer = nullptr;
QTimer* m_midTimer = nullptr;
QTimer* m_slowTimer = nullptr;
QTimer* m_selfCheckTimer = nullptr;
bool m_lastCommOk = true;
bool m_armMode = false;
// 本地自检序列(CAN 矩阵无自检报文,见 .cpp TODO)
int m_selfCheckIndex = 0;
bool m_selfCheckFault = true;
// ---- 分类一 上行控制状态 ----
// Chassis_ControlCmd 0x18208081
quint16 m_gear = kRcAxisMid; // Vehi_gear:后 0 / 中 2048 / 前 4096
quint16 m_turning = kRcAxisMid; // Vehi_turning:左 0 / 中 2048 / 右 4096
quint16 m_targetSpd = 0; // Vehi_TargetSpd,精度 0.01,0~500(0~5.00 km/h)
// Arm_ControlCmd1/2 0x18218081 / 0x18228081 —— 六轴位 0~4096
quint16 m_updown = kRcAxisMid;
quint16 m_leftright = kRcAxisMid;
quint16 m_frontrear = kRcAxisMid;
quint16 m_roll = kRcAxisMid;
quint16 m_pitch = kRcAxisMid;
quint16 m_yaw = kRcAxisMid;
quint8 m_homingPause = 0x55; // System_homing_pause:0xAA=系统回位 0x55=暂停回位
// Decontam_ControlCmd 0x18238081
// 四个参数缓存与 config.ini 的 param/* 同源:构造时按存盘值初始化,
// 页面保存时经 sendSetParam 更新,周期帧只读缓存(不再每帧读文件)。
quint8 m_decontamMode = 0; // 2=手动消除 3=手动消毒
bool m_decontamStart = false;
int m_plungerFlow = 20; // PlungerPump_flow,L/min,0~24(param/pump_flow)
int m_foamRatio = 6; // Expansion_ratioCmd,倍,6~12(param/foam_ratio)
int m_foamPercent = 3; // Foam_ratio,%,0~10(param/foam_percent)
int m_airFlow = 100; // AirComp_flow,L/min,0~340(param/air_flow)
// Decontam_DebugCmd 0x18248081
bool m_debugMode = false; // 0=正常模式 1=调试模式(球阀/泵操作置 1)
bool m_plungerOn = false, m_airOn = false, m_vaneOn = false;
bool m_d1Open = false, m_d2Open = false;
quint16 m_airRpm = 0, m_plungerRpm = 0, m_vaneRpm = 0;
// Detector_ControlCmd 0x18258081 / Emergency_Cmd 0x18268081
quint8 m_detectorCmd = 0x55; // 0xAA=启动检测 0x55=停止检测
quint8 m_emergStop = 0; // 0x55=急停 0=正常
// ---- 下行故障缓存 ----
// 底盘故障由 VSFB1~4 四帧共同构成,各自重建后再合并,避免互相覆盖。
// 气体检测仪告警周期 1000ms、洗消故障 200ms,分开存放,否则后到的会把先到的清掉。
QVector<CanFault> m_vsf1Faults, m_vsf2Faults, m_vsf3Faults, m_vsf4Faults;
QVector<CanFault> m_washFaults, m_pumpFaults, m_detectorFaults;
QSet<QString> m_reportedFaults; // 已记入故障历史的“系统|码”,周期性报文只上报新增故障
};
#endif // CAR_H