当前位置: 首页 > news >正文

QT之键盘控制虚拟遥控系统开发总结

一、项目概述

本文总结了一个基于Qt框架开发的键盘控制虚拟遥控系统,通过WSADQE六个按键实现方向控制功能。系统模拟了真实遥控器的操作逻辑,包括前进/后退控制、左右上下转向功能。

二、核心功能实现

1. 键盘事件处理机制

系统通过重写Qt的keyPressEventkeyReleaseEvent方法实现键盘控制:

void MainWindow::keyPressEvent(QKeyEvent *event)
{// W键 - 前进if(event->key()==Qt::Key_W){movementState = FORWARD;ui->but_forward->setStyleSheet("background-color:rgb(138,43,226)");}// ...其他按键处理
}void MainWindow::keyReleaseEvent(QKeyEvent *event)
{// W键释放 - 停止前进if(event->key()==Qt::Key_W&&!event->isAutoRepeat()){movementState = STOPPED;mainThrottle = 0;ui->but_forward->setStyleSheet("background-color:white");}// ...其他按键释放处理
}

关键点:

  • 使用Qt::Key枚举识别特定按键

  • !event->isAutoRepeat()防止按键重复触发

  • 按键状态与UI元素(按钮样式)同步更新

2. 状态机设计

系统采用状态机模式管理运动状态:

// 运动状态枚举
enum MovementState {STOPPED = 0,   // 停止FORWARD = 1,   // 前进BACKWARD = 2   // 后退
};// 转向状态枚举
enum SteeringState {NONE = 0,    // 无LEFT = 1,    // 左RIGHT = 2,   // 右UP = 3,      // 上DOWN = 4     // 下
};// 状态变量
quint8 movementState = 0;     // 运动状态
quint8 steeringState = 0;     // 转向/升降状态

优势:

  • 清晰的状态定义和转换逻辑

  • 便于扩展新的控制状态

  • 组合状态处理更直观

3. 组合控制逻辑

系统实现了多种组合控制模式:

// 前进+左转组合
if(movementState == FORWARD && steeringState == LEFT)
{if(mainThrottle < maxThrottle) mainThrottle += 100;upperRudderAngle = 20;lowerRudderAngle = 20;
}// 后退+右转组合
if(movementState == BACKWARD && steeringState == RIGHT)
{if(mainThrottle > minThrottle) mainThrottle -= 50;upperRudderAngle = -20;lowerRudderAngle = -20;
}

特点:

  • 前进/后退与转向/升降可任意组合

  • 不同方向采用差异化参数调整

  • 设置了合理的油门限制范围

三、关键技术点

1. 油门控制与转向角度管理

// 油门参数
qint16 mainThrottle = 0;         // 主推进器油门值
const qint16 maxThrottle = 700;  // 最大转速限制
const qint16 minThrottle = -350; // 最小转速限制// 角度
qint8 upperRudderAngle = 0;      // 上角度
qint8 lowerRudderAngle = 0;      // 下角度
qint8 leftRudderAngle = 0;       // 左角度
qint8 rightRudderAngle = 0;      // 右角度

设计考虑:

  • 前进/后退采用非对称速度限制

  • 转向角度固定增量调整(±20度)

2. 指令生成与发送机制

// 构建控制指令
QString list = "$1RC," + throttleStr + "," + upperRudderStr + "," + lowerRudderStr + "," + leftRudderStr + "," + rightRudderStr + "^";// 发送策略
if((movementState != lastMovementState) || (steeringState != lastSteeringState))
{// 状态变化时立即发送qDebug() << "list:" << list.toLatin1();lastMovementState = movementState;lastSteeringState = steeringState;
}
else if((movementState != STOPPED) || (steeringState != NONE))
{// 持续状态时定期发送(每20次计数)commandCounter += 1;if(commandCounter == 20){qDebug() << "list:" << list.toLatin1();commandCounter = 0;}
}

优化点:

  • 状态变化时即时响应

  • 持续操作时降低发送频率

  • 采用标准指令格式($1RC开头,^结尾)

四、UI反馈设计

