# can a node listen to two other nodes?

Hey forum members, greetings to you all!

I am new to ROS, I was wondering if it is possible to create a node which will listen to a topic where two other nodes are publishing information.

Let's say I have even_number_node that generates even numbers and odd_number_node that generates odd numbers, they both are publishing let's say std_msgs::UInt64 data to a mathTopic, this third node adder_node will subscribe to the mathTopic and will get odd and even numbers generated by previous nodes, how can I identify which data is sent from which node and find sum of them?

I actually attempted to make it work based on the talker-listener nodes provided in ROS tutorials but messed everything up. Yes, I can create such a thing with service-client node but I want to break it down to be able to understand the details.

I know this sounds pretty much a dumb questions to experts, so thanks for the help!

Update1: Got it to work! Please see update2 below!

I was playing with the code and now it says: build system error and takes me to the following line: message(FATAL_ERROR "\nAssertion failed: file '${FILENAME}' does not exist. Message:${MESSAGE}\n")

// CMakeLists.txt includes:

add_message_files(
FILES
twoData.msg)


// twoData.msg file includes:

    std_msgs/UInt64 data1
std_msgs/UInt64 data2


evenNumberGenerator node, oddNumberGenerator node is the same with minor changes described below in comments:

#include "ros/ros.h"
#include "std_msgs/UInt64.h"
#include "mathematics/msg/twoData.h"

int main(int argc, char **argv)
{
// initialize evenNumberGenerator
ros::init(argc, argv, "evenNumberGenerator"); //oddNumberGenerator node for the other node

ros::NodeHandle nodeObject;

// publish to mathTopic

ros::Rate loop_rate(1);

int i = 1;

while(ros::ok())
{
twoData::UInt64 number;

while(ros::ok())
{
number.data2 = 2*i; //this is number.data1 = 2*i-1; for oddNumberGenerator node
i++;
ROS_INFO("%lli", number.data2); // number.data1 for the other node

loop_rate.sleep();

publisherObject.publish(number);
}

}

return 0;
}


Update2: I got it to work. As @ahendrix said each node sends a complete message, not part of it, like:

node1 sends:

data1: 1 # odd numbers
data2: 0
---------------
data1: 3
data2: 0
--------------
...

and node2 sends:

data1: 0
data2: 2 # even numbers
---------------
data1: 0
data2: 4
--------------
...

and the third node which is supposed to listen to both of them at the same topic returns:

I believe oddNumberGenerator says: 1 # data from oddNumberGenerator
I believe evenNumberGenerator says: 0
------------------------------------------------------------
I believe oddNumberGenerator says: 0 # data from evenNumberGenerator
I believe evenNumberGenerator says: 2
------------------------------------------------------------
I believe oddNumberGenerator says: 3 # data from oddNumberGenerator
I believe evenNumberGenerator says: 0
------------------------------------------------------------
I believe oddNumberGenerator says: 0 # data from evenNumberGenerator
I believe evenNumberGenerator says: 4
------------------------------------------------------------
I believe oddNumberGenerator says: 5 # data from oddNumberGenerator
I believe evenNumberGenerator says: 0
------------------------------------------------------------
I believe oddNumberGenerator says: 0 # data from evenNumberGenerator
I believe evenNumberGenerator says: 6
------------------------------------------------------------
...


As expected, so I decided to go with @ahendrix's advise on Time Synchronizer and modified my code as it is below:

#include "ros/ros.h"
#include "mathematics/TwoData.h"
#include "message_filters ...
edit retag close merge delete

1

I think you question is rather how you can see which node sent a specific message instead of what you wrote in the title, right?

( 2017-07-16 14:35:34 -0600 )edit

Well, I think that's what came to my mind when I was thinking about the problem. But yes, how can I see which node outputs what without having to look at the code?

( 2017-07-17 02:39:49 -0600 )edit

Sort by » oldest newest most voted

As @Wolf and @gvdhoorn have pointed out, topics are Anonymous; this means that you can have any number of subscribers and any number of publishers on them. While it is technically possible to get the name of the publisher for a received message (say, for debugging), good system design should not depend on the publisher name for correct functionality.

It sounds like you want to make a subscriber that receives messages from two different sources, adds them and publishes the result. The typical ROS way to do this is to represent each source as a separate topic and subscribe to both topics.

Regards of whether you use one or two topics, keep in mind that since you're receiving data from two different sources, the data from each source will not arrive at the same time, and you will need to do something to synchronize it.

You can write your own synchronization, or, if your messages have a Header, ROS has the TimeSynchronizer in the message_filters library which can synchronize two or more topics based on the timestamp in their headers.

more

The typical ROS way to do this is to represent each source as a separate topic and subscribe to both topics.

I definitely didn't know this but still is it more efficient that the other way? Considering you have to call two functions and synchronize them, subscribing to one topic sounds easier.

( 2017-07-17 02:47:54 -0600 )edit

and that is what is stuck in my mind for now, so I have to solve it somehow. I thought ROS specific approach to this would be to use services but as I said I wanna fully understand nodes. Do you have any idea how I can do it with two nodes and one topic? And thank you for the help.

( 2017-07-17 02:50:26 -0600 )edit
1

Each publisher sends a complete message; not part of a message. If you look at the data that you receive when you try to use a single topic, you'll see that each message only has half of the data filled in.

( 2017-07-17 13:23:29 -0600 )edit

Yeah, that was the plan actually. And the listener node will get half the message from the first and the other from part of the message from the second node, so it will add them together. Or not (?) Anyways, I can't build the package as it tells me I have done something wrong.

( 2017-07-18 00:49:41 -0600 )edit
1

The subscriber will not automatically combine messages. For your error, I think the msg/ path prefix is unnecessary in the CMakeLists.txt ; just use twoData.msg

( 2017-07-18 03:57:07 -0600 )edit

fixed it and updated the question.

( 2017-07-19 04:33:17 -0600 )edit

As I mentioned before, if you want to use the TimeSynchronizer your messages need a Header. Try using a message like:

Header header
uint64 data


And make sure that you fill in the timestamp when sending messages in C++:

msg.header.stamp = ros::Time::now();

( 2017-07-19 10:33:13 -0600 )edit

added, still gives me the same error, because synchronizer synchronizes two different topics not two different nodes publishing to the same topic. Well, I am gonna use the normal ROS way, thank you so much.

( 2017-07-19 12:00:40 -0600 )edit

Yes, a node can listen to a topic while two nodes are Broadcasting to this topic. ROS topic allow one-to-one, one-to-one, many-to-many and many-to-one connections.

As pointed by @gvdhoorn you can identify the Sender using message Events in tcpros. http://wiki.ros.org/roscpp/Overview/P...

more

3

And no, There no way to identify the node a specific Message was received from

That is not actually true. See wiki/roscpp/Subscribing to a Topic - MessageEvent.

( 2017-07-16 15:41:51 -0600 )edit
1

Thank you For the hint, i edited the answer.

( 2017-07-16 23:44:55 -0600 )edit

Thank you guys for the answers, I think I should read roscpp documentation first then I will update my question.

( 2017-07-17 01:22:16 -0600 )edit