Issue with ros NodeHandle.subscribe with a class method - c++

I am using ros melodic on Ubuntu18.04 and C++14 and am trying to subscribe to a topic using a callback function in a Derived class. I know this is possible as a base class as seen in the 2.3.2 Class Methods section of the ros wiki, but I am trying to modify that for a derived class. I would like to be able to have multiple Scan_matching derived classes for different algorithms, and for main class to be able to select one. Here is what I have:
class Scan_Matching
{
public:
void get_transform(const sensor_msgs::PointCloud2ConstPtr& cloud_msg);
};
class ICP : public Scan_Matching
{
public:
void get_transform(const sensor_msgs::PointCloud2ConstPtr& cloud_msg);
};
int main(){
...
ScanMatching* scan_matching;
scan_matching = new ICP(...);
ros::Subscriber sub = nh.subscribe(topic, 100, &Scan_Matching::get_transform, scan_matching);
...
}
I am confident this is possible but I am not sure if I am implementing this correctly as I
get a linking error from catkin:
[ 14%] Linking CXX executable /home/mike/documents/autonomous_sim/devel/lib/mike_av_stack/localization
CMakeFiles/mike_av_stack_node.dir/scripts/localization/localization.cpp.o: In function `main':
localization.cpp:(.text.startup+0x718): undefined reference to `Scan_Matching::get_transform(boost::shared_ptr<sensor_msgs::PointCloud2_<std::allocator<void> > const> const&)'
collect2: error: ld returned 1 exit status
mike_av_stack/CMakeFiles/mike_av_stack_node.dir/build.make:392: recipe for target '/home/mike/documents/autonomous_sim/devel/lib/mike_av_stack/localization' failed
make[2]: *** [/home/mike/documents/autonomous_sim/devel/lib/mike_av_stack/localization] Error 1
CMakeFiles/Makefile2:2493: recipe for target 'mike_av_stack/CMakeFiles/mike_av_stack_node.dir/all' failed
make[1]: *** [mike_av_stack/CMakeFiles/mike_av_stack_node.dir/all] Error 2
Makefile:145: recipe for target 'all' failed
make: *** [all] Error 2
Invoking "make -j12 -l12" failed
To me this seems like the subscribe function is sending my get_transform function a parameter that is not the type
const sensor_msgs::PointCloud2ConstPtr& cloud_msg
(or in other words)
const boost::shared_ptr<sensor_msgs::PointCloud2 const>& cloud_msg
but instead the type
boost::shared_ptr<sensor_msgs::PointCloud2_std::allocator<void > const> const&
I tested this by trying the following code which compiles fine.
void callback(const boost::shared_ptr<sensor_msgs::PointCloud2 const>& cloud_msg){
}
int main(){
...
ros::Subscriber sub = nh.subscribe(topic, 100, callback);
...
}
I think it might be because of the derived class and I am calling the incorrect overloaded subscriber function. Can someone help me understand what I am doing wrong, and how to fix? Thank you

Related

