ROS2 Humble 学习【openEuler】

news2024/11/14 15:34:26

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  726 14:27 examples_rclpy_executors
drwxr-xr-x.  2 root root  4096  726 14:27 examples_rclpy_executors-0.15.1-py3.9.egg-info
drwxr-xr-x.  3 root root  4096  726 14:27 examples_rclpy_guard_conditions
drwxr-xr-x.  2 root root  4096  726 14:27 examples_rclpy_guard_conditions-0.15.1-py3.9.egg-info
drwxr-xr-x.  3 root root  4096  726 14:27 examples_rclpy_minimal_action_client
drwxr-xr-x.  2 root root  4096  726 14:27 examples_rclpy_minimal_action_client-0.15.1-py3.9.egg-info
drwxr-xr-x.  3 root root  4096  726 14:27 examples_rclpy_minimal_action_server
drwxr-xr-x.  2 root root  4096  726 14:27 examples_rclpy_minimal_action_server-0.15.1-py3.9.egg-info
drwxr-xr-x.  3 root root  4096  726 14:27 examples_rclpy_minimal_client
drwxr-xr-x.  2 root root  4096  726 14:27 examples_rclpy_minimal_client-0.15.1-py3.9.egg-info
drwxr-xr-x.  3 root root  4096  726 14:27 examples_rclpy_minimal_publisher
drwxr-xr-x.  2 root root  4096  726 14:27 examples_rclpy_minimal_publisher-0.15.1-py3.9.egg-info
drwxr-xr-x.  3 root root  4096  726 14:27 examples_rclpy_minimal_service
drwxr-xr-x.  2 root root  4096  726 14:27 examples_rclpy_minimal_service-0.15.1-py3.9.egg-info
drwxr-xr-x.  3 root root  4096  726 14:27 examples_rclpy_minimal_subscriber
drwxr-xr-x.  2 root root  4096  726 14:27 examples_rclpy_minimal_subscriber-0.15.1-py3.9.egg-info
drwxr-xr-x.  3 root root  4096  726 14:27 examples_rclpy_pointcloud_publisher
drwxr-xr-x.  2 root root  4096  726 14:27 examples_rclpy_pointcloud_publisher-0.15.1-py3.9.egg-info
drwxr-xr-x.  5 root root  4096  726 14:27 rclpy
drwxr-xr-x.  2 root root  4096  726 14:27 rclpy-3.3.8-py3.9.egg-info
drwxr-xr-x.  3 root root  4096  726 14:27 rclpy_message_converter
drwxr-xr-x.  2 root root  4096  726 14:27 rclpy_message_converter-2.0.1-py3.9.egg-info
drwxr-xr-x.  4 root root  4096  726 14:33 rclpy_message_converter_msgs
drwxr-xr-x.  2 root root  4096  726 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]
      一次处理一个包。
    • 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1984594.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL深分页和浅分页

前言 最近有面试过也遇到了问关于深分页问题&#xff0c;在这里简单从MySQL、ES等方面分享一下自己对该问题认识和总结。 一、深分页定义 可以从ES定义上来划分浅分页和深分页的边界&#xff0c;即页数超过10000页为深分页&#xff0c;少于10000页为浅分页。 二、MySQL深分…

数字化时代:蚓链助力企业破局与腾飞!

在当今数字化浪潮汹涌澎湃的时代&#xff0c;企业面临着前新机遇与新挑战。您是否渴望在竞争激烈的市场中实现数字化弯道超车&#xff1f;是否梦想着打造专属自己的独特生意赛道&#xff1f;是否期盼着拥有专享的资源生态圈&#xff1f;如果您的答案是肯定的&#xff0c;那么蚓…

CSP - J day9

一. 题目 &#xff08;1&#xff09;早安 思路&#xff1a; &#xff08;1&#xff09;cin和scanf读入字符串时遇到空格或换行就停止读入&#xff0c;对于要读入带空格的字符串时&#xff0c;常用 两种方法&#xff1a; // 法一string s;getline( cin, s ); // 法…

OrangePi AIpro学习1 —— 烧写和ssh系统

目录 一、下载烧写工具和系统 二、烧写和启动 2.1 烧写和启动 2.2 烧写失败后的问题解决 三、串口连接到主机 3.1 串口连接到主机 四、网络连接到主机 4.1 修改香橙派IP地址 4.2 win11配置以太网静态ip 4.4 主机和香橙派直连 4.5 主机和香橙派连接到同一个路由器 五…

Hive SQL进阶:掌握间隔连续查询技巧,优化大数据分析(二)

目录 1.访问次数最多的5个用户 2.近 30 天的每日活跃用户数 3.获取1-180天注册活跃留存表 4.学生名次统计 5.最近连续3周连续活跃用户数 6.最近7天内连续3天活跃用户数 7.餐馆营业额变化增长 相关拓展 1.访问次数最多的5个用户 输出每个app 下访问次数最多的5个用户 返…

DC-7靶机渗透测试

DC-7靶机 DC: 7 ~ VulnHub 文章目录 DC-7靶机信息收集web渗透权限提升Drupal后台getshell权限提升靶机总结信息收集 经过扫描得到IP地址为192.168.78.154.其中开启了ssh和80端口,看来立足点就在于web渗透找到漏洞,获取用户密码来进行ssh连接进行寻找提权方案了使用dirb扫描…

Windows平台下内存泄漏检测工具Visual Leak detector介绍(vscode使用)

