从上周搞定ROS工程下使用Protbuf的问题后,陆续对原有工程进行了更改,在这一过程中,探索了下Protobuf与ROS工程结合的不同方式,暂时总结了一份模板,并在此记录下心得。
1. 使用 Proto 的 ROS 节点
在这贴下个人使用的范例:
1 2 3 4 5 6 7 8 9 10 11 . ├── CMakeLists.txt ├── include │ └── map │ ├── map.cpp │ └── map.h ├── package.xml ├── proto │ └── map.proto └── src └── map_node.cpp
个人在尝试不同的组织结构的过程中,也试过把proto文件单独设置一个节点,后续节点只需要添加即可,不需要都更改CmakeLists.txt文件。但对比Apollo工程发现,这样做会使工程目录不够清晰,不能直观地看到工程中是否引用了proto文件。再三考虑后还是决定每个节点单独设置proto文件夹来存在proto文件,这样更清晰直观。
2. CmakeLists.txt模板
目前最终效果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 cmake_minimum_required (VERSION 2.8 .3 )project (map)find_package (catkin REQUIRED COMPONENTS roscpp std_msgs ) list (APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR} /cmake)include (FindProtobuf)find_package (Protobuf REQUIRED)set (proto_dir ${PROJECT_SOURCE_DIR} /proto)file (GLOB proto_files "${proto_dir}/*.proto" )catkin_destinations() set (proto_gen_dir ${CATKIN_DEVEL_PREFIX} /${CATKIN_GLOBAL_INCLUDE_DESTINATION} /${PROJECT_NAME} )set (proto_gen_cpp_dir ${proto_gen_dir} )file (MAKE_DIRECTORY ${proto_gen_dir} )file (MAKE_DIRECTORY ${proto_gen_cpp_dir} )set (protogen_include_dirs ${proto_gen_cpp_dir} /../ ${proto_gen_python_dir} )set (proto_gen_cpp_files "" )foreach (proto_file ${proto_files} ) get_filename_component (proto_name ${proto_file} NAME_WE) list (APPEND proto_gen_cpp_files ${proto_gen_cpp_dir} /${proto_name} .pb.h ${proto_gen_cpp_dir} /${proto_name} .pb.cc ) endforeach (proto_file ${proto_files} ) add_custom_command ( OUTPUT ${proto_gen_cpp_files} COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --proto_path=${proto_dir} --cpp_out=${proto_gen_cpp_dir} ${proto_files} DEPENDS ${PROTOBUF_PROTOC_EXECUTABLE} ${proto_files} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) set_source_files_properties (${proto_gen_cpp_files} PROPERTIES GENERATED TRUE )add_custom_target (${PROJECT_NAME} _generate_headers DEPENDS ${proto_gen_cpp_files} ) include_directories (${PROTOBUF_INCLUDE_DIR} ${PROTOBUF_INCLUDE_DIR} /../../)add_library (${PROJECT_NAME} _proto ${proto_gen_cpp_files} )target_link_libraries (${PROJECT_NAME} _proto ${PROTOBUF_LIBRARY} )add_dependencies (${PROJECT_NAME} _proto ${PROJECT_NAME} _generate_headers)catkin_package( INCLUDE_DIRS ${protogen_include_dirs} LIBRARIES ${PROJECT_NAME} _proto ) install (TARGETS ${PROJECT_NAME} _proto ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} ) install (DIRECTORY ${proto_gen_cpp_dir} / DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} FILES_MATCHING PATTERN "*.h" ) catkin_package( INCLUDE_DIRS include ) include_directories ( ${catkin_INCLUDE_DIRS} ${PROTOBUF_INCLUDE_DIR} ${CATKIN_DEVEL_PREFIX} include ) add_library (${PROJECT_NAME} include /${PROJECT_NAME} /map.cpp ) add_executable (map_node src/map_node.cpp include /${PROJECT_NAME} /map.cpp ) target_link_libraries (${PROJECT_NAME} _node ${catkin_LIBRARIES} ${PROTOBUF_LIBRARIES} ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} )
在使用中,有以下几点需要注意:
使用时必须保证节点根目录下存在proto文件夹,并放置好proto文件,否则会提示无目标文件错误;
使用时需对应修改下与节点名称相关的变量
注意:生成的proto文件存在于devel目录inlude文件夹下,对应生成节点名称的文件夹,下面存在生成的变量。
include_directories目录中包含${CATKIN_DEVEL_PREFIX}宏,之后才可以引用devel文件目录中的proto生成文件;