使用过ROS2的人,都需要写 CMakeLists.txt 文件.
我记录一下我的历程, 以后备查.
1 引入包
我希望一劳永逸, 所以, 在 find_package(ament_cmake REQUIRED) 的下面这么写:
# 导入Ros2 和项目库
set(ros2_dependencies
# geometry_msgs
# laser_geometry
# map_msgs
# message_filters
# nav2_msgs
# nav2_util
# nav2_voxel_grid
# nav_msgs
# pluginlib
rclcpp
# rclcpp_lifecycle
# sensor_msgs
# std_msgs
# std_srvs
# tf2
# tf2_geometry_msgs
# tf2_ros
# tf2_sensor_msgs
# visualization_msgs
# angles
)
foreach(dep ${ros2_dependencies})
find_package(${dep} REQUIRED)
endforeach()
# 导入非ROS2的第三方库
set(thd_dependencies
OpenCV
)
foreach(dep ${thd_dependencies})
find_package(${dep} REQUIRED)
include_directories(
${${dep}_INCLUDE_DIRS}
)
endforeach()
需要引入哪个包就取消注释. 后面不论是库还是执行程序, 都是相同一句:
ament_target_dependencies([targe_name] ${ros2_dependencies} ${thd_dependencies})
好了, 包引入的问题解决了.
当然, package.xml 也同样需要加入引用.
<depend>rclcpp</depend>
这里不影响单一包的编译, 但会影响编译的顺序.
2, 构建一个库, 可以其他包使用
add_library([lib_name] SHARED
src/[源文件]
)
target_include_directories([lib_name]
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
set_target_properties([lib_name] PROPERTIES
SOVERSION 1
VERSION 0.1.0
)
ament_target_dependencies([lib_name] ${ros2_dependencies} ${thd_dependencies})
# 链接本包内的库
target_link_libraries([app_name] [lib_name])
ament_export_include_directories(include)
install(DIRECTORY include/
DESTINATION include/
)
ament_export_libraries([lib_name])
install(TARGETS [lib_name]
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
请把上面的 [lib_name] 替换目标名称. 这一套下来, 一个库就搞定了. 只要在其他包中 CMakeLists.txt 的把你的包名加到第一项的 ros2_dependencies 定义中, 其他包就可以使用这个库了.
如果在同一包中, 要使用这个库, 则需要
# 链接本包内的库
target_link_libraries([app_name] [lib_name])
3, 构建一个应用
add_executable([app_name] src/[源文件])
target_include_directories([app_name] PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
ament_target_dependencies([app_name] ${ros2_dependencies} ${thd_dependencies})
# 链接本包内的库
target_link_libraries([app_name] [lib_name])
install(TARGETS
[app_name]
DESTINATION lib/${PROJECT_NAME}
)
3. 构建一个ROS2的消息,服务,Action 等.
按照文档, 很好配置
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/xxxxx.msg"
"srv/xxxxx.srv"
"action/xxxx.action"
)
ament_export_dependencies(rosidl_default_runtime)
然后在 package.xml 文件中
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
好了,如果这个时候, 我需要使用定义在同一个包中的msg, srv, action, 怎么办, 要加上:
# 使用本包内的自定义消息接口
rosidl_get_typesupport_target(cpp_typesupport_target ${PROJECT_NAME} rosidl_typesupport_cpp)
target_link_libraries([app_name] "${cpp_typesupport_target}")
否则你编译不过去.
就这么简单. 清爽吧. 这些设置的组合使用, 就可以完成整个 ROS2 项目的构建工程配置了.