1.1 ROS2简介
场景
机器人是一种高度复杂的系统性实现,机器人设计包含了机械结构设计、机械加工、硬件设计、嵌入式软件设计、上层软件设计等诸多模块,是各种硬件与软件的有机结合,甚至可以说机器人系统是当今工业体系的集大成者。机器人体系是相当庞大的,其复杂度之高,以至于没有任何个人、组织甚至公司能够独立完成系统性的机器人研发生产任务。
那么问题随之而来:既然机器人实现如此困难,那么我们应该如何开展相关工作呢?
一种合适的策略是——合作。让机器人研发者专注于自己擅长的领域,其他模块则直接复用相关领域更专业研发团队的实现,当然自身的研究也可以被他人继续复用。这种基于“复用”的分工协作,遵循了不重复发明轮子的原则,显然是可以大大提高机器人的研发效率的,尤其是随着机器人硬件越来越丰富,软件库越来越庞大,这种复用性和模块化开发需求也愈发强烈。
在此大背景下,便诞生了ROS。ROS是一套机器人通用软件框架,可以提升功能模块的复用性,并且随着ROS2的推出,ROS日臻完善,是机器人软件开发的不二之选。
概念
ROS(Robot Operating System)是用于构建机器人应用程序的软件开发工具包。ROS是开源的,它由一组软件库和若干工具组成。
在机器人领域,ROS是一个标准软件平台,这个平台为开发者提供了构建机器人应用程序所需的各个功能模块,并且开发者能够以“可插拔”的方式组织各个功能模块,无论开发者的程序是用于课堂实验、科学研究、原型设计或是最终产品,ROS都提供了一站式的技术支持。
另外需要注意的是,ROS虽然字面意思是机器人操作系统,但是它并非经典意义上的操作系统,更准确的讲ROS是一个 SDK(Software Development Kit)也即软件开发工具包。
作用
秉着“不要重复发明轮子”的原则,通过ROS可以复用已有功能并方便快捷的拓展新功能。
1.1.1 ROS2发展历程
1.起源
2007年,一家名为柳树车库(Willow Garage)的机器人公司发布了ROS,ROS集开源、免费、高复用、低耦合、工具丰富等等诸多优势于一身,一经推出便迅速吸引了大量的开发者、科研人员、硬件供应商的加入,形成了稳定且多样的机器人生态,水到渠成的ROS也成为了机器人领域的主流软件框架并流行至今。
但是自ROS诞生的十几年来,不管是机器人相关软件、硬件还是ROS社区都发生了天翻地覆的变化,加之ROS1存在一些设计上的先天性缺陷,各种内外因素叠加下,导致ROS1在许多应用场景下都已经显得力不从心了。此背景下,官方于2017正式推出了新一代机器人操作系统——ROS2,ROS2基于全新的设计框架,保留了ROS1的优点并改进其缺陷,ROS2的目标是适应新时代的新需求。
2.发行版本
ROS发行版是一组版本化的ROS功能包,它类似于Linux发行版(例如 Ubuntu)。ROS发行版的目的是让开发人员可以在一个相对稳定的代码库上工作,直到新的发行版推出。
以下列表为ROS2各不同发布版本的简单说明。
ROS2版本发布特点:
发布版本与Ubuntu版本对应,生命周期也有Ubuntu保持一致,正常情况下偶数年份发布长支持版(5年),奇数年份发布短支持版(2年);
版本名称由形容词+名词的格式组成,这一点与Ubuntu版本名称规则一致;
正常情况下,每年的5月23日,世界海龟日发布新版本。
需要另外说明的是:
官方于2020年发布了ROS1的最终版本,并将于2025年终止ROS1的维护。而早在2017年就已经推出了ROS2的第一个正式版本,并且随着ROS2的不断完善,于2022年又推出ROS2的第一个5年长支持版。对于ROS而言,这是一个里程碑式的事件,这意味着自此开始,ROS2将全面取代ROS1。
1.1.2 ROS2组成体系
整个ROS生态由通信(Plumbing)、工具(Tools)、功能(Capabilities)与社区(Community)四大部分组成。


