ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Publish message to a topic from Callback function

asked 2018-09-08 22:11:59 -0500

kk2105 gravatar image

updated 2018-09-09 13:49:33 -0500

Hi Guys,

This question had been already asked, however I am looking for ways without using C++ classes.

Below is my problem statement.

#include "ros/ros.h"
#include "std_msgs/String.h"

void chatter_callback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("Received the message : [%s]", msg->data.c_str());        
    // Here I need to convert this message other datatypes and publish it to topic "X"
    // Can we have while(ros::ok()) here in this callback function

    while(ros::ok())
    {
          chatter_pub.publish(new_msg);
    }
}

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

ros::init(argc, argv, "listener_v1");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatter_callback);
ros::Publisher chatter_pub = n.advertise<other data type>("chatter", 1000);
    ros::Rate loop_rate(10);
ros::spin();    

return 0;
}

Also please note that Publisher is defined in main and being used in callback function. I am afraid this is not the right way to use it.

Kindly let me know if the question is not clear and needs more information.

Updating the code :

#include "ros/ros.h"
#include "std_msgs/String.h"

void chatter_callback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("Received the message : [%d]", msg->data.c_str());        
   // Convert the msg to the datatype we wanted to 

    chatter_pub.publish(new_msg);

}

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

ros::init(argc, argv, "listener_v1");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatter_callback);
ros::Publisher chatter_pub = n.advertise<other data type>("chatter", 1000);
    ros::Rate loop_rate(10);

    while(ros::ok()
   {
        ros::spinOnce();
   }    

return 0;
}

Thank you, KK

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
2

answered 2018-09-09 06:42:58 -0500

snowee gravatar image

updated 2018-09-09 17:34:13 -0500

Just declare your publisher in the global scope. So, above your callback. Then, in main, you can loop the way you mentioned, but use ros::spinOnce() instead of ros::spin()

while (ros::ok()) {
  ros::spinOnce();
  loop_rate.sleep(); // Don't forget this! *
}

* Thanks @gvdhoorn: Without this, your node would use 100% CPU, even if it has nothing to do.

EDIT: loop_rate.sleep()

edit flag offensive delete link more

Comments

@snowee Thanks for the reply.

So there will be 2 while(ros::ok()) { ros::spinOnce() } ?

One in callback and one in main ??

Thank you.

kk2105 gravatar image kk2105  ( 2018-09-09 07:42:29 -0500 )edit

This is basically what I wrote, no?

gvdhoorn gravatar image gvdhoorn  ( 2018-09-09 11:06:27 -0500 )edit

also: please add a ros::Rate::sleep() in your while loop if you're going to do it this way.

Right now your node is using 100% CPU, even if it has nothing to do (ie: there are no messages).

gvdhoorn gravatar image gvdhoorn  ( 2018-09-09 11:07:00 -0500 )edit

@gvdhoorn Thanks for clarifying. I was just wondering whether we can have 2 while(ros::ok()) { ros::spinOnce() } in a single program.

kk2105 gravatar image kk2105  ( 2018-09-09 11:33:10 -0500 )edit

Never put an infinite while loop in a callback. Ever.

Please clarify why you think you'd need an additional while.

gvdhoorn gravatar image gvdhoorn  ( 2018-09-09 11:36:47 -0500 )edit

Also: @snowee: why do you suggest to use while (ros::ok)? I don't understand how that connects to the question by the OP of how to use a variable in global scope?

gvdhoorn gravatar image gvdhoorn  ( 2018-09-09 11:37:59 -0500 )edit

@gvdhoorn I have updated the question with the code. Could you please check if that is the right implementation and my understanding is correct ?

kk2105 gravatar image kk2105  ( 2018-09-09 13:50:10 -0500 )edit

@gvdhoorn he asked something about it in the original question

snowee gravatar image snowee  ( 2018-09-09 17:31:17 -0500 )edit
1

answered 2018-09-09 04:13:09 -0500

gvdhoorn gravatar image

updated 2018-09-09 04:29:59 -0500

The only thing classes add (in a case like this, there are obviously other benefits to classes) is a scope that can persist variables outside the callback's scope.

In your case, without a class, you could use the global scope.


Edit: two alternatives:

  • if using C++11: use a lambda expression and capture chatter_pub, then use that in the lambda body
  • use boost::bind and pass a reference to chatter_pub to the chatter_callback directly
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-09-08 22:11:59 -0500

Seen: 2,070 times

Last updated: Sep 09 '18