0
$\begingroup$

Rosanswers logo

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/subscriber.h"
#include "message_filters/time_synchronizer.h"

using namespace mathematics;
using namespace message_filters;

void callback(const TwoDataConstPtr& odd_sub, const TwoDataConstPtr& even_sub)
{
  ROS_INFO("I believe oddNumberGenerator says: [%lli]", odd_sub->data1);
  ROS_INFO("I believe evenNumberGenerator says: [%lli]", even_sub->data2);
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener");

  ros::NodeHandle nodeObject;

  Subscriber<TwoData> odd_sub(nodeObject, "oddNumberGenerator", 1);
  Subscriber<TwoData> even_sub(nodeObject, "evenNumberGenerator", 1);

  TimeSynchronizer<TwoData, TwoData> sync(odd_sub, even_sub, 10);

  sync.registerCallback(boost::bind(&callback, _1, _2));

  ros::spin();

  return 0;
}

Aaand now, it still complains about something that I don't understand, here is the error message:

/opt/ros/indigo/include/message_filters/sync_policies/exact_time.h:127: error: 'value' is not a member of 'ros::message_traits::TimeStamp<mathematics::TwoData_<std::allocator<void> >, void>'
     Tuple& t = tuples_[mt::TimeStamp<typename mpl::at_c<Messages, i>::type>::value(*evt.getMessage())];
                                                                                                     ^

What am I doing wrong again?

Update3: Alright, I guess trying to invent something in a system that you don't fully understand is madness. I am gonna stick with the current methods and will use them. As my attempt described here was not unsuccessful but better and safer way to work with nodes is to have separate topic for each of them.

Thank you everyone for your help!!!


Originally posted by Kenn on ROS Answers with karma: 5 on 2017-07-16

Post score: 0


Original comments

Comment by NEngelhard on 2017-07-16:
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?

Comment by Kenn on 2017-07-17:
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?

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

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.


Originally posted by ahendrix with karma: 47576 on 2017-07-17

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by Kenn on 2017-07-17:
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.

Comment by Kenn on 2017-07-17:
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.

Comment by ahendrix on 2017-07-17:
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.

Comment by Kenn on 2017-07-18:
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.

Comment by ahendrix on 2017-07-18:
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

Comment by Kenn on 2017-07-19:
fixed it and updated the question.

Comment by ahendrix on 2017-07-19:
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();

Comment by Kenn on 2017-07-19:
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.

Comment by ahendrix on 2017-07-20:
It still seems like your message definition is incorrect. The docs for the C++ class that is throwing the error indicates that it results in a compile error if the message doesn't have a header: http://docs.ros.org/jade/api/roscpp_traits/html/structros_1_1message__traits_1_1TimeStamp.html

$\endgroup$
0
$\begingroup$

Rosanswers logo

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/Publishers%20and%20Subscribers#MessageEvent_.5BROS_1.1.2B-.5D


Originally posted by Wolf with karma: 7555 on 2017-07-16

This answer was NOT ACCEPTED on the original site

Post score: 2


Original comments

Comment by gvdhoorn on 2017-07-16:\

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.

Comment by Wolf on 2017-07-16:
Thank you For the hint, i edited the answer.

Comment by Kenn on 2017-07-17:
Thank you guys for the answers, I think I should read roscpp documentation first then I will update my question.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.