ROS主题尚未发布

ROS topic is not published yet

我有这段代码可以从节点(订阅)接收数据,然后在这个节点内我做了一些 数学运算,那我想把数据发布到某个话题

#!/usr/bin/env python

import rospy
from std_msgs.msg import String, Float32
from math import cos,sin

import sys
import os
import logging
from types import *
import time

class exact_pose():

    def callback_car_yaw(self, data):
        self.car_yaw = data

    def callback_line_pose(self,data):
        self.line_pose = data

        
    def init(self):
      
 
        self.car_yaw = None
        self.line_pose = None
      

    def subscriber(self):
        
 
            
        self.car_yaw_sub = rospy.Subscriber('~car/yaw',Float32, self.callback_car_yaw)
            
        self.line_pose_sub = rospy.Subscriber('~line_pose',Float32, self.callback_line_detect_xL15)

    def publisher(self):

        self.exact_pose_pub = rospy.Publisher('exact_pose',Float32, queue_size=10)
        

        rospy.Rate(1)
        rospy.spin()
      
      
        #sloving for exact pose 

    def calculation(self,):
        while not rospy.is_shutdown():

            self.exact_pose = self.line_pose_sub * cos(self.car_yaw_sub) + self.line_pose_sub * sin(self.car_yaw_sub)
            info1 = Float32()
            info1.data = self.exact_pose
            self.exact_pose_pub.publish(info1)


            rospy.Rate.sleep()
            rospy.spin()


if __name__ == '__main__':
    rospy.init_node('exact_pose', anonymous=True)
    try:
      ne = exact_pose()

    except rospy.ROSInterruptException: pass

所以代码是做什么的,从前一个节点订阅一个主题,然后对主题内的这些数据进行一些数学运算,然后在单独的节点上发布最后的结果

当需要异步通信时,例如在订阅者中,必须涉及并行的多个线程 运行。 ROS 使用 callbacks 来向其用户隐藏订阅者所需的多线程。当新消息到达时,这些回调将被添加到回调队列(其最大大小可以为每个 publisher/subscriber 定义)然后被处理。 C++ 和 Python:

的工作方式不同
  • 在 C++ 中,回调队列与特定节点相关联,必须通过调用阻塞 ros::spin() 一次或重复调用 ros::spinOnce() 来处理此队列。这些回调队列的处理通过微调线程按顺序发生,但您可以部署多个微调线程以增加吞吐量以及使用不同的节点句柄来处理不同的订阅者。可以找到更详细的解释here.
  • 在Pythoneach subscriber is running in a different thread and therefore there the only thing that rospy.spin() does is block the main thread from returning and thus keep the subscriber threads alive. You can also replace it with a while loop as explained here.

在 ROS2 中,这个概念是相似的,但它被称为 executors 并通过所谓的回调组进一步扩展它。

这意味着您实际上必须在初始化例程中使用回调注册订阅者和发布者,然后让您的节点在所需的时间内保持活动状态,或者使用 while循环或rospy.spin().

虽然不能硬性保证所有消息都得到实际处理。如果您的吞吐量不足(如果您的回调执行得太慢),您将填满队列并最终开始丢弃消息。如果这不是您所需要的,那么请查看其他通信方法 - ROS services and actions。其他通讯方式虽然有点复杂。


您的代码有几个错误。你很幸运 Python 被翻译而不是编译并且它从未进入相关代码部分..

  • subscriberpublishercalculation 等函数永远不会在您的代码中调用,这意味着发布者和订阅者永远不会注册。
  • ros.Rate.sleep()rospy.spin()publishercalculation 例程中没有任何关系。只要ROS为运行,它们就是用来让线程陷入死循环的。这只在程序内部发生一次,为了清楚起见,这应该是主循环!
  • exact_pose 实际上必须使用 class 中的本地 values/class 成员,如 self.line_pos,而不是像 self.line_pose_sub 这样的订阅者。订阅者只有在收到新数据时才会执行。您不能强迫订阅者按照您尝试的方式检查新数据!
  • whileros.spin() 不能组合使用。在 C++ 中有 ros::spinOnce() 但在 Python 中没有等价物。因此,您需要使用 whilerospy.Rate.sleep(d) 来代替!
  • rospy.Rate.sleep 需要一个持续时间作为第一个输入参数,并且不能留空。
  • 您包含了很多您的代码实际上不需要的库。

我尝试对其进行重组,以下代码有效:

#!/usr/bin/env python

import rospy
from std_msgs.msg import Float32
from math import cos,sin

class exact_pose():
  def __init__(self):
    # Set default values
    self.car_yaw = 0.0
    self.line_pose = 0.0

    # Initialise node
    rospy.init_node("emergency_procedure", anonymous=True)
    r = rospy.Rate(1)

    # Register topics
    self.car_yaw_sub = rospy.Subscriber('car/yaw',Float32, self.callback_car_yaw)
    self.line_pose_sub = rospy.Subscriber('line_pose',Float32, self.callback_line_pose)
    self.exact_pose_pub = rospy.Publisher('exact_pose',Float32, queue_size=10)

    # Repeat the following code in a loop
    while not rospy.is_shutdown():
      # Perform some calculation and publish to topic
      self.exact_pose = self.line_pose * cos(self.car_yaw) + self.line_pose * sin(self.car_yaw)
      info1 = Float32()
      info1.data = self.exact_pose
      self.exact_pose_pub.publish(info1)
      # Sleep for some time
      rospy.Rate.sleep(r)
    return;

  def callback_car_yaw(self, data):
    # Copy data to class
    self.car_yaw = data
    return;

  def callback_line_pose(self,data):
    # Copy data to class
    self.line_pose = data
    return;

if __name__ == '__main__':
  try:
    # Create instance of class when node is called
    e = exact_pose()
  except rospy.ROSInterruptException:
    pass

将代码中的这段代码放入 .py 文件中,打开一个新的控制台并使用 source devel/setup.bash 源工作区,然后启动 roscore,打开另一个控制台,源再次打开工作区并启动您的 Python 节点 rosrun <package> <node>.py。最后启动另一个控制台,再次获取工作区并输出 Python 节点 rostopic echo /exact_pose 发布的主题。如果没有其他节点是 运行 这应该输出你 0.0 每秒。