150 lines
6.8 KiB
C++
150 lines
6.8 KiB
C++
#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
|