I noticed something weird that seems like a bug. When a subscriber listens to a topic that contains a slash and that a publisher advertises the "parent" topic (the part before the slash), then the subscriber changes the topic to what it listens to match the publisher.
Here is an example. I open three terminals that will exchange on topic /parent/child
.
Step 1: In Terminal 1, I start rostopic echo /parent/child
Step 2: In Terminal 2, I start rostopic echo /parent
Step 3: In Terminal 3, I start a node with publishers for /parent
and parent/child
Step 4: In Terminal 3, the node publishes on both topics
The result is that only the subscriber in Terminal 2 gets the message. In addition, rxgraph shows that Terminal 1 is then subscribing to /parent instead of /parent/child. In Terminal 1, I get this instead of the message: no field named [/child]
What's happening here?
Here is the code:
#include <ros/ros.h>
#include <std_msgs/String.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "MyPublisher");
ros::NodeHandle nh("~");
ros::Rate oneSecond(1);
// Creates a publisher to see if it replicates the bug
ros::Publisher pubParent = nh.advertise<std_msgs::String>("/parent", 10);
// Waits for the subscribers to connect
oneSecond.sleep();
ros::Publisher pubChild = nh.advertise<std_msgs::String>("/parent/child", 10);
// Waits for the subscribers to connect
oneSecond.sleep();
std_msgs::String msgChild;
msgChild.data = "Hello World! (on /parent/child)";
pubChild.publish(msgChild);
ROS_INFO("Message published (on /parent/child)");
std_msgs::String msgParent;
msgParent.data = "Hello World! (on /parent)";
pubParent.publish(msgParent);
ROS_INFO("Message published (on /parent)");
// Waits for the user to manually stop the node (to give time to see the update in rxgraph)
ros::spin();
return 0;
}
Here is the info about the nodes:
Terminal 1:
Node [/rostopic_27422_1352897219007]
Publications:
* /rosout [rosgraph_msgs/Log]
Subscriptions:
* /parent [std_msgs/String]
Services: None
Pid: 27422
Connections:
* topic: /rosout
* to: /rosout
* direction: outbound
* transport: TCPROS
* topic: /parent
* to: /MyPublisher (http://dfki-benoit:33822/)
* direction: inbound
* transport: TCPROS
Terminal 2:
Node [/rostopic_27405_1352897218194]
Publications:
* /rosout [rosgraph_msgs/Log]
Subscriptions:
* /parent [std_msgs/String]
Services: None
Pid: 27405
Connections:
* topic: /rosout
* to: /rosout
* direction: outbound
* transport: TCPROS
* topic: /parent
* to: /MyPublisher (http://dfki-benoit:33822/)
* direction: inbound
* transport: TCPROS
Terminal 3:
Node [/MyPublisher]
Publications:
* /parent [std_msgs/String]
* /parent/child [std_msgs/String]
* /rosout [rosgraph_msgs/Log]
Subscriptions: None
Services:
* /MyPublisher/get_loggers
* /MyPublisher/set_logger_level
Pid: 27455
Connections:
* topic: /rosout
* to: /rosout
* direction: outbound
* transport: TCPROS
* topic: /parent
* to: /rostopic_27405_1352897218194
* direction: outbound
* transport: TCPROS
* topic: /parent
* to: /rostopic_27422_1352897219007
* direction: outbound
* transport: TCPROS
EDIT (12/12/12): Following the answer from @Dirk Thomas, I tried his Python script. The behavior that I observe is the following. If I start the standard Python listener and rostopic echo
, they both receive the messages on /parent/child
. However, if I start only rostopic echo
, then it "switches" to /parent
and tries to read the field /child
. In addition, rostopic echo
does not print the WARNING: topic [/parent/child] does not appear to be published yet
if the standard listener was started before.
These observations mean that the presence of a standard listener changes the behavior of rostopic echo
.
In my opinion, this is unintuitive and most importantly not "repeatable". It means that my scripts using rostopic echo
would yield different results if my colleagues started some listeners on the ROS network, for example.
Originally posted by Benoit Larochelle on ROS Answers with karma: 867 on 2012-11-12
Post score: 1
Original comments
Comment by Lorenz on 2012-11-12:
What's the output of rosnode info
on the two subscriber nodes?
Comment by dornhege on 2012-11-12:
Does the subscription for 1 change in between the other steps? I cannot reproduce this with rostopic echo/pub. For me in step 4 both rostopic echo get the message.
Comment by Benoit Larochelle on 2012-11-13:
No, the rosnode info
for Terminal 1 does not change between steps, other than adding the publisher when I start it in Step 2. The subscriber in Terminal 1 thus starts on /eoi
.
Comment by dornhege on 2012-11-13:
Can you reproduce the exact steps (after a roscore restart) using standard messages? This looks like a weird bug to me.
Comment by Benoit Larochelle on 2012-11-13:
Ok, I'll come up with a minimal example that shows this behavior
Comment by dornhege on 2012-11-14:
I can confirm this by following step 1 and 2 and then rostopic pub -r 5 /parent/ std_msgs/String -- "{data: Hello}"
. It only works after a roscore restart. When a publisher for /parent and /parent/child are present before the subscribers are started everything works fine.
Comment by dornhege on 2012-11-14:
Either you are not allowed to have a topic at /parent while there is one at /parent/child (thus parent becoming a namespace) or this is a bug that should be filed. In any case something is wrong as I can get both subscriptions to run depending on the order. It should be always or never.
Comment by Lorenz on 2012-11-14:
I think that's definitely a bug and should be filed. Even if that's desired behavior, it is not intuitive and at least a warning or error should be thrown. Nice catch...
Comment by Benoit Larochelle on 2012-11-15:
I filed this issue: https://github.com/ros/ros_comm/issues/24
Comment by Benoit Larochelle on 2012-12-11:
I would suggest that rostopic echo take a -f option to list the fields to be displayed within a topic. Not providing this option would display all fields (standard current behavior)