OpenThermal / libseek-thermal

SEEK thermal compact camera driver supporting the thermal Compact, thermal CompactXR and and thermal CompactPRO
MIT License
286 stars 99 forks source link

Can't Find CMAKE library. #76

Open itspalomo opened 1 year ago

itspalomo commented 1 year ago

System Information

OpenCV python version: 4.2.0 && 4.6.0 Operating System: Ubuntu Server 20.04 Platform: Raspberry Pi 4b Firmware: Nov 18 2021 16:17:39 version: d9b293558b4cef6aabedcc53c178e7604de90788 (clean) (release) (start_x) Python version: 3.8.10

Detailed description

Hello, I am using ROS to configure the libseek-thermal compact pro on a drone to publish the feed so it's usable by multiple programs. This is for my university capstone project, please forgive me if it is a silly error I am not catching. I am running into an issue where I continue to get undefined reference errors in the following code:

// Image Processing libraries
#include <opencv2/opencv.hpp> // Processing and VL
#include "seek/seek.h" // Thermal Imaging

// ROS2 Specific Libraries
#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/image.hpp"
#include "std_msgs/msg/header.hpp"
#include "cv_bridge/cv_bridge.h"

// for Size
#include <opencv2/core/types.hpp>
// for CV_8UC3
#include <opencv2/core/hal/interface.h>
// for thermal image cap
#include <opencv2/highgui/highgui.hpp>
// for compressing the image
#include <image_transport/image_transport.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <chrono>
#include <memory>
#include <stdio.h>

using namespace std::chrono_literals;

class ImagePub : public rclcpp::Node {
  public:
    ImagePub() : Node("imagepub"), count_(0) {
        visible_pub =
            this->create_publisher<sensor_msgs::msg::Image>("imagepub/visible_light", 10);
            //this->create_publisher<sensor_msgs::msg::Image>("imagepub/seek_thermal", 10);

        timer_ = this->create_wall_timer(
            100ms, std::bind(&ImagePub::timer_callback, this));
    }

  private:
    void timer_callback() {
        //Check if the cameras are working properly
        if (!vl_cam->open(0)) 
            std::cerr << "ERROR: Could not open visible light camera." << std::endl;

        cv::Mat visible_light_sensor;
        //get the frame and put it into a cv matrix
        *vl_cam >> visible_light_sensor;
        if(visible_light_sensor.empty())
            std::cerr << "Something is wrong with the webcam, could not get frame." << std::endl;

        sensor_msgs::msg::Image::SharedPtr msg = cv_bridge::CvImage(std_msgs::msg::Header(), "bgr8", visible_light_sensor).toImageMsg();

        visible_pub->publish(*msg.get());
        std::cout << "Published visible light!" << std::endl;
    }

    rclcpp::TimerBase::SharedPtr timer_;

    rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr visible_pub;
    //rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr thermal_pub;

    size_t count_;

    cv::VideoCapture *vl_cam = new cv::VideoCapture();

};

int main(int argc, char *argv[]) {

    LibSeek::SeekThermal seek;
    LibSeek::SeekCam* cam;

    printf("Starting...");
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<ImagePub>());
    rclcpp::shutdown();
    return 0;
}

More specifically, I get the following issues:

/usr/bin/ld: CMakeFiles/image_pub.dir/src/image_pub.cpp.o: in function `main':
image_pub.cpp:(.text+0x1c8): undefined reference to `LibSeek::SeekThermal::SeekThermal()'
/usr/bin/ld: CMakeFiles/image_pub.dir/src/image_pub.cpp.o: in function `LibSeek::SeekThermal::~SeekThermal()':
image_pub.cpp:(.text._ZN7LibSeek11SeekThermalD2Ev[_ZN7LibSeek11SeekThermalD5Ev]+0xc): undefined reference to `vtable for LibSeek::SeekThermal'
/usr/bin/ld: image_pub.cpp:(.text._ZN7LibSeek11SeekThermalD2Ev[_ZN7LibSeek11SeekThermalD5Ev]+0x10): undefined reference to `vtable for LibSeek::SeekThermal'
/usr/bin/ld: image_pub.cpp:(.text._ZN7LibSeek11SeekThermalD2Ev[_ZN7LibSeek11SeekThermalD5Ev]+0x24): undefined reference to `LibSeek::SeekCam::~SeekCam()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/image_pub.dir/build.make:226: image_pub] Error 1
make[1]: *** [CMakeFiles/Makefile2:78: CMakeFiles/image_pub.dir/all] Error 2
make: *** [Makefile:141: all] Error 2

I suspect this to be a CMAKE issue but am unsure what I am doing wrong... ROS uses amentcmake, and here is the CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(imaging)