通信(Plumbing)
通信是整个ROS系统的核心实现,是ROS内置的一个消息传递系统,通常称之为middleware(中间件)或Plumbing(管道)。
在构建新的应用程序或使用与硬件交互的软件时,如何实现通信是首当其冲的问题,为此ROS提供了专门的消息传递系统,它可以管理不同节点之间的通信细节,提高开发者的工作效率。这套消息传递系统使用了“面向接口”的编程思想,可以通过清晰规范的接口,将不同模块分离,从而也将故障隔离。使得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.1.3 ROS2优势
1.ROS与其他机器人软件框架比较
ROS是构建机器人的最快捷方式!
1.1 开源
ROS一直是开源的,并且将永远是开源的,以确保全世界的爱好者、开发人员可以自由、不受限制地访问高质量、一流、功能齐全的机器人SDK。另外官方也在其他开源项目之上构建ROS,ROS会尽可能的利用并遵循开放标准(例如OMG的DDS)。
1.2 免费
官方鼓励用户对ROS做出开源贡献,也欢迎提出宝贵意见,但不干涉开发者将ROS集成进非开源软件,不反对将ROS集成进专有产品。
1.3 多平台支持
ROS2支持Linux、Windows和macOS以及各种嵌入式平台(通过micro-ROS)并且不同平台都已经通过了官方测试,这意味着通过ROS2可以实现开发、部署后端管理系统和用户界面的无缝衔接。分层支持模型还允许将ROS2移植到诸如实时和嵌入式操作系统等新平台上,以便在获得关注和投资时将ROS2引入和推广到这些新平台中。
1.4 应用领域广泛
ROS可以在各种机器人应用中使用,从室内到室外,从家用到汽车,从水下到太空,从消费市场到工业领域,ROS都可以独当一面。
1.5 全球化社区
十多年来,ROS项目通过培育由数百万开发人员和用户组成的全球化社区,为机器人技术做出贡献和改进,从而产生了一个庞大的机器人软件生态系统。 ROS由该社区开发并为该社区服务,该社区将成为其未来的管理者。
1.6 可缩短产品上市时间
ROS提供了开发机器人应用程序所需的工具、库和功能,使开发者可以将更多的时间花费在与自身业务相关的工作上。由于它还是开源的,所以开发者可以决定何时何处使用ROS,甚至还可以根据自身需求修改ROS。另外ROS是友好的,不具排他性,开发者可以在ROS和其他机器人软件框架之间自由选择,或者也可以将ROS与其他软件框架集成,以取长补短。
1.7 广泛的行业支持
业界对ROS的支持非常强大。除了在ROS上开发产品外,来自世界各地的大大小小的公司都在投入资源为ROS做出开源贡献。
1.8 业界肯定
整个机器人行业都依赖于ROS。ROS是教授机器人技术的标准,是大多数机器人研究的基础,从单个学生项目到多机构合作再到大型竞赛,ROS都占据着主导地位。世界各地不计其数的机器人内部都运行着ROS,仅在自主移动机器人 (AMR) 中,ROS就帮助创造了数十亿美元的价值。
2.ROS2较之于ROS1的优势
ROS2是全新一代机器人操作系统,不只是功能增强的ROS1。
2.1 去中心化
在ROS1中使用master节点管理调度ROS系统,这存在极大的安全隐患,一旦master节点异常退出,那么会导致整个系统的崩溃。在ROS2中采用了去中心化,各个节点之间无需通过master关联,各个节点都是等态的,可以相互发现彼此。
2.2 全新通信底层实现
秉着不重复发明轮子的原则,ROS2不再自实现通信底层,而是直接更换为DDS通信,这使得ROS2较之于ROS1无论是通信的实行性、可靠性还是连续性都有大幅度提升。
2.3 应用场景更为广泛
ROS1在设计之初有着天生的硬件优势以及局限性:
单机;
工作站级的计算资源;
无实时性要求(有此类需求也可以以特殊方式满足);
出色的网络连接(有线或近距离高带宽无线);
主要用于学术界;
灵活有余而约束不足。
这导致了它的一些先天性缺陷,不能适应新时代的需求,比如:
对多机器人编队支持欠佳;
小型嵌入式平台不能很好的支持ROS;
实时性差;
ROS之间的数据传输受网络质量影响严重;
产品不易落地。
随着ROS2的推出,上述场景的缺陷都得到很大程度的修复。
2.4 大量采用新技术、新的设计理念
随着ROS十数年的发展,大量的新技术也产生、改进、成熟并被广泛采用,ROS也开始引入并应用一些新技术,比如:
DDS( Data Distribution Service——数据分发服务);
Zeroconf;
ZeroMQ;
Redis;
WebSockets。
这些新技术为ROS带来了更多的便利,比如:更少的维护成本,却有着更多的功能拓展,并且随着第三方库的升级而持续受益。
此外,ROS2还重构了API系统,改进了ROS1的API在设计上的不足。
1.2 ROS2安装
本节主要介绍如何在Ubuntu 操作系统上安装ROS2,所以在安装之前请先准备好与ROS2版本相匹配的Ubuntu操作系统。
1.2.1 安装ROS2
整体而言,ROS2的安装步骤不算复杂,大致步骤如下:
准备1:设置语言环境;
准备2:启动Ubuntu universe存储库;
设置软件源;
安装ROS2;
配置环境。
请注意:虽然安装比较简单,但是安装过程比较耗时,需要耐心等待。
1.准备1:设置语言环境
请先检查本地语言环境是否支持UTF-8编码,可调用如下指令检查并设置UTF-8编码:
locale # 检查是否支持 UTF-8
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8
locale # 验证设置是否成果
注意:语言环境可以不同,但必须支持UTF-8编码。
2.准备2:启动Ubuntu universe存储库
常用的启动Ubuntu universe存储库方式有两种:图形化操作与命令行操作。
方式1:图形化操作
请打开软件与更新(Software & Updates)窗口,确保启动了universe存储库,以保证可以下载”社区维护的免费和开源软件“,操作示例如下:

