Qt GUI для ROS: ошибка сегментации (дамп памяти) - PullRequest
0 голосов
/ 08 февраля 2019

Я программирую графический интерфейс C ++ Qt для дистанционного управления кинетическим роботом ROS.Я подписываюсь на пять sensor_msgs/Image и одну sensor_msgs/Imu тему.Вскоре после запуска графического интерфейса, то есть между немедленным и примерно до пяти минут, графический интерфейс пользователя отключается, печатая сообщение Segmentation fault (core dumped).Я действительно понятия не имею, как решить эту проблему.Кто-то сказал мне сделать трассировку GDB;так вот оно и есть.Надеюсь, кто-то более опытный, чем я, знает, что это говорит мне.

Что касается кода, кажется, что причиной segfault может быть переполнение стека?Если это правда, целесообразно ли использовать только указатели?Для обработки данных, которые я получаю от ROS, я использую cv:Mat и cv_bridge::CvImagePtr -объекты для преобразования данных изображения.Должен ли я использовать их в качестве указателя?Для отображения данных imu, которые я использую QVector -объекты, я должен также использовать указатели там?Я уже пытался сбросить размер QVector, чтобы они не росли бесконечно, но это не решило проблему.

main.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();
}

mainwindow.cpp:

#include "mainwindow.h"
#include <QMenu>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), itLeft(nh), itArm(nh), itRight(nh), itRear(nh), itStereo(nh)
{
    //QImage Objects
    camImgArm = new QImage;
    camImgLeft = new QImage;
    camImgRight = new QImage;
    camImgRear = new QImage;
    camImgStereo = new QImage;

    //subscribe to (stereo)kameras
    imageSubLeft = itLeft.subscribe("/camera_3/image_raw", 1, &MainWindow::camCallbackLeft, this);
    imageSubRight = itRight.subscribe("/camera_2/image_raw", 1, &MainWindow::camCallbackRight, this);
    imageSubRear = itRear.subscribe("/camera_1/image_raw", 1, &MainWindow::camCallbackRear, this);
    imageSubArm = itArm.subscribe("/camera_5/image_raw", 1, &MainWindow::camCallbackArm, this);

    //subscribe to imu_data
    imuSub = nh.subscribe("/imu_data", 1, &MainWindow::imuCallback, this);

    pagestack = new QStackedWidget;

    page1 = new QWidget;
    grid = new QGridLayout;
    page1->setLayout(grid);
    pagestack->addWidget(page1);

    editorPage2 = new QLabel;
    pagestack->addWidget(editorPage2);


    //Menubar
    pageMenu = new QMenu(tr("&Seite"), this);
    menuBar()->addMenu(pageMenu);
    page1Act = pageMenu->addAction(tr("Seite &1"), this, SLOT(pageChange1()), QKeySequence(tr("Ctrl+1", "Seite|Seite 1")));
    page2Act = pageMenu->addAction(tr("Seite &2"), this, SLOT(pageChange2()), QKeySequence(tr("Ctrl+2", "Seite|Seite 2")));
    pageChangeAG = new QActionGroup(this);
        pageChangeAG->addAction(page1Act);
        pageChangeAG->addAction(page2Act);

    displayMenu = new QMenu(tr("&Anzeigen"), this);
    menuBar()->addMenu(displayMenu);

    labelMidMenu = displayMenu->addMenu(tr("&Hauptanzeige"));

    showArmCamera = labelMidMenu->addAction(tr("Zeige &Armkamera"), this, SLOT(switchToArmCamera()), QKeySequence(tr("Anzeigen|Hauptanzeige|Zeige Armkamera")));
        showArmCamera->setCheckable(true);
    showStereo = labelMidMenu->addAction(tr("Zeige &Stereokamera"), this, SLOT(switchToStereo()), QKeySequence(tr("Anzeigen|Hauptanzeige|Zeige Stereokamera")));
        showStereo->setCheckable(true);
    labelMidAG = new QActionGroup(this);
        labelMidAG->addAction(showArmCamera);
        labelMidAG->addAction(showStereo);
        showArmCamera->setChecked(true);


    //Plot
    ahrsPlot = new QCustomPlot;
    ahrsPlot->addGraph();
    ahrsPlot->addGraph();
    ahrsPlot->addGraph();
    ahrsPlot->graph(0)->setPen(QPen(Qt::blue));
    ahrsPlot->graph(0)->setName("Rollwinkel");
    ahrsPlot->graph(1)->setPen(QPen(Qt::red));
    ahrsPlot->graph(1)->setName("Nickwinkel");
    ahrsPlot->graph(2)->setPen(QPen(Qt::yellow));
    ahrsPlot->graph(2)->setName("Gierwinkel");
    ahrsPlot->xAxis->setLabel("Zeit in s");
    ahrsPlot->yAxis->setLabel("Winkel in Grad");
    ahrsPlot->yAxis->setRange(-30, 30);
    ahrsPlot->legend->setVisible(true);
    ahrsPlot->legend->setBrush(QColor(255, 255, 255, 150));
    ahrsPlot->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
    ahrsPlot->setMinimumSize(300, 300);
    time.resize(0);
    roll.resize(0);
    pitch.resize(0);
    yaw.resize(0);

    labelLeft = new QLabel;
    labelMid = new QLabel;
    labelRight = new QLabel;
    labelBot = new QLabel;

    grid->addWidget(labelLeft, 0, 1);
    grid->addWidget(labelMid, 0, 2);
    grid->addWidget(labelRight, 0, 3);
    grid->addWidget(ahrsPlot, 1, 1);
    grid->addWidget(labelBot, 1, 2);

    spin = new SpinClass;
    rosThread = new QThread;
    connect(rosThread, SIGNAL(started()), spin, SLOT(startSpinner()));
    spin->moveToThread(rosThread);
    rosThread->start();

    this->setCentralWidget(pagestack);
    this->setWindowState(Qt::WindowMaximized);
    this->setMinimumSize(1024, 768);
}

