Subscriber error in ROS - boost

This is my subscriber declaration followed by the callback function
message_filters::Subscriber<geometry_msgs::Point32>
point_sub(*nh, "tracked_point", 1);
point_sub.registerCallback(&visualservoing3D::pointCallback);
The callback declaration is
void
visualservoing3D::pointCallback(const geometry_msgs::Point32ConstPtr& msg)
{
//Some functions
}
But the following error pops up. I know its something to do with my subscriber.
/usr/include/boost/function/function_template.hpp:225:
error: no match for call to
‘(boost::_mfi::mf1<void,
visualservoing3D, const
boost::shared_ptr<const
geometry_msgs::Point32_<std::allocator<void>
> >&>) (const boost::shared_ptr<const geometry_msgs::Point32_<std::allocator<void>
>&)’
Thanks,
Nagsaver

point_sub.registerCallback(&visualservoing3D::pointCallback);
You need to bind the non-static member function to an object instance:
#include <boost/bind.hpp>
point_sub.registerCallback(boost::bind(&visualservoing3D::pointCallback, p_vs, _1));
Where p_vs is a (shared) pointer to a visualservoing3D object. If you need/wish to bind to a reference, use boost::ref(vs)

Related

How I can use std::bind to bind class member function as function pointer?

I have Base and Dervided classes. In the Base class I have a typedef for specific function pointer (I think this is function pointer, im not sure):
typedef void (responseHandler)(BaseClass* instance,int resultCode, char* resultString);
And in the same base class I have several functions which accepts this typedef:
unsigned sendDescribeCommand(responseHandler* responseHandler, Authenticator* authenticator = NULL);
In my custom derived class from this Base class I have my response handler function, like this:
void continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString);
How I can use this method as input for sendDescribeCommand?
I tried this:
DerivedClass->sendDescribeCommand(DerivedCLass->continueAfterDescribe, MyAuth), but this did not build with error:
"error C3867: 'DerivedClass::continueAfterDESCRIBE': non-standard syntax; use '&' to create a pointer to member"
I also tried to use std::bind:
auto responseCallback = std::bind(&DerivedClass::continueAfterDESCRIBE, DerivedClassInstance);
DerivedClass->sendDescribeCommand(responseCallback, ourAuthenticator);
It also give me an error: no suitable conversion from std::bind to my response handler.
I know there is a way to make my method static, but Im curious if there is another way?

Callback pattern with a Functor

