Hi,
Coding publisher and subscriber were easy but they are getting confusing for me because of rospy.spin(), rospy.on_shutdown() and other related functions that are used many times in different ways in tutorials and lectures. I was about to provide some samples from lectures and tutorials but it is also messy so that I will ask rather simple questions to get rid of my doubts.
-
I understand that rospy.spin()
is used when a subscriber is involved. But where in the code? Where should it be placed? Can i place it in a subscriber at a random place? Also, why did not you use spin function in odom_topic_subscriber
in this tutorial? That collapses what I learnt in ROS courses.
-
rospy.on_shutdown()
is used but how and why? For instance as below, shutdownhook
function is passed to rospy.on_shutdown()
.
2.1. Is that just to modify variable of ctrl_c
as True
so that the while loop is interrupted? If so, I have read on internet that rospy.on_shutdown()
function does not take any argument. Is passing shutdownhook function to on_shutdown for preventing getting odometry data and nothing related with shutting down the node?
2.2. rospy.on_shutdown()
is inside the main function and is not called from another function. As soon as the program runs, isn’t it executed and shutdown the rosnode? Or, is rospy.on_shutdown()
called ONLY WHEN ctrl+c is pressed by the user? In short, how and when
is it called?
ctrl_c = False
def shutdownhook():
# works better than the rospy.is_shut_down()
global ctrl_c
print "shutdown time!"
ctrl_c = True
rospy.on_shutdown(shutdownhook)
while not ctrl_c:
data = odom_reader_object.get_odomdata()
rospy.loginfo(data)
rate.sleep()
-
For the code below, you already subscribe to /odom
topic and call topic_callback
function. That is to read Odometry data. So why did you also create get_odomdata
function and call it from while loop in the main function? That seems to me like doing the same thing with more function. I mean, I think we could achieve the same result without while loop in the main function since we subscribe to /odom topic. Also, i did not understand this assignment: self._odomdata = msg
. Isn’t the msg
already Odometry()
. Can you please elaborate the code below line-by-line if possible? I really need an answer. I am so confused.
class OdomTopicReader(object):
def __init__(self, topic_name = '/odom'):
self._topic_name = topic_name
self._sub = rospy.Subscriber(self._topic_name, Odometry, self.topic_callback)
self._odomdata = Odometry()
def topic_callback(self, msg):
self._odomdata = msg
rospy.logdebug(self._odomdata)
def get_odomdata(self):
return self._odomdata
Thanks in advance.
Hi @enderayhan,
I’ll try to address your questions.
-
Check this link / explanation: https://answers.ros.org/question/332192/difference-between-rospyspin-and-rospysleep/
You basically use it to keep your node running, when you have a node that doesn’t do anything. A topic subscriber is a good example. The subscribers run in their own thread and execute their callbacks. The main node you launched has to be open and running though, otherwise the script would stop. So you use rospy.spin() to keep it in an infinite loop
- Usually you use infinite loops like this:
while rospy.is_shutdown() == false:
This will run loops, as long as rospy is running. So the code breaks, when you interrupt ROS. Sometimes this doesnt work for some loops, so we set a global variable ctrl_c
, which gets set to True, when we shutdown ros. And we check in our loops, that that variable is false. This is especially the case, when we have multiple threads running, as ctrl-c (pressing it on the keyboard), usually only aborts the active thread we started, and not necessarily the threads that our code started.
rospy.on_shutdown() gets triggered, when ROS shuts down, which is usually done by either pressing ctrl-c or the code finishing
-
This code is not meant to be run alone, like the topic subscribers before, but for the class to be imported by our main program.
class OdomTopicReader(object): #create a class object, we can import into main program
def __init__(self, topic_name = '/odom'): #initialize class
self._topic_name = topic_name
self._sub = rospy.Subscriber(self._topic_name, Odometry, self.topic_callback) #create subsciber
self._odomdata = Odometry() # create a class variable of the type Odometry()
# the subscriber runs in its own thread and calls this function every time, it receives a new topic
def topic_callback(self, msg):
self._odomdata = msg #the odometry data gets saved in our class variable
rospy.logdebug(self._odomdata)
#in our main code we can call this function, to immediately return the last odometry
#that was received
def get_odomdata(self):
return self._odomdata
1 Like
Dear @simon.steinmann91,
To be honest, I could not relate your answers to my questions exactly.
- I was trying to ask that why didn’t you use spin function in the odom_topic_subscriber in sphero tutorial? is it because the node does something outside of it callback function? Here is not clear
- The question is:
- you define
self._odomdata = Odometry()
inside init function. You also define self._odomdata = msg
inside callback funtion. What is the difference? I mean self._odomata = Odometry()
becomes pointless. Am i wrong? Soo confused.
1 Like
@enderayhan,
Adding to what @simon.steinmann91 already said:
-
Actually, it’s not mandatory to use rospy.spin()
, for ROS Python subscribers (it’s mandatory for C++). It can be replaced by the kind of while loop in the code above (just to keep the main program from exiting). See this post for further clarifications:
-
rospy.on_shutdown()
is not meant to be called the way you think. It’s a “configuration” statement that tells ROS the function to be called when it’s shutting down. In other words, when we write rospy.on_shutdown(shutdownhook)
, we are saying “Hey ROS, whenever you are shutting down please call the shutdownhook() function!”
-
The line self._odomdata = Odometry()
initializes self._odomdata
with an empty odometry message while the line self._odomdata = msg
actually assigns it a real odometry message from the subscriber.
1 Like
@bayodesegun Thanks a lot. That’s the understandable answer !