C++ subscriber not working for first messages
Just out of curiosity, I modified the simple c++ publisher and simple python publisher. I got rid of the while loop and did the following.
c++
loop_rate.sleep();
msg.data = "hello world 1";
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
msg.data = "hello world 2";
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
msg.data = "hello world 3";
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
python
rate.sleep()
hello_str = "1-hello world py"
pub.publish(hello_str)
rate.sleep()
hello_str = "2-hello world py"
pub.publish(hello_str)
rate.sleep()
hello_str = "3-hello world py"
pub.publish(hello_str)
rate.sleep()
Now when I run both publishers one after the other, rostopic echo
gives me the following, which is expected
data: "1-hello world py"
---
data: "2-hello world py"
---
data: "3-hello world py"
---
data: "hello world 1"
---
data: "hello world 2"
---
data: "hello world 3"
---
The problem is, c++ subscriber callback is not triggered for the first messages. To be exact, it gets triggered after only the 3rd message for c++ publisher and after the 2nd message for python publisher. After that it works fine. This is the c++ subscriber output I get
[ INFO] [1569905819.772859593]: I heard: [2-hello world py]
[ INFO] [1569905819.874401168]: I heard: [3-hello world py]
[ INFO] [1569905825.212111970]: I heard: [hello world 3]
Python subscriber works fine
[INFO] [1569905819.678143]: /listener_17329_1569905813773I heard 1-hello world py
[INFO] [1569905819.772875]: /listener_17329_1569905813773I heard 2-hello world py
[INFO] [1569905819.875100]: /listener_17329_1569905813773I heard 3-hello world py
[INFO] [1569905825.012191]: /listener_17329_1569905813773I heard hello world 1
[INFO] [1569905825.112169]: /listener_17329_1569905813773I heard hello world 2
[INFO] [1569905825.212244]: /listener_17329_1569905813773I heard hello world 3
Can someone please explain what's happening here? I don't get it.
c++ publisher - talker.cpp
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker");
ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
ros::Rate loop_rate(10);
std_msgs::String msg;
std::stringstream ss;
loop_rate.sleep();
msg.data = "hello world 1";
ROS_INFO("%s", msg.data.c_str());
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
msg.data = "hello world 2";
ROS_INFO("%s", msg.data.c_str());
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
msg.data = "hello world 3";
ROS_INFO("%s", msg.data.c_str());
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
return 0;
}
python publisher - talker.py
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
rate.sleep()
hello_str = "1-hello world py"
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
hello_str = "2-hello world py"
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
hello_str = "3-hello world py"
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
Subscribers are identical to the ones provided in the example pages (c++, python)
Asked by teshansj on 2019-10-01 00:35:28 UTC
Comments
The relevant part of the code is missing (the definition of the subscriber as well as what comes after it). But after you register a subscriber, it might take a little while until it is fully set-up and connected to all topics. So you could simply add a sleep for a second or so after the instantiation of the subscriber and check if this already solves you issue.
Asked by mgruhler on 2019-10-01 00:44:14 UTC
As I have mentioned at the beginning, I modified the code in the examples c++ and python. Didn't include it in the question since it would make the question too long to read. I'll append it at the bottom of the question
Asked by teshansj on 2019-10-01 01:45:07 UTC
@mgruhler Yes adding a delay solves the problem. So it it happening because
init
functions exit before they actually finish initializing things?Asked by teshansj on 2019-10-01 01:55:15 UTC
Are you running all your nodes from a single launch file ? Try launching only the
listeners
nodes first and then after one or two secs thetalkers
nodes. As @mgruhler said, it's not related toinit
functions but to the time to connect to the topics.Asked by Delb on 2019-10-01 02:06:02 UTC
I am launching them separately. And of course I am running the listeners first. To solve the problem, delay need to be added in the publisher after the
init
Asked by teshansj on 2019-10-01 02:46:13 UTC
Please see #q287548 and #q313491, of which your question appears to be a duplicate @teshansj.
You probably already did, but just to make sure: please try to search for previous Q&As before posting a new one. Try to use Google, as it's much better than the built-in search. Using something like
first message lost site:answers.ros.org
got me #q287548 and #q313491 as the two top results.don't add delays (time-based). A state-based approach will always be more robust.
Finally: if message reception (and acknowledgement) are really important, don't use publish-subscribe (in ROS 1). It's a fire-and-forget communication pattern, with literally no guarantees about anything whatsoever (see also #q203129). Use services or actions.
Asked by gvdhoorn on 2019-10-01 03:16:58 UTC
I've actually closed this as a duplicate.
If you don't agree @teshansj, please comment here, clarify and we could re-open if that would be justified.
Asked by gvdhoorn on 2019-10-01 03:48:33 UTC