安装
ubuntu 20.04
1 | sudo apt install ros-rolling-desktop |
http://docs.ros.org/en/rolling/Installation/Ubuntu-Install-Debians.html#
配置环境
- “workspace”是一个ROS术语,表示在系统上使用ROS2进行开发的位置。
- 核心ROS工作区被称为”underlay“,本地ROS工作区称为 ”overlays“
环境设置脚本自启动
1 | echo "source /opt/ros/rolling/setup.bash" >> ~/.bashrc |
基础概念
Node
ROS图(ROS graph)是一个由ROS 2元素组成的网络,在同一时间一起处理数据。图中包括所有的可执行文件和它们之间的联系。
ROS中的每个节点(ROS Node)应该只负责单一模块化的用途(例如,一个节点负责控制车轮马达,一个节点负责控制激光测距仪等等)。每个节点可以通过主题(topics)、服务(services)、行动(actions)或参数(parameters)向其他节点发送和接收数据。
一个完整的机器人系统由许多协同工作的节点组成。在ROS2中,单个可执行文件(C++程序、Python程序等)可以包含一个或多个节点。
命令
ros2 run <package_name> <executable_name>
:从包启动可执行文件。ros2 node list
:显示所有运行节点的名称,当您想要与一个节点交互时,或者当您的系统运行许多节点并且需要跟踪它们时,这尤其有用。使用
Remapping
可以指定节点属性(如节点名称、主题名称、服务名称等)例:
ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle
ros2 node info <node_name>
:知道了节点的名称,可以通过该命令访问有关节点的更多信息
Topics
ROS2将复杂系统分解为许多模块化节点。主题(Topics)是ROS图的一个重要元素,充当节点交换消息的总线。
节点可以将数据发布到任意数量的主题,同时可以订阅任意数量的主题。主题是在节点之间以及系统不同部分之间移动数据的主要方式之一。也就是说,主题可以不只是点对点的交流,它可以是一对多、多对一或多对多。
工具
我们可以使用rqt_graph
来可视化不断变化的节点和主题,以及它们之间的连接。
上图描述了/turtlesim
节点和/teleop_turtle
节点如何通过主题相互通信。/teleop_turtle
节点将数据发布到/turtle1/cmd_vel
主题中(输入用于移动海龟的按键),并且/turtlesim
节点订阅该主题以接收数据。
命令
ros2 topic list
:返回系统中当前活动的所有主题的列表ros2 topic list -t
:将返回相同的主题列表,返回结果括号中的是主题类型。ros2 topic echo <topic_name>
:查看主题上正在发布的数据ros2 topic info <topic_name>
:返回主题信息(有多少个订阅者,有多少个发布者)ros2 interface show <type>
:节点使用消息通过主题发送数据。发布者和订阅者必须发送和接收相同类型的消息才能进行通信。如果主题/turtle1/cmd_vel
的类型是geometry_msgs/msg/Twist
,这意味着在geometry_msgs
包中有一个名为Twist
的消息。ros2 interface show <msg type>
可以查看该类型的细节,假设得到的类型细节为:1
2
3
4
5
6
7
8Vector3 linear
float64 x
float64 y
float64 z
Vector3 angular
float64 x
float64 y
float64 z这说明
/turtlesim
节点需要一条消息,该消息包含两个向量,即linear
向量和angular
向量,每个向量包含三个元素。ros2 topic pub <topic_name> <msg_type> '<args>'
:使用该命令直接将数据发布到主题,前提是数据的具体结构。需要注意的是,args
需要符合YAML语法规范,例:1
ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
ros2 topic hz
:查看数据发布的速率
Services
服务(services)是ROS图中节点的另一种通信方法。服务基于呼叫和响应(call-and-response)模型,而不是发布者-订阅者(publisher-subscriber)模型。虽然主题允许节点订阅数据流并获得持续更新,但服务仅在客户端专门调用时提供数据。
命令
ros2 service list
:返回系统中当前活动的所有服务的列表ros2 service type <service_name>
:服务类型的定义与主题类型类似,只是服务类型有两部分:一部分用于请求,另一部分用于响应。假如一个服务的类型是std_srvs/srv/Empty
,这表示服务调用在发出请求时不发送数据,在接收响应时不接收数据。ros2 service find <service_type>
:查找特定类型的所有服务ros2 interface show <service_type_name>
:返回类型的具体结构,返回结果的---
将请求结构(上面)与响应结构(下面)分开。ros2 service call <service_name> <service_type> <arguments>
:调用服务
Parameters
参数(parameters)是节点的配置值。节点可以将参数存储为整数、浮点、布尔、字符串和列表。在ROS2中,每个节点维护自己的参数。所有参数都可动态重新配置,并基于ROS 2服务构建。
命令
ros2 param list
:查看参数列表ros2 param get <node_name> <parameter_name>
:查看参数类型和当前值ros2 param set <node_name> <parameter_name> <value>
:设置参数值ros2 param dump > dumpfile
:查看节点的所有当前参数值ros2 param load <node_name> <parameter_file>
:将参数从文件加载到当前运行的节点只读参数只能在启动前修改,启动后修改有可能会出现问题(比如一些QOS参数)
ros2 run <package_name> <executable_name> --ros-args --params-file <file_name>
:在启动时加载参数
Actions
Actions是ROS 2中的通信类型之一,用于长时间运行的任务。它们由三部分组成:目标(goal)、反馈(feedback)和结果(result)
行动建立在主题和服务之上,功能与服务类似,只是可以取消操作。它们还提供稳定的反馈,而不是像服务一样只返回单一响应。
Actions使用client-server模型,类似于pubsub模型(在主题教程中介绍)。“action client”节点向“action server”节点发送目标,后者确认目标并返回反馈流和结果。
命令
ros2 action list -t
ros2 action info
ros2 interface show
:返回结果被---
分为三个部分,分别是目标请求的结构、结果的结构、反馈的结构。ros2 action send_goal <action_name> <action_type> <values> --feedback
:发生Action中的目标
工作区
工作区(workspace)是包含ROS2包的目录。
source ROS2环境:
source /opt/ros/rolling/setup.bash
创建目录:最好是为每个新的工作区创建新目录,并将所有的包都放置在
src
文件夹在
src
文件夹执行:git clone https://github.com/ros/ros_tutorials.git -b rolling-devel
在构建工作区之前,您需要解析包依赖关系:
rosdep install -i --from-path src --rosdistro rolling -y
,找不到
rosdep
命令 的解决方法:1
>apt install python3-rosdep2
rosdep update
失败的解决方法:- 使用rosdepc:本文之后,世上再无rosdep更新失败问题!如果有….小鱼就… - 古月居 (guyuehome.com)
- 使用github proxy:ROS安装过程中如何解决 rosdep update 命令出现错误 - 知乎 (zhihu.com)
使用
colcon
构建工作空间:colcon build
。build
完成后会生成三个文件夹,build
、install
、log
,其中install
目录是您的工作区的安装文件所在的位置,您可以使用它来source overlay。- 找不到
colcon
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25sudo apt update && sudo apt install -y \
build-essential \
cmake \
git \
python3-colcon-common-extensions \
python3-flake8 \
python3-pip \
python3-pytest-cov \
python3-rosdep \
python3-setuptools \
python3-vcstool \
wget
# install some pip packages needed for testing
python3 -m pip install -U \
flake8-blind-except \
flake8-builtins \
flake8-class-newline \
flake8-comprehensions \
flake8-deprecated \
flake8-docstrings \
flake8-import-order \
flake8-quotes \
pytest-repeat \
pytest-rerunfailures \
pytest- build 失败的解决办法:
python版本的问题,将
/usr/bin
中的python3.5执行文件改成其他文件名,只留下python3.8执行文件- 找不到
source overlay(本地工作区):
. install/local_setup.bash
在source本地工作区之前,需要打开一个新的终端,与构建工作区的终端分开,这一点非常重要,不然有可能会产生复杂的问题
修改本地工作区的代码:
- 将
~/dev_ws/src/ros_tutorials/turtlesim/src/turtle_frame.cpp
中52行的setWindowTitle("TurtleSim");
修改为setWindowTitle("MyTurtleSim");
colcon build
. install/local_setup.bash
、ros2 run turtlesim turtlesim_node
- 将
ROS包
包(package)可以被认为是你的ROS 2代码的容器。如果你希望能够安装你的代码或与他人分享,那么你就需要把它组织在一个包里。通过包,你可以发布你的ROS 2工作,并允许其他人轻松构建和使用它。
ROS 2的软件包创建使用ament
作为其构建系统,colcon
作为其构建工具,你可以使用官方支持的CMake或Python来创建一个软件包。除了这些,也存在其他的构建方式。
Ament是catkin编译工具的优化迭代版本。
colcon是一个构建软件包集合的命令行工具,是ros构建工具catkin_make, catkin_make_isolated, catkin_tools 和ament_tools的迭代版本。
Python构建软件包需要:
package.xml
文件,包含关于包的元信息。setup.py
,包含如何安装软件包的说明setup.cfg
在软件包有可执行文件时是必需的,这样 ros2 run 可以找到它们。/<package_name>
一个与你的软件包同名的目录,被ROS 2工具用来寻找你的软件包,包含__init__.py
最简单的Python包文件结构:
1 | my_package/ |
CMake构建软件包需要:
package.xml
文件,包含关于包的元信息。CMakeLists.txt
文件,描述了如何构建包内的代码
最简单的的C/C++包文件结构:
1 | my_package/ |
一个工作区可以包含你想要的任何数量的包,每个包都在自己的文件夹里。你也可以在一个工作区中拥有不同构建类型的包(CMake、Python等),但是不能有嵌套的包。最好的做法是在你的工作区里有一个src文件夹,并在那里创建你的包。这样可以保持工作区顶层的干净。
一个典型的工作空间可能看起来是这样的:
1 | workspace_folder/ |
在ROS 2中创建一个新包的命令语法是:
1 | ros2 pkg create --build-type ament_cmake <package_name> |
或者
1 | ros2 pkg create --build-type ament_python <package_name> |
例子:
1 | ros2 pkg create --build-type ament_cmake --node-name my_node my_package |
把软件包放在工作区是一件有意义的事,因为你可以通过在工作区根目录下运行colcon build
来一次性构建所有软件包,而不用单独构建每个包。
1 | colcon build --packages-select my_package |
build失败,原因是email和maintainer包含反斜杆,去掉就行
尝试运行,ros2 run my_package my_node
会看到输出。修改my_node.cpp
,重新编译运行,可以看到不同的输出。
pubsub模型
C++版本
Python版本
创建包
在src
文件下执行:
1 | ros2 pkg create --build-type ament_python py_pubsub |
发布Node
在src/py_pubsub/py_pubsub
目录下添加文件publisher_member_function.py
1 | import rclpy |
添加依赖
在package.xml
中添加依赖:
1 | <exec_depend>rclpy</exec_depend> |
添加入口点(entry point)
打开setup.py
,将信息修改为package.xml
中的信息。并修改以下字段:
1 | entry_points={ |
检查setup.cfg
一般来说,setup.cfg
的文件内容是:
1 | [develop] |
含义是告诉 setuptools
要把你的可执行文件放在 lib
中,因为 ros2 run 会在那里寻找可执行文件。
订阅Node
1 | import rclpy |
在setup.py
添加入口点:
1 | 'listener = py_pubsub.subscriber_member_function:main', |
编译运行
1 | #检查依赖 |
CS模型
C++版本
请求和响应的结构由一个.srv
文件决定。
创建包
1 | ros2 pkg create --build-type ament_cmake cpp_srvcli --dependencies rclcpp example_interfaces |
参数--dependencies
将自动在package.xml
和CMakeLists.txt
中添加必要的依赖关系行。
example_interfaces
包中有我们将需要的.srv
文件的包。
1 | int64 a |
服务端Node
1 |
|
添加入口
add_executable
宏会生成一个可以用ros2 run来运行的执行文件,在CMakeLists.txt
中添加以下代码块,以创建一个名为server的可执行文件。
1 | add_executable(server src/add_two_ints_server.cpp) |
为了让ros2运行能够找到可执行文件,需要在文件末尾添加以下几行,就在ament_package()
之前。
客户端Node
1 | #include "rclcpp/rclcpp.hpp" |
一样需要添加入口
编译运行
1 | colcon build --packages-select cpp_srvcli |
Python版本
自定义的msg和srv
创建包
1 | ros2 pkg create --build-type ament_cmake tutorial_interfaces |
注意必须是一个CMake包。
好的做法是将.msg
和.srv
文件放在软件包内各自的目录中。
创建自定义的definitions
注意msg
、srv
、src
文件夹在同一层级
Num.msg
:1
int64 num
AddThreeInts.srv
:1
2
3
4
5int64 a
int64 b
int64 c
---
int64 sumCMakeLists.txt
:将定义的接口转换为特定语言的代码(如C++和Python),以便它们可以在这些语言中使用,需要添加以下代码1
2
3
4
5
6find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/Num.msg"
"srv/AddThreeInts.srv"
)package.xml
:接口依赖rosidl_default_generators
来生成特定语言的代码,你需要声明对它的依赖性。1
2
3
4
5<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
编译查看
1 | colcon build --packages-select tutorial_interfaces |
使用
C++
源码
1
#include "tutorial_interfaces/msg/num.hpp" # CHANGE
CMakeLists.txt
1
2
3find_package(tutorial_interfaces REQUIRED) # CHANGE
ament_target_dependencies(talker rclcpp tutorial_interfaces) # CHANGE
ament_target_dependencies(listener rclcpp tutorial_interfaces) # CHANGEpackage.xml
1
<depend>tutorial_interfaces</depend>
Python
源码
1
from tutorial_interfaces.msg import Num # CHANGE
package.xml
1
<exec_depend>tutorial_interfaces</exec_depend>
拓展ROS 2的接口(interface)
你可以在一个新的接口定义中使用一个现有的接口定义。
ROS Launch
ROS2 启动系统
ROS 2中的启动系统负责帮助用户描述其系统的配置,然后按照描述执行。系统的配置包括运行什么程序,在哪里运行,向它们传递什么参数,以及ROS特定的约定,通过给它们各自不同的配置,使整个系统中的组件易于重复使用。它还负责监控启动的进程的状态,并报告和/或对这些进程的状态变化做出反应。
用Python编写的启动文件可以启动和停止不同的节点,也可以触发各种事件并对其采取行动。提供这个框架的包是 launch_ros,它在下面使用非ROS专用的启动框架。
编写ROS 2启动文件
如果你还没有,请确保你浏览了关于如何创建ROS 2软件包的快速入门教程。在ROS 2中创建启动文件的一种方法是使用Python文件,这些文件由ROS 2 CLI工具ros2 launch来执行。我们首先使用ros2 pkg create <pkg-name> --dependencies [deps]
在我们的工作区创建一个ROS 2软件包,并创建一个新的启动目录。
C++ 包
如果你正在创建一个C++包,我们将只调整CMakeLists.txt文件,添加:
1 | # Install launch files. |
到文件的末尾(但在ament_package()
之前)。
编写启动文件
在你的启动目录中,创建一个后缀为.launch.py
的新启动文件。例如:my_script.launch.py
。
你的启动文件应该定义generate_launch_description()
,它返回一个 launch.LaunchDescription(),供 ros2 launch
使用。
1 | import launch |
使用
1 | ros2 launch my_package script.launch.py |