# Default to C99
if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 17)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(OpenCV REQUIRED)
find_package(cv_bridge REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(std_msgs REQUIRED)
find_package(image_transport REQUIRED)
find_package(libseek REQUIRED)

add_executable(image_pub src/image_pub.cpp)

target_include_directories(image_pub PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>)
ament_target_dependencies(
  image_pub
  "rclcpp"
  "image_transport"
  "cv_bridge"
  "sensor_msgs"
  "std_msgs"
  "OpenCV"
  "libseek"
)

install(TARGETS image_pub
  DESTINATION lib/${PROJECT_NAME})

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # uncomment the line when a copyright and license is not present in all source files
  #set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # uncomment the line when this package is not in a git repo
  #set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

Running sudo make install again reinstalls the library as expected in the /usr/local/... directory. Is there a way to tell CMAKE to include them?

Install the project...
-- Install configuration: "Release"
-- Up-to-date: /usr/local/lib/libseek.so
-- Up-to-date: /usr/local/include/seek/SeekCam.h
-- Up-to-date: /usr/local/include/seek/SeekDevice.h
-- Up-to-date: /usr/local/include/seek/seek.h
-- Up-to-date: /usr/local/include/seek/SeekLogging.h
-- Up-to-date: /usr/local/include/seek/SeekThermal.h
-- Up-to-date: /usr/local/include/seek/SeekThermalPro.h

Note: testing commands via CLI as described in the readme work as expected.

Bostwickenator commented 1 year ago

Oof linker errors, never fun to debug. First thing I would sanity check here is if this is really the shared library not being found. Just delete it and see if the error changes. I think the library is being found otherwise you'd see find_package complaining not the linker.

Bostwickenator commented 1 year ago

Also if you go to the directory containing libseek.so and run objdump -T libseek.so | grep _ZN7LibSeek11SeekThermalD5Ev should show you if that function exists in the library. I'm pretty sure it doesn't. The example programs are statically linking. So I suggest to get you moving again trying that while I figure out the virtual function issues which seem to be happening here ( haven't touched c++ in a couple of years and need to reimport some knowledge ).

itspalomo commented 1 year ago

So I tried using find_library with accompanying target_linked_libraries instead of find_package and that worked. The issue seems to be that once the library is installed, it doesn't generate the CMAKE_MODULE_PATH variables which should be in the /usr/local/lib/cmake/[libname].cmake directory. Though, I am unsure as to how to do that, is there a way to just export it so find_package is able to find it? Here is the CMAKE working file:

cmake_minimum_required(VERSION 3.5)
project(imaging)

# Default to C99
if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 17)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_library(seeklib seek NAME libseek libseek-thermal lseek DOC "seek library" REQUIRED )

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(OpenCV 4.2.0 REQUIRED)
find_package(cv_bridge REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(std_msgs REQUIRED)
find_package(image_transport REQUIRED)

add_executable(image_pub src/image_pub.cpp)

target_link_libraries(image_pub ${seeklib})

target_include_directories(image_pub PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>
  )

ament_target_dependencies(
  image_pub
  "rclcpp"
  "image_transport"
  "cv_bridge"
  "sensor_msgs"
  "std_msgs"
  "OpenCV"
)

install(TARGETS image_pub
  DESTINATION lib/${PROJECT_NAME})

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # uncomment the line when a copyright and license is not present in all source files
  #set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # uncomment the line when this package is not in a git repo
  #set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

Though I find it interesting that it didn't need the path for the include directories but linked directories it did.

itspalomo commented 1 year ago

Also if you go to the directory containing libseek.so and run objdump -T libseek.so | grep _ZN7LibSeek11SeekThermalD5Ev should show you if that function exists in the library. I'm pretty sure it doesn't. The example programs are statically linking. So I suggest to get you moving again trying that while I figure out the virtual function issues which seem to be happening here ( haven't touched c++ in a couple of years and need to reimport some knowledge ).

also, running this command did not produce an output.

ubuntu@ubuntu:/usr/local/lib$ ls
cmake                       libopencv_features2d.so        libopencv_highgui.so.406      libopencv_ml.so.4.6.0         libopencv_videoio.so
libopencv_calib3d.so        libopencv_features2d.so.406    libopencv_highgui.so.4.6.0    libopencv_objdetect.so        libopencv_videoio.so.406
libopencv_calib3d.so.406    libopencv_features2d.so.4.6.0  libopencv_imgcodecs.so        libopencv_objdetect.so.406    libopencv_videoio.so.4.6.0
libopencv_calib3d.so.4.6.0  libopencv_flann.so             libopencv_imgcodecs.so.406    libopencv_objdetect.so.4.6.0  libopencv_video.so
libopencv_core.so           libopencv_flann.so.406         libopencv_imgcodecs.so.4.6.0  libopencv_photo.so            libopencv_video.so.406
libopencv_core.so.406       libopencv_flann.so.4.6.0       libopencv_imgproc.so          libopencv_photo.so.406        libopencv_video.so.4.6.0
libopencv_core.so.4.6.0     libopencv_gapi.so              libopencv_imgproc.so.406      libopencv_photo.so.4.6.0      libseek.so
libopencv_dnn.so            libopencv_gapi.so.406          libopencv_imgproc.so.4.6.0    libopencv_stitching.so        libuvc.so
libopencv_dnn.so.406        libopencv_gapi.so.4.6.0        libopencv_ml.so               libopencv_stitching.so.406    python2.7
libopencv_dnn.so.4.6.0      libopencv_highgui.so           libopencv_ml.so.406           libopencv_stitching.so.4.6.0  python3.8
ubuntu@ubuntu:/usr/local/lib$ objdump -T libseek.so | grep _ZN7LibSeek11SeekThermalD5Ev
ubuntu@ubuntu:/usr/local/lib$