ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | Q&A
Ask Your Question

How to add parameters to a subscriber callback function given that it is also an action_client

asked 2017-08-02 20:12:54 -0600

Canni gravatar image

Hello, I'm new to ROS and my situation is the following: I have a node which subscribes to a Topic, so of course I have my callback function (which by the way uses a custom message so the problem may be there, I don't know. I don't really know C++ either :D ). The point is that this node must also be a client for an actionlib Client-Server structure. So every time my node reads something from the topic it is subscribed to, I need also to inform my actionlib Server. This is why I need to have a "Client" parameter in my callback function, to send also a message to the Server.

My callback SHOULD look like this:

void polygonCallback(const es_1::Draw msg, Client* cl){//Stuff}

And I just defined "Client" like this

typedef actionlib::SimpleActionClient<es_1::polygonAction> Client;

Now, I found online that to do what I want to do I sould use boost::bind() and I did. Just like this:

ros::Subscriber sub = n.subscribe<es_1::Draw>("draw", 1000, boost::bind(polygonCallback,_1,&client));

But when I try to "catkin_make" this is the error that pops out:

In file included from /usr/include/boost/bind.hpp:22:0, from /opt/ros/kinetic/include/ros/publisher.h:35, from /opt/ros/kinetic/include/ros/node_handle.h:32, from /opt/ros/kinetic/include/ros/ros.h:45, from /home/canniz/Desktop/catkin_ws/src/es_1/src/polygon_action_client.cpp:1: /usr/include/boost/bind/bind.hpp: In instantiation of ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = void (*)(es_1::Draw_<std::allocator<void> >, actionlib::SimpleActionClient<es_1::polygonAction_<std::allocator<void> > >*); A = boost::_bi::list1<const boost::shared_ptr<const es_1::Draw_<std::allocator<void> > >&>; A1 = boost::arg<1>; A2 = boost::_bi::value<actionlib::SimpleActionClient<es_1::polygonAction_<std::allocator<void> > >*>]’: /usr/include/boost/bind/bind_template.hpp:47:59: required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(const A1&) [with A1 = boost::shared_ptr<const es_1::Draw_<std::allocator<void> > >; R = void; F = void (*)(es_1::Draw_<std::allocator<void> >, actionlib::SimpleActionClient<es_1::polygonAction_<std::allocator<void> > >*); L = boost::_bi::list2<boost::arg<1>, boost::_bi::value<actionlib::SimpleActionClient<es_1::polygonAction_<std::allocator<void> > >*> >; boost::_bi::bind_t<R, F, L>::result_type = void]’ /usr/include/boost/function/function_template.hpp:159:11: required from ‘static void boost::detail::function::void_function_obj_invoker1<FunctionObj, R, T0>::invoke(boost::detail::function::function_buffer&, T0) [with FunctionObj = boost::_bi::bind_t<void, void (*)(es_1::Draw_<std::allocator<void> >, actionlib::SimpleActionClient<es_1::polygonAction_<std::allocator<void> > >*), boost::_bi::list2<boost::arg<1>, boost::_bi::value<actionlib::SimpleActionClient<es_1::polygonAction_<std::allocator<void> > >*> > >; R = void; T0 = const boost::shared_ptr<const es_1::Draw_<std::allocator<void> > >&]’ /usr/include/boost/function/function_template.hpp:940:38: required from ‘void boost::function1<R, T1>::assign_to(Functor) [with Functor = boost::_bi::bind_t<void, void (*)(es_1::Draw_<std::allocator<void> >, actionlib::SimpleActionClient<es_1::polygonAction_<std::allocator<void> > >*), boost::_bi::list2<boost::arg<1>, boost ... (more)

edit retag flag offensive close merge delete

2 Answers

Sort by » oldest newest most voted

answered 2017-08-03 03:40:32 -0600

naveedhd gravatar image

updated 2017-08-03 03:42:26 -0600

First, change your callback argument const es_1::Draw msg to const es_1::Draw::ConstPtr& msg.

As mentioned in section 2.2. of roscpp tutorial, "The message is passed in a boost shared_ptr"

Now since callback accepts the arguments as boost::shared_ptr, you may encapsulate your action client like this:

boost::shared_ptr<Client> client;

client.reset(new Client(..)); // initialize

ros::Subscriber sub = n.subscribe<es_1::Draw>("draw", 1000, boost::bind(polygonCallback, _1, client));


void polygonCallback(const es_1::Draw::ConstPtr &msg, const boost::shared_ptr<Client> &cl){//Stuff} // use cl by ->

edit flag offensive delete link more


Thank you so much! I didn't study c++ so all this stuff is absolutely new to me. One day maybe I'll understand in detail what I'm doing ahahah Now it's compiling!

Canni gravatar image Canni  ( 2017-08-03 11:47:39 -0600 )edit

answered 2017-08-02 23:52:19 -0600

jayess gravatar image

updated 2017-08-03 00:04:29 -0600

It's not exactly clear to me what you're trying accomplish, but it sounds like you need to have an action server be updated by data on a topic. A good way to accomplish this would be with a server with a class and a client with a class.

edit flag offensive delete link more


Thanks for the answer The problem Is that this is a stupid homework and I can't change the structure which looks like this: Publisher->Topic->Subscriber/ActionClient->ActionServer->Turtlebot So my problem Is that I must have one more parameter in the callback function (which Is called by Ros )

Canni gravatar image Canni  ( 2017-08-03 00:00:38 -0600 )edit

And so, the callback can't Just have one more parameter without using the Boost::bind trick. But It isn't working

Canni gravatar image Canni  ( 2017-08-03 00:01:45 -0600 )edit

Unless I'm misunderstanding your comment the Subscriber/ActionClient portion would be the class.

jayess gravatar image jayess  ( 2017-08-03 00:04:01 -0600 )edit

Your Answer

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

Add Answer

Question Tools



Asked: 2017-08-02 20:12:54 -0600

Seen: 1,791 times

Last updated: Aug 03 '17