0. 前言
-
网上对于 QT5 开发 ROS2 界面的资料几乎没有,我从 Github 上的一个仓库 Fork 了一个,进行了修改,形成一个模板,可以在此模板的基础上进行修改开发自己的 ROS2 GUI 。
-
Github 链接:ros2_qt_template
1. QT5 和 ROS 插件安装
- 下载 .run 文件,推荐使用清华源在线安装包,速度很快: 下载链接
- 执行安装:
chmod a+x qt-unified-linux-x64-online.run ./qt-unified-linux-x64-online.run --mirror https://mirrors.tuna.tsinghua.edu.cn/qt
-
从 Github 下载对应版本并安装 ros_qtc_plugin ,注意需要以 root 权限执行可以将插件安装到系统文件夹中,否则只能安装到用户文件夹:
sudo /opt/Qt/Tools/QtCreator/bin/qtcreator
2. 创建 ROS2 QT 项目
注意:似乎只支持 QT5,对于 QT6,结合 ROS2 无法编译通过。
- 新建文件夹
ws_qt
; - 创建工作空间:
-
修改文件夹筛选器,显示出 src 文件夹,右键 src 文件夹,新建 ROS 功能包:
-
进入 src 文件夹下:
git clone https://github.com/SEUZTh/ros2_qt_template.git
-
在 QT 中编译项目;
-
运行节点:
source install/setup.sh ros2 run ros2_qt_demo ros2_qt_demo
3. 模板代码解析
3.1 CMakeLists.txt
CMakeLists.txt 解析(这里没有列出全部代码,只是代码片段):
# 可以修改为自己想要的功能包名称,同时在 package.xml 中也需要修改名称
project(ros2_qt_template)
# 添加需要用到的 ROS2 包
find_package(rclcpp REQUIRED)
# find_package(sensor_msgs REQUIRED)
# find_package(cv_bridge REQUIRED)
# 添加依赖的 ROS2 库,上面添加的包在这里也需要添加才能使用
ament_target_dependencies(${PROJECT_NAME} rclcpp Boost)
3.2 rclcomm.cpp
对应的头文件就不说了,直接来看 rclcomm.cpp 中的函数定义:
#include "rclcomm.h"
// 这里需要对发布者和订阅者进行初始化
// 如果一个可执行文件中定义多个节点,ROS2 的初始化不能放在这里,因为同一个可执行文件中不能初始化两次
rclcomm::rclcomm() {
node=rclcpp::Node::make_shared("ros2_qt_demo");
_publisher =
node->create_publisher<std_msgs::msg::Int32>("ros2_qt_demo_publish", 10);
_subscription = node->create_subscription<std_msgs::msg::Int32>("ros2_qt_demo_publish", 10,std::bind(&rclcomm::recv_callback,this,std::placeholders::_1));
this->start();
}
// run()函数是QThread类中的虚函数,它在新的线程中被调用,不需要你手动调用
void rclcomm::run(){
std_msgs::msg::Int32 pub_msg;
pub_msg.data=0;
rclcpp::WallRate loop_rate(10); // 10HZ
while (rclcpp::ok())
{
pub_msg.data++;
_publisher->publish(pub_msg);
rclcpp::spin_some(node);
loop_rate.sleep();
}
rclcpp::shutdown();
}
// 回调函数,其中实现你想实现的功能即可,这里实现的功能是触发 QT 信号
void rclcomm::recv_callback(const std_msgs::msg::Int32::SharedPtr msg){
emitTopicData("I head from ros2_qt_demo_publish:"+QString::fromStdString(std::to_string(msg->data)));
}
3.3 mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QImage img;
img.load(":/icon/images/foxy.jpg");
img.scaled(ui->label->width(),ui->label->height());
ui->label->setPixmap(QPixmap::fromImage(img).scaled(ui->label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
// 初始化 ROS2
int argc=0;
char **argv=NULL;
rclcpp::init(argc,argv);
// 实例化节点(可以在这里实例化多个节点,用于不同的功能)
commNode = new rclcomm();
connect(commNode, SIGNAL(emitTopicData(QString)), this, SLOT(updateTopicInfo(QString)));
}
void MainWindow::updateTopicInfo(QString data){
ui->label_4->clear();
ui->label_4->setText(data);
}
MainWindow::~MainWindow()
{
delete ui;
}
评论(0)
您还未登录,请登录后发表或查看评论