Ask Your Question
0

Why "subs_.push_back" in listener_with_userdata.cpp

asked 2016-05-17 20:23:14 -0500

Weiwei gravatar image

In the tutorial of listener, there is an example for listener_with_userdata, why we use push_back to initialise the three different callback functions.

class Listener
{
public:
  ros::NodeHandle node_handle_;
  ros::V_Subscriber subs_;

  Listener(const ros::NodeHandle& node_handle)
  : node_handle_(node_handle)
  {
  }

  void init()
  {
    subs_.push_back(node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(&Listener::chatterCallback, this, _1, "User 1")));
    subs_.push_back(node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(&Listener::chatterCallback, this, _1, "User 2")));
    subs_.push_back(node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(&Listener::chatterCallback, this, _1, "User 3")));
  }

  void chatterCallback(const std_msgs::String::ConstPtr& msg, std::string user_string)
  {
    ROS_INFO("I heard: [%s] with user string [%s]", msg->data.c_str(), user_string.c_str());
  }
};

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener_with_userdata");
  ros::NodeHandle n;

  Listener l(n);
  l.init();

  ros::spin();

  return 0;
}

For the init() part.

void init()
 {
        subs_.push_back(node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(&Listener::chatterCallback, this, _1, "User 1")));
        subs_.push_back(node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(&Listener::chatterCallback, this, _1, "User 2")));
        subs_.push_back(node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(&Listener::chatterCallback, this, _1, "User 3")));
 }

I checked the code document, it seems that the line match this version of subscriber http://docs.ros.org/indigo/api/roscpp...

It seems that the push_back code matches the bellowing version.

template<class M>
Subscriber subscribe(const std::string& topic, 
  uint32_t queue_size, 
  const boost::function<void (const boost::shared_ptr<M const>&)>& callback, 
  const VoidConstPtr& tracked_object = VoidConstPtr(), 
  const TransportHints& transport_hints = TransportHints())
{
  SubscribeOptions ops;
  ops.template init<M>(topic, queue_size, callback);
  ops.tracked_object = tracked_object;
  ops.transport_hints = transport_hints;
  return subscribe(ops);
}

I know the basic demos of publish and subscribe mechanism of ROS, but I am not so familiar with the advanced C++ templates.

Q1. <std_msgs::String>is the return type of node_handle_.subscribe is that right? Is this type match the first argument of the chatterCallback function?

Q2. Why we use push_back() to initialize these three callback functions? Are they running as separated thread after push into the V_Subscriber?

Q3. I also did not catch the meaning of "On success, a Subscriber that, when all copies of it go out of scope, will unsubscribe from this topic.". What is the scope and why it will go out of scope during the callback?

Does any could explain the logic here?

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2016-05-17 21:09:08 -0500

Dirk Thomas gravatar image

Answer for Q1:

The return type of a function / method is before the function / method name. In this case it is Subscriber.

Answer for Q2:

The subscribe methods return a reference counted publisher. When all copies of it go out of scope it will unsubscribe from the topic. Therefore the subscribers are stored in a vector to prevent them from going out of scope. You could also store each subscriber in a local variable instead. I vector has nothing to do with threads.

Answer for Q3:

I think you need to google a bit about variable scope, reference counting and when such objects are being deleted. A simple example:

{
  Subscriber s = node_handle.subscribe<std_msgs::String>(...);
  // some more code
} <-- in this line the scope of variable "s" on the stack ends, therefore it is being removed

In case of an object it is being destructed. In case of a reference counted instance it is being destructed if no other reference is stored anywhere.

By storing the subscriber in the vector (which has a bigger scope) the subscriber is not being removed yet but stays around (in the case of the tutorial until the program terminates).

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

1 follower

Stats

Asked: 2016-05-17 20:23:14 -0500

Seen: 56 times

Last updated: May 17 '16