0
$\begingroup$

Rosanswers logo

Consider node 'x' publishes topic 'a' and 'b'. Now, I should create a node 'y' to subscribe a topic 'a'. Then the subscribed topic should be edited and published again in the name 'c'.

I tried,

// some part of the codes

void chattercallback(const .... )
{

.........

// edit or process the subscribed value<
//to publish the edited data

ros::Publisher d =......;

d.publish(..) ;

....}

int main (int argc, char **argv){

ros::init (..);

ros::Subscriber sub = .....(.. , .. , chattercallback);

....

}

But, the data is not published continuously. This node publishes data only when the topic 'a' is available i.e) only when the data is subscricbed. I need to change this codes such that data is to be published continuously i.e) even if the subscriber does not subscribe any data, it should publish the data according to the last subscribed one.

Is there any ideas for this problem?


I cannot find the option 'post a comment' below the answers. So I will post it here.

But the problem is how to access the value in topic 'a' for storing it to a variable?


Originally posted by chris_chris on ROS Answers with karma: 84 on 2012-10-14

Post score: 2


Original comments

Comment by chris_chris on 2012-10-14:
I cannot find the option 'post a comment' below the answers. So I will post it here.

But the problem is how to access the value in topic 'a' for storing it to a variable?

Comment by Lorenz on 2012-10-15:
Normally,publishers, subscribers and callbacks are implemented as class members. If you need to store a value, you just put it into a member variable so that e.g. a publisher can access it.

$\endgroup$

3 Answers 3

0
$\begingroup$

Rosanswers logo

Store the last value from topic a in a variable. In main, use an explicit spin loop. In that loop, after a timeout, publish on c.


Originally posted by KruseT with karma: 7848 on 2012-10-14

This answer was ACCEPTED on the original site

Post score: 7


Original comments

Comment by chris_chris on 2012-10-17:
I used callback function as a class member and store data from callback function into a data member. I do publishing in the main function within a while loop (loop has ros::spinOnce). But, I cannot understand what is explicit spin loop and where to put the spin loop in the main function.

Comment by dornhege on 2012-10-17:
Using spinOnce in a while loop is called an explicit spin loop.

$\endgroup$
0
$\begingroup$

Rosanswers logo

You should not declare your publiser in your callback function : this callback function is called only when data is received on topic 'a', that is why topic 'c' depends on topic 'a'. Store the data you got from topic 'a' into a "global" variable and declare your published topic 'c' into the main. For example :

float64 aux;

void chatterCallback(const& msg)
{
   aux=msg->data;
}

int main (int argc, char **argv){

ros::init (..);

ros::Subscriber sub = .....(.. , .. , chattercallback);

ros::Publisher d =......;

d.publish(..) ;

}

Update : To your question "how to access data from a topic" (see comments)

For example, if you want to access the x position of your robot spawned in gazebo empty world. You can get that information from the topic /model_state that you can get in gazebo your callback function would look like this :

void chatterCallback(const& msg)
{
   aux=msg->pose[1].position.x;
}

Look at the links above. If you need better understanding, launch a robot in gazebo and run the following

$ rostopic echo /gazebo/model_states

Originally posted by arzhed with karma: 143 on 2012-10-14

This answer was NOT ACCEPTED on the original site

Post score: 4


Original comments

Comment by ErivaldoJunior on 2016-02-10:
Thank you! This worked for me, but do you think this is a good a idea to have a global variable?

Comment by ami on 2016-06-10:
This works for me, thanks!!

$\endgroup$
0
$\begingroup$

Rosanswers logo

After publishing on topic you need to let the ROS spin, to make sure data is actually send on the topic. Calling "publish" doesn't put the data on the topic, so if you destroy publisher before the data is send, you lose the information stored in the buffer.

The best solution is to make your callback a class member and access data as a private variable of the class from function that is publishing this information. Quick code example:

int main (int argc, char **argv)
{
    ros::init (..);
    myClass myObject;

    while(ros::ok())
    {
        myObject.publishDataIfRecieved();
        ros::spinOnce();
    }

}

