C++ subscriber not working for first messages [closed]
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)
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.
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
@mgruhler Yes adding a delay solves the problem. So it it happening because
init
functions exit before they actually finish initializing things?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.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
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.
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.