从qt线程制作一个ros节点

making a ros node from a qt thread

我的应用程序中有一个 qt 线程,它发出一个 Mat 类型的图像,以便其他线程可以使用它。图像来自相机,使用 opencv 库的 VideoCapture 对象。现在我打算做的是从 rostopic 获取这张图片,而不是直接从相机获取。为了做到这一点,我必须在我的线程中创建一个 ros 节点,我被卡住了。有没有人有整合ros node和qt的经验? 这是我的话题:

#include "../include/Ground_Station/camera.h"
#include <iostream>

using namespace std;

Camera::Camera()
{

}

void Camera::run()
{

    VideoCapture cap;
    cap.open(0);

    while(1){

        Mat image;
        cap >> image;

        cvtColor(image,image,CV_BGR2RGB);

        emit ImgSignal(&image);
        QThread::msleep(30);
    }
}

和Camera.h:

#ifndef CAMERA_H
#define CAMERA_H

#include <QObject>
#include <QThread>
#include <QtCore>
#include <QtGui>

#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <ros/ros.h>

#include <opencv2/opencv.hpp>

using namespace cv;

class Camera: public QThread
{
    Q_OBJECT
public:
    Camera();

    void run();
    bool Stop = false;

signals:
    void ImgSignal(Mat*);

private:                                                                 

public slots:


};

#endif // THREAD_H

基本上,你包含main()函数的可执行文件必须同时是你的ros节点和你的QT应用程序。在你的 "main.cpp" 你打电话给 ros::init(...) 并订阅你想听的话题。您的订阅者回调函数可能会将 ros 图像转换为 Mat 并在每次调用时发出 ImgSignal。为此,我将创建一个 RosImageProvider class,类似于 ..

class RosImageProvider: public QObject
{
    Q_OBJECT
public:
  void ImageSubscriberCallback(const sensor_msgs::Image::ConstPtr& img);
...
signals:
  void ImgSignal(Mat*);
};

我在处理来自 Qt 中 ROS 节点的 TCP/IP 连接时遇到了同样的问题,我的解决方案是直接从 QThread 对象继承,因此在初始化 class 时,你初始化ROS 节点并在回调和线程 运行() 函数中实现工作 TODO。

最后,我的代码看起来像这样:

#ifndef INCLUDE_TCPHANDLER_HPP_
#define INCLUDE_TCPHANDLER_HPP_

#include <ros/ros.h>

#include <QThread>
#include <string>

class TCP_Handler : public QThread
{
    Q_OBJECT

private:
    int init_argc;
    char** init_argv;

    ros::Publisher cmd_control_publisher;
    ros::Subscriber feedback_subscriber;

public:
    TCP_Handler()
    {}

    virtual ~TCP_Handler(){}

 /**
     * @brief ROS methods
 *
 */
    inline bool init_ros()
    {
        int argc =0; char** argv = new char*();
        ros::init(argc,argv,"tcp_handler");
        ros::NodeHandle n;
        cmd_control_publisher = n.advertise<robot_common::cmd_control>("cmd_control", 1000);
        feedback_subscriber = n.subscribe<robot_common::feedback>("wifibot_pose", 4, &TCP_Handler::FeedbackCallback , this);
        return true;
    }

    void FeedbackCallback(const robot_common::feedback::ConstPtr& pose)
    {
        //.....
    }

 /**
 * @brief Threading methods
 *
 */
    virtual void init(int, std::string ip_addr = "127.0.0.1") = 0;
    virtual void run() = 0;
    virtual void stop() = 0;

/**
 * @brief TCP methods (Server/Client have to implement these folks)
 *
 */

    virtual bool Send_data(char* data, int size) = 0;
    virtual int  Receive_data(char* in_data, int size) = 0;
    virtual bool Open_connection() = 0;
    virtual void Close_connection() = 0;
};

#endif /* INCLUDE_TCPHANDLER_HPP_ */ 

此代码只是用于 TCP 连接的 Qt-threaded-ROS 节点的模板,因为我不知道您的具体需求。随意构建您自己的!

干杯,