python多线程处理ROS消息数据

最近使用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()

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ROS(Robot Operating System)是一个用于构建机器人应用程序的开源框架。它提供了一系列工具、库和约定,用于简化机器人软件开发的过程。ROS中,多线程发布订阅是一常见的通信机制,用于实现不同节点之间的数据传。 在ROS中,发布者(Publisher)节点责将数据发布到特定的主题(Topic),而订阅者(Subscriber)节点则负责从主题中接收数据多线程发布订阅允许多订阅者同时接收来自同一个主题的数据,从而提高系统的并发性能。 在Python中使用ROS进行多线程发布订阅,可以按照以下步骤进行: 1. 导入所需的ROS库和模块: ```python import rospy from std_msgs.msg import String ``` 2. 初始化ROS节点: ```python rospy.init_node('node_name') ``` 3. 创建发布者对象,并指定要发布的主题和消息类型: ```python pub = rospy.Publisher('topic_name', String, queue_size=10) ``` 4. 创建订阅者回调函数,用于处理接收到的消息: ```python def callback(data): rospy.loginfo("Received: %s", data.data) ``` 5. 创建订阅者对象,并指定要订阅的主题和消息类型,以及回调函数: ```python sub = rospy.Subscriber('topic_name', String, callback) ``` 6. 编写发布数据的逻辑,并使用发布者对象发布消息: ```python rate = rospy.Rate(10) # 设置发布频率为10Hz while not rospy.is_shutdown(): msg = "Hello ROS!" pub.publish(msg) rate.sleep() ``` 以上是使用ROS进行多线程发布订阅的基本步骤。通过创建发布者和订阅者对象,并在回调函数中处理接收到的消息,可以实现节点之间的数据传输和通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值