'ROS topic is not published yet
I have this code which receives data from node (subscribe) and then inside this node I do some mathematical operation, then I want to publish the data to a certain topic.
#!/usr/bin/env python
import rospy
from std_msgs.msg import String, Float32
from math import cos,sin
import sys
import os
import logging
from types import *
import time
class exact_pose():
def callback_car_yaw(self, data):
self.car_yaw = data
def callback_line_pose(self,data):
self.line_pose = data
def init(self):
self.car_yaw = None
self.line_pose = None
def subscriber(self):
self.car_yaw_sub = rospy.Subscriber('~car/yaw',Float32, self.callback_car_yaw)
self.line_pose_sub = rospy.Subscriber('~line_pose',Float32, self.callback_line_detect_xL15)
def publisher(self):
self.exact_pose_pub = rospy.Publisher('exact_pose',Float32, queue_size=10)
rospy.Rate(1)
rospy.spin()
#sloving for exact pose
def calculation(self,):
while not rospy.is_shutdown():
self.exact_pose = self.line_pose_sub * cos(self.car_yaw_sub) + self.line_pose_sub * sin(self.car_yaw_sub)
info1 = Float32()
info1.data = self.exact_pose
self.exact_pose_pub.publish(info1)
rospy.Rate.sleep()
rospy.spin()
if __name__ == '__main__':
rospy.init_node('exact_pose', anonymous=True)
try:
ne = exact_pose()
except rospy.ROSInterruptException: pass
so what the code does, subscribe to a topic from a previous node, then do some mathematical operation for these data inside the topics, then publish the last result on separate Node
Solution 1:[1]
When requiring asynchronous communication, like in subscribers, multiple threads running in parallel will have to be involved. ROS uses callbacks in order to hide multi-threading required for subscribers from its users. When a new message arrives these callbacks will be added to a callback queue (whose maximum size can be defined for each publisher/subscriber) and then be processed. The way this works differs between C++ and Python:
- In C++ the callback queue is associated to a particular node and this queue has to be processed by calling the blocking
ros::spin()
once or repeatedly callingros::spinOnce()
. The processing of these callback queue happens sequentially by means of a spinner thread but you can deploy multiple spinner threads to increase the throughput as well as use different node handles that process different subscribers. A more detailed explanation can be found here. - In Python each subscriber is running in a different thread and therefore there the only thing that
rospy.spin()
does is block the main thread from returning and thus keep the subscriber threads alive. You can also replace it with awhile
loop as explained here.
In ROS2 the concept is similar but it is termed executors and further extends it with so called callback groups.
This means that you actually have to register the subscribers and publisher with their callbacks inside a initialisation routine and then you keep your node alive for the desired time, either with a while
loop or rospy.spin()
.
There is though no hard guarantee that all messages are actually processed. If your throughput is not sufficient (if your callbacks are executed too slowly) you will fill up the queue and eventually start dropping messages. If that is not what you need then have a look at the other communication methods - ROS services and actions. The other communication methods are though a bit more complicated.
Your code has several errors. You are lucky that Python is translated and not compiled and it never entered the relevant code parts..
- Functions like
subscriber
,publisher
andcalculation
are never called inside your code, meaning the publisher and subscriber are never registered. ros.Rate.sleep()
androspy.spin()
have nothing to do inside thepublisher
anccalculation
routines. They are used to put the thread into an endless loop as long as ROS is running. This happens once inside a program only and that should be the main loop for clarity!exact_pose
has actually to use the local values/class members inside the class likeself.line_pos
and not the subscribers likeself.line_pose_sub
. The subscribers are only executed when they receive new data. You can't force a subscriber to check for new data the way you seem to try it!while
andros.spin()
does not work in combination. In C++ there isros::spinOnce()
but there is no equivalent in Python. You therefore need to usewhile
androspy.Rate.sleep(d)
instead!rospy.Rate.sleep
requires a duration as first input argument and can't be left void.- You include a lot of libraries your code actually does not need.
I tried to restructure it and the following code works:
#!/usr/bin/env python
import rospy
from std_msgs.msg import Float32
from math import cos,sin
class exact_pose():
def __init__(self):
# Set default values
self.car_yaw = 0.0
self.line_pose = 0.0
# Initialise node
rospy.init_node("emergency_procedure", anonymous=True)
r = rospy.Rate(1)
# Register topics
self.car_yaw_sub = rospy.Subscriber('car/yaw',Float32, self.callback_car_yaw)
self.line_pose_sub = rospy.Subscriber('line_pose',Float32, self.callback_line_pose)
self.exact_pose_pub = rospy.Publisher('exact_pose',Float32, queue_size=10)
# Repeat the following code in a loop
while not rospy.is_shutdown():
# Perform some calculation and publish to topic
self.exact_pose = self.line_pose * cos(self.car_yaw) + self.line_pose * sin(self.car_yaw)
info1 = Float32()
info1.data = self.exact_pose
self.exact_pose_pub.publish(info1)
# Sleep for some time
rospy.Rate.sleep(r)
return;
def callback_car_yaw(self, data):
# Copy data to class
self.car_yaw = data
return;
def callback_line_pose(self,data):
# Copy data to class
self.line_pose = data
return;
if __name__ == '__main__':
try:
# Create instance of class when node is called
e = exact_pose()
except rospy.ROSInterruptException:
pass
Put this code inside your code into your .py
-file, open a new console and source the workspace with source devel/setup.bash
, then start the roscore
, open another console, source the workspace again and launch your Python node rosrun <package> <node>.py
. Finally launch another console, source the workspace again and output the topic published by the Python node rostopic echo /exact_pose
. If no other node is running this should output you 0.0
every second.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |