Python real time plotting ROS data

假如想象 提交于 2019-12-07 22:24:02

问题


I am trying to plot real time data coming to the computer using python. Data comes in a ROS topic and I use 'rospy' to subscribe to the topic in order to get data. This is the code I wrote

import rospy
from sensor_msgs.msg import ChannelFloat32
import matplotlib.pyplot as plt

N = 200
i = 0

topic = "chatter"

x = range(N)
lmotor = [0]*N
rmotor = [0]*N

plt.ion()

fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlim([0,N])
ax.set_ylim([-1,1])

line1, = ax.plot(lmotor, 'r-')
line2, = ax.plot(rmotor, 'g')

def plotThrottle(data):
    global x, lmotor, rmotor, i

    [x[i],lmotor[i],rmotor[i], tmp] = data

    line1.set_ydata(lmotor)
    line1.set_xdata(x)
    line2.set_ydata(rmotor)
    line2.set_xdata(x)

    fig.canvas.draw()

def callBack(packet):
    data = list(packet.values)
    plotThrottle(data)


def listner():
    rospy.init_node('listener', anonymous=True)
    rospy.Subscriber(topic, ChannelFloat32, callBack)
    rospy.spin()

if __name__ == '__main__':
    listner()

My problem is when I call plotThrottle() with the data I got from rostopic, I get following error.

[ERROR]
[WallTime: 1454388985.317080] bad callback: <function callBack at 0x7f13d98ba6e0>
Traceback (most recent call last):
  File "/opt/ros/indigo/lib/python2.7/dist-packages/rospy/topics.py", line 720, in _invoke_callback
    cb(msg)
  File "dummy2.py", line 41, in callBack
    plotThrottle(data)
  File "dummy2.py", line 37, in plotThrottle
    fig.canvas.draw()
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 349, in draw
    tkagg.blit(self._tkphoto, self.renderer._renderer, colormode=2)
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/tkagg.py", line 13, in blit
    tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode, id(bbox_array))
RuntimeError: main thread is not in main loop

But if I use the same function and pass some data generated within the code (some random data) plot works fine. I am an absolute beginner to python. I searched about this error and it says that this is because of some threading problem. But I don't understand how to fix this code. I am really grateful if someone can explain the problem and help fix this code.


回答1:


Here you have two threads running, rospy.spin() and top.mainloop() (from Tkinter, backend of matplotlib in your case).

From this answer:

The problems stem from the fact that the _tkinter module attempts to gain control of the main thread via a polling technique when processing calls from other threads.

Your Tkinter code in Thread-1 is trying to peek into the main thread to find the main loop, and it's not there.

From this answer:

If there is another blocking call that keeps your program running, there is no need to call rospy.spin(). Unlike in C++ where spin() is needed to process all the threads, in python all it does is block.

So you can use plt.show(block=True) to keep your program from closing, in that case you will use Tkinter mainloop, redrawing your canvas without problems.

The listener fuction should look like this:

    def listener():
        rospy.init_node('listener', anonymous=True)
        rospy.Subscriber(topic, ChannelFloat32, callBack)
        # rospy.spin()
        plt.show(block=True)

Anyway this seems a bit a workaround for other alternatives see again this answer or simply use separate node for plotting i.e. ros suggested tools like rqt_graph.



来源:https://stackoverflow.com/questions/35145555/python-real-time-plotting-ros-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!