方式2:命令行操作
首先,通过如下命令检查是否已经启动了Ubuntu universe存储库:
apt-cache policy | grep universe
500 http://us.archive.ubuntu.com/ubuntu jammy/universe amd64 Packages
release v=22.04,o=Ubuntu,a=jammy,n=jammy,l=Ubuntu,c=universe,b=amd64
如果没有如上所示的输出,那么请调用如下命令启动Ubuntu universe存储库:
sudo apt install software-properties-common
sudo add-apt-repository universe
3.设置软件源
先将ROS 2 apt存储库添加到系统,用apt授权我们的GPG密钥:
sudo apt update && sudo apt install curl gnupg lsb-release
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
提示:如果抛出连接 raw.githubusercontent.com 失败的异常信息,解决方式请参考本节最后部分补充2内容。
然后将存储库添加到源列表:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
4.安装ROS2
首先更新apt存储库缓存:
sudo apt update
然后升级已安装的软件(ROS2软件包建立在经常更新的Ubuntu系统上,在安装新软件包之前请确保您的系统是最新的):
sudo apt upgrade
安装桌面版ROS2(建议),包含:ROS、RViz、示例与教程,安装命令如下:
sudo apt install ros-humble-desktop
或者,也可以安装基础版ROS2,包含:通信库、消息包、命令行工具,但是没有 GUI 工具,安装命令如下:
sudo apt install ros-humble-ros-base
5.配置环境
终端下,执行ROS2程序时,需要调用如下命令配置环境:
source /opt/ros/humble/setup.bash
每次新开终端时,都得执行上述命令,或者也可以执行如下命令,将配置环境指令写入 ”~/.bashrc“ 文件,那么每次新启动终端时,不需要在手动配置环境:
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
到目前为止,ROS2就已经安装且配置完毕了。
补充1:关于卸载(谨慎操作)
ROS2安装完毕之后,如果想卸载ROS2,可以执行如下命令:
sudo apt remove ~nros-humble-* && sudo apt autoremove
还可以再删除ROS2对应的存储库:
sudo rm /etc/apt/sources.list.d/ros2.list
sudo apt update
sudo apt autoremove
# Consider upgrading for packages previously shadowed.
sudo apt upgrade
补充2:关于 raw.githubusercontent.com 连接失败的处理
安装ROS2过程中,执行到步骤3也即设置软件源时,可能会抛出异常。
异常提示:curl: (7) Failed to connect to raw.githubusercontent.com port 443: 拒绝连接。
异常原因:DNS被污染。
解决思路:查询错误提示中域名的IP地址,然后修改 /etc/hosts 文件,添加域名与IP映射。
具体实现:
1.访问 https://www.ipaddress.com/ 并输入域名 raw.githubusercontent.com,查询 ip 地址。
查询到的ip地址可能有多个,记录任意一个地址即可。
2.修改/etc/hosts文件:
sudo gedit /etc/hosts
添加ip和域名映射到hosts文件,保存并退出。
操作完毕后,终端再次运行安装指令即可正常执行
1.2.2 测试ROS2
在ROS2中已经内置了一些案例,安装完毕之后,就可以运行这些案例,以测试ROS2的安装与配置是否正常,在此,我们选用ROS2内置的小乌龟案例,具体操作如下。
1.打开两个终端(可以使用快捷键Ctrl + Alt + T);
2.终端1中输入指令:ros2 run turtlesim turtlesim_node,执行完毕,会启动一个绘有小乌龟的窗口;
3.终端2中输入指令:ros2 run turtlesim turtle_teleop_key,执行完毕,可以在此终端中通过键盘控制乌龟运动。
运行结果示例如下:


