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

Basic data passing question.

asked 2011-04-13 14:24:59 -0600

MikeV gravatar image

updated 2011-04-13 17:16:15 -0600

Hi I'm am very new to both ROS and C++ so this is a very basic question.

The problem boils down to trying to send a char array from one node to another and then being able to process that string after it is read by the other node. I have been trying to pass a char array using publishers and subscribers, but have been failing for about a week (I guess I'm a stubborn SOB). Should I try a service-client model instead?

Whats the best way to do this?

The long story is a have 3 nodes that each read from a different serial port(ttyUSB0-ttyUSB2)format the data they get from that port. Each node then publishes that data to its own respective Topic. This part is easy. I need to get the data from all 3 topics into a 'main' node then format all the data a bit(the data formatting is trivial) and then send the resulting data through an XBee (the sending is easy as well). My problem arises when I try to have a 'main' node subscribe to all 3 topics. Basically the main node gets stuck in an infinite loop, it just keeps doing the callback loop and never progresses further into the program.

How do I write the callback function so that I can just pass the data into an array or string and move on with my program?

EDIT:

I have written a example program that shows the issue (I don't think I explained it very well above).

This programs tries to listen to the "chatter" topic made by talker.cpp from the "Writing a Simple Publisher and Subscriber (C++)" tutorial. The program is simply a modified version of listener from the same tutorial.

 #include "ros/ros.h"
#include "std_msgs/String.h"
#include <iostream>
#include <sstream>

void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
//ROS_INFO("I heard: [%s]", msg->data.c_str());
printf("\nstuck in the callback loop");
}

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

  ros::init(argc, argv, "listener");

  ros::NodeHandle n;

    while (ros::ok())
    {
    sleep(3);

    ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

    printf("\nIM Not stuck anymore!\n");

        ros::spin();
    }
  return 0;

}

Basically i want to be able to run commands bellow the:

ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

call. If I were able to do this, when I run the program I should see my printf saying "IM Not stuck anymore!"

instead i see this:

  IM Not stuck anymore!

stuck in the callback loop
stuck in the callback loop
stuck in the callback loop
stuck in the callback loop
stuck in the callback loop
stuck in the callback loop

The program never reaches the lower printf statement after the callback begins (I'm not sure why it does on the first iteration but whatever). This is problematic as my goal is to read in a string from a topic, then modify it below the read statement. Ultimately I would like to do this with ... (more)

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
7

answered 2011-04-13 15:09:09 -0600

AHornung gravatar image

updated 2011-04-13 17:29:41 -0600

Have a look at the tutorial Writing a Simple Publisher and Subscriber (C++). That does exactly the thing you want to do (sending an receiving a string). Note that there are no arrays sent or received in ROS, but rather std::strings and C++ vectors.

If you want to handle all three topics at once in the same callback, you would probably want a Time Synchronizer from message_filters.

Updated answer to your code snipplet: You need to move the callback creation out of the loop, else you will constantly create and destroy callbacks. You only create it once before the loop. Also, you need to replace spin() with spinOnce() if you have your own loop:

ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

while (ros::ok())
{
ros::spinOnce();
sleep(0.1);
printf("\nIM Not stuck anymore!\n");
}
return 0;

For details, see Callbacks and Spinning

edit flag offensive delete link more

Comments

1
Thanks for the quick reply. :) its good to know about the string and vector thing. I am using code modified form "talker.cpp" and my problem is I my program goes into chattercallback and just keeps looping. so the string want to get never becomes usable in main. Is this just how subscribers work?
MikeV gravatar image MikeV  ( 2011-04-13 16:01:40 -0600 )edit
THANKS! That answers my question exactly!
MikeV gravatar image MikeV  ( 2011-04-13 20:04:31 -0600 )edit
5

answered 2011-04-13 17:39:15 -0600

Bill Smart gravatar image

The problem might be how you're thinking about callbacks. You don't have to explicitly ask for a callback to be activated. The line

ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

sets things up such that chatterCallback will be called (behind the scenes, in a different thread), whenever there's data on the topic "chatter". Once you pass this line, things works as if by magic.

The call to

ros::spin();

gives control to the underlying ROS machinery, and never returns. This is why, in your first example, you see the print statement fire once. Once the execution gets to the spin call, it never returns from it.

As Armin suggested, all you need in your code is

ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
ros::spin();

and everything should work as expected. Armin's example with spinOnce() is for cases when you want to do something of your own interleaved with ROS (not including the callback code). If not, spin() is the call you want.

edit flag offensive delete link more

Comments

This combined with the above reply is perfect. Now I am actually beginning understand what is going on with the ro::spin and such. Thanks this really clarified how Topics work. I just wish I had seen this a week ago.
MikeV gravatar image MikeV  ( 2011-04-13 20:07:41 -0600 )edit

Question Tools

Stats

Asked: 2011-04-13 14:24:59 -0600

Seen: 2,606 times

Last updated: Apr 13 '11