ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
8

How to make callback function called by several subscriber?

asked 2013-05-30 12:45:13 -0600

zieben gravatar image

updated 2022-02-24 10:24:29 -0600

130s gravatar image

Hello, I want to make multi-subscriber that calls same function with different argument.

For example,

std::vector<ros::Subscriber> sub;
std::vector<sensor_msgs::JointState> position;

position.resize(2);
sub.resize(2);

for(int i=0; i < sub.size(); i++)
{
   char sub_name[20];
   sprintf(sub_name, "sub_%d", i);
   sub[i] = node.subscribe(sub_name, 1, &Myclass::callback, this);
}

Myclass::callback(const sensor_msgs::JointStateConstPtr &msg)
{
   this->position[i] = *msg;
}

So my questions are:

  1. How to sent array index i from main function to Myclass::callback?

  2. Can several subscriber call same callback function like that?

Thank you for your answer. This is additional question.

I modified source code as follows:

position.resize(2);
sub.resize(2);

for(int i=0; i < sub.size(); i++)
{
   char sub_name[20];
   sprintf(sub_name, "sub_%d", i);
   sub[i] = node.subscribe(sub_name, 1, boost::bind(&Myclass::callback, this, _1, i));
}

Myclass::callback(const sensor_msgs::JointStateConstPtr &msg, int i)
{
   this->position[i] = *msg;
}

And this is error messages I got.

error: no matching function for call to ‘ros::NodeHandle::subscribe(char [20], int, boost::_bi::bind_t<void, boost::_mfi::mf2<void, Myclass, const boost::shared_ptr<const sensor_msgs::JointState_<std::allocator<void> > >&, int>, boost::_bi::list3<boost::_bi::value<Myclass*>, boost::arg<1>, boost::_bi::value<int> > >)’

and candidates are:

/opt/ros/groovy/include/ros/node_handle.h:379:14: note: template<class M, class T> ros::Subscriber ros::NodeHandle::subscribe(const string&, uint32_t, void (T::*)(M), T*, const ros::TransportHints&)
/opt/ros/groovy/include/ros/node_handle.h:390:14: note: template<class M, class T> ros::Subscriber ros::NodeHandle::subscribe(const string&, uint32_t, void (T::*)(M)const, T*, const ros::TransportHints&)
/opt/ros/groovy/include/ros/node_handle.h:438:14: note: template<class M, class T> ros::Subscriber ros::NodeHandle::subscribe(const string&, uint32_t, void (T::*)(const boost::shared_ptr<const MReq>&), T*, const ros::TransportHints&)
/opt/ros/groovy/include/ros/node_handle.h:448:14: note: template<class M, class T> ros::Subscriber ros::NodeHandle::subscribe(const string&, uint32_t, void (T::*)(const boost::shared_ptr<const MReq>&)const, T*, const ros::TransportHints&)
/opt/ros/groovy/include/ros/node_handle.h:498:14: note: template<class M, class T> ros::Subscriber ros::NodeHandle::subscribe(const string&, uint32_t, void (T::*)(M), const boost::shared_ptr<U>&, const ros::TransportHints&)
/opt/ros/groovy/include/ros/node_handle.h:509:14: note: template<class M, class T> ros::Subscriber ros::NodeHandle::subscribe(const string&, uint32_t, void (T::*)(M)const, const boost::shared_ptr<U>&, const ros::TransportHints&)
/opt/ros/groovy/include/ros/node_handle.h:559:14: note: template<class M, class T> ros::Subscriber ros::NodeHandle::subscribe(const string&, uint32_t, void (T::*)(const boost::shared_ptr<const MReq>&), const boost::shared_ptr<U>&, const ros::TransportHints&)
/opt/ros/groovy/include/ros/node_handle.h:570:14: note: template<class M, class T> ros::Subscriber ros::NodeHandle::subscribe(const string&, uint32_t, void (T::*)(const boost::shared_ptr<const MReq>&)const, const boost::shared_ptr<U>&, const ros::TransportHints&)
/opt/ros/groovy/include/ros/node_handle.h:618:14: note: template<class M> ros::Subscriber ros::NodeHandle::subscribe(const string&, uint32_t, void (*)(M), const ros::TransportHints&)
/opt/ros/groovy/include/ros/node_handle.h:663:14: note: template<class M> ros::Subscriber ros::NodeHandle ...
(more)
edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted
21

answered 2013-05-30 14:19:04 -0600

Philip gravatar image

updated 2013-06-01 02:00:00 -0600

Just use boost::bind to create a "virtual" callback function based on your "real" one. I haven't got the syntax for callbacks to objects in my head right now, but

for (int i = 0; i < 10, i++)
     sub[i] = node.subscribe(sub_name, 1, boost::bind(callback, _1, i));

would create 10 subscribers that are each tied to the function callback(msg_type msg, int i).

Edit: Using a member-function of an actual object is done the same way as you'd do it without boost::bind.

for (int i = 0; i < 10, i++)
     sub[i] = node.subscribe(sub_name, 1, boost::bind(&MyClass::callback, this, _1, i));

Edit 2: With respect to the new question, the first thing I'd try is templating the subscriber to the correct datatype:

[...]
sub[i] = node.subscribe<sensor_msgs::JointState>(sub_name, 1, boost::bind(&Myclass::callback, this, _1, i));
[...}
edit flag offensive delete link more

Comments

The ros2 create_subscription equivalent #q289207

lucasw gravatar image lucasw  ( 2018-11-01 10:25:04 -0600 )edit

Question Tools

3 followers

Stats

Asked: 2013-05-30 12:45:13 -0600

Seen: 11,309 times

Last updated: Feb 24 '22