Ask Your Question
0

can a node listen to two other nodes?

asked 2017-07-16 09:30:27 -0500

Kenn gravatar image

updated 2017-07-20 05:21:13 -0500

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::Publisher publisherObject = nodeObject.advertise<twoData::UInt64>("mathTopic", 1);

    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 ...
(more)
edit retag flag offensive close merge delete

Comments

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?

NEngelhard gravatar imageNEngelhard ( 2017-07-16 14:35:34 -0500 )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?

Kenn gravatar imageKenn ( 2017-07-17 02:39:49 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted
1

answered 2017-07-17 02:21:04 -0500

ahendrix gravatar image

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.

edit flag offensive delete link more

Comments

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.

Kenn gravatar imageKenn ( 2017-07-17 02:47:54 -0500 )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.

Kenn gravatar imageKenn ( 2017-07-17 02:50:26 -0500 )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.

ahendrix gravatar imageahendrix ( 2017-07-17 13:23:29 -0500 )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.

Kenn gravatar imageKenn ( 2017-07-18 00:49:41 -0500 )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

ahendrix gravatar imageahendrix ( 2017-07-18 03:57:07 -0500 )edit

fixed it and updated the question.

Kenn gravatar imageKenn ( 2017-07-19 04:33:17 -0500 )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();
ahendrix gravatar imageahendrix ( 2017-07-19 10:33:13 -0500 )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.

Kenn gravatar imageKenn ( 2017-07-19 12:00:40 -0500 )edit
2

answered 2017-07-16 15:12:06 -0500

Wolf gravatar image

updated 2017-07-16 23:38:20 -0500

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...

edit flag offensive delete link more

Comments

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.

gvdhoorn gravatar imagegvdhoorn ( 2017-07-16 15:41:51 -0500 )edit
1

Thank you For the hint, i edited the answer.

Wolf gravatar imageWolf ( 2017-07-16 23:44:55 -0500 )edit

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

Kenn gravatar imageKenn ( 2017-07-17 01:22:16 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2017-07-16 09:30:27 -0500

Seen: 496 times

Last updated: Jul 20 '17