Linker Error: Undefined reference to `ThreadPool::ThreadPool()'

I have a class threadpool. I have a header file threadpool.h and the implementation threadpool.cc. When trying to I initialize the threadpool like so: ThreadPool *tp = new ThreadPool(); I get the following linker error:
/usr/bin/ld: ../src/libmapreducelib.a(mapreduce_impl.cc.o): in function `Master::Master(MapReduceSpec const&, std::vector<FileShard, std::allocator<FileShard> > const&)':
/aos-pr4/src/master.h:43: undefined reference to `ThreadPool::ThreadPool()'
collect2: error: ld returned 1 exit status
make[2]: *** [test/CMakeFiles/mrdemo.dir/build.make:127: bin/mrdemo] Error 1
make[1]: *** [CMakeFiles/Makefile2:330: test/CMakeFiles/mrdemo.dir/all] Error 2
make: *** [Makefile:130: all] Error 2
Here is my project source hierarchy:
src/
>CMakeLists.txt
>threadpool.h
>threadpool.cc
>otherfiles
CMakeLists.txt
Below is my threadpool.h, threadpool.cc and CMakeLists.txt file.
// in theadpool.h
#ifndef THREADPOOL_H
#define THREADPOOL_H
#pragma once
class ThreadPool {
public:
using Task = std::function<void()>;
// constructor, init static number of workers to be added to queue
ThreadPool()
ThreadPool(int numOfWorkers);
virtual ~ThreadPool();
....
}
#endif
// in threadpool.cc
#include "threadpool.h"
ThreadPool::ThreadPool(){
// commented out
}
....
I even ensured my cmakelist library includes the threadpool.h.
//CMakeLists.txt
project(mapreducer)
include(GenerateProtos.cmake)
add_library(
mapreducelib #library name
mapreduce.cc mapreduce_impl.cc #sources
master.h mapreduce_spec.h file_shard.h threadpool.h) #headers
target_link_libraries(mapreducelib p4protolib)
target_include_directories(mapreducelib PUBLIC ${MAPREDUCE_INCLUDE_DIR})
add_dependencies(mapreducelib p4protolib)
I believe it should be fine and I've used my threadpool in another project. It must be the project hierarchy.

Why am I getting a linker error when using this basic inheritance setup?

This is probably a quite simple question, but I don't how to solve it. I have the following setup of my C++ classes:
MappingTechnique.h
struct MappingTechnique {
virtual void processFrame();
};
struct SimpleGreedyMappingTechnique : MappingTechnique {
void processFrame();
};
MappingTechnique.cpp
#include "MappingTechnique.h"
void SimpleGreedyMappingTechnique::processFrame() {
}
Yet, when I build (using CMake) I get the following error:
Linking CXX executable PayloadRegionMapper
Undefined symbols for architecture x86_64:
"typeinfo for MappingTechnique", referenced from:
typeinfo for SimpleGreedyMappingTechnique in MappingTechnique.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [PayloadRegionMapper] Error 1
make[2]: *** [CMakeFiles/PayloadRegionMapper.dir/all] Error 2
make[1]: *** [CMakeFiles/PayloadRegionMapper.dir/rule] Error 2
make: *** [PayloadRegionMapper] Error 2
I don't get what's the problem here? Why can't I implement the virtual method of the superclass in the subclass? Can anyone help me out on this?
OK, I found the solution myself thanks to #Sneftel's comment noting that I didn't declare it as pure virtual nor did I give it a definition.
After googling what that means, I came up with the following options:
Giving it a definition:
struct MappingTechnique {
virtual void processFrame() {};
};
Making it pure:
struct MappingTechnique {
virtual void processFrame() = 0;
};
I decided for making it pure, only thing to take care of then is that when the abstract class is used (and it is not yet know what actual subclass it will be initialized with), you need to use:
MappingTechnique *mappingTechnique instead of MappingTechnique mappingTechnique
(which is logical when you think about it but might not be that obvious to a C++ novice). Thanks to #Sneftel!

C++ class not within scope

I have a class called Video and is defined as the following:
class Video
{
public:
Video() { }
~Video()
{
}
unsigned int m_max_ad_duration;
unsigned int m_max_skippable_duration;
unsigned int m_start_delay;
unsigned short int m_inventory_type;
unsigned short int m_skippable_Request;
};
If i have the above in a fresh file called Video.h the build works fine, however when i declare the above in an existing file containing a number of classes the build fails with errors such as
../../include/CampaignCache.h:33:56: error: ‘Video’ was not declared in this scope
../../include/CampaignCache.h:33:62: error: template argument 1 is invalid
../../include/CampaignCache.h:33:62: error: template argument 2 is invalid
../../include/CampaignCache.h:33:64: error: template argument 2 is invalid
../../include/CampaignCache.h:33:64: error: template argument 5 is invalid
../../include/CampaignCache.h:33:89: error: invalid type in declaration before ‘;’ token
../../include/CampaignCache.h:97:51: error: ‘Video’ has not been declared
make[2]: *** [BaseOpenRTBBidRequest.o] Error 1
make[2]: Leaving directory `/home/asif/RTB3.0trunk/trunk/3.0/src/bidder/ssp/OpenRTB'
make[1]: *** [OpenRTB] Error 2
make[1]: Leaving directory `/home/asif/RTB3.0trunk/trunk/3.0/src/bidder'
make: *** [compile] Error 2
Ideally i would like the Video class within the file with subclasses, can someone please explain why one causes a build error and the other doesn't?
I just simply put the video class in an independent file and all started to work fine

undefined reference to `elast_opt()' collect2: ld returned 1 exit status