I will skip the class, but constructor should create both subscriber and publisher, callback should be part of a class, as well as the temporary data storage variable/structure and some boolean to indicate new data presence. For high frequency data you should provide some security for overwriting by callback not yet published data.

Also if you are not doing any computation an the data, you can just publish it inside the callback, using publisher that is already initialized as a class member, but you should avoid too much operation in your callback

Easier solution is global variable, as mentioned before, but it is not so elegant one.

EDIT:

ros::spinOnce() callend once in a while (as often as possible) will do the trick, but if you reallllly want to use ros::spin() instead, other solution is:

class myClass
{
    (...)
    public:
    myClass() { pub = (...); sub = (...) }
    
    private:
    ros::Publisher pub;
    ros::Subscriber sub;
    
    void chattercallback(...) { pub.publish(...); }
}

int main (int argc, char **argv)
{
    ros::init (..);
    myClass myObject;
    ros::spin();
}

Originally posted by kszonek with karma: 459 on 2012-10-15

This answer was NOT ACCEPTED on the original site

Post score: 8


Original comments

Comment by chris_chris on 2012-10-17:
But. In the main function where will you call the ros::spin for the callback function of subscriber? Also, I have a doubt whether updation of publishing topic will happen inside the while loop

Comment by kszonek on 2012-10-17:
There is a slight difference betwean ros::spin() and ros::spinOnce(). First blocks the program and allows ros callbacks to handle node work, when second one releases after doing all ros related stuff. It allows you to do code in main function letting ros do it work.

Comment by chris_chris on 2012-10-17:
I subscribe a point cloud data into this node. If I write a main function as mentioned above without a spin in main function, it gives an error because the subscribed data will be available only at some particular point of time. In case of spin loop inside the main function it will not give error.

Comment by chris_chris on 2012-10-17:
thats why I am asking where to put the spin loop. Also, In your answer, I didn't understand 'Calling "publish" doesn't put the data on the topic, so if you destroy publisher before the data is send, you lose the information stored in the buffer'

Comment by dornhege on 2012-10-17:
In your code, the publisher is a local variable and thus will be destroyed immediately after the callback is handled - thus you won't get any publish.

Comment by chris_chris on 2012-10-18:
In my code, the publisher is data member of the class. So, I think when it enters the callback function it will not be destroyed (callback is the member function of the same class)

Comment by kszonek on 2012-10-18:
@Chris: as mentioned already by domhege, your publisher is being destroyed at the end of a chattercallback function, since it is declared within it. Your publisher is NOT class member.

About the spinning, let me edit my answer, since this comment is already too long.

Comment by chris_chris on 2012-10-18:
Already, I declared my pub as a class member. So, I expect this should be problem with the other node subscribing this one..

Comment by dornhege on 2012-10-18:
We only see the code excerpt in your question, which is not using a class member. If your code has that fixed, you can always test with rostopic echo to eliminate the "other node" as a failure option.

Comment by Sudhan on 2012-10-25:
I would like to know what do you mean in this lines (For high frequency data you should provide some security for overwriting by callback not yet published data.)?

Comment by dornhege on 2012-10-25:
If the callback receives very high frequency data, it might not have been processed (published) until the next data arrives. Thus it will be overwritten, if not handled by queuing.

Comment by Sudhan on 2012-10-25:
so, Can you please tell me how to handle these type of datas?

Comment by dornhege on 2012-10-25:
The usual way is to use a queue as the builtin queue in ROS.

Comment by Sudhan on 2012-10-25:
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

Do you mean this number 1000 for queueing?

As I understand for subscribing high frequency messages, bigger number would be better. I would like to know what I understood is correct?

Comment by dornhege on 2012-10-25:
Not necessarily. A bigger number allows to buffer more messages, but if you cannot handle messages in the speed they arrive, you might get an opposing effect that your queue is full and newer messages are discarded. You will need to decide depending on your system.

$\endgroup$

Your Answer

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