单个功能包的组织形式
一个功能包必须包含如下的两个文件:
-
package.xml
-
CMakeLists.txt
并且,每一个功能包必须拥有自己的文件夹。
一般而言,我们会在功能包下面再创建一个src
文件夹用于存放源代码,这一步骤不一定是必须手动操作的,因为如果你是通过catkin_create_pkg命令创建的package,那么该命令会自动创建好src文件夹,而如果你是在Qt Creator中通过ros-qtc-plugin插件进行package开发的话,那么就需要用户手动创建src文件夹了,虽然这一步不是必须的,但是从规范化的角度来看还是很有必要的,特别是当项目比较复杂的时候,节点比较多的时候,源文件是比较多的,各种文件糅合在一个文件夹中是非常难看,不方便管理的。
package01/
package.xml
CMakeLists.txt
src/
node01.cpp
node02.cpp
...
过个功能包在工作空间中的组织形式
catkin_ws/
src/
CMakeLists.txt
package01/
CMakeLists.txt
package.xml
src/
node01.cpp
node02.cpp
...
package02/
CMakeLists.txt
package.xml
src/
node01.cpp
node02.cpp
...
...
package0n/
CMakeLists.txt
package.xml
src/
node01.cpp
node02.cpp
...
创建一个功能包并构建它
创建一个功能包的前提是必须创建了一个catkin工作空间,而我们的功能包就是在工作空间中创建的,因此在进行如下操作的时候,默认是已经创建好了一个catkin功能包:
cd catkin_ws/src
catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
cd ..
catkin_make
创建功能包的命令格式如下:
catkin_create_pkg package_name [depends1] [depends2] [pdends3] ...
其中package_name是我们要创建的功能包的名称,而depends1, depends2, ...等是该功能包的依赖包。
最后,别忘了source一下的你工作空间中的devel/setup.bash文件,这样就把当前的工作空间添加进ROS的环境中。
执行如下的命令,source一下catkin_ws工作空间,前提是你的当前终端停留在~/catkin_ws下:
source devel/setup.bash
功能包的依赖关系
就上面的我们创建的功能包为例,我们来学习功能包的依赖关系。
我们用rospack depends1
来输出上面创建的功能包的第一层次依赖关系,也叫作直接依赖关系:
cd ~/Desktop/catkin_ws
source devel/setup.bash
rospack depends1 beginner_tutorials
输出结果为:
liuqiang@liuqiang-pc:~/Desktop/catkin_ws$ rospack depends1 beginner_tutorials
roscpp
rospy
std_msgs
检测直接依赖关系roscpp
的直接依赖关系:
rospack depends1 roscpp
输出结果为:
liuqiang@liuqiang-pc:~/Desktop/catkin_ws$ rospack depends1 roscpp
cpp_common
message_runtime
rosconsole
roscpp_serialization
roscpp_traits
rosgraph_msgs
rostime
std_msgs
xmlrpcpp
假如,我们需要检测我们创建的功能包beginner_tutorials的所有依赖关系(包括直接和间接的依赖关系),那么,我们需要使用如下的命令,幸运的是rospack
可以递归地检测出所有嵌套的依赖关系并通过列表输出:
rospack depends beginner_tutorials
输出结果为:
liuqiang@liuqiang-pc:~/Desktop/catkin_ws$ rospack depends beginner_tutorials
cpp_common
rostime
roscpp_traits
roscpp_serialization
catkin
genmsg
genpy
message_runtime
gencpp
genlisp
message_generation
rosbuild
rosconsole
std_msgs
rosgraph_msgs
xmlrpcpp
roscpp
rosgraph
rospack
roslib
rospy
定制我们创建的功能包
可以看出,我们前面通过catkin_create_pkg
创建的功能包里面包含了package.xml和CMakeLists.txt文件,而我们要创建自己特定功能的功能包,就需要按照自己的需求来改写这两个文件。
.
├── CMakeLists.txt
├── include
│ └── beginner_tutorials
├── package.xml
└── src
首先,我们来认识一下package.xml文件的内容及其各部分的含义:
<?xml version="1.0"?>
<package>
<name>beginner_tutorials</name>
<version>0.0.0</version>
<description>The beginner_tutorials package</description>
# 上面一句是功能包的描述标签
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="liuqiang@todo.todo">liuqiang</maintainer>
# 上面一句是功能包维护者邮箱的标签
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>TODO</license>
# 上面是许可证标签
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/beginner_tutorials</url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *_depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use run_depend for packages you need at runtime: -->
<!-- <run_depend>message_runtime</run_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend>
# 上面是构建工具依赖包
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
# 上面是构建依赖功能包
<run_depend>roscpp</run_depend>
<run_depend>rospy</run_depend>
<run_depend>std_msgs</run_depend>
# 上面是运行依赖功能包
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>
package.xml文件的关键内容提取出来就是:
<?xml version="1.0"?>
<package>
<name>beginner_tutorials</name>
<version>0.0.0</version>
<description>The beginner_tutorials package</description>
# 上面一句是功能包的描述标签
<maintainer email="liuqiang@todo.todo">liuqiang</maintainer>
# 上面一句是功能包维护者邮箱的标签
<license>TODO</license>
# 上面是许可证标签
<buildtool_depend>catkin</buildtool_depend>
# 上面是构建工具依赖包
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
# 上面是构建依赖功能包
<run_depend>roscpp</run_depend>
<run_depend>rospy</run_depend>
<run_depend>std_msgs</run_depend>
# 上面是运行依赖功能包
</package>
接着,我们来认识一下CMakeLists.txt,如果我们要构建我们自己的功能包,那么就要按需修改功能包的CMakeLists.txt文件
首先,我们来概览一下CMakeLists.txt文件的结构和顺序:
cmake_minimum_required(VERSION 2.8.3 FATAL_ERROR)
project(beginner_tutorials)
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)
find_package(Boost REQUIRED COMPONENTS thread)
catkin_python_setup()
add_message_files(Message1.msg Message2.msg)
add_service_files(Service1.srv Service2.srv)
add_action_files(Action1.action Action2.action)
generate_messages(DEPENDENCIES std_msgs sensor_msgs)
catkin_package(INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS roscpp nodelet
DEPENDS eigen opencv)
include(${catkin_INCLUDE_DIRS})
add_libraries(${PROJECT_NAME} src/${PROJECT_NAME}/beginner_tutorials.cpp)
add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_executable(${PROJECT_NAME}_node src/beginner_tutorials_node.cpp)
set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(${PROJECT_NAME}_node ${catkin_LIBRARIES})
install(PROGRAMS scripts/my_python_script DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
详细操作,请参阅:http://wiki.ros.org/catkin/CMakeLists.txt
接着,我们来查看一下CMakeLists.txt文件中的内容:
cmake_minimum_required(VERSION 2.8.3)
# 上面指定Cmake最低的版本要求
project(beginner_tutorials)
# 上面给定项目名称
## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
)
# 上面查找依赖的功能包
## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)
## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()
################################################
## Declare ROS messages, services and actions ##
################################################
## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
## * add a build_depend tag for "message_generation"
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
## but can be declared for certainty nonetheless:
## * add a run_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
## * add "message_generation" and every package in MSG_DEP_SET to
## find_package(catkin REQUIRED COMPONENTS ...)
## * add "message_runtime" and every package in MSG_DEP_SET to
## catkin_package(CATKIN_DEPENDS ...)
## * uncomment the add_*_files sections below as needed
## and list every .msg/.srv/.action file to be processed
## * uncomment the generate_messages entry below
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
## Generate messages in the 'msg' folder
# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )
## Generate services in the 'srv' folder
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
## Generate actions in the 'action' folder
# add_action_files(
# FILES
# Action1.action
# Action2.action
# )
## Generate added messages and services with any dependencies listed here
# generate_messages(
# DEPENDENCIES
# std_msgs
# )
################################################
## Declare ROS dynamic reconfigure parameters ##
################################################
## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
## * add a build_depend and a run_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
## * add "dynamic_reconfigure" to
## find_package(catkin REQUIRED COMPONENTS ...)
## * uncomment the "generate_dynamic_reconfigure_options" section below
## and list every .cfg file to be processed
## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
# cfg/DynReconf1.cfg
# cfg/DynReconf2.cfg
# )
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if you package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES beginner_tutorials
# CATKIN_DEPENDS roscpp rospy std_msgs
# DEPENDS system_lib
)
# 为功能包生成cmake配置文件
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
# 添加头文件
## Declare a C++ library
# add_library(${PROJECT_NAME}
# src/${PROJECT_NAME}/beginner_tutorials.cpp
# )
## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/beginner_tutorials_node.cpp)
## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
#############
## Install ##
#############
# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark executables and/or libraries for installation
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )
## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
# # myfile1
# # myfile2
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_beginner_tutorials.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()
## Add folders to be run by python nosetests
# catkin_add_nosetests(test)
构建功能包
source devel/setup.bash
catkin_make
如果把catkin_make
分解出来,可以执行如下的命令流:
mkdir build
cd build
cmake ..
make -j4