Ros小车多功能QT上位机
-
代码仓库:
https://github.com/zhuchen99899/RosCar/tree/master/Ros_car_pid_test
-
小车嵌入式控制可以查看我的博客:
https://blog.csdn.net/zhuchen88988/article/details/118612242?spm=1001.2014.3001.5501
-
小车通讯协议可以参看我的博客:
https://blog.csdn.net/zhuchen88988/article/details/118637714?spm=1001.2014.3001.5501
-
QT上位机界面如下(MPU6050数据暂时未加入):
-
此上位机功能:
①修改电机方向
②修改电机速度
③修改小车PID参数
④控制小车行进方向
⑤接收小车速度,并在图表上显示,图表指针移动上去有X,Y位置指示,下方勾选栏可以屏蔽,显示电机1/2曲线,按钮可以暂停接收/继续接收速度数据。数据图表可以使用滚轮放大缩小曲线刻度,方便查看,右键复位原先尺寸,方便于PID调参。
⑥可以使用Xbox手柄控制小车,或者使用北通之类的。只要在驱动中显示为xbox360的手柄均可。 -
小车北通手柄WIFI控制:
功能①~④均为协议的基础实现,使用QT基本控件以及实现qttcp客户端。通过QT信号槽即可完成。
- 使用网络需要在.pro文件中加入network
- 协议类已经在protocol.cpp中实现
class protocol
{
public: union float_trans_forM1_rec_speed{
float f;
unsigned char uch[4];
};
union float_trans_forM1_PID{
float f;
unsigned char uch[4];
};
union float_trans_forM1_ctrl_speed{
float f;
unsigned char uch[4];
};
public:
protocol();
~protocol();
/*方向控制报文方法*/
QByteArray Control_direction(QByteArray block,uchar motor,uchar dir);
/*pwm控制报文方法*/
QByteArray Control_PWM(QByteArray block,uchar motor,int PWM_percentage);
QByteArray Control_set_PID(QByteArray block,uchar motor,PID PID_data);
QByteArray Control_Speed(QByteArray block,uchar motor,float speed_data[]);
QByteArray Control_SpeedAndDir(QByteArray block,uchar motor,float speed_data[],uchar dir[]);
/*接收一帧数据,筛选数据类型,并进行CRC校验和长度校验*/
uchar Receive_data(QByteArray block,qint64 tcp_readsize);
/*校验后,按照数据包头类型,选择解帧方法*/
/*解速度帧数据*/
void Receive_Data_Speed(float speed_data[],QByteArray block);
private:
/*CRC16——MODBUS 校验计算*/
ushort CRC16_calculate(QByteArray block);
/*CRC16校验结果转换 ushort 型 ->转为两个字节 uchar*/
void CRC16_trans(uchar *CRC_out_uchar,ushort CRC16_res);
/*取字节流最后两位组成CRC校验值*/
ushort CRC16_comb(QByteArray block,qint64 tcp_buffsize);
};
#endif // PROTOCOL_H
- 注意协议的CRC校验计算是使用C语言完成,QT中可以使用 extern 引用头文件方式使用C写的库。
extern "C"{
#include "crc16.h"
}
功能⑤为重写qchart功能实现。可参照网上代码完成
- 使用qchart功能需要在.pro中加入 charts
class ChartView : public QChartView
{
Q_OBJECT
public:
ChartView(QChart *chart, QWidget *parent = nullptr);
~ChartView();
// 保存坐标区域,用于复位
void saveAxisRange();
protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
private:
QPoint m_lastPoint;
bool m_isPress;
bool m_ctrlPress;
bool m_alreadySaveRange;
double m_xMin, m_xMax, m_yMin, m_yMax;
QGraphicsSimpleTextItem* m_coordItem;
};
功能⑥为qgamepad功能实现。
- 使用qgamepad功能需要在.pro中加入gamepad
- qgamepad在qt官方也有例子 可在欢迎界面搜索例程学习。不过官方例子是基于qml实现,在经过网上搜索后也找到了C++的例子。
- 通过信号槽来连接手柄的按键,可以从名字上清楚看出每个信号的作用
m_gamepad = new QGamepad(0, this);
connect(m_gamepad, &QGamepad::buttonR1Changed, this, [=](double value){
GamePAD_getBtnVaule(1, value);
});
connect(m_gamepad, &QGamepad::buttonR2Changed, this, [=](double value){
GamePAD_getBtnVaule(2, value);
});
connect(m_gamepad, &QGamepad::buttonL1Changed, this, [=](double value){
GamePAD_getBtnVaule(3, value);
});
connect(m_gamepad,&QGamepad::buttonL2Changed, this, [=](double value){
GamePAD_getBtnVaule(4, value);
});
connect(m_gamepad, &QGamepad::buttonUpChanged, this, [=](double value){
GamePAD_getBtnVaule(5, value);
});
connect(m_gamepad, &QGamepad::buttonDownChanged, this, [=](double value){
GamePAD_getBtnVaule(6, value);
});
connect(m_gamepad, &QGamepad::buttonRightChanged, this, [=](double value){
GamePAD_getBtnVaule(7, value);
});
connect(m_gamepad, &QGamepad::buttonLeftChanged, this, [=](double value){
GamePAD_getBtnVaule(8, value);
});
connect(m_gamepad, &QGamepad::axisRightXChanged, this, [=](double value){
GamePAD_getBtnVaule(9, value);
});
connect(m_gamepad, &QGamepad::axisRightYChanged, this, [=](double value){
GamePAD_getBtnVaule(10, value);
});
connect(m_gamepad, &QGamepad::axisLeftXChanged, this, [=](double value){
GamePAD_getBtnVaule(11, value);
});
connect(m_gamepad, &QGamepad::axisLeftYChanged, this, [=](double value){
GamePAD_getBtnVaule(12, value);
});
- 在对应的槽函数GamePAD_getBtnVaule中判断btName数值来判断哪个按键被按下并做响应处理。
- 普通按键value为1即为按下,摇杆按下需要判断value 正负,从上述信号可以看出,摇杆有X轴和Y轴,正负即为轴的不同方向的数值,以此判断摇杆状态。value为0时摇杆回0,给小车下发停止的协议。
- 使用过程中代码中加入判断机制,当有按键变动时再发送TCP信息给Ros小车,降低小车通讯压力。