PointCloudLibrary / pcl

Point Cloud Library (PCL)
https://pointclouds.org/
Other
9.85k stars 4.61k forks source link

Linker error with MedianFIlter #768

Closed sidahuja closed 10 years ago

sidahuja commented 10 years ago

I have built the latest pcl code from the trunk and tried to use the median filter and i got a linker error for some reason. The log is attached for your reference.

$ make VERBOSE=1 /usr/bin/cmake -H/home/sid-pcl/code/cpp -B/home/sid-pcl/code/cpp/build --check-build-system CMakeFiles/Makefile.cmake 0 /usr/bin/cmake -E cmake_progress_start /home/sid-pcl/code/cpp/build/CMakeFiles /home/sid-pcl/code/cpp/build/CMakeFiles/progress.marks make -f CMakeFiles/Makefile2 all make[1]: Entering directory /home/sid-pcl/code/cpp/build' make -f CMakeFiles/filter_scans.dir/build.make CMakeFiles/filter_scans.dir/depend make[2]: Entering directory/home/sid-pcl/code/cpp/build' cd /home/sid-pcl/code/cpp/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/sid-pcl/code/cpp /home/sid-pcl/code/cpp /home/sid-pcl/code/cpp/build /home/sid-pcl/code/cpp/build /home/sid-pcl/code/cpp/build/CMakeFiles/filter_scans.dir/DependInfo.cmake --color= make[2]: Leaving directory /home/sid-pcl/code/cpp/build' make -f CMakeFiles/filter_scans.dir/build.make CMakeFiles/filter_scans.dir/build make[2]: Entering directory/home/sid-pcl/code/cpp/build' Linking CXX executable ../bin/filter_scans /usr/bin/cmake -E cmake_link_script CMakeFiles/filter_scans.dir/link.txt --verbose=1 /usr/bin/c++ -Wno-deprecated CMakeFiles/filter_scans.dir/src/filter_scans.cpp.o -o ../bin/filter_scans -L/usr/local/lib -rdynamic -lboost_system-mt -lboost_filesystem-mt -lboost_thread-mt -lpthread -lboost_date_time-mt -lboost_iostreams-mt -lboost_mpi-mt -lboost_serialization-mt -lboost_chrono-mt /usr/local/lib/libpcl_common.so /usr/local/lib/libpcl_octree.so -lOpenNI /usr/lib/libvtkCommon.so.5.8.0 /usr/lib/libvtkFiltering.so.5.8.0 /usr/lib/libvtkImaging.so.5.8.0 /usr/lib/libvtkGraphics.so.5.8.0 /usr/lib/libvtkGenericFiltering.so.5.8.0 /usr/lib/libvtkIO.so.5.8.0 /usr/lib/libvtkRendering.so.5.8.0 /usr/lib/libvtkVolumeRendering.so.5.8.0 /usr/lib/libvtkHybrid.so.5.8.0 /usr/lib/libvtkWidgets.so.5.8.0 /usr/lib/libvtkParallel.so.5.8.0 /usr/lib/libvtkInfovis.so.5.8.0 /usr/lib/libvtkGeovis.so.5.8.0 /usr/lib/libvtkViews.so.5.8.0 /usr/lib/libvtkCharts.so.5.8.0 /usr/local/lib/libpcl_io.so -Wl,-Bstatic -lflann_cpp_s -Wl,-Bdynamic /usr/local/lib/libpcl_kdtree.so /usr/local/lib/libpcl_search.so /usr/local/lib/libpcl_sample_consensus.so /usr/local/lib/libpcl_filters.so /usr/local/lib/libpcl_features.so /usr/local/lib/libpcl_keypoints.so -lqhull /usr/local/lib/libpcl_surface.so /usr/local/lib/libpcl_registration.so /usr/local/lib/libpcl_ml.so /usr/local/lib/libpcl_segmentation.so /usr/local/lib/libpcl_recognition.so /usr/local/lib/libpcl_visualization.so /usr/local/lib/libpcl_people.so /usr/local/lib/libpcl_outofcore.so /usr/local/lib/libpcl_stereo.so /usr/local/lib/libpcl_tracking.so /usr/local/lib/libpcl_apps.so /usr/local/lib/libpcl_3d_rec_framework.so -lboost_system-mt -lboost_filesystem-mt -lboost_thread-mt -lpthread -lboost_date_time-mt -lboost_iostreams-mt -lboost_mpi-mt -lboost_serialization-mt -lboost_chrono-mt -lqhull -lOpenNI -Wl,-Bstatic -lflann_cpp_s -Wl,-Bdynamic /usr/lib/libvtkCommon.so.5.8.0 /usr/lib/libvtkFiltering.so.5.8.0 /usr/lib/libvtkImaging.so.5.8.0 /usr/lib/libvtkGraphics.so.5.8.0 /usr/lib/libvtkGenericFiltering.so.5.8.0 /usr/lib/libvtkIO.so.5.8.0 /usr/lib/libvtkRendering.so.5.8.0 /usr/lib/libvtkVolumeRendering.so.5.8.0 /usr/lib/libvtkHybrid.so.5.8.0 /usr/lib/libvtkWidgets.so.5.8.0 /usr/lib/libvtkParallel.so.5.8.0 /usr/lib/libvtkInfovis.so.5.8.0 /usr/lib/libvtkGeovis.so.5.8.0 /usr/lib/libvtkViews.so.5.8.0 /usr/lib/libvtkCharts.so.5.8.0 /opt/ros/hydro/lib/libopencv_calib3d.so /opt/ros/hydro/lib/libopencv_contrib.so /opt/ros/hydro/lib/libopencv_core.so /opt/ros/hydro/lib/libopencv_features2d.so /opt/ros/hydro/lib/libopencv_flann.so /opt/ros/hydro/lib/libopencv_gpu.so /opt/ros/hydro/lib/libopencv_highgui.so /opt/ros/hydro/lib/libopencv_imgproc.so /opt/ros/hydro/lib/libopencv_legacy.so /opt/ros/hydro/lib/libopencv_ml.so /opt/ros/hydro/lib/libopencv_nonfree.so /opt/ros/hydro/lib/libopencv_objdetect.so /opt/ros/hydro/lib/libopencv_photo.so /opt/ros/hydro/lib/libopencv_stitching.so /opt/ros/hydro/lib/libopencv_superres.so /opt/ros/hydro/lib/libopencv_ts.so /opt/ros/hydro/lib/libopencv_video.so /opt/ros/hydro/lib/libopencv_videostab.so /usr/local/lib/libpcl_common.so /usr/local/lib/libpcl_octree.so /usr/local/lib/libpcl_io.so /usr/local/lib/libpcl_kdtree.so /usr/local/lib/libpcl_search.so /usr/local/lib/libpcl_sample_consensus.so /usr/local/lib/libpcl_filters.so /usr/local/lib/libpcl_features.so /usr/local/lib/libpcl_keypoints.so /usr/local/lib/libpcl_surface.so /usr/local/lib/libpcl_registration.so /usr/local/lib/libpcl_ml.so /usr/local/lib/libpcl_segmentation.so /usr/local/lib/libpcl_recognition.so /usr/local/lib/libpcl_visualization.so /usr/local/lib/libpcl_people.so /usr/local/lib/libpcl_outofcore.so /usr/local/lib/libpcl_stereo.so /usr/local/lib/libpcl_tracking.so /usr/local/lib/libpcl_apps.so /usr/local/lib/libpcl_3d_rec_framework.so /opt/ros/hydro/lib/libopencv_calib3d.so /opt/ros/hydro/lib/libopencv_contrib.so /opt/ros/hydro/lib/libopencv_core.so /opt/ros/hydro/lib/libopencv_features2d.so /opt/ros/hydro/lib/libopencv_flann.so /opt/ros/hydro/lib/libopencv_gpu.so /opt/ros/hydro/lib/libopencv_highgui.so /opt/ros/hydro/lib/libopencv_imgproc.so /opt/ros/hydro/lib/libopencv_legacy.so /opt/ros/hydro/lib/libopencv_ml.so /opt/ros/hydro/lib/libopencv_nonfree.so /opt/ros/hydro/lib/libopencv_objdetect.so /opt/ros/hydro/lib/libopencv_photo.so /opt/ros/hydro/lib/libopencv_stitching.so /opt/ros/hydro/lib/libopencv_superres.so /opt/ros/hydro/lib/libopencv_ts.so /opt/ros/hydro/lib/libopencv_video.so /opt/ros/hydro/lib/libopencv_videostab.so /usr/lib/libvtkViews.so.5.8.0 /usr/lib/libvtkInfovis.so.5.8.0 /usr/lib/libvtkWidgets.so.5.8.0 /usr/lib/libvtkVolumeRendering.so.5.8.0 /usr/lib/libvtkHybrid.so.5.8.0 /usr/lib/libvtkParallel.so.5.8.0 /usr/lib/libvtkRendering.so.5.8.0 /usr/lib/libvtkImaging.so.5.8.0 /usr/lib/libvtkGraphics.so.5.8.0 /usr/lib/libvtkIO.so.5.8.0 /usr/lib/libvtkFiltering.so.5.8.0 /usr/lib/libvtkCommon.so.5.8.0 -lm /usr/lib/libvtksys.so.5.8.0 -ldl -Wl,-rpath,/usr/local/lib:/opt/ros/hydro/lib:/usr/lib/openmpi/lib -Wl,-rpath-link,/usr/lib/openmpi/lib CMakeFiles/filter_scans.dir/src/filter_scans.cpp.o:(.rodata._ZTVN3pcl12MedianFilterINS_9PointXYZIEEE[_ZTVN3pcl12MedianFilterINS_9PointXYZIEEE]+0x24): undefined reference to pcl::MedianFilter<pcl::PointXYZI>::applyFilter(pcl::PointCloud<pcl::PointXYZI>&)' collect2: error: ld returned 1 exit status make[2]: *** [../bin/filter_scans] Error 1 make[2]: Leaving directory/home/sid-pcl/code/cpp/build' make[1]: * [CMakeFiles/filter_scans.dir/all] Error 2 make[1]: Leaving directory `/home/sid-pcl/code/cpp/build' make: * [all] Error 2

Here is the source file for median filtering:

include

include <pcl/io/pcd_io.h>

include <pcl/point_types.h>

include <pcl/filters/statistical_outlier_removal.h>

include <pcl/filters/conditional_removal.h>

include <pcl/common/time.h>

include <pcl/console/parse.h>

include <pcl/visualization/pcl_visualizer.h>

include <pcl/ModelCoefficients.h>

include <pcl/filters/project_inliers.h>

include <pcl/filters/median_filter.h>

// Global Variables bool save_output = false; bool show_input = false; bool show_output = false;

void printUsage (const char* progName) { std::cout << "\n\nUsage: "<<progName<<" [options] \n\n" << "Options:\n" << "-------------------------------------------\n" << "-save_output \t\twant to save the output as a pcd cloud?\t(default "<<save_output<<")\n" << "-show_input \t\tshow the input pcd cloud?\t(default "<<show_input<<")\n" << "-show_output \t\tshow the output pcd cloud?\t(default "<<show_output<<")\n" << "-h\t \tthis help\n" << "\n\n"; }

///////////////////////////////////// // Open 3D viewer and add point cloud ///////////////////////////////////// boost::shared_ptrpcl::visualization::PCLVisualizer View1 (pcl::PointCloudpcl::PointXYZI::ConstPtr cloud) { boost::shared_ptrpcl::visualization::PCLVisualizer viewer (new pcl::visualization::PCLVisualizer ("3D Viewer")); viewer->setBackgroundColor (0, 0, 0); pcl::visualization::PointCloudColorHandlerGenericFieldpcl::PointXYZI handler(cloud,"intensity"); viewer->addPointCloudpcl::PointXYZI (cloud, handler, "input cloud"); viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "input cloud"); viewer->initCameraParameters (); return (viewer); }

///////////////////////////////////////////////////// // Open 3D viewer with two views and add point clouds ///////////////////////////////////////////////////// boost::shared_ptrpcl::visualization::PCLVisualizer View2 (pcl::PointCloudpcl::PointXYZI::ConstPtr cloud1, pcl::PointCloudpcl::PointXYZI::ConstPtr cloud2) { boost::shared_ptrpcl::visualization::PCLVisualizer viewer (new pcl::visualization::PCLVisualizer ("3D Viewer")); viewer->initCameraParameters (); pcl::visualization::PointCloudColorHandlerGenericFieldpcl::PointXYZI handler(cloud1,"intensity"); pcl::visualization::PointCloudColorHandlerGenericFieldpcl::PointXYZI handler1(cloud2,"intensity");

int v1(0); viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1); viewer->setBackgroundColor (0, 0, 0, v1); viewer->addText("Input Cloud", 10, 10, "v1 text", v1); viewer->addPointCloudpcl::PointXYZI (cloud1, handler,"input_cloud", v1);

int v2(0); viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2); viewer->setBackgroundColor (0.3, 0.3, 0.3, v2); viewer->addText("Output Cloud", 10, 10, "v2 text", v2); viewer->addPointCloudpcl::PointXYZI (cloud2, handler1, "output_cloud", v2);

viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "input_cloud"); viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "output_cloud");

return (viewer); }

int main (int argc, char\ argv) {
pcl::PointCloudpcl::PointXYZI::Ptr point_cloud_ptr (new pcl::PointCloudpcl::PointXYZI); pcl::PointCloudpcl::PointXYZI::Ptr point_cloud2_ptr (new pcl::PointCloudpcl::PointXYZI);

// Parse command line arguments
if (pcl::console::find_argument (argc, argv, "-h") >= 0)
{
    printUsage (argv[0]);
    return 0;
}
if (pcl::console::parse (argc, argv, "-save_output", save_output) >=0)
{
    std::cout << "Setting option to save output cloud to : " << save_output << std::endl ;
}
if (pcl::console::parse (argc, argv, "-show_input", show_input) >=0)
{
    std::cout << "Setting option to show input cloud to : " << show_input << std::endl ;
}
if (pcl::console::parse (argc, argv, "-show_output", show_output) >=0)
{
    std::cout << "Setting option to show output cloud to : " << show_output << std::endl ;
}

std::vector<int> pcd_filename_indices = pcl::console::parse_file_extension_argument (argc, argv, "pcd");
if (pcd_filename_indices.empty ()) 
{
    printUsage (argv[0]);
    return 0;
}
else 
{
    // Read file .pcd
    std::string filename = argv[pcd_filename_indices[0]];
    if (pcl::io::loadPCDFile (filename, *point_cloud_ptr) == -1) 
    {
       std::cout << "Was not able to open file \""<<filename<<"\".\n";
       printUsage (argv[0]);
       return 0;
    }
}

//----------------------------------------------------
// Median Filter the point cloud
//----------------------------------------------------
std::cout << "Median filter removal" << std::endl;

pcl::MedianFilterpcl::PointXYZI mf; mf.setInputCloud (point_cloud_ptr); mf.setWindowSize (5); mf.filter (*point_cloud2_ptr);

//----------------------------------------------------
// Visualize point clouds
//----------------------------------------------------
if(show_input)
{
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
    if(show_output)
    {
        viewer = View2(point_cloud_ptr, point_cloud2_ptr);
    }
    else
    {
        viewer = View1(point_cloud_ptr);
    }
    //----------------------------------------------------
    // Main loop
    //----------------------------------------------------
    while (!viewer->wasStopped ()) 
    {
        viewer->spinOnce (100);
        boost::this_thread::sleep (boost::posix_time::microseconds (100000));
    }
}

return (0); }

Here is the CMAKELists.txt

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

set(PCL_DIR "/usr/share/pcl-1.7/PCLConfig.cmake") find_package(PCL 1.7) find_package( OpenCV ) include_directories(${PCL_INCLUDE_DIRS} include) link_directories(${PCL_LIBRARY_DIRS}) add_definitions(${PCL_DEFINITIONS})

Set Output Directories.

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)

function(my_add_executable TargetName) set(Files ${ARGV}) list(REMOVE_AT Files 0) add_executable(${TargetName} ${Files}) target_link_libraries (${TargetName} ${PCL_LIBRARIES} ${OpenCV_LIBS}) endfunction()

my_add_executable(filter_scans src/filter_scans.cpp)

taketwo commented 10 years ago

Hi. This is a bug tracker, not a support forum. Questions like this should be asked on the users mailing list. Also, please use Markdown code fences when pasting large chunks of code/program output.

That being said, the problem is that the filter in question is not precompiled for the type of point you want to use. I think you need to add #include <pcl/filters/impl/median_filter.hpp>. @rbrusu @jspricke please correct me if this is not the right way to use a PCL class with a point type for which it was not precompiled.

taketwo commented 10 years ago

Let me be more precise in terminology. By precompilation I mean explicit template instantiation during compilation of PCL. This instantiation is triggered in the corresponding .cpp file. Here you can see that PointXYZI is not in the list. This means that if you want to use the filter in your code with this specific point type, the compiler will need to instantiate it for you. In order to do that, it needs the definition of template to be available. The definition (do not confuse with declaration) is contained in the .hpp file. That is why I suggested to include it.

if the desired functionality is not pre-compiled for the point type i am using, then i would consider it a bug

We can not precompile for every point type, there are way too many of them. The library compilation time and the size of the produced .so (or .lib on Windows) files will be enormous.

sidahuja commented 10 years ago

Alright. Thanks for that! It worked after adding that additional header file to the code. I would advise making it more generic and not have to rely on any specific point type. I am not sure how you would go about it. If it is not possible to do so, there needs to be a clear documentation suggesting what point types are supported and what needs to be done in order to solve the problem should it arise for other people.