I've written some oop code that use dealii library.
class elastic is defined in prelim header as:
using namespace dealii;
template <int dim>
class elastic
{
public:
elastic(const Triangulation<dim> *triang);
~elastic() ;
void run() ;
private:
.
.
.
and in another header that includes header:
template <int dim>
elastic<dim>::elastic(const Triangulation<dim> *triang): dof_handler (triangulation), fe (FE_Q<dim>(1))
{triangulation.copy_triangulation (*triang);}
and my main is written below:
#include "prelim.h"
using namespace dealii;
int main()
{
deallog.depth_console (0);
elastic<2> *elast_opt();
for ( iter=0; iter<5 ; ++iter)
elast_opt()->run();
return 0;
}
When I compile I get these errors:
....../main.cc:16: undefined reference to `elast_opt()'
collect2: ld returned 1 exit status
make: *** [main] Error 1
thanks hmjd for response .
it works just as i eliminate some parts in prelim and setup header as :
in prelim header:
public: elastic(/*const Triangulation<dim> *triang*/);
~elastic() ;
void run() ; in setup header :
elastic<dim>::elastic(/*const Triangulation<dim> *triang*/): dof_handler (triangulation),
fe (FE_Q<dim>(1))
{/*triangulation.copy_triangulation (*triang);*/}
but these parts must not be deleted and actually i want to know what's the matter with these parts.
my apology i forgot to mention that with aplying changes suggested and without eliminating beforementioned parts the error is changed to :
==============debug========= main.cc -> main.g.o main.g.o
main.cc: In function ‘int main()’:
main.cc:11:43: error: no matching function for call to ‘elastic<2>::elastic()’
main.cc:11:43: note: candidates are:
setup.h:12:3: note: elastic<dim>::elastic(const dealii::Triangulation<dim>*) [with int dim = 2]
setup.h:12:3: note: candidate expects 1 argument, 0 provided
prelim.h:38:7: note: elastic<2>::elastic(const elastic<2>&)
prelim.h:38:7: note: candidate expects 1 argument, 0 provided
make: *** [main.g.o] Error 1
s

problem with inheritance

class OGraph {
public:
OGraph() { }
virtual ~OGraph();
virtual bool is_directed()=0;
};
class OUGraph : public OGraph {
public:
OUGraph() { }
bool is_directed() { return false; }
~OUGraph() {}
};
but when I do this
OUGraph myGraph();
cout << myGraph.is_directed();
I get the following error:
Undefined symbols: "typeinfo for
OGraph", referenced from:
typeinfo for OUGraphin main.o "vtable for OGraph", referenced from:
OGraph::OGraph()in main.o mkdir -p dist/Debug/GNU-MacOSX "OGraph::~OGraph()", referenced from:
g++ -o
dist/Debug/GNU-MacOSX/opengraph
build/Debug/GNU-MacOSX/OGraph.o
build/Debug/GNU-MacOSX/main.o
OUGraph::~OUGraph()in main.o
OUGraph::~OUGraph()in main.o ld: symbol(s) not found collect2: ld
returned 1 exit status make[2]: *
[dist/Debug/GNU-MacOSX/opengraph]
Error 1 make[1]: [.build-conf]
Error 2 make: ** [.build-impl] Error
2
BUILD FAILED (exit value 2, total
time: 568ms)
This:
OUGraph myGraph();
is declaring a function called myGraph that returns a OUGraph. You need to instead have:
OUGraph myGraph;
This declares a variable, as you intend.
It's the same old thing all new C++ people fall for.
OUGraph myGraph();
You've not created a variable called myGraph, you've declared a function called myGraph that returns an OUGraph. Remove the "()".
You also apparently never defined your base's destructor anywhere. Even if it's empty you'll need to define it since you declared it in your class definition.
You have no implementation provided for virtual ~OGraph();. Either provide an implementation, specify it as pure virtual with = 0;, or just get rid of it.
The compiler is expecting to attach type info for the class to the implementation of its first virtual method. Your first virtual method is undefined, so the implementation is never generated, and you get related linking errors.
Additionally, as everyone is saying, you should remove the parentheses from your definition of myGraph.
If you're constructing a new object based using a 'default' constructor, I believe you call it without the empty parenthesis.
So, you would use OUGraph myGraph not OUGraph myGraph()