0
$\begingroup$

Rosanswers logo

I've been banging my head against my keyboard for the last week or so trying to figure this one out and still havent - so here I am asking for help from the internet!

I have this package I've been porting from ROS1 to ROS2, lets call it lidar_driver. There is a provided SDK via a static lib (.a) file that I link to in the CMakeList file and use some additional header files as well from this SDK.

For ROS1 I use the normal find_package() , specify the path to the static lib and can link to it just fine and run the ROS1 node. This all works as expected and overall a very pleasant experience in ROS1.

Now when I try to migrate over to ROS2, still using find_package() and specifying the path I still can find it (_FOUND CMake variable is 1) and all the other CMake variables needed are set and look great. I am using ament_auto_add_library to create the library with the node so all my depends in my package.xml are accounted for, and also creating a ROS2 component via rclcpp_components_register_node.

This all compiles fine using colcon build, but when I try and run the node using ros2 run it executes up until I use the cpp object provided by the static lib like so shared_ptr.reset(new sdk::Lidar())

So my question is what step am I missing thats different between catkin and ament/colcon to link to a static lib?

Any help or advice would be greatly appreciated!

UPDATE3: thank you to @404RobotNotFound for the tips, I ended up using gdb to debug the problem and finally got an error to print out! After following the answer here on how to run gdb for a ros2 node I was able to see this error printing out:

Thread 1 "some_node" received signal SIGSEGV, Segmentation fault.

and it went on to print out in what exact function the error was occuring. It was happening inside the StaticLib, so that means we are successfully linking to it, just maybe missing some dependency for it somehow. I will dig into this with the library provider and see what we can come up with. thanks again so much for the support digging into this problem.

UPDATE2: the StaticLib does use some UDP functions to open a UDP socket for receiving/sending....I wonder if that is interferring with something ROS2 has already open while doing its underlying DDS stuff...? Going to ask the provider of the SDK what exactly is going on there.

UPDATE: here is the basic CMakeList file that is causing me issues in ROS2:

 cmake_minimum_required(VERSION 3.5.2)
 project(some_driver)
 
 # Default to C++14
 if(NOT CMAKE_CXX_STANDARD)
   set(CMAKE_CXX_STANDARD 14)
 endif()
 
 if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
   add_compile_options(-Wall -Wextra -Wpedantic)
 endif()
 
 find_package(ament_cmake_auto REQUIRED)
 ament_auto_find_build_dependencies()
 
 unset(STATIC_LIB_DEV)
 
 find_package(StaticLib
   PATHS ${CMAKE_CURRENT_SOURCE_DIR}/StaticLib/Apps/sdk/lib/cmake/libStaticLib
   REQUIRED)
 
 get_target_property(StaticLib_INCLUDE_DIRS
     StaticLib INTERFACE_INCLUDE_DIRECTORIES)
 get_target_property(StaticLib_LIB_DIRS
     StaticLib INTERFACE_LIBRARY_DIRECTORIES)
 get_target_property(StaticLib_LINK_LIBRARIES
     StaticLib INTERFACE_LINK_LIBRARIES)
 get_target_property(StaticLib_STATIC_LIB
     StaticLib IMPORTED_LOCATION_RELEASE)
 
 message(STATUS ${StaticLib_FOUND})
 message(STATUS ${StaticLib_INCLUDE_DIRS})
 message(STATUS ${StaticLib_LIB_DIRS})
 message(STATUS ${StaticLib_LINK_LIBRARIES})
 message(STATUS ${StaticLib_STATIC_LIB})
 
 set(BUILD_SHARED_LIBS True)
 
 ament_auto_add_library(${PROJECT_NAME} SHARED
   src/some_node.cpp
 )
 
 ament_export_dependencies(StaticLib)
 
 target_include_directories(${PROJECT_NAME}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include 
   ${StaticLib_INCLUDE_DIRS}
 )
 
 target_link_libraries(${PROJECT_NAME}
   StaticLib
 )
 
 if(WIN32)
   target_compile_definitions(${PROJECT_NAME} PUBLIC "SOME_DRIVER_BUILDING_DLL")
 endif(WIN32)
 
 rclcpp_components_register_node(${PROJECT_NAME}
   PLUGIN "drivers::some_driver::SomeNode"
   EXECUTABLE some_node
 )
 
 install(DIRECTORY ${StaticLib_INCLUDE_DIRS}/
   DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}
 )
 
 install(
   FILES ${StaticLib_STATIC_LIB}
   TYPE LIB
 )
 
 ament_auto_package(
   INSTALL_TO_SHARE
     launch
     params
 )

Originally posted by flynneva on ROS Answers with karma: 191 on 2021-06-23

Post score: 0


Original comments

Comment by 404RobotNotFound on 2021-06-23:
Is there a specific error you are seeing when your code tries to reset the shared pointer? That might help in identifying the problem.

On a separate note, by default in ROS 1 libraries were built as shared libraries (.so files in linux), but in ROS 2 you need to specify them or they build as static libraries (.a files). You need to pass in "SHARED" to the ament_auto_add_library call to make it a shared library again.

Also, in ROS 2, you have to install build artifacts to generally be able to use them, see the ament cmake documentation for building a library on the correct way to install the library and export the library target correctly.

