问题描述
我正在尝试使用python绘制进入计算机的实时数据.数据来自 ROS 主题,我使用rospy"订阅该主题以获取数据.这是我写的代码
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()
我的问题是,当我使用从rostopic获得的数据调用 plotThrottle()
时,出现以下错误.
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
但是,如果我使用相同的函数并传递代码内生成的一些数据(一些随机数据),则绘图效果很好.我绝对是 python 的初学者.我搜索了这个错误,它说这是因为一些线程问题.但我不知道如何解决此代码.如果有人可以解释问题并帮助修复此代码,我真的很感激.
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.
推荐答案
这里有两个线程在运行,rospy.spin() 和 top.mainloop()(来自 Tkinter,在你的案例中是 matplotlib 的后端).
Here you have two threads running, rospy.spin() and top.mainloop() (from Tkinter, backend of matplotlib in your case).
来自此答案:
问题源于_tkinter模块尝试执行以下操作:当通过轮询技术获得对主线程的控制时处理来自其他线程的调用.
您在 Thread-1 中的 Tkinter 代码正试图窥视主线程找到主循环,但它不在那里.
Your Tkinter code in Thread-1 is trying to peek into the main threadto find the main loop, and it's not there.
来自此答案:
如果有另一个阻塞调用使您的程序继续运行,无需调用rospy.spin().不像在 C++ 中,spin() 是需要处理所有线程,在python中它所做的就是阻塞.
所以你可以使用 plt.show(block=True)
来防止你的程序关闭,在这种情况下你将使用 Tkinter 主循环,重新绘制你的画布没有问题.
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)
无论如何,这似乎是其他替代方案的解决方法,请再次查看this回答或简单地使用单独的节点进行绘图,即 ros 建议的工具,如 rqt_graph.
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.
这篇关于Python实时绘制ROS数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!