系统通过按钮样式变化提供操作反馈:

// 按键按下时改变样式
ui->but_forward->setStyleSheet("background-color:rgb(138,43,226)");// 按键释放时恢复默认
ui->but_forward->setStyleSheet("background-color:white");

视觉设计:

  • 不同功能使用不同颜色标识

  • 前进(紫色)、后退(黄色)、左转(红色)等

  • 即时反馈提升操作体验

五、项目总结

本键盘控制虚拟遥控系统展示了:

  1. Qt事件处理机制的有效应用

  2. 状态机设计在控制系统的实用性

  3. 组合控制逻辑的清晰实现方式

  4. 用户反馈的即时可视化设计

完整项目代码已实现核心控制功能(见文末),通过进一步优化可发展为完善的虚拟遥控平台,适用于机器人控制、无人机模拟等应用场景。

关键收获:

  • Qt键盘事件处理的正确方式

  • 复杂控制逻辑的状态管理技巧

  • 实时系统的人机交互设计要点

  • 控制指令的优化传输策略

完整项目代码

// 基于键盘控制的虚拟遥控---通过WSADQE键控制方向#include "keyevent.h"qint16 mainThrottle = 0;         // 主推进器油门值
quint8 commandCounter = 0;        // 指令发送计数器
quint8 movementState = 0;         // 运动状态(0:停止,1:前进,2:后退)
quint8 steeringState = 0;         // 转向/升降状态(0:无,1:左,2:右,3:上,4:下)
quint8 lastMovementState = 0;     // 上一次的运动状态
quint8 lastSteeringState = 0;     // 上一次的转向/升降状态
qint8 upperRudderAngle = 0;      // 上角度(默认0)
qint8 lowerRudderAngle = 0;      // 下角度(默认0)
qint8 leftRudderAngle = 0;       // 左角度(默认0)
qint8 rightRudderAngle = 0;      // 右角度(默认0)const qint16 maxThrottle = 700; // 最大转速限制
const qint16 minThrottle = -350;  // 最小转速限制// 运动状态枚举
enum MovementState {STOPPED = 0,   // 停止FORWARD = 1,   // 前进BACKWARD = 2   // 后退
};// 转向/升降状态枚举
enum SteeringState {NONE = 0,    // 无LEFT = 1,    // 左RIGHT = 2,   // 右UP = 3,      // 上DOWN = 4     // 下
};// 按键按下事件处理
void MainWindow::keyPressEvent(QKeyEvent *event)
{// W键 - 前进if(event->key()==Qt::Key_W){movementState = FORWARD; // 设置前进状态ui->but_forward->setStyleSheet("background-color:rgb(138,43,226)"); // 改变按钮颜色}// S键 - 后退if(event->key()==Qt::Key_S){movementState = BACKWARD; // 设置后退状态ui->but_back->setStyleSheet("background-color:rgb(255,255,0)");}// A键 - 左转if(event->key()==Qt::Key_A) {steeringState = LEFT;ui->but_left->setStyleSheet("background-color:rgb(255,0,0)");}// D键 - 右转if(event->key()==Qt::Key_D) {steeringState = RIGHT;ui->but_right->setStyleSheet("background-color:rgb(127,255,0)");}// Q键 - 上升if(event->key()==Qt::Key_Q) {steeringState = UP;ui->but_up->setStyleSheet("background-color:rgb(127,255,0)");}// E键 - 下潜if(event->key()==Qt::Key_E) {steeringState = DOWN;ui->but_down->setStyleSheet("background-color:rgb(127,255,0)");}// 以下是组合键处理逻辑// 仅左转(无前后运动)if(movementState == STOPPED && steeringState == LEFT)   {upperRudderAngle = 20; // 上角度设为20lowerRudderAngle = 20; // 下角度设为20}// 仅右转(无前后运动)if(movementState == STOPPED && steeringState == RIGHT)    {upperRudderAngle = -20; // 上角度设为-20lowerRudderAngle = -20; // 下角度设为-20}// 仅上升(无前后运动)if(movementState == STOPPED && steeringState == UP)    {leftRudderAngle = 20; // 左角度设为20rightRudderAngle = 20; // 右角度设为20}// 仅下潜(无前后运动)if(movementState == STOPPED && steeringState == DOWN)    {leftRudderAngle = -20; // 左角度设为-20rightRudderAngle = -20; // 右角度设为-20}// 仅前进(无转向/升降)if(movementState == FORWARD && steeringState == NONE)   //前进{mainThrottle += 100; // 增加主推转速if(mainThrottle > maxThrottle || mainThrottle < 0) //检查油门值是否超出合理范围,是否超过最大限制,是否小于0(无效值){mainThrottle = maxThrottle; // 限制转速范围}}// 前进+左转if(movementState == FORWARD && steeringState == LEFT)   {if(mainThrottle < maxThrottle){mainThrottle += 100;  // 增加主推转速}upperRudderAngle = 20;lowerRudderAngle = 20; // 设置角度为左转}// 前进+右转if(movementState == FORWARD && steeringState == RIGHT)    {if(mainThrottle < maxThrottle){mainThrottle += 100;}upperRudderAngle = -20;lowerRudderAngle = -20; // 设置角度为右转}// 前进+上升if(movementState == FORWARD && steeringState == UP)    {if(mainThrottle < maxThrottle){mainThrottle += 100;}leftRudderAngle = 20;rightRudderAngle = 20; // 设置角度为上升}// 前进+下潜if(movementState == FORWARD && steeringState == DOWN)    {if(mainThrottle < maxThrottle){mainThrottle += 100;}leftRudderAngle = -20;rightRudderAngle = -20; // 设置角度为下潜}// 仅后退if(movementState == BACKWARD && steeringState == NONE)   //后退{if(mainThrottle > minThrottle){mainThrottle -= 50; // 减小主推转速}}// 后退+左转if(movementState == BACKWARD && steeringState == LEFT)   {if(mainThrottle > minThrottle){mainThrottle -= 50;}upperRudderAngle = 20;lowerRudderAngle = 20;}// 后退+右转if(movementState == BACKWARD && steeringState == RIGHT)    {if(mainThrottle > minThrottle){mainThrottle -= 50;}upperRudderAngle = -20;lowerRudderAngle = -20;}// 后退+上升if(movementState == BACKWARD && steeringState == UP)   {if(mainThrottle > minThrottle){mainThrottle -= 50;}leftRudderAngle = 20;rightRudderAngle = 20;}// 后退+下潜if(movementState == BACKWARD && steeringState == DOWN)   {if(mainThrottle > minThrottle){mainThrottle -= 50;}leftRudderAngle = -20;rightRudderAngle = -20;}
}// 按键释放事件处理
void MainWindow::keyReleaseEvent(QKeyEvent *event)
{// W键释放 - 停止前进if(event->key()==Qt::Key_W&&!event->isAutoRepeat()){movementState = STOPPED;mainThrottle = 0; // 重置油门中位ui->but_forward->setStyleSheet("background-color:white"); // 恢复按钮颜色}// S键释放 - 停止后退if(event->key()==Qt::Key_S&&!event->isAutoRepeat()){movementState = STOPPED;mainThrottle = 0; // 重置油门中位ui->but_back->setStyleSheet("background-color:white");}// A键释放 - 停止左转if(event->key()==Qt::Key_A&&!event->isAutoRepeat()){steeringState = NONE;upperRudderAngle = 0;lowerRudderAngle = 0; // 重置角度到中位ui->but_left->setStyleSheet("background-color:white");}// D键释放 - 停止右转if(event->key()==Qt::Key_D&&!event->isAutoRepeat()){steeringState = NONE;upperRudderAngle = 0;lowerRudderAngle = 0; // 重置角度到中位ui->but_right->setStyleSheet("background-color:white");}// Q键释放 - 停止上升if(event->key()==Qt::Key_Q&&!event->isAutoRepeat()){steeringState = NONE;leftRudderAngle = 0;rightRudderAngle = 0; // 重置角度到中位ui->but_up->setStyleSheet("background-color:white");}// E键释放 - 停止下潜if(event->key()==Qt::Key_E&&!event->isAutoRepeat()){steeringState = NONE;leftRudderAngle = 0;rightRudderAngle = 0;ui->but_down->setStyleSheet("background-color:white");}// 任何控制键释放时发送数据if((event->key() == Qt::Key_W) || (event->key() == Qt::Key_S) || (event->key() == Qt::Key_A) || (event->key() == Qt::Key_D) || (event->key() == Qt::Key_Q) || (event->key() == Qt::Key_E)) //发送数据{// 将各参数转换为字符串QString throttleStr = QString::number(mainThrottle);QString upperRudderStr = QString::number(upperRudderAngle);QString lowerRudderStr = QString::number(lowerRudderAngle);QString leftRudderStr = QString::number(leftRudderAngle);QString rightRudderStr = QString::number(rightRudderAngle);// 构建指令字符串:$1RC,主推转速,上角度,下角度,左角度,右角度^QString list = "$1RC," + throttleStr + "," + upperRudderStr + "," + lowerRudderStr + "," + leftRudderStr + "," + rightRudderStr +"^";QByteArray list_1 = list.toLatin1();  // 转换为Latin1编码// 如果当前有运动状态,则每20次计数发送一次指令if((movementState != STOPPED) || (steeringState != NONE)){// id1=startTimer(1000);commandCounter += 1;if(commandCounter == 20){Radio_SUM = 0;//my_serialport->write(list_1); // 实际发送指令(被注释)qDebug() << "list:" << list_1;commandCounter = 0;}}// 如果状态发生变化,立即发送指令if((movementState != lastMovementState) || (steeringState != lastSteeringState)){Radio_SUM = 0;//my_serialport->write(list_1); // 实际发送指令(被注释)qDebug() << "list:" << list_1;lastMovementState = movementState;  // 更新上一次前后状态lastSteeringState = steeringState;  // 更新上一次转向/升降状态}}
}

