Qt Creatorで作成したGUIでROSメッセージのPub・Sub


前回Qt Cretorで作成したGUIをROSノード化しました.

今回はROSの基本通信Pub/Subの機能の追加方法を記載します.

内容

1.pub

・GUIでボタンの追加 => ボタン右クリックのSLOT設定を押して,イベントハンドラー関数を生成

・前回の記事で作成したROSノードプログラム元に各プログラムを以下のように変更します

main.cpp
#include "mainwindow.h"

#include <QApplication>
#include <ros/ros.h>


int main(int argc, char *argv[])
{

    ros::init(argc, argv, "aaa");

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    ros::Rate loop_rate(20);
    while (ros::ok()){
      ros::spinOnce();
      a.processEvents();
      loop_rate.sleep();
    }
}

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <ros/ros.h>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_released();

private:
    Ui::MainWindow *ui;
    ros::NodeHandle nh_;
    ros::Publisher string_pub_;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"

#include <ros/ros.h>
#include <std_msgs/String.h>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{

    ui->setupUi(this);
    string_pub_ = nh_.advertise<std_msgs::String>("chatter", 10);

}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_released()
{
    std_msgs::String string_msg;
    string_msg.data="string";
    string_pub_.publish(string_msg);
    ROS_INFO("pub: %s", string_msg.data.c_str());
}

結果

roscoreを起動して,Qt Creatorから実行すると以下のようなGUIが立ち上がり,
ボタンを押すと/chatterトピックが配信されます

2.sub

次はsubscriber GUIを作成します

・まずGUIにlabelを設置します

・次に各プログラムを以下のように変更します

main.cpp
#include "mainwindow.h"

#include <QApplication>
#include <ros/ros.h>


int main(int argc, char *argv[])
{

    ros::init(argc, argv, "aaa");

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    ros::Rate loop_rate(20);
    while (ros::ok()){
      ros::spinOnce();
      a.processEvents();
      loop_rate.sleep();
    }
}
mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"

#include <ros/ros.h>
#include <std_msgs/String.h>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{

    ui->setupUi(this);
    ui->label->setText("Hello World!");
    string_sub_ = nh_.subscribe("chatter", 10, &MainWindow::stringCallback, this);
    printf("register\n");
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::stringCallback(const std_msgs::String& string_msg){
  QString text = QString::fromStdString(string_msg.data);
  ui->label->setText(text);
  ROS_INFO("sub: %s", string_msg.data.c_str());
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <ros/ros.h>
#include <std_msgs/String.h>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    ros::NodeHandle nh_;
    ros::Subscriber string_sub_;
    void stringCallback(const std_msgs::String& msg);
};
#endif // MAINWINDOW_H

結果

実行してchatterトピックにメッセージを送信するとGUI上のlabelテキストが変更されました

さいごに

Qt Creatorを使うとボタンのコールバック関数などを自動生成できたり楽でいいですね!

参考