Error: responded with an error: b"error processing request: 'SqBB' object has no attribute 'Obst_detect

I keep getting the error when I try to call the service, I don’t know the reason, the class code is this, its for making the robot move in squares and stop if there is an obstacle:

#! /usr/bin/env python

import rospy 
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
import time 

class SqBB:
    def __init__(self):
        self.pub = rospy.Publisher('/cmd_vel',Twist,queue_size=1)
        self.sub = rospy.Subscriber('/scan',LaserScan,self.callback)
        self.action = Twist()
        #self.rate = rospy.Rate(1)
        self.ctrlC = False 
        rospy.on_shutdown(self.exitplan)
        while self.pub.get_num_connections()<1:
            print("waiting for publisher /cmd_vel---------")
        print("-------------------------------------")

    def callback(self,msg):
        
        if (min(msg.ranges)>0.2):
            self.Obst_detect=False
        else:
            print("Obstacle detected",min(msg.ranges))
            self.Obst_detect=True
            self.stop()

        #self.view = msg
        #self.fview = msg.ranges[89] 
        #if self.fview > 0.3:
        #    self.obstdetect = True 
        #else:
        #    self.obstdetect = False 
    
    def stop(self):
        self.action.linear.x = 0 
        self.action.angular.z = 0
        self.pub.publish(self.action)
    
    def line(self):
        self.action.linear.x = 0.3 
        self.action.angular.z = 0
        if not self.Obst_detect < 0.3:
            self.pub.publish(self.action)
            for i in range(50):
                if not self.Obst_detect < 0.3:
                    rospy.sleep(0.1)
                else: 
                    print('Obstacle deceted so we stop')
                    self.stop()
                    break
    
    def rotate(self):
        self.action.linear.x = 0 
        self.action.angular.z = 0.3
        self.pub.publish(self.action)
        rospy.sleep(5.5)
        self.stop()
    
    def exitplan(self):
        self.ctrlC = True
        self.stop()
    
    def squaremotion(self):
        self.line()
        self.rotate()
        self.line()
        self.rotate()
        self.line()
        self.rotate()
        self.line()
        self.stop()

if __name__ == '__main__':
    rospy.init_node('classmove',anonymous=True)
    movebb = SqBB()
    movebb.line

the service code is this:

#! /usr/bin/env python

import rospy
from square_service.srv import MoveInSquare, MoveInSquareResponse
from movestat import SqBB

def serback(request):
    result = MoveInSquareResponse
    motion = SqBB()
    motion.squaremotion()
    result.complete = True 
    return result 

rospy.init_node('callsquare')
ser = rospy.Service('/sqmoveser',MoveInSquare,serback)
rospy.spin()

Hi @mkakram , can you share the error that’s shown on program execution as is. also share the unit number within the course

[ERROR] [1643277449.403695, 3055.157000]: Error processing request: ‘SqBB’ object has no attribute ‘Obst_detect’
[‘Traceback (most recent call last):\n’, ’ File “/opt/ros/noetic/lib/python3/dist-packages/rospy/impl/tcpros_service.py”, line 632, in _handle_request\n response = convert_return_to_response(self.handler(request), self.response_class)\n’, ’ File “/home/user/catkin_ws/src/square_service/scripts/square_server.py”, line 10, in serback\n motion.squaremotion()\n’, ’ File “/home/user/catkin_ws/src/square_service/scripts/movestat.py”, line 66, in squaremotion\n self.line()\n’, ’ File “/home/user/catkin_ws/src/square_service/scripts/movestat.py”, line 44, in line\n if not self.Obst_detect < 0.3:\n’, “AttributeError: ‘SqBB’ object has no attribute ‘Obst_detect’\n”]
Obstacle detected 0.11999999731779099
Obstacle detected 0.11999999731779099
then it start printing the distance but the call already gives the error in the topic

You should first declare the boolean variable

Hi @mkakram , i am assuming that you are doing the problem mentioned in unit 6, service quiz 6.4.

  1. in the quiz, its not asked to check for obstacles, so there is no need to subscribe to a topic.

  2. There is no sensors scanning for obstacles in BB8 unlike other robots (not that its asked in the exercise). you can see this by using the cmd

