【问题标题】:Replotting graph based on ROS subscribed data根据 ROS 订阅数据重新绘制图表
【发布时间】:2014-06-25 20:34:35
【问题描述】:

架构

我有一个阴谋。以及该图中的一条曲线。 我在文件中有一个节点和一个订阅者。该订阅者订阅了一些正在发布的浮动数据。 每次发布一些数据时,我都会通过将新数据点添加到现有数据集来更新曲线。

问题

图表未正确更新。由于每秒都有数据进来,GUI 会挂起,一段时间后,GUI 由于分段错误而中止。

代码

def initUI(self):

    # x11.XInitThreads()

    # xlib.XInitThreads()

    # initialising the window

    QtGui.QWidget.__init__(self)

    # self.setGeometry(300, 300, 160, 1000)
    # self.setWindowTitle('Visualizer')

    # main layout

    self.layout = QtGui.QVBoxLayout(self)

    # Creating the elements in this widget

    a = QtGui.QLabel("Navigation", self)

    a.setStyleSheet("QLabel{ background-color: white; color: black; font-size: 25px; }")

    self.plot = Qwt.QwtPlot(self)
    self.plot.setCanvasBackground(Qt.black)
    self.plot.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time')
    self.plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10, 1)
    self.plot.setAxisTitle(Qwt.QwtPlot.yLeft, 'Temperature')
    self.plot.setAxisScale(Qwt.QwtPlot.yLeft, 0, 250, 40)
    self.plot.replot()

    self.curve = Qwt.QwtPlotCurve('')
    self.curve.setRenderHint(Qwt.QwtPlotItem.RenderAntialiased)
    pen = QPen(QColor('limegreen'))
    pen.setWidth(2)
    self.curve.setPen(pen)
    self.curve.attach(self.plot)

    self.layout.addWidget(a)
    self.layout.addWidget(self.plot)

def listener(self):       

    rospy.init_node('listener', anonymous=True)

    rospy.Subscriber(TOPIC_NAME, String, self.callback)

def callback(self, data):

    self.xData.append(self.counter + 1)
    self.yData.append(int(str(data.data)))
    self.counter += 1

    self.curve.setData(self.xData, self.yData)
    self.plot.replot()

调用这些函数:-

self.listener()
self.initUI()

一旦调用了监听器,订阅者就会自动与回调函数关联。回调函数查看新数据,将其添加到 y 轴,然后重新绘制图形。

错误

每次发布​​新数据点时我都会收到此错误:-

QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPainter::begin: Paint device returned engine == 0, type: 2
QPainter::setPen: Painter not active
QPainter::setBrush: Painter not active
QPainter::drawRects: Painter not active
QPainter::begin: Paint device returned engine == 0, type: 2
QPainter::translate: Painter not active
QPainter::save: Painter not active
QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::save: Painter not active
QPainter::setPen: Painter not active
QPainter::restore: Unbalanced save/restore
QPainter::restore: Unbalanced save/restore
QPainter::end: Painter not active, aborted

我不明白这个错误。

关于发布者

ROS 遵循Publisher-Subscribe 模式。我已经创建了一个发布随机整数的节点。这个整数应该绘制在图表上。

规格

Ubuntu 12.04
ROS Hydro
PyQt4
Qwt5

【问题讨论】:

    标签: python pyqt ros qwt


    【解决方案1】:

    您的callback 方法正在线程中运行。您不能从另一个线程更新 Qt GUI 对象。这就是为什么您会看到错误并出现段错误的原因。

    解决办法是:

    • 在回调中,将数据附加到列表中。使用从主线程启动的QTimer 定期检查列表的更新并重新绘制图表(不是理想的解决方案,但可能会完成工作)

    • 在回调中,将数据放在 python Queue.Queue() 中。每次从Queue 读取某些内容时,从该队列读取数据时有一个QThread 块并发出一个qt 信号(其中包含数据)。将主线程中的方法连接到此 qt 信号。因此,您在主线程中的方法获取数据并可以从主线程更新绘图。

    这里有一堆其他堆栈溢出问题,它们做类似的事情(将数据从线程发送到 qt 主线程以避免段错误)或者在深入研究多线程 pyqt 应用程序时很有用:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-12
      • 2020-04-01
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 2013-11-26
      相关资源
      最近更新 更多