ROS之构建系统(四)

构建系统

(仅作学习笔记)
ROS的构建系统默认使用CMake(Cross Platform Make),其构建环境在功能包目录中的CMakeLists.txt文件中描述。在ROS中,CMake被修改为适合于ROS的“catkin” 构建系统。在ROS中使用CMake的是为了在多个平台上构建 ROS功能包。CMake支持Unix类的Linux、BSD和OS X以外,还支持Windows系列。并且,它还支持Microsoft Visual Studio,也还可以轻松应用于Qt开发。此外,catkin 构建系统可以轻松使用与ROS相关的构建、功能包管理和功能包之间的依赖关系。
一、创建功能包
创建ROS功能包的命令如下。

catkin_create_pkg [功能包名称] [依赖功能包1] [依赖功能包n]

“catkin_create_pkg”命令在创建用户功能包时会生成catkin 构建系统所需的CMakeLists.txt和package.xml文件的包目录。让我们来创建一个简单的功能包,以巩固理解。首先打开一个新的终端窗口(Ctrl + Alt + t)并运行以下命令移至工作目录.

cd ~/catkin_ws/src

要创建的功能包名称是“my_first_ros_pkg”。ROS中的功能包名称全部是小写字母,不能包含空格。格式规则是将每个单词用下划线(_)而不是短划线( - )连接起来。有关ROS编程,请参阅相关页面的编码风格和命名约定.
http://wiki.ros.org/CppStyleGuide
http://wiki.ros.org/PyStyleGuide
那么下面使用以下命令创建一个名为my_first_ros_pkg的功能包:

catkin_create_pkg my_first_ros_pkg std_msgs roscpp

上面用“std_msgs”和“roscpp”作为前面命令格式中的依赖功能包的选项。这意味着为了使用ROS的标准消息包std_msgs和客户端库roscpp(为了在ROS中使用C/C++),在创建功能包之前先进行这些选项安装。这些相关的功能包的设置可以在创建功能包时指定,但是用户也可以在创建之后直接在package.xml中输入。
如果已经创建了功能包,“~/catkin_ws/src”会创建“my_first_ros_pkg”功能包目录、ROS功能包应有的内部目录以及CMakeLists.txt和package.xml文件。用户可以用下面的“ls”命令来检查内容。

$ cd my_first_ros_pkg
$ ls
include → include目录
src → 源代码目录
CMakeLists.txt → 构建配置文件
package.xml → 功能包配置文件

二、修改功能包配置文件(package.xml)
必要的ROS配置文件之一的package.xml是一个包含功能包信息的XML文件,包括功能包名称、作者、许可证和依赖功能包。最初没有做任何修改的原始文件如下:

xml version="1.0"?>
<package>
<name>my_first_ros_pkg</name>
<version>0.0.0</version>
<description>The my_first_ros_pkg package</description>


<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="oroca@todo.todo">pyo</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 mutiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/my_first_ros_pkg</url> -->


<!-- Author tags are optional, mutiple are allowed, one per tag -->
<!-- Authors do not have to be maintianers, 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>std_msgs</build_depend>
<run_depend>roscpp</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>

下面是对每个语句的说明。

<?xml> 这是一个定义文档语法的语句,随后的内容表明在遵循xml版本1.0。

<package> 从这个语句到最后</package>的部分是ROS功能包的配置部分。

<name> 功能包的名称。使用创建功能包时输入的功能包名称。正如其他选项,用户可以随时更改。

<version> 功能包的版本。可以自由指定。

<description> 功能包的简要说明。通常用两到三句话描述。

<maintainer> 提供功能包管理者的姓名和电子邮件地址。

<license> 记录版权许可证。写BSD、MIT、Apache、GPLv3或LGPLv3即可。

<url> 记录描述功能包的说明,如网页、错误管理、存储库的地址等。根据功能包的类型,用户可以填写网站、错误跟踪(bugtracker)或存储库的地址。

<author> 记录参与功能包开发的开发人员的姓名和电子邮件地址。如果涉及多位开发人员,只需在下一行添加<author>标签。

<buildtool_depend> 描述构建系统的依赖关系。我们正在使用catkin 构建系统,因此输入catkin。

<build_depend> 在编写功能包时写下您所依赖的功能包的名称。

<run_depend> 填写运行功能包时依赖的功能包的名称。

<test_depend> 填写测试功能包时依赖的功能包名称。

<export> 在使用ROS中未指定的标签名称时会用到<export>。最广泛使用的情况是元功能包的情况,这时用<export> <metapackage/> </export>格式表明是元功能包。

<metapackage> 在export标签中使用的官方标签声明,当前功能包为一个元功能包时声明它。

修改了功能包配置文件(package.xml),如下所示。也可以根据自己的环境进行修改。如果还不熟悉,可以键入以下内容:

