У меня есть код Python 2.7 с различными потоками, работающими параллельно. Поток с FuncAnimation для matplotlib просто показывает черный экран. Мне нужна помощь с исправлением размещения FuncAnimation в моем коде.
Я попытался вывести графическую функцию с FuncAnimation за пределы потока, и она отлично работает с рандомизированными данными.
Более того, без FuncAnimation, используя простую команду plot, все работает, но это слишком медленно, поэтому я хотел использовать FuncAnimation в своем коде.
runGraph (threadName, sleepTime) запускается один раз и вызывает updateG (frame) один раз.
import os
from time import sleep, strftime
from math import tan, pi
from threading import Thread
import matplotlib.pyplot as plt #1.55 SECONDS
from matplotlib.animation import FuncAnimation
import GPS_USB_Controller
graphX=[]
graphY=[]
last_received = ''
cnt=0
frame=0
initial_y=0
initial_x=0
exitapp = False
GPS_USB_Controller.start_gps()
plt.ion()
Xper_last=0
Yper_last=0
ix=0
iy=0
fig=0
ax=0
ln=0
cnt=0
fig,ax=plt.subplots(1,1)
ln, = plt.plot([], [], 'ro')
plt.show()
def GPS_fix():
try:
while (GPS_USB_Controller.gpsc.gpsd.fix.mode != 3):
print "Waiting for GPS Fix. GPS mode:",GPS_USB_Controller.gpsc.gpsd.fix.mode, "Satellites:", GPS_USB_Controller.gpsc.satellites
#1 - no fix, 2 - 2D fix, 3 - 3D fix
except KeyboardInterrupt:
#print "GPS fix acquired."
sleep(1)
pass
def zeroLevel():
i=0
global initial_x
global initial_y
global Xper_last
global Yper_last
buffer_string = ''
last_received = ''
while (i < 100):
buffer_string = buffer_string + ser.read(ser.inWaiting())
if '\n' in buffer_string:
lines = buffer_string.split('\n') # Guaranteed to have at least 2 entries
last_received = lines[-2]
buffer_string = lines[-1]
##print last_received
response = last_received
if (response.count(";")) == 3: #Y; X; Heading; from IMU
current_values=response.split(';')
current_values.pop()
initial_x=tan(float(current_values[2])*(pi/180))*100 #convert degrees to radians to percent
initial_y=tan(float(current_values[1])*(pi/180))*100
Xper_last=initial_x
Yper_last=initial_y
#print ("Initial X:" + str(initial_x) +", Initial Y: "+ str(initial_y))
i=i+1
##print i
else:
print "Not all initialization data recieved - retrying"
print "Level initialization complete"
GPS_fix ()
#Calibrate level
##print "Total Time", total
print "Enter the current percent cross slope (X)"
userX = input()
print "Enter the current percent running slope (Y)"
userY = input()
zeroLevel ()
def initG():
global ax,fig,ln
ax.set_xlim(-15,15)
ax.set_ylim(-15, 15)
return ln,
def runLevel(threadName, sleepTime):
ser.flushInput()
global Xper
global Yper
global last_received
global Xper_last
global Yper_last
Xper=initial_x
Yper=initial_y
buffer_string = ''
global ix
global iy
while not exitapp:
sleep(sleepTime)
buffer_string = buffer_string + ser.read(ser.inWaiting())
if '\n' in buffer_string:
lines = buffer_string.split('\n') # Guaranteed to have at least 2 entries
last_received = lines[-2]
buffer_string = lines[-1]
##print last_received
response = last_received
if (response.count(";")) == 3: #check if recieved time; Y; X; and Heading; from IMU-time removed
current_values=response.split(';')
current_values.pop()
current_x=tan(float(current_values[2])*(pi/180))*100 #convert degrees to radians to percent
current_y=tan(float(current_values[1])*(pi/180))*100
Xper_actual=round((userX-initial_x)+current_x,2)
Yper_actual=round((userY-initial_y)+current_y,2)
Zper=round(float(current_values[0]),2)
Xchange=abs(Xper_last-Xper_actual)
Ychange=abs(Yper_last-Yper_actual)
if (ix>4):
Xper=Xper_actual
ix=0
elif (Xchange > 3):
Xper=Xper_last
ix=ix+1
else:
Xper=Xper_actual
ix=0
if (iy>4):
Yper=Yper_actual
iy=0
elif (Ychange > 3):
Yper=Yper_last
iy=iy+1
else:
Yper=Yper_actual
iy=0
Xper_last=Xper
Yper_last=Yper
matrixwritecommand([0x58]) #clear screen
matrixwritecommand([0x47,1,1])
ser_lcd.write("Cross: "+str(Xper)+"%")#cross slope
matrixwritecommand([0x47,1,2])
ser_lcd.write("Running: "+str(Yper)+"%")#running slope
database_stuff.log_data (GPS_USB_Controller.gpsc.fix.latitude, GPS_USB_Controller.gpsc.fix.longitude, Xper, Yper, Zper, "n/a", "n/a")
else:
print "Data error"
def isnan(value):
try:
import math
return math.isnan(float(value))
except:
return False
def updateG(frame):
global Xper,Yper,graphX,graphY,cnt,isnan
if(not isnan(Xper)):
graphX.append(Xper)
graphY.append(Yper)
print("----------------")
print(graphX)
print(graphY)
print("----------------")
ln.set_data(graphX, graphY)
if(cnt>=50):
graphX.pop(0)
graphY.pop(0)
cnt=0
return ln,
def runGraph(threadName, sleepTime):
global fig,ax,ln,cnt,updateG,initG,Xper
print("graph running")
ani = FuncAnimation(fig, updateG, frames=int(Xper), init_func=initG, blit=True, interval=0)
print(ani)
plt.show()
def runGPS(threadName, sleepTime):
while not exitapp:
sleep(sleepTime)
GPS_USB_Controller.print_gps()
if __name__ == '__main__':
try:
fig,ax=plt.subplots(1,1)
ln, = plt.plot([], [], 'ro')
plt.show()
t1=Thread(target=runLevel, args=("Level", 0))
t2=Thread(target=runGPS, args=("GPS", .5))
t4=Thread(target=runGraph, args=("Graph", .5))
t1.daemon=True
t2.daemon=True
t4.daemon=True
t1.start()
t2.start()
t4.start()
while True:
sleep(.5)
except KeyboardInterrupt: #Ctrl C or Ctrl D
exitapp=True
lcdflash()
matrixwritecommand([0x47,1,1])
ser_lcd.write("Cancelled ")
except:
lcdflash()
matrixwritecommand([0x47,1,1])
ser_lcd.write("ERROR ")
exitapp=True
raise
finally:
GPS_USB_Controller.gpsc.stopController()
GPS_USB_Controller.gpsc.join()
t1.join()
t2.join()
t4.join()
database_stuff.create_csv()
matrixwritecommand([0x47,1,2])
ser_lcd.write("CSV File Created")
matrixwritecommand([0x46])
Я не получаю ошибок или предупреждений, только в черном окне matplotlib, которое не должно иметь место. На экране matplotlib должен отображаться график в реальном времени.