UI

http://www.dtcms.com/a/325730.html

相关文章:

  • Qt串口通信中继电器状态解析的优化实践
  • 跨平台、低延迟、可嵌入:实时音视频技术在 AI 控制系统中的进化之路
  • c++ 常见关键字
  • 带简易后台管理的米表系统 域名出售系统 自适应页面
  • 适用于高质量核磁共振(NMR)的溶剂推荐
  • 未来物联网大模型:物联网硬件+底层驱动+AI 自动生成和调优LUA脚本,
  • Maven 的 module 管理
  • 变频器实习总结13 传统数据存储、OSS和云数据库 RDS
  • 【11-计算机视觉介绍】
  • C#/.NET/.NET Core技术前沿周刊 | 第 49 期(2025年8.1-8.10)
  • 常用设计模式系列(十九)- 状态模式
  • Flink TableAPI 按分钟统计数据量
  • 电路笔记参考图
  • 老式大头显示器(CRT)和当前最高分辨率的LED显示器对比
  • 掌握do-while循环:从语法到运用
  • IoT/实现和分析 NB-IoT+DTLS+PSK 接入华为云物联网平台IoTDA过程,总结避坑攻略
  • DeepCompare文件深度对比软件:权限管理与安全功能全面解析
  • Day12 Maven高级
  • openpnp - 顶部相机环形灯光DIY
  • 基于AI量化模型的比特币周期重构:传统四年规律是否被算法因子打破?
  • Apple Intelligence
  • 代币化股票的崛起:比特币安全吗?
  • Linux操作系统从入门到实战(十九)进程状态
  • SpringBoot 实现 Excel 导入导出功能的三种实现方式
  • SpringBoot 自动配置核心机制(面试高频考点)
  • 随身WiFi技术军备赛白热化:WiFi6架构下放中端市场,格行中兴华为三足鼎立;从芯片到场景的 10 款标杆产品深度解析
  • 使用Windbg分析多线程死锁项目实战问题分享
  • FPGA学习笔记——DS18B20(数字温度传感器)
  • 智慧工地:以三大监测技术筑牢安全屏障
  • 衡石科技HENGSHI SENSE 6.0 亮点功能一览-新增仪表盘入口和可视化