ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Plotting data with mayavi via the subscriber node

asked 2017-04-12 06:50:07 -0600

atom gravatar image

Hi, I want a real time 3d plot of the data points from my topic so i wrote a basic subscriber and expected it to work. This is my code

#!/usr/bin/env python
import rospy
from sensor_msgs.msg import LaserScan
# import matplotlib.pyplot as plt
import numpy as np
import math
import mayavi.mlab as mlab
import time

def callback(data):
    rospy.loginfo("I heard %f %f %f", math.degrees(data.angle_increment), math.degrees(data.angle_min), math.degrees(data.angle_max) )    
    theta = np.arange(data.angle_min, data.angle_max+data.angle_increment, data.angle_increment)
    rospy.loginfo("%s %s", str(len(theta)), str(len(data.ranges)) )
    z=np.ones(len(theta))
    # plt.ylabel('distance')
    # plt.xlabel('angle')
    # plt.xticks(data.angle_min, data.angle_max, data.angle_increment)
    mlab.clf()
    mla*b.plot3d(theta, data.ranges,z)
    # time.sleep(0.001)
    # plt.pause(0.001)
    # plt.clf()
def listener():
    rospy.init_node('listener', anonymous=True)
    rospy.Subscriber("scan", LaserScan, callback)
    # spin() simply keeps python from exiting until this node is stopped
    rospy.spin()
if __name__ == '__main__':
    listener()

I get the following error:

QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject::startTimer: QTimer can only be used with threads started with QThread

I tried writing the callback function as a inner(nested) function even that did not resolve the issue, i've also tried the same with matplotlib, a similar sort of error showed up, which says TkInter is not running in the main thread.

Any help is appreciated. Cheers.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2017-04-13 12:16:38 -0600

atom gravatar image

Hi, I solved this problem by instantiating a new window for plotting the data because the TkInter library requires that the GUI management has to be in main thread, and there are using the created window to plot the data in it.

the code for a new window:

#!/usr/bin/env python
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

import matplotlib
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as  NavigationToolbar
from matplotlib.figure import Figure
from mpl_toolkits.mplot3d import Axes3D

class PlotWindow(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle('Sliding histogramm')
        self.create_main_frame()
        self.on_draw()

    def save_plot(self):
        pass

    def on_about(self):
        pass

    def on_pick(self, event):
        pass

    def on_draw(self):
        self.axes.clear()        
        self.axes.grid(True)
        self.canvas.draw()

    def create_main_frame(self):
        self.main_frame = QWidget()
        self.dpi = 100
        self.fig = Figure((5.0, 4.0), dpi=self.dpi)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.axes = self.fig.add_subplot(111, projection='3d')
        # self.axes.get_zaxis().set_visible(False)
        self.canvas.mpl_connect('pick_event', self.on_pick)
        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)     
        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        vbox.addWidget(self.mpl_toolbar)
        self.main_frame.setLayout(vbox)
        self.setCentralWidget(self.main_frame)

and the code to plot:

#!/usr/bin/env python
import rospy
from sensor_msgs.msg import LaserScan
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from windowonline import PlotWindow
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class plotnew(PlotWindow): 
    def __init__(self): 
        PlotWindow.__init__(self)
        self.window_size=20
        rospy.init_node('listener', anonymous=True)
        self.subscriber=rospy.Subscriber("scan", LaserScan, self.callback)


    def callback(self, data):    
        print data
        theta = np.arange(data.angle_min, data.angle_max+data.angle_increment, data.angle_increment)
        z=np.ones(len(theta))
        self.axes.plot(theta, data.ranges,1,color='red',linewidth=2)
        self.canvas.draw()
        plt.pause(0.001)
        self.axes.clear()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = plotnew()
    window.show()
    app.exec_()

Hope this helps someone who's having the same problem.

cheers, atom.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2017-04-12 06:50:07 -0600

Seen: 765 times

Last updated: Apr 13 '17