Ask Your Question
0

A strange problem about ros::init()

asked 2012-02-09 05:42:43 -0600

Mike Gao gravatar image

Hello! I encounter a really strange problem about ros::init(). I successfully compile the whole program, and of course the ros::init function is called at the first line of the "main program" as usual, then the creation of ros::NodeHandle is called. But when I run the program, the ros tells me that "You must call ros::init() before creating the first NodeHandle", then stops the program. And I also checked the related source code which says it is because the ros initiation fails (well, naturally), but why? Can anyone provide some clues? Really appreciate!

edit retag flag offensive close merge delete

Comments

By "main program" do you mean `main()`?
DimitriProsser gravatar imageDimitriProsser ( 2012-02-09 05:50:46 -0600 )edit
Take the first/minimal example from the tutorials and that should work. You can compare it to your code and see what's different. Without any more information, people can just guess what you are doing.
dornhege gravatar imagedornhege ( 2012-02-09 06:27:14 -0600 )edit

3 Answers

Sort by » oldest newest most voted
7

answered 2012-02-09 16:07:04 -0600

Mac gravatar image

Do you have any ROS-related variables outside of main? For example, when I write a small node (too small be rolled up inside a class), I usually end up with global variables; main initializes them, and then my callback uses them.

But: global variables get constructed before main is called, so if you're using something that refers to a NodeHandle internally, you'll get this error. I almost always get it with tf::TransformListener, just because I forget that it's going to happen.

The solution is to store a pointer (I generally use a boost::shared_ptr<T>) to that object, not just a raw object, and then fill the pointer in in main after you call ros::init().

edit flag offensive delete link more

Comments

That is my problem. Can you give more details on your solution? Thanks.

Procópio gravatar imageProcópio ( 2012-03-01 23:38:34 -0600 )edit

All of my ROS-aware global variables are declared as boost::shared_ptr<T>s, rather than just objects; those pointers get set in main(), _after_ ros::init().

Mac gravatar imageMac ( 2012-03-02 15:59:13 -0600 )edit

Could you provide a code sample? Thank you.

2ROS0 gravatar image2ROS0 ( 2014-11-25 14:19:06 -0600 )edit

i tryed your suggessedboost::shared_ptr<Robot> tars(new Robot());it doesn`t work:^(

feixiao gravatar imagefeixiao ( 2015-08-31 20:14:27 -0600 )edit
0

answered 2018-01-19 21:26:55 -0600

clyde gravatar image

updated 2018-01-19 21:54:44 -0600

@Mac is exactly right. I'm adding another answer only to suggest another common design pattern: use a C++ class to defer variable initialization. The example below includes a TransformBroadcaster private variable, which will create a NodeHandle. It gets initialized when Publisher publisher is created.

#include <ros/ros.h>
#include <tf2_ros/transform_broadcaster.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
#include <sensor_msgs/Imu.h>

class Publisher
{
private:

  tf2_ros::TransformBroadcaster tf_broadcaster_;
  ros::Subscriber imu_sub_;

  void imuCallback(const sensor_msgs::ImuConstPtr &msg)
  {
    geometry_msgs::TransformStamped imu_tf;
    imu_tf.header.stamp = ros::Time::now();
    imu_tf.header.frame_id = "base_link";
    imu_tf.child_frame_id = "imu_link";
    imu_tf.transform.rotation = msg->orientation;
    tf_broadcaster_.sendTransform(imu_tf);
  }

public:

  Publisher(ros::NodeHandle& nh_priv)
  {
    imu_sub_ = nh_priv.subscribe<sensor_msgs::Imu>("/imu/data", 10, &Publisher::imuCallback, this);
  }
};

int main(int argc, char **argv)
{
  ros::init(argc, argv, "tf_publish");
  ros::NodeHandle nh("");
  ros::NodeHandle nh_priv("~");
  Publisher publisher(nh_priv);
  ros::spin();
  return 0;
}
edit flag offensive delete link more

Comments

Should your { and } be ( and ), respectively?

jayess gravatar imagejayess ( 2018-01-19 21:35:07 -0600 )edit

Ah, I was having fun w/ C++14. I changed it to parens. :-)

clyde gravatar imageclyde ( 2018-01-19 21:55:40 -0600 )edit
0

answered 2012-02-09 16:32:08 -0600

ahendrix gravatar image

It's possible that you have some sort of global variable that either is a nodeHandle, or contains a nodeHandle, which is initialized before main() starts.

Are you passing the appropriate arguments to ros::init() ?

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2012-02-09 05:42:43 -0600

Seen: 3,470 times

Last updated: Jan 19 '18