Ubuntu学习笔记4-Qt-ros话题通讯
前言
前面安装好了Qt-ros 的环境,下面开始尝试一下再Qt中实现话题通讯。
一、发布者实现
1、新建ROS工程,并添加功能包,功能包中创建一个pub节点。
2、在ROS工程中加入Qt界面
右击ros功能包中的src目录,新建一个Qt设计师界面
3、将Qt界面文件配置进Ros的CmakeList中,主要需要修改如下几点:
本文目录结构如下:
(1)在依赖后面增加以下描述代码
find_package(Qt5 REQUIRED COMPONENTS Widgets )#寻找Qt的包
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
(2)添加头文件包含
include_directories(
include/demo02
include ${catkin_INCLUDE_DIRS}
)
(3)添加所有cpp文件与ui文件
add_executable(${PROJECT_NAME}_node
src/control.cpp
src/control.ui
src/Pubtext.cpp)
(4)链接Qt库
target_link_libraries(${PROJECT_NAME}_node Qt5::Widgets )#链接Qt库
4、修改代码
本案例实现Qt界面中的按键控制发生LineEdit中的文本到指定话题,主要代码如下:
(1)Pubtext.cpp(原先的节点文件)
#include "ros/ros.h"
#include "std_msgs/String.h"
#include "control.h"
#include <QApplication>
int main(int argc, char **argv)
{
ros::init(argc, argv, "Pubtext");
QApplication a(argc,argv);
Control C1;
C1.show();
return a.exec();
// ros::Rate loop_rate(10);
// while (ros::ok())
// {
// std_msgs::String msg;
// msg.data = "hello world";
// chatter_pub.publish(msg);
// ros::spinOnce();
// loop_rate.sleep();
// }
}
(2)control.h
#ifndef CONTROL_H
#define CONTROL_H
#include <QWidget>
#include "ros/ros.h"
#include "std_msgs/String.h"
namespace Ui {
class Control;
}
class Control : public QWidget
{
Q_OBJECT
public:
explicit Control(QWidget *parent = nullptr);
~Control();
ros::NodeHandle nh;
ros::Publisher chatter_pub;
private slots:
void on_pushButton_clicked();
private:
Ui::Control *ui;
};
#endif // CONTROL_H
(3)control.cpp
#include "control.h"
#include "ui_control.h"
Control::Control(QWidget *parent) :
QWidget(parent),
ui(new Ui::Control)
{
ui->setupUi(this);
chatter_pub = nh.advertise<std_msgs::String>("chatter", 1000);
}
Control::~Control()
{
delete ui;
}
void Control::on_pushButton_clicked()
{
std_msgs::String msg;
msg.data = ui->lineEdit->text().toStdString();
chatter_pub.publish(msg);
}
(5)ui界面
注意:Pub所需的std_msgs依赖自行配置,改下CmakeList文件跟xml文件即可,这里不再赘述。上方代码主要就是将主函数改回原来Qt 的界面显示主函数(熟悉Qt 的应该都认识里面的main.cpp),并在生成界面前初始化ros节点,因为ros句柄及话题已经挪到了界面类中,因此必须先初始化ros节点,否则报错,随后将话题消息发布写到了按键的槽函数中。
结尾
运行前需要启动roscore,或者将节点集成到launch文件中(launch文件默认启动roscore)
主要实现效果如下:
二、订阅者实现
对于订阅方的实现,由于还没有时间去了解ROS节点与Qt的信号槽的机制关系,所以暂时直接硬方法实现一下,原理主要如下:
通过界面中的按键启动子线程,子线程中实现对话题的订阅,并将订阅的话题消息通过信号发生回界面类中进行显示。
注意:由于Ros的回调函数不属于Qt中自定义的线程类,所以需要将其定义为静态函数,又由于Qt的静态函数发出信号需要中转,因此需要额外定义一组信号槽用于回调函数信号的发送。参考自:
Qt静态函数发送信号
代码过长,就只贴出其中关键的子线程代码:
结尾
最终实现效果如下: