I'm trying to subscribe to different topics in ROS (one for every vehicle that pops up) using the same callback for all of them. The idea is that boost::bind will pass the topic name as an additional argument so I know which vehicle I should access in the callback.
The problem is that, even though I've gone through multiple questions on the topic, none of the solutions seem to work.
Basically, I have the following class VOBase containing a std::map<std::string, VOAgent*> agents_ with a member function as follows:
void VOBase::callback_agentState(const custom_msgs::VState::ConstPtr& vStateMsg,
std::string topic) {
// [...] regex to find agent name from topic string
std::string agent_name = match.str();
// [...] Check if agent name exists, else throw exception
// Process message
agents_[agent_name]->pos_ = vStateMsg->pose.position; // etc.
}
Which I'm calling through this subscription:
void VOBase::callback_agentList(const custom_msgs::VehicleList& vehListMsg) {
// [...] New agent/vehicle found: process vehListMsg and get agent_name string
// Subscribe to VState
topic_name = agent_name + "/state_estimate";
subscribers_[topic_name] = nodeHandlePtr->subscribe<custom_msgs::VState>(topic_name, 1,
std::bind(&VOBase::callback_agentState, this, _1, topic_name));
}
However, I'm getting a template argument deduction/substitution failed with all the candidates and this error:
mismatched types ‘std::reference_wrapper<_Tp>’ and ‘VO::VOBase*’
typename add_cv<_Functor>::type&>::type>()(
I've tested a number of the solutions out there, e.g. using std::ref(this) to get a std::reference_wrapper<_Tp> instead of a VO::VOBase* (the reference doesn't survive though: use of deleted function), using boost::bind instead of std::bind (but it should be all the same since C++11), with and without the ...::ConstPtr for the ROS message in the callback function arguments (and in the subscribe<acl_msgs::ViconState::ConstPtr>, etc. So I'm just juggling with partial solutions and their permutations here...
Any clues?
I haven't looked into the specifics of the code you show (it's hard to figure out the information not shown and deduce what's required).
However, last time I helped someone with ROS subscriptions and the type-deduction, it was apparent that the handler should take a shared_ptr to the message. This might help you get started seeing a solution:
Error using boost::bind for subscribe callback
Related
I have a question regarding ROS2 messages or possibly just standard C++, maybe one of you have tried something similar before, or can tell me that what I am trying to accomplish won't work.
What I'm trying to create is a library that I can use to quickly create a ROS2 Node, dynamically add publishers and/or subscribers, depending on the situation, before starting the node.
The problem I'm facing is that ROS2 uses message types like std_msgs::msg::String. Example source can be found on github.
The source uses the following code to create a subscriber:
subscription_ = this->create_subscription<std_msgs::msg::String>("topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
I would like to create a function that can create a subscriber using a given message type i.e.:
void createListener(std::string topicName, 'messagetype')
{
auto subscription_ = this->create_subscription<'messagetype'>(topicname, 10, [this]{}, this, _1));
//adding the created subscriber to a list is already done
}
This would allow me to use the same function while still being able to use different messages like:
nav_msgs::msg::Path
geometry_msgs::msg::Point
without having to create a new function for every message type.
I can't seem to find the template type that is used in the create_subscribtion<>() function, all I can find is that each message creates its own type.
std_msgs::msg::String would return the std_msgs::msg::String_<std::allocator<void>> type.
Is there a way that i can make this work?
You could use templates here right, by doing the following:
template <typename MsgType>
void createListener(std::string topicName)
{
auto subscription_ = this->create_subscription<MsgType>(topicname, 10, [this]{}, this, _1));
//adding the created subscriber to a list is already done
}
This function can then be called, for example by:
createListener<nav_msgs::msg::Path>("topicName")
In order to avoid computations in GUI thread on button click I'm trying to run it in separate thread.
As soon as I want to have ability to monitor progress my code is based on this source.
So, my code is:
futureWatcher.setFuture(QtConcurrent::mapped(library_pool.cbegin(), library_pool.cend(), util->loadFilesInLibrary(library_pool)));
futureWatcher.waitForFinished();
table = QFuture::result();
Which is quite similar to the given sorce from qt docs, but it gives corresponding errors:
C2893: Failed to specialize function template 'QFuture<QtPrivate::MapResultType<void,MapFunctor>::ResultType> QtConcurrent::mapped(Iterator,Iterator,MapFunctor)'
C2780: 'QFuture<QtPrivate::MapResultType<void,MapFunctor>::ResultType> QtConcurrent::mapped(const Sequence &,MapFunctor)': expects 2 arguments - 3 provided
C2955: 'QFuture': use of class template requires template argument list
'QFuture<T>::result': illegal call of non-static member function
So, how do I properly populate worker thread(s) with function from non-gui class in button_clicked slot without making GUI hand?
UPD
Well, I've succeeded with compiling code for now and this is how it works:
futureWatcher.setFuture(QtConcurrent::run(&this->util, &Utils::loadFilesInLibrary, library_pool.at(0)));
futureWatcher.waitForFinished();
library_pool = future.result();
But button click still results to error in runtime:
My function which I'm trying to run generates no widgets, so the reason of this message is unclear.
I've read couple questions (like this) where all the code stated to work but it resides only in main() which is far from my needs. So, again, how do I start it from GUI thread?
You can use non-static members with QtConcurrent methods with the help of a wrapper. There is more discussion about it at Qt's Forums. Here's another similar question asking about how to use the wrapper.
struct AddWrapper {
Utils *utils = nullptr;
typedef MyType result_type;
AddWrapper(Util *u): instance(u) {};
MyType operator()(const MyType &t) const {
return instance->longMethod(t);
}
}
Utils *foo = new Utils();
AddWrapper wrapper(foo);
QFuture<MyType> results = QtConcurrent::mapped(myList, wrapper);
I'm trying to connect a timeout handler to my gtkmm code as shown in gtkmm book. However, my particular on_timeout() function doesn't need any arguments, and I'm struggling to properly create a sigc::slot object to pass to the connect function, as I encounter the following error (among others):
error: no matching function for call to ‘bind(sigc::bound_mem_functor0<bool, DerivedWindow>)
and several
candidate expects 2 arguments, 1 provided
referring to sigc::bind. How I am calling both functions:
_timeout_slot = sigc::bind(sigc::mem_fun(*this,&DerivedWindow::on_timeout));
_connection = Glib::signal_timeout().connect(_timeout_slot,timeout_value);
I'm doing this on a class DerivedWindow derived from Gtk::Window. What exactly am I doing wrong? Do I need to use sigc::bind and sigc::mem_func if I don't require any arguments?
You don't need sigc::bind here since you are not binding any additional arguments to the slot (dealing with dereferencing the member function pointer for this is already taken care of by sigc::mem_fun). So, this is sufficient:
_timeout_slot = sigc::mem_fun(*this, &MyWindow::on_timeout)
_connection = Glib::signal_timeout().connect(_timeout_slot, timeout_value);
A quick tip: if you can use C++11, you can just pass lambdas as arguments to connect, which makes things more readable:
_connection = Glib::signal_timeout().connect([this]{ return on_timeout(); }, timeout_value);
For this to work, you may need to add
namespace sigc{
SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
}
Also, if you want to connect to signals of a class instance (say a Gtk::Button* btn), you can make things even more compact by defining a macro
#define CONNECT(src, signal, ...) (src)->signal_##signal().connect(__VA_ARGS__)
which then allows you to write
CONNECT(btn, clicked, [this]{ btn_clicked_slot(); });
Here's what I am trying to figure out, their docs don't explain this well enough, at least to me..
Senario:
I have 5 proto files that I generate with protoc for C++. My application needs to receive a message and then be able to iterate through all the fields while accessing their values and names.
What I would like to do is parse a message into the DynamicMessage class and then do the iteration through the fields. This way I don't have to know exactly what message it is and I can handle them all in a single generic way.
I know it's possible to handle the messages by parsing them to their specific type then treating them as their Message base class but for my application that is not desirable.
It looks like what I want to do should be possible via the "--descriptor_set_out" and dynamic message class.
What I've Tried (And Failed With):
I moved the descriptor.proto into the folder with my protos and included it along side my others in the compilation step. I also set the--descriptor_set_out flag to print to a file "my_descriptors.pb.ds"
I have no idea where to proceed from there.
Here's what i've referenced, although there isn't much...
Sorry for the long post, and somewhat vague topic naming schema.
Also, incase it wasn't clear, I assume the messages aren't "Unknown." I assume there will still be the requirement of including the respective headers for each proto so my code knows about the 'unknown' message its handling.
The most common way is to use message composition. Something like:
message Foo {...}
message Bar {...}
message GenericMessage {
enum Type {FOO = 1, BAR = 2};
optional Foo foo = 1;
optional Bar bar = 2;
}
If you make sure that exactly one of either Foo or Bar is present in each GenericMessage, you get the desired behaviour. You read one GenericMessage and then process it as one of several specific messages.
Think about refactoring the protocol. If all you need to do is iterate over the fields, maybe you'd be better off with something like a simple key-value map:
message ValueMessage {
required string key = 1;
optional int IntValue = 2;
optional string StringValue = 3;
optional bool BoolValue = 4;
...
}
message GenericMessage{
repeated ValueMessage = 1;
}
Or maybe you can refactor you protocol some other way.
Warning: my answer is not completely correct I am having some compilation errors regarding conflicts, i will edit when I fix it :). but this is a starting point
It might have been a long time since this question was posted, but I faced something similar this days now working with Protocol Buffers.
First of all the reference is wrong the option on the command that must be added is:
--descriptor_set_out=<Directory>
where Directory is where your compiled version of the descriptor.proto (or .proto compiled that describes your file) is located.
after this you will have to add the reference to the Descriptor.proto file in your autodescriving .proto file.
message MyMessage
{
required google.protobuf.FileDescriptorSet proto_files = 1;
...
}
I have a TcpDevice class which encapsulates a TCP connection, which has an onRemoteDisconnect method which gets called whenever the remote end hangs up. Then, there's a SessionManager object which creates TcpSession objects which take a TcpDevice as a communication channel and inserts them in an internal pointer container for the application to use. In case any of the managed TcpSessions should end, I would like the SessionManager instance to be notified about it and then remove the corresponding session from the container, freeing up the resources associated with it.
I found my problem to be very similar to this question:
Object delete itself from container
but since he has a thread for checking the connections state, it gets a little different from mine and the way I intended to solve it using boost::signals, so I decided to go for a new question geared towards it - I apologize if it's the wrong way to do it... I'm still getting the feel on how to properly use S.O. :)
Since I'm kind of familiar with QT signals/slots, I found boost::signals offers a similar mechanism (I'm already using boost::asio and have no QT in this project), so I decided to implement a remoteDeviceDisconnected signal to be emitted by TcpDevice's onRemoteDisconnect, and for which I would have a slot in SessionManager, which would then delete the disconnected session and device from the container.
To initially try it out I declared the signal as a public member of TcpDevice in tcpdevice.hpp:
class TcpDevice
{
(...)
public:
boost::signal <void ()> remoteDeviceDisconnected;
(...)
}
Then I emitted it from TcpDevice's onRemoteDisconnect method like this:
remoteDeviceDisconnected();
Now, is there any way to connect this signal to my SessionManager slot from inside session manager? I tried this:
unsigned int SessionManager::createSession(TcpDevice* device)
{
unsigned int session_id = session_counter++;
boost::mutex::scoped_lock lock(sessions_mutex);
sessions.push_back(new TcpSession(device, session_id));
device->remoteDeviceDisconnected.connect(boost::bind(&SessionManager::removeDeadSessionSlot, this));
return session_id;
}
It compiles fine but at link time it complains of multiple definitions of remoteDeviceDisconnected in several object code files:
tcpsession.cpp.o:(.bss+0x0): multiple definition of `remoteDeviceDisconnected'
tcpdevice.cpp.o: (.bss+0x0): first defined here
sessionmanager.cpp.o:(.bss+0x0): multiple definition of `remoteDeviceDisconnected'
tcpdevice.cpp.o: (.bss+0x0): first defined here
I found this strange, since I didn't redefine the signal anywhere, but just used it at the createSession method above.
Any tips would be greatly appreciated! Thank you!
My bad! Like we all should expect, the linker was right... there was indeed a second definition, I just couldn't spot it right away because it wasn't defined by any of my classes, but just "floating" around one of my .cpp files, like those found on boost::signals examples.
Just for the record, the initial idea worked like a charm: when a given TcpDevice gets disconnected from the remote end, it emits the remoteDeviceDisconnected signal, which is then caught by the SessionManager object which holds the TcpSession instance that points to that TcpDevice. Once notified, SessionManager's method removeDeadSessionSlot gets executed, iterating through the sessions ptr_list container and removing the one which was disconnected:
void SessionManager::removeDeadSessionSlot()
{
boost::mutex::scoped_lock lock(sessions_mutex);
TcpSession_ptr_list_it it = sessions.begin();
while (it != sessions.end()) {
if (!(*it).device->isConnected())
it = sessions.erase(it);
else
++it;
}
}
Hope that may serve as a reference to somebody!