MainWindow::~MainWindow(){}

void MainWindow::pageChange1()
{
  pagestack->setCurrentIndex(pagestack->indexOf(page1));
}

void MainWindow::pageChange2()
{
  pagestack->setCurrentIndex(pagestack->indexOf(editorPage2));
}

void MainWindow::camCallbackLeft(const sensor_msgs::Image::ConstPtr &msg)
{
        try
        {
            cvImgPtrLeft = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
        }
        catch(cv_bridge::Exception &e)
        {
            ROS_ERROR("cv_bridge exception: %s", e.what());
            return;
        }

        camFrameLeft = cvImgPtrLeft->image;
        cvtColor(camFrameLeft, camFrameLeft, CV_BGR2RGB);
        *camImgLeft = QImage((const unsigned char*)(camFrameLeft.data), camFrameLeft.cols, camFrameLeft.rows, QImage::Format_RGB888);
        labelLeft->setPixmap(QPixmap::fromImage(*camImgLeft));
        labelLeft->resize(labelLeft->pixmap()->size());
}

void MainWindow::camCallbackArm(const sensor_msgs::Image::ConstPtr &msg){}

void MainWindow::camCallbackRight(const sensor_msgs::Image::ConstPtr &msg){}

void MainWindow::camCallbackRear(const sensor_msgs::Image::ConstPtr& msg){}

void MainWindow::camCallbackStereo(const sensor_msgs::Image::ConstPtr& msg){}

void MainWindow::imuCallback(const sensor_msgs::Imu::ConstPtr &msg)
{
    angVelXGrad = msg->angular_velocity.x * 180 / M_PI;
    angVelYGrad = msg->angular_velocity.y * 180 / M_PI;
    angVelZGrad = msg->angular_velocity.z * 180 / M_PI;

    if(time.size()==0)
    {
        time.resize(1);
        roll.resize(1);
        pitch.resize(1);
        yaw.resize(1);

        linVelX.resize(1);
        linVelY.resize(1);
        linVelZ.resize(1);

        posX.resize(1);
        posY.resize(1);
        posZ.resize(1);

        time[0] = msg->header.stamp.sec + (msg->header.stamp.nsec * 1e-9);
        roll[0] = 0;
        pitch[0] = 0;
        yaw[0] = 0;

        linVelX[0] = 0;
        linVelY[0] = 0;
        linVelZ[0] = 0;

        posX[0] = 0;
        posY[0] = 0;
        posZ[0] = 0;

        return;
    }

    time.append(msg->header.stamp.sec + (msg->header.stamp.nsec * 1e-9));

    roll.append(roll[roll.size()-1] + (angVelXGrad * (time[time.size()-1] - time[time.size()-2])));
    pitch.append(pitch[pitch.size()-1] + (angVelYGrad * (time[time.size()-1] - time[time.size()-2])));
    yaw.append(yaw[yaw.size()-1] + (angVelZGrad * (time[time.size()-1] -time[time.size()-2])));

    ahrsPlot->graph(0)->setData(time, roll);
    ahrsPlot->graph(1)->setData(time, pitch);
    ahrsPlot->graph(2)->setData(time, yaw);
    ahrsPlot->xAxis->setRange(time[time.size()-1]-10.0,time[time.size()-1]+4.0);
    ahrsPlot->replot();
}

void MainWindow::switchToArmCamera()
{
    imageSubStereo.shutdown();
    imageSubArm = itArm.subscribe("/camera_5/image_raw", 1, &MainWindow::camCallbackArm, this);
}

