Ask Your Question
0

Custom QT GUI in ROS for real time data freeze

asked 2019-05-06 16:21:37 -0500

vrosuser gravatar image

Hi,

I am new to integrating ROS with QT. I am developing a custom gui to publish topic directly to a GUI that displays data in real time as it is read from a unit. I followed this link: http://wiki.ros.org/qt_create/Tutoria... .
GUI seems to work except it freezes after couple of minutes. Below is concept of how I have implemented.

 ---include/
               - main_winndow.hpp 
                -qnode.hpp`

---src/
  -main.cpp
  -main_winndow.cpp  => updates UI
  -qnode.cpp  => starts ros, reads ethernet packets from unit and publishes as "/raw_packets". Rawpacket is remapped to "input_data" in launch file and subscribed to functions call "msgrec" that decodes packets to topic parameters. I have 2 Q_EMIT. one to update ROS info in LIST-VIEW of UI and second Q_EMIT is after decoding of packets.

main_winndow.cpp

        :
        :
    MainWindow::MainWindow(int argc, char** argv, QWidget *parent)
        : QMainWindow(parent)
        , qnode(argc,argv)
    {
        :
        :
        // CONNECT GUI Button to Qnode init
        QObject::connect(ui.BUTTON, SIGNAL(clicked()), this, SLOT(StartqnodeInit()));

    // SIGNAL from Qnode after messages are read from unit to be displayed on GUI
        QObject::connect(&qnode, 
                         SIGNAL(logunitsmessages(std::string, std::string)), this, 
                         SLOT(ui_logunitsmessages(std::string, std::string)));


        // GUI List view gets updated after loggingUpdated signal from qnode
        ui.listView_log->setModel(qnode.loggingModel());
        QObject::connect(&qnode, SIGNAL(loggingUpdated()), this, SLOT(updateLoggingView()));

    }

    void MainWindow::StartqnodeInit()
    {        
        if ( !qnode.init(ui.lineEdit->text().toStdString()) ) {
          showNoMasterMessage();
        }
    }

    /*****************************************************************************
    ** GUI UPDATE HERE
    *****************************************************************************/   
    void MainWindow::updateLoggingView()   // LIST View updated here in signal loggingUpdated() from QNode 
    {
        ui.listView_log->scrollToBottom();
    }
    void MainWindow::ui_logunitsmessages( std::string msg1, std::string msg2 )
    {
    // LABELS updated here in signal logunitsmessages() from QNode 
         ui.msg1_valuelabel->setText(QString::fromStdString(msg1)); 
         ui.msg2_valuelabel->setText(QString::fromStdString(msg2));
    }
}

qnode.cpp

        :
            :
   // INIT
    bool QNode::init() {

    ros::init(init_argc,init_argv,"qexample");

    if ( ! ros::master::check() ) {
    return false;
    }
    ros::start(); // explicitly needed since our nodehandle is going out of scope.
    ros::NodeHandle n;


    pub_rawpack_ = n.advertise<custometh::ethpacket>("/raw_packets", 1, this);

    sub_rawpack_ = n.subscribe(input_data, 1, &QNode::msgrec, this); 

    pub_topicmsg_ = n.advertise<std_msgs::String>("/decodedmsg", 1);


    start();
    return true;
    }

     // RUN 
    void QNode::run() {
            ros::Rate loop_rate(10);
            /* loop until shut down or end of file */
            while(ros::ok() && rawpacketpolling())
            {
                pub_topicmsg_.publish(topicmessage);

            Q_EMIT logunitsmessages(topicmessage.msg1, topicmessage.msg2); // EMIT after messages is decoded.

                ros::spinOnce();
                loop_rate.sleep();
            }

            Q_EMIT rosShutdown(); // used to signal the gui for a shutdown (useful to roslaunch)  
    }

    msgrec ()
    {
    //code that decodes raw packets into "topicmessage" msg of std_msgs::String type
    }

    void QNode::log( const LogLevel &level, const std::string &msg) {
    : // some code here    
      Q_EMIT loggingUpdated(); // used to readjust the scrollbar
    }

I have read couple of posts that say to use QTime. Could someone help me how I can use Qtime in my example. If Qtime is not the right way to defreeze then what is the right method to go about to display real time topic without GUI freeze.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2019-05-30 22:53:50 -0500

kkrasnosky gravatar image

The problem is in your void void QNode::run() function. The while loop in this function makes this a "blocking function" meaning that the processor never gets handed back to the GUI to update. The way I usually deal with this problem is by using a qTimer.

Basically you want to create a timer in your main_window tells ROS things to happen. In between timer calls the GUI will be able to update properly.

Add the following member to your main_window.hpp

#include <QTimer>
...
class MainWindow : public QMainWindow{
...

private slots:
    void spin_ros();
private:
    QTimer *rosTimer;
...
}

In your main_window.cpp

in your constructor add:

rosTimer = new QTimer(this);
connect(rosTimer, SIGNAL(timeout()), this, SLOT(spin_ros()));
rosTimer->start(10);  // set your spin rate here

implement the spin_ros() function we declared in the header. This will be the function that does the body of your while loop invoid QNode::run()function.

void MainWindow::spin_ros(){
    myQnode.runOnce();   // you will need to modify QNode::run so it only does one loop iteration when called!
}

Plausible function for QNode::runOnce():

void QNode::runOnce() {
        if(ros::ok() && rawpacketpolling())
        {
            pub_topicmsg_.publish(topicmessage);

            Q_EMIT logunitsmessages(topicmessage.msg1, topicmessage.msg2); // EMIT after messages is decoded.

            ros::spinOnce();
            loop_rate.sleep();
        }
}
edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2019-05-06 16:21:37 -0500

Seen: 136 times

Last updated: May 30