Skip to main content

02.项目文件结构

2、项目文件结构

2、项目文件结构2.1、项目文件结构2.2、工作空间2.3、package功能包2.4、CMakeLists.txt介绍2.4.1、概述2.4.2、格式2.4.3、Boost2.4.4、catkin_package()2.4.5、包括路径和库路径2.4.6、可执行目标2.4.7、库文件2.4.8、target_link_libraries2.4.8、消息、服务和动作2.5、package.xml介绍

2.1、项目文件结构

ROS的文件结构,并非每个文件夹都是必须的,根据业务需求设计。

image-20210830115928145

2.2、工作空间

工作空间就是管理和组织ROS工程项目文件的地方,直观的形容就是一个仓库,里面装载着ROS的各种项目工程,便于系统组织管理调用。在可视化图形界面里是一个文件夹。我们自己写的ROS代码通常就放在工作空间中。其下主要的一级目录有四个:

  • src:源空间;ROS的catkin软件包(源代码包)
  • build:编译空间;catkin(CMake)的缓存信息和中间文件
  • devel:开发空间;生成的目标文件(包括头文件,动态链接库,静态链接库,可执行文件等)、环境变量
  • install:安装空间

最顶层的工作空间(可以任意命名)和 src (必须为src)文件夹是需要自己创建;

  • build 和 devel 文件夹由 catkin_make 命令自动创建;
  • install 文件夹由 catkin_make install 命令自动创建,几乎不怎么使用,一般不创建。

注意:使用 catkin_make 编译之前一定要回到最顶层的工作空间。同一个工作空间下,不允许存在同名功能包;不同工作空间下,允许存在同名功能包。

xxxxxxxxxx mkdir \- p ~/ catkin_ws / src # 创建 cd catkin_ws / # 进入工作空间 catkin_make # 编译 source devel / setup . bash # 更新工作空间环境

2.3、package功能包

package是一种特定的文件结构和文件夹组合。通常将实现同一个具体功能的程序代码放到一个package中。只有 CMakeLists.txt 和 package.xml 是【必须 】的,其余路径根据软件包是否需要来决定。

创建功能包

xxxxxxxxxx cd ~/ catkin_ws / src catkin_create_pkg my_pkg rospy rosmsg roscpp

【rospy】、【rosmsg】、【roscpp】是依赖库,可根据业务需求添加,也可加其他的,创建时加上就不需要再配置,忘记添加需要自己配置。

文件结构

xxxxxxxxxx |-- CMakeLists . txt # (必须)当前package的编译规则。通常需要为c++代码添加编译时的依赖,执行等操作。 | —— package . xml # (必须)package的描述信息。通常添加一些ros库的支持。 | —— include文件夹 # 存放c++ 头文件的 | —— config文件夹 # 存放参数配置文件 | —— launch文件夹 # 存放launch文件(.launch或.xml) | —— meshes文件夹 # 存放机器人或仿真场景的3D模型(.sda, .stl, .dae等) ; | —— urdf文件夹 # 存放机器人的模型描述(.urdf或.xacro) ; | —— rviz文件夹 # rviz文件 | —— src文件夹 # c++源代码 | —— scripts文件夹 # 可执行脚本;例如shell脚本(.sh)、Python脚本(.py) ; | —— srv文件夹 # 自定义service | —— msg文件夹 # 自定义topic | —— action文件夹 # 自定义action

2.4、CMakeLists.txt介绍

2.4.1、概述

CMakeLists.txt原本是Cmake编译系统的规则文件,而Catkin编译系统基本沿用了CMake的编译风格,只是针对ROS工程添加了一些宏定义。所以在写法上,catkin的CMakeLists.txt与CMake的基本一致。

这个文件直接规定了这个package要依赖哪些package,要编译生成哪些目标,如何编译等等流程。所以CMakeLists.txt非常重要,它指定了由源码到目标文件的规则,catkin编译系统在工作时首先会找到每个package下的CMakeLists.txt,然后按照规则来编译构建。

2.4.2、格式

CMakeLists.txt的基本语法都还是按照CMake,而Catkin在其中加入了少量的宏,总体的结构如下:

