ROS2 Humble 学习
- 1 介绍
- 1.1 概述
- 1.2 ROS2 详细介绍
- 1.3 openEuler 安装 ROS2 Humble
- 1.4 ROS2 系统架构
- 2 ROS2 基础
- 2.1 节点编写、编译、运行【简单示例】
- 节点编写
- 节点编译 g++
- 节点运行
- 节点编译 make
- 节点编译 CMakeLists.txt
- CMake依赖查找流程
- Python 依赖查找流程
- 2.2 节点交互、启动、查看【命令】
- 2.3 ROS2 工作空间、功能包、构建工具 Colcon
- 工作空间
- 功能包
- 功能包获取【安装】
- 功能包获取【手动编译】
- 功能包指令 ros2 pkg
- 构建工具 Colcon 介绍 & 安装
- 2.4 编写节点
- 编写节点【RCLCPP】
- 创建工作空间
- 创建功能包
- 创建节点
- 编写代码
- 编译运行
- 测试
- 编写节点【RCLPY】
- 创建工作空间
- 创建功能包
- 创建节点
- 编写代码
- 编译运行
- 测试
- 2.5 节点编写、编译、运行【面向对象编程 OOP】
- C++ 示例
- Python
- 2.6 Colcon 介绍
- colcon
- catkin_make
- ament_tools
- 构建指令
- 指定构建后安装的目录
- 合并构建目录
- 符号链接安装
- 错误时继续安装
- CMake参数
- 控制构建线程
- 开启构建日志
- 2.7 ROS2节点发现与多机通信
- 选择域ID (短版本)
- 选择域ID (长版本)
- 2.8 通信--话题与服务
- TCP/UDP
- 基于共享内存的进程间通信(IPC)方式
- ZeroMQ
- PyZmq
- 话题
- 命令
- 实现 RCLCPP
- 实现 RCLPY
- 服务
- 实现 RCLCPP
- 实现 RCLPY
- 2.9 通信--参数
- 3 机器人学
- 4 建模仿真
- 5 Navi2 导航
- 6 Moveit2 机械臂
- 参考
1 介绍
1.1 概述
ROS(Robot Operating System,下文简称“ROS”)是一个适用于机器人的开源的元操作系统。它提供了操作系统应有的服务,包括硬件抽象,底层设备控制,常用函数的实现,进程间消息传递,以及包管理。它也提供用于获取、编译、编写、和跨计算机运行代码所需的工具和库函数。
ROS 2 Documentation humble
小鱼–动手学ROS2
机器人操作系统入门讲义
本文在 openEuler 22.03 虚拟机中按照 ROS2 Humble 官方教程、小鱼文章大纲、机器人操作系统入门讲义 进行学习调试记录
1.2 ROS2 详细介绍
ROS2 详细介绍
1.3 openEuler 安装 ROS2 Humble
openEuler 安装 ROS2 Humble
1.4 ROS2 系统架构
- 抽象DDS层-RMW(ROS Middleware Interface)
- RCL(ROS Client Library)ROS客户端库,其实就是ROS的一种API,提供了对ROS话题、服务、参数、Action等接口。
2 ROS2 基础
2.1 节点编写、编译、运行【简单示例】
ROS2的C++节点
节点编写
- 创建文件 ros2_node.cpp
touch ros2_node.cpp
- 编写代码
#include "rclcpp/rclcpp.hpp"
int main(int argc, char **argv)
{
// 调用rclcpp的初始化函数
rclcpp::init(argc, argv);
// 调用rclcpp的循环运行我们创建的first_node节点
rclcpp::spin(std::make_shared<rclcpp::Node>("first_node"));
return 0;
}
节点编译 g++
- 编译报错
[euler@Euler node]$ ls
ros2_node.cpp
[euler@Euler node]$ g++ ros2_node.cpp
ros2_node.cpp:1:10: 致命错误:rclcpp/rclcpp.hpp:没有那个文件或目录
1 | #include "rclcpp/rclcpp.hpp"
| ^~~~~~~~~~~~~~~~~~~
编译中断。
[euler@Euler node]$
- 定位头文件
/opt/ros/humble/include/rclcpp
ls rclcpp/* | grep rclcpp.h
[euler@Euler rclcpp]$ ls rclcpp/* | grep rclcpp.h
rclcpp/rclcpp.hpp
[euler@Euler rclcpp]$
- g++ 指定相应目录
g++ ros2_node.cpp -I /opt/ros/humble/include/rclcpp/
[euler@Euler node]$ g++ ros2_node.cpp -I /opt/ros/humble/include/rclcpp/
In file included from /opt/ros/humble/include/rclcpp/rclcpp/executors/multi_threaded_executor.hpp:25,
from /opt/ros/humble/include/rclcpp/rclcpp/executors.hpp:21,
from /opt/ros/humble/include/rclcpp/rclcpp/rclcpp.hpp:155,
from ros2_node.cpp:1:
/opt/ros/humble/include/rclcpp/rclcpp/executor.hpp:30:10: 致命错误:rcl/guard_condition.h:没有那个文件或目录
30 | #include "rcl/guard_condition.h"
| ^~~~~~~~~~~~~~~~~~~~~~~
编译中断。
[euler@Euler node]$
- g++ 指令多层依赖目录
g++ ros2_node.cpp -lrclcpp -lrcutils -std=c++17 \
-I/opt/ros/humble/include/rclcpp/ \
-I /opt/ros/humble/include/rcl/ \
-I /opt/ros/humble/include/rcutils/ \
-I /opt/ros/humble/include/rmw \
-I /opt/ros/humble/include/rcl_yaml_param_parser/ \
-I /opt/ros/humble/include/rosidl_runtime_c \
-I /opt/ros/humble/include/rosidl_typesupport_interface \
-I /opt/ros/humble/include/rcpputils \
-I /opt/ros/humble/include/builtin_interfaces \
-I /opt/ros/humble/include/rosidl_runtime_cpp \
-I /opt/ros/humble/include/tracetools \
-I /opt/ros/humble/include/rcl_interfaces \
-I /opt/ros/humble/include/libstatistics_collector \
-I /opt/ros/humble/include/statistics_msgs \
-L /opt/ros/humble/lib/ \
-Wl,-rpath,/opt/ros/humble/lib/
-Wl: 这个前缀告诉编译器,接下来的选项是传递给链接器(ld)的。
-rpath: 这个选项指定了运行时库的搜索路径。
节点运行
打开新的终端,使用ros2 node list查看正在运行的节点,是否有first_node。
source /opt/ros/humble/setup.bash
节点编译 make
- 安装 make
- 编写 Makefile
新建Makefile
build:
g++ ros2_node.cpp -lrclcpp -lrcutils -std=c++17 \
-I/opt/ros/humble/include/rclcpp/ \
-I /opt/ros/humble/include/rcl/ \
-I /opt/ros/humble/include/rcutils/ \
-I /opt/ros/humble/include/rmw \
-I /opt/ros/humble/include/rcl_yaml_param_parser/ \
-I /opt/ros/humble/include/rosidl_runtime_c \
-I /opt/ros/humble/include/rosidl_typesupport_interface \
-I /opt/ros/humble/include/rcpputils \
-I /opt/ros/humble/include/builtin_interfaces \
-I /opt/ros/humble/include/rosidl_runtime_cpp \
-I /opt/ros/humble/include/tracetools \
-I /opt/ros/humble/include/rcl_interfaces \
-I /opt/ros/humble/include/libstatistics_collector \
-I /opt/ros/humble/include/statistics_msgs \
-L /opt/ros/humble/lib/ \
-Wl,-rpath,/opt/ros/humble/lib/
clean:
rm a.out
euler@Euler node]$ ls
Makefile ros2_node.cpp
[euler@Euler node]$ make build
[euler@Euler node]$ ls
a.out Makefile ros2_node.cpp
[euler@Euler node]$ make clean
rm a.out
[euler@Euler node]$
节点编译 CMakeLists.txt
使用 make 调用 Makefile,需要自己手写 Makefile,而 cmake 通过调用 CMakeLists.txt 可以直接生成 Makefile。
- 新建CMakeLists.txt
touch CMakeLists.txt
- 编写
cmake_minimum_required(VERSION 3.22)
project(first_node)
#include_directories 添加特定的头文件搜索路径 ,相当于指定g++编译器的-I参数
include_directories(/opt/ros/humble/include/rclcpp/)
include_directories(/opt/ros/humble/include/rcl/)
include_directories(/opt/ros/humble/include/rcutils/)
include_directories(/opt/ros/humble/include/rcl_yaml_param_parser/)
include_directories(/opt/ros/humble/include/rosidl_runtime_c/)
include_directories(/opt/ros/humble/include/rosidl_typesupport_interface/)
include_directories(/opt/ros/humble/include/rcpputils/)
include_directories(/opt/ros/humble/include/builtin_interfaces/)
include_directories(/opt/ros/humble/include/rmw/)
include_directories(/opt/ros/humble/include/rosidl_runtime_cpp/)
include_directories(/opt/ros/humble/include/tracetools/)
include_directories(/opt/ros/humble/include/rcl_interfaces/)
include_directories(/opt/ros/humble/include/libstatistics_collector/)
include_directories(/opt/ros/humble/include/statistics_msgs/)
# link_directories - 向工程添加多个特定的库文件搜索路径,相当于指定g++编译器的-L参数
link_directories(/opt/ros/humble/lib/)
# add_executable - 生成first_node可执行文件
add_executable(first_node ros2_node.cpp)
# target_link_libraries - 为first_node(目标) 添加需要动态链接库,相同于指定g++编译器-l参数
# 下面的语句代替 -lrclcpp -lrcutils
target_link_libraries(first_node rclcpp rcutils)
# c++17
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
[euler@Euler node]$ ls
CMakeLists.txt ros2_node.cpp
[euler@Euler node]$ mkdir build
[euler@Euler node]$ ls
build CMakeLists.txt ros2_node.cpp
[euler@Euler node]$ cd build/
[euler@Euler build]$ ls
[euler@Euler build]$ cmake ..
[euler@Euler build]$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
[euler@Euler build]$ make
[ 50%] Building CXX object CMakeFiles/first_node.dir/ros2_node.cpp.o
[100%] Linking CXX executable first_node
[100%] Built target first_node
[euler@Euler build]$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake first_node Makefile
[euler@Euler build]$
CMake依赖查找流程
用cmake虽然成功,但是CMakeLists.txt的内容有些臃肿,需要简化。
- CMakeLists.txt 优化如下
cmake_minimum_required(VERSION 3.22)
project(first_node)
find_package(rclcpp REQUIRED)
add_executable(first_node ros2_node.cpp)
target_link_libraries(first_node rclcpp::rclcpp)
- 加载 ros 环境
source /opt/ros/humble/setup.bash
- 生成和编译
mkdir build
cd build
cmake ..
make
[euler@Euler build]$ cmake ..
-- Found rclcpp: 16.0.4 (/opt/ros/humble/share/rclcpp/cmake)
-- Found rosidl_generator_c: 3.1.4 (/opt/ros/humble/share/rosidl_generator_c/cmake)
-- Found rosidl_adapter: 3.1.4 (/opt/ros/humble/share/rosidl_adapter/cmake)
-- Found rosidl_generator_cpp: 3.1.4 (/opt/ros/humble/share/rosidl_generator_cpp/cmake)
-- Using all available rosidl_typesupport_c: rosidl_typesupport_fastrtps_c;rosidl_typesupport_introspection_c
-- Using all available rosidl_typesupport_cpp: rosidl_typesupport_fastrtps_cpp;rosidl_typesupport_introspection_cpp
CMake Warning at /opt/ros/humble/share/libyaml_vendor/cmake/ament_cmake_export_libraries-extras.cmake:116 (message):
Package 'libyaml_vendor' exports library 'yaml' which couldn't be found
Call Stack (most recent call first):
/opt/ros/humble/share/libyaml_vendor/cmake/libyaml_vendorConfig.cmake:41 (include)
/opt/ros/humble/share/rcl_yaml_param_parser/cmake/ament_cmake_export_dependencies-extras.cmake:21 (find_package)
/opt/ros/humble/share/rcl_yaml_param_parser/cmake/rcl_yaml_param_parserConfig.cmake:41 (include)
/opt/ros/humble/share/rcl/cmake/ament_cmake_export_dependencies-extras.cmake:21 (find_package)
/opt/ros/humble/share/rcl/cmake/rclConfig.cmake:41 (include)
/opt/ros/humble/share/libstatistics_collector/cmake/ament_cmake_export_dependencies-extras.cmake:21 (find_package)
/opt/ros/humble/share/libstatistics_collector/cmake/libstatistics_collectorConfig.cmake:41 (include)
/opt/ros/humble/share/rclcpp/cmake/ament_cmake_export_dependencies-extras.cmake:21 (find_package)
/opt/ros/humble/share/rclcpp/cmake/rclcppConfig.cmake:41 (include)
CMakeLists.txt:4 (find_package)
-- Found rmw_implementation_cmake: 6.1.1 (/opt/ros/humble/share/rmw_implementation_cmake/cmake)
-- Found rmw_fastrtps_cpp: 6.2.2 (/opt/ros/humble/share/rmw_fastrtps_cpp/cmake)
-- Using RMW implementation 'rmw_fastrtps_cpp' as default
-- Configuring done
-- Generating done
-- Build files have been written to: /home/euler/worthsen/node/build
[euler@Euler build]$
- find_package查找路径对应的环境变量如下。
<package>_DIR
CMAKE_PREFIX_PATH
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
PATH
- echo $PATH
[euler@Euler build]$ echo $PATH
/opt/ros/humble/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin
[euler@Euler build]$
PATH中的路径如果以bin或sbin结尾,则自动回退到上一级目录,接着检查这些目录下的
<prefix>/(lib/<arch>|lib|share)/cmake/<name>*/ (U)
<prefix>/(lib/<arch>|lib|share)/<name>*/ (U)
<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (U)
cmake找到这些目录后,会开始依次找Config.cmake或Find.cmake文件。找到后即可执行该文件并生成相关链接信息。
打开 /opt/ros/humble/share/rclcpp/cmake 会发现 rclcppConfig.cmake 就在其中。
Python 依赖查找流程
python 打包和引入依赖,比C++简单很多。
- 编写 ROS2 的 Python 节点
touch ros2_node.py
vim ros2_node.py 输入如下内容
# 导入rclpy库
import rclpy
from rclpy.node import Node
# 调用rclcpp的初始化函数
rclpy.init()
# 调用rclcpp的循环运行我们创建的second_node节点
rclpy.spin(Node("second_node"))
- 运行
python3 ros2_node.py
- 查看
[euler@Euler ~]$ source /opt/ros/humble/setup.bash
[euler@Euler ~]$ ros2 node list
/second_node
[euler@Euler ~]$
- Python 包查找流程
Python3 运行 import rclpy 是通过环境变量 PYTHONPATH 查找到的
echo $PYTHONPATH
[euler@Euler node]$ echo $PYTHONPATH
/opt/ros/humble/lib/python3.9/site-packages
[euler@Euler node]$ ls -l /opt/ros/humble/lib/python3.9/site-packages | grep rclpy
drwxr-xr-x. 3 root root 4096 7月 26 14:27 examples_rclpy_executors
drwxr-xr-x. 2 root root 4096 7月 26 14:27 examples_rclpy_executors-0.15.1-py3.9.egg-info
drwxr-xr-x. 3 root root 4096 7月 26 14:27 examples_rclpy_guard_conditions
drwxr-xr-x. 2 root root 4096 7月 26 14:27 examples_rclpy_guard_conditions-0.15.1-py3.9.egg-info
drwxr-xr-x. 3 root root 4096 7月 26 14:27 examples_rclpy_minimal_action_client
drwxr-xr-x. 2 root root 4096 7月 26 14:27 examples_rclpy_minimal_action_client-0.15.1-py3.9.egg-info
drwxr-xr-x. 3 root root 4096 7月 26 14:27 examples_rclpy_minimal_action_server
drwxr-xr-x. 2 root root 4096 7月 26 14:27 examples_rclpy_minimal_action_server-0.15.1-py3.9.egg-info
drwxr-xr-x. 3 root root 4096 7月 26 14:27 examples_rclpy_minimal_client
drwxr-xr-x. 2 root root 4096 7月 26 14:27 examples_rclpy_minimal_client-0.15.1-py3.9.egg-info
drwxr-xr-x. 3 root root 4096 7月 26 14:27 examples_rclpy_minimal_publisher
drwxr-xr-x. 2 root root 4096 7月 26 14:27 examples_rclpy_minimal_publisher-0.15.1-py3.9.egg-info
drwxr-xr-x. 3 root root 4096 7月 26 14:27 examples_rclpy_minimal_service
drwxr-xr-x. 2 root root 4096 7月 26 14:27 examples_rclpy_minimal_service-0.15.1-py3.9.egg-info
drwxr-xr-x. 3 root root 4096 7月 26 14:27 examples_rclpy_minimal_subscriber
drwxr-xr-x. 2 root root 4096 7月 26 14:27 examples_rclpy_minimal_subscriber-0.15.1-py3.9.egg-info
drwxr-xr-x. 3 root root 4096 7月 26 14:27 examples_rclpy_pointcloud_publisher
drwxr-xr-x. 2 root root 4096 7月 26 14:27 examples_rclpy_pointcloud_publisher-0.15.1-py3.9.egg-info
drwxr-xr-x. 5 root root 4096 7月 26 14:27 rclpy
drwxr-xr-x. 2 root root 4096 7月 26 14:27 rclpy-3.3.8-py3.9.egg-info
drwxr-xr-x. 3 root root 4096 7月 26 14:27 rclpy_message_converter
drwxr-xr-x. 2 root root 4096 7月 26 14:27 rclpy_message_converter-2.0.1-py3.9.egg-info
drwxr-xr-x. 4 root root 4096 7月 26 14:33 rclpy_message_converter_msgs
drwxr-xr-x. 2 root root 4096 7月 26 14:33 rclpy_message_converter_msgs-2.0.1-py3.9.egg-info
[euler@Euler node]$
2.2 节点交互、启动、查看【命令】
-
ROS2 四种通信方式:
1)话题-topics
2)服务-services
3)动作-Action
4)参数-parameters -
启动节点命令
# 启动 包 中的节点
ros2 run <package_name> <executable_name>
eg: ros2 run turtlesim turtlesim_node
- 查看节点
ros2 node list
- 查看节点信息
ros2 node info <node_name>
[euler@Euler ~]$ ros2 node info /first_node
/first_node
Subscribers:
/parameter_events: rcl_interfaces/msg/ParameterEvent
Publishers:
/parameter_events: rcl_interfaces/msg/ParameterEvent
/rosout: rcl_interfaces/msg/Log
Service Servers:
/first_node/describe_parameters: rcl_interfaces/srv/DescribeParameters
/first_node/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
/first_node/get_parameters: rcl_interfaces/srv/GetParameters
/first_node/list_parameters: rcl_interfaces/srv/ListParameters
/first_node/set_parameters: rcl_interfaces/srv/SetParameters
/first_node/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
Service Clients:
Action Servers:
Action Clients:
- 重映射节点名称
ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle
- 运行节点时设置参数
ros2 run example_parameters_rclcpp parameters_basic --ros-args -p rcl_log_level:=10
2.3 ROS2 工作空间、功能包、构建工具 Colcon
工作空间
一个工作空间下可以有多个功能包,一个功能包可以有多个节点存在。
eg: 创建 ros2 工作区,其中包含 src 文件夹
mkdir worthsen
cd worthsen
mkdir -p ros2/src
功能包
功能包中存放节点,ROS2 中功能包根据编译方式的不同分为三种类型。
(1)ament_python,适用于python程序
(2)cmake,适用于C++
(3)ament_cmake,适用于C++程序,是cmake的增强版
功能包获取【安装】
sudo yum install ros-<version>-package_name
安装获取会自动放置到系统目录,不用再次手动source。
功能包获取【手动编译】
手动编译之后,需要手动source工作空间的install目录。
功能包指令 ros2 pkg
create Create a new ROS2 package
executables Output a list of package specific executables
list Output a list of available packages
prefix Output the prefix path of a package
xml Output the XML of the package manifest or a specific tag
- 创建功能包
ros2 pkg create <package-name> --build-type {cmake,ament_cmake,ament_python} --dependencies <依赖名字>
- 列出可执行文件
# 列出所有
ros2 pkg executables
# 列出turtlesim功能包的所有可执行文件
ros2 pkg executables turtlesim
- 列出所有的包
ros2 pkg list
- 输出某个包所在路径的前缀
ros2 pkg prefix <package-name>
eg: 比如小乌龟
ros2 pkg prefix turtlesim
[euler@Euler ~]$ source /opt/ros/humble/setup.bash
[euler@Euler ~]$ ros2 pkg prefix turtlesim
/opt/ros/humble
[euler@Euler ~]$
- 列出包的清单描述文件
每一个功能包都有一个标配的manifest.xml文件,用于记录这个包的名字,构建工具,编译信息,拥有者,干啥用的等信息。
通过这个信息,就可以自动为该功能包安装依赖,构建时确定编译顺序等
ros2 pkg xml turtlesim
[euler@Euler ~]$ ros2 pkg xml turtlesim
<package format="3">
<name>turtlesim</name>
<version>1.4.2</version>
<description>
turtlesim is a tool made for teaching ROS and ROS packages.
</description>
<maintainer email="audrow@openrobotics.org">Audrow Nash</maintainer>
<maintainer email="michael.jeronimo@openrobotics.org">Michael Jeronimo</maintainer>
<license>BSD</license>
<url type="website">http://www.ros.org/wiki/turtlesim</url>
<url type="bugtracker">https://github.com/ros/ros_tutorials/issues</url>
<url type="repository">https://github.com/ros/ros_tutorials</url>
<author email="dthomas@osrfoundation.org">Dirk Thomas</author>
<author>Josh Faust</author>
<author email="mabel@openrobotics.org">Mabel Zhang</author>
<author email="sloretz@openrobotics.org">Shane Loretz</author>
<build_depend>qt5-qmake</build_depend>
<build_depend>qtbase5-dev</build_depend>
<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>libqt5-core</exec_depend>
<exec_depend>libqt5-gui</exec_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<depend>ament_index_cpp</depend>
<depend>geometry_msgs</depend>
<depend>rclcpp</depend>
<depend>rclcpp_action</depend>
<depend>std_msgs</depend>
<depend>std_srvs</depend>
<member_of_group>rosidl_interface_packages</member_of_group>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
[euler@Euler ~]$
构建工具 Colcon 介绍 & 安装
ROS2 默认是没有安装 colcon 的,colcon 想当于 ros1 中的 catkin 工具。
colcon是一系列python脚本,是对cmake等编译工具的封装。
- 安装
# Using pip on any platform
# 普通用户权限安装,避障权限问题
pip install -U colcon-common-extensions
openEuler 安装 ROS2 Humble【编译系统】
- 克隆示例代码
[euler@Euler colcon]$ pwd
/home/euler/worthsen/node/colcon
[euler@Euler colcon]$ git clone https://github.com/ros2/examples src/examples -b humble
[euler@Euler colcon]$ tree -L 4
.
└── src
└── examples
├── CONTRIBUTING.md
├── launch_testing
│ └── launch_testing_examples
├── LICENSE
├── rclcpp
│ ├── actions
│ ├── composition
│ ├── executors
│ ├── README.md
│ ├── services
│ ├── timers
│ ├── topics
│ └── wait_set
├── rclpy
│ ├── actions
│ ├── executors
│ ├── guard_conditions
│ ├── pytest.ini
│ ├── services
│ └── topics
└── README.md
18 directories, 5 files
[euler@Euler colcon]$
- 编译
colcon build
eg:
[euler@Euler colcon]$ source /opt/ros/humble/setup.bash
[euler@Euler colcon]$ colcon build
...
Summary: 22 packages finished [5min 2s]
[euler@Euler colcon]$ tree -L 1
.
├── build
├── install
├── log
└── src
4 directories, 0 files
-
目录
(1)build 目录存储的是中间文件。对于每个包,将创建一个子文件夹,在其中调用例如CMake
(2)install 目录是每个软件包将安装到的位置。默认情况下,每个包都将安装到单独的子目录中。
(3)log 目录包含有关每个colcon调用的各种日志信息。 -
终端 1 运行订阅者节点
# source 一下资源
source install/setup.bash
# 运行一个订阅节点
ros2 run examples_rclcpp_minimal_subscriber subscriber_member_function
- 终端 2 运行发布者节点
# source 一下资源
source install/setup.bash
# 运行一个订阅节点
ros2 run examples_rclcpp_minimal_publisher publisher_member_function
2.4 编写节点
编写节点【RCLCPP】
创建工作空间
[euler@Euler node]$ mkdir -p cpp_ws/src
创建功能包
创建example_cpp功能包,使用ament-cmake作为编译类型,并为其添加rclcpp依赖。
[euler@Euler node]$ cd cpp_ws/src/
[euler@Euler src]$ ros2 pkg create example_cpp --build-type ament_cmake --dependencies rclcpp
[euler@Euler src]$ tree -L 3
.
└── example_cpp
├── CMakeLists.txt
├── include
│ └── example_cpp
├── package.xml
└── src
4 directories, 2 files
(1)pkg create 是创建包的意思
(2)–build-type 用来指定该包的编译类型,一共有三个可选项 ament_python、ament_cmake、cmake
(3)–dependencies 指的是这个功能包的依赖,这里使用 ros2 的 C++ 客户端接口 rclcpp
创建节点
在example_cpp/src下创建一个node_01.cpp文件:
[euler@Euler src]$ tree -L 3
.
└── example_cpp
├── CMakeLists.txt
├── include
│ └── example_cpp
├── package.xml
└── src
└── node_01.cpp
4 directories, 3 files
编写代码
- node_01.cpp 输入代码
#include "rclcpp/rclcpp.hpp"
int main(int argc, char **argv)
{
/* 初始化rclcpp */
rclcpp::init(argc, argv);
/*产生一个node_01的节点*/
auto node = std::make_shared<rclcpp::Node>("node_01");
// 打印一句自我介绍
RCLCPP_INFO(node->get_logger(), "node_01节点已经启动.");
/* 运行节点,并检测退出信号 Ctrl+C*/
rclcpp::spin(node);
/* 停止运行 */
rclcpp::shutdown();
return 0;
}
- 修改 CMakeLists.txt
在CmakeLists.txt最后一行加入下面代码。
# 添加可执行文件
add_executable(node_01 src/node_01.cpp)
# 添加依赖项
ament_target_dependencies(node_01 rclcpp)
# 添加安装目标
install(TARGETS
node_01
DESTINATION lib/${PROJECT_NAME}
)
编译运行
[euler@Euler cpp_ws]$ ls
src
[euler@Euler cpp_ws]$ colcon build
Starting >>> example_cpp
Finished <<< example_cpp [8.13s]
Summary: 1 package finished [8.52s]
[euler@Euler cpp_ws]$ tree -L 1
.
├── build
├── install
├── log
└── src
4 directories, 0 files
测试
[euler@Euler cpp_ws]$ source install/setup.bash
[euler@Euler cpp_ws]$ ros2 run example_cpp node_01
[INFO] [1722828608.116903186] [node_01]: node_01节点已经启动.
新开窗口查看节点列表:
[euler@Euler ~]$ source /opt/ros/humble/setup.bash
[euler@Euler ~]$ ros2 node list
/node_01
[euler@Euler ~]$
编写节点【RCLPY】
创建工作空间
[euler@Euler node]$ mkdir -p py_ws/src
创建功能包
创建example_py功能包,使用ament-cmake作为编译类型,并为其添加rclpy依赖。
[euler@Euler node]$ cd cpp_ws/src/
[euler@Euler src]$ ros2 pkg create example_py --build-type ament_python --dependencies rclpy
[euler@Euler src]$ tree -L 3
.
└── example_py
├── example_py
│ └── __init__.py
├── package.xml
├── resource
│ └── example_py
├── setup.cfg
├── setup.py
└── test
├── test_copyright.py
├── test_flake8.py
└── test_pep257.py
4 directories, 8 files
(1)pkg create 是创建包的意思
(2)–build-type 用来指定该包的编译类型,一共有三个可选项 ament_python、ament_cmake、cmake
(3)–dependencies 指的是这个功能包的依赖,这里使用 ros2 的 python 客户端接口 rclpy
创建节点
example_py下创建 node_02.py
[euler@Euler py_ws]$ ls
src
[euler@Euler py_ws]$ touch src/example_py/example_py/node_02.py
编写代码
- node_02.cpp 输入代码
import rclpy
from rclpy.node import Node
def main(args=None):
"""
ros2运行该节点的入口函数
编写ROS2节点的一般步骤
1. 导入库文件
2. 初始化客户端库
3. 新建节点对象
4. spin循环节点
5. 关闭客户端库
"""
rclpy.init(args=args) # 初始化rclpy
node = Node("node_02") # 新建一个节点
node.get_logger().info("大家好,我是node_02.")
rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
rclpy.shutdown() # 关闭rclpy
- 修改setup.py
声明一个ROS2的节点,声明后使用colcon build才能检测到,从而将其添加到install目录下。
entry_points={
'console_scripts': [
"node_02 = example_py.node_02:main"
],
},
)
编译运行
[euler@Euler py_ws]$ ls
src
[euler@Euler py_ws]$ colcon build
Starting >>> example_py
Finished <<< example_py [1.56s]
Summary: 1 package finished [1.92s]
[euler@Euler py_ws]$ tree -L 1
.
├── build
├── install
├── log
└── src
4 directories, 0 files
测试
[euler@Euler py_ws]$ source install/setup.bash
[euler@Euler py_ws]$ ros2 run example_py node_02
[INFO] [1722833143.392257307] [node_02]: 大家好,我是node_02.
新开窗口查看节点列表:
[euler@Euler ~]$ source /opt/ros/humble/setup.bash
[euler@Euler ~]$ ros2 node list
/node_02
[euler@Euler ~]$
2.5 节点编写、编译、运行【面向对象编程 OOP】
面向过程编程思想。缩写:POP
面向对象编程思想。缩写:OOP
函数式思想。缩写:FP
C++ 示例
#include "rclcpp/rclcpp.hpp"
/*
创建一个类节点,名字叫做Node03,继承自Node.
*/
class Node03 : public rclcpp::Node
{
public:
// 构造函数,有一个参数为节点名称
Node03(std::string name) : Node(name)
{
// 打印一句
RCLCPP_INFO(this->get_logger(), "大家好,我是%s.",name.c_str());
}
private:
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
/*产生一个node_03的节点*/
auto node = std::make_shared<Node03>("node_03");
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
Python
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
class Node04(Node):
"""
创建一个Node04节点,并在初始化时输出一个话
"""
def __init__(self,name):
super().__init__(name)
self.get_logger().info("大家好,我是%s!" % name)
def main(args=None):
rclpy.init(args=args) # 初始化rclpy
node = Node04("node_04") # 新建一个节点
rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
rclpy.shutdown() # 关闭rclpy
2.6 Colcon 介绍
colcon
colcon是一个命令行工具,用于改进构建,测试和使用多个软件包的工作流程。它自动化了流程,处理了订购并设置了使用软件包的环境。
catkin_make
该工具仅调用 CMake 一次,并使用 CMake 的函数在单个上下文中处理所有包。虽然这是一种有效的方法,因为所有包中的所有目标都可以并行化,但它具有明显的缺点。由于所有函数名称、目标和测试都共享一个命名空间,并且规模更大,这很容易导致冲突。
ament_tools
ament_tools 由用于构建 ROS 2 包的独立 Python 3 包提供。它是为引导ROS 2项目而开发的,因此仅针对Python 3,并且可以在Linux,MacOS和Windows上运行。
构建指令
–packages-select ,仅生成单个包(或选定的包)。
–packages-up-to,构建选定的包,包括其依赖项。
–packages-above,整个工作区,然后对其中一个包进行了更改。此指令将重构此包以及(递归地)依赖于此包的所有包。
指定构建后安装的目录
可以通过 --build-base参数和–install-base,指定构建目录和安装目录。
合并构建目录
–merge-install,使用 作为所有软件包的安装前缀,而不是安装基中的软件包特定子目录。–install-base
如果没有此选项,每个包都将提供自己的环境变量路径,从而导致非常长的环境变量值。
使用此选项时,添加到环境变量的大多数路径将相同,从而导致环境变量值更短。
符号链接安装
启用–symlink-install后将不会把文拷贝到install目录,而是通过创建符号链接的方式。
错误时继续安装
启用–continue-on-error,当发生错误的时候继续进行编译。
CMake参数
–cmake-args,将任意参数传递给CMake。与其他选项匹配的参数必须以空格为前缀。
控制构建线程
-
–executor EXECUTOR,用于处理所有作业的执行程序。默认值是根据所有可用执行程序扩展的优先级选择的。要查看完整列表,请调用 colcon extensions colcon_core.executor --verbose。
-
- sequential [colcon-core]
一次处理一个包。
- sequential [colcon-core]
-
- parallel [colcon-parallel-executor]
处理多个作业平行.
- parallel [colcon-parallel-executor]
-
–parallel-workers NUMBER
-
- 要并行处理的最大作业数。默认值为 os.cpu_count() 给出的逻辑 CPU 内核数。
开启构建日志
使用–log-level可以设置日志级别,比如–log-level info。
2.7 ROS2节点发现与多机通信
在没有 ROSMASTER 的情况下,ROS2 如何实现互相发现。
ROS 2用于通讯的默认中间件是DDS。在DDS中,不同逻辑网络共享物理网络的主要机制称为域(Domain) ID。同一域上的ROS 2节点可以自由地相互发现并发送消息,而不同域上的ROS 2节点则不能。所有ROS 2节点默认使用域ID为0。
选择域ID (短版本)
选择一个介于0和101之间的安全的域ID (包括0和101)。
选择域ID (长版本)
DDS使用域ID计算将用于发现和通讯的UDP端口。在网络中,UDP端口是 无符号16位整型 。因此可以分配的最大端口号是65535。
-
Linux
默认情况下,linux内核使用端口32768-60999作为临时端口。这意味着域ID 0-101 和 215-232 可以安全使用,而不会与临时端口发生冲突。临时端口范围可在Linux中通过在 /proc/sys/net/ipv4/ip_local_port_range 中设置自定义值进行配置。如果使用自定义临时端口范围,则可能需要相应地调整上述数字。 -
Windows
默认情况下,Windows上的临时端口范围为49152-65535。这意味着域ID 0-166可以安全使用,不会与临时端口发生冲突。临时的端口范围可通过 使用netsh 在窗口中配置。如果使用自定义临时端口范围,则可能需要相应地调整上述数字。
对于计算机上运行的每个ROS 2进程,将创建一个DDS “participant” 。由于每个DDS参与者占用计算机上的两个端口,因此在一台计算机上运行120个以上的 ROS 2 进程可能会溢出到其他域ID或临时端口。
2.8 通信–话题与服务
TCP/UDP
ping 192.168.0.1
# 终端 1: 监听端口
nc -l 1234
# 终端 2: 发送数据
echo "Hello, TCP!" | nc 127.0.0.1 1234
基于共享内存的进程间通信(IPC)方式
在Linux命令行中,可以使用ipcs和ipcrm命令来管理共享内存段。
通过ipcs命令查看当前系统中的共享内存段:
ipcs -m
使用ipcrm命令删除不再需要的共享内存段:
ipcrm -m <shmid>
ZeroMQ
FastDDS 官网强调自己比 ZeroMQ 性能要好。
ZeroMQ 非常的轻量,也就是小巧,占用资源少,Zero Message Queue,零消息队列。
PyZmq
https://pyzmq.readthedocs.io/en/latest/
话题
同一个话题,所有的发布者和接收者必须使用相同消息接口。
# 终端 1
[euler@Euler cpp_ws]$ source install/setup.bash
[euler@Euler cpp_ws]$ ros2 run example_cpp node_01
# 终端 2
[euler@Euler py_ws]$ source install/setup.bash
[euler@Euler py_ws]$ ros2 run example_py node_02
# 终端 3
rqt_graph
openEuler 没有安装 rqt,安装后再补充。
命令
# 返回系统中当前活动的所有主题的列表
ros2 topic list
# 增加消息类型
ros2 topic list -t
# 打印实时话题内容
ros2 topic echo
eg: ros2 topic echo /chatter
# 查看主题信息
ros2 topic info
eg: ros2 topic info /chatter
# 查看消息类型
ros2 interface show
eg: ros2 interface show std_msgs/msg/String
# 手动发布命令
ros2 topic pub arg
eg: ros2 topic pub /chatter std_msgs/msg/String 'data: "123"'
实现 RCLCPP
实现 RCLPY
服务
实现 RCLCPP
实现 RCLPY
2.9 通信–参数
3 机器人学
4 建模仿真
5 Navi2 导航
6 Moveit2 机械臂
参考
1、ROS 2 Documentation humble
2、官方–ROS2 Humble 教程
3、官方–ROS2 Humble 控制
4、ROS2
5、ROS2 Humble学习笔记
6、ROS2-humble学习
7、ROS2 学习(一)ROS2 简介与基本使用
8、小鱼–动手学ROS2
9、openEuler22.03SP3中的cmake3.22.0读取openssl版本号为乱码,导致使用cmakecache的其他程序出错
10、官方 colcon – Installation
11、openEuler-22.03-LTS–嵌入式ROS运行时支持
12、生肖Robot–电鼠
13、src-openEuler/ament_cmake
14、ament_cmake_python user documentation
15、ROS2 教程
16、ROS2探索总结-4.ament编译系统
17、机器人操作系统入门讲义
18、Overview and usage of RQt