ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
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 image DimitriProsser  ( 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 image dornhege  ( 2012-02-09 06:27:14 -0600 )edit

3 Answers

Sort by » oldest newest most voted
9

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 image Procó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 image Mac  ( 2012-03-02 15:59:13 -0600 )edit

Could you provide a code sample? Thank you.

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

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

feixiao gravatar image feixiao  ( 2015-08-31 20:14:27 -0600 )edit
1

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 image jayess  ( 2018-01-19 21:35:07 -0600 )edit

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

clyde gravatar image clyde  ( 2018-01-19 21:55:40 -0600 )edit
1

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

Question Tools

Stats

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

Seen: 5,216 times

Last updated: Jan 19 '18