xxxxxxxxxx cmake_minimum_required () # 所需CMake版本 project () # 软件包名称 find_package () # 找到编译需要的其他CMake/Catkin package catkin_python_setup () # 启用Python模块支持 add_message_files () # message生成器 add_service_files () # service生成器 add_action_files () # action生成器 generate_message () # 生成不同语言版本的msg/srv/action接口 catkin_package () # 生成当前package的cmake配置,供依赖本包的其他软件包调用 add_library () # 用来指定编译产生的库。默认的catkin编译产生共享库。 add_executable () # 生成可执行二进制文件 add_dependencies () # 定义目标文件依赖于其他目标文件,确保其他目标已被构建 target_link_libraries () # 指定可执行文件链接的库。这个要用在add_executable()后面。 catkin_add_gtest () # 测试建立 install () # 安装至本机

2.4.3、Boost

如果使用C ++和Boost,您需要在Boost上调用find_package(),并指定用作组件的Boost的哪些方面。例如,如果你想使用Boost线程,你会说:

xxxxxxxxxx find_package(Boost REQUIRED COMPONENTS thread)

2.4.4、catkin_package()

catkin_package() 是一个catkin 提供的CMake宏。这是为构建系统指定catkin特定信息所必需的,后者又用于生成pkg-config和CMake文件。

在使用add_library()add_executable()声明任何目标之前** ****必须调用** 此函数。该函数有5个可选 参数:

  • INCLUDE_DIRS - 包的导出包含路径
  • LIBRARIES - 从项目导出的库
  • CATKIN_DEPENDS - 该项目依赖的其他catkin项目
  • DEPENDS - 该项目所依赖的非catkin CMake项目。为了更好的理解,请看这个解释
  • CFG_EXTRAS - 其他配置选项

完整的宏文档可以在这里找到。

举个例子:

xxxxxxxxxx catkin_package ( INCLUDE_DIRS include LIBRARIES $ { PROJECT_NAME } CATKIN_DEPENDS roscpp nodelet DEPENDS eigen opencv )

这表示包文件夹中的文件夹“include”是导出头文件的地方。CMake环境变量$ {PROJECT_NAME}评估到之前传给project()函数的任何东西,在这种情况下它将是“robot_brain”。“roscpp”+“nodelet”是需要存在来构建/运行此程序包的软件包,“eigen”+“opencv”是需要存在的用于构建/运行此程序包的系统依赖项。

2.4.5、包括路径和库路径

在指定目标之前,您需要指定可以为所述目标找到资源的位置,特别是头文件和库:

xxxxxxxxxx \- 包括路径 - 在哪里可以找到代码(最常见于C / C ++)的头文件 \- 库路径 - 哪些库位于该可执行目标建立对象? \- include_directories(<dir1>,<dir2>,...,<dirN>) \- link_directories(<dir1>,<dir2>,...,<dirN>)

  • include_directories()

include_directories的参数应该是find_package调用和需要包含的任何其他目录生成的* _INCLUDE_DIRS变量。如果您使用catkin和Boost,您的include_directories()调用应该如下所示:

xxxxxxxxxx include_directories ( include $ { Boost_INCLUDE_DIRS } $ { catkin_INCLUDE_DIRS })

第一个参数“include”表示包中的include /目录也是路径的一部分。

  • link_directories()

例:

xxxxxxxxxx link_directories ( ~/ my_libs )

CMake link_directories()函数可用于添加额外的库路径,但是不推荐这样做。所有catkin和CMake软件包在find_packaged时都会自动添加链接信息,只需链接到target_link_libraries()中的库。

请参阅本cmake的线程可以看到使用的详细例子target_link_libraries()link_directories()

2.4.6、可执行目标

要指定必须构建的可执行目标,我们必须使用add_executable() CMake函数。

xxxxxxxxxx add_executable ( myProgram src / main . cpp src / some_file . cpp src / another_file . cpp )

这将构建一个名为myProgram的目标可执行文件,它由3个源文件构建:src / main.cpp,src / some_file.cpp和src / another_file.cpp。

2.4.7、库文件

add_library() CMake的功能是用来指定库来构建。默认情况下,catkin构建共享库。

xxxxxxxxxx add_library( $ { PROJECT_NAME } $ { $ { PROJECT_NAME } _SRCS } )

使用target_link_libraries()函数来指定可执行目标链接的库。这通常在add_executable()调用之后完成。如果找不到ros,则添加$ {catkin_LIBRARIES}

