0
$\begingroup$

Rosanswers logo

Hello everyone.
I built a bag file that, every time is played, sends messaged to two topics. I start bag playing from keyboard:

rosbag play -r 2 subset.bag

On the other side, there's a simple program receiving messages from both topics and calling right functions in a specified class to manage them according to their nature:

int main(int argc, char **argv){
    stage_listener sl;
    char buffer [1024];
    while(1){
        int i = fscanf(stdin,"%s",buffer);
        
        if(strcmp("exit",buffer) == 0)
            exit(0);
            
        else if(strcmp("num_nodes",buffer) == 0){
            printf("\nOdometry nodes: %i\nScan nodes: %i\n",sl.numOdom(),sl.numScan());
            //int b = (*sl).numOdom();
        }
        
        else if(strcmp("listen",buffer) == 0){
            ROS_INFO("Activating topics listening...\n");
            ros::init(argc,argv, "listener");
            ros::NodeHandle n_odom, n_scan;
            ros::Subscriber sub_odom = n_odom.subscribe("/odom", 1000, &stage_listener::addOdomNode, &sl);
            ros::Subscriber sub_scan = n_scan.subscribe("/base_scan", 1000, &stage_listener::addScanNode, &sl); 
        
            ros::spin();
            ROS_INFO("Listening activity completed");
        }
        
        else{
            ROS_INFO("Command not found\n");
        }
    }

}

The receiver stands waiting for messages after executing instruction

ros::spin();

The problem is that receiver doesn't know when all messages have been sent and keeps waiting, without regaining control and proceeding in executing subsequent instructions. I want, after the end of messages in bag file, main() function to regain control and print on screen by instruction

ROS_INFO("Listening activity completed");

Then, a new execution of while(1) must start, in such a way new commands can be inserted from keyboard through instruction

int i = fscanf(stdin,"%s",buffer);

Is there a way to break ros::spin() loop when there are no more messages to be received?

Thanks for help.


Originally posted by ubisum on ROS Answers with karma: 23 on 2012-12-11

Post score: 0


Original comments

Comment by SL Remy on 2012-12-11:
Can you more fully explain what you're trying to do? At the surface level it sounds like you need service calls if you care about control/sequence..

Comment by ubisum on 2012-12-11:
i edited file, i hope this will help to explain better my problem

Comment by SL Remy on 2012-12-11:
If the program is called with "listen" then it subscribes to /odom and /base_scan.. and you'd like it to stop when the data is done?

Comment by ubisum on 2012-12-11:
yes, exactly

$\endgroup$

3 Answers 3

0
$\begingroup$

Rosanswers logo

Try using roslaunch. E.g.

<launch>
  <node pkg="rosbag" type="rosbag" name="rosbag" args="play -2 $(find NAME_OF_PACKAGE)/subset.bag" required = "true"/>
  <node pkg="stagelistener" type="stagelistener" name="stagelistener" args="listen"/>
</launch>

Not sure why you need the stdin stuff.. but I'm sure you have a good reason.


Originally posted by SL Remy with karma: 2022 on 2012-12-11

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by ubisum on 2012-12-11:
thanks for answer. i never used launch files, since i'm a ros newbie. could you explain to me how xml code states that ros::spin() loop has to be broken once all messages have been sent?

Comment by SL Remy on 2012-12-11:
The parameter required="true" means that if that node stops (or terminate) then all the other nodes in the launch script also must be stopped. Assuming that the stagelistener code is processing the data as expected, when the rosbag node is done, it should be terminated by roslaunch housekeeping.

$\endgroup$
0
$\begingroup$

Rosanswers logo

I'm not aware of such functionality in rosbag specifically.

rosbag quits once it is through, so you could just check if the rosbag node is still running. If one of the topics is only contained in the bagfile, you could also just see if there is a publisher for the topic left and if not, conclude that it has finished.


Originally posted by dornhege with karma: 31395 on 2012-12-11

This answer was NOT ACCEPTED on the original site

Post score: 1

$\endgroup$
0
$\begingroup$

Rosanswers logo

Another potential solution is to write the second part of your system (the part that takes input from the keyboard) as a separate ROS node that communicates with the original node. Then, you don't have to drop out of the spin(). This doesn't solve the problem of knowing when rosbag is done, though.

One hack that might work is to record a second bag file done.bag with a single message in it on a new topic (let's call it done). Then play the bags back-to-back: rosbag play subset.bag done.bag. When you see the message on the done topic, then you know that the first bag is finished, and that you can start listening for command-line input (using the method in the first part of this answer).

A bit kludgey, but it might work.


Originally posted by Bill Smart with karma: 1263 on 2012-12-11

This answer was NOT ACCEPTED on the original site

Post score: 1

$\endgroup$

Your Answer

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