Ros_posible_python_mistake

Ros_posible_python_mistake

伙计们,我正在制作基本的 运行 并停止 ROS 模拟程序,我发现了一个问题。 我不知道为什么,当回调函数 运行s self.l_scan = scan_data -> 像它应该的那样更新。 但是当is_obstacle成员函数运行s。 self.l_scan 是空的。我可能有一些拼写错误,但我试着找了一个小时,但我找不到错误。主题 /scan 来自 Turtlebot,运行 应该如此。我通过回声试过了。

代码

#!/usr/bin/env python
import rospy
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist
import math

class Robot(object):
    def __init__(self):
        # Params
        self.l_scan = LaserScan()
        self.loop_rate = rospy.Rate(10)
        self.velocity = Twist()

        self.pub = rospy.Publisher("/cmd_vel", Twist, queue_size=10)
        self.sub = rospy.Subscriber("/scan", LaserScan, self.callback)

    def callback(self,scan_data):
        self.l_scan = scan_data
        print("readed")

    def is_obstacle(self,distance):
        print(self.l_scan)
        slice_of_array = self.l_scan.ranges[174: 184+1]
        if min(slice_of_array) < distance:
            return True
        else:
            return False

    def stop(self):
        print("stop")    
        self.velocity = Twist()
        self.pub.publish(self.velocity)

    ## move until find obstacle closer than 0.6, laser [-5,+5] degrees
    def move(self):
        self.velocity.linear.x = 1

        while not self.is_obstacle(0.6):
            print("moving")
            self.pub.publish(velocity)
            self.loop_rate.sleep()
        self.stop()

## rotate until find obstacle greater then 3
##def rotate():
##    global l_scan
##    laser_sub = rospy.Subscriber("/scan", LaserScan, scan_callback)
##    vel_pub = rospy.Publisher("/cmd_vel", Twist)

if __name__ == '__main__':
    try:
        rospy.init_node('Turtle_robot_control', anonymous=True)
        my_robot = Robot()
        my_robot.move()

    except rospy.ROSInterruptException:
        rospy.loginfo("node terminated.")

输出

header: 
  seq: 0
  stamp: 
    secs: 0
    nsecs:         0
  frame_id: ''
angle_min: 0.0
angle_max: 0.0
angle_increment: 0.0
time_increment: 0.0
scan_time: 0.0
range_min: 0.0
range_max: 0.0
ranges: []
intensities: []
readed
Traceback (most recent call last):
  File "/home/trahery/catkin_ws/src/ros_essentials_cpp/src/topic04_perception02_laser/robot_control.py", line 54, in <module>
    print(my_robot.is_obstacle(0.2))
  File "/home/trahery/catkin_ws/src/ros_essentials_cpp/src/topic04_perception02_laser/robot_control.py", line 24, in is_obstacle
    if min(slice_of_array) < distance:
ValueError: min() arg is an empty sequence

您的问题是因为您在完成构造函数后立即调用 move;您在哪里设置订阅者。这意味着收到任何数据的可能性相对为 0。相反,您应该在 尝试切片列表和对数据进行其他操作之前 验证您是否有足够的数据;因为这些操作假设您确实有数据。像这样:

def is_obstacle(self,distance):
    if len(self.l_scan.ranges) < 185:
        rospy.logwarn(f'Not enough data for calculation. {self.l_scan.ranges} points read')
        return False
    slice_of_array = self.l_scan.ranges[174: 184+1]
    if min(slice_of_array) < distance:
        return True
    else:
        return False

请注意,这会导致代码的其他部分出现问题。现在它将立即退出循环并停止,但还会记录一条错误消息。要解决此问题,并根据您当前的代码设置,您需要验证是否已收到进入循环的数据:

while len(self.l_scan.ranges) == 0:
    self.loop_rate.sleep()
while not self.is_obstacle(0.6):
    #...

最后一点,在特征稀疏的环境中,如果没有检测到足够的激光扫描点,您的代码也可能会中断。