句法:

xxxxxxxxxx target_link_libraries( < executableTargetName > , < lib1 > , < lib2 > , ... < libN > )

例:

xxxxxxxxxx add_executable ( foo src / foo . cpp ) add_library ( moo src / moo . cpp ) target_link_libraries ( foo moo ) \-- This links foo against libmoo . so

请注意,在大多数用例中不需要使用link_directories(),因为信息通过find_package()自动引入。

2.4.8、消息、服务和动作

消息(.msg),服务(.srv)和动作(.action)文件在ROS包构建和使用之前需要一个特殊的预处理器构建步骤。这些宏的要点是生成编程语言特定的文件,以便可以利用其选择的编程语言中的消息,服务和动作。构建系统将使用所有可用的生成器(例如gencpp,genpy,genlisp等)生成绑定。

提供了三个宏来分别处理消息,服务和动作:

  • add_message_files
  • add_service_files
  • add_action_files

这些宏之后必须跟随调用生成的宏:

xxxxxxxxxx generate_messages()

如果你从未接触过CMake的语法,请阅读《CMake实践》:https://github.com/Akagi201/learning-cmake/blob/master/docs/cmake-practice.pdf 。掌握CMake语法对于理解ROS工程很有帮助。

2.5、package.xml介绍

  • 概述

该软件包清单是一个XML文件名为package.xml中必须包括与任何兼容包的根文件夹。package.xml也是一个catkin的package必备文件,它是这个软件包的描述文件,在较早的ROS版本(rosbuild编译系统)中,这个文件叫做manifest.xml,用于描述pacakge的基本信息。如果你在网上看到一些ROS项目里包含着manifest.xml,那么它多半是hydro版本之前的项目了。pacakge.xml包含了package的名称、版本号、内容描述、维护人员、软件许可、编译构建工具、编译依赖、运行依赖等信息。

package.xml文件build_depend必须包含 message_generation,run_depend必须包含 message_runtime。

  • 格式

xxxxxxxxxx < pacakge > # 根标记文件 < name > # 包名 < version > # 版本号 < description > # 内容描述 < maintainer > # 维护者 < license > # 软件许可证 < buildtool_depend > # 编译构建工具,通常为catkin < depend > # 指定依赖项为编译、导出、运行需要的依赖,最常用 < build_depend > # 编译依赖项 < build_export_depend > # 导出依赖项 < exec_depend > # 运行依赖项 < test_depend > # 测试用例依赖项 < doc_depend > # 文档依赖项

  • 依赖关系

具有最小标签的包清单不指定对其他包的任何依赖关系。软件包可以有六种依赖关系:

**构建依赖关系 <build_depend>**指定构建此包所需的包。在构建时需要这些软件包中的任何文件时才是这种情况。这可以包括在编译时的头文件,链接到这些包的库文件或在构建时需要任何其他资源(特别是当这些包在CMake 中是find_package()时)。在交叉编译场景中,构建依赖关系针对目标体系结构。

**构建导出依赖关系 <build_export_depend>**指定根据此包构建库所需的包。当您将此头文件包含在此包中的公用头文件中时(特别是当CMake中的catkin_package()中声明为(CATKIN_DEPENDS 时),就是这种情况。

**执行依赖关系 <exec_depend>**指定在此程序包中运行代码所需的软件包。当您依赖此程序包中的共享库(尤其是当CMake 中的catkin_package()中声明为(CATKIN_DEPENDS )时),就是这种情况。

**测试依赖关系 <test_depend>**仅指定单元测试的附加依赖项。他们不应该将已经提到的任何依赖关系重复为构建或运行依赖关系。

**构建工具依赖关系 <buildtool_depend>**指定此软件包需要构建自身的构建系统工具。通常唯一的构建工具是catkin。在交叉编译场景中,构建工具依赖关系用于执行编译的架构。

**文档工具依赖关系 <doc_depend>**指定此软件包需要生成文档的文档工具。

  • 附加标签

<url> - 有关该软件包信息的URL,通常是ros.org上的wiki页面。

<author> - 包的作者

xxxxxxxxxx < url type = "website" > http : // www . ros . org / wiki / turtlesim </ url > < author > Yahboom </ author >