这里我们以ndt_omp库为例来讲解ROS2工程如何引用第三方库。
我们自己的库是slam_lib_3d, 这个库是一个标准的ROS2库,slam_lib_3d内部会使用到ndt_omp,因此,我们需要将ndt_omp引入slam_lib_3d中,使得slam_lib_3d能够使用ndt_omp中的符号以及找到对应的头文件。
step1
首先我们需要编辑slam_lib_3d的package.xml,重要的就下面这一句:
<build_depend> ndt_omp </build_depend>
它将告诉colcon编译器slam_lib_3d的编译需要依赖ndt_omp,这样colcon将先编译ndt_omp,然后再编译slam_lib_3d。
如果没有这句话那么会出现:
slam_lib_3d的CMakeLists.txt的find_package(ndt_omp REQUIRED)将执行失败。
step2
接着编辑CMakeLists.txt, 对于非ROS的第三方库,采用普通的cmake方法去引用,比如slam_lib_3d需要用到pcl、ceres、tbb等非ros第三方库,那么使用下述方法:
find_package(Ceres REQUIRED)
find_package(PCL 1.7 REQUIRED)
find_package(TBB REQUIRED)
add_library(slam_pointcloud SHARED
${pointcloud_src}
)
target_include_directories(slam_pointcloud PUBLIC
include
${PCL_INCLUDE_DIRS}
${CERES_INCLUDE_DIRS}
${TBB_INCLUDE_DIRS}
)
target_link_libraries(slam_pointcloud PUBLIC
${PCL_LIBRARIES}
${CERES_LIBRARIES}
${TBB_LIBRARIES}
)
对于ROS第三方库,ament_cmake提供了更加方便的办法,比如ndt_omp是一个ROS2库,那么我们加入下面代码:
find_package(ndt_omp REQUIRED)
ament_target_dependencies(slam_pointcloud PUBLIC ndt_omp)
这里ament_target_dependencies是关键,对于任何可以成功执行find_package的第三方ROS2库(并不是随便一个ROS2包都可以在其他ROS2包中成功执行find_package,这也需要满足一定的CMakeLists.txt规则,稍后探讨这个问题),ament_target_dependencies就相当于执行了:
target_include_directories()
target_link_libraries()
到这里如何在一个ROS2包中引入其他第三方库的方法就介绍完毕了,是不是很简单? 下面总结一下:
1、对于非ROS第三方库,如果支持find_package, 那么使用常规的方法引入。
2、对于ROS第三方库,则使用ament_target_dependencies,不过我们需要让这个ROS库支持find_package。
那么显然就出现了一个关键问题,如何让一个ROS包支持find_package呢? 下面我们来探讨这个问题。
2、让一个ROS2包支持find_package
在CMakeLists.txt中通过下面两行代码就能让ROS2包支持find_package-
find_package(ament_cmake REQUIRED)
...
ament_package()
因为这两行代码将在colcon build编译时在生成workspace/install/ndt_omp/share/ndt_omp/cmake/ndt_ompConfig.cmake文件,熟悉cmake的朋友都知道,find_package的搜索目标之一就是这个文件。
那么是不是这就够了呢? 并不是,还需要执行两个命令-ament_export_libraries和ament_export_include_directories。
ament_export_include_directories的作用是在ros_workspace/install/ndt_omp/share/ndt_omp/cmake中生成ament_cmake_export_include_directories-extras.cmake。
ament_cmake_export_include_directories-extras.cmake将被ndt_ompConfig.cmake调用,并生成ndt_omp_INCLUDE_DIRS,这样执行ament_target_dependencies后就能找到库的头文件目录,假如没有ament_export_include_directories(include)那么编译就会报错:
ament_export_libraries
这个命令将生成ament_cmake_export_libraries-extras.cmake,类似的,这个文件里将创建 ndt_omp_LIBRARIES,如果没有执行这个命令编译时将出现找不到定义的错误。
另外,ament_export_libraries和ament_export_include_directories需要和install命令联用,因为ament_export_include_directories(include) 这里面的include是install里的include(解析出来是/code/robot_ws/install/slam_lib_3d/include),因此我们 需要将include目录给安装到install目录下。