首页 > 解决方案 > ROS python从订阅者回调中设置全局变量

问题描述

我正在使用下面的代码来尝试读取激光数据并确定我的机器人的哪一侧最靠近墙壁。激光数据在左右回调中成功打印,但尝试将这两个值分配给全局变量并在第三个函数中使用这些变量。但是,变量不会在我的 run() 函数中打印:

#!/usr/bin/env python

import rospy
import math
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist
from nav_msgs.msg import Odometry
from tf import transformations
from sensor_msgs.msg import LaserScan

subL_value = ''
subR_value = 'test'

def callbackLeft(msg) :
    subL_value = min(msg.ranges[0:49])

def callbackRight(msg) :
    global subR_value
    subR_value = min(msg.ranges[0:49])

def run() :
    # rospy.Subscriber('/scan_left', LaserScan, callbackLeft)
    rospy.Subscriber('/scan_right', LaserScan, callbackRight)

    # print('\tLeft: '), 
    # print(subL_value)
    print('\tRight: '), 
    global subR_value 
    print(subR_value)

if __name__ == "__main__":
    rospy.init_node('wall_detector')
    run()
    rospy.spin()

在上面的代码中,我只使用了subR_value,将其初始化为test的值,在callbackRight订阅者回调函数中将其重置,并尝试在 run() 函数中读取新值。

但是,运行脚本,我有两个问题:

  1. 打印的值是测试值,因此不会像预期的那样被覆盖
  2. 该脚本不会循环仅输出单个Right: 测试输出

我发现这篇文章是一个类似的问题,也是这个问题,但我似乎满足了必要的全局变量标签。

我错过了什么吗?

标签: python-2.7global-variablesros

解决方案


在您的代码中,您只调用run一次,它不会定期调用,因此也不会定期打印。

该节点在您的内部初始化__main__,进入run()例程一次,注册回调/scan_right,打印print(...)语句并退出例程。返回到主程序将停止退出由于rospy.spin()。只要每次/scan_right收到有关该主题的新消息时 ROS 还活着,callbackRight就会调用它来更新全局变量(但不打印它)。

如果您想在每次更新发生时打印变量,则必须调用print(...)内部回调。如果您想定期打印它(以固定速率但不是每次更新),您必须修改ros.spin()为类似

rate = rospy.Rate(10) # Fixed update frequency of 10hz
while not rospy.is_shutdown():
    # Call your print function here
    rate.sleep() 

我不会使用全局变量,而是将代码移动到一个类中。此外,不要将 print 与 ROS 一起使用,而是使用rospy.loginfo(),rospy.logwarn()rospy.logerr(). 正如本文底部已经讨论的那样,它们具有几个优点。


推荐阅读