0
$\begingroup$

Rosanswers logo

I am creating a class that subscribes to an Odometry message and in the corresponding callback function updates an OccupancyGrid message which is published to a topic. I've got all this working just fine. However, in the class constructor, where I initialize the OccupancyGrid, I would like to publish that OccupancyGrid even before the callback function ever gets called. This for some reason is not working. I also notice another problem, which I think is related. When I go to set the OccupancyGrid.info.map_load_time to ros::Time::now() in the class constructor the time is always zero. However, when I do the same thing for the OccupancyGrid.header.stamp in the callback function, everything works as expected (as does the publish).

I created a simplified program that exhibits the same problem where I subscribe to a std_msgs/Bool message and publish a std_msgs/Time message. Again, the publish and ros::Time::now() don't work in the constructor but do work in the callback function.

Here's the class declaration:

class PubTest {
 private:
  std_msgs::Time time_;
  void CB(const std_msgs::Bool& msg);
  ros::NodeHandle nh_;
  ros::Publisher pub_;
  ros::Subscriber sub_;

 public:
  PubTest();
  ~PubTest();
};

Here's the Constructor:

PubTest::PubTest() {
  // Set up the publisher and subsciber objects                                 
  pub_ = nh_.advertise<std_msgs::Time>("time",1);
  sub_ = nh_.subscribe("test",10,&PubTest::CB,this);
  // Test to see if this command works or returns zero                          
  ros::Time begin = ros::Time::now();
  ROS_INFO_STREAM("The time in the constructor is " << begin);
  // And test to see if publish works                                           
  time_.data = begin;
  pub_.publish(time_);
};

The callback function:

void PubTest::CB(const std_msgs::Bool& msg){
  // Test to see if this command works or returns zero                          
  ros::Time currTime = ros::Time::now();
  ROS_INFO_STREAM("The time in the callback function is " << currTime);
  // And test to see if publish works                                           
  time_.data = currTime;
  pub_.publish(time_);
} 

And finally, main:

int main(int argc, char **argv) {
  ros::init(argc, argv, "pubTest");
  PubTest pubTest;
  ROS_INFO_STREAM("The time in main after the constructor is " << ros::Time::now());
  ros::spin();
  return 0;
}

And the output:

[ INFO] [1438286118.670196332]: The time in the constructor is 0.000000000
[ INFO] [1438286118.670353480]: The time in main after the constructor is 0.000000000
[ INFO] [1438286119.440117003, 4853.700000000]: The time in the callback function is 4853.700000000

The results of running this program is that the publish in the constructor never happens and all the times that are printed to the screen with ROS_INFO_STREAM are zero (including the one that happens in main). However, whenever I publish a std_msgs/Bool to the topic "test", the correct ROS time is printed to the screen with ROS_INFO_STREAM and the publish function works correctly. Any idea what it is that I'm missing?

EDIT 1

I was previously running all of this with stage running in the background. When I shut down roscore and everything along with it and reran my pubTest node by itself the time all worked just fine and corresponded to wall time. However, the initial publish inside the constructor still did not work.

Upon reading the Clock documentation, I noticed the following:

If the /use_sim_time parameter is set, the ROS Time API will return time=0 until it has received a value from the /clock topic.

If publishing and subscribing aren't working inside the class constructor, this would explain the return of 0 time since no value has been received from the /clock topic. So from this, I think the problem boils down to publishing and subscribing not working. It has nothing to do with time.

EDIT 2

And on further inspection, adding a small ros::Duration(0.1).sleep(); before the publish command solves everything. I'm wondering now if there is a more elegant way to wait until publishing and subscribing is working. A try, catch or something?


Originally posted by kleinma on ROS Answers with karma: 48 on 2015-07-30

Post score: 0

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

A time of zero means that time has not been initialized. Time documentation

It will have needed to check the parameter server for use_sim_time and then fallen back to wall clock time. (Or if you're in a simulator to have recieved a /clock signal.)

The reason it's not publishing is a similar problem that you're calling publish before the publisher has estabilized a connection with the subscribers. It's not uncommon for a message published immediately after a publisher is created to not be received.

Edit:

As mentioned in the docs. A common approach is to loop waiting for non-zero time now values. (The duration sleep implicitly does this.)


Originally posted by tfoote with karma: 58457 on 2015-07-30

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by kleinma on 2015-07-31:
Yes, a small wait was necessary for the publishing and subscribing to begin working. This also made time = 0.0 during simulation since no message on /clock was received.

$\endgroup$

Your Answer

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