0
$\begingroup$

Rosanswers logo

Hello all,

So I have a topic published by a publisher node, at 50 Hz. The topic publishes a message 'loadMsg' which consists of the following data types

  1. string unit

  2. float64 load

Now I have my subscriber node, which is the following piece of code

#include <ros/ros.h>
#include <robot_comm/robot_comm.h>
#include "std_msgs/String.h"
#include "cell_node/loadMsg.h"


void loadSensor(const cell_node::loadMsg &d)
{
  ROS_INFO("Load Unit = [%s] , Value = [%lf] ", d.unit.c_str(),d.load);
}



int main(int argc, char** argv)
{
  ros::init(argc, argv, "demo");
  //FILE * pFile;
  
  ros::NodeHandle n;

  ros::Subscriber sub = n.subscribe("loadSensor", 1000, loadSensor);
  //ros::Rate loop_rate(50);
int i = 0;
while(i<10)
{
  usleep(20000);
  ros::spinOnce();
  i++;
}
  //pFile = fopen ( "myfile.txt" , "w+" );
  //fwrite (buffer , 1 , sizeof(buffer) , pFile );
  //fclose (pFile);

return 0;
}

So what this should do is basically sample from the stream of 'loadMsg' data being published at 50Hz. And the sampling should happen again at 50Hz (1/20000usec).

However, I am not getting any output! rosmake/make work perfectly, without any errors. When I run the node however, I get nothing.

What may be going wrong? In an earlier post, I asked a similar question. But it worked then, it refuses to work now. Here is the link to that:

http://answers.ros.org/question/38131/rosspinonce-not-functioning-properly/

Also, if I replace ros::spinOnce() by ros::spin() and remove the while loop, then it does sample from the topic, but seemingly at a lesser frequency.

All help is greatly appreciated!


Originally posted by Nishant on ROS Answers with karma: 143 on 2012-07-09

Post score: 0


Original comments

Comment by Nishant on 2012-07-09:
Hey ipso, thanks for the hint to topic_tools. However, I don't get one thing. When I did sleep(N) in my while loop here

http://answers.ros.org/question/38131/rosspinonce-not-functioning-properly/

why did polling work here?

Comment by Nishant on 2012-07-09:
Also, what do you think about the ros::Timer library? Can I use that instead of this method where I poll every time I want data from the topic stream?

Comment by ipso on 2012-07-09:
@Nishant: read my answer: you're not polling from the topic 'stream' (actually: events). You either receive the publications or you don't. AFAIK there is currently no support for polled topics in ROS. You could use ros::Timer in your publisher yes, your subscriber does not need it.

Comment by ipso on 2012-07-09:
@Nishant: the only thing you change by running your own while loop (as in the answer you linked) is the rate at which ROS looks at the queue of incoming events. @PerkinsJames also describes this in the accepted answer. As you publisher is @10Hz, so is your subscriber's callback.

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

I'm not sure of your issue, but your WHILE loop will only last for approximately 1/10th of a second, meaning there must be a message waiting for you from your publisher within that 1/10th of a second or before.

I am not sure if output from a publisher will even buffer if nothing on your system is listening to it (since ROS core somehow makes direct connections between ROS nodes once they subscribe).

Try this. Change while(i<10) to while(ros::ok()) and see if you then ever get those messages through. If you do, it probably has something to do with your timing of when the publisher sends and the the subscriber checks for it.

Also, if you are starting your publisher after the receiver, it surely wont get anything (although it seems you're not doing this).


Originally posted by PerkinsJames with karma: 506 on 2012-07-09

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by ipso on 2012-07-09:
"Also, if you are starting your publisher after the receiver, it surely wont get anything": why do you say this? Cause AFAIK there is no temporal binding between publishers and subscribers?

Comment by PerkinsJames on 2012-07-09:
That sentence was specific to code @Nishant posted. He/she just checks for messages 10 times very quickly, which would finish and then exit more quickly than he/she could type rosrun on the publisher.

Comment by ipso on 2012-07-09:
Ah ok, I understand. In that case you're right of course. I was referring to the general case.

Comment by Lorenz on 2012-07-09:
Also, it takes a while until the connection between a publisher and a subscriber is established and 1/10th of a second might not be enough for that. Although a publisher might be up and running, no message might be received in this short time window.

Comment by Nishant on 2012-07-10:
Hey PerkinJames, so I tried doing what you told me to do (substitute i<10 with ros::ok()) and it worked! That does mean that it might happen that maybe my subscriber is starting to look for readings in between two readings that are actually being published by the publisher.

Comment by Lorenz on 2012-07-10:
@Nishant, look at my previous comment. That's what probably is happening. After subscribing to a topic, you need to give ROS some time to actually establish the connection. 0.1 seconds might not be enough for that. More info: http://www.ros.org/wiki/ROS/Technical%20Overview

Comment by PerkinsJames on 2012-07-10:
@Nishant, and to expand on @Lorenz answer, spinOnce may not wait for the connection to be fully ready to use. Hence, you could still call spinOnce when the connection is not fully set, burning through that while() loop

$\endgroup$
0
$\begingroup$

Rosanswers logo

Just something I notice in other questions on this site: the fact that you insert a sleep(N) in your while loop does not mean that you are sampling anything at any rate.

ROS is (mostly) an asynchronous event based system and messages from publishers will result in callbacks being called if there are subscriptions for them (if there are no subscriptions, no callbacks will be called). Running your own while loop (with an embedded sleep(N) in it) will only determine the pace at which ROS looks at the pile of events it has currently received. Then, it will call the registered callback(s) for each of these events.

This is very different from a synchronous polling based sampling system, which looks N times (per second/hour/whatever) at the value of a particular signal. ros::spinOnce() does not look at the 'value' of the 'loadSensor' topic, it just signals ROS that it should process any outstanding events now.


RE: your problem:

So what this should do is basically sample from the stream of 'loadMsg' data being published at 50Hz. And the sampling should happen again at 50Hz (1/20000usec).

No it should not, and the above hopefully made it clear why it shouldn't.


To slow down the rate at which events are delivered to a particular node, you could make use of the topic_tools/throttle node. This does not turn ROS into a sampling based system, but does allow you to set a limit on the maximum number of events delivered to your node.


Originally posted by ipso with karma: 1416 on 2012-07-09

This answer was NOT ACCEPTED on the original site

Post score: 1


Original comments

Comment by PerkinsJames on 2012-07-09:
Edit: I'm trying to understand your answer. I agree that he is only telling ROS to process events, not sample data (if there's nothing there, it will receive nothing). To answer the question, does your post just state that the ROS signal rate does not guarantee anything about the publisher?

Comment by ipso on 2012-07-09:
@PerkinsJames: The post was more of a general "don't think of ROS as a synchronous sampling system", as this seems to cause a great deal of confusion (ie: thinking ros::spinOnce() is like sample(), etc). Re the question: what do you mean with 'the ROS signal rate'?

Comment by PerkinsJames on 2012-07-10:
@ipso, sorry, i think i used the wrong terms. I meant the rate at which the subscriber checks for outstanding messages (the rate spinOnce is called))

$\endgroup$

Your Answer

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