0
$\begingroup$

Rosanswers logo

Hi, here the minimal example I could create to explain a problem with my program which is splitted into 2 classes. One class creates an istance of the second one:

Let's start with the main file:

#include <ros/ros.h>
#include "include/foo.h"
#include "include/bar.h"
int main ( int argc, char **argv ) {
   ros::init( argc, argv, "main_node" );
   ros::NodeHandle nh;
   ros::NodeHandle nh_private( "~" );
    
    boost::scoped_ptr<Foo> trajectory( new Foo( nh, nh_private ) );
    ROS_INFO( "Waiting some seconds..." ); // Just for fun
    ros::Duration(3.0).sleep();
    
    return 0;
}

The class Foo has a constructor which initialize the class and later, thtough an internal function, create an istance of the second class.

class Foo {
    private:
     /* private variables here */

    private:
    void initParam();
    /* of course here there are much more functions already implemented.... */

}

in initParam() I have the following creation of the last class:

void initParam()  // A method defined in Foo
{
 /* code code code...*/
  boost::scoped_ptr<Bar> way( new Bar( nh_ ) ); // <- !!!! Here is the same NodeHdandle of the master class pased by VALUE
  way->amIAlive(); // <- Yes it is....the call is working
  ROS_INFO( "Getting a random value: %6.4f", way->generateValues() ) // <-working perfectly here too
  /*...*/
}

and lately the class Bar in which I have defined a timer to publish some data regularly:

class Bar {
   Bar::Bar( ros::NodeHandle nh ): nh_(nh) {

    marker_pub_ = nh_.advertise<visualization_msgs::MarkerArray>( "visualization_marker_array", 10 ); // To publish data on RViz
   
  ros::Timer timeloop_ = nh_.createTimer( ros::Duration( set_duration_time_ ), &Bar::publishPoints, this ); // Nothing...here doesn't publish anything... Why!?!?

void Bar::publishPoints( const ros::TimerEvent& event ) const {
    /* publish the markers */
    marker_pub_.publish( marker_array_ );
}
}

So guys...the problem. The problem is the second class (Bar) gets the node passed by value but doesn't publish anything. Doing:

$ rostopic echo /visualization_marker_array

stucks all the time. Other functions implemented in the class are working correctly and I get the calculation for the points in the right way. What could be the reason?

I put some comments in the constrctors and destructors of both classes to see where could be the problem and here is the output:

me@YE-166:~/workspace_ros$ rosrun my_pkg my_prog
[ INFO] [1417875069.502609530]: Constructor of the Foo class has been called
[ INFO] [1417875069.505375417]: Constructor of the Bar class has been called
[ INFO] [1417875069.505837985]: Valid number of requested waypoints
[ INFO] [1417875072.506157010]: Number of points: 7
[ WARN] [1417875072.506273683]: Calling Destructor of the Bar's class...
[ INFO] [1417875072.508900594]: Waiting some seconds...
[ WARN] [1417875075.509383455]: Calling Destructor of the Foo's Class...
me@YE-166:~/workspace_ros$

Seems to working correctly but I suppose (and it is my opinion) that the class Bar doesn't have the time to publish data on the topic. Fpor that reasons I put a waiting function inside of it to give it time. But it doesn't help. The class runs the function Bar::publishPoints() which is time event function and it is suppose to run all the time. But get destroy with the class

2 things I have:

  • I want to be able to publish data from the second class Bar passing the nodehandle (doesn't matter how: pointer, value, reference...);
  • The timed function must run all the time in background. So the class Bar must not be destroyed;

Could you give me some help? Regards


Originally posted by Andromeda on ROS Answers with karma: 893 on 2014-12-06

Post score: 2


Original comments

Comment by kramer on 2014-12-06:
Is there a spin or spinOnce anywhere in your code?

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

As @kramer has pointed out, you have no ros::spin() function in your main, meaning that a) no callbacks get processed and b) main returns immediately, destroying Foo.

Even after adding ros::spin(), Bar will still die earlier than you expect, because it will be destroyed when the initParam function returns.

Please read about lifetime, scope, and blocking on stackoverflow.


Originally posted by paulbovbel with karma: 4518 on 2014-12-06

This answer was ACCEPTED on the original site

Post score: 3


Original comments

Comment by kramer on 2014-12-06:
For clarity: a Timer uses ROS's callback mechanism for its operation; without a spin, the publishPoints method will never be called.

I totally overlooked Bar's scope and destruction...nice catch, @paulbovbel.

Comment by Andromeda on 2014-12-07:
Ok, guys. Thanks. a lot. A didn't know, that a timer has the same callback like messages and topics. About the scope of a class I agree with you, but I was sure that the running timer doesn't let the function to return. The visibility is right, but I misunderstood how a timer is currently working.

Comment by paulbovbel on 2014-12-07:
createTimer does return immediately. And then the timer object goes out of scope, so it won't be running anymore. Just like with pub/sub, you need the object to be in scope (i.e. be a member of the class and not just temporary on the heap), and you need ros::spin to process callbacks.

$\endgroup$

Your Answer

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