!!!此工具只能检测配合VC进行代码的内存泄漏检测 1、搜索VLD工具下载 2、配置环境变量 3、在main.cpp中加入#include<vld.h> 4、在CMakeLists.txt中添加 SET(VLD_PATH "xxx") # 链接vld静态库 target_link_libraries(${PROJECT_NAME} PRIVATE ${VLD_PATH})…

学习STM32(2)--STM32单片机GPIO应用

目录 1 引 言 2 实验目的 3 实验内容 3.1掌握STM32F103的GPIO控制 3.1.1 GPIO的分组 3.1.2 GPIO的常用功能 3.1.3 STM32单片机GPIO位结构 3.1.4 STM32单片机GPIO工作模式 3.1.5 STM32的GPIO 输出-点亮LED编程要点 使用GPIO时&#xff0c;按下面步骤进行&#xff1…

antd-5版本table组件修改滚动条样式不生效问题

问题描述 在react项目中使用antd-ProComponents组件库的Protable组件时修改table自带的滚动条样式不生效。 排查记录 一般来说直接table组件库要自定义滚动条的样式&#xff0c;只需要修改 ant-table-body 的样式即可&#xff0c;代码如下&#xff1a; .ant-table-body {&am…

pikachu文件包含漏洞

一&#xff1a;漏洞基础 程序在引用文件的时&#xff0c;引用的文件名存在可控的情况&#xff0c;传入的文件名没有经过合理的校验或校验不严&#xff0c;从而操作了预想之外的文件&#xff0c;就有可能导致文件泄漏和恶意的代码注入&#xff1b; 文件包含漏洞概念 在PHP程序…

如果忘了Linux密码如何重置?

忘记密码是我们常会遇到的情况之一&#xff0c;无论是在操作系统、网站账户、手机、电子邮件还是其他渠道上。 忘记密码是我们常会遇到的情况之一&#xff0c;无论是在操作系统、网站账户、手机、电子邮件还是其他渠道上。有时候如果密码需要符合特定的复杂性要求&#xff0c;…

【C++题解】1023. 判断素数

欢迎关注本专栏《C从零基础到信奥赛入门级&#xff08;CSP-J&#xff09;》 问题&#xff1a;1023. 判断素数 类型&#xff1a;函数&#xff0c;sqrt函数入门 题目描述&#xff1a; 任意输入一个整数&#xff0c;判断它是否为素数。是的话输出 T ,不是的话输出 F。 质数又称…

从传统监控到智能化升级:EasyCVR视频汇聚平台的一站式解决方案

随着科技的飞速发展和社会的不断进步&#xff0c;视频监控已经成为现代社会治安防控、企业管理等场景安全管理中不可或缺的一部分。而在视频监控领域&#xff0c;EasyCVR视频汇聚平台凭借其强大的多协议接入能力&#xff0c;在复杂多变的网络环境中展现出了卓越的性能和广泛的应…

Android 12系统源码_多屏幕(一)多屏幕设备显示Activity

前言 分屏&#xff1a;是指一个屏幕分出多个窗口&#xff0c;分别显示不同应用的界面&#xff0c;这在当前的手机设备中很常见。多屏&#xff1a;是指一个设备存在多个屏幕&#xff0c;这些可能是虚拟屏幕或者实体硬件屏幕&#xff0c;不同的应用同时显示在不同的屏幕中&#…

全面解析:msvcp140_atomic_wait.dll 丢失的解决之道,助你轻松应对

在尝试解决“msvcp140_atomic_wait.dll丢失”的问题时&#xff0c;首先需要确认错误信息的准确性。用户应仔细检查在启动程序或执行特定操作时是否确实出现了这一错误提示。确认错误后&#xff0c;可以进一步采取措施来解决问题。这包括检查系统日志和错误报告&#xff0c;以确…

RK3562J技术分享 | 使用SPI挂载数字式RTD温度传感器的方法

MAX31865是简单易用的热敏电阻至数字输出转换器&#xff0c;优化用于铂电阻温度检测器(RTD)。外部电阻设置RTD灵敏度&#xff0c;高精度Δ-Σ ADC将RTD电阻与基准电阻之比转换为数字输出。MAX31865输入具有高达45V的过压保护&#xff0c;提供可配置的RTD及电缆开路、短路条件检…

如何避免或者减少线上空指针问题的发生

一、背景 在我们的日常工作中&#xff0c;我们会经常遇到空指针问题&#xff0c;理论上来说只是一个判段空指针的小问题&#xff0c;但是因为这行代码的报错&#xff0c;程序中断了后面的执行&#xff0c;可能导致整体业务逻辑受影响。那在工作中我们应该如何避免&#xff0c;…

layer.load 加倒计时

实现效果 loadinglayer.load(1, {content:"",shade: [0.7, #333],time:5000,success: function(layero,index) {var i 5;var timer null;var fn function() {// 显示的提示layero.find(".layui-layer-content").html(正在连接&#xff0c;请稍等&…

谷歌突然停止为应用程序生成胖APK 只提供AAB包可能会影响用户侧载安装

谷歌最初是在 2018 年开始准备 Android App Bundle (即 AAB) 安装包&#xff0c;到 2021 年这种格式已经成为默认格式&#xff0c;开发者在提交应用程序时需要将其构建为 AAB 格式方便 Google Play 应用商店分发。 AAB 格式的优势在于适用于不同屏幕尺寸、语言、CPU 架构和 An…

js基础与判断

1.加减乘除 2.逻辑运算符 4.分支 5.swicth switch与if-else区别 6.break和continue