ros线程订阅API

代码功能

这段代码实现了一个ROS的临时Subscriber,主要功能是:

  1. 初始化时传入topic名称、消息类型、队列大小等参数

  2. 提供get_data()接口获取最新消息数据

  3. 调用get_data()时才会创建Subscriber,并开始接收数据

  4. 一定时间内如果没有调用,则会自动销毁Subscriber

  5. 可以重用,再次调用get_data()会重新创建Subscriber

主要涉及的功能点包括:

  1. init_subscriber() 创建Subscriber

  2. destroy() 销毁Subscriber

  3. callback() 接收到消息的回调函数

  4. createTimer() 创建定时器,用于判断超时关闭

  5. timer_callback() 定时器回调,判断是否需要关闭

  6. subscriber_flag 标志是否已经创建了Subscriber

  7. last_call_time 记录最后调用时间

这样就实现了一个按需创建,自动关闭的Subscriber,可以根据需要启用和关闭,减少不必要的资源占用。

如果需要我可以进一步详细解释其中的功能逻辑。请指出您需要我着重解释的部分。

代码

#!/usr/bin/env python
# coding=utf-8

import rospy  
import time
import os
import threading
from threading import Lock,Thread

# 导入相关的Python库

class TemporarySubscriber(object):

    # 自定义的临时Subscriber类

    DEFAULT_TIME_OUT = 15
    # 默认的超时时间,单位秒

    def __init__(self, name, data_class, queue_size=None, tcp_nodelay=False, timeout=DEFAULT_TIME_OUT):
      
        # 构造函数,初始化对象属性
        
        self.name = name  
        # Subscriber的topic名称
        
        self.data_class = data_class
        # Subscriber的消息类型
        
        self.queue_size = queue_size
        # Subscriber的队列大小
        
        self.tcp_nodelay = tcp_nodelay
        # TCP参数,禁用延迟发送
        
        self.timeout = timeout
        # 自定义的超时时间,单位秒
        
        self.last_call_time = 0
        # 记录最后一次调用get_data()的时间
        
        self.subscriber = None
        # Subscriber对象,初始化为None
        
        self.data = data_class()
        # 接收到的消息数据,初始化为空消息
        
        self.subscriber_flag = False
        # 标志是否已经创建了Subscriber
        

    def __del__(self):
        
        # 析构函数,在对象被删除时调用
        
        self.destroy()
        # 关闭并销毁Subscriber
        
    def destroy(self):
       
        # 关闭Subscriber
        
        if self.subscriber is not None:
            self.subscriber.unregister()
            # 如果Subscriber存在,注销注册
              
        self.subscriber = None
        # 置空
        
        self.data = self.data_class()
        # 消息数据重新初始化
        
        self.subscriber_flag = False
        # 标志置为False

    def init_subscriber(self):
        
        # 创建并初始化Subscriber
        
        self.subscriber = rospy.Subscriber(self.name, self.data_class, self.callback, queue_size=self.queue_size)
        # 创建Subscriber,订阅指定topic
        
        self.createTimer()
        # 创建定时器,用于判断超时关闭
        
    def get_data(self):
        
        # 获取订阅的数据
        # 如果需要会首先创建Subscriber
        
        self.last_call_time = time.time()
        # 更新最后调用时间
        
        if  not self.subscriber_flag:
            
            self.subscriber_flag = True
            # 将标志置为True
            
            self.init_subscriber()
            # 创建并初始化Subscriber
            
            return self.data
            
        else:
            
            return self.data
            

    def callback(self, data):
        
        # 接收到订阅消息的回调函数
        
        self.data = data
        # 保存接收到的消息数据

    def createTimer(self):
      
        # 创建定时器,用于判断是否需要关闭Subscriber
        
        timer = threading.Timer(3 ,self.timer_callback) 
        timer.setDaemon(True)
        timer.start()

    def timer_callback(self):
      
        # 定时器回调函数
      
        if time.time() - self.last_call_time >= self.timeout:
            
            self.destroy()
            # 如果超过指定时间没有调用,关闭Subscriber
            
        else:
            
            self.createTimer()
            # 否则重新创建定时器

举个粒子吧

这个临时Subscriber的使用方法如下:

  1. 导入类:
from temporary_subscriber import TemporarySubscriber
  1. 创建实例:
sub = TemporarySubscriber("/scan", LaserScan)

需要传入topic名称和消息类型。

  1. 调用get_data()获取数据:
scan_data = sub.get_data()

第一次调用会创建Subscriber,开始接收数据。

scan_data会包含接收到的最新消息。

  1. 获取数据后进行处理:
ranges = scan_data.ranges
print(min(ranges))
  1. 一段时间后Subscriber会自动关闭。

  2. 再次获取数据会重新创建:

scan_data = sub.get_data() 

这样就可以实现按需获取数据,不需要长时间运行Subscriber。

在使用上就是导入这个类,创建实例,然后调用get_data()获取数据即可,比较简单方便。

需要注意超时时间设置合理,不要太短,保证有足够时间来接收到数据。

如果有别的问题可以继续讨论。

你可能感兴趣的:(ROS,多线程,订阅者)