I'm trying to wrap an HttpRequest object (from Cocos2d-x) in my own functor. Everything's working fine except calling the callback passed to my functor. Can you spot the error in the classes below? (I only pasted the relevant parts of the code).
Cloud.hpp:
#ifndef Cloud_hpp
#define Cloud_hpp
#include "external/json/document.h"
#include "network/HttpClient.h"
using namespace cocos2d::network;
typedef std::function<void()> CloudCallback;
class Cloud
{
private:
std::string url { "http://localhost:3000/1.0/" };
std::string end_point;
CloudCallback callback;
std::string getPath();
void onHttpRequestCompleted(HttpClient *sender, HttpResponse *response);
public:
Cloud (std::string end_point) : end_point(end_point) {}
void operator() (CloudCallback callback);
};
#endif /* Cloud_hpp */
This is the class that stores the callback passed in the constructor. Here's the implementation:
#include "Cloud.hpp"
#include <iostream>
std::string Cloud::getPath()
{
return url + end_point;
}
void Cloud::operator()(CloudCallback callback)
{
this->callback = callback;
std::vector<std::string> headers;
HttpRequest* request = new (std::nothrow) HttpRequest();
request->setUrl(this->getPath().c_str());
request->setRequestType(HttpRequest::Type::GET);
request->setHeaders(headers);
request->setResponseCallback(CC_CALLBACK_2(Cloud::onHttpRequestCompleted, this));
HttpClient::getInstance()->send(request);
request->release();
}
void Cloud::onHttpRequestCompleted(HttpClient *sender, HttpResponse *response)
{
this->callback();
}
What I'm trying to do is, make a simple Http request with the help of a functor, calling like this:
Cloud cloud("decks");
cloud([&]() {
CCLOG("Got the decks");
});
I'm getting EXC_BAD_ACCESS(Code=EXC_I386_GPFLT) as soon as the line
this->callback();
is called.
What is it that I am doing wrong here?
EDIT: Now I guess it's something to do with threads. If I remove the HttpRequest and call the callback method passed to the operator() immediately, this works without any problems. Begging for help :-)
It looks like the problem could be a lifetime issue. Since the http response callback is called asynchronously, some objects may have been destroyed in the meantime. There are two possibilities:
The Cloud object itself is destroyed before the callback is called.
One or more objects referenced by the lambda (since you're capturing by reference), may have also gone out of scope and been destroyed.
Try this:
void Cloud::operator()(const CloudCallback &callback)

asio socket, inside a class declaration, scope issue

I want to have a class inside which I initialize and open a tcp socket, but I want to repeatedly write to the socket only by calling a method of that class, without having to re-establish connection everytime.
My code is below. I get the compile time errors as pasted here below the code block.
The method is unable to see the socket that was initialized in the constructor. Seems to be a simple C++ "scope" issue, but beats me!
#include <ctime>
#include <iostream>
#include <string>
#include <asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using asio::ip::udp;
using asio::ip::tcp;
class rpcClass {
char sendBuffer[16];
asio::ip::tcp::endpoint epdPt;
asio::io_service io_service;
asio::ip::tcp::endpoint endPt;
public:
rpcClass () { // constructor
asio::ip::tcp::socket socketTCP(io_service);
strcpy (sendBuffer, "*Constructor*\n");
endPt = asio::ip::tcp::endpoint(asio::ip::address::from_string("127.0.0.1"),\
boost::lexical_cast<int>(5004));
socketTCP.connect(endPt);
socketTCP.write_some (asio::buffer(sendBuffer));
};
void sendRPCData (void) { //send data when called from main()
strcpy (sendBuffer, "rpcData\n");
socketTCP.write_some (asio::buffer(sendBuffer));
};
};
int main(void) {
rpcClass rpc; // I WANT THE rpc OBJECT TO SEND DATA
rpc.sendRPCData (); // ONLY WHEN THIS METHOD IS CALLED
return (0);
}
Here is the error output (Eclipse)
rpc-class.cpp: In member function ‘void rpcClass::sendRPCData()’:
rpc-class.cpp: error: ‘socketTCP’ was not declared in this scope
Thanks a lot for helping!
-pn
You've declared socketTCP as a local variable in the constructor, not a member variable of the class.
That means you can't use it in other functions.
Presumably you meant to declare a member variable, and initialize that in the constructor instead of a local variable.

how do we access the socket handle inside a boost asio completion handler?

Is there any possible way to access the socket handle inside a boost asio async completion handler ? i looked at the boost asio placeholders but there is no variable which stores the socket handle.
You can just arrange for it, anyway you would outside boost or asio.
To bind a function that takes e.g. a socket to expose a void() function you can use bind:
int foo(std::string const& s, int);
std::function<void()> adapted = std::bind(foo, "hello world", 42);
So, usually you'd have code similar to this:
boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
boost::bind(&client::handle_connect, this, boost::asio::placeholders::error));
Note, by using bind and this, we've bound a member function to the completion handler:
struct client
{
// ....
void handle_connect(boost::system::error_code err)
{
// you can just use `this->socket_` here
// ...
}
};
This implies that in handle_connect we can just use the socket_ member variable.
However, if you want to make things complicated you can use free functions as well
boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
boost::bind(&free_handle_connect, boost::ref(socket_), boost::asio::placeholders::error));
Now the implied handler function looks like
static void free_handle_connect(
boost::asio::ip::tcp::socket& socket_,
boost::system::error_code err)
{
// using `socket_` as it was passed in
int fd = _socket.native_handle_type();
}

C++11 Lambda function compilation error

i am new using c++11 features and also tryng to use SDL_Widget-2 lib for build a simple Gui for my project. But i am getting stuck in the problem :
#include "sdl-widgets.h"
class Builder
{
public:
Builder():top_win(nullptr)
,but(nullptr)
{
top_win=new TopWin("Hello",Rect(100,100,120,100),0,0,false,
[]() {
top_win->clear();
draw_title_ttf->draw_string(top_win->render,"Hello world!",Point(20,40));
}
);
but=new Button(top_win,0,Rect(5,10,60,0),"catch me",
[](Button *b) {
static int dy=60;
b->hide();
b->move(0,dy);
b->hidden=false;
dy= dy==60 ? -60 : 60;
});
}
private:
TopWin * top_win;
Button *but;
};
int main(int,char**) {
Builder aViewBuilder;
get_events();
return 0;
}
with the error in the compilation stage:
In lambda function:
error: 'this' was not captured for this lambda function
error: 'this' was not captured for this lambda function
this error is printed out twice int the console.
I have try :
[this](){}
[=](){}
and
[&](){}
with different compile error but a cannot go more further.
Can any see a fix?
You do need to capture with [this] or [&]. I suspect that the TopWin and Button constructors take raw function pointers, and need to take std::functions instead.
A plain vanilla function pointer is not compatible with capturing lambdas. std::function is able to work like a function pointer that also allows safe storage of captured data. (i.e. the captured objects will need to be properly copied or destroyed when the function object is itself copied or destroyed)

Resources