void MainWindow::switchToStereo()
{
    imageSubArm.shutdown();
    imageSubStereo = itStereo.subscribe("/camera_4/image_raw", 1, &MainWindow::camCallbackStereo, this);
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    rosThread->terminate();
    rosThread->wait();
    event->accept();
}

spinclass.h

#ifndef SPINCLASS_H
#define SPINCLASS_H

#include <QObject>
#include "ros/ros.h"

class SpinClass : public QObject
{
    Q_OBJECT
public:
    explicit SpinClass(QObject *parent = nullptr);

    ros::MultiThreadedSpinner *spinner;

public slots:
    void startSpinner();

};

#endif // SPINCLASS_H

spinclass.cpp

#include "spinclass.h"

SpinClass::SpinClass(QObject *parent) : QObject(parent)
{
    spinner = new ros::MultiThreadedSpinner;
}

void SpinClass::startSpinner()
{
    spinner->spin();
}

gdb backtrace:

Thread 1 "gui_node" received signal SIGSEGV, Segmentation fault.
0x00007ffff26dc1e0 in QRasterPaintEngine::updateOutlineMapper() () from /usr/lib/x86_64-linux-jgnu/libQt5Gui.so.5
(gdb) bt
#0  0x00007ffff26dc1e0 in QRasterPaintEngine::updateOutlineMapper() () from /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#1  0x00007ffff26dc3ec in QRasterPaintEngine::updateRasterState() () from /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#2  0x00007ffff26e6bb0 in QRasterPaintEngine::updatePen(QPen const&) () from /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#3  0x00007ffff26e7855 in QRasterPaintEngine::drawTextItem(QPointF const&, QTextItem const&) () from /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#4  0x00007ffff27052d1 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#5  0x00007ffff2592c5d in QTextLine::draw(QPainter*, QPointF const&, QTextLayout::FormatRange const*) const () from /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#6  0x00007ffff26fb9b5 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#7  0x00007ffff2702503 in QPainter::drawText(QRect const&, int, QString const&, QRect*) () from /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#8  0x00007ffff2aca6d4 in QStyle::drawItemText(QPainter*, QRect const&, int, QPalette const&, bool, QString const&, QPalette::ColorRole) const ()
   from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#9  0x00007ffff2ba9ee4 in QLabel::paintEvent(QPaintEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#10 0x00007ffff2aa4fc8 in QWidget::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#11 0x00007ffff2ba3b8e in QFrame::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#12 0x00007ffff2a6205c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#13 0x00007ffff2a67516 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#14 0x00007ffff216f38b in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#15 0x00007ffff2a9dab9 in QWidgetPrivate::sendPaintEvent(QRegion const&) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#16 0x00007ffff2a9e101 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) ()
   from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#17 0x00007ffff2a9edac in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*)
    () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#18 0x00007ffff2a9ec99 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*)
---Type <return> to continue, or q <return> to quit---return
    () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#19 0x00007ffff2a9dc71 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) ()
   from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#20 0x00007ffff2a9edac in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*)
    () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#21 0x00007ffff2a9dc71 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) ()
   from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#22 0x00007ffff2a9edac in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*)
    () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#23 0x00007ffff2a9dc71 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) ()
   from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#24 0x00007ffff2a6f8aa in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#25 0x00007ffff2a6fa8c in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#26 0x00007ffff2a8dc5f in QWidgetPrivate::syncBackingStore() () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#27 0x00007ffff2aa4dc8 in QWidget::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#28 0x00007ffff2bbadbb in QMainWindow::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#29 0x00007ffff2a6205c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#30 0x00007ffff2a67516 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#31 0x00007ffff216f38b in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#32 0x00007ffff2171786 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#33 0x00007ffff21c53c3 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#34 0x00007fffe8d87197 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
---Type <return> to continue, or q <return> to quit---return
#35 0x00007fffe8d873f0 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#36 0x00007fffe8d8749c in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#37 0x00007ffff21c57cf in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#38 0x00007ffff216cb4a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#39 0x00007ffff2174bec in QCoreApplication::exec() () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#40 0x00000000004b8fb3 in main (argc=1, argv=0x7fffffffd9d8) at /home/user/catkin_ws_qtc/src/gui/src/gui_node.cpp:12

Относительно QRasterPaintEndinge, упомянутого несколько раз,Я даже не использую его непосредственно в своем коде, и, похоже, он не наследуется ни одним классом, который я использую.В последней строке gui_node.cpp содержит return app.exec(); в строке 12.

Если вам нужна дополнительная информация, пожалуйста, дайте мне знать.

Заранее спасибо!

...