user:~$ rostopic list | grep bb8


/bb8/camera1/camera_info
/bb8/camera1/image_raw
/bb8/camera1/image_raw/compressed
/bb8/camera1/image_raw/compressed/parameter_descriptions
/bb8/camera1/image_raw/compressed/parameter_updates
/bb8/camera1/image_raw/compressedDepth
/bb8/camera1/image_raw/compressedDepth/parameter_descriptions
/bb8/camera1/image_raw/compressedDepth/parameter_updates
/bb8/camera1/image_raw/theora
/bb8/camera1/image_raw/theora/parameter_descriptions
/bb8/camera1/image_raw/theora/parameter_updates
/bb8/camera1/parameter_descriptions
/bb8/camera1/parameter_updates

You notice that there is no topic /scan under /bb8.

The only other topic called /scan that exists,exists outside of the namespace /bb8/-- is not transmitting anything,which can be proved by

user:~$ rostopic echo /scan
WARNING: topic [/scan] does not appear to be published yet

Conclusion: Try rewriting the code without subscribing to anything, since its only asked to move the robot around and not to check for obstacles.

Its the code for the first ROS basics real robot project Turtlebot but I’m gonna check if that is the issue

no the scan topic exists here

Hi @mkakram , can you mention the unit number and exercise number:

Sample of Unit number:

image

exercise number sample:

image

Screenshot 2022-01-27 193256

It’s this one part 2 services

Hi @mkakram ,
The corrected code is below. I have commented where the correction were made and why. It worked on my system, do check if this solves the problem

#! /usr/bin/env python

import rospy 
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
import time 

class SqBB:
    def __init__(self):
        self.pub = rospy.Publisher('/cmd_vel',Twist,queue_size=1)
        self.sub = rospy.Subscriber('/scan',LaserScan,self.callback)
        self.action = Twist()
        #self.rate = rospy.Rate(1)
        self.ctrlC = False
        #add  self.Obst_detect here so that its avaialble to the class during initialisation itself
        self.Obst_detect=False
        rospy.on_shutdown(self.exitplan)
        while self.pub.get_num_connections()<1:
            print("waiting for publisher /cmd_vel---------")
        print("Publsiher Ready")

    def callback(self,msg):
        # store laser reading in variable called self.distance_to_obstacle,
        #storing only the front laser value and NOT minimum of all laser reading, since there will 
        #be an obstacle somewhere near the robot at all points, but not necessarily the front
        self.distance_to_obstacle=msg.ranges[89]
        if (self.distance_to_obstacle>0.2):
            self.Obst_detect=False
        else:
            print("Obstacle detected",min(msg.ranges))
            self.Obst_detect=True
            self.stop()

        #self.view = msg
        #self.fview = msg.ranges[89] 
        #if self.fview > 0.3:
        #    self.obstdetect = True 
        #else:
        #    self.obstdetect = False 
    
    def stop(self):
        print("Stoping")
        self.action.linear.x = 0 
        self.action.angular.z = 0
        self.pub.publish(self.action)
    
    def line(self):
        print("Moving forward")
        self.action.linear.x = 0.1
        self.action.angular.z = 0
        # Here you were tring to <0.3 with a bool value,hence you were getting error
        # if not self.Obst_detect < 0.3:
        if not self.Obst_detect:
            self.pub.publish(self.action)
            for i in range(25):
                if not self.Obst_detect:
                    rospy.sleep(0.1)
                else: 
                    print('Obstacle deceted so we stop')
                    self.stop()
                    break
        print("Finished Moving")
    
    def rotate(self):
        print("Rotating")
        self.action.linear.x = 0 
        self.action.angular.z = 0.1
        self.pub.publish(self.action)
        rospy.sleep(5.5)
        self.stop()
    
    def exitplan(self):
        self.ctrlC = True
        self.stop()
    
    def squaremotion(self):
        self.line()
        self.rotate()
        self.line()
        self.rotate()
        self.line()
        self.rotate()
        self.line()
        self.stop()

if __name__ == '__main__':
    rospy.init_node('classmove',anonymous=True)
    movebb = SqBB()
    movebb.line()