最近使用python处理时间序列数据,使用简单的串行输出结果会导致数据严重的滞后性,(matplotlib输出动态图片时会有短暂的pause),看了一些网上的方法,其中使用pyqt5进行输出时,由于ROS的msg送不到ndarrary中,导致数据不刷新(个人水平有限),如下使用多线程的方法,数据滞后性得到了明显的改善。
#!/usr/bin/env python
#coding=utf-8
from math import floor
from tokenize import single_quoted
import numpy as np
from numpy.fft import fft
import scipy.io
from scipy import signal
import matplotlib.pyplot as plt
from matplotlib.pylab import mpl
from mimetypes import init
import rospy
from gaitech_bci_bringup.msg import TransverseBipolar
import time
import threading
data_lenth = 500
list_o1_o2 = np.zeros(data_lenth)
def get_data(msg):
global list_o1_o2
list_o1_o2[:-1] = list_o1_o2[1:]
list_o1_o2[-1] = msg.o1_o2
def data_make(msg):
global list_o1_o2 , list1_o1_o2 , list2_o1_o2
global t , f_oneside , X_oneside , max_indx
get_data(msg)
len_data = data_lenth
Fs = 1000.0
Ts = 1.0 / Fs
t = (np.arange(0,len_data,dtype = float)) * Ts
h_hz = 5
wn_1 = 2*h_hz/1000.0
b1,a1 = signal.butter(8,wn_1,'highpass')
list1_o1_o2 = signal.filtfilt(b1 , a1 , list_o1_o2)
l_hz = 30
wn_2 = 2*l_hz/1000.0
b2,a2 = signal.butter(8,wn_2,'lowpass')
list2_o1_o2 = signal.filtfilt(b2 , a2 , list1_o1_o2)
X = fft(list2_o1_o2)
N = len(X)
n = np.arange(N)
T = N/Fs
freq = n/T
n_oneside = N//2
f_oneside = freq[:n_oneside]
X_oneside =X[:n_oneside]/n_oneside
max_indx = np.argmin(np.abs(X_oneside))
def figure_out(msg):
global list_o1_o2 , list1_o1_o2 , list2_o1_o2
global t , f_oneside , X_oneside , max_indx
# plt.plot()
# plt.clf()
# plt.title('python-12hz')
# plt.plot(f_oneside, np.abs(X_oneside))
# plt.plot(f_oneside[max_indx],np.abs(X_oneside)[max_indx],'ks')
# show_max='['+str(f_oneside[max_indx])+ ' , ' +str(np.abs(X_oneside)[max_indx])+']'
# plt.annotate(show_max,xytext=(f_oneside[max_indx],np.abs(X_oneside)[max_indx]),xy=(f_oneside[max_indx],np.abs(X_oneside)[max_indx]))
# plt.xlabel('Freq (Hz)')
# plt.ylabel('FFT Amplitude |X(freq)|')
# plt.xlim(0,30)
# plt.pause(0.01)
# plt.ioff()
plt.clf()
plt.plot(t , list_o1_o2)
plt.pause(0.0000001)
plt.ioff()
def Data_Callback(msg):
# t0 = threading.Thread(target=get_data(msg))
t1 = threading.Thread(target=data_make(msg))
t2 = threading.Thread(target=figure_out(msg))
# t0.start()
t1.start()
t2.start()
def Data_Suber():
rospy.init_node('gaitech_bci_device', anonymous=True)
rospy.Subscriber("/gaitech_bci_device_1/data_tb" , TransverseBipolar, Data_Callback)
rospy.spin()
if __name__ == '__main__':
Data_Suber()