0
$\begingroup$

Rosanswers logo

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 the other 2 topics as well and then send a combined formatted message out the serial port.

Is the method that I am trying even possible or have I just completely misunderstood how publishers and subscribers work? If it's possible what do I need to do?

Thanks in advance for any help.


Originally posted by MikeV on ROS Answers with karma: 1 on 2011-04-13

Post score: 0

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

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


Originally posted by AHornung with karma: 5904 on 2011-04-13

This answer was ACCEPTED on the original site

Post score: 7


Original comments

Comment by MikeV on 2011-04-13:
THANKS! That answers my question exactly!

Comment by MikeV on 2011-04-13:
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?

$\endgroup$
0
$\begingroup$

Rosanswers logo

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.


Originally posted by Bill Smart with karma: 1263 on 2011-04-13

This answer was NOT ACCEPTED on the original site

Post score: 5


Original comments

Comment by MikeV on 2011-04-13:
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.

$\endgroup$

Your Answer

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