Comment by flynneva on 2021-06-25:
none what-so-ever...thats the frustrating bit. it just crashes. i am already using SHARED in my ament_auto_add_library step....so thats not it. and as far as installing properly goes, my understanding of ament_auto is that it does all the installation for you, automatically. i might be wrong though?

im leaning more towards the static lib that im trying to use isnt added as a runtime dependency somehow. do you know how to add that in so ament can know to install that too?

Comment by 404RobotNotFound on 2021-06-25:
Without looking at the CMakeList file it would be hard to guess, but another problem could be that ament_auto_add_library only calls target_link_libraries("${target}" ${${PROJECT_NAME}_LIBRARIES}) and nothing that would be external would be caught with that. After calling the auto_add_library, you might need to also call target_link_libraries(<LIB_TARGET> ${<external_pkg>_LIBRARIES}) assuming it is exported correctly from that package. How was it built in ROS 1?

Comment by flynneva on 2021-06-25:
@404RobotNotFound thanks so much for your help with this! I think ive done both of those as well - to help ive added the problem CMakeList file. the same find_package approach as above works for ROS1....but for some reason doesnt work for ROS2 and ament.

Comment by 404RobotNotFound on 2021-06-29:
As another follow up, when it crashes do you get some kind of stacktrace or anything?

Comment by flynneva on 2021-06-29:
there is nothing printed out in the console and ive added prints just before and after the shared_ptr.reset call so i know it is that line.

ive checked also the $HOME/.ros/log file generated but its absolutely empty (nothing in them).

any tips on how to turn on some sort of "debug mode"?

Comment by 404RobotNotFound on 2021-06-29:
So if your node is closing unexpectedly, there should at least be something like a "Segmentation Fault" or "process has died, exit code [some code]". However, in either case looking at logs probably won't capture that info.

For turning on some debug mode, you can add debug symbols with adding --cmake-args -DCMAKE_BUILD_TYPE=Debug or --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo I believe both work (I usually use RelWithDebInfo). However, this is really useful when debugging a code dump, which is something you can do with GDB to track down what call is having the issue. However, you already know what line is having the issue. So I am not sure if it is a problem with finding the library in the first place, or maybe some kind of error happening when you create the object - that is something GDB could probably tell you was the case by following the stack trace.

Comment by flynneva on 2021-06-30:
@404RobotNotFound thanks for the tips on gdb! I updated the question with some updates...but also posting this here for anyone else that ends up here: to run gdb for a ros2 node:

https://answers.ros.org/question/267261/how-can-i-run-ros2-nodes-in-a-debugger-eg-gdb/

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

Instead of

target_link_libraries(${PROJECT_NAME}
   StaticLib
 )

try

target_link_libraries(${PROJECT_NAME}
   ${StaticLib_LIBRARIES}
 )

Another option if that doesn't work is check the variable ${${PROJECT_NAME}_FOUND_BUILD_DEPENDS} before / after the ament_auto_add_library call.

If StaticLib is not in there, you might be able to add ament_target_dependencies(${PROJECT_NAME} StaticLib)

Edit:

It seems like you have found your answer for the time being, which was you were successfully linking to it but there might be some missing dependency inside of the library when the object is created.

Out of curiosity, are you building this library and can look at the code or just received a static library to use and did not build it?


Originally posted by 404RobotNotFound with karma: 331 on 2021-06-25

This answer was NOT ACCEPTED on the original site

Post score: 1


Original comments

Comment by flynneva on 2021-06-29:
so yeah I tried the ${StaticLib_LIBRARIES} but that variable is empty...probably not set by the FindStaticLib cmake script. whats tough is this static lib is 3rd party so I cant change it really.

the output of message(STATUS ${${PROJECT_NAME}_FOUND_BUILD_DEPENDS}) shows the library that im looking for....so that means cmake found it, right?

StaticLibrclcpprclcpp_componentsstd_msgssensor_msgscv_bridgecamera_info_managerimage_transport

Comment by flynneva on 2021-06-29:
the weird thing to me is that this approach works for ROS1 but not ROS2. so the find_package and target_link_libraries as I show above works perfectly fine for ROS1.....but not for ROS2. I dont understand what the difference is here.

Comment by 404RobotNotFound on 2021-06-29:
What does the message(STATUS ${StaticLib_STATIC_LIB}) output?

Comment by flynneva on 2021-06-29:
the full path to the lib with the static lib filename, ive tried to put that into target_link_libraries as well...same story.

Comment by flynneva on 2021-06-30:
@404RobotNotFound to answer your edit, I do not have access to the staticlib source - just receive it prebuilt to use and i did not build it.

$\endgroup$
0
$\begingroup$

Rosanswers logo

to update everyone - the StaticLib was compiled using C++ 11 and does not support C++ 14 (ROS2 default) just yet. by changing the CMAKE_CXX_STANDARD variable to 11 I was able to compile and run successfully the node.

# Default to C++14 for ROS2
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 11)  #  changed this to 11
endif()

thanks so much @404RobotNotFound for the help with debugging this problem!


Originally posted by flynneva with karma: 191 on 2021-07-01

This answer was ACCEPTED on the original site

Post score: 1

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.