注意:在使用键盘控制乌龟运动时,需要保证光标聚焦在终端2中,否则乌龟无响应。
1.2.3 安装colcon构建工具
colcon是一个命令行工具,用于改进编译,测试和使用多个软件包的工作流程。它实现过程自动化,处理需求并设置环境以便于使用软件包。ROS2中便是使用colcon作为包构建工具的,但是ROS2中没有默认安装colcon,需要自行安装,安装命令如下:
sudo apt install python3-colcon-common-extensions
安装完colcon之后,就可以在ROS2中编写应用程序了,下一节我们将介绍ROS2版本的HelloWorld实现。
1.3 ROS2快速体验
ROS2中涉及的编程语言以C++和Python为主,ROS2中的大多数功能两者都可以实现,在本系列教程中,如无特殊情况,每一个案例也都会分别使用C++和Python两种方案演示。本节我们将介绍一个最基本的案例——ROS2版本的HelloWorld,通过学习本节内容,你可以了解ROS2程序的编写、编译与执行流程。
1.3.1 案例简介
1.需求
编写ROS2程序,要求程序运行时,可以在终端输出文本"Helo World"。
2.准备
无论是使用C++还是Python编写ROS2程序,都需要依赖于工作空间,在此,我们先实现工作空间的创建与编译,打开终端,输入如下指令:
mkdir -p ws00_helloworld/src #创建工作空间以及子级目录 src,工作空间名称可以自定义
cd ws00_helloworld #进入工作空间
colcon build #编译
上述指令执行完毕,将创建ws00_helloworld目录,且该目录下包含build、install、log、src共四个子级目录。
3.流程简介
工作空间创建完毕后,我么可以在工作空间下的src目录中编写C++或Python程序,且两种语言的实现流程大致一致,主要包含如下步骤:
创建功能包;
编辑源文件;
编辑配置文件;
编译;
执行。
下面两节我们会介绍具体的实现细节。
1.3.2 HelloWorld(C++)
1.创建功能包
终端下,进入ws00_helloworld/src目录,使用如下指令创建一个C++功能包:
ros2 pkg create pkg01_helloworld_cpp --build-type ament_cmake --dependencies rclcpp --node-name helloworld
执行完毕,在src目录下将生成一个名为pkg01_helloworld_cpp的目录,且目录中已经默认生成了一些子级文件与文件夹。
2.编辑源文件
进入pkg01_helloworld_cpp/src目录,该目录下有一helloworld.cpp文件,修改文件内容如下:
#include "rclcpp/rclcpp.hpp"
int main(int argc, char ** argv)
{
// 初始化 ROS2
rclcpp::init(argc,argv);
// 创建节点
auto node = rclcpp::Node::make_shared("helloworld_node");
// 输出文本
RCLCPP_INFO(node->get_logger(),"hello world!");
// 释放资源
rclcpp::shutdown();
return 0;
}
3.编辑配置文件
在步骤1创建功能包时所使用的指令已经默认生成且配置了配置文件,不过实际应用中经常需要自己编辑配置文件,所以在此对相关内容做简单介绍,所使用的配置文件主要有两个,分别是功能包下的package.xml与CMakeLists.txt。
1.package.xml
文件内容如下:
<?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>
注释部分以后需要根据实际的包依赖进行添加或修改。
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)
# 映射源文件与可执行文件
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()
中文注释部分以后可能需要根据实际情况修改。
4.编译
终端下进入到工作空间,执行如下指令:
colcon build
5.执行
终端下进入到工作空间,执行如下指令:
. install/setup.bash
ros2 run pkg01_helloworld_cpp helloworld
程序执行,在终端下将输出文本:"hello world!"。
1.3.3 HelloWorld(Python)
1.创建功能包
终端下,进入ws00_helloworld/src目录,使用如下指令创建一个python功能包:
ros2 pkg create pkg02_helloworld_py --build-type ament_python --dependencies rclpy --node-name helloworld
执行完毕,在src目录下将生成一个名为pkg02_helloworld_py的目录,且目录中已经默认生成了一些子级文件与文件夹。
2.编辑源文件
进入pkg02_helloworld_py/pkg02_helloworld_py目录,该目录下有一helloworld.py文件,修改文件内容如下:
import rclpy
def main():
# 初始化 ROS2
rclpy.init()
# 创建节点
node = rclpy.create_node("helloworld_py_node")
# 输出文本
node.get_logger().info("hello world!")
# 释放资源
rclpy.shutdown()
if __name__ == '__main__':
main()
3.编辑配置文件
与C++类似的,在步骤1创建功能包时所使用的指令也已经默认生成且配置了配置文件,不过实际应用中经常需要自己编辑配置文件,所以在此对相关内容做简单介绍,所使用的配置文件主要有两个,分别是功能包下的package.xml与setup.py。
1.package.xml
文件内容如下:
<?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>pkg02_helloworld_py</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="ros2@todo.todo">ros2</maintainer>
<license>TODO: License declaration</license>
<!-- 所需要依赖 -->
<depend>rclpy</depend>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
注释部分以后需要根据实际的包依赖进行添加或修改。
2.setup.py
文件内容如下:
from setuptools import setup
package_name = 'pkg02_helloworld_py'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='ros2',
maintainer_email='ros2@todo.todo',
description='TODO: Package description',
license='TODO: License declaration',
tests_require=['pytest'],
entry_points={
'console_scripts': [
# 映射源文件与可执行文件
'helloworld = pkg02_helloworld_py.helloworld:main'
],
},
)
注释部分以后可能需要根据实际情况修改。
4.编译
终端下进入到工作空间,执行如下指令:
colcon build
5.执行
终端下进入到工作空间,执行如下指令:
. install/setup.bash
ros2 run pkg02_helloworld_py helloworld
程序执行,在终端下将输出文本:"hello world!"。
1.3.4 运行优化
每次终端中执行工作空间下的节点时,都需要调用. install/setup.bash指令,使用不便,优化策略是,可以将该指令的调用添加进~/setup.bash,操作格式如下:
echo "source /{工作空间路径}/install/setup.bash" >> ~/.bashrc
示例:
echo "source /home/ros2/ws00_helloworld/install/setup.bash" >> ~/.bashrc
以后再启动终端时,无需手动再手动刷新环境变量,使用更方便。
1.4 ROS2集成开发环境搭建
和大多数开发环境一样,理论上,在ROS2中,只需要记事本就可以编写基本的ROS2程序,但是工欲善其事必先利其器,为了提高开发效率,可以先安装集成开发工具和使用方便的工具:IDE、终端、git。
1.4.1 安装VSCode
VSCode全称Visual Studio Code,是微软推出的一款轻量级代码编辑器,免费、开源而且功能强大。它支持几乎所有主流的程序语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比Diff、GIT 等特性,支持插件扩展,并针对网页开发和云端应用开发做了优化。软件跨平台支持Win、Mac以及Linux。
1.下载
vscode下载:https://code.visualstudio.com/Download。
历史版本下载链接:https://code.visualstudio.com/updates。
2.vscode 安装与卸载
2.1 安装
方式1:双击安装即可(或右击选择安装);
方式2:sudo dpkg -i xxxx.deb。
2.2 卸载
sudo dpkg --purge code
3.VSCode启动
VSCode启动也比较简单,可以直接在Show Applications(显示应用程序) 中搜索VSCode直接启动(也可以将其添加到收藏夹)。
或者,也可以在终端下进入需要被打开的目录(比如:前面创建的ROS2工作空间ws00_helloworld),然后输入命令:code .。
4.VSCode插件
VSCode支持插件扩展,依赖于VSCode丰富多样的插件,可以大大提高程序开发效率,为了方便ROS2程序开发,我们也需要安装一些插件。
首先点击侧边栏的Extensions(插件)选项或者使用快捷键Ctrl+Shift+X打开插件窗口,本课程建议安装的插件如下:

当然,上述只是部分推荐插件,大家可以根据自身需求安装其他扩展。
5.VSCode配置
在VSCode中,cpp文件中的#include "rclcpp/rclcpp.hpp"包含语句会抛出异常,这是因为没有设置VSCode配置文件中 includepath属性,可以按照如下步骤解决此问题:


将鼠标移到错误提示语句,此时会出现弹窗;
点击弹窗中的快速修复,会有新的弹窗,再点击
编辑"includePath"设置;在新页面中,包含路径属性对应的文本域中,换行输入被包含的路径
/opt/ros/humble/include/**。
至此,问题修复。
VSCode安装并配置完毕后,大家就可以在其中编写ROS2程序了。当然为了提高编码效率,我们会经常性的使用到一些快捷键,VSCode的快捷键可以在菜单栏的“帮助”中查看。
1.4.2 安装终端
在ROS2中,需要频繁的使用到终端,且可能需要同时开启多个窗口,推荐一款较为好用的终端:Terminator。效果如下:


1.安装
sudo apt install terminator
2.启动
可以直接在Show Applications(显示应用程序) 中搜索terminator直接启动(也可以将其添加到收藏夹);或者,也可以直接使用快捷键Ctrl+Alt+T启动。
3.Terminator 常用快捷键
第一部份:关于在同一个标签内的操作
Alt+Up //移动到上面的终端
Alt+Down //移动到下面的终端
Alt+Left //移动到左边的终端
Alt+Right //移动到右边的终端
Ctrl+Shift+O //水平分割终端
Ctrl+Shift+E //垂直分割终端
Ctrl+Shift+Right //在垂直分割的终端中将分割条向右移动
Ctrl+Shift+Left //在垂直分割的终端中将分割条向左移动
Ctrl+Shift+Up //在水平分割的终端中将分割条向上移动
Ctrl+Shift+Down //在水平分割的终端中将分割条向下移动
Ctrl+Shift+S //隐藏/显示滚动条
Ctrl+Shift+F //搜索
Ctrl+Shift+C //复制选中的内容到剪贴板
Ctrl+Shift+V //粘贴剪贴板的内容到此处
Ctrl+Shift+W //关闭当前终端
Ctrl+Shift+Q //退出当前窗口,当前窗口的所有终端都将被关闭
Ctrl+Shift+X //最大化显示当前终端
Ctrl+Shift+Z //最大化显示当前终端并使字体放大
Ctrl+Shift+N or Ctrl+Tab //移动到下一个终端
Ctrl+Shift+P or Ctrl+Shift+Tab //Crtl+Shift+Tab 移动到之前的一个终端
第二部份:有关各个标签之间的操作
F11 //全屏开关
Ctrl+Shift+T //打开一个新的标签
Ctrl+PageDown //移动到下一个标签
Ctrl+PageUp //移动到上一个标签
Ctrl+Shift+PageDown //将当前标签与其后一个标签交换位置
Ctrl+Shift+PageUp //将当前标签与其前一个标签交换位置
Ctrl+Plus (+) //增大字体
Ctrl+Minus (-) //减小字体
Ctrl+Zero (0) //恢复字体到原始大小
Ctrl+Shift+R //重置终端状态
Ctrl+Shift+G //重置终端状态并clear屏幕
Super+g //绑定所有的终端,以便向一个输入能够输入到所有的终端
Super+Shift+G //解除绑定
Super+t //绑定当前标签的所有终端,向一个终端输入的内容会自动输入到其他终端
Super+Shift+T //解除绑定
Ctrl+Shift+I //打开一个窗口,新窗口与原来的窗口使用同一个进程
Super+i //打开一个新窗口,新窗口与原来的窗口使用不同的进程1.4.3 安装git
Git 是一个免费和开源的分布式版本控制系统,旨在高速高效的处理从小型到大型项目的所有内容。在Ubuntu下可以调用如下命令安装git:
sudo apt install git
在本教程中会经常使用git clone 仓库地址的方式来将Git仓库拷贝到本地。
关于git工具使用可以在终端下输入:git --help查看帮助文档。关于git的其他详细信息请参考:https://git-scm.com/
1.5 ROS2体系框架
在1.1.2 ROS2组成体系一节中,我们已经简单了解了ROS2的体系框架,并且随着前面介绍了ROS2功能包的编写、编译、执行流程,也对ROS2应用程序的构建有了基本的认识。本节会进一步从微观和宏观两个维度来介绍ROS2的不同部分,以帮助大家了解ROS2的学习、工作内容以及以后可选择的发展方向。
微观上会介绍ROS2的文件系统、ROS2的核心模块(通信与工具),这些都是官方提供的标准内容。宏观上会介绍关于ROS2的技术支持、ROS2的应用方向,这部分则是得益于ROS2的强大社区。1.5.1 ROS2文件系统
立足系统架构,如下图所示,ROS2可以划分为三层:
操作系统层(OS Layer)
如前所述,ROS虽然称之为机器人操作系统,但实质只是构建机器人应用程序的软件开发工具包,ROS必须依赖于传统意义的操作系统,目前ROS2可以运行在Linux、Windows、Mac或RTOS上。
中间层(Middleware Layer)
主要由数据分发服务DDS与ROS2封装的关于机器人开发的中间件组成。DDS是一种去中心化的数据通讯方式,ROS2还引入了服务质量管理 (Quality of Service)机制,借助该机制可以保证在某些较差网络环境下也可以具备良好的通讯效果。ROS2中间件则主要由客户端库、DDS抽象层与进程内通讯API构成。
应用层(Application Layer)
是指开发者构建的应用程序,在应用程序中是以功能包为核心的,在功能包中可以包含源码、数据定义、接口等内容。
对于一般开发者而言,工作内容主要集中在应用层,开发者一般通过实现具有某一特定功能的功能包来构建机器人应用程序。对应的我们所介绍的ROS2文件系统主要是指在硬盘上以功能包为核心的目录与文件的组织形式。

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:存储导航所需地图文件。
|-- ......
上述这些目录也可以定义为其他名称,或者根据需要创建其他一些目录。
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");
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更被推荐,是因为继承方式可以在一个进程内组织多个节点,这对于提高节点间的通信效率是很有帮助的,但是直接实例化则与该功能不兼容。
3.配置文件说明
在ROS2功能包中,经常需要开发者编辑一些配置文件以设置功能包的构建信息,功能包类型不同,所需修改的配置文件也有所不同。C++功能包的构建信息主要包含在package.xml与CMakeLists.txt中,Python功能包的构建信息则主要包含在package.xml和setup.py中,接下来我们就简单了解一下这些配置文件。
1.package.xml
不管是何种类型的功能包,package.xml的格式都是类似的,在该文件中包含了包名、版本、作者、依赖项的信息,package.xml可以为colcon构建工具确定功能包的编译顺序。一个简单的package.xml示例如下:
<?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>
1.根标签
<package>:该标签为整个xml文件的根标签,format属性用来声明文件的格式版本。
2.元信息标签
<name>:包名;
<version>:包的版本号;
<description>:包的描述信息;
<maintainer>:维护者信息;
<license>:软件协议;
<url>:包的介绍网址;
<author>:包的作者信息。
3.依赖项
<buildtool_depend>:声明编译工具依赖;
<build_depend>:声明编译依赖;
<build_export_depend>:声明根据此包构建库所需依赖;
<exec_depend>:声明执行时依赖;
<depend>:相当于<build_depend>、<build_export_depend>、<exec_depend>三者的集成;
<test_depend>:声明测试依赖;
<doc_depend>:声明构建文档依赖。
2.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()
在示例中关于文件的使用已经通过注释给出了简短说明,其实关于CMakeLists.txt的配置是比较复杂的,后续随着学习的深入,还会给出更多的补充说明。
3.setup.py
Python功能包中需要配置setup.py文件,该文件描述了如何构建Python功能包,一个简单的setup.py示例如下:
from setuptools import setup
package_name = 'pkg02_helloworld_py'
setup(
name=package_name, # 包名
version='0.0.0', # 版本
packages=[package_name], # 功能包列表
data_files=[ #需要被安装的文件以及安装路径
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'], # 安装依赖
zip_safe=True,
maintainer='ros2', # 维护者
maintainer_email='ros2@todo.todo', # 维护者 email
description='TODO: Package description', # 包描述
license='TODO: License declaration', # 软件协议
tests_require=['pytest'], # 测试依赖
entry_points={
'console_scripts': [
# 映射源文件与可执行文件
'helloworld = pkg02_helloworld_py.helloworld:main'
],
},
)
使用语法可参考上述示例中的注释。
4.操作命令
ROS2的文件系统核心是功能包,我们可以通过编译指令colcon和ROS2内置的工具指令ros2来实现功能包的创建、编译、查找与执行等相关操作。
1.创建
新建功能包语法如下:
ros2 pkg create 包名 --build-type 构建类型 --dependencies 依赖列表 --node-name 可执行程序名称
格式解释:
--build-type:是指功能包的构建类型,有cmake、ament_cmake、ament_python三种类型可选;
--dependencies:所依赖的功能包列表;
--node-name:可执行程序的名称,会自动生成对应的源文件并生成配置文件。
2.编译
编译功能包语法如下:
colcon build
或
colcon build --packages-select 功能包列表
前者会构建工作空间下的所有功能包,后者可以构建指定功能包。
3.查找
在ros2 pkg命令下包含了多个查询功能包相关信息的参数。
ros2 pkg executables [包名] # 输出所有功能包或指定功能包下的可执行程序。
ros2 pkg list # 列出所有功能包
ros2 pkg prefix 包名 # 列出功能包路径
ros2 pkg xml # 输出功能包的package.xml内容
4.执行
执行命令语法如下:
ros2 run 功能包 可执行程序 参数
小提示:
可以通过
命令 -h或命令 --help来获取命令的帮助文档。
1.5.2 ROS2核心模块
通信与工具是ROS2的核心模块,也是我们以后学习和工作的重点所在,本节将会介绍通信和工具中涉及到的一些知识点。
1.通信模块
通信模块是整个ROS2架构中的重中之重,比如你可能想要了解在ROS2中是如何控制机器人底盘运动的?雷达、摄像头、imu、GPS等这些传感器数据是如何传输到ROS2系统的?人机交互时调用者如何下发指令,机器人又是如何反馈数据的?导航、机械臂等系统性实现不同模块之间是如何交互数据的......等等,其实这些都离不开通信模块。另外,开发者构建应用程序时,通信部分在工作内容中占有相当大的比重。
2.功能包应用
功能包的应用主要有三种方式:
1.二进制安装
ROS官方或社区提供的功能包可以很方便的通过二进制方式安装,安装命令如下:
sudo apt install ros-ROS2版本代号-功能包名称
小提示:
可以调用
apt search ros-ROS2版本代号-* | grep -i 关键字格式的命令,根据关键字查找所需的功能包。
2.源码安装
也可以直接下载官方、社区或其他第三方提供的源代码,一般我们会从github获取源码,下载命令如下:
git clone 仓库地址
源码下载后,需要自行编译。
3.自实现
开发者按照业务需求自己编写功能包实现。
3.分布式
ROS2是一个分布式架构,不同的ROS2设备之间可以方便的实现通信,这在多机器人设备协同中是极其重要的。
4.终端命令与rqt
在ROS2中提供了丰富的命令行工具,可以方便的调试程序、提高开发效率。
rqt是一个图形化工具,它的功能与命令行工具类似,但是图形化的交互方式更为友好。
示例1:使用命令行工具在turtlesim_node中生成一只新乌龟。

示例2:使用rqt在turtlesim_node中生成一只新乌龟。

5.launch文件
通过launch文件,可以批量的启动ROS2节点,这是在构建大型项目时启动多节点的常用方式。
示例:一次性启动多个turtlesim_node节点。

6.TF坐标变换
TF坐标变换可以实现机器人不同部件或不同机器人之间的相对位置关系的转换。
示例1:发布机器人不同部件之间的坐标系关系。

示例2:使用turtlesim_node模拟多机器人编队。

7.可视化
ROS2内置了三维可视化工具rviz2,它可以图形化的方式显示机器人模型或显示机器人系统中的一些抽象数据。
示例1:显示传感器数据。

示例2:显示机器人模型。

1.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。
1.5.4 ROS2应用方向
许多ROS团队伴随ROS成长到今日,其规模已经发展到足以被认为是独立组织的程度了。在导航、机械臂、无人驾驶、无人机等诸多领域大放异彩,下面列出了其中的一些团队项目,这些项目对我们以后的进阶发展,也提供了指导。
NAV2
Nav2项目继承自ROS Navigation Stack。该项目旨在可以让移动机器人从A点安全的移动到B点。它也可以应用于涉及机器人导航的其他应用,例如跟随动态点。Nav2将用于实现路径规划、运动控制、动态避障和恢复行为等一系列功能。
OpenCV
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。OpenCV旨在为计算机视觉应用程序提供通用基础架构,并加速机器感知在商业产品中的使用。OpenCV允许企业轻松地使用和修改代码。
MoveIt
MoveIt是一组ROS软件包, 主要包含运动规划、碰撞检测、运动学、3D感知、操作控制等功能。它可以用于构建机械臂的高级行为。MoveIt现在可以用于市面上的大多数机械臂,并被许多大公司使用。
The Autoware Foundation
Autoware Foundation是ROS下属的非营利组织,支持实现自动驾驶的开源项目。Autoware基金会在企业发展和学术研究之间创造协同效应,为每个人提供自动驾驶技术。
F1 Tenth
F1 Tenth是将模型车改为无人车的竞速赛事,是一个由研究人员、工程师和自主系统爱好者组成的国际社区。它最初于 2016 年在宾夕法尼亚大学成立,但后来扩展到全球许多其他机构。
microROS
在基于ROS的机器人应用中,micro-ROS正在弥合性能有限的微控制器和一般处理器之间的差距。micro-ROS在各种嵌入式硬件上运行,使ROS能直接应用于机器人硬件。
Open Robotics
Open Robotics与全球ROS社区合作,为机器人创建开放的软件和硬件平台,包括 ROS1、ROS2、Gazebo模拟器和Ignition模拟器。Open Robotics使用这些平台解决一些重要问题,并通过为各种客户组织提供软件和硬件开发服务来帮助其他人做同样的事情。
PX4
PX4是一款用于无人机和其他无人驾驶车辆的开源飞行控制软件。该项目为无人机开发人员提供了一套灵活的工具,用于共享技术并为无人机应用程序创建量身定制解决方案。
ROS-Industrial
ROS-Industrial是一个开源项目,将 ROS 软件的高级功能扩展到工业相关硬件和应用程序。
1.6 本章小结
本章主要介绍了ROS2的相关概念以及ROS2的环境搭建。
概念相关知识点如下:
ROS2概念、发展历程、组成体系以及在机器人领域的优势;
ROS2体系框架:文件系统、核心模块、技术支持、应用方向。
环境搭建相关知识点如下:
ROS2安装与测试;
ROS2的“helloworld”实现;
ROS2集成开发环境搭建;
在概念部分,我们以时间轴为参考介绍了ROS2的发展历程,以空间轴为参考介绍了ROS2的组成体系,又分别在横向和纵向两个维度介绍了ROS2在机器人研发领域的优势。关于ROS2的体系框架则又分别立足微观和宏观的角度介绍了关于ROS2的学习内容,介绍了行业的可发展方向。
在环境搭建部分,则介绍了ROS2的具体安装流程。通过helloworld程序,了解了ROS2程序的编写、编译和执行流程。最后还介绍了如何使用VSCode搭建对开发者友好的集成开发环境。至此,ROS2的大门已经敞开,向着未来扬帆起航吧,good luck!