<?xml version="1.0"?>
<package>
 <name>my_first_ros_pkg</name>
 <version>0.0.1</version>
 <description>The my_first_ros_pkg package</description>
 <license>Apache License 2.0</license>
 <author email="pyo@robotis.com">Yoonseok Pyo</author>
 <maintainer email="pyo@robotis.com">Yoonseok Pyo</maintainer>
 <url type="bugtracker">https://github.com/ROBOTIS-GIT/ros_turtorials/issues</url>
 <url type="repository">https://github.com/ROBOTIS-GIT/ros_turtorials.git</url>
 <url type="website">http://www.robotis.com</url>
 <buildtool_depend>catkin</buildtool_depend>
 <build_depend>std_msgs</build_depend>
 <build_depend>roscpp</build_depend>
 <run_depend>std_msgs</run_depend>
<run_depend>roscpp</run_depend>
<export></export>
</package>

三、修改构建配置文件(CMakeLists.txt)
ROS的构建系统catkin基本上使用CMake,并在功能包目录中的CMakeLists.txt文件中描述构建环境。在这个文件中设置可执行文件的创建、依赖包优先构建、连接器(linker)的创建等等。
构建配置文件(CMakeLists.txt)中的每一项如下所示。第一条是操作系统中安装的cmake的最低版本。由于它目前被指定为版本2.8.3,所以如果使用低于此版本的cmake,则必须更新版本。

cmake_minimum_required(VERSION 2.8.3)

project项是功能包的名称。只需使用用户在package.xml中输入的功能包名即可。请注意,如果功能包名称与package.xml中的标记中描述的功能包名称不同,则在构建时会发生错误,因此需要注意。

project(my_first_ros_pkg)

find_package项是进行构建所需的组件包。目前,roscpp和std_msgs被添加为依赖包。如果此处没有输入功能包名称,则在构建时会向用户报错。换句话说,这是让用户先创建依赖包的选项。

find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
)

以下是使用ROS以外的功能包时使用的方法。例如,使用Boost时,必须安装system功能包。功能如前面的说明,是让用户先创建依赖功能包的选项。

find_package(Boost REQUIRED COMPONENTS system)

catkin_python_setup( )选项是在使用Python,也就是使用rospy时的配置选项。其功能是调用Python安装过程setup.py。

catkin_python_setup()

add_message_files是添加消息文件的选项。FILES将引用当前功能包目录的msg目录中的*.msg文件,自动生成一个头文件(*.h)。在这个例子中,我们将使用消息文件Message1.msg和Message2.msg。

add_message_files(
FILES
Message1.msg
Message2.msg
)

add_service_files是添加要使用的服务文件的选项。使用FILES会引用功能包目录中的srv目录中的*.srv文件。在这个例子中,用户可以选择使用服务文件Service1.srv和Service2.srv。

add_service_files(
FILES
Service1.srv
Service2.srv
)

generate_messages是设置依赖的消息的选项。此示例是将DEPENDENCIES选项设置为使用std_msgs消息包。

generate_messages(
DEPENDENCIES
std_msgs
)

generate_dynamic_reconfigure_options是使用dynamic_reconfigure时加载要引用的配置文件的设置。

generate_dynamic_reconfigure_options(
cfg/DynReconf1.cfg
cfg/DynReconf2.cfg
)

以下是catkin 构建选项。INCLUDE_DIRS表示将使用INCLUDE_DIRS后面的内部目录include的头文件。LIBRARIES表示将使用随后而来的功能包的库。CATKIN_DEPENDS后面指定如roscpp或std_msgs等依赖包。目前的设置是表示依赖于roscpp和std_msgs。DEPENDS是一个描述系统依赖包的设置。

catkin_package(
INCLUDE_DIRS include
LIBRARIES my_first_ros_pkg
CATKIN_DEPENDS roscpp std_msgs
DEPENDS system_lib
)

include_directories是可以指定包含目录的选项。目前设定为 c a t k i n I N C L U D E D I R S , 这 意 味 着 将 引 用 每 个 功 能 包 中 的 i n c l u d e 目 录 中 的 头 文 件 。 当 用 户 想 指 定 一 个 额 外 的 i n c l u d e 目 录 时 , 写 在 {catkin_INCLUDE_DIRS},这意味着将引用每个功能包中的include目录中的头文件。当用户想指定一个额外的include目录时,写在 catkinINCLUDEDIRSincludeinclude{catkin_INCLUDE_DIRS}的下一行即可。

include_directories(
${catkin_INCLUDE_DIRS}
)

add_library声明构建之后需要创建的库。以下是引用位于my_first_ros_pkg功能包的src目录中的my_first_ros_pkg.cpp文件来创建my_first_ros_pkg库的命令。

add_library(my_first_ros_pkg
src/${PROJECT_NAME}/my_first_ros_pkg.cpp
)

