完整课程框架及本篇章节内容
赵虚左RO2讲义:
完整课程 篇级 框架
学习路线
在了解ROS2的优点后,我们可以按照以下步骤来学习ROS2:
1.学习基础概念:首先,了解ROS2的基本概念和术语,如节点、话题、服务等。可以通过阅读官方文档、教程或参加在线课程来学习。
2.安装和配置:根据自己的操作系统,选择适合的ROS2版本,并按照官方提供的安装指南进行安装和配置ROS2环境。可以从源码编译安装或使用二进制安装包进行安装。
3.编写简单程序:通过编写简单的ROS2程序来熟悉ROS2的基本操作和通信机制。可以开始发布和订阅消息、调用服务等常见的ROS2操作,然后逐步扩展到更复杂的功能。
4.学习常用工具:了解ROS2提供的常用工具,如可视化工具Rviz、仿真工具Gazebo、调试工具rqt等。学会如何使用这些工具来调试、验证和可视化ROS2程序。
5.深入学习ROS2功能包:学习常用的ROS2功能包,如导航功能包、感知功能包等,了解它们的用途和原理。可以通过阅读源代码、参与开源项目或实践项目来深入理解和运用这些功能包。
6.实践项目:选择一个感兴趣的项目,结合ROS2进行实践。可以开始简单的项目,逐步增加复杂度和功能。通过实际项目的开发,加深对ROS2的理解和应用,并培养解决实际问题的能力。
本核心篇-章节概览(Ros2的核心通信机制和开发工具)
第一章 Ros2概述与开发环境搭建
1 Ros2简介
1.1 ROS概述
ROS是机器人操作系统(Robot Operating System)的英文缩写,是一个软件,是用于构建机器人应用程序的软件开发工具包。
ROS2是一种面向机器人技术的操作系统。它为开发者提供了丰富的工具和库,用于构建、测试和执行各种复杂的机器人程序。ROS2的出现极大地提高了机器人开发的效率,降低了技术门槛,使得更多的开发者能够参与到机器人技术的创新中来。
ROS2由一系列的软件包组成,包括基础框架、功能包、工具集以及其他的库。它的核心是一个消息传递系统,用于在不同的软件包之间传递信息。ROS2的架构灵活,可以支持从小型桌面机器人到大型工业机器人的各种应用场景。这个平台为开发者提供了构建机器人应用程序所需的各个功能模块,并且开发者能够以“可插拔”的方式组织各个功能模块,无论开发者的程序是用于课堂实验、科学研究、原型设计或是最终产品,ROS都提供了一站式的技术支持。
需要注意的是,ROS本身并不是一个操作系统,而是可以安装在现在已有的操作系统上(Linux、Windows、Mac)上的软件库和工具集。
ROS2生态组成体系:
整个ROS生态由通信(Plumbing)、工具(Tools)、功能(Capabilities)与社区(Community)四大部分组成。
通信(Plumbing)
通信是整个ROS系统的核心实现,是ROS内置的一个消息传递系统,通常称之为middleware(中间件)或Plumbing(管道)。
在构建新的应用程序或使用与硬件交互的软件时,如何实现通信是首当其冲的问题,为此ROS提供了专门的消息传递系统,它可以管理不同节点之间的通信细节,提高开发者的工作效率。这套消息传递系统使用了“面向接口/规范”的编程思想(不面向具体对接对象),可以通过清晰规范的接口,将不同模块分离,从而也将故障隔离。
接口规范可以由开发者自行定义。同时为了方便使用,在ROS中也提供了许多标准的接口,这些标准接口有着广泛应用,比如:将雷达或摄像头数据传输到可视化的用户界面或是传输到定位算法模块,都会使用到标准接口。
工具(Tools)
构建机器人应用程序极具挑战性。开发者除了会遇到一些传统的软件开发问题之外,还需要通过传感器或执行器与物理世界进行异步交互。显而易见的,良好的开发工具可以提高应用程序的开发效率,在ROS中就内置了launch、调试、可视化、绘图、录制回放等一系列工具(非常有用的 调试工具)。这些工具不光可以提高开发效率,还可以在发布产品时直接包含在产品之中。
功能(Capabilities)
ROS生态系统是机器人软件的聚宝盆。无论开发者需要用于GPS的设备驱动程序、用于四足仿生机器人的步行和平衡控制器,还是用于移动机器人的地图系统,ROS都能满足你的需求。从驱动程序到算法,再到用户界面,ROS都提供了相关实现,开发者只需专注于自身应用程序即可。
ROS的目标是提供一站式的技术支持,降低构建机器人应用程序的门槛。ROS希望任何开发者都可以将自己的“创意”变为现实,而无需了解底层软件和硬件的所有内容。
社区(Community)
ROS社区规模庞大、多样且全球化,从学生和业余爱好者到跨国公司和政府机构,各行各业的人和组织都在推动着ROS项目的发展。
该项目的社区中心和中立管家是Open Robotics,它托管共享在线服务(例如ROS官网:https://www.ros.org/),创建和管理分发版本(包括您安装的二进制包),并开发和维护大部分ROS核心软件。Open Robotics还提供与 ROS 相关的工程服务。
1.2 ros2优势
开源
免费
全球化社区
十多年来,ROS项目通过培育由数百万开发人员和用户组成的全球化社区,为机器人技术做出贡献和改进,从而产生了一个庞大的机器人软件生态系统。ROS由该社区开发并为该社区服务,该社区将成为其未来的管理者。
多平台支持
ROS2支持Linux、Windows和macOS以及各种嵌入式平台(通过micro-ROS)并且不同平台都已经通过了官方测试,这意味着通过ROS2可以实现开发、部署后端管理系统和用户界面的无缝衔接。分层支持模型还允许将ROS2移植到诸如实时和嵌入式操作系统等新平台上,以便在获得关注和投资时将ROS2引入和推广到这些新平台中。
可缩短产品上市时间
ROS提供了开发机器人应用程序所需的工具、库和功能,使开发者可以将更多的时间花费在与自身业务相关的工作上。由于它还是开源的,所以开发者可以决定何时何处使用ROS,甚至还可以根据自身需求修改ROS。另外ROS是友好的,不具排他性,开发者可以在ROS和其他机器人软件框架之间自由选择,或者也可以将ROS与其他软件框架集成,以取长补短。
ros2相对于ros1优势
- 去中心化
在ROS1中使用master节点管理调度ROS系统,这存在极大的安全隐患,一旦master节点异常退出,那么会导致整个系统的崩溃。在ROS2中采用了去中心化,各个节点之间无需通过master关联,各个节点都是等态的,可以相互发现彼此。
- 全新通信底层实现
秉着不重复发明轮子的原则,ROS2不再自实现通信底层,而是直接更换为DDS通信,这使得ROS2较之于ROS1无论是通信的实行性、可靠性还是连续性都有大幅度提升。
应用场景更为广泛
ROS1在设计之初有着天生的硬件优势以及局限性:
单机;
工作站级的计算资源;
无实时性要求(有此类需求也可以以特殊方式满足);
出色的网络连接(有线或近距离高带宽无线);
主要用于学术界;
灵活有余而约束不足。
这导致了它的一些先天性缺陷,不能适应新时代的需求,比如:
对多机器人编队支持欠佳;
小型嵌入式平台不能很好的支持ROS;
实时性差;
ROS之间的数据传输受网络质量影响严重;
产品不易落地。
随着ROS2的推出,上述场景的缺陷都得到很大程度的修复。
大量采用新技术、新的设计理念
随着ROS十数年的发展,大量的新技术也产生、改进、成熟并被广泛采用,ROS也开始引入并应用一些新技术,比如:
DDS( Data Distribution Service——数据分发服务);
Zeroconf;
ZeroMQ;
Redis;
WebSockets。
这些新技术为ROS带来了更多的便利,比如:更少的维护成本,却有着更多的功能拓展,并且随着第三方库的升级而持续受益。
此外,ROS2还重构了API系统,改进了ROS1的API在设计上的不足。
2 Ros2安装
Ros2版本说明
ROS2版本发布特点:
-
发布版本与Ubuntu版本对应,生命周期也有Ubuntu保持一致,正常情况下偶数年份发布长支持版(5年),奇数年份发布短支持版(2年)
首先升级本地ubuntu20.04到22.04,然后安装 ros2的humble版
安装colcon构建工具
colcon是一个命令行工具,用于改进编译,测试和使用多个软件包的工作流程。它实现过程自动化,处理需求并设置环境以便于使用软件包。ROS2中便是使用colcon作为包构建工具的,但是ROS2中没有默认安装colcon,需要自行安装,安装命令如下:
sudo apt install python3-colcon-common-extensions
安装完colcon之后,就可以在ROS2中编写应用程序了,下一节我们将介绍ROS2版本的HelloWorld实现。
3 初体验-在终端编写ROS2版本的HelloWorld并测试
需求:编写ros2的程序,程序运行时,可以在终端输出“HelloWorld”。
3.1 工作空间(目录)的创建与编译
mkdir -p ros2_helloworld/src #创建工作空间以及子级目录 src,工作空间名称可以自定义
cd ros2_helloworld #进入工作空间
colcon build #编译
上述指令执行完毕,将创建ros2_helloworld 一级目录。该目录下包含build、install、log、src共四个子级目录,除了src,其他三个是build出来的。架构如下:
可见,3.1和3.2能够快速的帮助我们在ubuntu命令行终端下创建一个 工程目录。我们可以直接专注于源文件的创作。
3.2 创建helloworld功能包
(ROS2的功能包主要有两种,cpp功能包和python功能包)
终端下,进入 ros2_helloworld/src 目录,使用如下指令创建一个 C++功能包:
ros2 pkg create pkg01_helloworld_cpp --build-type ament_cmake --dependencies rclcpp --node-name helloworld
创建功能包命令解析:
ros2 pkg create pkg01_helloworld_cpp //创建一个名为 pkg01_helloworld_cpp 的功能包
--build-type ament_cmake //根据功能包的语言 指定功能包的编译类型(如果是python,则为 ament_python)
--dependencies rclcpp //添加功能包依赖的库 rclcpp (缩写:ros2 client cpp)
--node-name helloworld //设置一个 源文件/可执行程序 名字
执行完毕,在src目录下将生成一个名为pkg01_helloworld_cpp的功能包目录,且目录中已经默认生成了一些子级文件与文件夹。
3.3 编辑源文件
进入pkg01_helloworld_cpp/src目录,该目录下有一helloworld.cpp文件,修改文件内容如下:
可以看出,ros2的helloworld程序主要使用了 rclcpp库
#include "rclcpp/rclcpp.hpp"
int main(int argc, char ** argv)
{
// 初始化 ROS2 客户端资源
rclcpp::init(argc,argv);
// 创建节点。rclcpp::Node类里面有个 make_shared 函数
auto node = rclcpp::Node::make_shared("helloworld_node");//helloworld_node是节点名
// 输出文本
RCLCPP_INFO(node->get_logger(),"hello world!");//输出一般消息日志的函数:RCLCPP_INFO(日志对象,日志信息)
// 对应init,释放ROS2 客户端资源
rclcpp::shutdown();
return 0;
}
疑问:
什么是ROS2程序中的节点?
make_shared?
创建智能指针
什么是hpp?
为什么要 init?
3.4 编辑 编译配置文件(cmake、依赖库xml)
在步骤1创建功能包时所使用的指令已经默认生成且配置了配置文件,不过实际应用中经常需要自己编辑配置文件。所以在此对相关内容做简单介绍,所使用的配置文件主要有两个,分别是功能包下的package.xml与CMakeLists.txt。
1.package.xml
文件内容如下:
下面内容重点关注这部分:
<!-- 所需要依赖 -->
<depend>rclcpp</depend>
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>pkg01_helloworld_cpp</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="ros2@todo.todo">ros2</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<!-- 所需要依赖 -->
<depend>rclcpp</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
注释部分以后需要根据实际的包依赖进行添加或修改。已经有了创建工程时的“所需要的依赖”rclcpp。工程创建完,后续再有需要依赖的库,直接在这里面修改即可。
2.CMakeLists.txt
文件内容如下:
cmake_minimum_required(VERSION 3.8)
project(pkg01_helloworld_cpp)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
# 引入外部依赖包
find_package(rclcpp REQUIRED)
# 1 映射源文件与可执行文件
add_executable(helloworld src/helloworld.cpp)
# 2 设置目标的依赖库
ament_target_dependencies(
helloworld
"rclcpp"
)
# 3 定义安装规则,将生成的可执行程序 helloworld安装在 lib/${PROJECT_NAME} 目录下
install(TARGETS helloworld
DESTINATION lib/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_package()
中文注释部分(1 2 3)以后可能需要根据实际情况修改。
3.5 编译
终端下进入到 工作空间 ros2_helloworld 一级目录下,执行如下指令:
colcon build
可以在cmake指定的 可执行程序安装目录下 找到 helloworld
3.6 执行
终端下进入到工作空间,执行如下指令:
如果不刷新环境变量,会导致 run后找不到可执行的功能包。
source install/setup.bash //刷新工作空间中install/下的setup.bash, 临时环境变量
ros2 run pkg01_helloworld_cpp helloworld //执行功能包pkg01_helloworld_cpp中的 helloworld 可执行文件
程序执行,在终端下将输出文本:"hello world!"。
[输出信息级别-info] [...] [节点名] :日志信息
执行命令优化
终端下,执行ROS某个工作空间下的功能包程序时,都需要先调用
. install/setup.bash
指令配置环境。使用不便。
优化策略是,可以将该指令的调用添加进 bashrc环境变量中,操作格式如下:
echo "source /{工作空间路径}/install/setup.bash" >> ~/.bashrc
示例:
echo "source /home/ros2/ws00_helloworld/install/setup.bash" >> ~/.bashrc
以后再启动终端时,无需手动再手动刷新环境变量,使用更方便。
4 初体验-ROS2集成开发环境vscode中编写helloworld功能包
区别于记事本,vscode中编写helloworld功能包,提高代码编写效率(补齐、纠错、高亮)
vscode中创建ros2功能包
打开已经创建好的工作空间,打开vscode终端,从 3.2步骤开始,可以同样创建一个pkg02功能包,并编译执行。
注意:编译阶段, 进入到工作空间,执行如下指令:colcon build,会把所有的功能包再编译一遍,已经编译过的就没有必要,编译也会浪费时间。可以加参数,选择要编译的功能包 (编译多个功能包则用空格隔开)。
需要修改配置文件案例:
假如工作空间中的功能包 pkg2 的src 需要新增新增一个源码,这个源码也有对应的可执行文件,此时应该如何修改?
1、功能包新增源码
2、修改cmake
3、重新编译功能包,并单独执行新增的源文件
5 正式学习-ROS2体系框架
***5.1 ROS2文件系统
立足ROS2系统架构,如下图所示,ROS2可以划分为三层:
操作系统层(OS Layer)
如前所述,ROS虽然称之为机器人操作系统,但实质只是构建机器人应用程序的软件开发工具包,ROS必须依赖于传统意义的操作系统,目前ROS2可以运行在Linux、Windows、Mac或RTOS上。
中间层(Middleware Layer)
主要由数据分发服务DDS与ROS2封装的关于机器人开发的中间件组成。DDS是一种去中心化的数据通讯方式。ROS2还引入了服务质量管理 (Quality of Service)机制,借助该机制可以保证在某些较差网络环境下也可以具备良好的通讯效果。ROS2中间件则主要由客户端库(如 rclcpp)、DDS抽象层与进程内通讯API构成。
应用层(Application Layer)
是指开发者构建的应用程序,在应用程序中是以功能包为核心的,在功能包中可以包含源码、数据定义、接口等内容。
对于一般开发者而言,工作内容主要集中在应用层,开发者一般通过实现具有某一特定功能的功能包来构建机器人应用程序。
下面我们所介绍的ROS2文件系统主要是指在硬盘上以功能包为核心的工作空间,是“应用程序层面的文件系统”。
5.1.1 工作空间概览
功能包是ROS2应用程序的核心,但是功能包不能直接构建,必须依赖于工作空间,一个ROS2工作空间的目录结构如下:
WorkSpace --- 自定义的工作空间。
|--- build:存储中间文件的目录,该目录下会为每一个功能包创建一个单独子目录。
|--- install:安装目录,该目录下会为每一个功能包创建一个单独子目录。
|--- log:日志目录,用于存储日志文件。
|--- src:用于存储功能包源码的目录。
|-- C++功能包
|-- package.xml:包信息,比如:包名、版本、作者、依赖项。
|-- CMakeLists.txt:配置编译规则,比如源文件、依赖项、目标文件。
|-- src:C++源文件目录。
|-- include:头文件目录。
|-- msg:消息接口文件目录。
|-- srv:服务接口文件目录。
|-- action:动作接口文件目录。
|-- Python功能包
|-- package.xml:包信息,比如:包名、版本、作者、依赖项。
|-- setup.py:与C++功能包的CMakeLists.txt类似。
|-- setup.cfg:功能包基本配置文件。
|-- resource:资源目录。
|-- test:存储测试相关文件。
|-- 功能包同名目录:Python源文件目录。
另外,无论是Python功能包还是C++功能包,除了一些基础目录,都可以自定义一些配置文件相关的目录。
|-- C++或Python功能包
|-- launch:存储launch文件。
|-- rviz:存储rviz2配置相关文件。
|-- urdf:存储机器人建模文件。
|-- params:存储参数文件。
|-- world:存储仿真环境相关文件。
|-- map:存储导航所需地图文件。
|-- ......
上述这些目录也可以定义为其他名称,或者根据需要创建其他一些目录。
5.1.2 源文件说明
在1.3 ROS2快速体验中,实现第一个ROS2程序时,都需要创建节点,无论是C++实现还是Python实现,都是直接实例化的Node对象。
C++实例化Node示例如下:
#include "rclcpp/rclcpp.hpp"
int main(int argc, char ** argv)
{
rclcpp::init(argc,argv);
auto node = rclcpp::Node::make_shared("helloworld_node");//node是智能指针对象
RCLCPP_INFO(node->get_logger(),"hello world!");
rclcpp::shutdown();
return 0;
}
Python实例化Node示例如下:
import rclpy
def main():
rclpy.init()
node = rclpy.create_node("helloworld_py_node")
node.get_logger().info("hello world!")
rclpy.shutdown()
if __name__ == '__main__':
main()
但是在ROS2中,上述编码风格是不被推荐的,更推荐以继承Node类(即作为基类)的方式来创建节点对象。
C++继承Node实现示例如下:
#include "rclcpp/rclcpp.hpp"
class MyNode: public rclcpp::Node{
public:
MyNode():Node("node_name"){ //构造函数初始化列表
RCLCPP_INFO(this->get_logger(),"hello world!");//构造函数中,调用日志输出
}
};
int main(int argc, char *argv[])
{
rclcpp::init(argc,argv);
auto node = std::make_shared<MyNode>();
rclcpp::shutdown();
return 0;
}
Python继承Node实现示例如下:
import rclpy
from rclpy.node import Node
class MyNode(Node):
def __init__(self):
super().__init__("node_name_py")
self.get_logger().info("hello world!")
def main():
rclpy.init()
node = MyNode()
rclpy.shutdown()
之所以继承比直接实例化Node更被推荐,是因为继承方式可以在一个进程内组织多个节点(直接实例化的话,一个进程只能组织一个节点),这对于提高节点间的通信效率是很有帮助的,但是直接实例化则与该功能不兼容。
5.1.3.配置文件说明
在ROS2功能包中,经常需要开发者编辑一些配置文件以设置功能包的构建信息。功能包类型不同,所需修改的配置文件也有所不同。C++功能包的构建信息主要包含在package.xml与CMakeLists.txt中,Python功能包的构建信息则主要包含在package.xml和setup.py中,接下来我们就简单了解一下这些配置文件。
package.xml到底是干什么用的?
ROS本质上就是由一个又一个的package组成的,package可以说是ROS的基本单位。
- 在ament_make的时候它会一个一个的去找package然后生成目标文件。
- 一个package可以有多个节点。
- 判断是否为Package :一个文件夹要被ROS认为是package的话,必须包含以下两个文件:CMakeList.txt和package.xml。即在一个ROS功能包中,CMakeList.txt和package.xml是不可缺少的两个文件。
CMakeLists.txt规定catkin编译的规则。(例如:源文件,依赖项,目标文件)。而package.xml文件定义了package的属性。(例如:包名,版本号,作者,依赖等等),二者缺一不可。
————————————————
原文链接:https://blog.csdn.net/wangxiao7474/article/details/109840779
package.xml(包清单):
不管是何种类型的功能包,package.xml的格式都是类似的,在该文件中包含了包名、版本、作者、依赖项的信息,package.xml可以为colcon构建工具确定功能包的编译顺序。一个简单的package.xml示例如下:
<?xml version="1.0"?> <!--版本号-->
<package format="2"> <!--根标签--> <!--package.xml文件从旧版本格式1format = "1"更新到了格式2format = "2"其中有些内容进行了更改升级。-->
<name>beginner_tutorials</name> <!--包名-->
<version>0.0.0</version>
<description>The beginner_tutorials package</description> <!--描述标签-->
<maintainer email="lh@TODO">lh</maintainer> <!--维护者的名字和联系方式(一般是邮箱)-->
<license>BSD</license>
<buildtool_depend>ament_cmake</buildtool_depend> <!--所依赖的编译工具-->
<build_depend>roscpp</build_depend> <!--编译依赖项-->
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_export_depend>roscpp</build_export_depend> <!--编译导出项-->
<build_export_depend>rospy</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>roscpp</exec_depend> <!--执行依赖项-->
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
</package>
1.根标签
<package>:该标签为整个xml文件的根标签,format属性用来声明文件的格式版本。
2.元信息标签
<name>:包名;
<version>:包的版本号;
<description>:包的描述信息;
<maintainer>:维护者信息;
<license>: 发布代码的软件许可证(例如GPL,BSD,ASL)。;
<url>:包的介绍网址;
<author>:包的作者信息。
3.依赖项
<buildtool_depend>:声明编译工具依赖(c++ 就是ament_cmake);
- <build_depend>: 构建依赖关系,使用某种特定的依赖关系来构建包。
- <build_export_depend> :构建导出依赖关系,如果功能包导出头文件,则其他包可能需要这个包,就应该使用这个标签,用来传递声明。
- <exec_depend>:执行依赖关系指定在此程序包中运行代码所需的软件包。如动态链接库、可执行文件、Python模块、脚本文件等。
- <depend> :等于以上三种depend的合集,通常使用它添加ROS功能包,是常用而简便的方法。
<test_depend>:声明测试依赖;
<doc_depend>:声明构建文档依赖。
package.xml和 CMakeLists.txt作用区别与联系:
package.xml的核心内容:
CMakeLists.txt:
C++功能包中需要配置CMakeLists.txt文件,该文件描述了如何构建C++功能包,一个简单的CMakeLists.txt示例如下:
# 声明cmake的最低版本
cmake_minimum_required(VERSION 3.8)
# 包名,需要与package.xml中的包名一致
project(pkg01_helloworld_cpp)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
# 引入外部依赖包
find_package(rclcpp REQUIRED)
# 映射源文件与可执行文件
add_executable(helloworld src/helloworld.cpp)
# 设置目标依赖库
ament_target_dependencies(
helloworld
"rclcpp"
)
# 定义安装规则
install(TARGETS helloworld
DESTINATION lib/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_package()
cmake_minimum_required() #CMake的最低版本号
project() #项目名称
find_package() #找到编译需要的其他CMake/Catkin package
catkin_python_setup() #catkin新加宏,打开catkin的Python Module的支持
add_message_files() #catkin新加宏,添加自定义Message文件
add_service_files() #catkin新加宏,添加自定义Service文件
add_action_files() #catkin新加宏,添加自定义Action文件
generate_message() #catkin新加宏,生成不同语言版本的msg/srv/action接口
catkin_package() #catkin新加宏,生成当前package的cmake配置,供依赖本包的其他软件包调用
add_library() #生成库
add_executable() #生成可执行二进制文件
add_dependencies() #定义目标文件依赖于其他目标文件,确保其他目标已被构建
target_link_libraries() #链接
catkin_add_gtest() #catkin新加宏,生成测试
install() #生成可安装目标
在示例中关于文件的使用已经通过注释给出了简短说明,其实关于CMakeLists.txt的配置是比较复杂的,后续随着学习的深入,还会给出更多的补充说明。
setup.py
Python功能包中需要配置setup.py文件(和前面1 的package.xml),该文件描述了如何构建Python功能包。
5.1.4 操作命令(都是在工作空间一级目录下执行,只有写源码才会进入功能包级目录)
下面大佬总结的,可参考:
ROS2的文件系统核心是功能包,我们可以通过编译指令colcon
和ROS2内置的工具指令ros2
来实现功能包的创建、编译、查找与执行等相关操作。
1.创建功能包
新建功能包语法如下:
ros2 pkg create 包名 --build-type 构建类型 --dependencies 依赖列表 --node-name 可执行程序名称
格式解释:
-
--build-type:是指功能包的构建类型,有cmake、ament_cmake(默认,cmake的增强版)、ament_python三种类型可选;
-
--dependencies:所依赖的功能包列表(如果创建功能包时候不设置,就要手动去xml里面修改);
-
--node-name:可执行程序的名称,会自动生成对应的源文件并生成配置文件。
2.编译
编译功能包语法如下:
colcon build
或
colcon build --packages-select 功能包列表
前者会构建工作空间下的所有功能包,后者可以构建指定功能包。
注意!!!:功能包在工作空间的src目录下面;编译、查找、执行都是在工作空间下面
3.查找
在ros2 pkg
命令下包含了多个查询功能包相关信息的参数。
ros2 pkg executables [包名] # 输出所有功能包及功能包中的可执行程序或(带参数)指定功能包下的可执行程序。
ros2 pkg list # 列出当前系统所有功能包,也可以跟 |grep -i xxx 筛选
ros2 pkg prefix 包名 # 列出功能包路径
ros2 pkg xml # 输出功能包的package.xml内容
4.执行
执行命令语法如下:
ros2 run 功能包 可执行程序 参数
小提示:
可以通过
命令 -h
或命令 --help
来获取命令的帮助文档。如:
ros2 pkg -h
5.2 ROS2核心模块
通信与工具是ROS2的核心模块,也是我们以后学习和工作的重点所在,本节将会介绍通信和工具中涉及到的一些知识点。
*5.2.1.通信模块
通信模块是整个ROS2架构中的重中之重,比如你可能想要了解在ROS2中是如何控制机器人底盘运动的?雷达、摄像头、imu、GPS等这些传感器数据是如何传输到ROS2系统的?人机交互时调用者如何下发指令,机器人又是如何反馈数据的?导航、机械臂等系统性实现不同模块之间是如何交互数据的......等等,其实这些都离不开通信模块。另外,开发者构建应用程序时,通信部分在工作内容中占有相当大的比重。
5.2.2功能包应用
功能包的应用主要有三种方式:
5.2.2.1.二进制安装
ROS官方或社区提供的功能包可以很方便的通过二进制方式安装,安装命令如下:
sudo apt install ros-ROS2版本代号-功能包名称
小提示:
可以调用
apt search ros-ROS2版本代号(如humble)-* | grep -i 关键字
格式的命令,根据关键字查找所需的功能包,然后自己下载。
5.2.2.2.源码安装
也可以直接下载官方、社区或其他第三方提供的源代码,一般我们会从github获取源码,下载命令如下:
git clone 仓库地址
源码下载后,需要自行编译。
案例:github上下载ros2的小乌龟教学案例功能包,修改源码,并编译运行流程
1、打开github找到案例
2、下载功能包到本地,并移动到自己的工作空间
注意选对代码分支,然后git下载
3、src目录下,寻找源码,并修改点儿显而易见的东西
4、重新编译,运行。
5.2.2.3.自实现
开发者按照业务需求自己编写功能包实现。
5.2.3.分布式
ROS2是一个分布式架构,不同的ROS2设备之间可以方便的实现通信,这在多机器人设备协同中是极其重要的。
5.2.4.终端命令与rqt
在ROS2中提供了丰富的命令行工具,可以方便的调试程序、提高开发效率。
示例1:使用命令行工具在turtlesim_node中生成一只新乌龟。
rqt是一个图形化工具,它的功能与命令行工具类似,但是图形化的交互方式更为友好。
示例2:使用rqt在turtlesim_node中生成一只新乌龟。
5.2.5.launch文件
通过launch文件,可以批量的启动ROS2节点,这是在构建大型项目时启动多节点的常用方式。
示例:一次性启动多个turtlesim_node节点。
5.2.6.TF坐标变换
TF坐标变换可以实现机器人不同部件或不同机器人之间的相对位置关系的转换。
示例1:发布机器人不同部件之间的坐标系关系。
示例2:使用turtlesim_node模拟多机器人编队。
5.2.7.可视化
ROS2内置了三维可视化工具rviz2,它可以图形化的方式显示机器人模型或显示机器人系统中的一些抽象数据。
示例1:显示传感器数据。
示例2:显示机器人模型。
5.3 ROS2技术支持
ROS社区提供了多种技术支持机制,主要包括:包文档、问答、论坛、包索引以及问题跟踪,每种机制都有自己的用途,合适的选择技术支持机制可以避免问题的重复提问、减少问题解决时间并对新思想的交流很有帮助。
ROS包文档
ROS核心包的文档以及包的特定内容托管在ROS包文档上,可以查找到ROS的官方教程、文档和API文档。
ROS问答
如果在学习和工作中,遇到解决不了的问题,那么可以访问ROS问答,在ROS问答模块已经涉及到60000多个问题且大部分都给出了答案。开发者可以先搜索遇到的问题,如果该问题尚未提出,那么可以自行发布相关问题(在发布之前请先查看问题发布指南)。
ROS论坛
在ROS论坛我们可以了解ROS社区的最新动态。请注意:论坛是发布公告、新闻和讨论共同爱好的地方,请不要在此提出技术问题或提交异常报告。
ROS包索引
在ROS包索引可以查找特定功能包的信息。
问题跟踪器
当用户发现系统BUG或者想请求新功能时,可以在问题跟踪器上提交报告。如果是报告BUG,那么请务必提供问题的详细描述、问题产生的环境以及可能有助于开发人员重现问题的任何细节,最好能够提供调试回溯。
除了上述多种技术支持之外,ROS社区还会举办一年一度的ROSCon(ROS开发者大会),ROSCon为所有级别的 ROS 开发人员(从初学者到专家)提供了一个机会,所有的开发者可以建立联系、相互学习、分享想法或是向专家请教。ROSCon一般为期两天,主要包括技术讲座和一些ROS教程,期间将介绍新的工具和库,也会介绍已有的工具和库的深层次知识。
ROS官方的目标是让ROSCon代表整个ROS社区,这个社区是全球性和多样化的。无论你是谁,无论你做什么,无论在哪,只要对ROS感兴趣,那么都希望能够加入ROSCon。尤其鼓励女性、少数派成员和其他不具代表性的群体成员参加ROSCon。