概述
前言
记录ROS2学习的各项核心概念,便于后续复习。
一、工作空间workshop
1.什么是工作空间
在ROS机器人开发中,工作空间是一个存放项目开发相关文件的文件夹,各种编写的代码、参数、脚本等文件,放置在一个文件夹里进行管理,这个文件夹在ROS系统中就叫做工作空间。PS:就是一个文件夹,放置代码的地方,就像VS的工程文件夹。
ROS系统中一个典型的工作空间结构如图1所示,这个dev_ws就是工作空间的根目录,里边会有四个子目录,或者叫做四个子空间。
src,代码空间,未来编写的代码、脚本,都需要人为的放置到这里; PS:这个需要我们自己建立
build,编译空间,保存编译过程中产生的中间文件;PS:自动建立
install,安装空间,放置编译得到的可执行文件和脚本; PS:自动建立
log,日志空间,编译和运行过程中,保存各种警告、错误、信息等日志。PS:自动建立
这四个空间的文件夹,我们绝大部分操作都是在src中进行的,编译成功后,就会执行install里边的结果,build和log两个文件夹用的很少。
2.创建工作空间
#建立目录
$ mkdir -p ~/dev_ws/src
$ cd ~/dev_ws/src
#放点代码进去,这里直接拉去了古月君的课程代码
$ git clone https://gitee.com/guyuehome/ros2_21_tutorials.git
3.自动安装依赖
使用工具自动分析src目录下得源代码,并对源代码进行依赖安装。
$ sudo apt install -y python3-pip
#这里安装了fishros的国产依赖工具rosdepc
$ sudo pip3 install rosdepc
#初始化
$ sudo rosdepc init
#更新
$ rosdepc update
$ cd ..
$ rosdepc install -i --from-path src --rosdistro humble -y
PS:这里面涉及rosdep工具的使用,小伙伴可以自行查阅相关资料。
这里是我的学习记录:
4.编译工作空间
依赖安装完成后,就可以使用如下命令编译工作空间啦,如果有缺少的依赖,或者代码有错误,编译过程中会有报错,否则编译过程应该不会出现任何错误:
#安装编译工具
$ sudo apt install python3-colcon-ros
#切换至工作空间主目录
$ cd ~/dev_ws/
#开始编译,colcon会分析src目录下的源代码并进行编译
$ colcon build
编译成功后,就可以在工作空间中看到自动生产的build、log、install文件夹了。
这里是我的学习记录
5.设置环境变量
编译成功后,为了让系统能够找到我们的功能包和可执行文件,还需要设置环境变量:
PS:
$ source install/local_setup.sh # 仅在当前终端生效
$ echo " source ~/dev_ws/install/local_setup.sh" >> ~/.bashrc # 所有终端均生效
至此,我们就完成了工作空间的创建、编译和配置。
二、功能包package
1.什么是功能包package
package是一种特定的文件结构和文件夹组合。通常将实现同一个具体功能的程序代码放到一个package中。
每个机器人可能有很多功能,比如移动控制、视觉感知、自主导航等,如果我们把这些功能的源码都放到一起当然也是可以的,但是当我们想把其中某些功能分享给别人时,就会发现代码都混合到了一起,很难拆分出来。
把不同功能的代码划分到不同的功能包中,尽量降低他们之间的耦合关系,当需要在ROS社区中分享给别人的时候,只需要说明这个功能包该如何使用,别人很快就可以用起来了。
所以功能包的机制,是提高ROS中软件复用率的重要方法之一。
2.创建功能包
如何在ROS2中创建一个功能包呢?我们可以使用这个指令:
$ ros2 pkg create --build-type <build-type> <package_name>
ros2命令中:
pkg:表示功能包相关的功能;
create:表示创建功能包;
build-type:表示新创建的功能包是C++还是Python的,如果使用C++或者C,那这里就跟ament_cmake,如果使用Python,就跟ament_python;
package_name:新建功能包的名字。
比如在终端中分别创建C++和Python版本的功能包
$ cd ~/dev_ws/src
$ ros2 pkg create --build-type ament_cmake learning_pkg_c # C++
$ ros2 pkg create --build-type ament_python learning_pkg_python # Python
3.编译功能包
在创建好的功能包中,我们可以继续完成代码的编写,之后需要编译和配置环境变量,才能正常运行:
$ cd ~/dev_ws/src
$ colcon build # 编译工作空间所有功能包
$ source install/local_setup.bash
4.功能包的结构
功能包并不是普通的文件夹,那如何判断一个文件夹是否是功能包呢?
文件结构
CMakeLists.txt: 定义package的包名、依赖、源文件、目标文件等编译规则,是package不可少的成分;
package.xml: 描述package的包名、版本号、作者、依赖等信息,是package不可少的成分 ;
src/: 存放ROS的源代码,包括C++的源码和(.cpp)以及Python的module(.py) ;
include/: 存放C++源码对应的头文件 ;
scripts/: 存放可执行脚本,例如shell脚本(.sh)、Python脚本(.py) ;
msg/: 存放自定义格式的消息(.msg) ;
srv/: 存放自定义格式的服务(.srv) ;
models/: 存放机器人或仿真场景的3D模型(.sda, .stl, .dae等) ;
urdf/: 存放机器人的模型描述(.urdf或.xacro) ;
launch/: 存放launch文件(.launch或.xml)
通常ROS文件组织都是按照以上的形式,这是约定俗成的命名习惯,建议遵守。以上路径中,只有 CMakeLists.txt 和 package.xml 是必须的,其余路径根据软件包是否需要来决定
CMakeLists.txt
CMakeLists.txt 原本是Cmake编译系统的规则文件,而Catkin编译系统基本沿用了CMake的编译风格,只是针对ROS工程添加了一些宏定义。所以在写法上,catkin的 CMakeLists.txt 与CMake的基本一致
这个文件直接规定了这个package要依赖哪些package,要编译生成哪些目标,如何编译等等流程。所以 CMakeLists.txt 非常重要,它指定了由源码到目标文件的规则,catkin编译系统在工作时首先会找到每个package下CMakeLists.txt ,然后按照规则来编译构建
我们使用cmake进行程序编译的时候,会根据CMakeLists.txt这个文件进行一步一步的处理,然后形成一个MakeFile文件,系统再通过这个文件的设置进行程序的编译
ROS中的CMakeLists.txt也是基于普通的cmake的。ROS中的CMakeLists.txt主要包括下面几个部分:
所需CMake版本(cmake_minimum_required)
软件包名称(project())
查找构建所需的其他CMake / Catkin 软件包(find_package())
启用Python模块支持(catkin_python_setup())
消息/服务/动作生成器(add_message_files(),add_service_files(),add_action_files())
消息/服务/动作生成(generate_messages())
指定包构建的消息导出(catkin_package())
要建立的库/可执行文件(add_library()/ add_executable()/ target_link_libraries())(target_link_libraryies通常情况下要有)
测试建立(catkin_add_gtest())
安装规则(install())
代码解析:
cmake_minimum_required(VERSION 2.8.3)
*catkinCMakeLists.txt都要以此开始,catkin编译需要2.8.3版本以上的cmake*
project(beginner_tutorials)
*通过project()这个函数指定包的名字,在CMake中指定后,你可在其他地方通过使用变量${PROJECT_NAME}来引用它*
find_package 依赖功能包
*这里指明构建这个package需要依赖的package,我们使用 catkin_make 的编译方式,至少需要catkin这个包,即 find_package(catkin REQUIRED)
如果要使用 C++ 和 Boost,则需要引用 find_package 包含 Boost,并且指明 Boost 的类型,如使用 Boost threads,则:find_package(Boost REQUIRED COMPONENTS thread)
需要的所有包我们都可用这种方式包含进来,比如我们还需要roscpp,rospy,std_msgs。我们可以写成:
find_package(roscpp REQUIRED)
find_package(rospy REQUIRED)
find_package(std_msgs REQUIRED)
这样的话,每个依赖的package都会产生几个变量,这样很不方便。所以还有另外一种方式:
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation )
这样,它会把所有pacakge里面的头文件和库文件等等目录加到一组变量上,比如:catkin_INCLUDE_DIRS,这样,我们就可以用这个变量查找需要的文件了。最终就只产生一组变量了。*
Declare ROS messages, services and actions
*当我们需要使用.msg .srv .action形式的文件时,我们需要特殊的预处理器把他们转化为系统可以识别特定编程语言(.h .cpp)。系统会用里面所有的(一些编程语言)生成器(比如 gencpp, genpy, genlisp, etc)生成相应的.cpp .py文件
这就需要三个宏:add_message_files, add_service_files,add_action_files来相应的控制.msg .srv .action。这些宏后面必须跟着一个调用generate_messages()
这些宏必须在catkin_package()宏前面
find_package()必须依赖包message_generation
package.xml文件build_depend必须包含 message_generation,run_depend必须包含 message_runtime
如果你有一个包编译.msg .srv,并且可执行文件要使用他们,那么你就需要创建一个显式的依赖项,自动生成message的target。这样才能按顺序来进行编译:
add_dependencies(some_target ${PROJECT_NAME}_generate_messages_cpp)
(这里的some_target是add_executable()设置的target的名字)*
catkin_package()
*这是一个catkin提供的cmake宏,当我们要给构建系统指定catkin的特定的信息时就需要了,或者反过来利用他产生pkg-config和CMake文件。这个函数必须在声明add_library()或者 add_executable()生成target之前使用,该函数有5个可选参数:
INCLUDE_DIRS :包的导出包含路径
LIBRARIES:从项目导出的库
CATKIN_DEPENDS:该项目依赖的其他catkin项目
DEPENDS:该项目所依赖的非catkin CMake项目。为了更好的理解,请看这个解释。
CFG_EXTRAS:其他配置选项*
Specifying Build Targets (指定编译的target)
*编译产生的target有多种形式,通常有两种:程序可以运行的可执行文件以及在可执行文件编译和运行时要用到的库*
target的命名
target的命名很重要,在catkin中target的名字必须是唯一的,和你之前构建产生的和安装的都不能相同。这只是cmake内部的需要。可以利用set_target_properties()函数将以个target进行重命名,例如:set_target_properties(rviz_image_view PROPERTIES OUTPUT_NAME image_view PREFIX "")这样就可将那个target rviz_image_view 改为image_view
几个函数介绍:
include_directories
他的参数是通过find_package产生的*_INCLUDE_DIRS变量和其他所有额外的头文件路径。例如:include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})(这里include表示你的pacakge里面的include这个路径也包含在里面)
link_directories()
这个函数用来添加额外的库的路径,然而,这并不鼓励使用,因为所有的catkin和cmake的package在使用find_package时就已经自动的有他们的链接信息。
简单的连接可以通过target_link_libraries()来进行
Executable Targets (可执行target)
要指定必须构建的可执行目标,我们必须使用add_executable()。例如:add_executable(myProgram src/main.cpp src/some_file.cpp src/another_file.cpp)
库target
add_library()用来指定编译产生的库
默认的catkin编译产生共享库:add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})
链接库(target_link_libraries)
使用target_link_libraries函数来指定可执行文件链接的库。
这个要用在add_executable()后面
使用target_link_libraries(<executableTargetName>, <lib1>, <lib2>, ... <libN>)
其他配置说明:
启用Python模块支持
如果您的ROS包提供了一些Python模块,您应该创建一个setup.py文件并调用catkin_python_setup()
单元测试
有一个catkin-specific宏用于处理名为catkin_add_gtest()的基于gtest的单元测试
catkin_add_gtest(myUnitTest test / utest.cpp)
指定可安装的目标
构建时间之后,目标被放置在catkin工作空间的空间中。但是,通常我们希望将目标安装到系统中(有关安装路径的信息可以在REP 122中找到 ),以便其他人或本地文件夹可以使用它们来测试系统级安装。换句话说,如果你想要做一个“make install”的代码,你需要指定目标应该在哪里
这是使用CMake install()函数作为参数完成的
目标:目标是安装
ARCHIVE DESTINATION:静态库和DLL(Windows).lib存根
LIBRARY DESTINATION:非DLL共享库和模块
RUNTIME DESTINATION:可执行目标和DLL(Windows)样式共享库
package.xml
package.xml 也是一个catkin的package必备文件,它是这个软件包的描述文件,在较早的ROS版本(rosbuild编译系统)中,这个文件叫做 manifest.xml ,用于描述pacakge的基本信息。如果你在网上看到一些ROS项目里包含着 manifest.xml ,那么它多半是hydro版本之前的项目了
pacakge.xml 包含了package的名称、版本号、内容描述、维护人员、软件许可、编译构建工具、编译依赖、运行依赖等信息。实际上 rospack find 、 rosdep 等命令之所以能快速定位和分析出package的依赖项信息,就是直接读取了每一个pacakge中的 package.xml 文件。它为用户提供了快速了解一个pacakge的渠道
pacakge.xml 遵循xml标签文本的写法,由于版本更迭原因,现在有两种格式并存(format1与format2),不过区别不大。
老版本(format1) 的 pacakge.xml 通常包含以下标签
在新版本(format2) 中,包含的标签为:
其他文件
在ROS的pacakge中,还有其他许多常见的文件类型,这里做个总结
launch文件
launch文件一般以.launch或.xml结尾,它对ROS需要运行程序进行了打包,通过一句命令来启动
一般launch文件中会指定要启动哪些package下的哪些可执行程序,指定以什么参数启动,以及一些管理控制的命令
launch文件通常放在软件包的 launch/ 路径中
msg/srv/action文件
ROS程序中有可能有一些自定义的消息/服务/动作文件,为程序的发者所设计的数据结构,这类的文件以 .msg , .srv , .action 结尾,
通常放在package的 msg/ , srv/ , action/ 路径下
urdf/xacro文件
urdf/xacro文件是机器人模型的描述文件,以.urdf或.xacro结尾
它定义了机器人的连杆和关节的信息,以及它们之间的位置、角度等信息,通过urdf文件可以将机器人的物理连接信息表示出来,并在可视化调试和仿真中显示
yaml文件
yaml文件一般存储了ROS需要加载的参数信息,一些属性的配置
通常在launch文件或程序中读取.yaml文件,把参数加载到参数服务器上。
通常把yaml文件存放在 param/ 路径下
dae/stl文件
dae或stl文件是3D模型文件,机器人的urdf或仿真环境通常会引用这类文件,它们描述了机器人的三维模型
相比urdf文件简单定义的性状,dae/stl文件可以定义复杂的模型,可以直接从solidworks或其他建模软件导出机器人装配模型,从而显示出更加精确的外形
rviz文件
rviz文件本质上是固定格式的文本文件,其中存储了RViz窗口的配置(显示哪些控件、视角、参数)
通常rviz文件不需要我们去手动修改,而是直接在RViz工具里保存,下次运行时直接读取
PS:本部分内容主要参考CSDN博主「duganlx」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_40626497/article/details/103741162
最后
以上就是昏睡糖豆为你收集整理的ROS2的基础概念的全部内容,希望文章能够帮你解决ROS2的基础概念所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复