add_dependencies是在构建该库和可执行文件之前,如果有需要预先生成的有依赖性的消息或dynamic_reconfigure,则要先执行。以下内容是优先生成my_first_ros_pkg库依赖的消息及dynamic reconfigure的设置。

add_dependencies(my_first_ros_pkg ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

add_executable是对于构建之后要创建的可执行文件的选项。以下内容是引用src/my_first_ros_pkg_node.cpp文件生成my_first_ros_pkg_node可执行文件。如果有多个要引用的*.cpp文件,将其写入my_first_ros_pkg_node.cpp之后。如果要创建两个以上的可执行文件,需追加add_executable项目。

add_executable(my_first_ros_pkg_node src/my_first_ros_pkg_node.cpp)

如前面描述的add_dependencies一样,add_dependencies是一个首选项,是在构建库和可执行文件之前创建依赖消息和dynamic reconfigure的设置。下面介绍名为my_first_ros_pkg_node的可执行文件的依赖关系,而不是上面提到的库。在建立可执行文件之前,先创建消息文件的情况下会经常用到。

add_dependencies(my_first_ros_pkg_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

target_link_libraries是在创建特定的可执行文件之前将库和可执行文件进行链接的选项。

target_link_libraries(my_first_ros_pkg_node
${catkin_LIBRARIES}
)

以下修改了构建配置文件(CMakeLists.txt),可以根据情况进行修改。有关如何使用它的更多信息,请参阅https://github.com/ROBOTIS-GIT上发布的TurtleBot3和OP3功能包。

CMakeLists.txt
cmake_minimum_required(VERSION 2.8.3)
project(my_first_ros_pkg)
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs)
catkin_package(CATKIN_DEPENDS roscpp std_msgs)
include_directories(${catkin_INCLUDE_DIRS})
add_executable(hello_world_node src/hello_world_node.cpp)
target_link_libraries(hello_world_node ${catkin_LIBRARIES})

四、编写源代码
在上述CMakelists.txt文件的可执行文件创建部分(add_executable)中,进行以下设置。

add_executable(hello_world_node src/hello_world_node.cpp)

换句话说,是引用功能包的src目录中的hello_world_node.cpp源代码来生成hello_world_node可执行文件。由于这里没有hello_world_node.cpp源代码,写一个简单的例子。首先,用cd命令转到功能包目录中包含源代码的目录(src),并创建hello_world_node.cpp文件。这个例子使用gedit编辑器,但是可以使用自己的编辑器,比如vi、gedit、qtcreator、vim或者emacs。

cd ~/catkin_ws/src/my_first_ros_pkg/src/
gedit hello_world_node.cpp

之后如下修改代码。

#include <ros/ros.h>
#include <std_msgs/String.h>
#include <sstream>
int main(int argc, char **argv)
{
ros::init(argc, argv, "hello_world_node");
ros::NodeHandle nh;
ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("say_hello_world", 1000);
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss << "hello world!" << count;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
++count;
}
return 0;
}

五、构建功能包
所有构建功能包的准备工作都已完成。在构建之前,使用以下命令更新ROS功能包的配置文件。这是一个将之前创建的功能包反映在ROS功能包列表的命令,这并不是必选操作,但在创建新功能包后更新的话使用时会比较方便。

rospack profile //可忽略

下面是catkin构建。移动到catkin工作目录后进行catkin构建。

cd ~/catkin_ws && catkin_make  //相当于之前博客设置快捷命令的cm

六、运行节点
如果构建无误,那么将在“~/catkin_ws/devel/lib/my_first_ros_pkg”中生成“hello_world_node”文件。下一步是运行该节点,打开一个终端窗口(Ctrl + Alt + t)并在运行该节点之前先运行roscore。请注意,运行roscore后,ROS中的所有节点都可用,除非退出了roscore,否则只需运行一次。

roscore

最后,打开一个新的终端窗口(Ctrl + Alt + t)并使用以下命令运行节点。这是在名为my_first_ros_pkg的功能包中运行名为hello_world_node的节点的命令。

rosrun my_first_ros_pkg hello_world_node

当您运行这个节点的时候,您可以在终端窗口中看到以hello world!0,1,2,3 … 作为字符串发送的消息。这不是一个实际的消息传递,但可以看作是讨论的构建系统的结果。

[INFO] [1499662568.416826810]: hello world!0
[INFO] [1499662568.516845339]: hello world!1
[INFO] [1499662568.616839553]: hello world!2
[INFO] [1499662568.716806374]: hello world!3
[INFO] [1499662568.816807707]: hello world!4
[INFO] [1499662568.916833281]: hello world!5
[INFO] [1499662569.016831357]: hello world!6
[INFO] [1499662569.116832712]: hello world!7
[INFO] [1499662569.216827362]: hello world!8
[INFO] [1499662569.316806268]: hello world!9
[INFO] [1499662569.416805945]: hello world!10
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值