I wrote this class for a laser/scan subscriber:
#! /usr/bin/env python
import rospy
from sensor_msgs.msg import LaserScan
import time
class laser_sub_class(object):
def __init__(self):
self.subscriber = rospy.Subscriber("/kobuki/laser/scan", LaserScan, self.laser_callback)
self.ctrl_c = False
rospy.on_shutdown(self.shutdownhook)
self.rate = rospy.Rate(10)
def shutdownhook(self):
rospy.loginfo("laser shutdownhook! stopped!")
self.ctrl_c=True
def laser_callback(self, msg):
rospy.loginfo("laser_callback")
self.range= msg.ranges
if __name__=="__main__":
rospy.init_node("laser_scan_subscriber")
laserScan_sub_ob = laser_sub_class()
rospy.spin()
and, I wrote this service_server that makes an object of mentioned class:
#! /usr/bin/env python
import rospy
from std_srvs.srv import Trigger, TriggerResponse
from laser_scan_subscriber import laser_sub_class
import time
def serv_callback(request):
rospy.loginfo("The Service obstacle_avoidance_service has been called")
laser_sub = laser_sub_class()
#time.sleep(0.3)
r = laser_sub.range
r_min= min(r)
min_ind = r.index(r_min)
response = TriggerResponse()
response.success = True
response.message = "straight"
if r_min <0.4:
response.success = False
if min_ind<360:
response.message = "left"
elif min_ind>360:
response.message = "right"
elif min_ind==360:
if r[0]>r[710]:
response.message = "right"
else:
response.message = "left"
return response
rospy.init_node("obst_avoid_service_server")
rospy.Service("obstacle_avoidance_service", Trigger, serv_callback)
rospy.loginfo("Service /obstacle_avoidance_service Ready")
rospy.spin()
When I call this service, I get this:
âlaser_sub_classâ object has no attribute ârangeâ.
why???
and another issue:
when I uncomment the time.sleep(0.3) in serv_callback, the code works properly, but why?!
The attribute is ranges not range. You also should look at youâre solution to the first quiz where turtlebot had to avoid the wall. In their you should see what else needs changing. One small hint this is not the place to make your responses think about python and the structures available for storing and returning the laser directions.
Thanks,
in self.range= msg.ranges, it is msg.ranges and it is correct.
then it is saved to object (from laser_sub_class class) in self.range.
but when I call the object in service_server file, I get this error:
âlaser_sub_classâ object has no attribute ârangeâ.
the ârangeâ in self.range can be any name and that is not the problem.
You canât import an entire class unless you turn it into a module. At this point in the project starting to turn youâre classes into modules that can be imported like numpy or some other common python package will only add to the complexity of the project. Import methods from youâre classes as needed. In this case you could do something like:
def laser_directions(self):
directionsâŚ
put what you need in this method and then from laser_scan_sub import laser_directions. You will find this much easier.
laser_sub is an object from laser_sub_class class and it is made in the service call_back function (serv_callback).
in laser_sub_class , subscriber is called and in its call_back function (laser_callback), ranges of laser/scan are read and saved in self.range.
now, the object (laser_sub) starts the subscriber, but it doesnât have the self.range.
thanks for your comment, but I donât understand the problem yet!
The problem is in this statement:
from laser_scan_subscriber import laser_sub_class you canât turn an entire class into an object which is what you are trying to do with this import and the statement laser_sub = laser_sub_class() you can only turn a class into a module and then import the methods from their. You should do this from laser_sub_class import laser_callback this just imports the method(function). So a method is basically a function that has been defined within a class. Write it once and import it into any number of other classes as well as using it within the class itself. This is the main concept of object oriented programming, write once use everywhere. So fill your class with the required method(functions) that can be imported with: from class A import method a, method b and so on theirs no limit to the number of methods you can import like this. All youâre classes should be written with this in mind. I hope this makes it a little more clear.
2 Likes
Thanks again,
But still, I donât truly understand the problem!
this is a code from section âusing python classesâ:
#! /usr/bin/env python
import rospy
from std_srvs.srv import Empty, EmptyResponse
from bb8_move_circle_class import MoveBB8
def my_callback(request):
rospy.loginfo("The Service move_bb8_in_circle has been called")
movebb8_object = MoveBB8()
movebb8_object.move_bb8()
rospy.loginfo("Finished service move_bb8_in_circle")
return EmptyResponse()
rospy.init_node('service_move_bb8_in_circle_server')
my_service = rospy.Service('/move_bb8_in_circle', Empty , my_callback)
rospy.loginfo("Service /move_bb8_in_circle Ready")
rospy.spin() # mantain the service open.
bb8_move_circle_class is the python file with the class MoveBB8 defined in it,
and
movebb8_object = MoveBB8()
is like the code Iâve written and it is correct.
The difference is youâre not importing a class, you are just making an object of the class which python allows. Importing a class is where you run into trouble.
You can use a class to make an object like movebb8_object = MoveBB8 since you are not importing
this is the key difference. If you tried to import the MoveBB8 class into another class like this:
from bb8_class import MoveBB8 and tried to make an object like movebb8_object = MoveBB8() it will give you an error. I would need to so the full code regarding the time.sleep(0.3) and you should really start a new topic if you have new question. This not only helps you by keeping each question/answer focused on one topic, but also the community. Should someone else have a similar question. To sum it up:
- Itâs OK to do this movebb8_object = MoveBB8() because no importing is required .
- If you were to try and import the MoveBB8() class and try movebb8_object = MoveBB8() it would fail with an error.
This is what distinguishes a module from a class.
1 Like