ROS-Qt GUI - 如何分发线程
ROS-Qt GUI - How to distribute the Threads?
我正在开发一个C++Qt GUI来远程控制ROS机器人。我已经读过 ros::spin()
命令应该在单独的线程中发出,所以我基本上有通常的 MainWindow 派生自QMainWindow
,其构造函数设置 GUI 元素,使订阅者对象订阅它们各自的主题(例如 image_transport::Subscriber
sensor_msgs/Image
主题),并启动另一个线程。为此,我从QThread
派生了一个"RosThread"类,该类除了在调用RosThread::run()
时启动ros:MultiThreadedSpinner
外什么都不做。
正如你可能知道的那样,我在编程方面并不完全有经验,所以我的问题是,我的项目背后的基本概念对你来说是否有意义?特别是我是否应该将 NodeHandle 和订阅者对象保留在 MainWindow 中,并从 MainWindow 构造函数设置订阅?
相关代码片段:
主窗口.cpp:
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), itLeft(nh), itArm(nh)
{
//subscribe to cameras
imageSubLeft = itLeft.subscribe("/camera_1/image_raw", 1000, &MainWindow::camCallbackLeft, this);
imageSubArm = itArm.subscribe("/camera_2/image_raw", 1000, &MainWindow::camCallbackArm, this);
pagestack = new QStackedWidget;
page1 = new QWidget;
grid = new QGridLayout;
page1->setLayout(grid);
pagestack->addWidget(page1);
labelLeft = new QLabel;
labelMid = new QLabel;
grid->addWidget(labelLeft, 0, 0);
grid->addWidget(labelMid, 0, 1);
this->startSpinThread(); //starts the seperate Thread where run() is executed
this->setCentralWidget(pagestack);
this->setWindowState(Qt::WindowMaximized);
this->setMinimumSize(1024, 768);
}
MainWindow::~MainWindow(){}
void MainWindow::camCallbackLeft(const sensor_msgs::Image::ConstPtr &msg){/*some code*/}
void MainWindow::camCallbackArm(const sensor_msgs::Image::ConstPtr &msg){/*some code*/}
void MainWindow::closeEvent(QCloseEvent *event){/*some code*/}
void MainWindow::startSpinThread()
{
if(rosSpin.isRunning())
{
return;
}
//rosSpin is an Object of the of QThread derived class
rosSpin.start();
}
rosthread.h:
#ifndef ROSTHREAD_H
#define ROSTHREAD_H
#include <ros/ros.h>
#include <QThread>
class RosThread : public QThread
{
Q_OBJECT
public:
RosThread();
protected:
void run();
private:
ros::MultiThreadedSpinner spinner;
};
#endif // ROSTHREAD_H
Rosthread.cpp:
#include "rosthread.h"
RosThread::RosThread()
{
}
void RosThread::run() {
spinner.spin();
}
主.cpp:
#include "mainwindow.h"
#include <QApplication>
#include <ros/ros.h>
int main(int argc, char **argv)
{
ros::init(argc, argv, "gui_node");
QApplication app (argc, argv);
MainWindow *win = new MainWindow();
win->show();
return app.exec();
}
实际上,QThread 并不打算以这种方式使用。看看这篇博客文章和这个例子。
但无论如何,我会建议使用标准C++线程。将std::unique_ptr<std::thread> thread;
添加到 MainWindow 类而不是 RosThread
对象。要启动线程,请使用 thread.reset(new std::thread([](){ static ros::MultiThreadedSpinner spinner; spinner.spin(); });
。智能指针std::unique_ptr
将自动删除线程对象,尽管您不应忘记在重置/销毁std::unique_ptr
对象之前使用std::thread::join()
或std::thread::detach()
。另一种解决方案是将ros::MultiThreadedSpinner
对象放入 MainWindow 类中,并使用 thread.reset(new std::thread(&ros::MultiThreadedSpinner::spin, spinner));
创建一个std::thread
。
在我看来,你应该把你的NodeHandle和Subscriber对象放到另一个类中,如果它们不直接属于MainWindow,则使用这个类的对象作为MainWindow的成员。
- QtConcurrent - 在发布到 UI 线程的数千个结果中保持 GUI 响应
- 线程和 GUI 处理
- 多线程Windows GUI应用程序中的死锁
- 带GUI的Qt多线程
- 与非主线程的 GUI 线程通信
- Qt 如何将数据从一个 GUI 传递到另一个线程
- Qt:工作线程和 GUI 事件之间的关系
- 解决方法:QPixmap:在GUI线程之外使用pixmap是不安全的
- 处理中断时,如何回到主gui线程
- 从其他std ::线程更新QT GUI
- QNetworkAccessManager即使在另一个线程中也能冻结GUI
- 如何在非 gui 线程上正确创建 QUdpSocket?未发出现读
- Qt的GUI线程在从外部对象调用方法时是否会在引擎盖下生成线程?
- ROS-Qt GUI - 如何分发线程
- 由于线程问题,Qt-Gui没有更新
- 当主GUI线程被阻塞时,如何从工作线程创建无模式对话框
- Qt 停止来自 GUI 线程的工作线程循环
- 使用第二个线程快速更新 GUI 窗口会通过调整窗口大小或移动窗口而崩溃
- 如何降低 QT Gui 线程优先级
- 使用 Qt 的简单线程 gui 应用程序的结构是什么?